Skip to content

Commit 621d7a7

Browse files
[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
1 parent 2de43d4 commit 621d7a7

File tree

6 files changed

+829
-0
lines changed

6 files changed

+829
-0
lines changed

openmp/runtime/src/dllexports

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1221,6 +1221,29 @@ kmp_set_disp_num_buffers 890
12211221
__kmpc_atomic_fixed8u_mul_fp
12221222
%endif
12231223

1224+
# OpenMP 5.1 atomics
1225+
__kmpc_atomic_float10_max 2139
1226+
__kmpc_atomic_float10_min 2140
1227+
__kmpc_atomic_float10_max_cpt 2141
1228+
__kmpc_atomic_float10_min_cpt 2142
1229+
1230+
__kmpc_atomic_bool_1_cas 2143
1231+
__kmpc_atomic_bool_2_cas 2144
1232+
__kmpc_atomic_bool_4_cas 2145
1233+
__kmpc_atomic_bool_8_cas 2146
1234+
__kmpc_atomic_val_1_cas 2147
1235+
__kmpc_atomic_val_2_cas 2148
1236+
__kmpc_atomic_val_4_cas 2149
1237+
__kmpc_atomic_val_8_cas 2150
1238+
__kmpc_atomic_bool_1_cas_cpt 2151
1239+
__kmpc_atomic_bool_2_cas_cpt 2152
1240+
__kmpc_atomic_bool_4_cas_cpt 2153
1241+
__kmpc_atomic_bool_8_cas_cpt 2154
1242+
__kmpc_atomic_val_1_cas_cpt 2155
1243+
__kmpc_atomic_val_2_cas_cpt 2156
1244+
__kmpc_atomic_val_4_cas_cpt 2157
1245+
__kmpc_atomic_val_8_cas_cpt 2158
1246+
12241247
%endif
12251248

12261249
# end of file #

openmp/runtime/src/kmp_atomic.cpp

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1235,6 +1235,10 @@ MIN_MAX_COMPXCHG(float8, max, kmp_real64, 64, <, 8r, 7,
12351235
KMP_ARCH_X86) // __kmpc_atomic_float8_max
12361236
MIN_MAX_COMPXCHG(float8, min, kmp_real64, 64, >, 8r, 7,
12371237
KMP_ARCH_X86) // __kmpc_atomic_float8_min
1238+
MIN_MAX_CRITICAL(float10, max, long double, <, 10r,
1239+
1) // __kmpc_atomic_float10_max
1240+
MIN_MAX_CRITICAL(float10, min, long double, >, 10r,
1241+
1) // __kmpc_atomic_float10_min
12381242
#if KMP_HAVE_QUAD
12391243
MIN_MAX_CRITICAL(float16, max, QUAD_LEGACY, <, 16r,
12401244
1) // __kmpc_atomic_float16_max
@@ -2717,6 +2721,10 @@ MIN_MAX_COMPXCHG_CPT(float8, max_cpt, kmp_real64, 64, <,
27172721
KMP_ARCH_X86) // __kmpc_atomic_float8_max_cpt
27182722
MIN_MAX_COMPXCHG_CPT(float8, min_cpt, kmp_real64, 64, >,
27192723
KMP_ARCH_X86) // __kmpc_atomic_float8_min_cpt
2724+
MIN_MAX_CRITICAL_CPT(float10, max_cpt, long double, <, 10r,
2725+
1) // __kmpc_atomic_float10_max_cpt
2726+
MIN_MAX_CRITICAL_CPT(float10, min_cpt, long double, >, 10r,
2727+
1) // __kmpc_atomic_float10_min_cpt
27202728
#if KMP_HAVE_QUAD
27212729
MIN_MAX_CRITICAL_CPT(float16, max_cpt, QUAD_LEGACY, <, 16r,
27222730
1) // __kmpc_atomic_float16_max_cpt
@@ -3686,6 +3694,168 @@ void __kmpc_atomic_end(void) {
36863694
__kmp_release_atomic_lock(&__kmp_atomic_lock, gtid);
36873695
}
36883696

3697+
// OpenMP 5.1 compare and swap
3698+
3699+
/*!
3700+
@param loc Source code location
3701+
@param gtid Global thread id
3702+
@param x Memory location to operate on
3703+
@param e Expected value
3704+
@param d Desired value
3705+
@return Result of comparison
3706+
3707+
Implements Compare And Swap atomic operation.
3708+
3709+
Sample code:
3710+
#pragma omp atomic compare update capture
3711+
{ r = x == e; if(r) { x = d; } }
3712+
*/
3713+
bool __kmpc_atomic_bool_1_cas(ident_t *loc, int gtid, char *x, char e, char d) {
3714+
return KMP_COMPARE_AND_STORE_ACQ8(x, e, d);
3715+
}
3716+
bool __kmpc_atomic_bool_2_cas(ident_t *loc, int gtid, short *x, short e,
3717+
short d) {
3718+
return KMP_COMPARE_AND_STORE_ACQ16(x, e, d);
3719+
}
3720+
bool __kmpc_atomic_bool_4_cas(ident_t *loc, int gtid, kmp_int32 *x, kmp_int32 e,
3721+
kmp_int32 d) {
3722+
return KMP_COMPARE_AND_STORE_ACQ32(x, e, d);
3723+
}
3724+
bool __kmpc_atomic_bool_8_cas(ident_t *loc, int gtid, kmp_int64 *x, kmp_int64 e,
3725+
kmp_int64 d) {
3726+
return KMP_COMPARE_AND_STORE_ACQ64(x, e, d);
3727+
}
3728+
3729+
/*!
3730+
@param loc Source code location
3731+
@param gtid Global thread id
3732+
@param x Memory location to operate on
3733+
@param e Expected value
3734+
@param d Desired value
3735+
@return Old value of x
3736+
3737+
Implements Compare And Swap atomic operation.
3738+
3739+
Sample code:
3740+
#pragma omp atomic compare update capture
3741+
{ v = x; if (x == e) { x = d; } }
3742+
*/
3743+
char __kmpc_atomic_val_1_cas(ident_t *loc, int gtid, char *x, char e, char d) {
3744+
return KMP_COMPARE_AND_STORE_RET8(x, e, d);
3745+
}
3746+
short __kmpc_atomic_val_2_cas(ident_t *loc, int gtid, short *x, short e,
3747+
short d) {
3748+
return KMP_COMPARE_AND_STORE_RET16(x, e, d);
3749+
}
3750+
kmp_int32 __kmpc_atomic_val_4_cas(ident_t *loc, int gtid, kmp_int32 *x,
3751+
kmp_int32 e, kmp_int32 d) {
3752+
return KMP_COMPARE_AND_STORE_RET32(x, e, d);
3753+
}
3754+
kmp_int64 __kmpc_atomic_val_8_cas(ident_t *loc, int gtid, kmp_int64 *x,
3755+
kmp_int64 e, kmp_int64 d) {
3756+
return KMP_COMPARE_AND_STORE_RET64(x, e, d);
3757+
}
3758+
3759+
/*!
3760+
@param loc Source code location
3761+
@param gtid Global thread id
3762+
@param x Memory location to operate on
3763+
@param e Expected value
3764+
@param d Desired value
3765+
@param pv Captured value location
3766+
@return Result of comparison
3767+
3768+
Implements Compare And Swap + Capture atomic operation.
3769+
3770+
v gets old valie of x if comparison failed, untouched otherwise.
3771+
Sample code:
3772+
#pragma omp atomic compare update capture
3773+
{ r = x == e; if(r) { x = d; } else { v = x; } }
3774+
*/
3775+
bool __kmpc_atomic_bool_1_cas_cpt(ident_t *loc, int gtid, char *x, char e,
3776+
char d, char *pv) {
3777+
char old = KMP_COMPARE_AND_STORE_RET8(x, e, d);
3778+
if (old == e)
3779+
return true;
3780+
KMP_ASSERT(pv != NULL);
3781+
*pv = old;
3782+
return false;
3783+
}
3784+
bool __kmpc_atomic_bool_2_cas_cpt(ident_t *loc, int gtid, short *x, short e,
3785+
short d, short *pv) {
3786+
short old = KMP_COMPARE_AND_STORE_RET16(x, e, d);
3787+
if (old == e)
3788+
return true;
3789+
KMP_ASSERT(pv != NULL);
3790+
*pv = old;
3791+
return false;
3792+
}
3793+
bool __kmpc_atomic_bool_4_cas_cpt(ident_t *loc, int gtid, kmp_int32 *x,
3794+
kmp_int32 e, kmp_int32 d, kmp_int32 *pv) {
3795+
kmp_int32 old = KMP_COMPARE_AND_STORE_RET32(x, e, d);
3796+
if (old == e)
3797+
return true;
3798+
KMP_ASSERT(pv != NULL);
3799+
*pv = old;
3800+
return false;
3801+
}
3802+
bool __kmpc_atomic_bool_8_cas_cpt(ident_t *loc, int gtid, kmp_int64 *x,
3803+
kmp_int64 e, kmp_int64 d, kmp_int64 *pv) {
3804+
kmp_int64 old = KMP_COMPARE_AND_STORE_RET64(x, e, d);
3805+
if (old == e)
3806+
return true;
3807+
KMP_ASSERT(pv != NULL);
3808+
*pv = old;
3809+
return false;
3810+
}
3811+
3812+
/*!
3813+
@param loc Source code location
3814+
@param gtid Global thread id
3815+
@param x Memory location to operate on
3816+
@param e Expected value
3817+
@param d Desired value
3818+
@param pv Captured value location
3819+
@return Old value of x
3820+
3821+
Implements Compare And Swap + Capture atomic operation.
3822+
3823+
v gets new valie of x.
3824+
Sample code:
3825+
#pragma omp atomic compare update capture
3826+
{ if (x == e) { x = d; }; v = x; }
3827+
*/
3828+
char __kmpc_atomic_val_1_cas_cpt(ident_t *loc, int gtid, char *x, char e,
3829+
char d, char *pv) {
3830+
char old = KMP_COMPARE_AND_STORE_RET8(x, e, d);
3831+
KMP_ASSERT(pv != NULL);
3832+
*pv = old == e ? d : old;
3833+
return old;
3834+
}
3835+
short __kmpc_atomic_val_2_cas_cpt(ident_t *loc, int gtid, short *x, short e,
3836+
short d, short *pv) {
3837+
short old = KMP_COMPARE_AND_STORE_RET16(x, e, d);
3838+
KMP_ASSERT(pv != NULL);
3839+
*pv = old == e ? d : old;
3840+
return old;
3841+
}
3842+
kmp_int32 __kmpc_atomic_val_4_cas_cpt(ident_t *loc, int gtid, kmp_int32 *x,
3843+
kmp_int32 e, kmp_int32 d, kmp_int32 *pv) {
3844+
kmp_int32 old = KMP_COMPARE_AND_STORE_RET32(x, e, d);
3845+
KMP_ASSERT(pv != NULL);
3846+
*pv = old == e ? d : old;
3847+
return old;
3848+
}
3849+
kmp_int64 __kmpc_atomic_val_8_cas_cpt(ident_t *loc, int gtid, kmp_int64 *x,
3850+
kmp_int64 e, kmp_int64 d, kmp_int64 *pv) {
3851+
kmp_int64 old = KMP_COMPARE_AND_STORE_RET64(x, e, d);
3852+
KMP_ASSERT(pv != NULL);
3853+
*pv = old == e ? d : old;
3854+
return old;
3855+
}
3856+
3857+
// End OpenMP 5.1 compare + capture
3858+
36893859
/*!
36903860
@}
36913861
*/

openmp/runtime/src/kmp_atomic.h

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -578,6 +578,10 @@ void __kmpc_atomic_float8_max(ident_t *id_ref, int gtid, kmp_real64 *lhs,
578578
kmp_real64 rhs);
579579
void __kmpc_atomic_float8_min(ident_t *id_ref, int gtid, kmp_real64 *lhs,
580580
kmp_real64 rhs);
581+
void __kmpc_atomic_float10_max(ident_t *id_ref, int gtid, long double *lhs,
582+
long double rhs);
583+
void __kmpc_atomic_float10_min(ident_t *id_ref, int gtid, long double *lhs,
584+
long double rhs);
581585
#if KMP_HAVE_QUAD
582586
void __kmpc_atomic_float16_max(ident_t *id_ref, int gtid, QUAD_LEGACY *lhs,
583587
QUAD_LEGACY rhs);
@@ -1254,6 +1258,12 @@ kmp_real64 __kmpc_atomic_float8_max_cpt(ident_t *id_ref, int gtid,
12541258
kmp_real64 __kmpc_atomic_float8_min_cpt(ident_t *id_ref, int gtid,
12551259
kmp_real64 *lhs, kmp_real64 rhs,
12561260
int flag);
1261+
long double __kmpc_atomic_float10_max_cpt(ident_t *id_ref, int gtid,
1262+
long double *lhs, long double rhs,
1263+
int flag);
1264+
long double __kmpc_atomic_float10_min_cpt(ident_t *id_ref, int gtid,
1265+
long double *lhs, long double rhs,
1266+
int flag);
12571267
#if KMP_HAVE_QUAD
12581268
QUAD_LEGACY __kmpc_atomic_float16_max_cpt(ident_t *id_ref, int gtid,
12591269
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,
17561766

17571767
// End of OpenMP 4.0 capture
17581768

1769+
// OpenMP 5.1 compare and swap
1770+
/*
1771+
__kmpc_atomic_bool_1_cas
1772+
__kmpc_atomic_bool_2_cas
1773+
__kmpc_atomic_bool_4_cas
1774+
__kmpc_atomic_bool_8_cas
1775+
__kmpc_atomic_val_1_cas
1776+
__kmpc_atomic_val_2_cas
1777+
__kmpc_atomic_val_4_cas
1778+
__kmpc_atomic_val_8_cas
1779+
__kmpc_atomic_bool_1_cas_cpt
1780+
__kmpc_atomic_bool_2_cas_cpt
1781+
__kmpc_atomic_bool_4_cas_cpt
1782+
__kmpc_atomic_bool_8_cas_cpt
1783+
__kmpc_atomic_val_1_cas_cpt
1784+
__kmpc_atomic_val_2_cas_cpt
1785+
__kmpc_atomic_val_4_cas_cpt
1786+
__kmpc_atomic_val_8_cas_cpt
1787+
*/
1788+
// In all interfaces of CAS (Compare And Swap):
1789+
// r is the boolean result of comparison
1790+
// x is memory location to operate on
1791+
// e is expected (old) value
1792+
// d is desired (new) value
1793+
// pv is pointer to captured value v whose location may coincide with e
1794+
1795+
// { r = x == e; if(r) { x = d; } }
1796+
// functions return result of comparison
1797+
bool __kmpc_atomic_bool_1_cas(ident_t *loc, int gtid, char *x, char e, char d);
1798+
bool __kmpc_atomic_bool_2_cas(ident_t *loc, int gtid, short *x, short e,
1799+
short d);
1800+
bool __kmpc_atomic_bool_4_cas(ident_t *loc, int gtid, kmp_int32 *x, kmp_int32 e,
1801+
kmp_int32 d);
1802+
bool __kmpc_atomic_bool_8_cas(ident_t *loc, int gtid, kmp_int64 *x, kmp_int64 e,
1803+
kmp_int64 d);
1804+
1805+
// { v = x; if (x == e) { x = d; } }
1806+
// functions return old value
1807+
char __kmpc_atomic_val_1_cas(ident_t *loc, int gtid, char *x, char e, char d);
1808+
short __kmpc_atomic_val_2_cas(ident_t *loc, int gtid, short *x, short e,
1809+
short d);
1810+
kmp_int32 __kmpc_atomic_val_4_cas(ident_t *loc, int gtid, kmp_int32 *x,
1811+
kmp_int32 e, kmp_int32 d);
1812+
kmp_int64 __kmpc_atomic_val_8_cas(ident_t *loc, int gtid, kmp_int64 *x,
1813+
kmp_int64 e, kmp_int64 d);
1814+
1815+
// { r = x == e; if(r) { x = d; } else { v = x; } }
1816+
// v gets old value if comparison failed, untouched otherwise
1817+
// functions return result of comparison
1818+
bool __kmpc_atomic_bool_1_cas_cpt(ident_t *loc, int gtid, char *x, char e,
1819+
char d, char *pv);
1820+
bool __kmpc_atomic_bool_2_cas_cpt(ident_t *loc, int gtid, short *x, short e,
1821+
short d, short *pv);
1822+
bool __kmpc_atomic_bool_4_cas_cpt(ident_t *loc, int gtid, kmp_int32 *x,
1823+
kmp_int32 e, kmp_int32 d, kmp_int32 *pv);
1824+
bool __kmpc_atomic_bool_8_cas_cpt(ident_t *loc, int gtid, kmp_int64 *x,
1825+
kmp_int64 e, kmp_int64 d, kmp_int64 *pv);
1826+
1827+
// { if (x == e) { x = d; }; v = x; }
1828+
// v gets old value if comparison failed, new value otherwise
1829+
// functions return old value
1830+
char __kmpc_atomic_val_1_cas_cpt(ident_t *loc, int gtid, char *x, char e,
1831+
char d, char *pv);
1832+
short __kmpc_atomic_val_2_cas_cpt(ident_t *loc, int gtid, short *x, short e,
1833+
short d, short *pv);
1834+
kmp_int32 __kmpc_atomic_val_4_cas_cpt(ident_t *loc, int gtid, kmp_int32 *x,
1835+
kmp_int32 e, kmp_int32 d, kmp_int32 *pv);
1836+
kmp_int64 __kmpc_atomic_val_8_cas_cpt(ident_t *loc, int gtid, kmp_int64 *x,
1837+
kmp_int64 e, kmp_int64 d, kmp_int64 *pv);
1838+
1839+
// End OpenMP 5.1 compare + capture
1840+
17591841
#endif // KMP_ARCH_X86 || KMP_ARCH_X86_64
17601842

17611843
/* ------------------------------------------------------------------------ */

0 commit comments

Comments
 (0)