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

            Bug ID: 128009
           Summary: wrong code at -O3 for a union of long double and
                    unsigned __int128 read through a pointer
           Product: gcc
           Version: 17.0
            Status: UNCONFIRMED
          Keywords: wrong-code
          Severity: normal
          Priority: P3
         Component: ipa
          Assignee: unassigned at gcc dot gnu.org
          Reporter: kyuwoncho18 at gmail dot com
  Target Milestone: ---
            Target: x86_64-pc-linux-gnu

union V { long double ld; unsigned __int128 q; unsigned char b[16]; };
__attribute__((noinline)) unsigned long long h(union V *p, int c, int n) {
  unsigned long long acc = 0;
  for (int i = 0; i < n; i++) {
    long double x = p->ld;
    if (c) acc += (unsigned long long)(p->q >> 64);
    acc += (unsigned long long)(x > 1.0L);
  }
  return acc;
}
int main(void) {
  union V v;
  v.ld = 1.5L;
  for (int k = 10; k < 16; k++) v.b[k] = 0xAA;
  unsigned long long r[2];
  for (int c = 0; c < 2; c++) r[c] = h(&v, c, 2);
  if (r[1] != 0xaaaaaaaaaaaa4000ULL * 2)
    __builtin_abort();
}

godbolt: https://godbolt.org/z/YbexK4Mo8

v holds 1.5L in bytes 0-9 and 0xAA in bytes 10-15, so p->q >> 64 is
0xaaaaaaaaaaaa3fff and h(&v, 1, 2) must return 0x5555555555548000. With -O0,
-O2 or -O3 -fno-ipa-sra the program exits normally, but with -O3 h(&v, 1, 2)
returns 0x8000 (it reads p->q >> 64 as 0x3fff, dropping bytes 10-15) and the
program aborts.

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

Reply via email to