[ARM] More MVE compare vector splat combines for ANDs
[llvm-complete.git] / test / CodeGen / AArch64 / arm64-ldxr-stxr.ll
blob4f87121c6ae419babaad0ddf460da15555aa9c48
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 define void @test_load_i8(i8* %addr) {
37 ; CHECK-LABEL: test_load_i8:
38 ; CHECK: ldxrb w[[LOADVAL:[0-9]+]], [x0]
39 ; CHECK-NOT: uxtb
40 ; CHECK-NOT: and
41 ; CHECK: str x[[LOADVAL]], [{{x[0-9]+}}, :lo12:var]
43   %val = call i64 @llvm.aarch64.ldxr.p0i8(i8* %addr)
44   %shortval = trunc i64 %val to i8
45   %extval = zext i8 %shortval to i64
46   store i64 %extval, i64* @var, align 8
47   ret void
50 define void @test_load_i16(i16* %addr) {
51 ; CHECK-LABEL: test_load_i16:
52 ; CHECK: ldxrh w[[LOADVAL:[0-9]+]], [x0]
53 ; CHECK-NOT: uxth
54 ; CHECK-NOT: and
55 ; CHECK: str x[[LOADVAL]], [{{x[0-9]+}}, :lo12:var]
57   %val = call i64 @llvm.aarch64.ldxr.p0i16(i16* %addr)
58   %shortval = trunc i64 %val to i16
59   %extval = zext i16 %shortval to i64
60   store i64 %extval, i64* @var, align 8
61   ret void
64 define void @test_load_i32(i32* %addr) {
65 ; CHECK-LABEL: test_load_i32:
66 ; CHECK: ldxr w[[LOADVAL:[0-9]+]], [x0]
67 ; CHECK-NOT: uxtw
68 ; CHECK-NOT: and
69 ; CHECK: str x[[LOADVAL]], [{{x[0-9]+}}, :lo12:var]
71   %val = call i64 @llvm.aarch64.ldxr.p0i32(i32* %addr)
72   %shortval = trunc i64 %val to i32
73   %extval = zext i32 %shortval to i64
74   store i64 %extval, i64* @var, align 8
75   ret void
78 define void @test_load_i64(i64* %addr) {
79 ; CHECK-LABEL: test_load_i64:
80 ; CHECK: ldxr x[[LOADVAL:[0-9]+]], [x0]
81 ; CHECK: str x[[LOADVAL]], [{{x[0-9]+}}, :lo12:var]
83   %val = call i64 @llvm.aarch64.ldxr.p0i64(i64* %addr)
84   store i64 %val, i64* @var, align 8
85   ret void
89 declare i64 @llvm.aarch64.ldxr.p0i8(i8*) nounwind
90 declare i64 @llvm.aarch64.ldxr.p0i16(i16*) nounwind
91 declare i64 @llvm.aarch64.ldxr.p0i32(i32*) nounwind
92 declare i64 @llvm.aarch64.ldxr.p0i64(i64*) nounwind
94 define i32 @test_store_i8(i32, i8 %val, i8* %addr) {
95 ; CHECK-LABEL: test_store_i8:
96 ; CHECK-NOT: uxtb
97 ; CHECK-NOT: and
98 ; CHECK: stxrb w0, w1, [x2]
99   %extval = zext i8 %val to i64
100   %res = call i32 @llvm.aarch64.stxr.p0i8(i64 %extval, i8* %addr)
101   ret i32 %res
104 define i32 @test_store_i16(i32, i16 %val, i16* %addr) {
105 ; CHECK-LABEL: test_store_i16:
106 ; CHECK-NOT: uxth
107 ; CHECK-NOT: and
108 ; CHECK: stxrh w0, w1, [x2]
109   %extval = zext i16 %val to i64
110   %res = call i32 @llvm.aarch64.stxr.p0i16(i64 %extval, i16* %addr)
111   ret i32 %res
114 define i32 @test_store_i32(i32, i32 %val, i32* %addr) {
115 ; CHECK-LABEL: test_store_i32:
116 ; CHECK-NOT: uxtw
117 ; CHECK-NOT: and
118 ; CHECK: stxr w0, w1, [x2]
119   %extval = zext i32 %val to i64
120   %res = call i32 @llvm.aarch64.stxr.p0i32(i64 %extval, i32* %addr)
121   ret i32 %res
124 define i32 @test_store_i64(i32, i64 %val, i64* %addr) {
125 ; CHECK-LABEL: test_store_i64:
126 ; CHECK: stxr w0, x1, [x2]
127   %res = call i32 @llvm.aarch64.stxr.p0i64(i64 %val, i64* %addr)
128   ret i32 %res
131 declare i32 @llvm.aarch64.stxr.p0i8(i64, i8*) nounwind
132 declare i32 @llvm.aarch64.stxr.p0i16(i64, i16*) nounwind
133 declare i32 @llvm.aarch64.stxr.p0i32(i64, i32*) nounwind
134 declare i32 @llvm.aarch64.stxr.p0i64(i64, i64*) nounwind
136 ; CHECK: test_clear:
137 ; CHECK: clrex
138 define void @test_clear() {
139   call void @llvm.aarch64.clrex()
140   ret void
143 declare void @llvm.aarch64.clrex() nounwind
145 define i128 @test_load_acquire_i128(i8* %p) nounwind readonly {
146 ; CHECK-LABEL: test_load_acquire_i128:
147 ; CHECK: ldaxp {{x[0-9]+}}, {{x[0-9]+}}, [x0]
148 entry:
149   %ldrexd = tail call %0 @llvm.aarch64.ldaxp(i8* %p)
150   %0 = extractvalue %0 %ldrexd, 1
151   %1 = extractvalue %0 %ldrexd, 0
152   %2 = zext i64 %0 to i128
153   %3 = zext i64 %1 to i128
154   %shl = shl nuw i128 %2, 64
155   %4 = or i128 %shl, %3
156   ret i128 %4
159 define i32 @test_store_release_i128(i8* %ptr, i128 %val) nounwind {
160 ; CHECK-LABEL: test_store_release_i128:
161 ; CHECK: stlxp {{w[0-9]+}}, {{x[0-9]+}}, {{x[0-9]+}}, [x0]
162 entry:
163   %tmp4 = trunc i128 %val to i64
164   %tmp6 = lshr i128 %val, 64
165   %tmp7 = trunc i128 %tmp6 to i64
166   %strexd = tail call i32 @llvm.aarch64.stlxp(i64 %tmp4, i64 %tmp7, i8* %ptr)
167   ret i32 %strexd
170 declare %0 @llvm.aarch64.ldaxp(i8*) nounwind
171 declare i32 @llvm.aarch64.stlxp(i64, i64, i8*) nounwind
173 define void @test_load_acquire_i8(i8* %addr) {
174 ; CHECK-LABEL: test_load_acquire_i8:
175 ; CHECK: ldaxrb w[[LOADVAL:[0-9]+]], [x0]
176 ; CHECK-NOT: uxtb
177 ; CHECK-NOT: and
178 ; CHECK: str x[[LOADVAL]], [{{x[0-9]+}}, :lo12:var]
180   %val = call i64 @llvm.aarch64.ldaxr.p0i8(i8* %addr)
181   %shortval = trunc i64 %val to i8
182   %extval = zext i8 %shortval to i64
183   store i64 %extval, i64* @var, align 8
184   ret void
187 define void @test_load_acquire_i16(i16* %addr) {
188 ; CHECK-LABEL: test_load_acquire_i16:
189 ; CHECK: ldaxrh w[[LOADVAL:[0-9]+]], [x0]
190 ; CHECK-NOT: uxth
191 ; CHECK-NOT: and
192 ; CHECK: str x[[LOADVAL]], [{{x[0-9]+}}, :lo12:var]
194   %val = call i64 @llvm.aarch64.ldaxr.p0i16(i16* %addr)
195   %shortval = trunc i64 %val to i16
196   %extval = zext i16 %shortval to i64
197   store i64 %extval, i64* @var, align 8
198   ret void
201 define void @test_load_acquire_i32(i32* %addr) {
202 ; CHECK-LABEL: test_load_acquire_i32:
203 ; CHECK: ldaxr w[[LOADVAL:[0-9]+]], [x0]
204 ; CHECK-NOT: uxtw
205 ; CHECK-NOT: and
206 ; CHECK: str x[[LOADVAL]], [{{x[0-9]+}}, :lo12:var]
208   %val = call i64 @llvm.aarch64.ldaxr.p0i32(i32* %addr)
209   %shortval = trunc i64 %val to i32
210   %extval = zext i32 %shortval to i64
211   store i64 %extval, i64* @var, align 8
212   ret void
215 define void @test_load_acquire_i64(i64* %addr) {
216 ; CHECK-LABEL: test_load_acquire_i64:
217 ; CHECK: ldaxr x[[LOADVAL:[0-9]+]], [x0]
218 ; CHECK: str x[[LOADVAL]], [{{x[0-9]+}}, :lo12:var]
220   %val = call i64 @llvm.aarch64.ldaxr.p0i64(i64* %addr)
221   store i64 %val, i64* @var, align 8
222   ret void
226 declare i64 @llvm.aarch64.ldaxr.p0i8(i8*) nounwind
227 declare i64 @llvm.aarch64.ldaxr.p0i16(i16*) nounwind
228 declare i64 @llvm.aarch64.ldaxr.p0i32(i32*) nounwind
229 declare i64 @llvm.aarch64.ldaxr.p0i64(i64*) nounwind
231 define i32 @test_store_release_i8(i32, i8 %val, i8* %addr) {
232 ; CHECK-LABEL: test_store_release_i8:
233 ; CHECK-NOT: uxtb
234 ; CHECK-NOT: and
235 ; CHECK: stlxrb w0, w1, [x2]
236   %extval = zext i8 %val to i64
237   %res = call i32 @llvm.aarch64.stlxr.p0i8(i64 %extval, i8* %addr)
238   ret i32 %res
241 define i32 @test_store_release_i16(i32, i16 %val, i16* %addr) {
242 ; CHECK-LABEL: test_store_release_i16:
243 ; CHECK-NOT: uxth
244 ; CHECK-NOT: and
245 ; CHECK: stlxrh w0, w1, [x2]
246   %extval = zext i16 %val to i64
247   %res = call i32 @llvm.aarch64.stlxr.p0i16(i64 %extval, i16* %addr)
248   ret i32 %res
251 define i32 @test_store_release_i32(i32, i32 %val, i32* %addr) {
252 ; CHECK-LABEL: test_store_release_i32:
253 ; CHECK-NOT: uxtw
254 ; CHECK-NOT: and
255 ; CHECK: stlxr w0, w1, [x2]
256   %extval = zext i32 %val to i64
257   %res = call i32 @llvm.aarch64.stlxr.p0i32(i64 %extval, i32* %addr)
258   ret i32 %res
261 ; FALLBACK-NOT: remark:{{.*}}test_store_release_i64
262 define i32 @test_store_release_i64(i32, i64 %val, i64* %addr) {
263 ; CHECK-LABEL: test_store_release_i64:
264 ; CHECK: stlxr w0, x1, [x2]
265 ; GISEL-LABEL: test_store_release_i64:
266 ; GISEL: stlxr w0, x1, [x2]
267   %res = call i32 @llvm.aarch64.stlxr.p0i64(i64 %val, i64* %addr)
268   ret i32 %res
271 declare i32 @llvm.aarch64.stlxr.p0i8(i64, i8*) nounwind
272 declare i32 @llvm.aarch64.stlxr.p0i16(i64, i16*) nounwind
273 declare i32 @llvm.aarch64.stlxr.p0i32(i64, i32*) nounwind
274 declare i32 @llvm.aarch64.stlxr.p0i64(i64, i64*) nounwind