Commit b4e93f45 by Jan Hubicka Committed by Jan Hubicka

re PR tree-optimization/51737 (g++ crashes (internal compiler error:…

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: r185694
parent e45381b3
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> 2012-03-22 Richard Guenther <rguenther@suse.de>
PR middle-end/52666 PR middle-end/52666
......
...@@ -1639,19 +1639,27 @@ cgraph_add_to_same_comdat_group (struct cgraph_node *new_, ...@@ -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 bool
cgraph_remove_node_and_inline_clones (struct cgraph_node *node) cgraph_remove_node_and_inline_clones (struct cgraph_node *node, struct cgraph_node *forbidden_node)
{ {
struct cgraph_edge *e, *next; struct cgraph_edge *e, *next;
bool found = false;
if (node == forbidden_node)
return true;
for (e = node->callees; e; e = next) for (e = node->callees; e; e = next)
{ {
next = e->next_callee; next = e->next_callee;
if (!e->inline_failed) 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); cgraph_remove_node (node);
return found;
} }
/* Notify finalize_compilation_unit that given node is reachable. */ /* Notify finalize_compilation_unit that given node is reachable. */
......
...@@ -478,7 +478,7 @@ void cgraph_insert_node_to_hashtable (struct cgraph_node *node); ...@@ -478,7 +478,7 @@ void cgraph_insert_node_to_hashtable (struct cgraph_node *node);
void cgraph_remove_edge (struct cgraph_edge *); void cgraph_remove_edge (struct cgraph_edge *);
void cgraph_remove_node (struct cgraph_node *); void cgraph_remove_node (struct cgraph_node *);
void cgraph_add_to_same_comdat_group (struct cgraph_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_release_function_body (struct cgraph_node *);
void cgraph_node_remove_callees (struct cgraph_node *node); void cgraph_node_remove_callees (struct cgraph_node *node);
struct cgraph_edge *cgraph_create_edge (struct cgraph_node *, struct cgraph_edge *cgraph_create_edge (struct cgraph_node *,
......
...@@ -336,8 +336,19 @@ save_inline_function_body (struct cgraph_node *node) ...@@ -336,8 +336,19 @@ save_inline_function_body (struct cgraph_node *node)
first_clone->ipa_transforms_to_apply); first_clone->ipa_transforms_to_apply);
first_clone->ipa_transforms_to_apply = NULL; 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 #ifdef ENABLE_CHECKING
verify_cgraph_node (first_clone); else
verify_cgraph_node (first_clone);
#endif #endif
return first_clone; return first_clone;
} }
......
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> 2012-03-22 Richard Guenther <rguenther@suse.de>
PR tree-optimization/52548 PR tree-optimization/52548
......
...@@ -4955,7 +4955,7 @@ delete_unreachable_blocks_update_callgraph (copy_body_data *id) ...@@ -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 = cgraph_edge (id->dst_node, gsi_stmt (bsi))) != NULL)
{ {
if (!e->inline_failed) if (!e->inline_failed)
cgraph_remove_node_and_inline_clones (e->callee); cgraph_remove_node_and_inline_clones (e->callee, id->dst_node);
else else
cgraph_remove_edge (e); cgraph_remove_edge (e);
} }
...@@ -4966,7 +4966,7 @@ delete_unreachable_blocks_update_callgraph (copy_body_data *id) ...@@ -4966,7 +4966,7 @@ delete_unreachable_blocks_update_callgraph (copy_body_data *id)
if ((e = cgraph_edge (node, gsi_stmt (bsi))) != NULL) if ((e = cgraph_edge (node, gsi_stmt (bsi))) != NULL)
{ {
if (!e->inline_failed) if (!e->inline_failed)
cgraph_remove_node_and_inline_clones (e->callee); cgraph_remove_node_and_inline_clones (e->callee, id->dst_node);
else else
cgraph_remove_edge (e); cgraph_remove_edge (e);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment