[flang] Fix crash in HLFIR generation (#118399)
[llvm-project.git] / clang / test / CodeGen / builtins-arm-exclusive.c
blobd2aaf26502a3d39da762af243e3e342433001d3c
1 // RUN: %clang_cc1 -Wall -Werror -triple thumbv8-linux-gnueabi -fno-signed-char -disable-O0-optnone -emit-llvm -o - %s | opt -S -passes=mem2reg | FileCheck %s
2 // RUN: %clang_cc1 -Wall -Werror -triple arm64-apple-ios7.0 -disable-O0-optnone -emit-llvm -o - %s | opt -S -passes=mem2reg | FileCheck %s --check-prefix=CHECK-ARM64
4 struct Simple {
5 char a, b;
6 };
8 int 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.p0(ptr elementtype(i8) %addr)
14 // CHECK: trunc i32 [[INTRES]] to i8
16 // CHECK-ARM64: [[INTRES:%.*]] = call i64 @llvm.aarch64.ldxr.p0(ptr elementtype(i8) %addr)
17 // CHECK-ARM64: trunc i64 [[INTRES]] to i8
19 sum += __builtin_arm_ldrex((short *)addr);
20 // CHECK: [[INTRES:%.*]] = call i32 @llvm.arm.ldrex.p0(ptr elementtype(i16) %addr)
21 // CHECK: trunc i32 [[INTRES]] to i16
23 // CHECK-ARM64: [[INTRES:%.*]] = call i64 @llvm.aarch64.ldxr.p0(ptr elementtype(i16) %addr)
24 // CHECK-ARM64: trunc i64 [[INTRES]] to i16
26 sum += __builtin_arm_ldrex((int *)addr);
27 // CHECK: call i32 @llvm.arm.ldrex.p0(ptr elementtype(i32) %addr)
29 // CHECK-ARM64: [[INTRES:%.*]] = call i64 @llvm.aarch64.ldxr.p0(ptr elementtype(i32) %addr)
30 // CHECK-ARM64: trunc i64 [[INTRES]] to i32
32 sum += __builtin_arm_ldrex((long long *)addr);
33 // CHECK: call { i32, i32 } @llvm.arm.ldrexd(ptr %addr)
35 // CHECK-ARM64: call i64 @llvm.aarch64.ldxr.p0(ptr elementtype(i64) %addr)
37 sum += __builtin_arm_ldrex(addr64);
38 // CHECK: call { i32, i32 } @llvm.arm.ldrexd(ptr %addr64)
40 // CHECK-ARM64: call i64 @llvm.aarch64.ldxr.p0(ptr elementtype(i64) %addr64)
42 sum += __builtin_arm_ldrex(addrfloat);
43 // CHECK: [[INTRES:%.*]] = call i32 @llvm.arm.ldrex.p0(ptr elementtype(i32) %addrfloat)
45 // CHECK-ARM64: [[INTRES:%.*]] = call i64 @llvm.aarch64.ldxr.p0(ptr elementtype(i32) %addrfloat)
46 // CHECK-ARM64: [[TRUNCRES:%.*]] = trunc i64 [[INTRES]] to i32
47 // CHECK-ARM64: bitcast i32 [[TRUNCRES]] to float
49 sum += __builtin_arm_ldrex((double *)addr);
50 // CHECK: [[STRUCTRES:%.*]] = call { i32, i32 } @llvm.arm.ldrexd(ptr %addr)
51 // CHECK: [[RESHI:%.*]] = extractvalue { i32, i32 } [[STRUCTRES]], 1
52 // CHECK: [[RESLO:%.*]] = extractvalue { i32, i32 } [[STRUCTRES]], 0
53 // CHECK: [[RESHI64:%.*]] = zext i32 [[RESHI]] to i64
54 // CHECK: [[RESLO64:%.*]] = zext i32 [[RESLO]] to i64
55 // CHECK: [[RESHIHI:%.*]] = shl nuw i64 [[RESHI64]], 32
56 // CHECK: [[INTRES:%.*]] = or i64 [[RESHIHI]], [[RESLO64]]
58 // CHECK-ARM64: [[INTRES:%.*]] = call i64 @llvm.aarch64.ldxr.p0(ptr elementtype(i64) %addr)
59 // CHECK-ARM64: bitcast i64 [[INTRES]] to double
61 sum += *__builtin_arm_ldrex((int **)addr);
62 // CHECK: [[INTRES:%.*]] = call i32 @llvm.arm.ldrex.p0(ptr elementtype(i32) %addr)
63 // CHECK: inttoptr i32 [[INTRES]] to ptr
65 // CHECK-ARM64: [[INTRES:%.*]] = call i64 @llvm.aarch64.ldxr.p0(ptr elementtype(i64) %addr)
66 // CHECK-ARM64: inttoptr i64 [[INTRES]] to ptr
68 sum += __builtin_arm_ldrex((struct Simple **)addr)->a;
69 // CHECK: [[INTRES:%.*]] = call i32 @llvm.arm.ldrex.p0(ptr elementtype(i32) %addr)
70 // CHECK: inttoptr i32 [[INTRES]] to ptr
72 // CHECK-ARM64: [[INTRES:%.*]] = call i64 @llvm.aarch64.ldxr.p0(ptr elementtype(i64) %addr)
73 // CHECK-ARM64: inttoptr i64 [[INTRES]] to ptr
74 return sum;
77 int test_ldaex(char *addr, long long *addr64, float *addrfloat) {
78 // CHECK-LABEL: @test_ldaex
79 // CHECK-ARM64-LABEL: @test_ldaex
80 int sum = 0;
81 sum += __builtin_arm_ldaex(addr);
82 // CHECK: [[INTRES:%.*]] = call i32 @llvm.arm.ldaex.p0(ptr elementtype(i8) %addr)
83 // CHECK: trunc i32 [[INTRES]] to i8
85 // CHECK-ARM64: [[INTRES:%.*]] = call i64 @llvm.aarch64.ldaxr.p0(ptr elementtype(i8) %addr)
86 // CHECK-ARM64: trunc i64 [[INTRES]] to i8
88 sum += __builtin_arm_ldaex((short *)addr);
89 // CHECK: [[INTRES:%.*]] = call i32 @llvm.arm.ldaex.p0(ptr elementtype(i16) %addr)
90 // CHECK: trunc i32 [[INTRES]] to i16
92 // CHECK-ARM64: [[INTRES:%.*]] = call i64 @llvm.aarch64.ldaxr.p0(ptr elementtype(i16) %addr)
93 // CHECK-ARM64: [[TRUNCRES:%.*]] = trunc i64 [[INTRES]] to i16
95 sum += __builtin_arm_ldaex((int *)addr);
96 // CHECK: call i32 @llvm.arm.ldaex.p0(ptr elementtype(i32) %addr)
98 // CHECK-ARM64: [[INTRES:%.*]] = call i64 @llvm.aarch64.ldaxr.p0(ptr elementtype(i32) %addr)
99 // CHECK-ARM64: trunc i64 [[INTRES]] to i32
101 sum += __builtin_arm_ldaex((long long *)addr);
102 // CHECK: call { i32, i32 } @llvm.arm.ldaexd(ptr %addr)
104 // CHECK-ARM64: call i64 @llvm.aarch64.ldaxr.p0(ptr elementtype(i64) %addr)
106 sum += __builtin_arm_ldaex(addr64);
107 // CHECK: call { i32, i32 } @llvm.arm.ldaexd(ptr %addr64)
109 // CHECK-ARM64: call i64 @llvm.aarch64.ldaxr.p0(ptr elementtype(i64) %addr64)
111 sum += __builtin_arm_ldaex(addrfloat);
112 // CHECK: [[INTRES:%.*]] = call i32 @llvm.arm.ldaex.p0(ptr elementtype(i32) %addrfloat)
114 // CHECK-ARM64: [[INTRES:%.*]] = call i64 @llvm.aarch64.ldaxr.p0(ptr elementtype(i32) %addrfloat)
115 // CHECK-ARM64: [[TRUNCRES:%.*]] = trunc i64 [[INTRES]] to i32
116 // CHECK-ARM64: bitcast i32 [[TRUNCRES]] to float
118 sum += __builtin_arm_ldaex((double *)addr);
119 // CHECK: [[STRUCTRES:%.*]] = call { i32, i32 } @llvm.arm.ldaexd(ptr %addr)
120 // CHECK: [[RESHI:%.*]] = extractvalue { i32, i32 } [[STRUCTRES]], 1
121 // CHECK: [[RESLO:%.*]] = extractvalue { i32, i32 } [[STRUCTRES]], 0
122 // CHECK: [[RESHI64:%.*]] = zext i32 [[RESHI]] to i64
123 // CHECK: [[RESLO64:%.*]] = zext i32 [[RESLO]] to i64
124 // CHECK: [[RESHIHI:%.*]] = shl nuw i64 [[RESHI64]], 32
125 // CHECK: [[INTRES:%.*]] = or i64 [[RESHIHI]], [[RESLO64]]
127 // CHECK-ARM64: [[INTRES:%.*]] = call i64 @llvm.aarch64.ldaxr.p0(ptr elementtype(i64) %addr)
128 // CHECK-ARM64: bitcast i64 [[INTRES]] to double
130 sum += *__builtin_arm_ldaex((int **)addr);
131 // CHECK: [[INTRES:%.*]] = call i32 @llvm.arm.ldaex.p0(ptr elementtype(i32) %addr)
132 // CHECK: inttoptr i32 [[INTRES]] to ptr
134 // CHECK-ARM64: [[INTRES:%.*]] = call i64 @llvm.aarch64.ldaxr.p0(ptr elementtype(i64) %addr)
135 // CHECK-ARM64: inttoptr i64 [[INTRES]] to ptr
137 sum += __builtin_arm_ldaex((struct Simple **)addr)->a;
138 // CHECK: [[INTRES:%.*]] = call i32 @llvm.arm.ldaex.p0(ptr elementtype(i32) %addr)
139 // CHECK: inttoptr i32 [[INTRES]] to ptr
141 // CHECK-ARM64: [[INTRES:%.*]] = call i64 @llvm.aarch64.ldaxr.p0(ptr elementtype(i64) %addr)
142 // CHECK-ARM64: inttoptr i64 [[INTRES]] to ptr
143 return sum;
146 int test_strex(char *addr) {
147 // CHECK-LABEL: @test_strex
148 // CHECK-ARM64-LABEL: @test_strex
149 int res = 0;
150 struct Simple var = {0};
151 res |= __builtin_arm_strex(4, addr);
152 // CHECK: call i32 @llvm.arm.strex.p0(i32 4, ptr elementtype(i8) %addr)
154 // CHECK-ARM64: call i32 @llvm.aarch64.stxr.p0(i64 4, ptr elementtype(i8) %addr)
156 res |= __builtin_arm_strex(42, (short *)addr);
157 // CHECK: call i32 @llvm.arm.strex.p0(i32 42, ptr elementtype(i16) %addr)
159 // CHECK-ARM64: call i32 @llvm.aarch64.stxr.p0(i64 42, ptr elementtype(i16) %addr)
161 res |= __builtin_arm_strex(42, (int *)addr);
162 // CHECK: call i32 @llvm.arm.strex.p0(i32 42, ptr elementtype(i32) %addr)
164 // CHECK-ARM64: call i32 @llvm.aarch64.stxr.p0(i64 42, ptr elementtype(i32) %addr)
166 res |= __builtin_arm_strex(42, (long long *)addr);
167 // CHECK: store i64 42, ptr [[TMP:%.*]], align 8
168 // CHECK: [[LOHI:%.*]] = load { i32, i32 }, ptr [[TMP]]
169 // CHECK: [[LO:%.*]] = extractvalue { i32, i32 } [[LOHI]], 0
170 // CHECK: [[HI:%.*]] = extractvalue { i32, i32 } [[LOHI]], 1
171 // CHECK: call i32 @llvm.arm.strexd(i32 [[LO]], i32 [[HI]], ptr %addr)
173 // CHECK-ARM64: call i32 @llvm.aarch64.stxr.p0(i64 42, ptr elementtype(i64) %addr)
175 res |= __builtin_arm_strex(2.71828f, (float *)addr);
176 // CHECK: call i32 @llvm.arm.strex.p0(i32 1076754509, ptr elementtype(i32) %addr)
178 // CHECK-ARM64: call i32 @llvm.aarch64.stxr.p0(i64 1076754509, ptr elementtype(i32) %addr)
180 res |= __builtin_arm_strex(3.14159, (double *)addr);
181 // CHECK: store double 3.141590e+00, ptr [[TMP:%.*]], align 8
182 // CHECK: [[LOHI:%.*]] = load { i32, i32 }, ptr [[TMP]]
183 // CHECK: [[LO:%.*]] = extractvalue { i32, i32 } [[LOHI]], 0
184 // CHECK: [[HI:%.*]] = extractvalue { i32, i32 } [[LOHI]], 1
185 // CHECK: call i32 @llvm.arm.strexd(i32 [[LO]], i32 [[HI]], ptr %addr)
187 // CHECK-ARM64: call i32 @llvm.aarch64.stxr.p0(i64 4614256650576692846, ptr elementtype(i64) %addr)
189 res |= __builtin_arm_strex(&var, (struct Simple **)addr);
190 // CHECK: [[INTVAL:%.*]] = ptrtoint ptr %var to i32
191 // CHECK: call i32 @llvm.arm.strex.p0(i32 [[INTVAL]], ptr elementtype(i32) %addr)
193 // CHECK-ARM64: [[INTVAL:%.*]] = ptrtoint ptr %var to i64
194 // CHECK-ARM64: call i32 @llvm.aarch64.stxr.p0(i64 [[INTVAL]], ptr elementtype(i64) %addr)
196 return res;
199 int test_stlex(char *addr) {
200 // CHECK-LABEL: @test_stlex
201 // CHECK-ARM64-LABEL: @test_stlex
202 int res = 0;
203 struct Simple var = {0};
204 res |= __builtin_arm_stlex(4, addr);
205 // CHECK: call i32 @llvm.arm.stlex.p0(i32 4, ptr elementtype(i8) %addr)
207 // CHECK-ARM64: call i32 @llvm.aarch64.stlxr.p0(i64 4, ptr elementtype(i8) %addr)
209 res |= __builtin_arm_stlex(42, (short *)addr);
210 // CHECK: call i32 @llvm.arm.stlex.p0(i32 42, ptr elementtype(i16) %addr)
212 // CHECK-ARM64: call i32 @llvm.aarch64.stlxr.p0(i64 42, ptr elementtype(i16) %addr)
214 res |= __builtin_arm_stlex(42, (int *)addr);
215 // CHECK: call i32 @llvm.arm.stlex.p0(i32 42, ptr elementtype(i32) %addr)
217 // CHECK-ARM64: call i32 @llvm.aarch64.stlxr.p0(i64 42, ptr elementtype(i32) %addr)
219 res |= __builtin_arm_stlex(42, (long long *)addr);
220 // CHECK: store i64 42, ptr [[TMP:%.*]], align 8
221 // CHECK: [[LOHI:%.*]] = load { i32, i32 }, ptr [[TMP]]
222 // CHECK: [[LO:%.*]] = extractvalue { i32, i32 } [[LOHI]], 0
223 // CHECK: [[HI:%.*]] = extractvalue { i32, i32 } [[LOHI]], 1
224 // CHECK: call i32 @llvm.arm.stlexd(i32 [[LO]], i32 [[HI]], ptr %addr)
226 // CHECK-ARM64: call i32 @llvm.aarch64.stlxr.p0(i64 42, ptr elementtype(i64) %addr)
228 res |= __builtin_arm_stlex(2.71828f, (float *)addr);
229 // CHECK: call i32 @llvm.arm.stlex.p0(i32 1076754509, ptr elementtype(i32) %addr)
231 // CHECK-ARM64: call i32 @llvm.aarch64.stlxr.p0(i64 1076754509, ptr elementtype(i32) %addr)
233 res |= __builtin_arm_stlex(3.14159, (double *)addr);
234 // CHECK: store double 3.141590e+00, ptr [[TMP:%.*]], align 8
235 // CHECK: [[LOHI:%.*]] = load { i32, i32 }, ptr [[TMP]]
236 // CHECK: [[LO:%.*]] = extractvalue { i32, i32 } [[LOHI]], 0
237 // CHECK: [[HI:%.*]] = extractvalue { i32, i32 } [[LOHI]], 1
238 // CHECK: call i32 @llvm.arm.stlexd(i32 [[LO]], i32 [[HI]], ptr %addr)
240 // CHECK-ARM64: call i32 @llvm.aarch64.stlxr.p0(i64 4614256650576692846, ptr elementtype(i64) %addr)
242 res |= __builtin_arm_stlex(&var, (struct Simple **)addr);
243 // CHECK: [[INTVAL:%.*]] = ptrtoint ptr %var to i32
244 // CHECK: call i32 @llvm.arm.stlex.p0(i32 [[INTVAL]], ptr elementtype(i32) %addr)
246 // CHECK-ARM64: [[INTVAL:%.*]] = ptrtoint ptr %var to i64
247 // CHECK-ARM64: call i32 @llvm.aarch64.stlxr.p0(i64 [[INTVAL]], ptr elementtype(i64) %addr)
249 return res;
252 void test_clrex(void) {
253 // CHECK-LABEL: @test_clrex
254 // CHECK-ARM64-LABEL: @test_clrex
256 __builtin_arm_clrex();
257 // CHECK: call void @llvm.arm.clrex()
258 // CHECK-ARM64: call void @llvm.aarch64.clrex()
261 #ifdef __aarch64__
262 // 128-bit tests
264 __int128 test_ldrex_128(__int128 *addr) {
265 // CHECK-ARM64-LABEL: @test_ldrex_128
267 return __builtin_arm_ldrex(addr);
268 // CHECK-ARM64: [[STRUCTRES:%.*]] = call { i64, i64 } @llvm.aarch64.ldxp(ptr %addr)
269 // CHECK-ARM64: [[RESHI:%.*]] = extractvalue { i64, i64 } [[STRUCTRES]], 1
270 // CHECK-ARM64: [[RESLO:%.*]] = extractvalue { i64, i64 } [[STRUCTRES]], 0
271 // CHECK-ARM64: [[RESHI64:%.*]] = zext i64 [[RESHI]] to i128
272 // CHECK-ARM64: [[RESLO64:%.*]] = zext i64 [[RESLO]] to i128
273 // CHECK-ARM64: [[RESHIHI:%.*]] = shl nuw i128 [[RESHI64]], 64
274 // CHECK-ARM64: [[INTRES:%.*]] = or i128 [[RESHIHI]], [[RESLO64]]
275 // CHECK-ARM64: ret i128 [[INTRES]]
278 int test_strex_128(__int128 *addr, __int128 val) {
279 // CHECK-ARM64-LABEL: @test_strex_128
281 return __builtin_arm_strex(val, addr);
282 // CHECK-ARM64: store i128 %val, ptr [[TMP:%.*]], align 16
283 // CHECK-ARM64: [[LOHI:%.*]] = load { i64, i64 }, ptr [[TMP]]
284 // CHECK-ARM64: [[LO:%.*]] = extractvalue { i64, i64 } [[LOHI]], 0
285 // CHECK-ARM64: [[HI:%.*]] = extractvalue { i64, i64 } [[LOHI]], 1
286 // CHECK-ARM64: call i32 @llvm.aarch64.stxp(i64 [[LO]], i64 [[HI]], ptr %addr)
289 __int128 test_ldaex_128(__int128 *addr) {
290 // CHECK-ARM64-LABEL: @test_ldaex_128
292 return __builtin_arm_ldaex(addr);
293 // CHECK-ARM64: [[STRUCTRES:%.*]] = call { i64, i64 } @llvm.aarch64.ldaxp(ptr %addr)
294 // CHECK-ARM64: [[RESHI:%.*]] = extractvalue { i64, i64 } [[STRUCTRES]], 1
295 // CHECK-ARM64: [[RESLO:%.*]] = extractvalue { i64, i64 } [[STRUCTRES]], 0
296 // CHECK-ARM64: [[RESHI64:%.*]] = zext i64 [[RESHI]] to i128
297 // CHECK-ARM64: [[RESLO64:%.*]] = zext i64 [[RESLO]] to i128
298 // CHECK-ARM64: [[RESHIHI:%.*]] = shl nuw i128 [[RESHI64]], 64
299 // CHECK-ARM64: [[INTRES:%.*]] = or i128 [[RESHIHI]], [[RESLO64]]
300 // CHECK-ARM64: ret i128 [[INTRES]]
303 int test_stlex_128(__int128 *addr, __int128 val) {
304 // CHECK-ARM64-LABEL: @test_stlex_128
306 return __builtin_arm_stlex(val, addr);
307 // CHECK-ARM64: store i128 %val, ptr [[TMP:%.*]], align 16
308 // CHECK-ARM64: [[LOHI:%.*]] = load { i64, i64 }, ptr [[TMP]]
309 // CHECK-ARM64: [[LO:%.*]] = extractvalue { i64, i64 } [[LOHI]], 0
310 // CHECK-ARM64: [[HI:%.*]] = extractvalue { i64, i64 } [[LOHI]], 1
311 // CHECK-ARM64: [[RES:%.*]] = call i32 @llvm.aarch64.stlxp(i64 [[LO]], i64 [[HI]], ptr %addr)
314 #endif