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