Hello ! Please consider the following testcase which makes a freshly built GCC 6.0 ICE at -O2. $ cat test.c int a; void f(void) { if(!a); else lbl: a = a; if(a) a = 8; goto lbl; } $ xgcc -w -O2 test.c test.c: In function ‘f’: test.c:12:1: error: loop with header 4 not in loop tree } ^ current.c:12:1: internal compiler error: in verify_loop_structure, at cfgloop.c:1647 0x708a75 verify_loop_structure() ../../srcdir/gcc/cfgloop.c:1647 0xa20955 loop_optimizer_init(unsigned int) ../../srcdir/gcc/loop-init.c:109 0xadc9e2 execute ../../srcdir/gcc/predict.c:3032 Please submit a full bug report, with preprocessed source if appropriate. Please include the complete backtrace with any bug report. See <http://gcc.gnu.org/bugs.html> for instructions.
Confirmed. The loop "appears" after CDDCE1 where a loop with multiple entries becomes one with a single entry. DCE expects cleanup-cfg to fix things but that doesn't do anything and thus doesn't end up fixing up loops. Mine.
Still ICEs; probably it's just about adding loops_state_set (LOOPS_NEED_FIXUP); somewhere into tree-ssa-dce.c?
Yeah, though "somewhere" would be all the time if we and up removing an edge. I've meant to see whether we can restrict it to "removed an edge with IRREDUCIBLE_LOOP flag set, but then we'd have to compute that first and we only do that for 'aggressive' aka CDDCE. Didn't get around to play with that ;) (note the ICE appears after CDDCE only, but I would need to convince myself that regular DCE can't trigger the same issue - I think it can't)
Note we already do /* If we made a BB unconditionally exit a loop then this transform alters the set of BBs in the loop. Schedule a fixup. */ if (loop_exit_edge_p (bb->loop_father, e)) loops_state_set (LOOPS_NEED_FIXUP); remove_edge (e2); thus this would need to add sth like || e2->flags & IRREDUCIBLE_LOOP
Taking this over for now.
Hm, adding || (e2->flags & EDGE_IRREDUCIBLE_LOOP) doesn't work; the E2 edge doesn't have the EDGE_IRREDUCIBLE_LOOP flag, even if I recompute that flag via mark_irreducible_loops. So maybe set LOOPS_NEED_FIXUP every time we remove an edge? FTR, the CFG looks like f () { int a.0_4; int a.0_7; <bb 2>: a.0_4 = a; if (a.0_4 == 0) goto <bb 3> (lbl); else goto <bb 4>; lbl: <bb 4>: a.0_7 = a; if (a.0_7 != 0) goto <bb 5>; else goto <bb 3> (lbl); <bb 5>: a = 8; goto <bb 3> (lbl); } so the 2 -> 4 and 2 -> 3 edges are multiple entries of a loop -- why aren't they EDGE_IRREDUCIBLE_LOOP?
(In reply to Marek Polacek from comment #6) > Hm, adding || (e2->flags & EDGE_IRREDUCIBLE_LOOP) doesn't work; the E2 edge > doesn't have the EDGE_IRREDUCIBLE_LOOP flag, even if I recompute that flag > via mark_irreducible_loops. So maybe set LOOPS_NEED_FIXUP every time we > remove an edge? I did some measurements on a GCC regtest. The edge removal was triggered ~13000 times, but for only ~4000 out of that was "loop_exit_edge_p (bb->loop_father, e)" true -- setting LOOPS_NEED_FIXUP unconditionally would be maybe too expensive thus.
Author: mpolacek Date: Thu Aug 27 17:07:35 2015 New Revision: 227268 URL: https://gcc.gnu.org/viewcvs?rev=227268&root=gcc&view=rev Log: PR middle-end/67005 * tree-ssa-dce.c (remove_dead_stmt): Also schedule fixup if removing an entry into an irreducible region. * gcc.dg/torture/pr67005.c: New test. Added: trunk/gcc/testsuite/gcc.dg/torture/pr67005.c Modified: trunk/gcc/ChangeLog trunk/gcc/testsuite/ChangeLog trunk/gcc/tree-ssa-dce.c
Fixed.
Can you please backport to GCC 5 as well?
(In reply to Richard Biener from comment #10) > Can you please backport to GCC 5 as well? Sure.
Author: mpolacek Date: Mon Aug 31 12:46:14 2015 New Revision: 227340 URL: https://gcc.gnu.org/viewcvs?rev=227340&root=gcc&view=rev Log: PR middle-end/67005 * tree-ssa-dce.c (remove_dead_stmt): Also schedule fixup if removing an entry into an irreducible region. * gcc.dg/torture/pr67005.c: New test. Added: branches/gcc-5-branch/gcc/testsuite/gcc.dg/torture/pr67005.c Modified: branches/gcc-5-branch/gcc/ChangeLog branches/gcc-5-branch/gcc/testsuite/ChangeLog branches/gcc-5-branch/gcc/tree-ssa-dce.c