Clang Project

clang_source_code/test/CodeGen/builtins-arm-exclusive.c
1// RUN: %clang_cc1 -Wall -Werror -triple thumbv8-linux-gnueabi -fno-signed-char -disable-O0-optnone -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s
2// RUN: %clang_cc1 -Wall -Werror -triple arm64-apple-ios7.0 -disable-O0-optnone -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s --check-prefix=CHECK-ARM64
3
4struct Simple {
5  char a, b;
6};
7
8int test_ldrex(char *addr, long long *addr64, float *addrfloat) {
9// CHECK-LABEL: @test_ldrex
10// CHECK-ARM64-LABEL: @test_ldrex
11  int sum = 0;
12  sum += __builtin_arm_ldrex(addr);
13// CHECK: [[INTRES:%.*]] = call i32 @llvm.arm.ldrex.p0i8(i8* %addr)
14// CHECK: trunc i32 [[INTRES]] to i8
15
16// CHECK-ARM64: [[INTRES:%.*]] = call i64 @llvm.aarch64.ldxr.p0i8(i8* %addr)
17// CHECK-ARM64: trunc i64 [[INTRES]] to i8
18
19  sum += __builtin_arm_ldrex((short *)addr);
20// CHECK: [[ADDR16:%.*]] = bitcast i8* %addr to i16*
21// CHECK: [[INTRES:%.*]] = call i32 @llvm.arm.ldrex.p0i16(i16* [[ADDR16]])
22// CHECK: trunc i32 [[INTRES]] to i16
23
24// CHECK-ARM64: [[ADDR16:%.*]] = bitcast i8* %addr to i16*
25// CHECK-ARM64: [[INTRES:%.*]] = call i64 @llvm.aarch64.ldxr.p0i16(i16* [[ADDR16]])
26// CHECK-ARM64: trunc i64 [[INTRES]] to i16
27
28  sum += __builtin_arm_ldrex((int *)addr);
29// CHECK: [[ADDR32:%.*]] = bitcast i8* %addr to i32*
30// CHECK: call i32 @llvm.arm.ldrex.p0i32(i32* [[ADDR32]])
31
32// CHECK-ARM64: [[ADDR32:%.*]] = bitcast i8* %addr to i32*
33// CHECK-ARM64: [[INTRES:%.*]] = call i64 @llvm.aarch64.ldxr.p0i32(i32* [[ADDR32]])
34// CHECK-ARM64: trunc i64 [[INTRES]] to i32
35
36  sum += __builtin_arm_ldrex((long long *)addr);
37// CHECK: [[TMP4:%.*]] = bitcast i8* %addr to i64*
38// CHECK: [[TMP5:%.*]] = bitcast i64* [[TMP4]] to i8*
39// CHECK: call { i32, i32 } @llvm.arm.ldrexd(i8* [[TMP5]])
40
41// CHECK-ARM64: [[ADDR64:%.*]] = bitcast i8* %addr to i64*
42// CHECK-ARM64: call i64 @llvm.aarch64.ldxr.p0i64(i64* [[ADDR64]])
43
44  sum += __builtin_arm_ldrex(addr64);
45// CHECK: [[ADDR64_AS8:%.*]] = bitcast i64* %addr64 to i8*
46// CHECK: call { i32, i32 } @llvm.arm.ldrexd(i8* [[ADDR64_AS8]])
47
48// CHECK-ARM64: call i64 @llvm.aarch64.ldxr.p0i64(i64* %addr64)
49
50  sum += __builtin_arm_ldrex(addrfloat);
51// CHECK: [[INTADDR:%.*]] = bitcast float* %addrfloat to i32*
52// CHECK: [[INTRES:%.*]] = call i32 @llvm.arm.ldrex.p0i32(i32* [[INTADDR]])
53// CHECK: bitcast i32 [[INTRES]] to float
54
55// CHECK-ARM64: [[INTADDR:%.*]] = bitcast float* %addrfloat to i32*
56// CHECK-ARM64: [[INTRES:%.*]] = call i64 @llvm.aarch64.ldxr.p0i32(i32* [[INTADDR]])
57// CHECK-ARM64: [[TRUNCRES:%.*]] = trunc i64 [[INTRES]] to i32
58// CHECK-ARM64: bitcast i32 [[TRUNCRES]] to float
59
60  sum += __builtin_arm_ldrex((double *)addr);
61// CHECK: [[TMP4:%.*]] = bitcast i8* %addr to double*
62// CHECK: [[TMP5:%.*]] = bitcast double* [[TMP4]] to i8*
63// CHECK: [[STRUCTRES:%.*]] = call { i32, i32 } @llvm.arm.ldrexd(i8* [[TMP5]])
64// CHECK: [[RESHI:%.*]] = extractvalue { i32, i32 } [[STRUCTRES]], 1
65// CHECK: [[RESLO:%.*]] = extractvalue { i32, i32 } [[STRUCTRES]], 0
66// CHECK: [[RESHI64:%.*]] = zext i32 [[RESHI]] to i64
67// CHECK: [[RESLO64:%.*]] = zext i32 [[RESLO]] to i64
68// CHECK: [[RESHIHI:%.*]] = shl nuw i64 [[RESHI64]], 32
69// CHECK: [[INTRES:%.*]] = or i64 [[RESHIHI]], [[RESLO64]]
70// CHECK: bitcast i64 [[INTRES]] to double
71
72// CHECK-ARM64: [[TMP4:%.*]] = bitcast i8* %addr to double*
73// CHECK-ARM64: [[TMP5:%.*]] = bitcast double* [[TMP4]] to i64*
74// CHECK-ARM64: [[INTRES:%.*]] = call i64 @llvm.aarch64.ldxr.p0i64(i64* [[TMP5]])
75// CHECK-ARM64: bitcast i64 [[INTRES]] to double
76
77  sum += *__builtin_arm_ldrex((int **)addr);
78// CHECK: [[TMP4:%.*]] = bitcast i8* %addr to i32**
79// CHECK: [[TMP5:%.*]] = bitcast i32** [[TMP4]] to i32*
80// CHECK: [[INTRES:%.*]] = call i32 @llvm.arm.ldrex.p0i32(i32* [[TMP5]])
81// CHECK: inttoptr i32 [[INTRES]] to i32*
82
83// CHECK-ARM64: [[TMP4:%.*]] = bitcast i8* %addr to i32**
84// CHECK-ARM64: [[TMP5:%.*]] = bitcast i32** [[TMP4]] to i64*
85// CHECK-ARM64: [[INTRES:%.*]] = call i64 @llvm.aarch64.ldxr.p0i64(i64* [[TMP5]])
86// CHECK-ARM64: inttoptr i64 [[INTRES]] to i32*
87
88  sum += __builtin_arm_ldrex((struct Simple **)addr)->a;
89// CHECK: [[TMP4:%.*]] = bitcast i8* %addr to %struct.Simple**
90// CHECK: [[TMP5:%.*]] = bitcast %struct.Simple** [[TMP4]] to i32*
91// CHECK: [[INTRES:%.*]] = call i32 @llvm.arm.ldrex.p0i32(i32* [[TMP5]])
92// CHECK: inttoptr i32 [[INTRES]] to %struct.Simple*
93
94// CHECK-ARM64: [[TMP4:%.*]] = bitcast i8* %addr to %struct.Simple**
95// CHECK-ARM64: [[TMP5:%.*]] = bitcast %struct.Simple** [[TMP4]] to i64*
96// CHECK-ARM64: [[INTRES:%.*]] = call i64 @llvm.aarch64.ldxr.p0i64(i64* [[TMP5]])
97// CHECK-ARM64: inttoptr i64 [[INTRES]] to %struct.Simple*
98  return sum;
99}
100
101int test_ldaex(char *addr, long long *addr64, float *addrfloat) {
102// CHECK-LABEL: @test_ldaex
103// CHECK-ARM64-LABEL: @test_ldaex
104  int sum = 0;
105  sum += __builtin_arm_ldaex(addr);
106// CHECK: [[INTRES:%.*]] = call i32 @llvm.arm.ldaex.p0i8(i8* %addr)
107// CHECK: trunc i32 [[INTRES]] to i8
108
109// CHECK-ARM64: [[INTRES:%.*]] = call i64 @llvm.aarch64.ldaxr.p0i8(i8* %addr)
110// CHECK-ARM64: trunc i64 [[INTRES]] to i8
111
112  sum += __builtin_arm_ldaex((short *)addr);
113// CHECK: [[ADDR16:%.*]] = bitcast i8* %addr to i16*
114// CHECK: [[INTRES:%.*]] = call i32 @llvm.arm.ldaex.p0i16(i16* [[ADDR16]])
115// CHECK: trunc i32 [[INTRES]] to i16
116
117// CHECK-ARM64: [[ADDR16:%.*]] = bitcast i8* %addr to i16*
118// CHECK-ARM64: [[INTRES:%.*]] = call i64 @llvm.aarch64.ldaxr.p0i16(i16* [[ADDR16]])
119// CHECK-ARM64: [[TRUNCRES:%.*]] = trunc i64 [[INTRES]] to i16
120
121  sum += __builtin_arm_ldaex((int *)addr);
122// CHECK: [[ADDR32:%.*]] = bitcast i8* %addr to i32*
123// CHECK:  call i32 @llvm.arm.ldaex.p0i32(i32* [[ADDR32]])
124
125// CHECK-ARM64: [[ADDR32:%.*]] = bitcast i8* %addr to i32*
126// CHECK-ARM64: [[INTRES:%.*]] = call i64 @llvm.aarch64.ldaxr.p0i32(i32* [[ADDR32]])
127// CHECK-ARM64: trunc i64 [[INTRES]] to i32
128
129  sum += __builtin_arm_ldaex((long long *)addr);
130// CHECK: [[TMP4:%.*]] = bitcast i8* %addr to i64*
131// CHECK: [[TMP5:%.*]] = bitcast i64* [[TMP4]] to i8*
132// CHECK: call { i32, i32 } @llvm.arm.ldaexd(i8* [[TMP5]])
133
134// CHECK-ARM64: [[ADDR64:%.*]] = bitcast i8* %addr to i64*
135// CHECK-ARM64: call i64 @llvm.aarch64.ldaxr.p0i64(i64* [[ADDR64]])
136
137  sum += __builtin_arm_ldaex(addr64);
138// CHECK: [[ADDR64_AS8:%.*]] = bitcast i64* %addr64 to i8*
139// CHECK: call { i32, i32 } @llvm.arm.ldaexd(i8* [[ADDR64_AS8]])
140
141// CHECK-ARM64: call i64 @llvm.aarch64.ldaxr.p0i64(i64* %addr64)
142
143  sum += __builtin_arm_ldaex(addrfloat);
144// CHECK: [[INTADDR:%.*]] = bitcast float* %addrfloat to i32*
145// CHECK: [[INTRES:%.*]] = call i32 @llvm.arm.ldaex.p0i32(i32* [[INTADDR]])
146// CHECK: bitcast i32 [[INTRES]] to float
147
148// CHECK-ARM64: [[INTADDR:%.*]] = bitcast float* %addrfloat to i32*
149// CHECK-ARM64: [[INTRES:%.*]] = call i64 @llvm.aarch64.ldaxr.p0i32(i32* [[INTADDR]])
150// CHECK-ARM64: [[TRUNCRES:%.*]] = trunc i64 [[INTRES]] to i32
151// CHECK-ARM64: bitcast i32 [[TRUNCRES]] to float
152
153  sum += __builtin_arm_ldaex((double *)addr);
154// CHECK: [[TMP4:%.*]] = bitcast i8* %addr to double*
155// CHECK: [[TMP5:%.*]] = bitcast double* [[TMP4]] to i8*
156// CHECK: [[STRUCTRES:%.*]] = call { i32, i32 } @llvm.arm.ldaexd(i8* [[TMP5]])
157// CHECK: [[RESHI:%.*]] = extractvalue { i32, i32 } [[STRUCTRES]], 1
158// CHECK: [[RESLO:%.*]] = extractvalue { i32, i32 } [[STRUCTRES]], 0
159// CHECK: [[RESHI64:%.*]] = zext i32 [[RESHI]] to i64
160// CHECK: [[RESLO64:%.*]] = zext i32 [[RESLO]] to i64
161// CHECK: [[RESHIHI:%.*]] = shl nuw i64 [[RESHI64]], 32
162// CHECK: [[INTRES:%.*]] = or i64 [[RESHIHI]], [[RESLO64]]
163// CHECK: bitcast i64 [[INTRES]] to double
164
165// CHECK-ARM64: [[TMP4:%.*]] = bitcast i8* %addr to double*
166// CHECK-ARM64: [[TMP5:%.*]] = bitcast double* [[TMP4]] to i64*
167// CHECK-ARM64: [[INTRES:%.*]] = call i64 @llvm.aarch64.ldaxr.p0i64(i64* [[TMP5]])
168// CHECK-ARM64: bitcast i64 [[INTRES]] to double
169
170  sum += *__builtin_arm_ldaex((int **)addr);
171// CHECK: [[TMP4:%.*]] = bitcast i8* %addr to i32**
172// CHECK: [[TMP5:%.*]] = bitcast i32** [[TMP4]] to i32*
173// CHECK: [[INTRES:%.*]] = call i32 @llvm.arm.ldaex.p0i32(i32* [[TMP5]])
174// CHECK: inttoptr i32 [[INTRES]] to i32*
175
176// CHECK-ARM64: [[TMP4:%.*]] = bitcast i8* %addr to i32**
177// CHECK-ARM64: [[TMP5:%.*]] = bitcast i32** [[TMP4]] to i64*
178// CHECK-ARM64: [[INTRES:%.*]] = call i64 @llvm.aarch64.ldaxr.p0i64(i64* [[TMP5]])
179// CHECK-ARM64: inttoptr i64 [[INTRES]] to i32*
180
181  sum += __builtin_arm_ldaex((struct Simple **)addr)->a;
182// CHECK: [[TMP4:%.*]] = bitcast i8* %addr to %struct.Simple**
183// CHECK: [[TMP5:%.*]] = bitcast %struct.Simple** [[TMP4]] to i32*
184// CHECK: [[INTRES:%.*]] = call i32 @llvm.arm.ldaex.p0i32(i32* [[TMP5]])
185// CHECK: inttoptr i32 [[INTRES]] to %struct.Simple*
186
187// CHECK-ARM64: [[TMP4:%.*]] = bitcast i8* %addr to %struct.Simple**
188// CHECK-ARM64: [[TMP5:%.*]] = bitcast %struct.Simple** [[TMP4]] to i64*
189// CHECK-ARM64: [[INTRES:%.*]] = call i64 @llvm.aarch64.ldaxr.p0i64(i64* [[TMP5]])
190// CHECK-ARM64: inttoptr i64 [[INTRES]] to %struct.Simple*
191  return sum;
192}
193
194int test_strex(char *addr) {
195// CHECK-LABEL: @test_strex
196// CHECK-ARM64-LABEL: @test_strex
197  int res = 0;
198  struct Simple var = {0};
199  res |= __builtin_arm_strex(4, addr);
200// CHECK: call i32 @llvm.arm.strex.p0i8(i32 4, i8* %addr)
201
202// CHECK-ARM64: call i32 @llvm.aarch64.stxr.p0i8(i64 4, i8* %addr)
203
204  res |= __builtin_arm_strex(42, (short *)addr);
205// CHECK: [[ADDR16:%.*]] = bitcast i8* %addr to i16*
206// CHECK:  call i32 @llvm.arm.strex.p0i16(i32 42, i16* [[ADDR16]])
207
208// CHECK-ARM64: [[ADDR16:%.*]] = bitcast i8* %addr to i16*
209// CHECK-ARM64:  call i32 @llvm.aarch64.stxr.p0i16(i64 42, i16* [[ADDR16]])
210
211  res |= __builtin_arm_strex(42, (int *)addr);
212// CHECK: [[ADDR32:%.*]] = bitcast i8* %addr to i32*
213// CHECK: call i32 @llvm.arm.strex.p0i32(i32 42, i32* [[ADDR32]])
214
215// CHECK-ARM64: [[ADDR32:%.*]] = bitcast i8* %addr to i32*
216// CHECK-ARM64: call i32 @llvm.aarch64.stxr.p0i32(i64 42, i32* [[ADDR32]])
217
218  res |= __builtin_arm_strex(42, (long long *)addr);
219// CHECK: store i64 42, i64* [[TMP:%.*]], align 8
220// CHECK: [[LOHI_ADDR:%.*]] = bitcast i64* [[TMP]] to { i32, i32 }*
221// CHECK: [[LOHI:%.*]] = load { i32, i32 }, { i32, i32 }* [[LOHI_ADDR]]
222// CHECK: [[LO:%.*]] = extractvalue { i32, i32 } [[LOHI]], 0
223// CHECK: [[HI:%.*]] = extractvalue { i32, i32 } [[LOHI]], 1
224// CHECK: [[TMP4:%.*]] = bitcast i8* %addr to i64*
225// CHECK: [[TMP5:%.*]] = bitcast i64* [[TMP4]] to i8*
226// CHECK: call i32 @llvm.arm.strexd(i32 [[LO]], i32 [[HI]], i8* [[TMP5]])
227
228// CHECK-ARM64: [[ADDR64:%.*]] = bitcast i8* %addr to i64*
229// CHECK-ARM64: call i32 @llvm.aarch64.stxr.p0i64(i64 42, i64* [[ADDR64]])
230
231  res |= __builtin_arm_strex(2.71828f, (float *)addr);
232// CHECK: [[TMP4:%.*]] = bitcast i8* %addr to float*
233// CHECK: [[TMP5:%.*]] = bitcast float* [[TMP4]] to i32*
234// CHECK: call i32 @llvm.arm.strex.p0i32(i32 1076754509, i32* [[TMP5]])
235
236// CHECK-ARM64: [[TMP4:%.*]] = bitcast i8* %addr to float*
237// CHECK-ARM64: [[TMP5:%.*]] = bitcast float* [[TMP4]] to i32*
238// CHECK-ARM64: call i32 @llvm.aarch64.stxr.p0i32(i64 1076754509, i32* [[TMP5]])
239
240  res |= __builtin_arm_strex(3.14159, (double *)addr);
241// CHECK: store double 3.141590e+00, double* [[TMP:%.*]], align 8
242// CHECK: [[LOHI_ADDR:%.*]] = bitcast double* [[TMP]] to { i32, i32 }*
243// CHECK: [[LOHI:%.*]] = load { i32, i32 }, { i32, i32 }* [[LOHI_ADDR]]
244// CHECK: [[LO:%.*]] = extractvalue { i32, i32 } [[LOHI]], 0
245// CHECK: [[HI:%.*]] = extractvalue { i32, i32 } [[LOHI]], 1
246// CHECK: [[TMP4:%.*]] = bitcast i8* %addr to double*
247// CHECK: [[TMP5:%.*]] = bitcast double* [[TMP4]] to i8*
248// CHECK: call i32 @llvm.arm.strexd(i32 [[LO]], i32 [[HI]], i8* [[TMP5]])
249
250// CHECK-ARM64: [[TMP4:%.*]] = bitcast i8* %addr to double*
251// CHECK-ARM64: [[TMP5:%.*]] = bitcast double* [[TMP4]] to i64*
252// CHECK-ARM64: call i32 @llvm.aarch64.stxr.p0i64(i64 4614256650576692846, i64* [[TMP5]])
253
254  res |= __builtin_arm_strex(&var, (struct Simple **)addr);
255// CHECK: [[TMP4:%.*]] = bitcast i8* %addr to %struct.Simple**
256// CHECK: [[TMP5:%.*]] = bitcast %struct.Simple** [[TMP4]] to i32*
257// CHECK: [[INTVAL:%.*]] = ptrtoint %struct.Simple* %var to i32
258// CHECK: call i32 @llvm.arm.strex.p0i32(i32 [[INTVAL]], i32* [[TMP5]])
259
260// CHECK-ARM64: [[TMP4:%.*]] = bitcast i8* %addr to %struct.Simple**
261// CHECK-ARM64: [[TMP5:%.*]] = bitcast %struct.Simple** [[TMP4]] to i64*
262// CHECK-ARM64: [[INTVAL:%.*]] = ptrtoint %struct.Simple* %var to i64
263// CHECK-ARM64: call i32 @llvm.aarch64.stxr.p0i64(i64 [[INTVAL]], i64* [[TMP5]])
264
265  return res;
266}
267
268int test_stlex(char *addr) {
269// CHECK-LABEL: @test_stlex
270// CHECK-ARM64-LABEL: @test_stlex
271  int res = 0;
272  struct Simple var = {0};
273  res |= __builtin_arm_stlex(4, addr);
274// CHECK: call i32 @llvm.arm.stlex.p0i8(i32 4, i8* %addr)
275
276// CHECK-ARM64: call i32 @llvm.aarch64.stlxr.p0i8(i64 4, i8* %addr)
277
278  res |= __builtin_arm_stlex(42, (short *)addr);
279// CHECK: [[ADDR16:%.*]] = bitcast i8* %addr to i16*
280// CHECK:  call i32 @llvm.arm.stlex.p0i16(i32 42, i16* [[ADDR16]])
281
282// CHECK-ARM64: [[ADDR16:%.*]] = bitcast i8* %addr to i16*
283// CHECK-ARM64:  call i32 @llvm.aarch64.stlxr.p0i16(i64 42, i16* [[ADDR16]])
284
285  res |= __builtin_arm_stlex(42, (int *)addr);
286// CHECK: [[ADDR32:%.*]] = bitcast i8* %addr to i32*
287// CHECK: call i32 @llvm.arm.stlex.p0i32(i32 42, i32* [[ADDR32]])
288
289// CHECK-ARM64: [[ADDR32:%.*]] = bitcast i8* %addr to i32*
290// CHECK-ARM64: call i32 @llvm.aarch64.stlxr.p0i32(i64 42, i32* [[ADDR32]])
291
292  res |= __builtin_arm_stlex(42, (long long *)addr);
293// CHECK: store i64 42, i64* [[TMP:%.*]], align 8
294// CHECK: [[LOHI_ADDR:%.*]] = bitcast i64* [[TMP]] to { i32, i32 }*
295// CHECK: [[LOHI:%.*]] = load { i32, i32 }, { i32, i32 }* [[LOHI_ADDR]]
296// CHECK: [[LO:%.*]] = extractvalue { i32, i32 } [[LOHI]], 0
297// CHECK: [[HI:%.*]] = extractvalue { i32, i32 } [[LOHI]], 1
298// CHECK: [[TMP4:%.*]] = bitcast i8* %addr to i64*
299// CHECK: [[TMP5:%.*]] = bitcast i64* [[TMP4]] to i8*
300// CHECK: call i32 @llvm.arm.stlexd(i32 [[LO]], i32 [[HI]], i8* [[TMP5]])
301
302// CHECK-ARM64: [[ADDR64:%.*]] = bitcast i8* %addr to i64*
303// CHECK-ARM64: call i32 @llvm.aarch64.stlxr.p0i64(i64 42, i64* [[ADDR64]])
304
305  res |= __builtin_arm_stlex(2.71828f, (float *)addr);
306// CHECK: [[TMP4:%.*]] = bitcast i8* %addr to float*
307// CHECK: [[TMP5:%.*]] = bitcast float* [[TMP4]] to i32*
308// CHECK: call i32 @llvm.arm.stlex.p0i32(i32 1076754509, i32* [[TMP5]])
309
310// CHECK-ARM64: [[TMP4:%.*]] = bitcast i8* %addr to float*
311// CHECK-ARM64: [[TMP5:%.*]] = bitcast float* [[TMP4]] to i32*
312// CHECK-ARM64: call i32 @llvm.aarch64.stlxr.p0i32(i64 1076754509, i32* [[TMP5]])
313
314  res |= __builtin_arm_stlex(3.14159, (double *)addr);
315// CHECK: store double 3.141590e+00, double* [[TMP:%.*]], align 8
316// CHECK: [[LOHI_ADDR:%.*]] = bitcast double* [[TMP]] to { i32, i32 }*
317// CHECK: [[LOHI:%.*]] = load { i32, i32 }, { i32, i32 }* [[LOHI_ADDR]]
318// CHECK: [[LO:%.*]] = extractvalue { i32, i32 } [[LOHI]], 0
319// CHECK: [[HI:%.*]] = extractvalue { i32, i32 } [[LOHI]], 1
320// CHECK: [[TMP4:%.*]] = bitcast i8* %addr to double*
321// CHECK: [[TMP5:%.*]] = bitcast double* [[TMP4]] to i8*
322// CHECK: call i32 @llvm.arm.stlexd(i32 [[LO]], i32 [[HI]], i8* [[TMP5]])
323
324// CHECK-ARM64: [[TMP4:%.*]] = bitcast i8* %addr to double*
325// CHECK-ARM64: [[TMP5:%.*]] = bitcast double* [[TMP4]] to i64*
326// CHECK-ARM64: call i32 @llvm.aarch64.stlxr.p0i64(i64 4614256650576692846, i64* [[TMP5]])
327
328  res |= __builtin_arm_stlex(&var, (struct Simple **)addr);
329// CHECK: [[TMP4:%.*]] = bitcast i8* %addr to %struct.Simple**
330// CHECK: [[TMP5:%.*]] = bitcast %struct.Simple** [[TMP4]] to i32*
331// CHECK: [[INTVAL:%.*]] = ptrtoint %struct.Simple* %var to i32
332// CHECK: call i32 @llvm.arm.stlex.p0i32(i32 [[INTVAL]], i32* [[TMP5]])
333
334// CHECK-ARM64: [[TMP4:%.*]] = bitcast i8* %addr to %struct.Simple**
335// CHECK-ARM64: [[TMP5:%.*]] = bitcast %struct.Simple** [[TMP4]] to i64*
336// CHECK-ARM64: [[INTVAL:%.*]] = ptrtoint %struct.Simple* %var to i64
337// CHECK-ARM64: call i32 @llvm.aarch64.stlxr.p0i64(i64 [[INTVAL]], i64* [[TMP5]])
338
339  return res;
340}
341
342void test_clrex() {
343// CHECK-LABEL: @test_clrex
344// CHECK-ARM64-LABEL: @test_clrex
345
346  __builtin_arm_clrex();
347// CHECK: call void @llvm.arm.clrex()
348// CHECK-ARM64: call void @llvm.aarch64.clrex()
349}
350
351#ifdef __aarch64__
352// 128-bit tests
353
354__int128 test_ldrex_128(__int128 *addr) {
355// CHECK-ARM64-LABEL: @test_ldrex_128
356
357  return __builtin_arm_ldrex(addr);
358// CHECK-ARM64: [[ADDR8:%.*]] = bitcast i128* %addr to i8*
359// CHECK-ARM64: [[STRUCTRES:%.*]] = call { i64, i64 } @llvm.aarch64.ldxp(i8* [[ADDR8]])
360// CHECK-ARM64: [[RESHI:%.*]] = extractvalue { i64, i64 } [[STRUCTRES]], 1
361// CHECK-ARM64: [[RESLO:%.*]] = extractvalue { i64, i64 } [[STRUCTRES]], 0
362// CHECK-ARM64: [[RESHI64:%.*]] = zext i64 [[RESHI]] to i128
363// CHECK-ARM64: [[RESLO64:%.*]] = zext i64 [[RESLO]] to i128
364// CHECK-ARM64: [[RESHIHI:%.*]] = shl nuw i128 [[RESHI64]], 64
365// CHECK-ARM64: [[INTRES:%.*]] = or i128 [[RESHIHI]], [[RESLO64]]
366// CHECK-ARM64: ret i128 [[INTRES]]
367}
368
369int test_strex_128(__int128 *addr, __int128 val) {
370// CHECK-ARM64-LABEL: @test_strex_128
371
372  return __builtin_arm_strex(val, addr);
373// CHECK-ARM64: store i128 %val, i128* [[TMP:%.*]], align 16
374// CHECK-ARM64: [[LOHI_ADDR:%.*]] = bitcast i128* [[TMP]] to { i64, i64 }*
375// CHECK-ARM64: [[LOHI:%.*]] = load { i64, i64 }, { i64, i64 }* [[LOHI_ADDR]]
376// CHECK-ARM64: [[LO:%.*]] = extractvalue { i64, i64 } [[LOHI]], 0
377// CHECK-ARM64: [[HI:%.*]] = extractvalue { i64, i64 } [[LOHI]], 1
378// CHECK-ARM64: [[ADDR8:%.*]] = bitcast i128* %addr to i8*
379// CHECK-ARM64: call i32 @llvm.aarch64.stxp(i64 [[LO]], i64 [[HI]], i8* [[ADDR8]])
380}
381
382__int128 test_ldaex_128(__int128 *addr) {
383// CHECK-ARM64-LABEL: @test_ldaex_128
384
385  return __builtin_arm_ldaex(addr);
386// CHECK-ARM64: [[ADDR8:%.*]] = bitcast i128* %addr to i8*
387// CHECK-ARM64: [[STRUCTRES:%.*]] = call { i64, i64 } @llvm.aarch64.ldaxp(i8* [[ADDR8]])
388// CHECK-ARM64: [[RESHI:%.*]] = extractvalue { i64, i64 } [[STRUCTRES]], 1
389// CHECK-ARM64: [[RESLO:%.*]] = extractvalue { i64, i64 } [[STRUCTRES]], 0
390// CHECK-ARM64: [[RESHI64:%.*]] = zext i64 [[RESHI]] to i128
391// CHECK-ARM64: [[RESLO64:%.*]] = zext i64 [[RESLO]] to i128
392// CHECK-ARM64: [[RESHIHI:%.*]] = shl nuw i128 [[RESHI64]], 64
393// CHECK-ARM64: [[INTRES:%.*]] = or i128 [[RESHIHI]], [[RESLO64]]
394// CHECK-ARM64: ret i128 [[INTRES]]
395}
396
397int test_stlex_128(__int128 *addr, __int128 val) {
398// CHECK-ARM64-LABEL: @test_stlex_128
399
400  return __builtin_arm_stlex(val, addr);
401// CHECK-ARM64: store i128 %val, i128* [[TMP:%.*]], align 16
402// CHECK-ARM64: [[LOHI_ADDR:%.*]] = bitcast i128* [[TMP]] to { i64, i64 }*
403// CHECK-ARM64: [[LOHI:%.*]] = load { i64, i64 }, { i64, i64 }* [[LOHI_ADDR]]
404// CHECK-ARM64: [[LO:%.*]] = extractvalue { i64, i64 } [[LOHI]], 0
405// CHECK-ARM64: [[HI:%.*]] = extractvalue { i64, i64 } [[LOHI]], 1
406// CHECK-ARM64: [[ADDR8:%.*]] = bitcast i128* %addr to i8*
407// CHECK-ARM64: [[RES:%.*]] = call i32 @llvm.aarch64.stlxp(i64 [[LO]], i64 [[HI]], i8* [[ADDR8]])
408}
409
410#endif
411