Makefile.in (cgraphbuild.o): Add dependency on ipa-utils.h
* Makefile.in (cgraphbuild.o): Add dependency on ipa-utils.h * cgraphbuild.c: Include ipa-utils.h (record_reference_ctx): New struct. (record_reference): Simplify to work on initializers; not statements. (mark_address, mark_load, mark_store): New. (build_cgraph_edges): Simplify using walk_stmt_load_store_addr_ops; walk PHI nodes too. (record_references_in_initializer): Update use of record_reference. (rebuild_cgraph_edges): Simplify using walk_stmt_load_store_addr_ops; walk PHI nodes too. From-SVN: r159032
This commit is contained in:
parent
688a10c2b9
commit
85912441e4
@ -1,3 +1,16 @@
|
||||
2010-05-04 Jan Hubicka <jh@suse.cz>
|
||||
|
||||
* Makefile.in (cgraphbuild.o): Add dependency on ipa-utils.h
|
||||
* cgraphbuild.c: Include ipa-utils.h
|
||||
(record_reference_ctx): New struct.
|
||||
(record_reference): Simplify to work on initializers; not statements.
|
||||
(mark_address, mark_load, mark_store): New.
|
||||
(build_cgraph_edges): Simplify using walk_stmt_load_store_addr_ops;
|
||||
walk PHI nodes too.
|
||||
(record_references_in_initializer): Update use of record_reference.
|
||||
(rebuild_cgraph_edges): Simplify using walk_stmt_load_store_addr_ops;
|
||||
walk PHI nodes too.
|
||||
|
||||
2010-05-04 Jan Hubicka <jh@suse.cz>
|
||||
|
||||
* lto-symtab.c (lto_cgraph_replace_node): Do not remove edges;
|
||||
|
@ -31,6 +31,13 @@ along with GCC; see the file COPYING3. If not see
|
||||
#include "intl.h"
|
||||
#include "gimple.h"
|
||||
#include "tree-pass.h"
|
||||
#include "ipa-utils.h"
|
||||
|
||||
/* Context of record_reference. */
|
||||
struct record_reference_ctx
|
||||
{
|
||||
bool only_vars;
|
||||
};
|
||||
|
||||
/* Walk tree and record all calls and references to functions/variables.
|
||||
Called via walk_tree: TP is pointer to tree to be examined.
|
||||
@ -42,26 +49,31 @@ record_reference (tree *tp, int *walk_subtrees, void *data)
|
||||
{
|
||||
tree t = *tp;
|
||||
tree decl;
|
||||
bool do_callgraph = data != NULL;
|
||||
struct record_reference_ctx *ctx = (struct record_reference_ctx *)data;
|
||||
|
||||
switch (TREE_CODE (t))
|
||||
{
|
||||
case VAR_DECL:
|
||||
if (TREE_STATIC (t) || DECL_EXTERNAL (t))
|
||||
{
|
||||
varpool_mark_needed_node (varpool_node (t));
|
||||
if (lang_hooks.callgraph.analyze_expr)
|
||||
return lang_hooks.callgraph.analyze_expr (tp, walk_subtrees);
|
||||
}
|
||||
case FUNCTION_DECL:
|
||||
gcc_unreachable ();
|
||||
break;
|
||||
|
||||
case FDESC_EXPR:
|
||||
case ADDR_EXPR:
|
||||
/* Record dereferences to the functions. This makes the
|
||||
functions reachable unconditionally. */
|
||||
decl = TREE_OPERAND (*tp, 0);
|
||||
if (TREE_CODE (decl) == FUNCTION_DECL && do_callgraph)
|
||||
decl = get_base_var (*tp);
|
||||
if (TREE_CODE (decl) == FUNCTION_DECL && !ctx->only_vars)
|
||||
cgraph_mark_address_taken_node (cgraph_node (decl));
|
||||
|
||||
if (TREE_CODE (decl) == VAR_DECL)
|
||||
{
|
||||
gcc_assert (TREE_STATIC (decl) || DECL_EXTERNAL (decl));
|
||||
if (lang_hooks.callgraph.analyze_expr)
|
||||
lang_hooks.callgraph.analyze_expr (&decl, walk_subtrees);
|
||||
varpool_mark_needed_node (varpool_node (decl));
|
||||
}
|
||||
*walk_subtrees = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -126,6 +138,75 @@ compute_call_stmt_bb_frequency (tree decl, basic_block bb)
|
||||
return freq;
|
||||
}
|
||||
|
||||
/* Mark address taken in STMT. */
|
||||
|
||||
static bool
|
||||
mark_address (gimple stmt ATTRIBUTE_UNUSED, tree addr,
|
||||
void *data ATTRIBUTE_UNUSED)
|
||||
{
|
||||
if (TREE_CODE (addr) == FUNCTION_DECL)
|
||||
{
|
||||
struct cgraph_node *node = cgraph_node (addr);
|
||||
cgraph_mark_address_taken_node (node);
|
||||
}
|
||||
else
|
||||
{
|
||||
addr = get_base_address (addr);
|
||||
if (addr && TREE_CODE (addr) == VAR_DECL
|
||||
&& (TREE_STATIC (addr) || DECL_EXTERNAL (addr)))
|
||||
{
|
||||
struct varpool_node *vnode = varpool_node (addr);
|
||||
int walk_subtrees;
|
||||
|
||||
if (lang_hooks.callgraph.analyze_expr)
|
||||
lang_hooks.callgraph.analyze_expr (&addr, &walk_subtrees);
|
||||
varpool_mark_needed_node (vnode);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Mark load of T. */
|
||||
|
||||
static bool
|
||||
mark_load (gimple stmt ATTRIBUTE_UNUSED, tree t,
|
||||
void *data ATTRIBUTE_UNUSED)
|
||||
{
|
||||
t = get_base_address (t);
|
||||
if (TREE_CODE (t) == VAR_DECL
|
||||
&& (TREE_STATIC (t) || DECL_EXTERNAL (t)))
|
||||
{
|
||||
struct varpool_node *vnode = varpool_node (t);
|
||||
int walk_subtrees;
|
||||
|
||||
if (lang_hooks.callgraph.analyze_expr)
|
||||
lang_hooks.callgraph.analyze_expr (&t, &walk_subtrees);
|
||||
varpool_mark_needed_node (vnode);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Mark store of T. */
|
||||
|
||||
static bool
|
||||
mark_store (gimple stmt ATTRIBUTE_UNUSED, tree t,
|
||||
void *data ATTRIBUTE_UNUSED)
|
||||
{
|
||||
t = get_base_address (t);
|
||||
if (TREE_CODE (t) == VAR_DECL
|
||||
&& (TREE_STATIC (t) || DECL_EXTERNAL (t)))
|
||||
{
|
||||
struct varpool_node *vnode = varpool_node (t);
|
||||
int walk_subtrees;
|
||||
|
||||
if (lang_hooks.callgraph.analyze_expr)
|
||||
lang_hooks.callgraph.analyze_expr (&t, &walk_subtrees);
|
||||
varpool_mark_needed_node (vnode);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Create cgraph edges for function calls.
|
||||
Also look for functions and variables having addresses taken. */
|
||||
|
||||
@ -141,49 +222,40 @@ build_cgraph_edges (void)
|
||||
/* Create the callgraph edges and record the nodes referenced by the function.
|
||||
body. */
|
||||
FOR_EACH_BB (bb)
|
||||
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
|
||||
{
|
||||
gimple stmt = gsi_stmt (gsi);
|
||||
tree decl;
|
||||
{
|
||||
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
|
||||
{
|
||||
gimple stmt = gsi_stmt (gsi);
|
||||
tree decl;
|
||||
|
||||
if (is_gimple_call (stmt) && (decl = gimple_call_fndecl (stmt)))
|
||||
{
|
||||
size_t i;
|
||||
size_t n = gimple_call_num_args (stmt);
|
||||
if (is_gimple_call (stmt) && (decl = gimple_call_fndecl (stmt)))
|
||||
cgraph_create_edge (node, cgraph_node (decl), stmt,
|
||||
bb->count, compute_call_stmt_bb_frequency (current_function_decl, bb),
|
||||
bb->count,
|
||||
compute_call_stmt_bb_frequency
|
||||
(current_function_decl, bb),
|
||||
bb->loop_depth);
|
||||
for (i = 0; i < n; i++)
|
||||
walk_tree (gimple_call_arg_ptr (stmt, i), record_reference,
|
||||
node, visited_nodes);
|
||||
if (gimple_call_lhs (stmt))
|
||||
walk_tree (gimple_call_lhs_ptr (stmt), record_reference, node,
|
||||
visited_nodes);
|
||||
}
|
||||
else
|
||||
{
|
||||
struct walk_stmt_info wi;
|
||||
memset (&wi, 0, sizeof (wi));
|
||||
wi.info = node;
|
||||
wi.pset = visited_nodes;
|
||||
walk_gimple_op (stmt, record_reference, &wi);
|
||||
if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
|
||||
&& gimple_omp_parallel_child_fn (stmt))
|
||||
{
|
||||
tree fn = gimple_omp_parallel_child_fn (stmt);
|
||||
walk_stmt_load_store_addr_ops (stmt, node, mark_load,
|
||||
mark_store, mark_address);
|
||||
if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
|
||||
&& gimple_omp_parallel_child_fn (stmt))
|
||||
{
|
||||
tree fn = gimple_omp_parallel_child_fn (stmt);
|
||||
cgraph_mark_needed_node (cgraph_node (fn));
|
||||
}
|
||||
if (gimple_code (stmt) == GIMPLE_OMP_TASK)
|
||||
{
|
||||
tree fn = gimple_omp_task_child_fn (stmt);
|
||||
if (fn)
|
||||
cgraph_mark_needed_node (cgraph_node (fn));
|
||||
}
|
||||
if (gimple_code (stmt) == GIMPLE_OMP_TASK)
|
||||
{
|
||||
tree fn = gimple_omp_task_child_fn (stmt);
|
||||
if (fn)
|
||||
cgraph_mark_needed_node (cgraph_node (fn));
|
||||
fn = gimple_omp_task_copy_fn (stmt);
|
||||
if (fn)
|
||||
cgraph_mark_needed_node (cgraph_node (fn));
|
||||
}
|
||||
}
|
||||
}
|
||||
fn = gimple_omp_task_copy_fn (stmt);
|
||||
if (fn)
|
||||
cgraph_mark_needed_node (cgraph_node (fn));
|
||||
}
|
||||
}
|
||||
for (gsi = gsi_start (phi_nodes (bb)); !gsi_end_p (gsi); gsi_next (&gsi))
|
||||
walk_stmt_load_store_addr_ops (gsi_stmt (gsi), node,
|
||||
mark_load, mark_store, mark_address);
|
||||
}
|
||||
|
||||
/* Look for initializers of constant variables and private statics. */
|
||||
for (step = cfun->local_decls;
|
||||
@ -194,8 +266,6 @@ build_cgraph_edges (void)
|
||||
if (TREE_CODE (decl) == VAR_DECL
|
||||
&& (TREE_STATIC (decl) && !DECL_EXTERNAL (decl)))
|
||||
varpool_finalize_decl (decl);
|
||||
else if (TREE_CODE (decl) == VAR_DECL && DECL_INITIAL (decl))
|
||||
walk_tree (&DECL_INITIAL (decl), record_reference, node, visited_nodes);
|
||||
}
|
||||
|
||||
pointer_set_destroy (visited_nodes);
|
||||
@ -229,8 +299,11 @@ void
|
||||
record_references_in_initializer (tree decl, bool only_vars)
|
||||
{
|
||||
struct pointer_set_t *visited_nodes = pointer_set_create ();
|
||||
struct record_reference_ctx ctx = {false};
|
||||
|
||||
ctx.only_vars = only_vars;
|
||||
walk_tree (&DECL_INITIAL (decl), record_reference,
|
||||
only_vars ? NULL : decl, visited_nodes);
|
||||
&ctx, visited_nodes);
|
||||
pointer_set_destroy (visited_nodes);
|
||||
}
|
||||
|
||||
@ -249,19 +322,26 @@ rebuild_cgraph_edges (void)
|
||||
node->count = ENTRY_BLOCK_PTR->count;
|
||||
|
||||
FOR_EACH_BB (bb)
|
||||
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
|
||||
{
|
||||
gimple stmt = gsi_stmt (gsi);
|
||||
tree decl;
|
||||
{
|
||||
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
|
||||
{
|
||||
gimple stmt = gsi_stmt (gsi);
|
||||
tree decl;
|
||||
|
||||
if (is_gimple_call (stmt) && (decl = gimple_call_fndecl (stmt)))
|
||||
cgraph_create_edge (node, cgraph_node (decl), stmt,
|
||||
bb->count,
|
||||
compute_call_stmt_bb_frequency
|
||||
(current_function_decl, bb),
|
||||
bb->loop_depth);
|
||||
if (is_gimple_call (stmt) && (decl = gimple_call_fndecl (stmt)))
|
||||
cgraph_create_edge (node, cgraph_node (decl), stmt,
|
||||
bb->count,
|
||||
compute_call_stmt_bb_frequency
|
||||
(current_function_decl, bb),
|
||||
bb->loop_depth);
|
||||
walk_stmt_load_store_addr_ops (stmt, node, mark_load,
|
||||
mark_store, mark_address);
|
||||
|
||||
}
|
||||
}
|
||||
for (gsi = gsi_start (phi_nodes (bb)); !gsi_end_p (gsi); gsi_next (&gsi))
|
||||
walk_stmt_load_store_addr_ops (gsi_stmt (gsi), node,
|
||||
mark_load, mark_store, mark_address);
|
||||
}
|
||||
gcc_assert (!node->global.inlined_to);
|
||||
|
||||
return 0;
|
||||
|
Loading…
Reference in New Issue
Block a user