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

            Bug ID: 127876
           Summary: Wrong code at -O3: conditional reduction to -0.0
                    returns +0.0 (CONST_COND_REDUCTION uses MAX_EXPR)
           Product: gcc
           Version: 17.0
            Status: UNCONFIRMED
          Keywords: wrong-code
          Severity: normal
          Priority: P3
         Component: tree-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: kyuwoncho18 at gmail dot com
  Target Milestone: ---

godbolt: https://godbolt.org/z/drczvec53
```c
#include <stdio.h>
#include <string.h>

__attribute__((noinline))
double f (double *a, int n)
{
  double r = 0.0;
  for (int i = 0; i < n; i++)
    if (a[i] > 100.0)
      r = -0.0;
  return r;
}

int main (void)
{
  double a[32];
  for (int i = 0; i < 32; i++)
    a[i] = 1.0;
  a[7] = 200.0;

  double r = f (a, 32);
  unsigned long long bits;
  memcpy (&bits, &r, sizeof bits);
  printf ("r=%g bits=%016llx\n", r, bits);
  return 0;
}
```
```console
$ gcc -O3 t.c && ./a.out
r=0 bits=0000000000000000
$ gcc -O3 -fno-tree-vectorize t.c && ./a.out
r=-0 bits=8000000000000000
```
Expected `-0` (bits `8000000000000000`): `a[7] > 100.0`, so `r` is set to
`-0.0`, and signed zeros are honored by default (`-O3 -fsigned-zeros` still
prints `0`). Clang prints `-0`.

The loop is vectorized as a `CONST_COND_REDUCTION`. `vectorizable_reduction`
picks `MAX_EXPR` because `fold_binary (LE_EXPR, 0.0, -0.0)` is true, but MAX
cannot tell `-0.0` from the initial `+0.0`. Nothing on this path checks
`HONOR_SIGNED_ZEROS`.

Fails with GCC 9.1 through trunk (17.0.0 20261012). The surviving sign depends
on which lane holds the `-0.0`: with `a[6] = 200.0` instead, trunk prints `-0`
but GCC 8.5 prints `0`.

Disclaimer: This test case was generated by a fuzzer, and the report was
written with LLM assistance.

Reply via email to