https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83703

            Bug ID: 83703
           Summary: Loop termination condition ignored in -O3, works in
                    -O2 or with smaller values
           Product: gcc
           Version: 7.2.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c
          Assignee: unassigned at gcc dot gnu.org
          Reporter: freddie_chopin at op dot pl
  Target Milestone: ---

Example code:

-- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 --

#include <stdint.h>
#include <stdio.h>

const int32_t limit {359};

const int32_t in[]
{
  5999999,
  6000000,
  6000001,
  11999999,
  12000000,
  12000001,
  17999999,
  18000000,
  18000001,
  25999999,
  26000000,
};

const int32_t out[]
{
  0,
  0,
  1,
  1,
  1,
  2,
  2,
  2,
  3,
  3,
  3,
};

int main()
{
  for (int32_t b1 = -limit; b1 < limit; ++b1)
  {
    for (int32_t b0 = -limit; b0 < limit; ++b0)
    {
      for (int32_t a0 = -limit; a0 < limit; ++a0)
      {
        if (a0 == 0)
          continue;
        int fail = 0;
        for (size_t i {}; i < sizeof(out) / sizeof(*out) && fail == 0; ++i)
        {
          fail |= (b1 * in[i] + b0) / a0 != out[i];
        }

        if (fail == 0)
        {
          printf("success! %i %i %i\n", (int)b1, (int)b0, (int)a0);
          return 0;
        }          
      }
    }
    printf("fail! %i\n", (int)b1);
  }
  return 0;
}

-- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 -- >8 --

This code works as intended when compiled with -O2 - last iteration of the
outer loop is with b1 == 358. However when compiled with -O3, the outer's loop
condition is completely ignored - the loop passes well above the value of
`limit` and continues infinitely. Increasing the value of `limit` gives exactly
the same result.

This fails:
$ gcc -O3 reg.cpp -Wall -Wextra && ./a.out
fail! -359
fail! -358
...
fail! 964
fail! 965
^C
$


This works:
$ gcc -O2 reg.cpp -Wall -Wextra && ./a.out
fail! -359
fail! -358
...
fail! 357
fail! 358
$

When I change `limit` to 358, at -O3 there is only ONE iteration.

$ gcc -O3 reg.cpp -Wall -Wextra && ./a.out 
fail! -358
$

When I change `limit` to 357, the program works as intended at -O3. Any value
lower and it's the same

$ gcc --version
gcc (GCC) 7.2.1 20171128
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Tested on two PCs with Arch Linux, but both are actually mostly identical in
h/w and s/w.

Reply via email to