]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR tree-optimization/51737 (g++ crashes (internal compiler error: Segmentation...
authorJan Hubicka <jh@suse.cz>
Sun, 25 Mar 2012 09:39:32 +0000 (11:39 +0200)
committerJan Hubicka <hubicka@gcc.gnu.org>
Sun, 25 Mar 2012 09:39:32 +0000 (09:39 +0000)
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.

PR middle-end/51737
* g++.dg/torture/pr51737.C: New testcase

From-SVN: r185774

gcc/ChangeLog
gcc/cgraph.c
gcc/cgraph.h
gcc/cgraphunit.c
gcc/testsuite/ChangeLog
gcc/tree-inline.c

index 42aabdb8bf6222b9731217595b869cf7edd5f8cc..1a278e5d5684532a36fd935cd322801f96b2fdc8 100644 (file)
@@ -1,3 +1,14 @@
+2012-03-24  Jan Hubicka  <jh@suse.cz>
+
+       Backport from mainline
+       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-24  Steven Bosscher  <steven@gcc.gnu.org>
 
        PR middle-end/52640
index 41265f86c606b954f77fb4cbbf3ff425eda46d01..d62674a0b3004147450323f4945d41d6b695952d 100644 (file)
@@ -1700,19 +1700,27 @@ cgraph_remove_node (struct cgraph_node *node)
   free_nodes = node;
 }
 
-/* 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.  */
index e2d2f50ca3e9e661ea091f83bce123fbf0a5af45..c83b4d38ccc46ececa57f3417686f6cf6c615db8 100644 (file)
@@ -547,7 +547,7 @@ void debug_cgraph_node (struct cgraph_node *);
 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_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 *,
index e6a0ea65b2634b6954a0ba301b5815370c365072..7ed75be48ddc3ca2ff42f36dae414a4ea13e0c13 100644 (file)
@@ -2157,8 +2157,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;
 }
index 0a184e47bf0217a5e71a3459bbea223260ed705c..8f7edd07be76462647c601749abe3b20a3df3aae 100644 (file)
@@ -1,3 +1,8 @@
+2012-03-24  Jan Hubicka  <jh@suse.cz>
+
+       PR middle-end/51737
+       * g++.dg/torture/pr51737.C: New testcase
+
 2012-03-24  Steven Bosscher  <steven@gcc.gnu.org>
 
        PR middle-end/52640
index 06fc18de69b85e13f607219d2f035e915dd79264..5933c32f032adda474cbef4dc6f8479b9346c408 100644 (file)
@@ -4947,7 +4947,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);
                  }
@@ -4957,8 +4957,8 @@ 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);
+                         if (!e->inline_failed && e->callee != id->src_node)
+                           cgraph_remove_node_and_inline_clones (e->callee, id->dst_node);
                          else
                            cgraph_remove_edge (e);
                        }