xref: /aosp_15_r20/external/clang/test/CodeGen/c11atomics.c (revision 67e74705e28f6214e480b399dd47ea732279e315)
1*67e74705SXin Li // RUN: %clang_cc1 %s -emit-llvm -o - -triple=armv5-unknown-freebsd -std=c11 | FileCheck %s
2*67e74705SXin Li 
3*67e74705SXin Li // Test that we are generating atomicrmw instructions, rather than
4*67e74705SXin Li // compare-exchange loops for common atomic ops.  This makes a big difference
5*67e74705SXin Li // on RISC platforms, where the compare-exchange loop becomes a ll/sc pair for
6*67e74705SXin Li // the load and then another ll/sc in the loop, expanding to about 30
7*67e74705SXin Li // instructions when it should be only 4.  It has a smaller, but still
8*67e74705SXin Li // noticeable, impact on platforms like x86 and RISC-V, where there are atomic
9*67e74705SXin Li // RMW instructions.
10*67e74705SXin Li //
11*67e74705SXin Li // We currently emit cmpxchg loops for most operations on _Bools, because
12*67e74705SXin Li // they're sufficiently rare that it's not worth making sure that the semantics
13*67e74705SXin Li // are correct.
14*67e74705SXin Li 
15*67e74705SXin Li struct elem;
16*67e74705SXin Li 
17*67e74705SXin Li struct ptr {
18*67e74705SXin Li     struct elem *ptr;
19*67e74705SXin Li };
20*67e74705SXin Li // CHECK-DAG: %struct.ptr = type { %struct.elem* }
21*67e74705SXin Li 
22*67e74705SXin Li struct elem {
23*67e74705SXin Li     _Atomic(struct ptr) link;
24*67e74705SXin Li };
25*67e74705SXin Li // CHECK-DAG: %struct.elem = type { %struct.ptr }
26*67e74705SXin Li 
27*67e74705SXin Li struct ptr object;
28*67e74705SXin Li // CHECK-DAG: @object = common global %struct.ptr zeroinitializer
29*67e74705SXin Li 
30*67e74705SXin Li // CHECK-DAG: @testStructGlobal = global {{.*}} { i16 1, i16 2, i16 3, i16 4 }
31*67e74705SXin Li // CHECK-DAG: @testPromotedStructGlobal = global {{.*}} { %{{.*}} { i16 1, i16 2, i16 3 }, [2 x i8] zeroinitializer }
32*67e74705SXin Li 
33*67e74705SXin Li 
34*67e74705SXin Li typedef int __attribute__((vector_size(16))) vector;
35*67e74705SXin Li 
36*67e74705SXin Li _Atomic(_Bool) b;
37*67e74705SXin Li _Atomic(int) i;
38*67e74705SXin Li _Atomic(long long) l;
39*67e74705SXin Li _Atomic(short) s;
40*67e74705SXin Li _Atomic(char*) p;
41*67e74705SXin Li _Atomic(float) f;
42*67e74705SXin Li _Atomic(vector) v;
43*67e74705SXin Li 
44*67e74705SXin Li // CHECK: testinc
testinc(void)45*67e74705SXin Li void testinc(void)
46*67e74705SXin Li {
47*67e74705SXin Li   // Special case for suffix bool++, sets to true and returns the old value.
48*67e74705SXin Li   // CHECK: atomicrmw xchg i8* @b, i8 1 seq_cst
49*67e74705SXin Li   b++;
50*67e74705SXin Li   // CHECK: atomicrmw add i32* @i, i32 1 seq_cst
51*67e74705SXin Li   i++;
52*67e74705SXin Li   // CHECK: atomicrmw add i64* @l, i64 1 seq_cst
53*67e74705SXin Li   l++;
54*67e74705SXin Li   // CHECK: atomicrmw add i16* @s, i16 1 seq_cst
55*67e74705SXin Li   s++;
56*67e74705SXin Li   // Prefix increment
57*67e74705SXin Li   // Special case for bool: set to true and return true
58*67e74705SXin Li   // CHECK: store atomic i8 1, i8* @b seq_cst, align 1
59*67e74705SXin Li   ++b;
60*67e74705SXin Li   // Currently, we have no variant of atomicrmw that returns the new value, so
61*67e74705SXin Li   // we have to generate an atomic add, which returns the old value, and then a
62*67e74705SXin Li   // non-atomic add.
63*67e74705SXin Li   // CHECK: atomicrmw add i32* @i, i32 1 seq_cst
64*67e74705SXin Li   // CHECK: add i32
65*67e74705SXin Li   ++i;
66*67e74705SXin Li   // CHECK: atomicrmw add i64* @l, i64 1 seq_cst
67*67e74705SXin Li   // CHECK: add i64
68*67e74705SXin Li   ++l;
69*67e74705SXin Li   // CHECK: atomicrmw add i16* @s, i16 1 seq_cst
70*67e74705SXin Li   // CHECK: add i16
71*67e74705SXin Li   ++s;
72*67e74705SXin Li }
73*67e74705SXin Li // CHECK: testdec
testdec(void)74*67e74705SXin Li void testdec(void)
75*67e74705SXin Li {
76*67e74705SXin Li   // CHECK: call arm_aapcscc zeroext i1 @__atomic_compare_exchange(i32 1, i8* @b
77*67e74705SXin Li   b--;
78*67e74705SXin Li   // CHECK: atomicrmw sub i32* @i, i32 1 seq_cst
79*67e74705SXin Li   i--;
80*67e74705SXin Li   // CHECK: atomicrmw sub i64* @l, i64 1 seq_cst
81*67e74705SXin Li   l--;
82*67e74705SXin Li   // CHECK: atomicrmw sub i16* @s, i16 1 seq_cst
83*67e74705SXin Li   s--;
84*67e74705SXin Li   // CHECK: call arm_aapcscc zeroext i1 @__atomic_compare_exchange(i32 1, i8* @b
85*67e74705SXin Li   --b;
86*67e74705SXin Li   // CHECK: atomicrmw sub i32* @i, i32 1 seq_cst
87*67e74705SXin Li   // CHECK: sub i32
88*67e74705SXin Li   --i;
89*67e74705SXin Li   // CHECK: atomicrmw sub i64* @l, i64 1 seq_cst
90*67e74705SXin Li   // CHECK: sub i64
91*67e74705SXin Li   --l;
92*67e74705SXin Li   // CHECK: atomicrmw sub i16* @s, i16 1 seq_cst
93*67e74705SXin Li   // CHECK: sub i16
94*67e74705SXin Li   --s;
95*67e74705SXin Li }
96*67e74705SXin Li // CHECK: testaddeq
testaddeq(void)97*67e74705SXin Li void testaddeq(void)
98*67e74705SXin Li {
99*67e74705SXin Li   // CHECK: call arm_aapcscc zeroext i1 @__atomic_compare_exchange(i32 1, i8* @b
100*67e74705SXin Li   // CHECK: atomicrmw add i32* @i, i32 42 seq_cst
101*67e74705SXin Li   // CHECK: atomicrmw add i64* @l, i64 42 seq_cst
102*67e74705SXin Li   // CHECK: atomicrmw add i16* @s, i16 42 seq_cst
103*67e74705SXin Li   b += 42;
104*67e74705SXin Li   i += 42;
105*67e74705SXin Li   l += 42;
106*67e74705SXin Li   s += 42;
107*67e74705SXin Li }
108*67e74705SXin Li // CHECK: testsubeq
testsubeq(void)109*67e74705SXin Li void testsubeq(void)
110*67e74705SXin Li {
111*67e74705SXin Li   // CHECK: call arm_aapcscc zeroext i1 @__atomic_compare_exchange(i32 1, i8* @b
112*67e74705SXin Li   // CHECK: atomicrmw sub i32* @i, i32 42 seq_cst
113*67e74705SXin Li   // CHECK: atomicrmw sub i64* @l, i64 42 seq_cst
114*67e74705SXin Li   // CHECK: atomicrmw sub i16* @s, i16 42 seq_cst
115*67e74705SXin Li   b -= 42;
116*67e74705SXin Li   i -= 42;
117*67e74705SXin Li   l -= 42;
118*67e74705SXin Li   s -= 42;
119*67e74705SXin Li }
120*67e74705SXin Li // CHECK: testxoreq
testxoreq(void)121*67e74705SXin Li void testxoreq(void)
122*67e74705SXin Li {
123*67e74705SXin Li   // CHECK: call arm_aapcscc zeroext i1 @__atomic_compare_exchange(i32 1, i8* @b
124*67e74705SXin Li   // CHECK: atomicrmw xor i32* @i, i32 42 seq_cst
125*67e74705SXin Li   // CHECK: atomicrmw xor i64* @l, i64 42 seq_cst
126*67e74705SXin Li   // CHECK: atomicrmw xor i16* @s, i16 42 seq_cst
127*67e74705SXin Li   b ^= 42;
128*67e74705SXin Li   i ^= 42;
129*67e74705SXin Li   l ^= 42;
130*67e74705SXin Li   s ^= 42;
131*67e74705SXin Li }
132*67e74705SXin Li // CHECK: testoreq
testoreq(void)133*67e74705SXin Li void testoreq(void)
134*67e74705SXin Li {
135*67e74705SXin Li   // CHECK: call arm_aapcscc zeroext i1 @__atomic_compare_exchange(i32 1, i8* @b
136*67e74705SXin Li   // CHECK: atomicrmw or i32* @i, i32 42 seq_cst
137*67e74705SXin Li   // CHECK: atomicrmw or i64* @l, i64 42 seq_cst
138*67e74705SXin Li   // CHECK: atomicrmw or i16* @s, i16 42 seq_cst
139*67e74705SXin Li   b |= 42;
140*67e74705SXin Li   i |= 42;
141*67e74705SXin Li   l |= 42;
142*67e74705SXin Li   s |= 42;
143*67e74705SXin Li }
144*67e74705SXin Li // CHECK: testandeq
testandeq(void)145*67e74705SXin Li void testandeq(void)
146*67e74705SXin Li {
147*67e74705SXin Li   // CHECK: call arm_aapcscc zeroext i1 @__atomic_compare_exchange(i32 1, i8* @b
148*67e74705SXin Li   // CHECK: atomicrmw and i32* @i, i32 42 seq_cst
149*67e74705SXin Li   // CHECK: atomicrmw and i64* @l, i64 42 seq_cst
150*67e74705SXin Li   // CHECK: atomicrmw and i16* @s, i16 42 seq_cst
151*67e74705SXin Li   b &= 42;
152*67e74705SXin Li   i &= 42;
153*67e74705SXin Li   l &= 42;
154*67e74705SXin Li   s &= 42;
155*67e74705SXin Li }
156*67e74705SXin Li 
157*67e74705SXin Li // CHECK-LABEL: define arm_aapcscc void @testFloat(float*
testFloat(_Atomic (float)* fp)158*67e74705SXin Li void testFloat(_Atomic(float) *fp) {
159*67e74705SXin Li // CHECK:      [[FP:%.*]] = alloca float*
160*67e74705SXin Li // CHECK-NEXT: [[X:%.*]] = alloca float
161*67e74705SXin Li // CHECK-NEXT: [[F:%.*]] = alloca float
162*67e74705SXin Li // CHECK-NEXT: [[TMP0:%.*]] = alloca float
163*67e74705SXin Li // CHECK-NEXT: [[TMP1:%.*]] = alloca float
164*67e74705SXin Li // CHECK-NEXT: store float* {{%.*}}, float** [[FP]]
165*67e74705SXin Li 
166*67e74705SXin Li // CHECK-NEXT: [[T0:%.*]] = load float*, float** [[FP]]
167*67e74705SXin Li // CHECK-NEXT: store float 1.000000e+00, float* [[T0]], align 4
168*67e74705SXin Li   __c11_atomic_init(fp, 1.0f);
169*67e74705SXin Li 
170*67e74705SXin Li // CHECK-NEXT: store float 2.000000e+00, float* [[X]], align 4
171*67e74705SXin Li   _Atomic(float) x = 2.0f;
172*67e74705SXin Li 
173*67e74705SXin Li // CHECK-NEXT: [[T0:%.*]] = load float*, float** [[FP]]
174*67e74705SXin Li // CHECK-NEXT: [[T1:%.*]] = bitcast float* [[T0]] to i8*
175*67e74705SXin Li // CHECK-NEXT: [[T2:%.*]] = bitcast float* [[TMP0]] to i8*
176*67e74705SXin Li // CHECK-NEXT: call arm_aapcscc void @__atomic_load(i32 4, i8* [[T1]], i8* [[T2]], i32 5)
177*67e74705SXin Li // CHECK-NEXT: [[T3:%.*]] = load float, float* [[TMP0]], align 4
178*67e74705SXin Li // CHECK-NEXT: store float [[T3]], float* [[F]]
179*67e74705SXin Li   float f = *fp;
180*67e74705SXin Li 
181*67e74705SXin Li // CHECK-NEXT: [[T0:%.*]] = load float, float* [[F]], align 4
182*67e74705SXin Li // CHECK-NEXT: [[T1:%.*]] = load float*, float** [[FP]], align 4
183*67e74705SXin Li // CHECK-NEXT: store float [[T0]], float* [[TMP1]], align 4
184*67e74705SXin Li // CHECK-NEXT: [[T2:%.*]] = bitcast float* [[T1]] to i8*
185*67e74705SXin Li // CHECK-NEXT: [[T3:%.*]] = bitcast float* [[TMP1]] to i8*
186*67e74705SXin Li // CHECK-NEXT: call arm_aapcscc void @__atomic_store(i32 4, i8* [[T2]], i8* [[T3]], i32 5)
187*67e74705SXin Li   *fp = f;
188*67e74705SXin Li 
189*67e74705SXin Li // CHECK-NEXT: ret void
190*67e74705SXin Li }
191*67e74705SXin Li 
192*67e74705SXin Li // CHECK: define arm_aapcscc void @testComplexFloat([[CF:{ float, float }]]*
testComplexFloat(_Atomic (_Complex float)* fp)193*67e74705SXin Li void testComplexFloat(_Atomic(_Complex float) *fp) {
194*67e74705SXin Li // CHECK:      [[FP:%.*]] = alloca [[CF]]*, align 4
195*67e74705SXin Li // CHECK-NEXT: [[X:%.*]] = alloca [[CF]], align 8
196*67e74705SXin Li // CHECK-NEXT: [[F:%.*]] = alloca [[CF]], align 4
197*67e74705SXin Li // CHECK-NEXT: [[TMP0:%.*]] = alloca [[CF]], align 8
198*67e74705SXin Li // CHECK-NEXT: [[TMP1:%.*]] = alloca [[CF]], align 8
199*67e74705SXin Li // CHECK-NEXT: store [[CF]]*
200*67e74705SXin Li 
201*67e74705SXin Li // CHECK-NEXT: [[P:%.*]] = load [[CF]]*, [[CF]]** [[FP]]
202*67e74705SXin Li // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[CF]], [[CF]]* [[P]], i32 0, i32 0
203*67e74705SXin Li // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[CF]], [[CF]]* [[P]], i32 0, i32 1
204*67e74705SXin Li // CHECK-NEXT: store float 1.000000e+00, float* [[T0]]
205*67e74705SXin Li // CHECK-NEXT: store float 0.000000e+00, float* [[T1]]
206*67e74705SXin Li   __c11_atomic_init(fp, 1.0f);
207*67e74705SXin Li 
208*67e74705SXin Li // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[CF]], [[CF]]* [[X]], i32 0, i32 0
209*67e74705SXin Li // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[CF]], [[CF]]* [[X]], i32 0, i32 1
210*67e74705SXin Li // CHECK-NEXT: store float 2.000000e+00, float* [[T0]]
211*67e74705SXin Li // CHECK-NEXT: store float 0.000000e+00, float* [[T1]]
212*67e74705SXin Li   _Atomic(_Complex float) x = 2.0f;
213*67e74705SXin Li 
214*67e74705SXin Li // CHECK-NEXT: [[T0:%.*]] = load [[CF]]*, [[CF]]** [[FP]]
215*67e74705SXin Li // CHECK-NEXT: [[T1:%.*]] = bitcast [[CF]]* [[T0]] to i8*
216*67e74705SXin Li // CHECK-NEXT: [[T2:%.*]] = bitcast [[CF]]* [[TMP0]] to i8*
217*67e74705SXin Li // CHECK-NEXT: call arm_aapcscc void @__atomic_load(i32 8, i8* [[T1]], i8* [[T2]], i32 5)
218*67e74705SXin Li // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[CF]], [[CF]]* [[TMP0]], i32 0, i32 0
219*67e74705SXin Li // CHECK-NEXT: [[R:%.*]] = load float, float* [[T0]]
220*67e74705SXin Li // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[CF]], [[CF]]* [[TMP0]], i32 0, i32 1
221*67e74705SXin Li // CHECK-NEXT: [[I:%.*]] = load float, float* [[T0]]
222*67e74705SXin Li // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[CF]], [[CF]]* [[F]], i32 0, i32 0
223*67e74705SXin Li // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[CF]], [[CF]]* [[F]], i32 0, i32 1
224*67e74705SXin Li // CHECK-NEXT: store float [[R]], float* [[T0]]
225*67e74705SXin Li // CHECK-NEXT: store float [[I]], float* [[T1]]
226*67e74705SXin Li   _Complex float f = *fp;
227*67e74705SXin Li 
228*67e74705SXin Li // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[CF]], [[CF]]* [[F]], i32 0, i32 0
229*67e74705SXin Li // CHECK-NEXT: [[R:%.*]] = load float, float* [[T0]]
230*67e74705SXin Li // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[CF]], [[CF]]* [[F]], i32 0, i32 1
231*67e74705SXin Li // CHECK-NEXT: [[I:%.*]] = load float, float* [[T0]]
232*67e74705SXin Li // CHECK-NEXT: [[DEST:%.*]] = load [[CF]]*, [[CF]]** [[FP]], align 4
233*67e74705SXin Li // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[CF]], [[CF]]* [[TMP1]], i32 0, i32 0
234*67e74705SXin Li // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[CF]], [[CF]]* [[TMP1]], i32 0, i32 1
235*67e74705SXin Li // CHECK-NEXT: store float [[R]], float* [[T0]]
236*67e74705SXin Li // CHECK-NEXT: store float [[I]], float* [[T1]]
237*67e74705SXin Li // CHECK-NEXT: [[T0:%.*]] = bitcast [[CF]]* [[DEST]] to i8*
238*67e74705SXin Li // CHECK-NEXT: [[T1:%.*]] = bitcast [[CF]]* [[TMP1]] to i8*
239*67e74705SXin Li // CHECK-NEXT: call arm_aapcscc void @__atomic_store(i32 8, i8* [[T0]], i8* [[T1]], i32 5)
240*67e74705SXin Li   *fp = f;
241*67e74705SXin Li 
242*67e74705SXin Li // CHECK-NEXT: ret void
243*67e74705SXin Li }
244*67e74705SXin Li 
245*67e74705SXin Li typedef struct { short x, y, z, w; } S;
246*67e74705SXin Li _Atomic S testStructGlobal = (S){1, 2, 3, 4};
247*67e74705SXin Li // CHECK: define arm_aapcscc void @testStruct([[S:.*]]*
testStruct(_Atomic (S)* fp)248*67e74705SXin Li void testStruct(_Atomic(S) *fp) {
249*67e74705SXin Li // CHECK:      [[FP:%.*]] = alloca [[S]]*, align 4
250*67e74705SXin Li // CHECK-NEXT: [[X:%.*]] = alloca [[S]], align 8
251*67e74705SXin Li // CHECK-NEXT: [[F:%.*]] = alloca [[S:%.*]], align 2
252*67e74705SXin Li // CHECK-NEXT: [[TMP0:%.*]] = alloca [[S]], align 8
253*67e74705SXin Li // CHECK-NEXT: store [[S]]*
254*67e74705SXin Li 
255*67e74705SXin Li // CHECK-NEXT: [[P:%.*]] = load [[S]]*, [[S]]** [[FP]]
256*67e74705SXin Li // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[S]], [[S]]* [[P]], i32 0, i32 0
257*67e74705SXin Li // CHECK-NEXT: store i16 1, i16* [[T0]], align 8
258*67e74705SXin Li // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[S]], [[S]]* [[P]], i32 0, i32 1
259*67e74705SXin Li // CHECK-NEXT: store i16 2, i16* [[T0]], align 2
260*67e74705SXin Li // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[S]], [[S]]* [[P]], i32 0, i32 2
261*67e74705SXin Li // CHECK-NEXT: store i16 3, i16* [[T0]], align 4
262*67e74705SXin Li // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[S]], [[S]]* [[P]], i32 0, i32 3
263*67e74705SXin Li // CHECK-NEXT: store i16 4, i16* [[T0]], align 2
264*67e74705SXin Li   __c11_atomic_init(fp, (S){1,2,3,4});
265*67e74705SXin Li 
266*67e74705SXin Li // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[S]], [[S]]* [[X]], i32 0, i32 0
267*67e74705SXin Li // CHECK-NEXT: store i16 1, i16* [[T0]], align 8
268*67e74705SXin Li // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[S]], [[S]]* [[X]], i32 0, i32 1
269*67e74705SXin Li // CHECK-NEXT: store i16 2, i16* [[T0]], align 2
270*67e74705SXin Li // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[S]], [[S]]* [[X]], i32 0, i32 2
271*67e74705SXin Li // CHECK-NEXT: store i16 3, i16* [[T0]], align 4
272*67e74705SXin Li // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[S]], [[S]]* [[X]], i32 0, i32 3
273*67e74705SXin Li // CHECK-NEXT: store i16 4, i16* [[T0]], align 2
274*67e74705SXin Li   _Atomic(S) x = (S){1,2,3,4};
275*67e74705SXin Li 
276*67e74705SXin Li // CHECK-NEXT: [[T0:%.*]] = load [[S]]*, [[S]]** [[FP]]
277*67e74705SXin Li // CHECK-NEXT: [[T1:%.*]] = bitcast [[S]]* [[T0]] to i8*
278*67e74705SXin Li // CHECK-NEXT: [[T2:%.*]] = bitcast [[S]]* [[F]] to i8*
279*67e74705SXin Li // CHECK-NEXT: call arm_aapcscc void @__atomic_load(i32 8, i8* [[T1]], i8* [[T2]], i32 5)
280*67e74705SXin Li   S f = *fp;
281*67e74705SXin Li 
282*67e74705SXin Li // CHECK-NEXT: [[T0:%.*]] = load [[S]]*, [[S]]** [[FP]]
283*67e74705SXin Li // CHECK-NEXT: [[T1:%.*]] = bitcast [[S]]* [[TMP0]] to i8*
284*67e74705SXin Li // CHECK-NEXT: [[T2:%.*]] = bitcast [[S]]* [[F]] to i8*
285*67e74705SXin Li // CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[T1]], i8* [[T2]], i32 8, i32 2, i1 false)
286*67e74705SXin Li // CHECK-NEXT: [[T3:%.*]] = bitcast [[S]]* [[T0]] to i8*
287*67e74705SXin Li // CHECK-NEXT: [[T4:%.*]] = bitcast [[S]]* [[TMP0]] to i8*
288*67e74705SXin Li // CHECK-NEXT: call arm_aapcscc void @__atomic_store(i32 8, i8* [[T3]], i8* [[T4]], i32 5)
289*67e74705SXin Li   *fp = f;
290*67e74705SXin Li 
291*67e74705SXin Li // CHECK-NEXT: ret void
292*67e74705SXin Li }
293*67e74705SXin Li 
294*67e74705SXin Li typedef struct { short x, y, z; } PS;
295*67e74705SXin Li _Atomic PS testPromotedStructGlobal = (PS){1, 2, 3};
296*67e74705SXin Li // CHECK: define arm_aapcscc void @testPromotedStruct([[APS:.*]]*
testPromotedStruct(_Atomic (PS)* fp)297*67e74705SXin Li void testPromotedStruct(_Atomic(PS) *fp) {
298*67e74705SXin Li // CHECK:      [[FP:%.*]] = alloca [[APS]]*, align 4
299*67e74705SXin Li // CHECK-NEXT: [[X:%.*]] = alloca [[APS]], align 8
300*67e74705SXin Li // CHECK-NEXT: [[F:%.*]] = alloca [[PS:%.*]], align 2
301*67e74705SXin Li // CHECK-NEXT: [[TMP0:%.*]] = alloca [[APS]], align 8
302*67e74705SXin Li // CHECK-NEXT: [[TMP1:%.*]] = alloca [[APS]], align 8
303*67e74705SXin Li // CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
304*67e74705SXin Li // CHECK-NEXT: [[TMP2:%.*]] = alloca %struct.PS, align 2
305*67e74705SXin Li // CHECK-NEXT: [[TMP3:%.*]] = alloca [[APS]], align 8
306*67e74705SXin Li // CHECK-NEXT: store [[APS]]*
307*67e74705SXin Li 
308*67e74705SXin Li // CHECK-NEXT: [[P:%.*]] = load [[APS]]*, [[APS]]** [[FP]]
309*67e74705SXin Li // CHECK-NEXT: [[T0:%.*]] = bitcast [[APS]]* [[P]] to i8*
310*67e74705SXin Li // CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* [[T0]], i8 0, i64 8, i32 8, i1 false)
311*67e74705SXin Li // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[APS]], [[APS]]* [[P]], i32 0, i32 0
312*67e74705SXin Li // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[PS]], [[PS]]* [[T0]], i32 0, i32 0
313*67e74705SXin Li // CHECK-NEXT: store i16 1, i16* [[T1]], align 8
314*67e74705SXin Li // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[PS]], [[PS]]* [[T0]], i32 0, i32 1
315*67e74705SXin Li // CHECK-NEXT: store i16 2, i16* [[T1]], align 2
316*67e74705SXin Li // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[PS]], [[PS]]* [[T0]], i32 0, i32 2
317*67e74705SXin Li // CHECK-NEXT: store i16 3, i16* [[T1]], align 4
318*67e74705SXin Li   __c11_atomic_init(fp, (PS){1,2,3});
319*67e74705SXin Li 
320*67e74705SXin Li // CHECK-NEXT: [[T0:%.*]] = bitcast [[APS]]* [[X]] to i8*
321*67e74705SXin Li // CHECK-NEXT: call void @llvm.memset.p0i8.i32(i8* [[T0]], i8 0, i32 8, i32 8, i1 false)
322*67e74705SXin Li // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[APS]], [[APS]]* [[X]], i32 0, i32 0
323*67e74705SXin Li // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[PS]], [[PS]]* [[T0]], i32 0, i32 0
324*67e74705SXin Li // CHECK-NEXT: store i16 1, i16* [[T1]], align 8
325*67e74705SXin Li // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[PS]], [[PS]]* [[T0]], i32 0, i32 1
326*67e74705SXin Li // CHECK-NEXT: store i16 2, i16* [[T1]], align 2
327*67e74705SXin Li // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[PS]], [[PS]]* [[T0]], i32 0, i32 2
328*67e74705SXin Li // CHECK-NEXT: store i16 3, i16* [[T1]], align 4
329*67e74705SXin Li   _Atomic(PS) x = (PS){1,2,3};
330*67e74705SXin Li 
331*67e74705SXin Li // CHECK-NEXT: [[T0:%.*]] = load [[APS]]*, [[APS]]** [[FP]]
332*67e74705SXin Li // CHECK-NEXT: [[T1:%.*]] = bitcast [[APS]]* [[T0]] to i8*
333*67e74705SXin Li // CHECK-NEXT: [[T2:%.*]] = bitcast [[APS]]* [[TMP0]] to i8*
334*67e74705SXin Li // CHECK-NEXT: call arm_aapcscc void @__atomic_load(i32 8, i8* [[T1]], i8* [[T2]], i32 5)
335*67e74705SXin Li // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[APS]], [[APS]]* [[TMP0]], i32 0, i32 0
336*67e74705SXin Li // CHECK-NEXT: [[T1:%.*]] = bitcast [[PS]]* [[F]] to i8*
337*67e74705SXin Li // CHECK-NEXT: [[T2:%.*]] = bitcast [[PS]]* [[T0]] to i8*
338*67e74705SXin Li // CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[T1]], i8* [[T2]], i32 6, i32 2, i1 false)
339*67e74705SXin Li   PS f = *fp;
340*67e74705SXin Li 
341*67e74705SXin Li // CHECK-NEXT: [[T0:%.*]] = load [[APS]]*, [[APS]]** [[FP]]
342*67e74705SXin Li // CHECK-NEXT: [[T1:%.*]] = bitcast { %struct.PS, [2 x i8] }* [[TMP1]] to i8*
343*67e74705SXin Li // CHECK-NEXT: call void @llvm.memset.p0i8.i32(i8* [[T1]], i8 0, i32 8, i32 8, i1 false)
344*67e74705SXin Li // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[APS]], [[APS]]* [[TMP1]], i32 0, i32 0
345*67e74705SXin Li // CHECK-NEXT: [[T2:%.*]] = bitcast [[PS]]* [[T1]] to i8*
346*67e74705SXin Li // CHECK-NEXT: [[T3:%.*]] = bitcast [[PS]]* [[F]] to i8*
347*67e74705SXin Li // CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[T2]], i8* [[T3]], i32 6, i32 2, i1 false)
348*67e74705SXin Li // CHECK-NEXT: [[T4:%.*]] = bitcast [[APS]]* [[T0]] to i8*
349*67e74705SXin Li // CHECK-NEXT: [[T5:%.*]] = bitcast [[APS]]* [[TMP1]] to i8*
350*67e74705SXin Li // CHECK-NEXT: call arm_aapcscc void @__atomic_store(i32 8, i8* [[T4]], i8* [[T5]], i32 5)
351*67e74705SXin Li   *fp = f;
352*67e74705SXin Li 
353*67e74705SXin Li // CHECK-NEXT: [[T0:%.*]] = load [[APS]]*, [[APS]]** [[FP]], align 4
354*67e74705SXin Li // CHECK-NEXT: [[T1:%.*]] = bitcast [[APS]]* [[T0]] to i8*
355*67e74705SXin Li // CHECK-NEXT: [[T2:%.*]] = bitcast [[APS]]* [[TMP3]] to i8*
356*67e74705SXin Li // CHECK-NEXT: call arm_aapcscc void @__atomic_load(i32 8, i8* [[T1]], i8* [[T2]], i32 5)
357*67e74705SXin Li // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[APS]], [[APS]]* [[TMP3]], i32 0, i32 0
358*67e74705SXin Li // CHECK-NEXT: [[T1:%.*]] = bitcast %struct.PS* [[TMP2]] to i8*
359*67e74705SXin Li // CHECK-NEXT: [[T2:%.*]] = bitcast %struct.PS* [[T0]] to i8*
360*67e74705SXin Li // CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[T1]], i8* [[T2]], i32 6, i32 2, i1 false)
361*67e74705SXin Li // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds %struct.PS, %struct.PS* [[TMP2]], i32 0, i32 0
362*67e74705SXin Li // CHECK-NEXT: [[T1:%.*]] = load i16, i16* [[T0]], align 2
363*67e74705SXin Li // CHECK-NEXT: [[T2:%.*]] = sext i16 [[T1]] to i32
364*67e74705SXin Li // CHECK-NEXT: store i32 [[T2]], i32* [[A]], align 4
365*67e74705SXin Li   int a = ((PS)*fp).x;
366*67e74705SXin Li 
367*67e74705SXin Li // CHECK-NEXT: ret void
368*67e74705SXin Li }
369*67e74705SXin Li 
test_promoted_load(_Atomic (PS)* addr)370*67e74705SXin Li PS test_promoted_load(_Atomic(PS) *addr) {
371*67e74705SXin Li   // CHECK-LABEL: @test_promoted_load(%struct.PS* noalias sret %agg.result, { %struct.PS, [2 x i8] }* %addr)
372*67e74705SXin Li   // CHECK:   [[ADDR_ARG:%.*]] = alloca { %struct.PS, [2 x i8] }*, align 4
373*67e74705SXin Li   // CHECK:   [[ATOMIC_RES:%.*]] = alloca { %struct.PS, [2 x i8] }, align 8
374*67e74705SXin Li   // CHECK:   store { %struct.PS, [2 x i8] }* %addr, { %struct.PS, [2 x i8] }** [[ADDR_ARG]], align 4
375*67e74705SXin Li   // CHECK:   [[ADDR:%.*]] = load { %struct.PS, [2 x i8] }*, { %struct.PS, [2 x i8] }** [[ADDR_ARG]], align 4
376*67e74705SXin Li   // CHECK:   [[ADDR64:%.*]] = bitcast { %struct.PS, [2 x i8] }* [[ADDR]] to i64*
377*67e74705SXin Li   // CHECK:   [[ATOMIC_RES64:%.*]] = bitcast { %struct.PS, [2 x i8] }* [[ATOMIC_RES]] to i64*
378*67e74705SXin Li   // CHECK:   [[ADDR8:%.*]] = bitcast i64* [[ADDR64]] to i8*
379*67e74705SXin Li   // CHECK:   [[RES:%.*]] = call arm_aapcscc i64 @__atomic_load_8(i8* [[ADDR8]], i32 5)
380*67e74705SXin Li   // CHECK:   store i64 [[RES]], i64* [[ATOMIC_RES64]], align 8
381*67e74705SXin Li   // CHECK:   [[ATOMIC_RES_STRUCT:%.*]] = bitcast i64* [[ATOMIC_RES64]] to %struct.PS*
382*67e74705SXin Li   // CHECK:   [[AGG_RESULT8:%.*]] = bitcast %struct.PS* %agg.result to i8*
383*67e74705SXin Li   // CHECK:   [[ATOMIC_RES8:%.*]] = bitcast %struct.PS* [[ATOMIC_RES_STRUCT]] to i8*
384*67e74705SXin Li   // CHECK:   call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[AGG_RESULT8]], i8* [[ATOMIC_RES8]], i32 6, i32 2, i1 false)
385*67e74705SXin Li 
386*67e74705SXin Li   return __c11_atomic_load(addr, 5);
387*67e74705SXin Li }
388*67e74705SXin Li 
test_promoted_store(_Atomic (PS)* addr,PS * val)389*67e74705SXin Li void test_promoted_store(_Atomic(PS) *addr, PS *val) {
390*67e74705SXin Li   // CHECK-LABEL: @test_promoted_store({ %struct.PS, [2 x i8] }* %addr, %struct.PS* %val)
391*67e74705SXin Li   // CHECK:   [[ADDR_ARG:%.*]] = alloca { %struct.PS, [2 x i8] }*, align 4
392*67e74705SXin Li   // CHECK:   [[VAL_ARG:%.*]] = alloca %struct.PS*, align 4
393*67e74705SXin Li   // CHECK:   [[NONATOMIC_TMP:%.*]] = alloca %struct.PS, align 2
394*67e74705SXin Li   // CHECK:   [[ATOMIC_VAL:%.*]] = alloca { %struct.PS, [2 x i8] }, align 8
395*67e74705SXin Li   // CHECK:   store { %struct.PS, [2 x i8] }* %addr, { %struct.PS, [2 x i8] }** [[ADDR_ARG]], align 4
396*67e74705SXin Li   // CHECK:   store %struct.PS* %val, %struct.PS** [[VAL_ARG]], align 4
397*67e74705SXin Li   // CHECK:   [[ADDR:%.*]] = load { %struct.PS, [2 x i8] }*, { %struct.PS, [2 x i8] }** [[ADDR_ARG]], align 4
398*67e74705SXin Li   // CHECK:   [[VAL:%.*]] = load %struct.PS*, %struct.PS** [[VAL_ARG]], align 4
399*67e74705SXin Li   // CHECK:   [[NONATOMIC_TMP8:%.*]] = bitcast %struct.PS* [[NONATOMIC_TMP]] to i8*
400*67e74705SXin Li   // CHECK:   [[VAL8:%.*]] = bitcast %struct.PS* [[VAL]] to i8*
401*67e74705SXin Li   // CHECK:   call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[NONATOMIC_TMP8]], i8* [[VAL8]], i32 6, i32 2, i1 false)
402*67e74705SXin Li   // CHECK:   [[ADDR64:%.*]] = bitcast { %struct.PS, [2 x i8] }* [[ADDR]] to i64*
403*67e74705SXin Li   // CHECK:   [[ATOMIC_VAL8:%.*]] = bitcast { %struct.PS, [2 x i8] }* [[ATOMIC_VAL]] to i8*
404*67e74705SXin Li   // CHECK:   [[NONATOMIC_TMP8:%.*]] = bitcast %struct.PS* [[NONATOMIC_TMP]] to i8*
405*67e74705SXin Li   // CHECK:   call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[ATOMIC_VAL8]], i8* [[NONATOMIC_TMP8]], i64 6, i32 2, i1 false)
406*67e74705SXin Li   // CHECK:   [[ATOMIC_VAL64:%.*]] = bitcast { %struct.PS, [2 x i8] }* [[ATOMIC_VAL]] to i64*
407*67e74705SXin Li   // CHECK:   [[ADDR8:%.*]] = bitcast i64* [[ADDR64]] to i8*
408*67e74705SXin Li   // CHECK:   [[VAL64:%.*]] = load i64, i64* [[ATOMIC_VAL64]], align 2
409*67e74705SXin Li   // CHECK:   call arm_aapcscc void @__atomic_store_8(i8* [[ADDR8]], i64 [[VAL64]], i32 5)
410*67e74705SXin Li   __c11_atomic_store(addr, *val, 5);
411*67e74705SXin Li }
412*67e74705SXin Li 
test_promoted_exchange(_Atomic (PS)* addr,PS * val)413*67e74705SXin Li PS test_promoted_exchange(_Atomic(PS) *addr, PS *val) {
414*67e74705SXin Li   // CHECK-LABEL: @test_promoted_exchange(%struct.PS* noalias sret %agg.result, { %struct.PS, [2 x i8] }* %addr, %struct.PS* %val)
415*67e74705SXin Li   // CHECK:   [[ADDR_ARG:%.*]] = alloca { %struct.PS, [2 x i8] }*, align 4
416*67e74705SXin Li   // CHECK:   [[VAL_ARG:%.*]] = alloca %struct.PS*, align 4
417*67e74705SXin Li   // CHECK:   [[NONATOMIC_TMP:%.*]] = alloca %struct.PS, align 2
418*67e74705SXin Li   // CHECK:   [[ATOMIC_VAL:%.*]] = alloca { %struct.PS, [2 x i8] }, align 8
419*67e74705SXin Li   // CHECK:   [[ATOMIC_RES:%.*]] = alloca { %struct.PS, [2 x i8] }, align 8
420*67e74705SXin Li   // CHECK:   store { %struct.PS, [2 x i8] }* %addr, { %struct.PS, [2 x i8] }** [[ADDR_ARG]], align 4
421*67e74705SXin Li   // CHECK:   store %struct.PS* %val, %struct.PS** [[VAL_ARG]], align 4
422*67e74705SXin Li   // CHECK:   [[ADDR:%.*]] = load { %struct.PS, [2 x i8] }*, { %struct.PS, [2 x i8] }** [[ADDR_ARG]], align 4
423*67e74705SXin Li   // CHECK:   [[VAL:%.*]] = load %struct.PS*, %struct.PS** [[VAL_ARG]], align 4
424*67e74705SXin Li   // CHECK:   [[NONATOMIC_TMP8:%.*]] = bitcast %struct.PS* [[NONATOMIC_TMP]] to i8*
425*67e74705SXin Li   // CHECK:   [[VAL8:%.*]] = bitcast %struct.PS* [[VAL]] to i8*
426*67e74705SXin Li   // CHECK:   call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[NONATOMIC_TMP8]], i8* [[VAL8]], i32 6, i32 2, i1 false)
427*67e74705SXin Li   // CHECK:   [[ADDR64:%.*]] = bitcast { %struct.PS, [2 x i8] }* [[ADDR]] to i64*
428*67e74705SXin Li   // CHECK:   [[ATOMIC_VAL8:%.*]] = bitcast { %struct.PS, [2 x i8] }* [[ATOMIC_VAL]] to i8*
429*67e74705SXin Li   // CHECK:   [[NONATOMIC_TMP8:%.*]] = bitcast %struct.PS* [[NONATOMIC_TMP]] to i8*
430*67e74705SXin Li   // CHECK:   call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[ATOMIC_VAL8]], i8* [[NONATOMIC_TMP8]], i64 6, i32 2, i1 false)
431*67e74705SXin Li   // CHECK:   [[ATOMIC_VAL64:%.*]] = bitcast { %struct.PS, [2 x i8] }* [[ATOMIC_VAL]] to i64*
432*67e74705SXin Li   // CHECK:   [[ATOMIC_RES64:%.*]] = bitcast { %struct.PS, [2 x i8] }* [[ATOMIC_RES]] to i64*
433*67e74705SXin Li   // CHECK:   [[ADDR8:%.*]] = bitcast i64* [[ADDR64]] to i8*
434*67e74705SXin Li   // CHECK:   [[VAL64:%.*]] = load i64, i64* [[ATOMIC_VAL64]], align 2
435*67e74705SXin Li   // CHECK:   [[RES:%.*]] = call arm_aapcscc i64 @__atomic_exchange_8(i8* [[ADDR8]], i64 [[VAL64]], i32 5)
436*67e74705SXin Li   // CHECK:   store i64 [[RES]], i64* [[ATOMIC_RES64]], align 8
437*67e74705SXin Li   // CHECK:   [[ATOMIC_RES_STRUCT:%.*]] = bitcast i64* [[ATOMIC_RES64]] to %struct.PS*
438*67e74705SXin Li   // CHECK:   [[AGG_RESULT8:%.*]] = bitcast %struct.PS* %agg.result to i8*
439*67e74705SXin Li   // CHECK:   [[ATOMIC_RES8:%.*]] = bitcast %struct.PS* [[ATOMIC_RES_STRUCT]] to i8*
440*67e74705SXin Li   // CHECK:   call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[AGG_RESULT8]], i8* [[ATOMIC_RES8]], i32 6, i32 2, i1 false)
441*67e74705SXin Li   return __c11_atomic_exchange(addr, *val, 5);
442*67e74705SXin Li }
443*67e74705SXin Li 
test_promoted_cmpxchg(_Atomic (PS)* addr,PS * desired,PS * new)444*67e74705SXin Li _Bool test_promoted_cmpxchg(_Atomic(PS) *addr, PS *desired, PS *new) {
445*67e74705SXin Li   // CHECK-LABEL: i1 @test_promoted_cmpxchg({ %struct.PS, [2 x i8] }* %addr, %struct.PS* %desired, %struct.PS* %new) #0 {
446*67e74705SXin Li   // CHECK:   [[ADDR_ARG:%.*]] = alloca { %struct.PS, [2 x i8] }*, align 4
447*67e74705SXin Li   // CHECK:   [[DESIRED_ARG:%.*]] = alloca %struct.PS*, align 4
448*67e74705SXin Li   // CHECK:   [[NEW_ARG:%.*]] = alloca %struct.PS*, align 4
449*67e74705SXin Li   // CHECK:   [[NONATOMIC_TMP:%.*]] = alloca %struct.PS, align 2
450*67e74705SXin Li   // CHECK:   [[ATOMIC_DESIRED:%.*]] = alloca { %struct.PS, [2 x i8] }, align 8
451*67e74705SXin Li   // CHECK:   [[ATOMIC_NEW:%.*]] = alloca { %struct.PS, [2 x i8] }, align 8
452*67e74705SXin Li   // CHECK:   store { %struct.PS, [2 x i8] }* %addr, { %struct.PS, [2 x i8] }** [[ADDR_ARG]], align 4
453*67e74705SXin Li   // CHECK:   store %struct.PS* %desired, %struct.PS** [[DESIRED_ARG]], align 4
454*67e74705SXin Li   // CHECK:   store %struct.PS* %new, %struct.PS** [[NEW_ARG]], align 4
455*67e74705SXin Li   // CHECK:   [[ADDR:%.*]] = load { %struct.PS, [2 x i8] }*, { %struct.PS, [2 x i8] }** [[ADDR_ARG]], align 4
456*67e74705SXin Li   // CHECK:   [[DESIRED:%.*]]= load %struct.PS*, %struct.PS** [[DESIRED_ARG]], align 4
457*67e74705SXin Li   // CHECK:   [[NEW:%.*]] = load %struct.PS*, %struct.PS** [[NEW_ARG]], align 4
458*67e74705SXin Li   // CHECK:   [[NONATOMIC_TMP8:%.*]] = bitcast %struct.PS* [[NONATOMIC_TMP]] to i8*
459*67e74705SXin Li   // CHECK:   [[NEW8:%.*]] = bitcast %struct.PS* [[NEW]] to i8*
460*67e74705SXin Li   // CHECK:   call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[NONATOMIC_TMP8]], i8* [[NEW8]], i32 6, i32 2, i1 false)
461*67e74705SXin Li   // CHECK:   [[ADDR64:%.*]] = bitcast { %struct.PS, [2 x i8] }* [[ADDR]] to i64*
462*67e74705SXin Li   // CHECK:   [[ATOMIC_DESIRED8:%.*]] = bitcast { %struct.PS, [2 x i8] }* [[ATOMIC_DESIRED]] to i8*
463*67e74705SXin Li   // CHECK:   [[DESIRED8:%.*]] = bitcast %struct.PS* [[DESIRED]]to i8*
464*67e74705SXin Li   // CHECK:   call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[ATOMIC_DESIRED8]], i8* [[DESIRED8]], i64 6, i32 2, i1 false)
465*67e74705SXin Li   // CHECK:   [[ATOMIC_DESIRED64:%.*]] = bitcast { %struct.PS, [2 x i8] }* [[ATOMIC_DESIRED]] to i64*
466*67e74705SXin Li   // CHECK:   [[ATOMIC_NEW8:%.*]] = bitcast { %struct.PS, [2 x i8] }* [[ATOMIC_NEW]] to i8*
467*67e74705SXin Li   // CHECK:   [[NONATOMIC_TMP8:%.*]] = bitcast %struct.PS* [[NONATOMIC_TMP]] to i8*
468*67e74705SXin Li   // CHECK:   call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[ATOMIC_NEW8]], i8* [[NONATOMIC_TMP8]], i64 6, i32 2, i1 false)
469*67e74705SXin Li   // CHECK:   [[ATOMIC_NEW64:%.*]] = bitcast { %struct.PS, [2 x i8] }* [[ATOMIC_NEW]] to i64*
470*67e74705SXin Li   // CHECK:   [[ADDR8:%.*]] = bitcast i64* [[ADDR64]] to i8*
471*67e74705SXin Li   // CHECK:   [[ATOMIC_DESIRED8:%.*]] = bitcast i64* [[ATOMIC_DESIRED64]] to i8*
472*67e74705SXin Li   // CHECK:   [[NEW64:%.*]] = load i64, i64* [[ATOMIC_NEW64]], align 2
473*67e74705SXin Li   // CHECK:   [[RES:%.*]] = call arm_aapcscc zeroext i1 @__atomic_compare_exchange_8(i8* [[ADDR8]], i8* [[ATOMIC_DESIRED8]], i64 [[NEW64]], i32 5, i32 5)
474*67e74705SXin Li   // CHECK:   ret i1 [[RES]]
475*67e74705SXin Li   return __c11_atomic_compare_exchange_strong(addr, desired, *new, 5, 5);
476*67e74705SXin Li }
477