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