X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fcgraph.c;h=9433301cf7761263d1c22bd2e5808d6ba7e2010e;hb=ab41202099d11e8eb23da94a9b697adce103a8ec;hp=60effb0f5ceca06940699809d05f7bd347119869;hpb=6f932b06df8837c89ebb97e12c497f86d08b7f60;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/cgraph.c b/gcc/cgraph.c index 60effb0f5ce..9433301cf77 100644 --- a/gcc/cgraph.c +++ b/gcc/cgraph.c @@ -1036,6 +1036,7 @@ cgraph_create_edge (struct cgraph_node *caller, struct cgraph_node *callee, struct cgraph_edge * cgraph_create_indirect_edge (struct cgraph_node *caller, gimple call_stmt, + int ecf_flags, gcov_type count, int freq, int nest) { struct cgraph_edge *edge = cgraph_create_edge_1 (caller, NULL, call_stmt, @@ -1044,8 +1045,9 @@ cgraph_create_indirect_edge (struct cgraph_node *caller, gimple call_stmt, edge->indirect_unknown_callee = 1; initialize_inline_failed (edge); - edge->indirect_info = GGC_NEW (struct cgraph_indirect_call_info); + edge->indirect_info = GGC_CNEW (struct cgraph_indirect_call_info); edge->indirect_info->param_index = -1; + edge->indirect_info->ecf_flags = ecf_flags; edge->next_callee = caller->indirect_calls; if (caller->indirect_calls) @@ -1292,6 +1294,15 @@ cgraph_node_remove_callees (struct cgraph_node *node) cgraph_edge_remove_callee (e); cgraph_free_edge (e); } + for (e = node->indirect_calls; e; e = f) + { + f = e->next_callee; + cgraph_call_edge_removal_hooks (e); + if (!e->indirect_unknown_callee) + cgraph_edge_remove_callee (e); + cgraph_free_edge (e); + } + node->indirect_calls = NULL; node->callees = NULL; if (node->call_site_hash) { @@ -1675,8 +1686,8 @@ cgraph_mark_needed_node (struct cgraph_node *node) void cgraph_mark_address_taken_node (struct cgraph_node *node) { + cgraph_mark_reachable_node (node); node->address_taken = 1; - cgraph_mark_needed_node (node); } /* Return local info for the compiled function. */ @@ -1819,6 +1830,8 @@ dump_cgraph_node (FILE *f, struct cgraph_node *node) fprintf (f, " always_inline"); else if (node->local.inlinable) fprintf (f, " inlinable"); + else if (node->local.versionable) + fprintf (f, " versionable"); if (node->local.redefined_extern_inline) fprintf (f, " redefined_extern_inline"); if (TREE_ASM_WRITTEN (node->decl)) @@ -2009,9 +2022,11 @@ cgraph_clone_edge (struct cgraph_edge *e, struct cgraph_node *n, } else { - new_edge = cgraph_create_indirect_edge (n, call_stmt, count, freq, + new_edge = cgraph_create_indirect_edge (n, call_stmt, + e->indirect_info->ecf_flags, + count, freq, e->loop_nest + loop_nest); - new_edge->indirect_info->param_index = e->indirect_info->param_index; + *new_edge->indirect_info = *e->indirect_info; } } else @@ -2033,12 +2048,14 @@ cgraph_clone_edge (struct cgraph_edge *e, struct cgraph_node *n, /* Create node representing clone of N executed COUNT times. Decrease the execution counts from original node too. + The new clone will have decl set to DECL that may or may not be the same + as decl of N. When UPDATE_ORIGINAL is true, the counts are subtracted from the original function's profile to reflect the fact that part of execution is handled by node. */ struct cgraph_node * -cgraph_clone_node (struct cgraph_node *n, gcov_type count, int freq, +cgraph_clone_node (struct cgraph_node *n, tree decl, gcov_type count, int freq, int loop_nest, bool update_original, VEC(cgraph_edge_p,heap) *redirect_callers) { @@ -2047,7 +2064,7 @@ cgraph_clone_node (struct cgraph_node *n, gcov_type count, int freq, gcov_type count_scale; unsigned i; - new_node->decl = n->decl; + new_node->decl = decl; new_node->origin = n->origin; if (new_node->origin) { @@ -2105,6 +2122,24 @@ cgraph_clone_node (struct cgraph_node *n, gcov_type count, int freq, new_node->clone_of = n; cgraph_call_node_duplication_hooks (n, new_node); + if (n->decl != decl) + { + struct cgraph_node **slot; + slot = (struct cgraph_node **) htab_find_slot (cgraph_hash, new_node, INSERT); + gcc_assert (!*slot); + *slot = new_node; + if (assembler_name_hash) + { + void **aslot; + tree name = DECL_ASSEMBLER_NAME (decl); + + aslot = htab_find_slot_with_hash (assembler_name_hash, name, + decl_assembler_name_hash (name), + INSERT); + gcc_assert (!*aslot); + *aslot = new_node; + } + } return new_node; } @@ -2146,11 +2181,13 @@ cgraph_create_virtual_clone (struct cgraph_node *old_node, tree old_decl = old_node->decl; struct cgraph_node *new_node = NULL; tree new_decl; - struct cgraph_node key, **slot; size_t i; struct ipa_replace_map *map; - gcc_assert (tree_versionable_function_p (old_decl)); +#ifdef ENABLE_CHECKING + if (!flag_wpa) + gcc_assert (tree_versionable_function_p (old_decl)); +#endif /* Make a new FUNCTION_DECL tree node */ if (!args_to_skip) @@ -2164,10 +2201,9 @@ cgraph_create_virtual_clone (struct cgraph_node *old_node, SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl)); SET_DECL_RTL (new_decl, NULL); - new_node = cgraph_clone_node (old_node, old_node->count, + new_node = cgraph_clone_node (old_node, new_decl, old_node->count, CGRAPH_FREQ_BASE, 0, false, redirect_callers); - new_node->decl = new_decl; /* Update the properties. Make clone visible only within this translation unit. Make sure that is not weak also. @@ -2230,21 +2266,6 @@ cgraph_create_virtual_clone (struct cgraph_node *old_node, new_node->lowered = true; new_node->reachable = true; - key.decl = new_decl; - slot = (struct cgraph_node **) htab_find_slot (cgraph_hash, &key, INSERT); - gcc_assert (!*slot); - *slot = new_node; - if (assembler_name_hash) - { - void **aslot; - tree name = DECL_ASSEMBLER_NAME (new_decl); - - aslot = htab_find_slot_with_hash (assembler_name_hash, name, - decl_assembler_name_hash (name), - INSERT); - gcc_assert (!*aslot); - *aslot = new_node; - } return new_node; }