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.

Reply via email to