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;

Reply via email to