[Openmp-commits] [openmp] 621d7a7 - [OpenMP] libomp: add atomic functions for new OpenMP 5.1 atomics.

via Openmp-commits openmp-commits at lists.llvm.org
Wed Oct 13 11:02:28 PDT 2021


Author: AndreyChurbanov
Date: 2021-10-13T21:02:18+03:00
New Revision: 621d7a75b16dd2e00fe4acc6c1e2c33d91114d96

URL: https://github.com/llvm/llvm-project/commit/621d7a75b16dd2e00fe4acc6c1e2c33d91114d96
DIFF: https://github.com/llvm/llvm-project/commit/621d7a75b16dd2e00fe4acc6c1e2c33d91114d96.diff

LOG: [OpenMP] libomp: add atomic functions for new OpenMP 5.1 atomics.

Added functions those implement "atomic compare".
Though clang does not use library interfaces to implement OpenMP atomics,
the functions added for consistency.
Also added missed functions for 80-bit floating min/max atomics.

Differential Revision: https://reviews.llvm.org/D110109

Added: 
    openmp/runtime/test/atomic/kmp_atomic_cas.c
    openmp/runtime/test/atomic/kmp_atomic_cas_cpt.c
    openmp/runtime/test/atomic/kmp_atomic_float10_max_min.c

Modified: 
    openmp/runtime/src/dllexports
    openmp/runtime/src/kmp_atomic.cpp
    openmp/runtime/src/kmp_atomic.h

Removed: 
    


################################################################################
diff  --git a/openmp/runtime/src/dllexports b/openmp/runtime/src/dllexports
index c806c80ea6c96..6c0e86e3aab22 100644
--- a/openmp/runtime/src/dllexports
+++ b/openmp/runtime/src/dllexports
@@ -1221,6 +1221,29 @@ kmp_set_disp_num_buffers                    890
     __kmpc_atomic_fixed8u_mul_fp
     %endif
 
+    # OpenMP 5.1 atomics
+    __kmpc_atomic_float10_max              2139
+    __kmpc_atomic_float10_min              2140
+    __kmpc_atomic_float10_max_cpt          2141
+    __kmpc_atomic_float10_min_cpt          2142
+
+    __kmpc_atomic_bool_1_cas               2143
+    __kmpc_atomic_bool_2_cas               2144
+    __kmpc_atomic_bool_4_cas               2145
+    __kmpc_atomic_bool_8_cas               2146
+    __kmpc_atomic_val_1_cas                2147
+    __kmpc_atomic_val_2_cas                2148
+    __kmpc_atomic_val_4_cas                2149
+    __kmpc_atomic_val_8_cas                2150
+    __kmpc_atomic_bool_1_cas_cpt           2151
+    __kmpc_atomic_bool_2_cas_cpt           2152
+    __kmpc_atomic_bool_4_cas_cpt           2153
+    __kmpc_atomic_bool_8_cas_cpt           2154
+    __kmpc_atomic_val_1_cas_cpt            2155
+    __kmpc_atomic_val_2_cas_cpt            2156
+    __kmpc_atomic_val_4_cas_cpt            2157
+    __kmpc_atomic_val_8_cas_cpt            2158
+
 %endif
 
 # end of file #

diff  --git a/openmp/runtime/src/kmp_atomic.cpp b/openmp/runtime/src/kmp_atomic.cpp
index fdcfc6ef540fe..701f157172f33 100644
--- a/openmp/runtime/src/kmp_atomic.cpp
+++ b/openmp/runtime/src/kmp_atomic.cpp
@@ -1235,6 +1235,10 @@ MIN_MAX_COMPXCHG(float8, max, kmp_real64, 64, <, 8r, 7,
                  KMP_ARCH_X86) // __kmpc_atomic_float8_max
 MIN_MAX_COMPXCHG(float8, min, kmp_real64, 64, >, 8r, 7,
                  KMP_ARCH_X86) // __kmpc_atomic_float8_min
+MIN_MAX_CRITICAL(float10, max, long double, <, 10r,
+                 1) // __kmpc_atomic_float10_max
+MIN_MAX_CRITICAL(float10, min, long double, >, 10r,
+                 1) // __kmpc_atomic_float10_min
 #if KMP_HAVE_QUAD
 MIN_MAX_CRITICAL(float16, max, QUAD_LEGACY, <, 16r,
                  1) // __kmpc_atomic_float16_max
@@ -2717,6 +2721,10 @@ MIN_MAX_COMPXCHG_CPT(float8, max_cpt, kmp_real64, 64, <,
                      KMP_ARCH_X86) // __kmpc_atomic_float8_max_cpt
 MIN_MAX_COMPXCHG_CPT(float8, min_cpt, kmp_real64, 64, >,
                      KMP_ARCH_X86) // __kmpc_atomic_float8_min_cpt
+MIN_MAX_CRITICAL_CPT(float10, max_cpt, long double, <, 10r,
+                     1) // __kmpc_atomic_float10_max_cpt
+MIN_MAX_CRITICAL_CPT(float10, min_cpt, long double, >, 10r,
+                     1) // __kmpc_atomic_float10_min_cpt
 #if KMP_HAVE_QUAD
 MIN_MAX_CRITICAL_CPT(float16, max_cpt, QUAD_LEGACY, <, 16r,
                      1) // __kmpc_atomic_float16_max_cpt
@@ -3686,6 +3694,168 @@ void __kmpc_atomic_end(void) {
   __kmp_release_atomic_lock(&__kmp_atomic_lock, gtid);
 }
 
