diff options
author | jamborm <jamborm@138bc75d-0d04-0410-961f-82ee72b054a4> | 2010-03-18 20:07:13 +0000 |
---|---|---|
committer | jamborm <jamborm@138bc75d-0d04-0410-961f-82ee72b054a4> | 2010-03-18 20:07:13 +0000 |
commit | c596d83002a937c3943de34c6f47da047337f865 (patch) | |
tree | b3c65fe0aa2410f77c557a506bd3f0cf02737f6e /gcc/cgraphunit.c | |
parent | dd5c72c237b288e15352aa0720416778e38e3962 (diff) | |
download | gcc-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.c | 123 |
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 |