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.