+// OpenMP 5.1 compare and swap
+
+/*!
+ at param loc Source code location
+ at param gtid Global thread id
+ at param x Memory location to operate on
+ at param e Expected value
+ at param d Desired value
+ at return Result of comparison
+
+Implements Compare And Swap atomic operation.
+
+Sample code:
+#pragma omp atomic compare update capture
+  { r = x == e; if(r) { x = d; } }
+*/
+bool __kmpc_atomic_bool_1_cas(ident_t *loc, int gtid, char *x, char e, char d) {
+  return KMP_COMPARE_AND_STORE_ACQ8(x, e, d);
+}
+bool __kmpc_atomic_bool_2_cas(ident_t *loc, int gtid, short *x, short e,
+                              short d) {
+  return KMP_COMPARE_AND_STORE_ACQ16(x, e, d);
+}
+bool __kmpc_atomic_bool_4_cas(ident_t *loc, int gtid, kmp_int32 *x, kmp_int32 e,
+                              kmp_int32 d) {
+  return KMP_COMPARE_AND_STORE_ACQ32(x, e, d);
+}
+bool __kmpc_atomic_bool_8_cas(ident_t *loc, int gtid, kmp_int64 *x, kmp_int64 e,
+                              kmp_int64 d) {
+  return KMP_COMPARE_AND_STORE_ACQ64(x, e, d);
+}
+
+/*!
+ at param loc Source code location
+ at param gtid Global thread id
+ at param x Memory location to operate on
+ at param e Expected value
+ at param d Desired value
+ at return Old value of x
+
+Implements Compare And Swap atomic operation.
+
+Sample code:
+#pragma omp atomic compare update capture
+  { v = x; if (x == e) { x = d; } }
+*/
+char __kmpc_atomic_val_1_cas(ident_t *loc, int gtid, char *x, char e, char d) {
+  return KMP_COMPARE_AND_STORE_RET8(x, e, d);
+}
+short __kmpc_atomic_val_2_cas(ident_t *loc, int gtid, short *x, short e,
+                              short d) {
+  return KMP_COMPARE_AND_STORE_RET16(x, e, d);
+}
+kmp_int32 __kmpc_atomic_val_4_cas(ident_t *loc, int gtid, kmp_int32 *x,
+                                  kmp_int32 e, kmp_int32 d) {
+  return KMP_COMPARE_AND_STORE_RET32(x, e, d);
+}
+kmp_int64 __kmpc_atomic_val_8_cas(ident_t *loc, int gtid, kmp_int64 *x,
+                                  kmp_int64 e, kmp_int64 d) {
+  return KMP_COMPARE_AND_STORE_RET64(x, e, d);
+}
+
+/*!
+ at param loc Source code location
+ at param gtid Global thread id
+ at param x Memory location to operate on
+ at param e Expected value
+ at param d Desired value
+ at param pv Captured value location
+ at return Result of comparison
+
+Implements Compare And Swap + Capture atomic operation.
+
+v gets old valie of x if comparison failed, untouched otherwise.
+Sample code:
+#pragma omp atomic compare update capture
+  { r = x == e; if(r) { x = d; } else { v = x; } }
+*/
+bool __kmpc_atomic_bool_1_cas_cpt(ident_t *loc, int gtid, char *x, char e,
+                                  char d, char *pv) {
+  char old = KMP_COMPARE_AND_STORE_RET8(x, e, d);
+  if (old == e)
+    return true;
+  KMP_ASSERT(pv != NULL);
+  *pv = old;
+  return false;
+}
+bool __kmpc_atomic_bool_2_cas_cpt(ident_t *loc, int gtid, short *x, short e,
+                                  short d, short *pv) {
+  short old = KMP_COMPARE_AND_STORE_RET16(x, e, d);
+  if (old == e)
+    return true;
+  KMP_ASSERT(pv != NULL);
+  *pv = old;
+  return false;
+}
+bool __kmpc_atomic_bool_4_cas_cpt(ident_t *loc, int gtid, kmp_int32 *x,
+                                  kmp_int32 e, kmp_int32 d, kmp_int32 *pv) {
+  kmp_int32 old = KMP_COMPARE_AND_STORE_RET32(x, e, d);
+  if (old == e)
+    return true;
+  KMP_ASSERT(pv != NULL);
+  *pv = old;
+  return false;
+}
+bool __kmpc_atomic_bool_8_cas_cpt(ident_t *loc, int gtid, kmp_int64 *x,
+                                  kmp_int64 e, kmp_int64 d, kmp_int64 *pv) {
+  kmp_int64 old = KMP_COMPARE_AND_STORE_RET64(x, e, d);
+  if (old == e)
+    return true;
+  KMP_ASSERT(pv != NULL);
+  *pv = old;
+  return false;
+}
+
+/*!
+ at param loc Source code location
+ at param gtid Global thread id
+ at param x Memory location to operate on
+ at param e Expected value
+ at param d Desired value
+ at param pv Captured value location
+ at return Old value of x
+
+Implements Compare And Swap + Capture atomic operation.
+
+v gets new valie of x.
+Sample code:
+#pragma omp atomic compare update capture
+  { if (x == e) { x = d; }; v = x; }
+*/
+char __kmpc_atomic_val_1_cas_cpt(ident_t *loc, int gtid, char *x, char e,
+                                 char d, char *pv) {
+  char old = KMP_COMPARE_AND_STORE_RET8(x, e, d);
+  KMP_ASSERT(pv != NULL);
+  *pv = old == e ? d : old;
+  return old;
+}
+short __kmpc_atomic_val_2_cas_cpt(ident_t *loc, int gtid, short *x, short e,
+                                  short d, short *pv) {
+  short old = KMP_COMPARE_AND_STORE_RET16(x, e, d);
+  KMP_ASSERT(pv != NULL);
+  *pv = old == e ? d : old;
+  return old;
+}
+kmp_int32 __kmpc_atomic_val_4_cas_cpt(ident_t *loc, int gtid, kmp_int32 *x,
+                                      kmp_int32 e, kmp_int32 d, kmp_int32 *pv) {
+  kmp_int32 old = KMP_COMPARE_AND_STORE_RET32(x, e, d);
+  KMP_ASSERT(pv != NULL);
+  *pv = old == e ? d : old;
+  return old;
+}
+kmp_int64 __kmpc_atomic_val_8_cas_cpt(ident_t *loc, int gtid, kmp_int64 *x,
+                                      kmp_int64 e, kmp_int64 d, kmp_int64 *pv) {
+  kmp_int64 old = KMP_COMPARE_AND_STORE_RET64(x, e, d);
+  KMP_ASSERT(pv != NULL);
+  *pv = old == e ? d : old;
+  return old;
+}
+
+// End OpenMP 5.1 compare + capture
+
 /*!
 @}
 */

