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 define void @test_load_i8(i8* %addr) {
37 ; CHECK-LABEL: test_load_i8:
38 ; CHECK: ldxrb w[[LOADVAL:[0-9]+]], [x0]
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
50 define void @test_load_i16(i16* %addr) {
51 ; CHECK-LABEL: test_load_i16:
52 ; CHECK: ldxrh w[[LOADVAL:[0-9]+]], [x0]
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
64 define void @test_load_i32(i32* %addr) {
65 ; CHECK-LABEL: test_load_i32:
66 ; CHECK: ldxr w[[LOADVAL:[0-9]+]], [x0]
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
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
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:
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)
104 define i32 @test_store_i16(i32, i16 %val, i16* %addr) {
105 ; CHECK-LABEL: test_store_i16:
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)
114 define i32 @test_store_i32(i32, i32 %val, i32* %addr) {
115 ; CHECK-LABEL: test_store_i32:
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)
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)
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
138 define void @test_clear() {
139 call void @llvm.aarch64.clrex()
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]
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
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]
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)
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]
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
187 define void @test_load_acquire_i16(i16* %addr) {
188 ; CHECK-LABEL: test_load_acquire_i16:
189 ; CHECK: ldaxrh w[[LOADVAL:[0-9]+]], [x0]
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
201 define void @test_load_acquire_i32(i32* %addr) {
202 ; CHECK-LABEL: test_load_acquire_i32:
203 ; CHECK: ldaxr w[[LOADVAL:[0-9]+]], [x0]
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
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
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:
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)
241 define i32 @test_store_release_i16(i32, i16 %val, i16* %addr) {
242 ; CHECK-LABEL: test_store_release_i16:
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)
251 define i32 @test_store_release_i32(i32, i32 %val, i32* %addr) {
252 ; CHECK-LABEL: test_store_release_i32:
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)
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)
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