diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/cgraph.c | 16 | ||||
-rw-r--r-- | gcc/cgraph.h | 2 | ||||
-rw-r--r-- | gcc/ipa-inline-transform.c | 13 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/tree-inline.c | 4 |
6 files changed, 42 insertions, 8 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 86f7e069dd5..a3e966fa5ea 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2012-03-22 Jan Hubicka <jh@suse.cz> + + PR middle-end/51737 + * cgraph.c (cgraph_remove_node_and_inline_clones): Add FORBIDDEN_NODE + parameter. + * cgraph.h (cgraph_remove_node_and_inline_clones): Update prototype. + * ipa-inline-transform.c (save_inline_function_body): Remove copied clone + if needed. + * tree-inline.c (delete_unreachable_blocks_update_callgraph): Update. + 2012-03-22 Richard Guenther <rguenther@suse.de> PR middle-end/52666 diff --git a/gcc/cgraph.c b/gcc/cgraph.c index 9cc36903a8c..7c44c059245 100644 --- a/gcc/cgraph.c +++ b/gcc/cgraph.c @@ -1639,19 +1639,27 @@ cgraph_add_to_same_comdat_group (struct cgraph_node *new_, } } -/* Remove the node from cgraph. */ +/* Remove the node from cgraph and all inline clones inlined into it. + Skip however removal of FORBIDDEN_NODE and return true if it needs to be + removed. This allows to call the function from outer loop walking clone + tree. */ -void -cgraph_remove_node_and_inline_clones (struct cgraph_node *node) +bool +cgraph_remove_node_and_inline_clones (struct cgraph_node *node, struct cgraph_node *forbidden_node) { struct cgraph_edge *e, *next; + bool found = false; + + if (node == forbidden_node) + return true; for (e = node->callees; e; e = next) { next = e->next_callee; if (!e->inline_failed) - cgraph_remove_node_and_inline_clones (e->callee); + found |= cgraph_remove_node_and_inline_clones (e->callee, forbidden_node); } cgraph_remove_node (node); + return found; } /* Notify finalize_compilation_unit that given node is reachable. */ diff --git a/gcc/cgraph.h b/gcc/cgraph.h index 191364ca377..db4bcea1fc4 100644 --- a/gcc/cgraph.h +++ b/gcc/cgraph.h @@ -478,7 +478,7 @@ void cgraph_insert_node_to_hashtable (struct cgraph_node *node); void cgraph_remove_edge (struct cgraph_edge *); void cgraph_remove_node (struct cgraph_node *); void cgraph_add_to_same_comdat_group (struct cgraph_node *, struct cgraph_node *); -void cgraph_remove_node_and_inline_clones (struct cgraph_node *); +bool cgraph_remove_node_and_inline_clones (struct cgraph_node *, struct cgraph_node *); void cgraph_release_function_body (struct cgraph_node *); void cgraph_node_remove_callees (struct cgraph_node *node); struct cgraph_edge *cgraph_create_edge (struct cgraph_node *, diff --git a/gcc/ipa-inline-transform.c b/gcc/ipa-inline-transform.c index 75b8e9daf11..32d8c167be1 100644 --- a/gcc/ipa-inline-transform.c +++ b/gcc/ipa-inline-transform.c @@ -336,8 +336,19 @@ save_inline_function_body (struct cgraph_node *node) first_clone->ipa_transforms_to_apply); first_clone->ipa_transforms_to_apply = NULL; + /* When doing recursive inlining, the clone may become unnecessary. + This is possible i.e. in the case when the recursive function is proved to be + non-throwing and the recursion happens only in the EH landing pad. + We can not remove the clone until we are done with saving the body. + Remove it now. */ + if (!first_clone->callers) + { + cgraph_remove_node_and_inline_clones (first_clone, NULL); + first_clone = NULL; + } #ifdef ENABLE_CHECKING - verify_cgraph_node (first_clone); + else + verify_cgraph_node (first_clone); #endif return first_clone; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 5bdb9a3d1a6..0e668832be3 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2012-03-22 Jan Hubicka <jh@suse.cz> + + PR middle-end/51737 + * g++.dg/torture/pr51737.C: New testcase + 2012-03-22 Richard Guenther <rguenther@suse.de> PR tree-optimization/52548 diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index ae773f63b58..5d58c5169bb 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -4955,7 +4955,7 @@ delete_unreachable_blocks_update_callgraph (copy_body_data *id) if ((e = cgraph_edge (id->dst_node, gsi_stmt (bsi))) != NULL) { if (!e->inline_failed) - cgraph_remove_node_and_inline_clones (e->callee); + cgraph_remove_node_and_inline_clones (e->callee, id->dst_node); else cgraph_remove_edge (e); } @@ -4966,7 +4966,7 @@ delete_unreachable_blocks_update_callgraph (copy_body_data *id) if ((e = cgraph_edge (node, gsi_stmt (bsi))) != NULL) { if (!e->inline_failed) - cgraph_remove_node_and_inline_clones (e->callee); + cgraph_remove_node_and_inline_clones (e->callee, id->dst_node); else cgraph_remove_edge (e); } |