X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=gcc%2Fcgraphbuild.c;h=689cede526ddc787b45e3c9c402c9d2ffd85300e;hb=960bfb6929fa5c463267b962b9ff9dabdb6df3f3;hp=f9d70dbb7926cf07f17bbf9c88b99cef98c5a8a8;hpb=a222c01a3c1303a06effdaae303394edcebf6c7b;p=gcc.git diff --git a/gcc/cgraphbuild.c b/gcc/cgraphbuild.c index f9d70dbb792..689cede526d 100644 --- a/gcc/cgraphbuild.c +++ b/gcc/cgraphbuild.c @@ -1,5 +1,5 @@ /* Callgraph construction. - Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. Contributed by Jan Hubicka @@ -33,6 +33,7 @@ along with GCC; see the file COPYING3. If not see #include "tree-pass.h" #include "ipa-utils.h" #include "except.h" +#include "ipa-inline.h" /* Context of record_reference. */ struct record_reference_ctx @@ -53,6 +54,12 @@ record_reference (tree *tp, int *walk_subtrees, void *data) tree decl; struct record_reference_ctx *ctx = (struct record_reference_ctx *)data; + t = canonicalize_constructor_val (t); + if (!t) + t = *tp; + else if (t != *tp) + *tp = t; + switch (TREE_CODE (t)) { case VAR_DECL: @@ -67,10 +74,10 @@ record_reference (tree *tp, int *walk_subtrees, void *data) decl = get_base_var (*tp); if (TREE_CODE (decl) == FUNCTION_DECL) { + struct cgraph_node *node = cgraph_get_create_node (decl); if (!ctx->only_vars) - cgraph_mark_address_taken_node (cgraph_node (decl)); - ipa_record_reference (NULL, ctx->varpool_node, - cgraph_node (decl), NULL, + cgraph_mark_address_taken_node (node); + ipa_record_reference (NULL, ctx->varpool_node, node, NULL, IPA_REF_ADDR, NULL); } @@ -80,8 +87,6 @@ record_reference (tree *tp, int *walk_subtrees, void *data) if (lang_hooks.callgraph.analyze_expr) lang_hooks.callgraph.analyze_expr (&decl, walk_subtrees); varpool_mark_needed_node (vnode); - if (vnode->alias && vnode->extra_name) - vnode = vnode->extra_name; ipa_record_reference (NULL, ctx->varpool_node, NULL, vnode, IPA_REF_ADDR, NULL); @@ -141,6 +146,15 @@ record_eh_tables (struct cgraph_node *node, struct function *fun) { eh_region i; + if (DECL_FUNCTION_PERSONALITY (node->symbol.decl)) + { + struct cgraph_node *per_node; + + per_node = cgraph_get_create_node (DECL_FUNCTION_PERSONALITY (node->symbol.decl)); + ipa_record_reference (node, NULL, per_node, NULL, IPA_REF_ADDR, NULL); + cgraph_mark_address_taken_node (per_node); + } + i = fun->eh->region_tree; if (!i) return; @@ -186,29 +200,6 @@ record_eh_tables (struct cgraph_node *node, struct function *fun) } } -/* Reset inlining information of all incoming call edges of NODE. */ - -void -reset_inline_failed (struct cgraph_node *node) -{ - struct cgraph_edge *e; - - for (e = node->callers; e; e = e->next_caller) - { - e->callee->global.inlined_to = NULL; - if (!node->analyzed) - e->inline_failed = CIF_BODY_NOT_AVAILABLE; - else if (node->local.redefined_extern_inline) - e->inline_failed = CIF_REDEFINED_EXTERN_INLINE; - else if (!node->local.inlinable) - e->inline_failed = CIF_FUNCTION_NOT_INLINABLE; - else if (e->call_stmt_cannot_inline_p) - e->inline_failed = CIF_MISMATCHED_ARGUMENTS; - else - e->inline_failed = CIF_FUNCTION_NOT_CONSIDERED; - } -} - /* Computes the frequency of the call statement so that it can be stored in cgraph_edge. BB is the basic block of the call statement. */ int @@ -234,35 +225,29 @@ compute_call_stmt_bb_frequency (tree decl, basic_block bb) /* Mark address taken in STMT. */ static bool -mark_address (gimple stmt ATTRIBUTE_UNUSED, tree addr, - void *data ATTRIBUTE_UNUSED) +mark_address (gimple stmt, tree addr, void *data) { + addr = get_base_address (addr); if (TREE_CODE (addr) == FUNCTION_DECL) { - struct cgraph_node *node = cgraph_node (addr); + struct cgraph_node *node = cgraph_get_create_node (addr); cgraph_mark_address_taken_node (node); ipa_record_reference ((struct cgraph_node *)data, NULL, node, NULL, IPA_REF_ADDR, stmt); } - else + else if (addr && TREE_CODE (addr) == VAR_DECL + && (TREE_STATIC (addr) || DECL_EXTERNAL (addr))) { - 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; + 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); - if (vnode->alias && vnode->extra_name) - vnode = vnode->extra_name; - ipa_record_reference ((struct cgraph_node *)data, NULL, - NULL, vnode, - IPA_REF_ADDR, stmt); - } + if (lang_hooks.callgraph.analyze_expr) + lang_hooks.callgraph.analyze_expr (&addr, &walk_subtrees); + varpool_mark_needed_node (vnode); + ipa_record_reference ((struct cgraph_node *)data, NULL, + NULL, vnode, + IPA_REF_ADDR, stmt); } return false; @@ -271,12 +256,21 @@ mark_address (gimple stmt ATTRIBUTE_UNUSED, tree addr, /* Mark load of T. */ static bool -mark_load (gimple stmt ATTRIBUTE_UNUSED, tree t, - void *data ATTRIBUTE_UNUSED) +mark_load (gimple stmt, tree t, void *data) { t = get_base_address (t); - if (t && TREE_CODE (t) == VAR_DECL - && (TREE_STATIC (t) || DECL_EXTERNAL (t))) + if (t && TREE_CODE (t) == FUNCTION_DECL) + { + /* ??? This can happen on platforms with descriptors when these are + directly manipulated in the code. Pretend that it's an address. */ + struct cgraph_node *node = cgraph_get_create_node (t); + cgraph_mark_address_taken_node (node); + ipa_record_reference ((struct cgraph_node *)data, NULL, + node, NULL, + IPA_REF_ADDR, stmt); + } + else if (t && TREE_CODE (t) == VAR_DECL + && (TREE_STATIC (t) || DECL_EXTERNAL (t))) { struct varpool_node *vnode = varpool_node (t); int walk_subtrees; @@ -284,8 +278,6 @@ mark_load (gimple stmt ATTRIBUTE_UNUSED, tree t, if (lang_hooks.callgraph.analyze_expr) lang_hooks.callgraph.analyze_expr (&t, &walk_subtrees); varpool_mark_needed_node (vnode); - if (vnode->alias && vnode->extra_name) - vnode = vnode->extra_name; ipa_record_reference ((struct cgraph_node *)data, NULL, NULL, vnode, IPA_REF_LOAD, stmt); @@ -296,8 +288,7 @@ mark_load (gimple stmt ATTRIBUTE_UNUSED, tree t, /* Mark store of T. */ static bool -mark_store (gimple stmt ATTRIBUTE_UNUSED, tree t, - void *data ATTRIBUTE_UNUSED) +mark_store (gimple stmt, tree t, void *data) { t = get_base_address (t); if (t && TREE_CODE (t) == VAR_DECL @@ -309,11 +300,9 @@ mark_store (gimple stmt ATTRIBUTE_UNUSED, tree t, if (lang_hooks.callgraph.analyze_expr) lang_hooks.callgraph.analyze_expr (&t, &walk_subtrees); varpool_mark_needed_node (vnode); - if (vnode->alias && vnode->extra_name) - vnode = vnode->extra_name; ipa_record_reference ((struct cgraph_node *)data, NULL, NULL, vnode, - IPA_REF_STORE, NULL); + IPA_REF_STORE, stmt); } return false; } @@ -325,7 +314,7 @@ static unsigned int build_cgraph_edges (void) { basic_block bb; - struct cgraph_node *node = cgraph_node (current_function_decl); + struct cgraph_node *node = cgraph_get_node (current_function_decl); struct pointer_set_t *visited_nodes = pointer_set_create (); gimple_stmt_iterator gsi; tree decl; @@ -346,14 +335,12 @@ build_cgraph_edges (void) bb); decl = gimple_call_fndecl (stmt); if (decl) - cgraph_create_edge (node, cgraph_node (decl), stmt, - bb->count, freq, - bb->loop_depth); + cgraph_create_edge (node, cgraph_get_create_node (decl), + stmt, bb->count, freq); else cgraph_create_indirect_edge (node, stmt, gimple_call_flags (stmt), - bb->count, freq, - bb->loop_depth); + bb->count, freq); } walk_stmt_load_store_addr_ops (stmt, node, mark_load, mark_store, mark_address); @@ -361,18 +348,18 @@ build_cgraph_edges (void) && gimple_omp_parallel_child_fn (stmt)) { tree fn = gimple_omp_parallel_child_fn (stmt); - ipa_record_reference (node, NULL, cgraph_node (fn), + ipa_record_reference (node, NULL, cgraph_get_create_node (fn), NULL, IPA_REF_ADDR, stmt); } if (gimple_code (stmt) == GIMPLE_OMP_TASK) { tree fn = gimple_omp_task_child_fn (stmt); if (fn) - ipa_record_reference (node, NULL, cgraph_node (fn), + ipa_record_reference (node, NULL, cgraph_get_create_node (fn), NULL, IPA_REF_ADDR, stmt); fn = gimple_omp_task_copy_fn (stmt); if (fn) - ipa_record_reference (node, NULL, cgraph_node (fn), + ipa_record_reference (node, NULL, cgraph_get_create_node (fn), NULL, IPA_REF_ADDR, stmt); } } @@ -436,11 +423,11 @@ unsigned int rebuild_cgraph_edges (void) { basic_block bb; - struct cgraph_node *node = cgraph_node (current_function_decl); + struct cgraph_node *node = cgraph_get_node (current_function_decl); gimple_stmt_iterator gsi; cgraph_node_remove_callees (node); - ipa_remove_all_references (&node->ref_list); + ipa_remove_all_references (&node->symbol.ref_list); node->count = ENTRY_BLOCK_PTR->count; @@ -457,14 +444,12 @@ rebuild_cgraph_edges (void) bb); decl = gimple_call_fndecl (stmt); if (decl) - cgraph_create_edge (node, cgraph_node (decl), stmt, - bb->count, freq, - bb->loop_depth); + cgraph_create_edge (node, cgraph_get_create_node (decl), stmt, + bb->count, freq); else cgraph_create_indirect_edge (node, stmt, gimple_call_flags (stmt), - bb->count, freq, - bb->loop_depth); + bb->count, freq); } walk_stmt_load_store_addr_ops (stmt, node, mark_load, mark_store, mark_address); @@ -487,10 +472,10 @@ void cgraph_rebuild_references (void) { basic_block bb; - struct cgraph_node *node = cgraph_node (current_function_decl); + struct cgraph_node *node = cgraph_get_node (current_function_decl); gimple_stmt_iterator gsi; - ipa_remove_all_references (&node->ref_list); + ipa_remove_all_references (&node->symbol.ref_list); node->count = ENTRY_BLOCK_PTR->count; @@ -534,7 +519,7 @@ struct gimple_opt_pass pass_rebuild_cgraph_edges = static unsigned int remove_cgraph_callee_edges (void) { - cgraph_node_remove_callees (cgraph_node (current_function_decl)); + cgraph_node_remove_callees (cgraph_get_node (current_function_decl)); return 0; }