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

            Bug ID: 128401
           Summary: Wrong code for negative infinity: x/x leads ranger to
                    fold x != x to true
           Product: gcc
           Version: 17.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: tree-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: jeffchen006 at gmail dot com
  Target Milestone: ---

GCC 17.0.0 20261102 (experimental), revision
7eb405c3d119d4fc84b31f21d6499069fbfedad8
Target: x86_64-linux-gnu; reproduced on Compiler Explorer.
Configure options (installation paths and packaging metadata omitted):
--build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
--disable-bootstrap --enable-multiarch --with-abi=m64
--with-multilib-list=m32,m64,mx32 --enable-multilib --enable-clocale=gnu
--enable-languages=c,c++,fortran,ada,objc,obj-c++,go,d,rust,m2,cobol,algol68
--enable-ld=yes --enable-gold=yes --enable-libstdcxx-time=yes
--enable-linker-build-id --enable-lto --enable-plugins --enable-threads=posix

The testcase is complete and has no #include dependencies. Compile and run with
no command-line arguments.

Testcase (bug-007.c):

int printf(const char *, ...);

int f(double x)
{
  double d = x / x;
  if (x >= 0)
    return 7;
  if (d > -1)
    return 1;
  if (x != x)
    return 2;
  return 3;
}

double v = -__builtin_inf();

int main(void)
{
  printf("%d\n", f(v));
  return 0;
}

Reproduction commands:

  gcc -std=gnu2x -Wall -Wextra -O0 bug-007.c -o o0
  ./o0
  gcc -std=gnu2x -Wall -Wextra -O3 bug-007.c -o o3
  ./o3

Expected: 3
Actual with -O0: 3
Actual with -O3: 2
Compilation produces no diagnostics with -Wall -Wextra.

The failure also persists with:

  -O3 -fno-strict-aliasing -fwrapv -fno-aggressive-loop-optimizations



Analysis and additional checks:

For x = negative infinity, x/x is a NaN but x itself is not a NaN. Neither x >=
0 nor (x/x) > -1 is true, and x != x is false, so f must return 3 on this
IEEE-754 target. The optimized executable returns 2. No fast-math or
finite-math-only option is used.

This version initializes the input with -__builtin_inf(), avoiding the
overflowing constant expression in the original reduction. It still fails on
current trunk and on Compiler Explorer GCC 13.4 and 15.3 at -O3.

Suspected area: floating-point range inference in foperator_div::op1_range. A
NaN result from x/x does not imply that x is a NaN, because infinity/infinity
also produces NaN. This diagnosis has not been verified by a compiler patch.

The ASan+UBSan+float-cast-overflow build runs without sanitizer diagnostics and
still prints 2.

Reply via email to