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

            Bug ID: 122368
           Summary: [16 Regression] gcc.target/s390/md/atomic_exchange-1.c
                    fails since r16-4081-g966cdec2b23b80
           Product: gcc
           Version: 16.0
            Status: UNCONFIRMED
          Keywords: wrong-code
          Severity: normal
          Priority: P3
         Component: middle-end
          Assignee: unassigned at gcc dot gnu.org
          Reporter: stefansf at gcc dot gnu.org
  Target Milestone: ---
            Target: s390*-*-*

If gcc itself is build with CFLAGS="-O0" CXXFLAGS="-O0", then the tests pass
and fail when CFLAGS="-O1" CXXFLAGS="-O1" is used:

FAIL: gcc.target/s390/md/atomic_exchange-1.c  -O0  execution test
FAIL: gcc.target/s390/md/atomic_exchange-1.c  -O0 -march=z13  execution test
FAIL: gcc.target/s390/md/atomic_exchange-1.c  -O0 -march=z900  execution test
FAIL: gcc.target/s390/md/atomic_exchange-1.c  -O1  execution test
FAIL: gcc.target/s390/md/atomic_exchange-1.c  -O1 -march=z13  execution test
FAIL: gcc.target/s390/md/atomic_exchange-1.c  -O1 -march=z900  execution test
FAIL: gcc.target/s390/md/atomic_exchange-1.c  -O2  execution test
FAIL: gcc.target/s390/md/atomic_exchange-1.c  -O2 -march=z13  execution test
FAIL: gcc.target/s390/md/atomic_exchange-1.c  -O2 -march=z900  execution test
FAIL: gcc.target/s390/md/atomic_exchange-1.c  -O3  execution test
FAIL: gcc.target/s390/md/atomic_exchange-1.c  -O3 -march=z13  execution test
FAIL: gcc.target/s390/md/atomic_exchange-1.c  -O3 -march=z900  execution test
WARNING: gcc.target/s390/md/atomic_exchange-1.c  -Os  execution test program
timed out.
FAIL: gcc.target/s390/md/atomic_exchange-1.c  -Os  execution test
FAIL: gcc.target/s390/md/atomic_exchange-1.c  -Os -march=z13  execution test
FAIL: gcc.target/s390/md/atomic_exchange-1.c  -Os -march=z900  execution test
FAIL: gcc.target/s390/md/atomic_exchange-1.c execution test

The failing part of the test is:

__int128 g128;

int main (void)
{
  __atomic_exchange_n (&g128, 0, 2);
  if (g128 != 0)
    __builtin_abort ();
  return 0;
}

In libatomic/config/s390/exch_n.c we have some special casing since on s390 a
TI value has an alignment of 8 byte and in case the compiler can prove that a
TI value is actually 16 byte aligned, we can exploit instruction
compare-and-swap in a loop:

#if !DONE && N == 16
UTYPE
SIZE(libat_exchange) (UTYPE *mptr, UTYPE newval, int smodel UNUSED)
{
  if (!((uintptr_t)mptr & 0xf))
    {
      /* Use the builtin only if the memory operand is 16 byte
         aligned.  */
      return __atomic_exchange_n ((UTYPE *)__builtin_assume_aligned (mptr, 16),
                                  newval, __ATOMIC_SEQ_CST);
    }
  else
    {
      UTYPE oldval;
      UWORD magic;

      pre_seq_barrier (smodel);
      magic = protect_start (mptr);

      oldval = *mptr;
      *mptr = newval;

      protect_end (mptr, magic);
      post_seq_barrier (smodel);

      return oldval;
    }
}
#define DONE 1
#endif /* N == 16 */

The then-case is, after r16-4081, compiled into an endless recursion, i.e.,

      return __atomic_exchange_n ((UTYPE *)__builtin_assume_aligned (mptr, 16),
                                  newval, __ATOMIC_SEQ_CST);

is turned into a call of __atomic_exchange_16 whereas previously it was
expanded via atomic_exchangeti.  The latter is no more the case since the
alignment information is lost and we fail in the expander:

  if (<MODE>mode != QImode
      && MEM_ALIGN (operands[1]) < GET_MODE_BITSIZE (<MODE>mode))
    FAIL;

The loss of the alignment must have happened prior expand_builtin where we have

(gdb) call get_pointer_alignment (TREE_OPERAND (exp, 3))
$1 = 8

after r16-4081 and

(gdb) call get_pointer_alignment (TREE_OPERAND (exp, 3))
$1 = 128

prior r16-4081.

Reply via email to