1 ; RUN: llc < %s -mtriple=arm64-linux-gnu | FileCheck %s
2 ; RUN: llc < %s -global-isel -global-isel-abort=2 -pass-remarks-missed=gisel* -mtriple=arm64-linux-gnu 2>&1 | FileCheck %s --check-prefixes=GISEL,FALLBACK
6 define i128 @f0(i8* %p) nounwind readonly {
8 ; CHECK: ldxp {{x[0-9]+}}, {{x[0-9]+}}, [x0]
10 %ldrexd = tail call %0 @llvm.aarch64.ldxp(i8* %p)
11 %0 = extractvalue %0 %ldrexd, 1
12 %1 = extractvalue %0 %ldrexd, 0
13 %2 = zext i64 %0 to i128
14 %3 = zext i64 %1 to i128
15 %shl = shl nuw i128 %2, 64
20 define i32 @f1(i8* %ptr, i128 %val) nounwind {
22 ; CHECK: stxp {{w[0-9]+}}, {{x[0-9]+}}, {{x[0-9]+}}, [x0]
24 %tmp4 = trunc i128 %val to i64
25 %tmp6 = lshr i128 %val, 64
26 %tmp7 = trunc i128 %tmp6 to i64
27 %strexd = tail call i32 @llvm.aarch64.stxp(i64 %tmp4, i64 %tmp7, i8* %ptr)
31 declare %0 @llvm.aarch64.ldxp(i8*) nounwind
32 declare i32 @llvm.aarch64.stxp(i64, i64, i8*) nounwind
34 @var = global i64 0, align 8
36 ; FALLBACK-NOT: remark:{{.*}}test_load_i8
37 define void @test_load_i8(i8* %addr) {
38 ; CHECK-LABEL: test_load_i8:
39 ; CHECK: ldxrb w[[LOADVAL:[0-9]+]], [x0]
42 ; CHECK: str x[[LOADVAL]], [{{x[0-9]+}}, :lo12:var]
44 ; FIXME: GlobalISel doesn't fold ands/adds into load/store addressing modes
45 ; right now/ So, we won't get the :lo12:var.
46 ; GISEL-LABEL: test_load_i8:
47 ; GISEL: ldxrb w[[LOADVAL:[0-9]+]], [x0]
49 ; GISEL: str x[[LOADVAL]], [{{x[0-9]+}}]
50 %val = call i64 @llvm.aarch64.ldxr.p0i8(i8* %addr)
51 %shortval = trunc i64 %val to i8
52 %extval = zext i8 %shortval to i64
53 store i64 %extval, i64* @var, align 8
57 ; FALLBACK-NOT: remark:{{.*}}test_load_i16
58 define void @test_load_i16(i16* %addr) {
59 ; CHECK-LABEL: test_load_i16:
60 ; CHECK: ldxrh w[[LOADVAL:[0-9]+]], [x0]
63 ; CHECK: str x[[LOADVAL]], [{{x[0-9]+}}, :lo12:var]
65 ; GISEL-LABEL: test_load_i16:
66 ; GISEL: ldxrh w[[LOADVAL:[0-9]+]], [x0]
68 ; GISEL: str x[[LOADVAL]], [{{x[0-9]+}}]
69 %val = call i64 @llvm.aarch64.ldxr.p0i16(i16* %addr)
70 %shortval = trunc i64 %val to i16
71 %extval = zext i16 %shortval to i64
72 store i64 %extval, i64* @var, align 8
76 ; FALLBACK-NOT: remark:{{.*}}test_load_i32
77 define void @test_load_i32(i32* %addr) {
78 ; CHECK-LABEL: test_load_i32:
79 ; CHECK: ldxr w[[LOADVAL:[0-9]+]], [x0]
82 ; CHECK: str x[[LOADVAL]], [{{x[0-9]+}}, :lo12:var]
84 ; GISEL-LABEL: test_load_i32:
85 ; GISEL: ldxr w[[LOADVAL:[0-9]+]], [x0]
87 ; GISEL: str x[[LOADVAL]], [{{x[0-9]+}}]
88 %val = call i64 @llvm.aarch64.ldxr.p0i32(i32* %addr)
89 %shortval = trunc i64 %val to i32
90 %extval = zext i32 %shortval to i64
91 store i64 %extval, i64* @var, align 8
95 ; FALLBACK-NOT: remark:{{.*}}test_load_i64
96 define void @test_load_i64(i64* %addr) {
97 ; CHECK-LABEL: test_load_i64:
98 ; CHECK: ldxr x[[LOADVAL:[0-9]+]], [x0]
99 ; CHECK: str x[[LOADVAL]], [{{x[0-9]+}}, :lo12:var]
101 ; GISEL-LABEL: test_load_i64:
102 ; GISEL: ldxr x[[LOADVAL:[0-9]+]], [x0]
104 ; GISEL: str x[[LOADVAL]], [{{x[0-9]+}}]
105 %val = call i64 @llvm.aarch64.ldxr.p0i64(i64* %addr)
106 store i64 %val, i64* @var, align 8
111 declare i64 @llvm.aarch64.ldxr.p0i8(i8*) nounwind
112 declare i64 @llvm.aarch64.ldxr.p0i16(i16*) nounwind
113 declare i64 @llvm.aarch64.ldxr.p0i32(i32*) nounwind
114 declare i64 @llvm.aarch64.ldxr.p0i64(i64*) nounwind
116 ; FALLBACK-NOT: remark:{{.*}}test_store_i8
117 define i32 @test_store_i8(i32, i8 %val, i8* %addr) {
118 ; CHECK-LABEL: test_store_i8:
121 ; CHECK: stxrb w0, w1, [x2]
122 ; GISEL-LABEL: test_store_i8:
125 ; GISEL: stxrb w0, w1, [x2]
126 %extval = zext i8 %val to i64
127 %res = call i32 @llvm.aarch64.stxr.p0i8(i64 %extval, i8* %addr)
131 ; FALLBACK-NOT: remark:{{.*}}test_store_i16
132 define i32 @test_store_i16(i32, i16 %val, i16* %addr) {
133 ; CHECK-LABEL: test_store_i16:
136 ; CHECK: stxrh w0, w1, [x2]
137 ; GISEL-LABEL: test_store_i16:
140 ; GISEL: stxrh w0, w1, [x2]
141 %extval = zext i16 %val to i64
142 %res = call i32 @llvm.aarch64.stxr.p0i16(i64 %extval, i16* %addr)
146 ; FALLBACK-NOT: remark:{{.*}}test_store_i32
147 define i32 @test_store_i32(i32, i32 %val, i32* %addr) {
148 ; CHECK-LABEL: test_store_i32:
151 ; CHECK: stxr w0, w1, [x2]
152 ; GISEL-LABEL: test_store_i32:
155 ; GISEL: stxr w0, w1, [x2]
156 %extval = zext i32 %val to i64
157 %res = call i32 @llvm.aarch64.stxr.p0i32(i64 %extval, i32* %addr)
161 ; FALLBACK-NOT: remark:{{.*}}test_store_i64
162 define i32 @test_store_i64(i32, i64 %val, i64* %addr) {
163 ; CHECK-LABEL: test_store_i64:
164 ; CHECK: stxr w0, x1, [x2]
165 ; GISEL-LABEL: test_store_i64:
166 ; GISEL: stxr w0, x1, [x2]
167 %res = call i32 @llvm.aarch64.stxr.p0i64(i64 %val, i64* %addr)
171 declare i32 @llvm.aarch64.stxr.p0i8(i64, i8*) nounwind
172 declare i32 @llvm.aarch64.stxr.p0i16(i64, i16*) nounwind
173 declare i32 @llvm.aarch64.stxr.p0i32(i64, i32*) nounwind
174 declare i32 @llvm.aarch64.stxr.p0i64(i64, i64*) nounwind
178 define void @test_clear() {
179 call void @llvm.aarch64.clrex()
183 declare void @llvm.aarch64.clrex() nounwind
185 define i128 @test_load_acquire_i128(i8* %p) nounwind readonly {
186 ; CHECK-LABEL: test_load_acquire_i128:
187 ; CHECK: ldaxp {{x[0-9]+}}, {{x[0-9]+}}, [x0]
189 %ldrexd = tail call %0 @llvm.aarch64.ldaxp(i8* %p)
190 %0 = extractvalue %0 %ldrexd, 1
191 %1 = extractvalue %0 %ldrexd, 0
192 %2 = zext i64 %0 to i128
193 %3 = zext i64 %1 to i128
194 %shl = shl nuw i128 %2, 64
195 %4 = or i128 %shl, %3
199 define i32 @test_store_release_i128(i8* %ptr, i128 %val) nounwind {
200 ; CHECK-LABEL: test_store_release_i128:
201 ; CHECK: stlxp {{w[0-9]+}}, {{x[0-9]+}}, {{x[0-9]+}}, [x0]
203 %tmp4 = trunc i128 %val to i64
204 %tmp6 = lshr i128 %val, 64
205 %tmp7 = trunc i128 %tmp6 to i64
206 %strexd = tail call i32 @llvm.aarch64.stlxp(i64 %tmp4, i64 %tmp7, i8* %ptr)
210 declare %0 @llvm.aarch64.ldaxp(i8*) nounwind
211 declare i32 @llvm.aarch64.stlxp(i64, i64, i8*) nounwind
213 ; FALLBACK-NOT: remark:{{.*}}test_load_acquire_i8
214 define void @test_load_acquire_i8(i8* %addr) {
215 ; CHECK-LABEL: test_load_acquire_i8:
216 ; CHECK: ldaxrb w[[LOADVAL:[0-9]+]], [x0]
219 ; CHECK: str x[[LOADVAL]], [{{x[0-9]+}}, :lo12:var]
221 ; FIXME: GlobalISel doesn't fold ands/adds into load/store addressing modes
222 ; right now/ So, we won't get the :lo12:var.
223 ; GISEL-LABEL: test_load_acquire_i8:
224 ; GISEL: ldaxrb w[[LOADVAL:[0-9]+]], [x0]
225 ; GISEL-DAG: str x[[LOADVAL]], [{{x[0-9]+}}]
226 %val = call i64 @llvm.aarch64.ldaxr.p0i8(i8* %addr)
227 %shortval = trunc i64 %val to i8
228 %extval = zext i8 %shortval to i64
229 store i64 %extval, i64* @var, align 8
233 ; FALLBACK-NOT: remark:{{.*}}test_load_acquire_i16
234 define void @test_load_acquire_i16(i16* %addr) {
235 ; CHECK-LABEL: test_load_acquire_i16:
236 ; CHECK: ldaxrh w[[LOADVAL:[0-9]+]], [x0]
239 ; CHECK: str x[[LOADVAL]], [{{x[0-9]+}}, :lo12:var]
241 ; GISEL-LABEL: test_load_acquire_i16:
242 ; GISEL: ldaxrh w[[LOADVAL:[0-9]+]], [x0]
243 ; GISEL: str x[[LOADVAL]], [{{x[0-9]+}}]
244 %val = call i64 @llvm.aarch64.ldaxr.p0i16(i16* %addr)
245 %shortval = trunc i64 %val to i16
246 %extval = zext i16 %shortval to i64
247 store i64 %extval, i64* @var, align 8
251 ; FALLBACK-NOT: remark:{{.*}}test_load_acquire_i32
252 define void @test_load_acquire_i32(i32* %addr) {
253 ; CHECK-LABEL: test_load_acquire_i32:
254 ; CHECK: ldaxr w[[LOADVAL:[0-9]+]], [x0]
257 ; CHECK: str x[[LOADVAL]], [{{x[0-9]+}}, :lo12:var]
259 ; GISEL-LABEL: test_load_acquire_i32:
260 ; GISEL: ldaxr w[[LOADVAL:[0-9]+]], [x0]
261 ; GISEL: str x[[LOADVAL]], [{{x[0-9]+}}]
262 %val = call i64 @llvm.aarch64.ldaxr.p0i32(i32* %addr)
263 %shortval = trunc i64 %val to i32
264 %extval = zext i32 %shortval to i64
265 store i64 %extval, i64* @var, align 8
269 ; FALLBACK-NOT: remark:{{.*}}test_load_acquire_i64
270 define void @test_load_acquire_i64(i64* %addr) {
271 ; CHECK-LABEL: test_load_acquire_i64:
272 ; CHECK: ldaxr x[[LOADVAL:[0-9]+]], [x0]
273 ; CHECK: str x[[LOADVAL]], [{{x[0-9]+}}, :lo12:var]
275 ; GISEL-LABEL: test_load_acquire_i64:
276 ; GISEL: ldaxr x[[LOADVAL:[0-9]+]], [x0]
277 ; GISEL: str x[[LOADVAL]], [{{x[0-9]+}}]
278 %val = call i64 @llvm.aarch64.ldaxr.p0i64(i64* %addr)
279 store i64 %val, i64* @var, align 8
284 declare i64 @llvm.aarch64.ldaxr.p0i8(i8*) nounwind
285 declare i64 @llvm.aarch64.ldaxr.p0i16(i16*) nounwind
286 declare i64 @llvm.aarch64.ldaxr.p0i32(i32*) nounwind
287 declare i64 @llvm.aarch64.ldaxr.p0i64(i64*) nounwind
289 ; FALLBACK-NOT: remark:{{.*}}test_store_release_i8
290 define i32 @test_store_release_i8(i32, i8 %val, i8* %addr) {
291 ; CHECK-LABEL: test_store_release_i8:
294 ; CHECK: stlxrb w0, w1, [x2]
295 ; GISEL-LABEL: test_store_release_i8:
298 ; GISEL: stlxrb w0, w1, [x2]
299 %extval = zext i8 %val to i64
300 %res = call i32 @llvm.aarch64.stlxr.p0i8(i64 %extval, i8* %addr)
304 ; FALLBACK-NOT: remark:{{.*}}test_store_release_i16
305 define i32 @test_store_release_i16(i32, i16 %val, i16* %addr) {
306 ; CHECK-LABEL: test_store_release_i16:
309 ; CHECK: stlxrh w0, w1, [x2]
310 ; GISEL-LABEL: test_store_release_i16:
313 ; GISEL: stlxrh w0, w1, [x2]
314 %extval = zext i16 %val to i64
315 %res = call i32 @llvm.aarch64.stlxr.p0i16(i64 %extval, i16* %addr)
319 ; FALLBACK-NOT: remark:{{.*}}test_store_release_i32
320 define i32 @test_store_release_i32(i32, i32 %val, i32* %addr) {
321 ; CHECK-LABEL: test_store_release_i32:
324 ; CHECK: stlxr w0, w1, [x2]
325 ; GISEL-LABEL: test_store_release_i32:
328 ; GISEL: stlxr w0, w1, [x2]
329 %extval = zext i32 %val to i64
330 %res = call i32 @llvm.aarch64.stlxr.p0i32(i64 %extval, i32* %addr)
334 ; FALLBACK-NOT: remark:{{.*}}test_store_release_i64
335 define i32 @test_store_release_i64(i32, i64 %val, i64* %addr) {
336 ; CHECK-LABEL: test_store_release_i64:
337 ; CHECK: stlxr w0, x1, [x2]
338 ; GISEL-LABEL: test_store_release_i64:
339 ; GISEL: stlxr w0, x1, [x2]
340 %res = call i32 @llvm.aarch64.stlxr.p0i64(i64 %val, i64* %addr)
344 declare i32 @llvm.aarch64.stlxr.p0i8(i64, i8*) nounwind
345 declare i32 @llvm.aarch64.stlxr.p0i16(i64, i16*) nounwind
346 declare i32 @llvm.aarch64.stlxr.p0i32(i64, i32*) nounwind
347 declare i32 @llvm.aarch64.stlxr.p0i64(i64, i64*) nounwind