[InstCombine] Signed saturation patterns
[llvm-complete.git] / test / CodeGen / AArch64 / arm64-ldxr-stxr.ll
blobaa9c5dfff5b7a1817adb4882c418bb87f8266f93
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
4 %0 = type { i64, i64 }
6 define i128 @f0(i8* %p) nounwind readonly {
7 ; CHECK-LABEL: f0:
8 ; CHECK: ldxp {{x[0-9]+}}, {{x[0-9]+}}, [x0]
9 entry:
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
16   %4 = or i128 %shl, %3
17   ret i128 %4
20 define i32 @f1(i8* %ptr, i128 %val) nounwind {
21 ; CHECK-LABEL: f1:
22 ; CHECK: stxp {{w[0-9]+}}, {{x[0-9]+}}, {{x[0-9]+}}, [x0]
23 entry:
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)
28   ret i32 %strexd
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]
40 ; CHECK-NOT: uxtb
41 ; CHECK-NOT: and
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]
48 ; GISEL-NOT: uxtb
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
54   ret void
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]
61 ; CHECK-NOT: uxth
62 ; CHECK-NOT: and
63 ; CHECK: str x[[LOADVAL]], [{{x[0-9]+}}, :lo12:var]
65 ; GISEL-LABEL: test_load_i16:
66 ; GISEL: ldxrh w[[LOADVAL:[0-9]+]], [x0]
67 ; GISEL-NOT: uxtb
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
73   ret void
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]
80 ; CHECK-NOT: uxtw
81 ; CHECK-NOT: and
82 ; CHECK: str x[[LOADVAL]], [{{x[0-9]+}}, :lo12:var]
84 ; GISEL-LABEL: test_load_i32:
85 ; GISEL: ldxr w[[LOADVAL:[0-9]+]], [x0]
86 ; GISEL-NOT: uxtb
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
92   ret void
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]
103 ; GISEL-NOT: uxtb
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
107   ret void
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:
119 ; CHECK-NOT: uxtb
120 ; CHECK-NOT: and
121 ; CHECK: stxrb w0, w1, [x2]
122 ; GISEL-LABEL: test_store_i8:
123 ; GISEL-NOT: uxtb
124 ; GISEL-NOT: and
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)
128   ret i32 %res
131 ; FALLBACK-NOT: remark:{{.*}}test_store_i16
132 define i32 @test_store_i16(i32, i16 %val, i16* %addr) {
133 ; CHECK-LABEL: test_store_i16:
134 ; CHECK-NOT: uxth
135 ; CHECK-NOT: and
136 ; CHECK: stxrh w0, w1, [x2]
137 ; GISEL-LABEL: test_store_i16:
138 ; GISEL-NOT: uxth
139 ; GISEL-NOT: and
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)
143   ret i32 %res
146 ; FALLBACK-NOT: remark:{{.*}}test_store_i32
147 define i32 @test_store_i32(i32, i32 %val, i32* %addr) {
148 ; CHECK-LABEL: test_store_i32:
149 ; CHECK-NOT: uxtw
150 ; CHECK-NOT: and
151 ; CHECK: stxr w0, w1, [x2]
152 ; GISEL-LABEL: test_store_i32:
153 ; GISEL-NOT: uxtw
154 ; GISEL-NOT: and
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)
158   ret i32 %res
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)
168   ret i32 %res
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
176 ; CHECK: test_clear:
177 ; CHECK: clrex
178 define void @test_clear() {
179   call void @llvm.aarch64.clrex()
180   ret void
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]
188 entry:
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
196   ret i128 %4
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]
202 entry:
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)
207   ret i32 %strexd
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]
217 ; CHECK-NOT: uxtb
218 ; CHECK-NOT: and
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
230   ret void
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]
237 ; CHECK-NOT: uxth
238 ; CHECK-NOT: and
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
248   ret void
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]
255 ; CHECK-NOT: uxtw
256 ; CHECK-NOT: and
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
266   ret void
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
280   ret void
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:
292 ; CHECK-NOT: uxtb
293 ; CHECK-NOT: and
294 ; CHECK: stlxrb w0, w1, [x2]
295 ; GISEL-LABEL: test_store_release_i8:
296 ; GISEL-NOT: uxtb
297 ; GISEL-NOT: and
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)
301   ret i32 %res
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:
307 ; CHECK-NOT: uxth
308 ; CHECK-NOT: and
309 ; CHECK: stlxrh w0, w1, [x2]
310 ; GISEL-LABEL: test_store_release_i16:
311 ; GISEL-NOT: uxth
312 ; GISEL-NOT: and
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)
316   ret i32 %res
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:
322 ; CHECK-NOT: uxtw
323 ; CHECK-NOT: and
324 ; CHECK: stlxr w0, w1, [x2]
325 ; GISEL-LABEL: test_store_release_i32:
326 ; GISEL-NOT: uxtw
327 ; GISEL-NOT: and
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)
331   ret i32 %res
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)
341   ret i32 %res
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