From: Jan Hubicka Date: Sun, 25 Mar 2012 09:39:32 +0000 (+0200) Subject: re PR tree-optimization/51737 (g++ crashes (internal compiler error: Segmentation... X-Git-Tag: releases/gcc-4.6.4~624 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7ef871ba96798bac1b083f1cdf4ff044919fdf5c;p=thirdparty%2Fgcc.git re PR tree-optimization/51737 (g++ crashes (internal compiler error: Segmentation fault) when compiling quickbook) 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 42aabdb8bf62..1a278e5d5684 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2012-03-24 Jan Hubicka + + 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 PR middle-end/52640 diff --git a/gcc/cgraph.c b/gcc/cgraph.c index 41265f86c606..d62674a0b300 100644 --- a/gcc/cgraph.c +++ b/gcc/cgraph.c @@ -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. */ diff --git a/gcc/cgraph.h b/gcc/cgraph.h index e2d2f50ca3e9..c83b4d38ccc4 100644 --- a/gcc/cgraph.h +++ b/gcc/cgraph.h @@ -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 *, diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c index e6a0ea65b263..7ed75be48ddc 100644 --- a/gcc/cgraphunit.c +++ b/gcc/cgraphunit.c @@ -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; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 0a184e47bf02..8f7edd07be76 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2012-03-24 Jan Hubicka + + PR middle-end/51737 + * g++.dg/torture/pr51737.C: New testcase + 2012-03-24 Steven Bosscher PR middle-end/52640 diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index 06fc18de69b8..5933c32f032a 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -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); }