1f4a2713aSLionel Sambuc // RUN: %clang_cc1 %s -emit-llvm -o - -triple=armv5-unknown-freebsd -std=c11 | FileCheck %s
2f4a2713aSLionel Sambuc
3f4a2713aSLionel Sambuc // Test that we are generating atomicrmw instructions, rather than
4f4a2713aSLionel Sambuc // compare-exchange loops for common atomic ops. This makes a big difference
5f4a2713aSLionel Sambuc // on RISC platforms, where the compare-exchange loop becomes a ll/sc pair for
6f4a2713aSLionel Sambuc // the load and then another ll/sc in the loop, expanding to about 30
7f4a2713aSLionel Sambuc // instructions when it should be only 4. It has a smaller, but still
8f4a2713aSLionel Sambuc // noticeable, impact on platforms like x86 and RISC-V, where there are atomic
9f4a2713aSLionel Sambuc // RMW instructions.
10f4a2713aSLionel Sambuc //
11f4a2713aSLionel Sambuc // We currently emit cmpxchg loops for most operations on _Bools, because
12f4a2713aSLionel Sambuc // they're sufficiently rare that it's not worth making sure that the semantics
13f4a2713aSLionel Sambuc // are correct.
14f4a2713aSLionel Sambuc
15*0a6a1f1dSLionel Sambuc // CHECK: @testStructGlobal = global {{.*}} { i16 1, i16 2, i16 3, i16 4 }
16*0a6a1f1dSLionel Sambuc // CHECK: @testPromotedStructGlobal = global {{.*}} { %{{.*}} { i16 1, i16 2, i16 3 }, [2 x i8] zeroinitializer }
17*0a6a1f1dSLionel Sambuc
18f4a2713aSLionel Sambuc typedef int __attribute__((vector_size(16))) vector;
19f4a2713aSLionel Sambuc
20f4a2713aSLionel Sambuc _Atomic(_Bool) b;
21f4a2713aSLionel Sambuc _Atomic(int) i;
22f4a2713aSLionel Sambuc _Atomic(long long) l;
23f4a2713aSLionel Sambuc _Atomic(short) s;
24f4a2713aSLionel Sambuc _Atomic(char*) p;
25f4a2713aSLionel Sambuc _Atomic(float) f;
26f4a2713aSLionel Sambuc _Atomic(vector) v;
27f4a2713aSLionel Sambuc
28f4a2713aSLionel Sambuc // CHECK: testinc
testinc(void)29f4a2713aSLionel Sambuc void testinc(void)
30f4a2713aSLionel Sambuc {
31f4a2713aSLionel Sambuc // Special case for suffix bool++, sets to true and returns the old value.
32f4a2713aSLionel Sambuc // CHECK: atomicrmw xchg i8* @b, i8 1 seq_cst
33f4a2713aSLionel Sambuc b++;
34f4a2713aSLionel Sambuc // CHECK: atomicrmw add i32* @i, i32 1 seq_cst
35f4a2713aSLionel Sambuc i++;
36f4a2713aSLionel Sambuc // CHECK: atomicrmw add i64* @l, i64 1 seq_cst
37f4a2713aSLionel Sambuc l++;
38f4a2713aSLionel Sambuc // CHECK: atomicrmw add i16* @s, i16 1 seq_cst
39f4a2713aSLionel Sambuc s++;
40f4a2713aSLionel Sambuc // Prefix increment
41f4a2713aSLionel Sambuc // Special case for bool: set to true and return true
42f4a2713aSLionel Sambuc // CHECK: store atomic i8 1, i8* @b seq_cst, align 1
43f4a2713aSLionel Sambuc ++b;
44f4a2713aSLionel Sambuc // Currently, we have no variant of atomicrmw that returns the new value, so
45f4a2713aSLionel Sambuc // we have to generate an atomic add, which returns the old value, and then a
46f4a2713aSLionel Sambuc // non-atomic add.
47f4a2713aSLionel Sambuc // CHECK: atomicrmw add i32* @i, i32 1 seq_cst
48f4a2713aSLionel Sambuc // CHECK: add i32
49f4a2713aSLionel Sambuc ++i;
50f4a2713aSLionel Sambuc // CHECK: atomicrmw add i64* @l, i64 1 seq_cst
51f4a2713aSLionel Sambuc // CHECK: add i64
52f4a2713aSLionel Sambuc ++l;
53f4a2713aSLionel Sambuc // CHECK: atomicrmw add i16* @s, i16 1 seq_cst
54f4a2713aSLionel Sambuc // CHECK: add i16
55f4a2713aSLionel Sambuc ++s;
56f4a2713aSLionel Sambuc }
57f4a2713aSLionel Sambuc // CHECK: testdec
testdec(void)58f4a2713aSLionel Sambuc void testdec(void)
59f4a2713aSLionel Sambuc {
60*0a6a1f1dSLionel Sambuc // CHECK: call arm_aapcscc zeroext i1 @__atomic_compare_exchange(i32 1, i8* @b
61f4a2713aSLionel Sambuc b--;
62f4a2713aSLionel Sambuc // CHECK: atomicrmw sub i32* @i, i32 1 seq_cst
63f4a2713aSLionel Sambuc i--;
64f4a2713aSLionel Sambuc // CHECK: atomicrmw sub i64* @l, i64 1 seq_cst
65f4a2713aSLionel Sambuc l--;
66f4a2713aSLionel Sambuc // CHECK: atomicrmw sub i16* @s, i16 1 seq_cst
67f4a2713aSLionel Sambuc s--;
68*0a6a1f1dSLionel Sambuc // CHECK: call arm_aapcscc zeroext i1 @__atomic_compare_exchange(i32 1, i8* @b
69f4a2713aSLionel Sambuc --b;
70f4a2713aSLionel Sambuc // CHECK: atomicrmw sub i32* @i, i32 1 seq_cst
71f4a2713aSLionel Sambuc // CHECK: sub i32
72f4a2713aSLionel Sambuc --i;
73f4a2713aSLionel Sambuc // CHECK: atomicrmw sub i64* @l, i64 1 seq_cst
74f4a2713aSLionel Sambuc // CHECK: sub i64
75f4a2713aSLionel Sambuc --l;
76f4a2713aSLionel Sambuc // CHECK: atomicrmw sub i16* @s, i16 1 seq_cst
77f4a2713aSLionel Sambuc // CHECK: sub i16
78f4a2713aSLionel Sambuc --s;
79f4a2713aSLionel Sambuc }
80f4a2713aSLionel Sambuc // CHECK: testaddeq
testaddeq(void)81f4a2713aSLionel Sambuc void testaddeq(void)
82f4a2713aSLionel Sambuc {
83*0a6a1f1dSLionel Sambuc // CHECK: call arm_aapcscc zeroext i1 @__atomic_compare_exchange(i32 1, i8* @b
84f4a2713aSLionel Sambuc // CHECK: atomicrmw add i32* @i, i32 42 seq_cst
85f4a2713aSLionel Sambuc // CHECK: atomicrmw add i64* @l, i64 42 seq_cst
86f4a2713aSLionel Sambuc // CHECK: atomicrmw add i16* @s, i16 42 seq_cst
87f4a2713aSLionel Sambuc b += 42;
88f4a2713aSLionel Sambuc i += 42;
89f4a2713aSLionel Sambuc l += 42;
90f4a2713aSLionel Sambuc s += 42;
91f4a2713aSLionel Sambuc }
92f4a2713aSLionel Sambuc // CHECK: testsubeq
testsubeq(void)93f4a2713aSLionel Sambuc void testsubeq(void)
94f4a2713aSLionel Sambuc {
95*0a6a1f1dSLionel Sambuc // CHECK: call arm_aapcscc zeroext i1 @__atomic_compare_exchange(i32 1, i8* @b
96f4a2713aSLionel Sambuc // CHECK: atomicrmw sub i32* @i, i32 42 seq_cst
97f4a2713aSLionel Sambuc // CHECK: atomicrmw sub i64* @l, i64 42 seq_cst
98f4a2713aSLionel Sambuc // CHECK: atomicrmw sub i16* @s, i16 42 seq_cst
99f4a2713aSLionel Sambuc b -= 42;
100f4a2713aSLionel Sambuc i -= 42;
101f4a2713aSLionel Sambuc l -= 42;
102f4a2713aSLionel Sambuc s -= 42;
103f4a2713aSLionel Sambuc }
104f4a2713aSLionel Sambuc // CHECK: testxoreq
testxoreq(void)105f4a2713aSLionel Sambuc void testxoreq(void)
106f4a2713aSLionel Sambuc {
107*0a6a1f1dSLionel Sambuc // CHECK: call arm_aapcscc zeroext i1 @__atomic_compare_exchange(i32 1, i8* @b
108f4a2713aSLionel Sambuc // CHECK: atomicrmw xor i32* @i, i32 42 seq_cst
109f4a2713aSLionel Sambuc // CHECK: atomicrmw xor i64* @l, i64 42 seq_cst
110f4a2713aSLionel Sambuc // CHECK: atomicrmw xor i16* @s, i16 42 seq_cst
111f4a2713aSLionel Sambuc b ^= 42;
112f4a2713aSLionel Sambuc i ^= 42;
113f4a2713aSLionel Sambuc l ^= 42;
114f4a2713aSLionel Sambuc s ^= 42;
115f4a2713aSLionel Sambuc }
116f4a2713aSLionel Sambuc // CHECK: testoreq
testoreq(void)117f4a2713aSLionel Sambuc void testoreq(void)
118f4a2713aSLionel Sambuc {
119*0a6a1f1dSLionel Sambuc // CHECK: call arm_aapcscc zeroext i1 @__atomic_compare_exchange(i32 1, i8* @b
120f4a2713aSLionel Sambuc // CHECK: atomicrmw or i32* @i, i32 42 seq_cst
121f4a2713aSLionel Sambuc // CHECK: atomicrmw or i64* @l, i64 42 seq_cst
122f4a2713aSLionel Sambuc // CHECK: atomicrmw or i16* @s, i16 42 seq_cst
123f4a2713aSLionel Sambuc b |= 42;
124f4a2713aSLionel Sambuc i |= 42;
125f4a2713aSLionel Sambuc l |= 42;
126f4a2713aSLionel Sambuc s |= 42;
127f4a2713aSLionel Sambuc }
128f4a2713aSLionel Sambuc // CHECK: testandeq
testandeq(void)129f4a2713aSLionel Sambuc void testandeq(void)
130f4a2713aSLionel Sambuc {
131*0a6a1f1dSLionel Sambuc // CHECK: call arm_aapcscc zeroext i1 @__atomic_compare_exchange(i32 1, i8* @b
132f4a2713aSLionel Sambuc // CHECK: atomicrmw and i32* @i, i32 42 seq_cst
133f4a2713aSLionel Sambuc // CHECK: atomicrmw and i64* @l, i64 42 seq_cst
134f4a2713aSLionel Sambuc // CHECK: atomicrmw and i16* @s, i16 42 seq_cst
135f4a2713aSLionel Sambuc b &= 42;
136f4a2713aSLionel Sambuc i &= 42;
137f4a2713aSLionel Sambuc l &= 42;
138f4a2713aSLionel Sambuc s &= 42;
139f4a2713aSLionel Sambuc }
140f4a2713aSLionel Sambuc
141f4a2713aSLionel Sambuc // CHECK-LABEL: define arm_aapcscc void @testFloat(float*
testFloat(_Atomic (float)* fp)142f4a2713aSLionel Sambuc void testFloat(_Atomic(float) *fp) {
143f4a2713aSLionel Sambuc // CHECK: [[FP:%.*]] = alloca float*
144f4a2713aSLionel Sambuc // CHECK-NEXT: [[X:%.*]] = alloca float
145f4a2713aSLionel Sambuc // CHECK-NEXT: [[F:%.*]] = alloca float
146f4a2713aSLionel Sambuc // CHECK-NEXT: [[TMP0:%.*]] = alloca float
147f4a2713aSLionel Sambuc // CHECK-NEXT: [[TMP1:%.*]] = alloca float
148f4a2713aSLionel Sambuc // CHECK-NEXT: store float* {{%.*}}, float** [[FP]]
149f4a2713aSLionel Sambuc
150f4a2713aSLionel Sambuc // CHECK-NEXT: [[T0:%.*]] = load float** [[FP]]
151f4a2713aSLionel Sambuc // CHECK-NEXT: store float 1.000000e+00, float* [[T0]], align 4
152f4a2713aSLionel Sambuc __c11_atomic_init(fp, 1.0f);
153f4a2713aSLionel Sambuc
154f4a2713aSLionel Sambuc // CHECK-NEXT: store float 2.000000e+00, float* [[X]], align 4
155f4a2713aSLionel Sambuc _Atomic(float) x = 2.0f;
156f4a2713aSLionel Sambuc
157f4a2713aSLionel Sambuc // CHECK-NEXT: [[T0:%.*]] = load float** [[FP]]
158f4a2713aSLionel Sambuc // CHECK-NEXT: [[T1:%.*]] = bitcast float* [[T0]] to i8*
159f4a2713aSLionel Sambuc // CHECK-NEXT: [[T2:%.*]] = bitcast float* [[TMP0]] to i8*
160f4a2713aSLionel Sambuc // CHECK-NEXT: call arm_aapcscc void @__atomic_load(i32 4, i8* [[T1]], i8* [[T2]], i32 5)
161f4a2713aSLionel Sambuc // CHECK-NEXT: [[T3:%.*]] = load float* [[TMP0]], align 4
162f4a2713aSLionel Sambuc // CHECK-NEXT: store float [[T3]], float* [[F]]
163f4a2713aSLionel Sambuc float f = *fp;
164f4a2713aSLionel Sambuc
165f4a2713aSLionel Sambuc // CHECK-NEXT: [[T0:%.*]] = load float* [[F]], align 4
166f4a2713aSLionel Sambuc // CHECK-NEXT: [[T1:%.*]] = load float** [[FP]], align 4
167f4a2713aSLionel Sambuc // CHECK-NEXT: store float [[T0]], float* [[TMP1]], align 4
168f4a2713aSLionel Sambuc // CHECK-NEXT: [[T2:%.*]] = bitcast float* [[T1]] to i8*
169f4a2713aSLionel Sambuc // CHECK-NEXT: [[T3:%.*]] = bitcast float* [[TMP1]] to i8*
170f4a2713aSLionel Sambuc // CHECK-NEXT: call arm_aapcscc void @__atomic_store(i32 4, i8* [[T2]], i8* [[T3]], i32 5)
171f4a2713aSLionel Sambuc *fp = f;
172f4a2713aSLionel Sambuc
173f4a2713aSLionel Sambuc // CHECK-NEXT: ret void
174f4a2713aSLionel Sambuc }
175f4a2713aSLionel Sambuc
176f4a2713aSLionel Sambuc // CHECK: define arm_aapcscc void @testComplexFloat([[CF:{ float, float }]]*
testComplexFloat(_Atomic (_Complex float)* fp)177f4a2713aSLionel Sambuc void testComplexFloat(_Atomic(_Complex float) *fp) {
178f4a2713aSLionel Sambuc // CHECK: [[FP:%.*]] = alloca [[CF]]*, align 4
179f4a2713aSLionel Sambuc // CHECK-NEXT: [[X:%.*]] = alloca [[CF]], align 8
180f4a2713aSLionel Sambuc // CHECK-NEXT: [[F:%.*]] = alloca [[CF]], align 4
181f4a2713aSLionel Sambuc // CHECK-NEXT: [[TMP0:%.*]] = alloca [[CF]], align 8
182f4a2713aSLionel Sambuc // CHECK-NEXT: [[TMP1:%.*]] = alloca [[CF]], align 8
183f4a2713aSLionel Sambuc // CHECK-NEXT: store [[CF]]*
184f4a2713aSLionel Sambuc
185f4a2713aSLionel Sambuc // CHECK-NEXT: [[P:%.*]] = load [[CF]]** [[FP]]
186f4a2713aSLionel Sambuc // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[CF]]* [[P]], i32 0, i32 0
187f4a2713aSLionel Sambuc // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[CF]]* [[P]], i32 0, i32 1
188f4a2713aSLionel Sambuc // CHECK-NEXT: store float 1.000000e+00, float* [[T0]]
189f4a2713aSLionel Sambuc // CHECK-NEXT: store float 0.000000e+00, float* [[T1]]
190f4a2713aSLionel Sambuc __c11_atomic_init(fp, 1.0f);
191f4a2713aSLionel Sambuc
192f4a2713aSLionel Sambuc // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[CF]]* [[X]], i32 0, i32 0
193f4a2713aSLionel Sambuc // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[CF]]* [[X]], i32 0, i32 1
194f4a2713aSLionel Sambuc // CHECK-NEXT: store float 2.000000e+00, float* [[T0]]
195f4a2713aSLionel Sambuc // CHECK-NEXT: store float 0.000000e+00, float* [[T1]]
196f4a2713aSLionel Sambuc _Atomic(_Complex float) x = 2.0f;
197f4a2713aSLionel Sambuc
198f4a2713aSLionel Sambuc // CHECK-NEXT: [[T0:%.*]] = load [[CF]]** [[FP]]
199f4a2713aSLionel Sambuc // CHECK-NEXT: [[T1:%.*]] = bitcast [[CF]]* [[T0]] to i8*
200f4a2713aSLionel Sambuc // CHECK-NEXT: [[T2:%.*]] = bitcast [[CF]]* [[TMP0]] to i8*
201f4a2713aSLionel Sambuc // CHECK-NEXT: call arm_aapcscc void @__atomic_load(i32 8, i8* [[T1]], i8* [[T2]], i32 5)
202f4a2713aSLionel Sambuc // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[CF]]* [[TMP0]], i32 0, i32 0
203f4a2713aSLionel Sambuc // CHECK-NEXT: [[R:%.*]] = load float* [[T0]]
204f4a2713aSLionel Sambuc // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[CF]]* [[TMP0]], i32 0, i32 1
205f4a2713aSLionel Sambuc // CHECK-NEXT: [[I:%.*]] = load float* [[T0]]
206f4a2713aSLionel Sambuc // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[CF]]* [[F]], i32 0, i32 0
207f4a2713aSLionel Sambuc // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[CF]]* [[F]], i32 0, i32 1
208f4a2713aSLionel Sambuc // CHECK-NEXT: store float [[R]], float* [[T0]]
209f4a2713aSLionel Sambuc // CHECK-NEXT: store float [[I]], float* [[T1]]
210f4a2713aSLionel Sambuc _Complex float f = *fp;
211f4a2713aSLionel Sambuc
212f4a2713aSLionel Sambuc // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[CF]]* [[F]], i32 0, i32 0
213f4a2713aSLionel Sambuc // CHECK-NEXT: [[R:%.*]] = load float* [[T0]]
214f4a2713aSLionel Sambuc // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[CF]]* [[F]], i32 0, i32 1
215f4a2713aSLionel Sambuc // CHECK-NEXT: [[I:%.*]] = load float* [[T0]]
216f4a2713aSLionel Sambuc // CHECK-NEXT: [[DEST:%.*]] = load [[CF]]** [[FP]], align 4
217f4a2713aSLionel Sambuc // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[CF]]* [[TMP1]], i32 0, i32 0
218f4a2713aSLionel Sambuc // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[CF]]* [[TMP1]], i32 0, i32 1
219f4a2713aSLionel Sambuc // CHECK-NEXT: store float [[R]], float* [[T0]]
220f4a2713aSLionel Sambuc // CHECK-NEXT: store float [[I]], float* [[T1]]
221f4a2713aSLionel Sambuc // CHECK-NEXT: [[T0:%.*]] = bitcast [[CF]]* [[DEST]] to i8*
222f4a2713aSLionel Sambuc // CHECK-NEXT: [[T1:%.*]] = bitcast [[CF]]* [[TMP1]] to i8*
223f4a2713aSLionel Sambuc // CHECK-NEXT: call arm_aapcscc void @__atomic_store(i32 8, i8* [[T0]], i8* [[T1]], i32 5)
224f4a2713aSLionel Sambuc *fp = f;
225f4a2713aSLionel Sambuc
226f4a2713aSLionel Sambuc // CHECK-NEXT: ret void
227f4a2713aSLionel Sambuc }
228f4a2713aSLionel Sambuc
229f4a2713aSLionel Sambuc typedef struct { short x, y, z, w; } S;
230*0a6a1f1dSLionel Sambuc _Atomic S testStructGlobal = (S){1, 2, 3, 4};
231f4a2713aSLionel Sambuc // CHECK: define arm_aapcscc void @testStruct([[S:.*]]*
testStruct(_Atomic (S)* fp)232f4a2713aSLionel Sambuc void testStruct(_Atomic(S) *fp) {
233f4a2713aSLionel Sambuc // CHECK: [[FP:%.*]] = alloca [[S]]*, align 4
234f4a2713aSLionel Sambuc // CHECK-NEXT: [[X:%.*]] = alloca [[S]], align 8
235f4a2713aSLionel Sambuc // CHECK-NEXT: [[F:%.*]] = alloca [[S:%.*]], align 2
236f4a2713aSLionel Sambuc // CHECK-NEXT: [[TMP0:%.*]] = alloca [[S]], align 8
237f4a2713aSLionel Sambuc // CHECK-NEXT: store [[S]]*
238f4a2713aSLionel Sambuc
239f4a2713aSLionel Sambuc // CHECK-NEXT: [[P:%.*]] = load [[S]]** [[FP]]
240f4a2713aSLionel Sambuc // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[S]]* [[P]], i32 0, i32 0
241f4a2713aSLionel Sambuc // CHECK-NEXT: store i16 1, i16* [[T0]], align 2
242f4a2713aSLionel Sambuc // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[S]]* [[P]], i32 0, i32 1
243f4a2713aSLionel Sambuc // CHECK-NEXT: store i16 2, i16* [[T0]], align 2
244f4a2713aSLionel Sambuc // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[S]]* [[P]], i32 0, i32 2
245f4a2713aSLionel Sambuc // CHECK-NEXT: store i16 3, i16* [[T0]], align 2
246f4a2713aSLionel Sambuc // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[S]]* [[P]], i32 0, i32 3
247f4a2713aSLionel Sambuc // CHECK-NEXT: store i16 4, i16* [[T0]], align 2
248f4a2713aSLionel Sambuc __c11_atomic_init(fp, (S){1,2,3,4});
249f4a2713aSLionel Sambuc
250f4a2713aSLionel Sambuc // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[S]]* [[X]], i32 0, i32 0
251f4a2713aSLionel Sambuc // CHECK-NEXT: store i16 1, i16* [[T0]], align 2
252f4a2713aSLionel Sambuc // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[S]]* [[X]], i32 0, i32 1
253f4a2713aSLionel Sambuc // CHECK-NEXT: store i16 2, i16* [[T0]], align 2
254f4a2713aSLionel Sambuc // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[S]]* [[X]], i32 0, i32 2
255f4a2713aSLionel Sambuc // CHECK-NEXT: store i16 3, i16* [[T0]], align 2
256f4a2713aSLionel Sambuc // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[S]]* [[X]], i32 0, i32 3
257f4a2713aSLionel Sambuc // CHECK-NEXT: store i16 4, i16* [[T0]], align 2
258f4a2713aSLionel Sambuc _Atomic(S) x = (S){1,2,3,4};
259f4a2713aSLionel Sambuc
260f4a2713aSLionel Sambuc // CHECK-NEXT: [[T0:%.*]] = load [[S]]** [[FP]]
261f4a2713aSLionel Sambuc // CHECK-NEXT: [[T1:%.*]] = bitcast [[S]]* [[T0]] to i8*
262f4a2713aSLionel Sambuc // CHECK-NEXT: [[T2:%.*]] = bitcast [[S]]* [[F]] to i8*
263f4a2713aSLionel Sambuc // CHECK-NEXT: call arm_aapcscc void @__atomic_load(i32 8, i8* [[T1]], i8* [[T2]], i32 5)
264f4a2713aSLionel Sambuc S f = *fp;
265f4a2713aSLionel Sambuc
266f4a2713aSLionel Sambuc // CHECK-NEXT: [[T0:%.*]] = load [[S]]** [[FP]]
267f4a2713aSLionel Sambuc // CHECK-NEXT: [[T1:%.*]] = bitcast [[S]]* [[TMP0]] to i8*
268f4a2713aSLionel Sambuc // CHECK-NEXT: [[T2:%.*]] = bitcast [[S]]* [[F]] to i8*
269f4a2713aSLionel Sambuc // CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[T1]], i8* [[T2]], i32 8, i32 2, i1 false)
270f4a2713aSLionel Sambuc // CHECK-NEXT: [[T3:%.*]] = bitcast [[S]]* [[T0]] to i8*
271f4a2713aSLionel Sambuc // CHECK-NEXT: [[T4:%.*]] = bitcast [[S]]* [[TMP0]] to i8*
272f4a2713aSLionel Sambuc // CHECK-NEXT: call arm_aapcscc void @__atomic_store(i32 8, i8* [[T3]], i8* [[T4]], i32 5)
273f4a2713aSLionel Sambuc *fp = f;
274f4a2713aSLionel Sambuc
275f4a2713aSLionel Sambuc // CHECK-NEXT: ret void
276f4a2713aSLionel Sambuc }
277f4a2713aSLionel Sambuc
278f4a2713aSLionel Sambuc typedef struct { short x, y, z; } PS;
279*0a6a1f1dSLionel Sambuc _Atomic PS testPromotedStructGlobal = (PS){1, 2, 3};
280f4a2713aSLionel Sambuc // CHECK: define arm_aapcscc void @testPromotedStruct([[APS:.*]]*
testPromotedStruct(_Atomic (PS)* fp)281f4a2713aSLionel Sambuc void testPromotedStruct(_Atomic(PS) *fp) {
282f4a2713aSLionel Sambuc // CHECK: [[FP:%.*]] = alloca [[APS]]*, align 4
283f4a2713aSLionel Sambuc // CHECK-NEXT: [[X:%.*]] = alloca [[APS]], align 8
284f4a2713aSLionel Sambuc // CHECK-NEXT: [[F:%.*]] = alloca [[PS:%.*]], align 2
285f4a2713aSLionel Sambuc // CHECK-NEXT: [[TMP0:%.*]] = alloca [[APS]], align 8
286f4a2713aSLionel Sambuc // CHECK-NEXT: [[TMP1:%.*]] = alloca [[APS]], align 8
287f4a2713aSLionel Sambuc // CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
288f4a2713aSLionel Sambuc // CHECK-NEXT: [[TMP2:%.*]] = alloca %struct.PS, align 2
289f4a2713aSLionel Sambuc // CHECK-NEXT: [[TMP3:%.*]] = alloca [[APS]], align 8
290f4a2713aSLionel Sambuc // CHECK-NEXT: store [[APS]]*
291f4a2713aSLionel Sambuc
292f4a2713aSLionel Sambuc // CHECK-NEXT: [[P:%.*]] = load [[APS]]** [[FP]]
293f4a2713aSLionel Sambuc // CHECK-NEXT: [[T0:%.*]] = bitcast [[APS]]* [[P]] to i8*
294f4a2713aSLionel Sambuc // CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* [[T0]], i8 0, i64 8, i32 8, i1 false)
295f4a2713aSLionel Sambuc // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[APS]]* [[P]], i32 0, i32 0
296f4a2713aSLionel Sambuc // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[PS]]* [[T0]], i32 0, i32 0
297f4a2713aSLionel Sambuc // CHECK-NEXT: store i16 1, i16* [[T1]], align 2
298f4a2713aSLionel Sambuc // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[PS]]* [[T0]], i32 0, i32 1
299f4a2713aSLionel Sambuc // CHECK-NEXT: store i16 2, i16* [[T1]], align 2
300f4a2713aSLionel Sambuc // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[PS]]* [[T0]], i32 0, i32 2
301f4a2713aSLionel Sambuc // CHECK-NEXT: store i16 3, i16* [[T1]], align 2
302f4a2713aSLionel Sambuc __c11_atomic_init(fp, (PS){1,2,3});
303f4a2713aSLionel Sambuc
304f4a2713aSLionel Sambuc // CHECK-NEXT: [[T0:%.*]] = bitcast [[APS]]* [[X]] to i8*
305f4a2713aSLionel Sambuc // CHECK-NEXT: call void @llvm.memset.p0i8.i32(i8* [[T0]], i8 0, i32 8, i32 8, i1 false)
306f4a2713aSLionel Sambuc // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[APS]]* [[X]], i32 0, i32 0
307f4a2713aSLionel Sambuc // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[PS]]* [[T0]], i32 0, i32 0
308f4a2713aSLionel Sambuc // CHECK-NEXT: store i16 1, i16* [[T1]], align 2
309f4a2713aSLionel Sambuc // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[PS]]* [[T0]], i32 0, i32 1
310f4a2713aSLionel Sambuc // CHECK-NEXT: store i16 2, i16* [[T1]], align 2
311f4a2713aSLionel Sambuc // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[PS]]* [[T0]], i32 0, i32 2
312f4a2713aSLionel Sambuc // CHECK-NEXT: store i16 3, i16* [[T1]], align 2
313f4a2713aSLionel Sambuc _Atomic(PS) x = (PS){1,2,3};
314f4a2713aSLionel Sambuc
315f4a2713aSLionel Sambuc // CHECK-NEXT: [[T0:%.*]] = load [[APS]]** [[FP]]
316f4a2713aSLionel Sambuc // CHECK-NEXT: [[T1:%.*]] = bitcast [[APS]]* [[T0]] to i8*
317f4a2713aSLionel Sambuc // CHECK-NEXT: [[T2:%.*]] = bitcast [[APS]]* [[TMP0]] to i8*
318f4a2713aSLionel Sambuc // CHECK-NEXT: call arm_aapcscc void @__atomic_load(i32 8, i8* [[T1]], i8* [[T2]], i32 5)
319f4a2713aSLionel Sambuc // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[APS]]* [[TMP0]], i32 0, i32 0
320f4a2713aSLionel Sambuc // CHECK-NEXT: [[T1:%.*]] = bitcast [[PS]]* [[F]] to i8*
321f4a2713aSLionel Sambuc // CHECK-NEXT: [[T2:%.*]] = bitcast [[PS]]* [[T0]] to i8*
322f4a2713aSLionel Sambuc // CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[T1]], i8* [[T2]], i32 6, i32 2, i1 false)
323f4a2713aSLionel Sambuc PS f = *fp;
324f4a2713aSLionel Sambuc
325f4a2713aSLionel Sambuc // CHECK-NEXT: [[T0:%.*]] = load [[APS]]** [[FP]]
326f4a2713aSLionel Sambuc // CHECK-NEXT: [[T1:%.*]] = bitcast { %struct.PS, [2 x i8] }* [[TMP1]] to i8*
327f4a2713aSLionel Sambuc // CHECK-NEXT: call void @llvm.memset.p0i8.i32(i8* [[T1]], i8 0, i32 8, i32 8, i1 false)
328f4a2713aSLionel Sambuc // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[APS]]* [[TMP1]], i32 0, i32 0
329f4a2713aSLionel Sambuc // CHECK-NEXT: [[T2:%.*]] = bitcast [[PS]]* [[T1]] to i8*
330f4a2713aSLionel Sambuc // CHECK-NEXT: [[T3:%.*]] = bitcast [[PS]]* [[F]] to i8*
331f4a2713aSLionel Sambuc // CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[T2]], i8* [[T3]], i32 6, i32 2, i1 false)
332f4a2713aSLionel Sambuc // CHECK-NEXT: [[T4:%.*]] = bitcast [[APS]]* [[T0]] to i8*
333f4a2713aSLionel Sambuc // CHECK-NEXT: [[T5:%.*]] = bitcast [[APS]]* [[TMP1]] to i8*
334f4a2713aSLionel Sambuc // CHECK-NEXT: call arm_aapcscc void @__atomic_store(i32 8, i8* [[T4]], i8* [[T5]], i32 5)
335f4a2713aSLionel Sambuc *fp = f;
336f4a2713aSLionel Sambuc
337f4a2713aSLionel Sambuc // CHECK-NEXT: [[T0:%.*]] = load [[APS]]** [[FP]], align 4
338f4a2713aSLionel Sambuc // CHECK-NEXT: [[T1:%.*]] = bitcast [[APS]]* [[T0]] to i8*
339f4a2713aSLionel Sambuc // CHECK-NEXT: [[T2:%.*]] = bitcast [[APS]]* [[TMP3]] to i8*
340f4a2713aSLionel Sambuc // CHECK-NEXT: call arm_aapcscc void @__atomic_load(i32 8, i8* [[T1]], i8* [[T2]], i32 5)
341f4a2713aSLionel Sambuc // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[APS]]* [[TMP3]], i32 0, i32 0
342f4a2713aSLionel Sambuc // CHECK-NEXT: [[T1:%.*]] = bitcast %struct.PS* [[TMP2]] to i8*
343f4a2713aSLionel Sambuc // CHECK-NEXT: [[T2:%.*]] = bitcast %struct.PS* [[T0]] to i8*
344f4a2713aSLionel Sambuc // CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[T1]], i8* [[T2]], i32 6, i32 2, i1 false)
345f4a2713aSLionel Sambuc // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds %struct.PS* [[TMP2]], i32 0, i32 0
346f4a2713aSLionel Sambuc // CHECK-NEXT: [[T1:%.*]] = load i16* [[T0]], align 2
347f4a2713aSLionel Sambuc // CHECK-NEXT: [[T2:%.*]] = sext i16 [[T1]] to i32
348f4a2713aSLionel Sambuc // CHECK-NEXT: store i32 [[T2]], i32* [[A]], align 4
349f4a2713aSLionel Sambuc int a = ((PS)*fp).x;
350f4a2713aSLionel Sambuc
351f4a2713aSLionel Sambuc // CHECK-NEXT: ret void
352f4a2713aSLionel Sambuc }
353f4a2713aSLionel Sambuc
354f4a2713aSLionel Sambuc // CHECK: define arm_aapcscc void @testPromotedStructOps([[APS:.*]]*
355f4a2713aSLionel Sambuc
356f4a2713aSLionel Sambuc // FIXME: none of these look right, but we can leave the "test" here
357f4a2713aSLionel Sambuc // to make sure they at least don't crash.
testPromotedStructOps(_Atomic (PS)* p)358f4a2713aSLionel Sambuc void testPromotedStructOps(_Atomic(PS) *p) {
359f4a2713aSLionel Sambuc PS a = __c11_atomic_load(p, 5);
360f4a2713aSLionel Sambuc __c11_atomic_store(p, a, 5);
361f4a2713aSLionel Sambuc PS b = __c11_atomic_exchange(p, a, 5);
362f4a2713aSLionel Sambuc _Bool v = __c11_atomic_compare_exchange_strong(p, &b, a, 5, 5);
363f4a2713aSLionel Sambuc v = __c11_atomic_compare_exchange_weak(p, &b, a, 5, 5);
364f4a2713aSLionel Sambuc }
365