Using GCC 4.8.0 as of 20121231 : $ cat bb.c int a, b, c; void foo() { unsigned d, l, *p, k = 1; if(bar()) { label: if((a = a <= 0)) { if(c) d = b; if (b || d ? l : k ? : 0) a = d = 0; goto label; } } while(*p++) goto label; } $ xgcc -w -O3 bb.c bb.c: In function ‘foo’: bb.c:24:1: error: edge from 27 to 29 should be marked irreducible } ^ bb.c:24:1: error: basic block 29 should be marked irreducible bb.c:24:1: error: edge from 29 to 7 should be marked irreducible bb.c:24:1: internal compiler error: in verify_loop_structure, at cfgloop.c:1582 Please submit a full bug report, with preprocessed source if appropriate. See <http://gcc.gnu.org/bugs.html> for instructions.
Confirmed. Also happens with 4.5 and 4.6 at least.
Thus marking as NEW. Related to PR52996.
Cannot reproduce with xgcc (GCC) 4.6.4 20130102 (prerelease).
(In reply to comment #3) > Cannot reproduce with xgcc (GCC) 4.6.4 20130102 (prerelease). Make sure to have checking enabled.
Also fails with 4.3.6, works with 4.1.2 though. Thus, technically a regression. Seems to work with 4.7 as well. RTL unswitching.
By unswitching on an exit test that exits to the enclosing loop we create an unswitched loop that is now reached by what looks like an exit test of the outer loop which is part of an irreducible region. I'm not sure we can reliably detect all cases we need to manually mark the entry edge for. So ... re-mark_irreducible_loops () after each transform? And cheaper checking by Index: loop-unswitch.c =================================================================== --- loop-unswitch.c (revision 195085) +++ loop-unswitch.c (working copy) @@ -145,12 +145,7 @@ unswitch_loops (void) /* Go through inner loops (only original ones). */ FOR_EACH_LOOP (li, loop, LI_ONLY_INNERMOST) - { - unswitch_single_loop (loop, NULL_RTX, 0); -#ifdef ENABLE_CHECKING - verify_loop_structure (); -#endif - } + unswitch_single_loop (loop, NULL_RTX, 0); iv_analysis_done (); } @@ -370,6 +365,10 @@ unswitch_single_loop (struct loop *loop, nloop = unswitch_loop (loop, bbs[i], copy_rtx_if_shared (cond), cinsn); gcc_assert (nloop); +#ifdef ENABLE_CHECKING + verify_loop_structure (); +#endif + /* Invoke itself on modified loops. */ unswitch_single_loop (nloop, rconds, num + 1); unswitch_single_loop (loop, conds, num + 1);
(In reply to comment #6) > By unswitching on an exit test that exits to the enclosing loop we create > an unswitched loop that is now reached by what looks like an exit test > of the outer loop which is part of an irreducible region. > > I'm not sure we can reliably detect all cases we need to manually mark > the entry edge for. So ... re-mark_irreducible_loops () after each > transform? Yeah, I'm looking into this for quite some time now and this occurred me too. I'm going to prepare some patch (together with your version of cheaper checking).
BTW, here is the CFG right before the verify_loops_structure (), which fails: http://people.redhat.com/mpolacek/src/pr55833.png
Zdenek may also have an idea here.
Author: mpolacek Date: Thu Jan 17 19:19:37 2013 New Revision: 195280 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=195280 Log: Fix PR55833. Added: trunk/gcc/testsuite/gcc.dg/pr55833.c Modified: trunk/gcc/ChangeLog trunk/gcc/cfgloopmanip.c trunk/gcc/loop-unswitch.c trunk/gcc/testsuite/ChangeLog
Fixed.
Considering backporting to 4.6.
(In reply to comment #12) > Considering backporting to 4.6. It's a checking verification failure only, also it's likely latent on the 4.7 branch. RM says FIXED in 4.8, not to be backported.