GCN: Implement __atomic_compare_exchange_{1,2} in libgcc [PR102215]
authorTobias Burnus <tobias@codesourcery.com>
Wed, 9 Mar 2022 18:34:48 +0000 (19:34 +0100)
committerTobias Burnus <tobias@codesourcery.com>
Wed, 9 Mar 2022 18:34:48 +0000 (19:34 +0100)
libgcc/ChangeLog:

PR target/102215
* config/gcn/atomic.c (__sync_val_compare_and_swap_##SIZE): Move
a line up to non-arg-dependent value first.
(__ATOMIC_COMPARE_EXCHANGE): Define + call to generate
__atomic_compare_exchange_{1,2}.

libgcc/config/gcn/atomic.c

index 8784f90..cf29fa8 100644 (file)
@@ -28,9 +28,9 @@
 TYPE                                                                        \
 __sync_val_compare_and_swap_##SIZE (TYPE *ptr, TYPE oldval, TYPE newval)     \
 {                                                                           \
+  unsigned int valmask = (1 << (SIZE * 8)) - 1;                                     \
   unsigned int *wordptr = (unsigned int *)((__UINTPTR_TYPE__ ) ptr & ~3UL);  \
   int shift = ((__UINTPTR_TYPE__ ) ptr & 3UL) * 8;                          \
-  unsigned int valmask = (1 << (SIZE * 8)) - 1;                                     \
   unsigned int wordmask = ~(valmask << shift);                              \
   unsigned int oldword = *wordptr;                                          \
   for (;;)                                                                  \
@@ -57,3 +57,30 @@ __sync_bool_compare_and_swap_##SIZE (TYPE *ptr, TYPE oldval, TYPE newval)    \
 __SYNC_SUBWORD_COMPARE_AND_SWAP (unsigned char, 1)
 __SYNC_SUBWORD_COMPARE_AND_SWAP (unsigned short, 2)
 
+
+#define __ATOMIC_COMPARE_EXCHANGE(TYPE,SIZE)                                 \
+bool                                                                         \
+__atomic_compare_exchange_##SIZE (TYPE *ptr, TYPE *expected,                 \
+                                 TYPE desired, bool weak,                    \
+                                 int success_memorder, int failure_memorder) \
+{                                                                            \
+  unsigned int valmask = (1 << (SIZE * 8)) - 1;                                      \
+                                                                             \
+  unsigned int *wordptr = (unsigned int *)((__UINTPTR_TYPE__ ) ptr & ~3UL);   \
+  int ptrshift = ((__UINTPTR_TYPE__ ) ptr & 3UL) * 8;                        \
+  unsigned int wordmask = ~(valmask << ptrshift);                            \
+                                                                             \
+  unsigned int ptrword = *wordptr;                                           \
+  unsigned int exptword = ptrword & wordmask;                                \
+  unsigned int newword = ptrword & wordmask;                                 \
+  exptword |= ((unsigned int) *expected) << ptrshift;                        \
+  newword |= ((unsigned int) desired) << ptrshift;                           \
+  if (__atomic_compare_exchange_4 (wordptr, &exptword, newword, weak,        \
+                                  success_memorder, failure_memorder))       \
+    return true;                                                             \
+  *expected = (TYPE) ((exptword >> ptrshift) & valmask);                     \
+  return false;                                                                      \
+}
+
+__ATOMIC_COMPARE_EXCHANGE (unsigned char, 1)
+__ATOMIC_COMPARE_EXCHANGE (unsigned short, 2)