Hi,
the testcase reproduce ICE in a very corner case of inlining. What happens is
1) early inlining is tricked to produce very complex self recursive callgraph
graph
by somewhat bogus inlining of self recursive cycles
2) late inliner decide to continue in the recursive inlining
3) ipa-pure-const detect that the recrusive cycle is non-throwing. This is not
detected by local-pure-const because at that time the inline cycle is still
indirect recursion we do not handle there
4) in inline-transform we notice the recursive inlining and save function body
for later reuse
5) during duplication we get rid of the now dead EH edge from call to EH
receiver
because of ipa-pure-const change on functio ndeclaration.
6) after duplication we must delete unreachable blocks to build dominators and
update
SSA. This gets rid of the dead basic block containing the inlined recursive
call.
This means updating all the clones by removing calls and if the call is
inlined
also the inline clones representing the duplication. Because inlining is
recursive,
we end up removing the inlined function itself, but we can not since we are
just
duplicating it. So we postpone this for later.
7) we ice in verify_cgraph clone because step 6) did not removed the dead call.
This patch fixes it. The bug existed in a tree quite forever, but it leads only
to enable-checking ICE and nothing else (the extra edge will be removed shortly
after the verify_cgraph_node call), so I think it needs no backporting.
Bootstrapped/regtested x86_64-linux, will commit it shortly.
Honza
PR tree-optimization/r55789
* cgraphclones.c (cgraph_remove_node_and_inline_clones): Remove
the dead call anyway.
* g++.dg/torture/pr55789.C: New testcase.
Index: testsuite/g++.dg/torture/pr55789.C
===================================================================
*** testsuite/g++.dg/torture/pr55789.C (revision 0)
--- testsuite/g++.dg/torture/pr55789.C (revision 0)
***************
*** 0 ****
--- 1,30 ----
+ /* { dg-do compile } */
+ /* { dg-options "-fno-guess-branch-probability -fno-tree-forwprop --param
max-early-inliner-iterations=10 --param=early-inlining-insns=176" } */
+
+ template < typename T > struct intrusive_ptr
+ {
+ ~intrusive_ptr ()
+ {
+ delete px;
+ }
+ T *px;
+ };
+
+ struct section_info
+ {
+ intrusive_ptr < section_info > parent;
+ };
+
+ struct file_info
+ {
+ intrusive_ptr < file_info > parent;
+ intrusive_ptr < section_info > switched_section;
+ };
+
+
+ void
+ start_file (void)
+ {
+ intrusive_ptr < file_info > parent;
+ }
+
Index: cgraphclones.c
===================================================================
*** cgraphclones.c (revision 195370)
--- cgraphclones.c (working copy)
*************** cgraph_remove_node_and_inline_clones (st
*** 570,576 ****
bool found = false;
if (node == forbidden_node)
! return true;
for (e = node->callees; e; e = next)
{
next = e->next_callee;
--- 570,579 ----
bool found = false;
if (node == forbidden_node)
! {
! cgraph_remove_edge (node->callers);
! return true;
! }
for (e = node->callees; e; e = next)
{
next = e->next_callee;