LoongArch: atomic_load and atomic_store are implemented using dbar grading.
commit26ab97e0da5d99c23654d90428d26e22ef976309
authorLulu Cheng <chenglulu@loongson.cn>
Fri, 17 Nov 2023 08:04:45 +0000 (17 16:04 +0800)
committerLulu Cheng <chenglulu@loongson.cn>
Sat, 18 Nov 2023 08:14:48 +0000 (18 16:14 +0800)
tree145761ae588e291974078cf423be782d738d8b4b
parent1b12e7a07fe45570a0f846a7ad19a272062a6691
LoongArch: atomic_load and atomic_store are implemented using dbar grading.

Because the la464 memory model design allows the same address load out of order,
so in the following test example, the Load of 23 lines may be executed first over
the load of 21 lines, resulting in an error.
So when memmodel is MEMMODEL_RELAXED, the load instruction will be followed by
"dbar 0x700" when implementing _atomic_load.

  1 void *
  2 gomp_ptrlock_get_slow (gomp_ptrlock_t *ptrlock)
  3 {
  4   int *intptr;
  5   uintptr_t oldval = 1;
  6
  7   __atomic_compare_exchange_n (ptrlock, &oldval, 2, false,
  8                                MEMMODEL_RELAXED, MEMMODEL_RELAXED);
  9
 10   /* futex works on ints, not pointers.
 11      But a valid work share pointer will be at least
 12      8 byte aligned, so it is safe to assume the low
 13      32-bits of the pointer won't contain values 1 or 2.  */
 14   __asm volatile ("" : "=r" (intptr) : "0" (ptrlock));
 15 #if __BYTE_ORDER == __BIG_ENDIAN
 16   if (sizeof (*ptrlock) > sizeof (int))
 17     intptr += (sizeof (*ptrlock) / sizeof (int)) - 1;
 18 #endif
 19   do
 20     do_wait (intptr, 2);
 21   while (__atomic_load_n (intptr, MEMMODEL_RELAXED) == 2);
 22   __asm volatile ("" : : : "memory");
 23   return (void *) __atomic_load_n (ptrlock, MEMMODEL_ACQUIRE);
 24 }

gcc/ChangeLog:

* config/loongarch/sync.md (atomic_load<mode>): New template.
gcc/config/loongarch/sync.md