1*f4a2713aSLionel Sambuc // RUN: %clang_cc1 %s -emit-llvm -o - -triple=i686-apple-darwin9 | FileCheck %s 2*f4a2713aSLionel Sambuc 3*f4a2713aSLionel Sambuc // Also test serialization of atomic operations here, to avoid duplicating the 4*f4a2713aSLionel Sambuc // test. 5*f4a2713aSLionel Sambuc // RUN: %clang_cc1 %s -emit-pch -o %t -triple=i686-apple-darwin9 6*f4a2713aSLionel Sambuc // RUN: %clang_cc1 %s -include-pch %t -triple=i686-apple-darwin9 -emit-llvm -o - | FileCheck %s 7*f4a2713aSLionel Sambuc #ifndef ALREADY_INCLUDED 8*f4a2713aSLionel Sambuc #define ALREADY_INCLUDED 9*f4a2713aSLionel Sambuc 10*f4a2713aSLionel Sambuc // Basic IRGen tests for __c11_atomic_* and GNU __atomic_* 11*f4a2713aSLionel Sambuc 12*f4a2713aSLionel Sambuc typedef enum memory_order { 13*f4a2713aSLionel Sambuc memory_order_relaxed, memory_order_consume, memory_order_acquire, 14*f4a2713aSLionel Sambuc memory_order_release, memory_order_acq_rel, memory_order_seq_cst 15*f4a2713aSLionel Sambuc } memory_order; 16*f4a2713aSLionel Sambuc 17*f4a2713aSLionel Sambuc int fi1(_Atomic(int) *i) { 18*f4a2713aSLionel Sambuc // CHECK: @fi1 19*f4a2713aSLionel Sambuc // CHECK: load atomic i32* {{.*}} seq_cst 20*f4a2713aSLionel Sambuc return __c11_atomic_load(i, memory_order_seq_cst); 21*f4a2713aSLionel Sambuc } 22*f4a2713aSLionel Sambuc 23*f4a2713aSLionel Sambuc int fi1a(int *i) { 24*f4a2713aSLionel Sambuc // CHECK: @fi1a 25*f4a2713aSLionel Sambuc // CHECK: load atomic i32* {{.*}} seq_cst 26*f4a2713aSLionel Sambuc int v; 27*f4a2713aSLionel Sambuc __atomic_load(i, &v, memory_order_seq_cst); 28*f4a2713aSLionel Sambuc return v; 29*f4a2713aSLionel Sambuc } 30*f4a2713aSLionel Sambuc 31*f4a2713aSLionel Sambuc int fi1b(int *i) { 32*f4a2713aSLionel Sambuc // CHECK: @fi1b 33*f4a2713aSLionel Sambuc // CHECK: load atomic i32* {{.*}} seq_cst 34*f4a2713aSLionel Sambuc return __atomic_load_n(i, memory_order_seq_cst); 35*f4a2713aSLionel Sambuc } 36*f4a2713aSLionel Sambuc 37*f4a2713aSLionel Sambuc void fi2(_Atomic(int) *i) { 38*f4a2713aSLionel Sambuc // CHECK: @fi2 39*f4a2713aSLionel Sambuc // CHECK: store atomic i32 {{.*}} seq_cst 40*f4a2713aSLionel Sambuc __c11_atomic_store(i, 1, memory_order_seq_cst); 41*f4a2713aSLionel Sambuc } 42*f4a2713aSLionel Sambuc 43*f4a2713aSLionel Sambuc void fi2a(int *i) { 44*f4a2713aSLionel Sambuc // CHECK: @fi2a 45*f4a2713aSLionel Sambuc // CHECK: store atomic i32 {{.*}} seq_cst 46*f4a2713aSLionel Sambuc int v = 1; 47*f4a2713aSLionel Sambuc __atomic_store(i, &v, memory_order_seq_cst); 48*f4a2713aSLionel Sambuc } 49*f4a2713aSLionel Sambuc 50*f4a2713aSLionel Sambuc void fi2b(int *i) { 51*f4a2713aSLionel Sambuc // CHECK: @fi2b 52*f4a2713aSLionel Sambuc // CHECK: store atomic i32 {{.*}} seq_cst 53*f4a2713aSLionel Sambuc __atomic_store_n(i, 1, memory_order_seq_cst); 54*f4a2713aSLionel Sambuc } 55*f4a2713aSLionel Sambuc 56*f4a2713aSLionel Sambuc int fi3(_Atomic(int) *i) { 57*f4a2713aSLionel Sambuc // CHECK: @fi3 58*f4a2713aSLionel Sambuc // CHECK: atomicrmw and 59*f4a2713aSLionel Sambuc // CHECK-NOT: and 60*f4a2713aSLionel Sambuc return __c11_atomic_fetch_and(i, 1, memory_order_seq_cst); 61*f4a2713aSLionel Sambuc } 62*f4a2713aSLionel Sambuc 63*f4a2713aSLionel Sambuc int fi3a(int *i) { 64*f4a2713aSLionel Sambuc // CHECK: @fi3a 65*f4a2713aSLionel Sambuc // CHECK: atomicrmw xor 66*f4a2713aSLionel Sambuc // CHECK-NOT: xor 67*f4a2713aSLionel Sambuc return __atomic_fetch_xor(i, 1, memory_order_seq_cst); 68*f4a2713aSLionel Sambuc } 69*f4a2713aSLionel Sambuc 70*f4a2713aSLionel Sambuc int fi3b(int *i) { 71*f4a2713aSLionel Sambuc // CHECK: @fi3b 72*f4a2713aSLionel Sambuc // CHECK: atomicrmw add 73*f4a2713aSLionel Sambuc // CHECK: add 74*f4a2713aSLionel Sambuc return __atomic_add_fetch(i, 1, memory_order_seq_cst); 75*f4a2713aSLionel Sambuc } 76*f4a2713aSLionel Sambuc 77*f4a2713aSLionel Sambuc int fi3c(int *i) { 78*f4a2713aSLionel Sambuc // CHECK: @fi3c 79*f4a2713aSLionel Sambuc // CHECK: atomicrmw nand 80*f4a2713aSLionel Sambuc // CHECK-NOT: and 81*f4a2713aSLionel Sambuc return __atomic_fetch_nand(i, 1, memory_order_seq_cst); 82*f4a2713aSLionel Sambuc } 83*f4a2713aSLionel Sambuc 84*f4a2713aSLionel Sambuc int fi3d(int *i) { 85*f4a2713aSLionel Sambuc // CHECK: @fi3d 86*f4a2713aSLionel Sambuc // CHECK: atomicrmw nand 87*f4a2713aSLionel Sambuc // CHECK: and 88*f4a2713aSLionel Sambuc // CHECK: xor 89*f4a2713aSLionel Sambuc return __atomic_nand_fetch(i, 1, memory_order_seq_cst); 90*f4a2713aSLionel Sambuc } 91*f4a2713aSLionel Sambuc 92*f4a2713aSLionel Sambuc _Bool fi4(_Atomic(int) *i) { 93*f4a2713aSLionel Sambuc // CHECK: @fi4 94*f4a2713aSLionel Sambuc // CHECK: cmpxchg i32* 95*f4a2713aSLionel Sambuc int cmp = 0; 96*f4a2713aSLionel Sambuc return __c11_atomic_compare_exchange_strong(i, &cmp, 1, memory_order_acquire, memory_order_acquire); 97*f4a2713aSLionel Sambuc } 98*f4a2713aSLionel Sambuc 99*f4a2713aSLionel Sambuc _Bool fi4a(int *i) { 100*f4a2713aSLionel Sambuc // CHECK: @fi4 101*f4a2713aSLionel Sambuc // CHECK: cmpxchg i32* 102*f4a2713aSLionel Sambuc int cmp = 0; 103*f4a2713aSLionel Sambuc int desired = 1; 104*f4a2713aSLionel Sambuc return __atomic_compare_exchange(i, &cmp, &desired, 0, memory_order_acquire, memory_order_acquire); 105*f4a2713aSLionel Sambuc } 106*f4a2713aSLionel Sambuc 107*f4a2713aSLionel Sambuc _Bool fi4b(int *i) { 108*f4a2713aSLionel Sambuc // CHECK: @fi4 109*f4a2713aSLionel Sambuc // CHECK: cmpxchg i32* 110*f4a2713aSLionel Sambuc int cmp = 0; 111*f4a2713aSLionel Sambuc return __atomic_compare_exchange_n(i, &cmp, 1, 1, memory_order_acquire, memory_order_acquire); 112*f4a2713aSLionel Sambuc } 113*f4a2713aSLionel Sambuc 114*f4a2713aSLionel Sambuc float ff1(_Atomic(float) *d) { 115*f4a2713aSLionel Sambuc // CHECK: @ff1 116*f4a2713aSLionel Sambuc // CHECK: load atomic i32* {{.*}} monotonic 117*f4a2713aSLionel Sambuc return __c11_atomic_load(d, memory_order_relaxed); 118*f4a2713aSLionel Sambuc } 119*f4a2713aSLionel Sambuc 120*f4a2713aSLionel Sambuc void ff2(_Atomic(float) *d) { 121*f4a2713aSLionel Sambuc // CHECK: @ff2 122*f4a2713aSLionel Sambuc // CHECK: store atomic i32 {{.*}} release 123*f4a2713aSLionel Sambuc __c11_atomic_store(d, 1, memory_order_release); 124*f4a2713aSLionel Sambuc } 125*f4a2713aSLionel Sambuc 126*f4a2713aSLionel Sambuc float ff3(_Atomic(float) *d) { 127*f4a2713aSLionel Sambuc return __c11_atomic_exchange(d, 2, memory_order_seq_cst); 128*f4a2713aSLionel Sambuc } 129*f4a2713aSLionel Sambuc 130*f4a2713aSLionel Sambuc int* fp1(_Atomic(int*) *p) { 131*f4a2713aSLionel Sambuc // CHECK: @fp1 132*f4a2713aSLionel Sambuc // CHECK: load atomic i32* {{.*}} seq_cst 133*f4a2713aSLionel Sambuc return __c11_atomic_load(p, memory_order_seq_cst); 134*f4a2713aSLionel Sambuc } 135*f4a2713aSLionel Sambuc 136*f4a2713aSLionel Sambuc int* fp2(_Atomic(int*) *p) { 137*f4a2713aSLionel Sambuc // CHECK: @fp2 138*f4a2713aSLionel Sambuc // CHECK: store i32 4 139*f4a2713aSLionel Sambuc // CHECK: atomicrmw add {{.*}} monotonic 140*f4a2713aSLionel Sambuc return __c11_atomic_fetch_add(p, 1, memory_order_relaxed); 141*f4a2713aSLionel Sambuc } 142*f4a2713aSLionel Sambuc 143*f4a2713aSLionel Sambuc int *fp2a(int **p) { 144*f4a2713aSLionel Sambuc // CHECK: @fp2a 145*f4a2713aSLionel Sambuc // CHECK: store i32 4 146*f4a2713aSLionel Sambuc // CHECK: atomicrmw sub {{.*}} monotonic 147*f4a2713aSLionel Sambuc // Note, the GNU builtins do not multiply by sizeof(T)! 148*f4a2713aSLionel Sambuc return __atomic_fetch_sub(p, 4, memory_order_relaxed); 149*f4a2713aSLionel Sambuc } 150*f4a2713aSLionel Sambuc 151*f4a2713aSLionel Sambuc _Complex float fc(_Atomic(_Complex float) *c) { 152*f4a2713aSLionel Sambuc // CHECK: @fc 153*f4a2713aSLionel Sambuc // CHECK: atomicrmw xchg i64* 154*f4a2713aSLionel Sambuc return __c11_atomic_exchange(c, 2, memory_order_seq_cst); 155*f4a2713aSLionel Sambuc } 156*f4a2713aSLionel Sambuc 157*f4a2713aSLionel Sambuc typedef struct X { int x; } X; 158*f4a2713aSLionel Sambuc X fs(_Atomic(X) *c) { 159*f4a2713aSLionel Sambuc // CHECK: @fs 160*f4a2713aSLionel Sambuc // CHECK: atomicrmw xchg i32* 161*f4a2713aSLionel Sambuc return __c11_atomic_exchange(c, (X){2}, memory_order_seq_cst); 162*f4a2713aSLionel Sambuc } 163*f4a2713aSLionel Sambuc 164*f4a2713aSLionel Sambuc X fsa(X *c, X *d) { 165*f4a2713aSLionel Sambuc // CHECK: @fsa 166*f4a2713aSLionel Sambuc // CHECK: atomicrmw xchg i32* 167*f4a2713aSLionel Sambuc X ret; 168*f4a2713aSLionel Sambuc __atomic_exchange(c, d, &ret, memory_order_seq_cst); 169*f4a2713aSLionel Sambuc return ret; 170*f4a2713aSLionel Sambuc } 171*f4a2713aSLionel Sambuc 172*f4a2713aSLionel Sambuc _Bool fsb(_Bool *c) { 173*f4a2713aSLionel Sambuc // CHECK: @fsb 174*f4a2713aSLionel Sambuc // CHECK: atomicrmw xchg i8* 175*f4a2713aSLionel Sambuc return __atomic_exchange_n(c, 1, memory_order_seq_cst); 176*f4a2713aSLionel Sambuc } 177*f4a2713aSLionel Sambuc 178*f4a2713aSLionel Sambuc char flag1; 179*f4a2713aSLionel Sambuc volatile char flag2; 180*f4a2713aSLionel Sambuc void test_and_set() { 181*f4a2713aSLionel Sambuc // CHECK: atomicrmw xchg i8* @flag1, i8 1 seq_cst 182*f4a2713aSLionel Sambuc __atomic_test_and_set(&flag1, memory_order_seq_cst); 183*f4a2713aSLionel Sambuc // CHECK: atomicrmw volatile xchg i8* @flag2, i8 1 acquire 184*f4a2713aSLionel Sambuc __atomic_test_and_set(&flag2, memory_order_acquire); 185*f4a2713aSLionel Sambuc // CHECK: store atomic volatile i8 0, i8* @flag2 release 186*f4a2713aSLionel Sambuc __atomic_clear(&flag2, memory_order_release); 187*f4a2713aSLionel Sambuc // CHECK: store atomic i8 0, i8* @flag1 seq_cst 188*f4a2713aSLionel Sambuc __atomic_clear(&flag1, memory_order_seq_cst); 189*f4a2713aSLionel Sambuc } 190*f4a2713aSLionel Sambuc 191*f4a2713aSLionel Sambuc struct Sixteen { 192*f4a2713aSLionel Sambuc char c[16]; 193*f4a2713aSLionel Sambuc } sixteen; 194*f4a2713aSLionel Sambuc struct Seventeen { 195*f4a2713aSLionel Sambuc char c[17]; 196*f4a2713aSLionel Sambuc } seventeen; 197*f4a2713aSLionel Sambuc 198*f4a2713aSLionel Sambuc int lock_free(struct Incomplete *incomplete) { 199*f4a2713aSLionel Sambuc // CHECK: @lock_free 200*f4a2713aSLionel Sambuc 201*f4a2713aSLionel Sambuc // CHECK: call i32 @__atomic_is_lock_free(i32 3, i8* null) 202*f4a2713aSLionel Sambuc __c11_atomic_is_lock_free(3); 203*f4a2713aSLionel Sambuc 204*f4a2713aSLionel Sambuc // CHECK: call i32 @__atomic_is_lock_free(i32 16, i8* {{.*}}@sixteen{{.*}}) 205*f4a2713aSLionel Sambuc __atomic_is_lock_free(16, &sixteen); 206*f4a2713aSLionel Sambuc 207*f4a2713aSLionel Sambuc // CHECK: call i32 @__atomic_is_lock_free(i32 17, i8* {{.*}}@seventeen{{.*}}) 208*f4a2713aSLionel Sambuc __atomic_is_lock_free(17, &seventeen); 209*f4a2713aSLionel Sambuc 210*f4a2713aSLionel Sambuc // CHECK: call i32 @__atomic_is_lock_free(i32 4, {{.*}}) 211*f4a2713aSLionel Sambuc __atomic_is_lock_free(4, incomplete); 212*f4a2713aSLionel Sambuc 213*f4a2713aSLionel Sambuc char cs[20]; 214*f4a2713aSLionel Sambuc // CHECK: call i32 @__atomic_is_lock_free(i32 4, {{.*}}) 215*f4a2713aSLionel Sambuc __atomic_is_lock_free(4, cs+1); 216*f4a2713aSLionel Sambuc 217*f4a2713aSLionel Sambuc // CHECK-NOT: call 218*f4a2713aSLionel Sambuc __atomic_always_lock_free(3, 0); 219*f4a2713aSLionel Sambuc __atomic_always_lock_free(16, 0); 220*f4a2713aSLionel Sambuc __atomic_always_lock_free(17, 0); 221*f4a2713aSLionel Sambuc __atomic_always_lock_free(16, &sixteen); 222*f4a2713aSLionel Sambuc __atomic_always_lock_free(17, &seventeen); 223*f4a2713aSLionel Sambuc 224*f4a2713aSLionel Sambuc int n; 225*f4a2713aSLionel Sambuc __atomic_is_lock_free(4, &n); 226*f4a2713aSLionel Sambuc 227*f4a2713aSLionel Sambuc // CHECK: ret i32 1 228*f4a2713aSLionel Sambuc return __c11_atomic_is_lock_free(sizeof(_Atomic(int))); 229*f4a2713aSLionel Sambuc } 230*f4a2713aSLionel Sambuc 231*f4a2713aSLionel Sambuc // Tests for atomic operations on big values. These should call the functions 232*f4a2713aSLionel Sambuc // defined here: 233*f4a2713aSLionel Sambuc // http://gcc.gnu.org/wiki/Atomic/GCCMM/LIbrary#The_Library_interface 234*f4a2713aSLionel Sambuc 235*f4a2713aSLionel Sambuc struct foo { 236*f4a2713aSLionel Sambuc int big[128]; 237*f4a2713aSLionel Sambuc }; 238*f4a2713aSLionel Sambuc struct bar { 239*f4a2713aSLionel Sambuc char c[3]; 240*f4a2713aSLionel Sambuc }; 241*f4a2713aSLionel Sambuc 242*f4a2713aSLionel Sambuc struct bar smallThing, thing1, thing2; 243*f4a2713aSLionel Sambuc struct foo bigThing; 244*f4a2713aSLionel Sambuc _Atomic(struct foo) bigAtomic; 245*f4a2713aSLionel Sambuc 246*f4a2713aSLionel Sambuc void structAtomicStore() { 247*f4a2713aSLionel Sambuc // CHECK: @structAtomicStore 248*f4a2713aSLionel Sambuc struct foo f = {0}; 249*f4a2713aSLionel Sambuc struct bar b = {0}; 250*f4a2713aSLionel Sambuc __atomic_store(&smallThing, &b, 5); 251*f4a2713aSLionel Sambuc // CHECK: call void @__atomic_store(i32 3, i8* {{.*}} @smallThing 252*f4a2713aSLionel Sambuc 253*f4a2713aSLionel Sambuc __atomic_store(&bigThing, &f, 5); 254*f4a2713aSLionel Sambuc // CHECK: call void @__atomic_store(i32 512, i8* {{.*}} @bigThing 255*f4a2713aSLionel Sambuc } 256*f4a2713aSLionel Sambuc void structAtomicLoad() { 257*f4a2713aSLionel Sambuc // CHECK: @structAtomicLoad 258*f4a2713aSLionel Sambuc struct bar b; 259*f4a2713aSLionel Sambuc __atomic_load(&smallThing, &b, 5); 260*f4a2713aSLionel Sambuc // CHECK: call void @__atomic_load(i32 3, i8* {{.*}} @smallThing 261*f4a2713aSLionel Sambuc 262*f4a2713aSLionel Sambuc struct foo f = {0}; 263*f4a2713aSLionel Sambuc __atomic_load(&bigThing, &f, 5); 264*f4a2713aSLionel Sambuc // CHECK: call void @__atomic_load(i32 512, i8* {{.*}} @bigThing 265*f4a2713aSLionel Sambuc } 266*f4a2713aSLionel Sambuc struct foo structAtomicExchange() { 267*f4a2713aSLionel Sambuc // CHECK: @structAtomicExchange 268*f4a2713aSLionel Sambuc struct foo f = {0}; 269*f4a2713aSLionel Sambuc struct foo old; 270*f4a2713aSLionel Sambuc __atomic_exchange(&f, &bigThing, &old, 5); 271*f4a2713aSLionel Sambuc // CHECK: call void @__atomic_exchange(i32 512, {{.*}}, i8* bitcast ({{.*}} @bigThing to i8*), 272*f4a2713aSLionel Sambuc 273*f4a2713aSLionel Sambuc return __c11_atomic_exchange(&bigAtomic, f, 5); 274*f4a2713aSLionel Sambuc // CHECK: call void @__atomic_exchange(i32 512, i8* bitcast ({{.*}} @bigAtomic to i8*), 275*f4a2713aSLionel Sambuc } 276*f4a2713aSLionel Sambuc int structAtomicCmpExchange() { 277*f4a2713aSLionel Sambuc // CHECK: @structAtomicCmpExchange 278*f4a2713aSLionel Sambuc _Bool x = __atomic_compare_exchange(&smallThing, &thing1, &thing2, 1, 5, 5); 279*f4a2713aSLionel Sambuc // CHECK: call zeroext i1 @__atomic_compare_exchange(i32 3, {{.*}} @smallThing{{.*}} @thing1{{.*}} @thing2 280*f4a2713aSLionel Sambuc 281*f4a2713aSLionel Sambuc struct foo f = {0}; 282*f4a2713aSLionel Sambuc struct foo g = {0}; 283*f4a2713aSLionel Sambuc g.big[12] = 12; 284*f4a2713aSLionel Sambuc return x & __c11_atomic_compare_exchange_strong(&bigAtomic, &f, g, 5, 5); 285*f4a2713aSLionel Sambuc // CHECK: call zeroext i1 @__atomic_compare_exchange(i32 512, i8* bitcast ({{.*}} @bigAtomic to i8*), 286*f4a2713aSLionel Sambuc } 287*f4a2713aSLionel Sambuc 288*f4a2713aSLionel Sambuc // Check that no atomic operations are used in any initialisation of _Atomic 289*f4a2713aSLionel Sambuc // types. 290*f4a2713aSLionel Sambuc _Atomic(int) atomic_init_i = 42; 291*f4a2713aSLionel Sambuc 292*f4a2713aSLionel Sambuc // CHECK: @atomic_init_foo 293*f4a2713aSLionel Sambuc void atomic_init_foo() 294*f4a2713aSLionel Sambuc { 295*f4a2713aSLionel Sambuc // CHECK-NOT: } 296*f4a2713aSLionel Sambuc // CHECK-NOT: atomic 297*f4a2713aSLionel Sambuc // CHECK: store 298*f4a2713aSLionel Sambuc _Atomic(int) j = 12; 299*f4a2713aSLionel Sambuc 300*f4a2713aSLionel Sambuc // CHECK-NOT: } 301*f4a2713aSLionel Sambuc // CHECK-NOT: atomic 302*f4a2713aSLionel Sambuc // CHECK: store 303*f4a2713aSLionel Sambuc __c11_atomic_init(&j, 42); 304*f4a2713aSLionel Sambuc 305*f4a2713aSLionel Sambuc // CHECK-NOT: atomic 306*f4a2713aSLionel Sambuc // CHECK: } 307*f4a2713aSLionel Sambuc } 308*f4a2713aSLionel Sambuc 309*f4a2713aSLionel Sambuc // CHECK: @invalid_atomic 310*f4a2713aSLionel Sambuc void invalid_atomic(_Atomic(int) *i) { 311*f4a2713aSLionel Sambuc __c11_atomic_store(i, 1, memory_order_consume); 312*f4a2713aSLionel Sambuc __c11_atomic_store(i, 1, memory_order_acquire); 313*f4a2713aSLionel Sambuc __c11_atomic_store(i, 1, memory_order_acq_rel); 314*f4a2713aSLionel Sambuc __c11_atomic_load(i, memory_order_release); 315*f4a2713aSLionel Sambuc __c11_atomic_load(i, memory_order_acq_rel); 316*f4a2713aSLionel Sambuc } 317*f4a2713aSLionel Sambuc 318*f4a2713aSLionel Sambuc #endif 319