From 63b0bea7f5af509ae68aa64919da34dfc7223727 Mon Sep 17 00:00:00 2001 From: hubicka Date: Tue, 4 May 2010 15:42:15 +0000 Subject: [PATCH] * 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@159032 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 13 ++++ gcc/cgraphbuild.c | 210 +++++++++++++++++++++++++++++++++++++----------------- 2 files changed, 158 insertions(+), 65 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index fb76cf6..b792a53 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,18 @@ 2010-05-04 Jan Hubicka + * 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 + * lto-symtab.c (lto_cgraph_replace_node): Do not remove edges; node will be removed anyway. (lto_varpool_replace_node): Allow also unanalyzed nodes; diff --git a/gcc/cgraphbuild.c b/gcc/cgraphbuild.c index bcc66c0..02c373a 100644 --- a/gcc/cgraphbuild.c +++ b/gcc/cgraphbuild.c @@ -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; - - if (is_gimple_call (stmt) && (decl = gimple_call_fndecl (stmt))) - { - size_t i; - size_t n = gimple_call_num_args (stmt); + { + 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->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)); + fn = gimple_omp_task_copy_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)); - } - } - } + } + } + 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; - - 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); - - } + { + 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); + 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; -- 2.7.4