summaryrefslogtreecommitdiff
path: root/gcc/cgraphunit.c
diff options
context:
space:
mode:
authorjamborm <jamborm@138bc75d-0d04-0410-961f-82ee72b054a4>2010-03-18 20:07:13 +0000
committerjamborm <jamborm@138bc75d-0d04-0410-961f-82ee72b054a4>2010-03-18 20:07:13 +0000
commitc596d83002a937c3943de34c6f47da047337f865 (patch)
treeb3c65fe0aa2410f77c557a506bd3f0cf02737f6e /gcc/cgraphunit.c
parentdd5c72c237b288e15352aa0720416778e38e3962 (diff)
downloadgcc-c596d83002a937c3943de34c6f47da047337f865.tar.gz
2010-03-18 Martin Jambor <mjambor@suse.cz>
PR middle-end/42450 * cgraph.h (cgraph_redirect_edge_call_stmt_to_callee): Declare. * cgraphunit.c (cgraph_materialize_all_clones): Update calls in all non-clones. Moved call redirection... (cgraph_redirect_edge_call_stmt_to_callee): ...to this new function. (cgraph_materialize_all_clones): Dispose of all combined_args_to_skip bitmaps. (verify_cgraph_node): Do not check for edges pointing to wrong nodes in inline clones. * tree-inline.c (copy_bb): Call cgraph_redirect_edge_call_stmt_to_callee. * ipa.c (cgraph_remove_unreachable_nodes): Call cgraph_node_remove_callees even when there are used clones. * testsuite/g++.dg/torture/pr42450.C: New test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@157546 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/cgraphunit.c')
-rw-r--r--gcc/cgraphunit.c123
1 files changed, 66 insertions, 57 deletions
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index f4580adbd75..c41477bede3 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -751,8 +751,9 @@ verify_cgraph_node (struct cgraph_node *node)
debug_tree (e->callee->decl);
error_found = true;
}
- else if (!clone_of_p (cgraph_node (decl), e->callee)
- && !e->callee->global.inlined_to)
+ else if (!node->global.inlined_to
+ && !e->callee->global.inlined_to
+ && !clone_of_p (cgraph_node (decl), e->callee))
{
error ("edge points to wrong declaration:");
debug_tree (e->callee->decl);
@@ -2222,11 +2223,60 @@ cgraph_materialize_clone (struct cgraph_node *node)
bitmap_obstack_release (NULL);
}
+/* If necessary, change the function declaration in the call statement
+ associated with E so that it corresponds to the edge callee. */
+
+gimple
+cgraph_redirect_edge_call_stmt_to_callee (struct cgraph_edge *e)
+{
+ tree decl = gimple_call_fndecl (e->call_stmt);
+ gimple new_stmt;
+ gimple_stmt_iterator gsi;
+
+ if (!decl || decl == e->callee->decl
+ /* Don't update call from same body alias to the real function. */
+ || cgraph_get_node (decl) == cgraph_get_node (e->callee->decl))
+ return e->call_stmt;
+
+ if (cgraph_dump_file)
+ {
+ fprintf (cgraph_dump_file, "updating call of %s/%i -> %s/%i: ",
+ cgraph_node_name (e->caller), e->caller->uid,
+ cgraph_node_name (e->callee), e->callee->uid);
+ print_gimple_stmt (cgraph_dump_file, e->call_stmt, 0, dump_flags);
+ }
+
+ if (e->callee->clone.combined_args_to_skip)
+ new_stmt = gimple_call_copy_skip_args (e->call_stmt,
+ e->callee->clone.combined_args_to_skip);
+ else
+ new_stmt = e->call_stmt;
+ if (gimple_vdef (new_stmt)
+ && TREE_CODE (gimple_vdef (new_stmt)) == SSA_NAME)
+ SSA_NAME_DEF_STMT (gimple_vdef (new_stmt)) = new_stmt;
+ gimple_call_set_fndecl (new_stmt, e->callee->decl);
+
+ gsi = gsi_for_stmt (e->call_stmt);
+ gsi_replace (&gsi, new_stmt, true);
+
+ /* Update EH information too, just in case. */
+ maybe_clean_or_replace_eh_stmt (e->call_stmt, new_stmt);
+
+ cgraph_set_call_stmt_including_clones (e->caller, e->call_stmt, new_stmt);
+
+ if (cgraph_dump_file)
+ {
+ fprintf (cgraph_dump_file, " updated to:");
+ print_gimple_stmt (cgraph_dump_file, e->call_stmt, 0, dump_flags);
+ }
+ return new_stmt;
+}
+
/* Once all functions from compilation unit are in memory, produce all clones
- and update all calls.
- We might also do this on demand if we don't want to bring all functions to
- memory prior compilation, but current WHOPR implementation does that and it is
- is bit easier to keep everything right in this order. */
+ and update all calls. We might also do this on demand if we don't want to
+ bring all functions to memory prior compilation, but current WHOPR
+ implementation does that and it is is bit easier to keep everything right in
+ this order. */
void
cgraph_materialize_all_clones (void)
{
@@ -2302,69 +2352,28 @@ cgraph_materialize_all_clones (void)
if (cgraph_dump_file)
fprintf (cgraph_dump_file, "Updating call sites\n");
for (node = cgraph_nodes; node; node = node->next)
- if (node->analyzed && gimple_has_body_p (node->decl)
- && (!node->clone_of || node->clone_of->decl != node->decl))
+ if (node->analyzed && !node->clone_of
+ && gimple_has_body_p (node->decl))
{
struct cgraph_edge *e;
current_function_decl = node->decl;
push_cfun (DECL_STRUCT_FUNCTION (node->decl));
for (e = node->callees; e; e = e->next_callee)
- {
- tree decl = gimple_call_fndecl (e->call_stmt);
- /* When function gets inlined, indirect inlining might've invented
- new edge for orginally indirect stmt. Since we are not
- preserving clones in the original form, we must not update here
- since other inline clones don't need to contain call to the same
- call. Inliner will do the substitution for us later. */
- if (decl && decl != e->callee->decl)
- {
- gimple new_stmt;
- gimple_stmt_iterator gsi;
-
- if (cgraph_get_node (decl) == cgraph_get_node (e->callee->decl))
- /* Don't update call from same body alias to the real function. */
- continue;
-
- if (cgraph_dump_file)
- {
- fprintf (cgraph_dump_file, "updating call of %s in %s:",
- cgraph_node_name (node),
- cgraph_node_name (e->callee));
- print_gimple_stmt (cgraph_dump_file, e->call_stmt, 0, dump_flags);
- }
-
- if (e->callee->clone.combined_args_to_skip)
- new_stmt = gimple_call_copy_skip_args (e->call_stmt,
- e->callee->clone.combined_args_to_skip);
- else
- new_stmt = e->call_stmt;
- if (gimple_vdef (new_stmt)
- && TREE_CODE (gimple_vdef (new_stmt)) == SSA_NAME)
- SSA_NAME_DEF_STMT (gimple_vdef (new_stmt)) = new_stmt;
- gimple_call_set_fndecl (new_stmt, e->callee->decl);
-
- gsi = gsi_for_stmt (e->call_stmt);
- gsi_replace (&gsi, new_stmt, true);
-
- /* Update EH information too, just in case. */
- maybe_clean_or_replace_eh_stmt (e->call_stmt, new_stmt);
-
- cgraph_set_call_stmt_including_clones (node, e->call_stmt, new_stmt);
-
- if (cgraph_dump_file)
- {
- fprintf (cgraph_dump_file, " updated to:");
- print_gimple_stmt (cgraph_dump_file, e->call_stmt, 0, dump_flags);
- }
- }
- }
+ cgraph_redirect_edge_call_stmt_to_callee (e);
pop_cfun ();
current_function_decl = NULL;
#ifdef ENABLE_CHECKING
verify_cgraph_node (node);
#endif
}
+ if (cgraph_dump_file)
+ fprintf (cgraph_dump_file, "Materialization Call site updates done.\n");
+ /* All changes to parameters have been performed. In order not to
+ incorrectly repeat them, we simply dispose of the bitmaps that drive the
+ changes. */
+ for (node = cgraph_nodes; node; node = node->next)
+ node->clone.combined_args_to_skip = NULL;
#ifdef ENABLE_CHECKING
verify_cgraph ();
#endif