diff options
Diffstat (limited to 'gcc-4.9/gcc/cgraph.c')
-rw-r--r-- | gcc-4.9/gcc/cgraph.c | 67 |
1 files changed, 58 insertions, 9 deletions
diff --git a/gcc-4.9/gcc/cgraph.c b/gcc-4.9/gcc/cgraph.c index be3661af6..180a63656 100644 --- a/gcc-4.9/gcc/cgraph.c +++ b/gcc-4.9/gcc/cgraph.c @@ -58,6 +58,7 @@ along with GCC; see the file COPYING3. If not see #include "rtl.h" #include "ipa-utils.h" #include "lto-streamer.h" +#include "l-ipo.h" #include "ipa-inline.h" #include "cfgloop.h" #include "gimple-pretty-print.h" @@ -773,7 +774,9 @@ cgraph_edge (struct cgraph_node *node, gimple call_stmt) { node->call_site_hash = htab_create_ggc (120, edge_hash, edge_eq, NULL); for (e2 = node->callees; e2; e2 = e2->next_callee) - cgraph_add_edge_to_call_site_hash (e2); + /* Skip fake edges. */ + if (e2->call_stmt) + cgraph_add_edge_to_call_site_hash (e2); for (e2 = node->indirect_calls; e2; e2 = e2->next_callee) cgraph_add_edge_to_call_site_hash (e2); } @@ -822,6 +825,8 @@ cgraph_set_call_stmt (struct cgraph_edge *e, gimple new_stmt, /* Constant propagation (and possibly also inlining?) can turn an indirect call into a direct one. */ struct cgraph_node *new_callee = cgraph_get_node (decl); + if (L_IPO_COMP_MODE && cgraph_pre_profiling_inlining_done) + new_callee = cgraph_lipo_get_resolved_node (decl); gcc_checking_assert (new_callee); e = cgraph_make_edge_direct (e, new_callee); @@ -1026,7 +1031,7 @@ cgraph_edge_remove_caller (struct cgraph_edge *e) else e->caller->callees = e->next_callee; } - if (e->caller->call_site_hash) + if (e->caller->call_site_hash && e->call_stmt) htab_remove_elt_with_hash (e->caller->call_site_hash, e->call_stmt, htab_hash_pointer (e->call_stmt)); @@ -1068,6 +1073,26 @@ cgraph_remove_edge (struct cgraph_edge *e) cgraph_free_edge (e); } +/* Remove fake cgraph edges for indirect calls. NODE is the callee + of the edges. */ + +void +cgraph_remove_fake_indirect_call_in_edges (struct cgraph_node *node) +{ + struct cgraph_edge *f, *e; + + if (!L_IPO_COMP_MODE) + return; + + for (e = node->callers; e; e = f) + { + f = e->next_caller; + if (!e->call_stmt) + cgraph_remove_edge (e); + } +} + + /* Set callee of call graph edge E and add it to the corresponding set of callers. */ @@ -1472,6 +1497,12 @@ cgraph_redirect_edge_call_stmt_to_callee (struct cgraph_edge *e) new_stmt = e->call_stmt; gimple_call_set_fndecl (new_stmt, e->callee->decl); update_stmt_fn (DECL_STRUCT_FUNCTION (e->caller->decl), new_stmt); + if (L_IPO_COMP_MODE) + { + int lp_nr = lookup_stmt_eh_lp (e->call_stmt); + if (lp_nr != 0 && !stmt_could_throw_p (e->call_stmt)) + remove_stmt_from_eh_lp (e->call_stmt); + } } /* If the call becomes noreturn, remove the lhs. */ @@ -1679,6 +1710,10 @@ cgraph_node_remove_callers (struct cgraph_node *node) void release_function_body (tree decl) { + if (cgraph_get_node (decl) + && cgraph_is_aux_decl_external (cgraph_get_node (decl))) + DECL_EXTERNAL (decl) = 1; + if (DECL_STRUCT_FUNCTION (decl)) { push_cfun (DECL_STRUCT_FUNCTION (decl)); @@ -1820,7 +1855,9 @@ cgraph_remove_node (struct cgraph_node *node) cgraph_release_function_body (node); } + cgraph_remove_link_node (node); node->decl = NULL; + if (node->call_site_hash) { htab_delete (node->call_site_hash); @@ -1837,6 +1874,7 @@ cgraph_remove_node (struct cgraph_node *node) free_nodes = node; } + /* Likewise indicate that a node is having address taken. */ void @@ -1978,6 +2016,9 @@ dump_cgraph_node (FILE *f, struct cgraph_node *node) if (node->count) fprintf (f, " executed "HOST_WIDEST_INT_PRINT_DEC"x", (HOST_WIDEST_INT)node->count); + if (node->max_bb_count) + fprintf (f, " hottest bb executed "HOST_WIDEST_INT_PRINT_DEC"x", + (HOST_WIDEST_INT)node->max_bb_count); if (node->origin) fprintf (f, " nested in: %s", node->origin->asm_name ()); if (gimple_has_body_p (node->decl)) @@ -2566,11 +2607,16 @@ clone_of_p (struct cgraph_node *node, struct cgraph_node *node2) skipped_thunk = true; } - if (skipped_thunk - && (!node2->clone_of - || !node2->clone.args_to_skip - || !bitmap_bit_p (node2->clone.args_to_skip, 0))) - return false; + if (skipped_thunk) + { + if (!node2->clone.args_to_skip + || !bitmap_bit_p (node2->clone.args_to_skip, 0)) + return false; + if (node2->former_clone_of == node->decl) + return true; + else if (!node2->clone_of) + return false; + } while (node != node2 && node2) node2 = node2->clone_of; @@ -2599,6 +2645,7 @@ verify_edge_count_and_frequency (struct cgraph_edge *e) error_found = true; } if (gimple_has_body_p (e->caller->decl) + && e->call_stmt && !e->caller->global.inlined_to && !e->speculative /* FIXME: Inline-analysis sets frequency to 0 when edge is optimized out. @@ -2855,7 +2902,9 @@ verify_cgraph_node (struct cgraph_node *node) error ("Alias has non-alias reference"); error_found = true; } - else if (ref_found) + else if (ref_found + /* in LIPO mode, the alias can refer to the real target also */ + && !L_IPO_COMP_MODE) { error ("Alias has more than one alias reference"); error_found = true; @@ -2969,7 +3018,7 @@ verify_cgraph_node (struct cgraph_node *node) for (e = node->callees; e; e = e->next_callee) { - if (!e->aux) + if (!e->aux && e->call_stmt) { error ("edge %s->%s has no corresponding call_stmt", identifier_to_locale (e->caller->name ()), |