https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71716
Jakub Jelinek <jakub at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |jakub at gcc dot gnu.org --- Comment #3 from Jakub Jelinek <jakub at gcc dot gnu.org> --- Short testcase for -Os -march=corei7: static void test_mult (void) { static volatile _Atomic (long double) a = (long double) -3; if ((a *= 5) != (long double) ((long double) -3 * 5)) __builtin_abort (); if (a != (long double) ((long double) -3 * 5)) __builtin_abort (); static volatile _Atomic (long double) b = (long double) -7; if ((b *= -20) != (long double) ((long double) -7 * -20)) __builtin_abort (); if (b != (long double) ((long double) -7 * -20)) __builtin_abort (); static volatile _Atomic (long double) c = (long double) 1.25; if ((c *= 3.5) != (long double) ((long double) 1.25 * 3.5)) __builtin_abort (); if (c != (long double) ((long double) 1.25 * 3.5)) __builtin_abort (); } int main () { test_mult (); return 0; } The problem is, before the ATOMIC_COMPARE_EXCHANGE transformation we have: long double D.1752; long double D.1751; ... _1 = __atomic_load_16 (&a, 5); _2 = VIEW_CONVERT_EXPR<long double>(_1); D.1751 = _2; ... _4 = D.1751; _5 = D.1750; _6 = (long double) _5; _7 = _4 * _6; D.1752 = _7; _8 = D.1752; _9 = VIEW_CONVERT_EXPR<__int128 unsigned>(_8); _10 = __atomic_compare_exchange_16 (&a, &D.1751, _9, 0, 5, 5); Already the VCE to long double might be weird, what if the memory at a contains some bits the VCE to long double does not preserve. What about sNaNs, etc.? In the lowering, because D.1751 is not addressable otherwise, we turn it into: _9 = VIEW_CONVERT_EXPR<__int128 unsigned>(_7); _128 = _146; _129 = VIEW_CONVERT_EXPR<__int128 unsigned>(_146); _130 = ATOMIC_COMPARE_EXCHANGE (&a, _129, _9, 16, 5, 5); _131 = IMAGPART_EXPR <_130>; _10 = (_Bool) _131; _132 = REALPART_EXPR <_130>; _133 = VIEW_CONVERT_EXPR<long double>(_132); _152 = _133; which introduces another VCE, and apparently both __int128 -> long double and long double -> __int128 VCEs are expanded as a store to a stack slot and load from it. The problem is that storing a long double into memory doesn't overwrite all bits and thus the subsequent load of __int128 contains some uninitialized bits in it.