summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog10
-rw-r--r--gcc/cgraph.c16
-rw-r--r--gcc/cgraph.h2
-rw-r--r--gcc/ipa-inline-transform.c13
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/tree-inline.c4
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);
}