[Bug middle-end/71716] [7 Regression] gcc.dg/atomic/c11-atomic-exec-4.c is miscompiled with -march=corei7
jakub at gcc dot gnu.org
gcc-bugzilla@gcc.gnu.org
Fri Jul 1 08:48:00 GMT 2016
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.
More information about the Gcc-bugs
mailing list