diff  --git a/openmp/runtime/src/kmp_atomic.h b/openmp/runtime/src/kmp_atomic.h
index 6a0827aaf1ea3..079b917285b1b 100644
--- a/openmp/runtime/src/kmp_atomic.h
+++ b/openmp/runtime/src/kmp_atomic.h
@@ -578,6 +578,10 @@ void __kmpc_atomic_float8_max(ident_t *id_ref, int gtid, kmp_real64 *lhs,
                               kmp_real64 rhs);
 void __kmpc_atomic_float8_min(ident_t *id_ref, int gtid, kmp_real64 *lhs,
                               kmp_real64 rhs);
+void __kmpc_atomic_float10_max(ident_t *id_ref, int gtid, long double *lhs,
+                               long double rhs);
+void __kmpc_atomic_float10_min(ident_t *id_ref, int gtid, long double *lhs,
+                               long double rhs);
 #if KMP_HAVE_QUAD
 void __kmpc_atomic_float16_max(ident_t *id_ref, int gtid, QUAD_LEGACY *lhs,
                                QUAD_LEGACY rhs);
@@ -1254,6 +1258,12 @@ kmp_real64 __kmpc_atomic_float8_max_cpt(ident_t *id_ref, int gtid,
 kmp_real64 __kmpc_atomic_float8_min_cpt(ident_t *id_ref, int gtid,
                                         kmp_real64 *lhs, kmp_real64 rhs,
                                         int flag);
+long double __kmpc_atomic_float10_max_cpt(ident_t *id_ref, int gtid,
+                                          long double *lhs, long double rhs,
+                                          int flag);
+long double __kmpc_atomic_float10_min_cpt(ident_t *id_ref, int gtid,
+                                          long double *lhs, long double rhs,
+                                          int flag);
 #if KMP_HAVE_QUAD
 QUAD_LEGACY __kmpc_atomic_float16_max_cpt(ident_t *id_ref, int gtid,
                                           QUAD_LEGACY *lhs, QUAD_LEGACY rhs,
@@ -1756,6 +1766,78 @@ long double __kmpc_atomic_float10_div_cpt_rev_fp(ident_t *id_ref, int gtid,
 
 // End of OpenMP 4.0 capture
 
+// OpenMP 5.1 compare and swap
+/*
+    __kmpc_atomic_bool_1_cas
+    __kmpc_atomic_bool_2_cas
+    __kmpc_atomic_bool_4_cas
+    __kmpc_atomic_bool_8_cas
+    __kmpc_atomic_val_1_cas
+    __kmpc_atomic_val_2_cas
+    __kmpc_atomic_val_4_cas
+    __kmpc_atomic_val_8_cas
+    __kmpc_atomic_bool_1_cas_cpt
+    __kmpc_atomic_bool_2_cas_cpt
+    __kmpc_atomic_bool_4_cas_cpt
+    __kmpc_atomic_bool_8_cas_cpt
+    __kmpc_atomic_val_1_cas_cpt
+    __kmpc_atomic_val_2_cas_cpt
+    __kmpc_atomic_val_4_cas_cpt
+    __kmpc_atomic_val_8_cas_cpt
+*/
+// In all interfaces of CAS (Compare And Swap):
+// r is the boolean result of comparison
+// x is memory location to operate on
+// e is expected (old) value
+// d is desired (new) value
+// pv is pointer to captured value v whose location may coincide with e
+
+// { r = x == e; if(r) { x = d; } }
+// functions return result of comparison
+bool __kmpc_atomic_bool_1_cas(ident_t *loc, int gtid, char *x, char e, char d);
+bool __kmpc_atomic_bool_2_cas(ident_t *loc, int gtid, short *x, short e,
+                              short d);
+bool __kmpc_atomic_bool_4_cas(ident_t *loc, int gtid, kmp_int32 *x, kmp_int32 e,
+                              kmp_int32 d);
+bool __kmpc_atomic_bool_8_cas(ident_t *loc, int gtid, kmp_int64 *x, kmp_int64 e,
+                              kmp_int64 d);
+
+// { v = x; if (x == e) { x = d; } }
+// functions return old value
+char __kmpc_atomic_val_1_cas(ident_t *loc, int gtid, char *x, char e, char d);
+short __kmpc_atomic_val_2_cas(ident_t *loc, int gtid, short *x, short e,
+                              short d);
+kmp_int32 __kmpc_atomic_val_4_cas(ident_t *loc, int gtid, kmp_int32 *x,
+                                  kmp_int32 e, kmp_int32 d);
+kmp_int64 __kmpc_atomic_val_8_cas(ident_t *loc, int gtid, kmp_int64 *x,
+                                  kmp_int64 e, kmp_int64 d);
+
+// { r = x == e; if(r) { x = d; } else { v = x; } }
+// v gets old value if comparison failed, untouched otherwise
+// functions return result of comparison
+bool __kmpc_atomic_bool_1_cas_cpt(ident_t *loc, int gtid, char *x, char e,
+                                  char d, char *pv);
+bool __kmpc_atomic_bool_2_cas_cpt(ident_t *loc, int gtid, short *x, short e,
+                                  short d, short *pv);
+bool __kmpc_atomic_bool_4_cas_cpt(ident_t *loc, int gtid, kmp_int32 *x,
+                                  kmp_int32 e, kmp_int32 d, kmp_int32 *pv);
+bool __kmpc_atomic_bool_8_cas_cpt(ident_t *loc, int gtid, kmp_int64 *x,
+                                  kmp_int64 e, kmp_int64 d, kmp_int64 *pv);
+
+// { if (x == e) { x = d; }; v = x; }
+// v gets old value if comparison failed, new value otherwise
+// functions return old value
+char __kmpc_atomic_val_1_cas_cpt(ident_t *loc, int gtid, char *x, char e,
+                                 char d, char *pv);
+short __kmpc_atomic_val_2_cas_cpt(ident_t *loc, int gtid, short *x, short e,
+                                  short d, short *pv);
+kmp_int32 __kmpc_atomic_val_4_cas_cpt(ident_t *loc, int gtid, kmp_int32 *x,
+                                      kmp_int32 e, kmp_int32 d, kmp_int32 *pv);
+kmp_int64 __kmpc_atomic_val_8_cas_cpt(ident_t *loc, int gtid, kmp_int64 *x,
+                                      kmp_int64 e, kmp_int64 d, kmp_int64 *pv);
+
+// End OpenMP 5.1 compare + capture
+
 #endif // KMP_ARCH_X86 || KMP_ARCH_X86_64
 
 /* ------------------------------------------------------------------------ */

diff  --git a/openmp/runtime/test/atomic/kmp_atomic_cas.c b/openmp/runtime/test/atomic/kmp_atomic_cas.c
new file mode 100644
index 0000000000000..82c4745b30980
--- /dev/null
+++ b/openmp/runtime/test/atomic/kmp_atomic_cas.c
@@ -0,0 +1,180 @@
+// RUN: %libomp-compile-and-run
+
+#include <stdio.h>
+#include <stdbool.h>
+#include <omp.h>
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+typedef void* ident_t;
+extern bool
+__kmpc_atomic_bool_1_cas(ident_t *loc, int gtid, char *x, char e, char d);
+extern bool
+__kmpc_atomic_bool_2_cas(ident_t *loc, int gtid, short *x, short e, short d);
+extern bool
+__kmpc_atomic_bool_4_cas(ident_t *loc, int gtid, int *x, int e, int d);
+extern bool
+__kmpc_atomic_bool_8_cas(ident_t *loc, int gtid, long long *x, long long e,
+                         long long d);
+extern char
+__kmpc_atomic_val_1_cas(ident_t *loc, int gtid, char *x, char e, char d);
+extern short
+__kmpc_atomic_val_2_cas(ident_t *loc, int gtid, short *x, short e, short d);
+extern int
+__kmpc_atomic_val_4_cas(ident_t *loc, int gtid, int *x, int e, int d);
+extern long long
+__kmpc_atomic_val_8_cas(ident_t *loc, int gtid, long long *x, long long e,
+                        long long d);
+#ifdef  __cplusplus
+}
+#endif
+
+int main() {
+  int ret = 0;
+  bool r;
+  char c0 = 1;
+  char c1 = 2;
+  char c2 = 3;
+  char co = 2;
+  char cc = 0;
+  short s0 = 11;
+  short s1 = 12;
+  short s2 = 13;
+  short so = 12;
+  short sc = 0;
+  int i0 = 211;
+  int i1 = 212;
+  int i2 = 213;
+  int io = 212;
+  int ic = 0;
+  long long l0 = 3111;
+  long long l1 = 3112;
+  long long l2 = 3113;
+  long long lo = 3112;
+  long long lc = 0;
+
+// initialize OpenMP runtime library
+  omp_set_dynamic(0);
+
+//  #pragma omp atomic compare update capture
+//    { r = x == e; if(r) { x = d; } }
+// char, co == c1 initially, co == c2 finally
+  r = __kmpc_atomic_bool_1_cas(NULL, 0, &co, c0, c2); // no-op
+  if (co != c1) {
+    ret++; printf("Error bool_1_cas no-op: %d != %d\n", co, c1); }
+  if (r) { ret++; printf("Error bool_1_cas no-op ret: %d\n", r); }
+  r = __kmpc_atomic_bool_1_cas(NULL, 0, &co, c1, c2);
+  if (co != c2) {
+    ret++; printf("Error bool_1_cas: %d != %d\n", co, c2); }
+  if (!r) { ret++; printf("Error bool_1_cas ret: %d\n", r); }
+// short
+  r = __kmpc_atomic_bool_2_cas(NULL, 0, &so, s0, s2); // no-op
+  if (so != s1) {
+    ret++; printf("Error bool_2_cas no-op: %d != %d\n", so, s1); }
+  if (r) { ret++; printf("Error bool_2_cas no-op ret: %d\n", r); }
+  r = __kmpc_atomic_bool_2_cas(NULL, 0, &so, s1, s2);
+  if (so != s2) {
+    ret++; printf("Error bool_2_cas: %d != %d\n", so, s2); }
+  if (!r) { ret++; printf("Error bool_2_cas ret: %d\n", r); }
+// int
+  r = __kmpc_atomic_bool_4_cas(NULL, 0, &io, i0, i2); // no-op
+  if (io != i1) {
+    ret++; printf("Error bool_4_cas no-op: %d != %d\n", io, i1); }
+  if (r) { ret++; printf("Error bool_4_cas no-op ret: %d\n", r); }
+  r = __kmpc_atomic_bool_4_cas(NULL, 0, &io, i1, i2);
+  if (io != i2) {
+    ret++; printf("Error bool_4_cas: %d != %d\n", io, i2); }
+  if (!r) { ret++; printf("Error bool_4_cas ret: %d\n", r); }
+// long long
+  r = __kmpc_atomic_bool_8_cas(NULL, 0, &lo, l0, l2); // no-op
+  if (lo != l1) {
+    ret++; printf("Error bool_8_cas no-op: %lld != %lld\n", lo, l1); }
+  if (r) { ret++; printf("Error bool_8_cas no-op ret: %d\n", r); }
+  r = __kmpc_atomic_bool_8_cas(NULL, 0, &lo, l1, l2);
+  if (lo != l2) {
+    ret++; printf("Error bool_8_cas: %lld != %lld\n", lo, l2); }
+  if (!r) { ret++; printf("Error bool_8_cas ret: %d\n", r); }
+
+//  #pragma omp atomic compare update capture
+//    { v = x; if (x == e) { x = d; } }
+// char, co == c2 initially, co == c1 finally
+  cc = __kmpc_atomic_val_1_cas(NULL, 0, &co, c0, c1); // no-op
+  if (co != c2) {
+    ret++; printf("Error val_1_cas no-op: %d != %d\n", co, c2); }
+  if (cc != c2) {
+    ret++; printf("Error val_1_cas no-op ret: %d != %d\n", cc, c2); }
+  cc = __kmpc_atomic_val_1_cas(NULL, 0, &co, c2, c1);
+  if (co != c1) {
+    ret++; printf("Error val_1_cas: %d != %d\n", co, c1); }
+  if (cc != c2) { ret++; printf("Error val_1_cas ret: %d != %d\n", cc, c2); }
+// short
+  sc = __kmpc_atomic_val_2_cas(NULL, 0, &so, s0, s1); // no-op
+  if (so != s2) {
+    ret++; printf("Error val_2_cas no-op: %d != %d\n", so, s2); }
+  if (sc != s2) {
+    ret++; printf("Error val_2_cas no-op ret: %d != %d\n", sc, s2); }
+  sc = __kmpc_atomic_val_2_cas(NULL, 0, &so, s2, s1);
+  if (so != s1) {
+    ret++; printf("Error val_2_cas: %d != %d\n", so, s1); }
+  if (sc != s2) {
+    ret++; printf("Error val_2_cas ret: %d != %d\n", sc, s2); }
+// int
+  ic = __kmpc_atomic_val_4_cas(NULL, 0, &io, i0, i1); // no-op
+  if (io != i2) {
+    ret++; printf("Error val_4_cas no-op: %d != %d\n", io, i2); }
+  if (ic != i2) {
+    ret++; printf("Error val_4_cas no-op ret: %d != %d\n", ic, i2); }
+  ic = __kmpc_atomic_val_4_cas(NULL, 0, &io, i2, i1);
+  if (io != i1) {
+    ret++; printf("Error val_4_cas: %d != %d\n", io, i1); }
+  if (ic != i2) {
+    ret++; printf("Error val_4_cas ret: %d != %d\n", ic, i2); }
+// long long
+  lc = __kmpc_atomic_val_8_cas(NULL, 0, &lo, l0, l1); // no-op
+  if (lo != l2) {
+    ret++; printf("Error val_8_cas no-op: %lld != %lld\n", lo, l2); }
+  if (lc != l2) {
+    ret++; printf("Error val_8_cas no-op ret: %lld != %lld\n", lc, l2); }
+  lc = __kmpc_atomic_val_8_cas(NULL, 0, &lo, l2, l1);
+  if (lo != l1) {
+    ret++; printf("Error val_8_cas: %lld != %lld\n", lo, l1); }
+  if (lc != l2) {
+    ret++; printf("Error val_8_cas ret: %lld != %lld\n", lc, l2); }
+
+// check in parallel
+  i0 = 1;
+  i1 = 0;
+  for (io = 0; io < 5; ++io) {
+    #pragma omp parallel num_threads(2) private(i2, ic, r)
+    {
+      if (omp_get_thread_num() == 0) {
+        // th0 waits for th1 to increment i1, then th0 increments i0
+        #pragma omp atomic read
+          i2 = i1;
+        ic = __kmpc_atomic_val_4_cas(NULL, 0, &i0, i2, i2 + 1);
+        while(ic != i2) {
+          #pragma omp atomic read
+            i2 = i1;
+          ic = __kmpc_atomic_val_4_cas(NULL, 0, &i0, i2, i2 + 1);
+        }
+      } else {
+        // th1 increments i1 if it is equal to i0 - 1, letting th0 to proceed
+        r = 0;
+        while(!r) {
+          #pragma omp atomic read
+            i2 = i0;
+          r = __kmpc_atomic_bool_4_cas(NULL, 0, &i1, i2 - 1, i2);
+        }
+      }
+    }
+  }
+  if (i0 != 6 || i1 != 5) {
+    ret++;
+    printf("Error in parallel, %d != %d or %d != %d\n", i0, 6, i1, 5);
+  }
+
+  if (ret == 0)
+    printf("passed\n");
+  return ret;
+}

diff  --git a/openmp/runtime/test/atomic/kmp_atomic_cas_cpt.c b/openmp/runtime/test/atomic/kmp_atomic_cas_cpt.c
new file mode 100644
index 0000000000000..f70cfbfe2fbed
--- /dev/null
+++ b/openmp/runtime/test/atomic/kmp_atomic_cas_cpt.c
@@ -0,0 +1,219 @@
+// RUN: %libomp-compile-and-run
+
+#include <stdio.h>
+#include <stdbool.h>
+#include <omp.h>
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+typedef void* ident_t;
+extern bool
+__kmpc_atomic_bool_1_cas_cpt(ident_t *loc, int gtid, char *x, char e, char d,
+                             char *pv);
+extern bool
+__kmpc_atomic_bool_2_cas_cpt(ident_t *loc, int gtid, short *x, short e, short d,
+                             short *pv);
+extern bool
+__kmpc_atomic_bool_4_cas_cpt(ident_t *loc, int gtid, int *x, int e, int d,
+                             int *pv);
+extern bool
+__kmpc_atomic_bool_8_cas_cpt(ident_t *loc, int gtid, long long *x, long long e,
+                             long long d, long long *pv);
+extern char
+__kmpc_atomic_val_1_cas_cpt(ident_t *loc, int gtid, char *x, char e, char d,
+                            char *pv);
+extern short
+__kmpc_atomic_val_2_cas_cpt(ident_t *loc, int gtid, short *x, short e, short d,
+                            short *pv);
+extern int
+__kmpc_atomic_val_4_cas_cpt(ident_t *loc, int gtid, int *x, int e, int d,
+                            int *pv);
+extern long long
+__kmpc_atomic_val_8_cas_cpt(ident_t *loc, int gtid, long long *x, long long e,
+                            long long d, long long *pv);
+#ifdef  __cplusplus
+}
+#endif
+
+int main() {
+  int ret = 0;
+  bool r;
+  char c0 = 1;
+  char c1 = 2;
+  char c2 = 3;
+  char co = 2;
+  char cc = 0;
+  char cv = 0;
+  short s0 = 11;
+  short s1 = 12;
+  short s2 = 13;
+  short so = 12;
+  short sc = 0;
+  short sv = 0;
+  int i0 = 211;
+  int i1 = 212;
+  int i2 = 213;
+  int io = 212;
+  int ic = 0;
+  int iv = 0;
+  long long l0 = 3111;
+  long long l1 = 3112;
+  long long l2 = 3113;
+  long long lo = 3112;
+  long long lc = 0;
+  long long lv = 0;
+
+// initialize OpenMP runtime library
+  omp_set_dynamic(0);
+
+//  #pragma omp atomic compare update capture
+//    { r = x == e; if(r) { x = d; } else { v = x; } }
+// char, co == c1 initially, co == c2 finally
+  r = __kmpc_atomic_bool_1_cas_cpt(NULL, 0, &co, c0, c2, &cv); // no-op
+  if (co != c1) {
+    ret++; printf("Error bool_1_cas_cpt no-op: %d != %d\n", co, c1); }
+  if (cv != co) {
+    ret++; printf("Error bool_1_cas_cpt no-op cpt: %d != %d\n", cv, co); }
+  if (r) { ret++; printf("Error bool_1_cas_cpt no-op ret: %d\n", r); }
+  cv = 0;
+  r = __kmpc_atomic_bool_1_cas_cpt(NULL, 0, &co, c1, c2, &cv);
+  if (co != c2) { ret++; printf("Error bool_1_cas_cpt: %d != %d\n", co, c2); }
+  if (cv != 0) { ret++; printf("Error bool_1_cas_cpt cpt: %d != %d\n", cv, 0); }
+  if (!r) { ret++; printf("Error bool_1_cas_cpt ret: %d\n", r); }
+// short
+  r = __kmpc_atomic_bool_2_cas_cpt(NULL, 0, &so, s0, s2, &sv); // no-op
+  if (so != s1) {
+    ret++; printf("Error bool_2_cas_cpt no-op: %d != %d\n", so, s1); }
+  if (sv != so) {
+    ret++; printf("Error bool_2_cas_cpt no-op cpt: %d != %d\n", sv, so); }
+  if (r) { ret++; printf("Error bool_2_cas_cpt no-op ret: %d\n", r); }
+  sv = 0;
+  r = __kmpc_atomic_bool_2_cas_cpt(NULL, 0, &so, s1, s2, &sv);
+  if (so != s2) { ret++; printf("Error bool_2_cas_cpt: %d != %d\n", so, s2); }
+  if (sv != 0) { ret++; printf("Error bool_2_cas_cpt cpt: %d != %d\n", sv, 0); }
+  if (!r) { ret++; printf("Error bool_2_cas_cpt ret: %d\n", r); }
+// int
+  r = __kmpc_atomic_bool_4_cas_cpt(NULL, 0, &io, i0, i2, &iv); // no-op
+  if (io != i1) {
+    ret++; printf("Error bool_4_cas_cpt no-op: %d != %d\n", io, i1); }
+  if (iv != io) {
+    ret++; printf("Error bool_4_cas_cpt no-op cpt: %d != %d\n", iv, io); }
+  if (r) { ret++; printf("Error bool_4_cas_cpt no-op ret: %d\n", r); }
+  iv = 0;
+  r = __kmpc_atomic_bool_4_cas_cpt(NULL, 0, &io, i1, i2, &iv);
+  if (io != i2) { ret++; printf("Error bool_4_cas_cpt: %d != %d\n", io, i2); }
+  if (iv != 0) { ret++; printf("Error bool_4_cas_cpt cpt: %d != %d\n", iv, 0); }
+  if (!r) { ret++; printf("Error bool_4_cas_cpt ret: %d\n", r); }
+// long long
+  r = __kmpc_atomic_bool_8_cas_cpt(NULL, 0, &lo, l0, l2, &lv); // no-op
+  if (lo != l1) {
+    ret++; printf("Error bool_8_cas_cpt no-op: %lld != %lld\n", lo, l1); }
+  if (lv != lo) {
+    ret++; printf("Error bool_8_cas_cpt no-op cpt: %lld != %lld\n", lv, lo); }
+  if (r) { ret++; printf("Error bool_8_cas_cpt no-op ret: %d\n", r); }
+  lv = 0;
+  r = __kmpc_atomic_bool_8_cas_cpt(NULL, 0, &lo, l1, l2, &lv);
+  if (lo != l2) {
+    ret++; printf("Error bool_8_cas_cpt: %lld != %lld\n", lo, l2); }
+  if (lv != 0) { // should not be assigned
+    ret++; printf("Error bool_8_cas_cpt cpt: %lld != %d\n", lv, 0); }
+  if (!r) { ret++; printf("Error bool_8_cas_cpt ret: %d\n", r); }
+
+//  #pragma omp atomic compare update capture
+//    { if (x == e) { x = d; }; v = x; }
+// char, co == c2 initially, co == c1 finally
+  cc = __kmpc_atomic_val_1_cas_cpt(NULL, 0, &co, c0, c1, &cv); // no-op
+  if (co != c2) {
+    ret++; printf("Error val_1_cas_cpt no-op: %d != %d\n", co, c2); }
+  if (cv != c2) {
+    ret++; printf("Error val_1_cas_cpt no-op cpt: %d != %d\n", cv, c2); }
+  if (cc != c2) {
+    ret++; printf("Error val_1_cas_cpt no-op ret: %d != %d\n", cc, c2); }
+  cc = __kmpc_atomic_val_1_cas_cpt(NULL, 0, &co, c2, c1, &cv);
+  if (co != c1) { ret++; printf("Error val_1_cas_cpt: %d != %d\n", co, c1); }
+  if (cv != c1) { ret++; printf("Error val_1_cas_cpt cpt: %d != %d\n", cv, c1); }
+  if (cc != c2) { ret++; printf("Error val_1_cas_cpt ret: %d != %d\n", cc, c2); }
+// short
+  sc = __kmpc_atomic_val_2_cas_cpt(NULL, 0, &so, s0, s1, &sv); // no-op
+  if (so != s2) {
+    ret++; printf("Error val_2_cas_cpt no-op: %d != %d\n", so, s2); }
+  if (sv != s2) {
+    ret++; printf("Error val_2_cas_cpt no-op cpt: %d != %d\n", sv, s2); }
+  if (sc != s2) {
+    ret++; printf("Error val_2_cas_cpt no-op ret: %d != %d\n", sc, s2); }
+  sc = __kmpc_atomic_val_2_cas_cpt(NULL, 0, &so, s2, s1, &sv);
+  if (so != s1) { ret++; printf("Error val_2_cas_cpt: %d != %d\n", so, s1); }
+  if (sv != s1) { ret++; printf("Error val_2_cas_cpt cpt: %d != %d\n", sv, s1); }
+  if (sc != s2) { ret++; printf("Error val_2_cas_cpt ret: %d != %d\n", sc, s2); }
+// int
+  ic = __kmpc_atomic_val_4_cas_cpt(NULL, 0, &io, i0, i1, &iv); // no-op
+  if (io != i2) {
+    ret++; printf("Error val_4_cas_cpt no-op: %d != %d\n", io, i2); }
+  if (iv != i2) {
+    ret++; printf("Error val_4_cas_cpt no-op cpt: %d != %d\n", iv, i2); }
+  if (ic != i2) {
+    ret++; printf("Error val_4_cas_cpt no-op ret: %d != %d\n", ic, i2); }
+  ic = __kmpc_atomic_val_4_cas_cpt(NULL, 0, &io, i2, i1, &iv);
+  if (io != i1) { ret++; printf("Error val_4_cas_cpt: %d != %d\n", io, i1); }
+  if (iv != i1) { ret++; printf("Error val_4_cas_cpt cpt: %d != %d\n", io, i1); }
+  if (ic != i2) { ret++; printf("Error val_4_cas_cpt ret: %d != %d\n", ic, i2); }
+// long long
+  lc = __kmpc_atomic_val_8_cas_cpt(NULL, 0, &lo, l0, l1, &lv); // no-op
+  if (lo != l2) {
+    ret++; printf("Error val_8_cas_cpt no-op: %lld != %lld\n", lo, l2); }
+  if (lv != l2) {
+    ret++; printf("Error val_8_cas_cpt no-op cpt: %lld != %lld\n", lv, l2); }
+  if (lc != l2) {
+    ret++; printf("Error val_8_cas_cpt no-op ret: %lld != %lld\n", lc, l2); }
+  lc = __kmpc_atomic_val_8_cas_cpt(NULL, 0, &lo, l2, l1, &lv);
+  if (lo != l1) { ret++; printf("Error val_8_cas_cpt: %lld != %lld\n", lo, l1); }
+  if (lv != l1) {
+    ret++; printf("Error val_8_cas_cpt cpt: %lld != %lld\n", lv, l1); }
+  if (lc != l2) {
+    ret++; printf("Error val_8_cas_cpt ret: %lld != %lld\n", lc, l2); }
+
+// check in parallel
+  i0 = 1;
+  i1 = 0;
+  for (io = 0; io < 5; ++io) {
+    #pragma omp parallel num_threads(2) private(i2, ic, r, iv)
+    {
+      if (omp_get_thread_num() == 0) {
+        // th0 waits for th1 to increment i1, then th0 increments i0
+        #pragma omp atomic read
+          i2 = i1;
+        ic = __kmpc_atomic_val_4_cas_cpt(NULL, 0, &i0, i2, i2 + 1, &iv);
+        while(ic != i2) {
+          if (iv != ic) {
+            ret++;
+            printf("Error 1 in parallel cpt, %d != %d\n", iv, ic);
+          }
+          #pragma omp atomic read
+            i2 = i1;
+          ic = __kmpc_atomic_val_4_cas_cpt(NULL, 0, &i0, i2, i2 + 1, &iv);
+        }
+        if (iv != i2 + 1) {
+          ret++;
+          printf("Error 2 in parallel cpt, %d != %d\n", iv, i2 + 1);
+        }
+      } else {
+        // th1 increments i1 if it is equal to i0 - 1, letting th0 to proceed
+        r = 0;
+        while(!r) {
+          #pragma omp atomic read
+            i2 = i0;
+          r = __kmpc_atomic_bool_4_cas_cpt(NULL, 0, &i1, i2 - 1, i2, &iv);
+        }
+      }
+    }
+  }
+  if (i0 != 6 || i1 != 5) {
+    ret++;
+    printf("Error in parallel, %d != %d or %d != %d\n", i0, 6, i1, 5);
+  }
+
+  if (ret == 0)
+    printf("passed\n");
+  return ret;
+}

diff  --git a/openmp/runtime/test/atomic/kmp_atomic_float10_max_min.c b/openmp/runtime/test/atomic/kmp_atomic_float10_max_min.c
new file mode 100644
index 0000000000000..6401dacb37d49
--- /dev/null
+++ b/openmp/runtime/test/atomic/kmp_atomic_float10_max_min.c
@@ -0,0 +1,155 @@
+// RUN: %libomp-compile -mlong-double-80 && %libomp-run
+// UNSUPPORTED: gcc
+
+#include <stdio.h>
+#include <omp.h>
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+typedef void* ident_t;
+extern void __kmpc_atomic_float10_max(ident_t *id_ref, int gtid,
+                                      long double *lhs, long double rhs);
+extern void __kmpc_atomic_float10_min(ident_t *id_ref, int gtid,
+                                      long double *lhs, long double rhs);
+extern long double __kmpc_atomic_float10_max_cpt(ident_t *id_ref, int gtid,
+                                                 long double *lhs,
+                                                 long double rhs, int flag);
+extern long double __kmpc_atomic_float10_min_cpt(ident_t *id_ref, int gtid,
+                                                 long double *lhs,
+                                                 long double rhs, int flag);
+#ifdef  __cplusplus
+}
+#endif
+
+int main() {
+  int ret = 0;
+  long double s = 012.3456; // small
+  long double e = 123.4567; // middle
+  long double d = 234.5678; // big
+  long double x = 123.4567; // object
+  long double v = 0.; // captured value
+
+// initialize OpenMP runtime library
+  omp_set_num_threads(4);
+
+// max
+//  #pragma omp atomic compare update
+//    if (x < d) x = d;
+  __kmpc_atomic_float10_max(NULL, 0, &x, d);
+  if (x != d) {
+    ret++;
+    printf("Error max: %Lf != %Lf\n", x, d);
+  }
+  __kmpc_atomic_float10_max(NULL, 0, &x, s); // no-op
+  if (x != d) {
+    ret++;
+    printf("Error max: %Lf != %Lf\n", x, d);
+  }
+
+// min
+//  #pragma omp atomic compare update
+//    if (x > s) x = s;
+  __kmpc_atomic_float10_min(NULL, 0, &x, s);
+  if (x != s) {
+    ret++;
+    printf("Error min: %Lf != %Lf\n", x, s);
+  }
+  __kmpc_atomic_float10_min(NULL, 0, &x, e); // no-op
+  if (x != s) {
+    ret++;
+    printf("Error min: %Lf != %Lf\n", x, s);
+  }
+
+// max_cpt old
+//  #pragma omp atomic compare update capture
+//    { v = x; if (x < d) x = d; }
+  v = __kmpc_atomic_float10_max_cpt(NULL, 0, &x, d, 0);
+  if (x != d) {
+    ret++;
+    printf("Error max_cpt obj: %Lf != %Lf\n", x, d);
+  }
+  if (v != s) {
+    ret++;
+    printf("Error max_cpt cpt: %Lf != %Lf\n", v, s);
+  }
+  v = __kmpc_atomic_float10_max_cpt(NULL, 0, &x, e, 0); // no-op
+  if (x != d) {
+    ret++;
+    printf("Error max_cpt obj: %Lf != %Lf\n", x, d);
+  }
+  if (v != d) {
+    ret++;
+    printf("Error max_cpt cpt: %Lf != %Lf\n", v, d);
+  }
+
+// min_cpt old
+//  #pragma omp atomic compare update capture
+//    { v = x; if (x > d) x = d; }
+  v = __kmpc_atomic_float10_min_cpt(NULL, 0, &x, s, 0);
+  if (x != s) {
+    ret++;
+    printf("Error min_cpt obj: %Lf != %Lf\n", x, s);
+  }
+  if (v != d) {
+    ret++;
+    printf("Error min_cpt cpt: %Lf != %Lf\n", v, d);
+  }
+  v = __kmpc_atomic_float10_min_cpt(NULL, 0, &x, e, 0); // no-op
+  if (x != s) {
+    ret++;
+    printf("Error max_cpt obj: %Lf != %Lf\n", x, s);
+  }
+  if (v != s) {
+    ret++;
+    printf("Error max_cpt cpt: %Lf != %Lf\n", v, s);
+  }
+
+// max_cpt new
+//  #pragma omp atomic compare update capture
+//    { if (x < d) x = d; v = x; }
+  v = __kmpc_atomic_float10_max_cpt(NULL, 0, &x, d, 1);
+  if (x != d) {
+    ret++;
+    printf("Error max_cpt obj: %Lf != %Lf\n", x, d);
+  }
+  if (v != d) {
+    ret++;
+    printf("Error max_cpt cpt: %Lf != %Lf\n", v, d);
+  }
+  v = __kmpc_atomic_float10_max_cpt(NULL, 0, &x, e, 1); // no-op
+  if (x != d) {
+    ret++;
+    printf("Error max_cpt obj: %Lf != %Lf\n", x, d);
+  }
+  if (v != d) {
+    ret++;
+    printf("Error max_cpt cpt: %Lf != %Lf\n", v, d);
+  }
+
+// min_cpt new
+//  #pragma omp atomic compare update capture
+//    { if (x > d) x = d; v = x; }
+  v = __kmpc_atomic_float10_min_cpt(NULL, 0, &x, s, 1);
+  if (x != s) {
+    ret++;
+    printf("Error min_cpt obj: %Lf != %Lf\n", x, s);
+  }
+  if (v != s) {
+    ret++;
+    printf("Error min_cpt cpt: %Lf != %Lf\n", v, s);
+  }
+  v = __kmpc_atomic_float10_min_cpt(NULL, 0, &x, e, 1); // no-op
+  if (x != s) {
+    ret++;
+    printf("Error max_cpt obj: %Lf != %Lf\n", x, s);
+  }
+  if (v != s) {
+    ret++;
+    printf("Error max_cpt cpt: %Lf != %Lf\n", v, s);
+  }
+
+  if (ret == 0)
+    printf("passed\n");
+  return ret;
+}


        


More information about the Openmp-commits mailing list