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
8 int test_ldrex(char *addr
, long long *addr64
, float *addrfloat
) {
9 // CHECK-LABEL: @test_ldrex
10 // CHECK-ARM64-LABEL: @test_ldrex
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
77 int test_ldaex(char *addr
, long long *addr64
, float *addrfloat
) {
78 // CHECK-LABEL: @test_ldaex
79 // CHECK-ARM64-LABEL: @test_ldaex
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
146 int test_strex(char *addr
) {
147 // CHECK-LABEL: @test_strex
148 // CHECK-ARM64-LABEL: @test_strex
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)
199 int test_stlex(char *addr
) {
200 // CHECK-LABEL: @test_stlex
201 // CHECK-ARM64-LABEL: @test_stlex
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)
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()
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)