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