Bug 67005 - [5/6 Regression] ICE: in verify_loop_structure, at cfgloop.c:1647 (loop with header n not in loop tree)
Summary: [5/6 Regression] ICE: in verify_loop_structure, at cfgloop.c:1647 (loop with ...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: middle-end (show other bugs)
Version: 6.0
: P3 normal
Target Milestone: 5.3
Assignee: Marek Polacek
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2015-07-25 08:32 UTC by Antoine Balestrat
Modified: 2015-08-31 12:46 UTC (History)
0 users

See Also:
Host:
Target:
Build:
Known to work: 4.9.3
Known to fail: 5.2.0, 6.0
Last reconfirmed: 2015-07-27 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Antoine Balestrat 2015-07-25 08:32:07 UTC
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.
Comment 1 Richard Biener 2015-07-27 08:12:53 UTC
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.
Comment 2 Marek Polacek 2015-08-25 08:59:54 UTC
Still ICEs; probably it's just about adding loops_state_set (LOOPS_NEED_FIXUP); somewhere into tree-ssa-dce.c?
Comment 3 Richard Biener 2015-08-25 09:06:27 UTC
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)
Comment 4 Richard Biener 2015-08-25 09:07:28 UTC
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
Comment 5 Marek Polacek 2015-08-25 11:48:59 UTC
Taking this over for now.
Comment 6 Marek Polacek 2015-08-25 12:57:51 UTC
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?
Comment 7 Marek Polacek 2015-08-25 14:49:36 UTC
(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.
Comment 8 Marek Polacek 2015-08-27 17:08:07 UTC
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
Comment 9 Marek Polacek 2015-08-27 17:08:47 UTC
Fixed.
Comment 10 Richard Biener 2015-08-28 09:34:21 UTC
Can you please backport to GCC 5 as well?
Comment 11 Marek Polacek 2015-08-31 11:31:40 UTC
(In reply to Richard Biener from comment #10)
> Can you please backport to GCC 5 as well?

Sure.
Comment 12 Marek Polacek 2015-08-31 12:46:46 UTC
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