Bug 56488 - [4.7 Regression] wrong code for loop at -O3
Summary: [4.7 Regression] wrong code for loop at -O3
Status: RESOLVED DUPLICATE of bug 55481
Alias: None
Product: gcc
Classification: Unclassified
Component: tree-optimization (show other bugs)
Version: 4.7.2
: P3 normal
Target Milestone: 4.7.3
Assignee: Not yet assigned to anyone
URL:
Keywords: wrong-code
Depends on:
Blocks:
 
Reported: 2013-03-01 04:25 UTC by Dara Hazeghi
Modified: 2013-03-01 12:23 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2013-03-01 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Dara Hazeghi 2013-03-01 04:25:43 UTC
The following code (reduced from a larger testcase) when compiled at -O3 with gcc 4.7.2 produces an executable that does not terminate.  Compiling with lower optimizations, current gcc trunk or the older 4.6.3 release at -O3, the executable terminates as expected.


$ gcc-4.7 --version
gcc-4.7 (GCC) 4.7.2
$ gcc-4.7 -O2 loop.c
$ ./a.out 
$ gcc-4.6 -O3 loop.c
$ ./a.out 
$ gcc-4.7 -O3 loop.c
$ ./a.out 
<hangs> ^C
$ cat loop.c

int a, c, d = 1;

struct
{
    int f0;
} b, f;

short e;

void fn1 (p1)
{
    int g[] = { };
    e = 0;
    for (; e != 1; e = e + 5)
    {
        int *h[] = {[0] & g[0] };
        if (p1);
        else
            return;
        f = b;
    }
}

int main ()
{
    int i, j;
    i = 0;
    for (; i < 6; i++)
    {
        j = 8;
        for (; j; j--)
            a = 0;
    }
    fn1 (d);
    for (; c;);
}
Comment 1 Andrew Pinski 2013-03-01 06:58:48 UTC
Works on the trunk.
Comment 2 Jakub Jelinek 2013-03-01 07:59:16 UTC
Seems to have started with http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=181172
and fixed by http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=190614

Slightly cleaned up testcase:
int a, c, d = 1;
struct S { int s; } b, f;
short e;

void
foo (int x)
{
  int g[] = { };
  for (e = 0; e != 1; e = e + 5)
    {
      int *h[1] = { &g[0] };
      if (!x)
return;
      f = b;
    }
}

int
main ()
{
  int i, j;
  for (i = 0; i < 6; i++)
    for (j = 8; j; j--)
      a = 0;
  foo (d);
  while (c)
    ;
  return 0;
}
Comment 3 Marc Glisse 2013-03-01 09:53:20 UTC
Seems to me that 'e' is signed and the testcase relies on wrapping overflow (-fwrapv helps).
Comment 4 Jakub Jelinek 2013-03-01 09:59:39 UTC
But e = e + 5 is avaluated as
e = (short) ((int) e + 5)
and thus I think it just falls down to implementation defined behavior (assuming short is smaller than int of course), because no overflow happens in the int type in which the addition is computed, and there is just cast of a larger int value to smaller short type.
Comment 5 Marc Glisse 2013-03-01 10:05:53 UTC
You are right, of course. I remembered that gcc defined unsigned->signed conversion, but I had forgotten that it defined all narrowing conversions as well, sorry.
Comment 6 Richard Biener 2013-03-01 12:20:21 UTC
The fixing rev. doesn't make much sense ;)  The issue must be still latent.

> But e = e + 5 is avaluated as
> e = (short) ((int) e + 5)

not true before VRP2:

  short int e.2;
  short int e.4;

...

<bb 3>:
  # e.2_4 = PHI <e.4_18(3), 0(2)>
  f = b;
  D.1777_45 = e.2_4 + 5;
  e.4_18 = D.1777_45;
  e = e.4_18;
  if (e.4_18 != 1)
    goto <bb 3>;
  else
    goto <bb 4>;

which turns it into an endless loop.  The FE shortened to

  e = (short int) ((short unsigned int) e + 5);

but IVOPTs makes it short.  There was a related bugfix by Zdenek for 4.8.
Comment 7 Richard Biener 2013-03-01 12:23:57 UTC
PR55481, backporting that fixes it.

*** This bug has been marked as a duplicate of bug 55481 ***