Revert "[AArch64] Add DAG combine for extract extend pattern"
[oota-llvm.git] / test / CodeGen / AArch64 / arm64-ldxr-stxr.ll
1 ; RUN: llc < %s -mtriple=arm64-linux-gnu | FileCheck %s
2
3 %0 = type { i64, i64 }
4
5 define i128 @f0(i8* %p) nounwind readonly {
6 ; CHECK-LABEL: f0:
7 ; CHECK: ldxp {{x[0-9]+}}, {{x[0-9]+}}, [x0]
8 entry:
9   %ldrexd = tail call %0 @llvm.aarch64.ldxp(i8* %p)
10   %0 = extractvalue %0 %ldrexd, 1
11   %1 = extractvalue %0 %ldrexd, 0
12   %2 = zext i64 %0 to i128
13   %3 = zext i64 %1 to i128
14   %shl = shl nuw i128 %2, 64
15   %4 = or i128 %shl, %3
16   ret i128 %4
17 }
18
19 define i32 @f1(i8* %ptr, i128 %val) nounwind {
20 ; CHECK-LABEL: f1:
21 ; CHECK: stxp {{w[0-9]+}}, {{x[0-9]+}}, {{x[0-9]+}}, [x0]
22 entry:
23   %tmp4 = trunc i128 %val to i64
24   %tmp6 = lshr i128 %val, 64
25   %tmp7 = trunc i128 %tmp6 to i64
26   %strexd = tail call i32 @llvm.aarch64.stxp(i64 %tmp4, i64 %tmp7, i8* %ptr)
27   ret i32 %strexd
28 }
29
30 declare %0 @llvm.aarch64.ldxp(i8*) nounwind
31 declare i32 @llvm.aarch64.stxp(i64, i64, i8*) nounwind
32
33 @var = global i64 0, align 8
34
35 define void @test_load_i8(i8* %addr) {
36 ; CHECK-LABEL: test_load_i8:
37 ; CHECK: ldxrb w[[LOADVAL:[0-9]+]], [x0]
38 ; CHECK-NOT: uxtb
39 ; CHECK-NOT: and
40 ; CHECK: str x[[LOADVAL]], [{{x[0-9]+}}, :lo12:var]
41
42   %val = call i64 @llvm.aarch64.ldxr.p0i8(i8* %addr)
43   %shortval = trunc i64 %val to i8
44   %extval = zext i8 %shortval to i64
45   store i64 %extval, i64* @var, align 8
46   ret void
47 }
48
49 define void @test_load_i16(i16* %addr) {
50 ; CHECK-LABEL: test_load_i16:
51 ; CHECK: ldxrh w[[LOADVAL:[0-9]+]], [x0]
52 ; CHECK-NOT: uxth
53 ; CHECK-NOT: and
54 ; CHECK: str x[[LOADVAL]], [{{x[0-9]+}}, :lo12:var]
55
56   %val = call i64 @llvm.aarch64.ldxr.p0i16(i16* %addr)
57   %shortval = trunc i64 %val to i16
58   %extval = zext i16 %shortval to i64
59   store i64 %extval, i64* @var, align 8
60   ret void
61 }
62
63 define void @test_load_i32(i32* %addr) {
64 ; CHECK-LABEL: test_load_i32:
65 ; CHECK: ldxr w[[LOADVAL:[0-9]+]], [x0]
66 ; CHECK-NOT: uxtw
67 ; CHECK-NOT: and
68 ; CHECK: str x[[LOADVAL]], [{{x[0-9]+}}, :lo12:var]
69
70   %val = call i64 @llvm.aarch64.ldxr.p0i32(i32* %addr)
71   %shortval = trunc i64 %val to i32
72   %extval = zext i32 %shortval to i64
73   store i64 %extval, i64* @var, align 8
74   ret void
75 }
76
77 define void @test_load_i64(i64* %addr) {
78 ; CHECK-LABEL: test_load_i64:
79 ; CHECK: ldxr x[[LOADVAL:[0-9]+]], [x0]
80 ; CHECK: str x[[LOADVAL]], [{{x[0-9]+}}, :lo12:var]
81
82   %val = call i64 @llvm.aarch64.ldxr.p0i64(i64* %addr)
83   store i64 %val, i64* @var, align 8
84   ret void
85 }
86
87
88 declare i64 @llvm.aarch64.ldxr.p0i8(i8*) nounwind
89 declare i64 @llvm.aarch64.ldxr.p0i16(i16*) nounwind
90 declare i64 @llvm.aarch64.ldxr.p0i32(i32*) nounwind
91 declare i64 @llvm.aarch64.ldxr.p0i64(i64*) nounwind
92
93 define i32 @test_store_i8(i32, i8 %val, i8* %addr) {
94 ; CHECK-LABEL: test_store_i8:
95 ; CHECK-NOT: uxtb
96 ; CHECK-NOT: and
97 ; CHECK: stxrb w0, w1, [x2]
98   %extval = zext i8 %val to i64
99   %res = call i32 @llvm.aarch64.stxr.p0i8(i64 %extval, i8* %addr)
100   ret i32 %res
101 }
102
103 define i32 @test_store_i16(i32, i16 %val, i16* %addr) {
104 ; CHECK-LABEL: test_store_i16:
105 ; CHECK-NOT: uxth
106 ; CHECK-NOT: and
107 ; CHECK: stxrh w0, w1, [x2]
108   %extval = zext i16 %val to i64
109   %res = call i32 @llvm.aarch64.stxr.p0i16(i64 %extval, i16* %addr)
110   ret i32 %res
111 }
112
113 define i32 @test_store_i32(i32, i32 %val, i32* %addr) {
114 ; CHECK-LABEL: test_store_i32:
115 ; CHECK-NOT: uxtw
116 ; CHECK-NOT: and
117 ; CHECK: stxr w0, w1, [x2]
118   %extval = zext i32 %val to i64
119   %res = call i32 @llvm.aarch64.stxr.p0i32(i64 %extval, i32* %addr)
120   ret i32 %res
121 }
122
123 define i32 @test_store_i64(i32, i64 %val, i64* %addr) {
124 ; CHECK-LABEL: test_store_i64:
125 ; CHECK: stxr w0, x1, [x2]
126   %res = call i32 @llvm.aarch64.stxr.p0i64(i64 %val, i64* %addr)
127   ret i32 %res
128 }
129
130 declare i32 @llvm.aarch64.stxr.p0i8(i64, i8*) nounwind
131 declare i32 @llvm.aarch64.stxr.p0i16(i64, i16*) nounwind
132 declare i32 @llvm.aarch64.stxr.p0i32(i64, i32*) nounwind
133 declare i32 @llvm.aarch64.stxr.p0i64(i64, i64*) nounwind
134
135 ; CHECK: test_clear:
136 ; CHECK: clrex
137 define void @test_clear() {
138   call void @llvm.aarch64.clrex()
139   ret void
140 }
141
142 declare void @llvm.aarch64.clrex() nounwind
143
144 define i128 @test_load_acquire_i128(i8* %p) nounwind readonly {
145 ; CHECK-LABEL: test_load_acquire_i128:
146 ; CHECK: ldaxp {{x[0-9]+}}, {{x[0-9]+}}, [x0]
147 entry:
148   %ldrexd = tail call %0 @llvm.aarch64.ldaxp(i8* %p)
149   %0 = extractvalue %0 %ldrexd, 1
150   %1 = extractvalue %0 %ldrexd, 0
151   %2 = zext i64 %0 to i128
152   %3 = zext i64 %1 to i128
153   %shl = shl nuw i128 %2, 64
154   %4 = or i128 %shl, %3
155   ret i128 %4
156 }
157
158 define i32 @test_store_release_i128(i8* %ptr, i128 %val) nounwind {
159 ; CHECK-LABEL: test_store_release_i128:
160 ; CHECK: stlxp {{w[0-9]+}}, {{x[0-9]+}}, {{x[0-9]+}}, [x0]
161 entry:
162   %tmp4 = trunc i128 %val to i64
163   %tmp6 = lshr i128 %val, 64
164   %tmp7 = trunc i128 %tmp6 to i64
165   %strexd = tail call i32 @llvm.aarch64.stlxp(i64 %tmp4, i64 %tmp7, i8* %ptr)
166   ret i32 %strexd
167 }
168
169 declare %0 @llvm.aarch64.ldaxp(i8*) nounwind
170 declare i32 @llvm.aarch64.stlxp(i64, i64, i8*) nounwind
171
172 define void @test_load_acquire_i8(i8* %addr) {
173 ; CHECK-LABEL: test_load_acquire_i8:
174 ; CHECK: ldaxrb w[[LOADVAL:[0-9]+]], [x0]
175 ; CHECK-NOT: uxtb
176 ; CHECK-NOT: and
177 ; CHECK: str x[[LOADVAL]], [{{x[0-9]+}}, :lo12:var]
178
179   %val = call i64 @llvm.aarch64.ldaxr.p0i8(i8* %addr)
180   %shortval = trunc i64 %val to i8
181   %extval = zext i8 %shortval to i64
182   store i64 %extval, i64* @var, align 8
183   ret void
184 }
185
186 define void @test_load_acquire_i16(i16* %addr) {
187 ; CHECK-LABEL: test_load_acquire_i16:
188 ; CHECK: ldaxrh w[[LOADVAL:[0-9]+]], [x0]
189 ; CHECK-NOT: uxth
190 ; CHECK-NOT: and
191 ; CHECK: str x[[LOADVAL]], [{{x[0-9]+}}, :lo12:var]
192
193   %val = call i64 @llvm.aarch64.ldaxr.p0i16(i16* %addr)
194   %shortval = trunc i64 %val to i16
195   %extval = zext i16 %shortval to i64
196   store i64 %extval, i64* @var, align 8
197   ret void
198 }
199
200 define void @test_load_acquire_i32(i32* %addr) {
201 ; CHECK-LABEL: test_load_acquire_i32:
202 ; CHECK: ldaxr w[[LOADVAL:[0-9]+]], [x0]
203 ; CHECK-NOT: uxtw
204 ; CHECK-NOT: and
205 ; CHECK: str x[[LOADVAL]], [{{x[0-9]+}}, :lo12:var]
206
207   %val = call i64 @llvm.aarch64.ldaxr.p0i32(i32* %addr)
208   %shortval = trunc i64 %val to i32
209   %extval = zext i32 %shortval to i64
210   store i64 %extval, i64* @var, align 8
211   ret void
212 }
213
214 define void @test_load_acquire_i64(i64* %addr) {
215 ; CHECK-LABEL: test_load_acquire_i64:
216 ; CHECK: ldaxr x[[LOADVAL:[0-9]+]], [x0]
217 ; CHECK: str x[[LOADVAL]], [{{x[0-9]+}}, :lo12:var]
218
219   %val = call i64 @llvm.aarch64.ldaxr.p0i64(i64* %addr)
220   store i64 %val, i64* @var, align 8
221   ret void
222 }
223
224
225 declare i64 @llvm.aarch64.ldaxr.p0i8(i8*) nounwind
226 declare i64 @llvm.aarch64.ldaxr.p0i16(i16*) nounwind
227 declare i64 @llvm.aarch64.ldaxr.p0i32(i32*) nounwind
228 declare i64 @llvm.aarch64.ldaxr.p0i64(i64*) nounwind
229
230 define i32 @test_store_release_i8(i32, i8 %val, i8* %addr) {
231 ; CHECK-LABEL: test_store_release_i8:
232 ; CHECK-NOT: uxtb
233 ; CHECK-NOT: and
234 ; CHECK: stlxrb w0, w1, [x2]
235   %extval = zext i8 %val to i64
236   %res = call i32 @llvm.aarch64.stlxr.p0i8(i64 %extval, i8* %addr)
237   ret i32 %res
238 }
239
240 define i32 @test_store_release_i16(i32, i16 %val, i16* %addr) {
241 ; CHECK-LABEL: test_store_release_i16:
242 ; CHECK-NOT: uxth
243 ; CHECK-NOT: and
244 ; CHECK: stlxrh w0, w1, [x2]
245   %extval = zext i16 %val to i64
246   %res = call i32 @llvm.aarch64.stlxr.p0i16(i64 %extval, i16* %addr)
247   ret i32 %res
248 }
249
250 define i32 @test_store_release_i32(i32, i32 %val, i32* %addr) {
251 ; CHECK-LABEL: test_store_release_i32:
252 ; CHECK-NOT: uxtw
253 ; CHECK-NOT: and
254 ; CHECK: stlxr w0, w1, [x2]
255   %extval = zext i32 %val to i64
256   %res = call i32 @llvm.aarch64.stlxr.p0i32(i64 %extval, i32* %addr)
257   ret i32 %res
258 }
259
260 define i32 @test_store_release_i64(i32, i64 %val, i64* %addr) {
261 ; CHECK-LABEL: test_store_release_i64:
262 ; CHECK: stlxr w0, x1, [x2]
263   %res = call i32 @llvm.aarch64.stlxr.p0i64(i64 %val, i64* %addr)
264   ret i32 %res
265 }
266
267 declare i32 @llvm.aarch64.stlxr.p0i8(i64, i8*) nounwind
268 declare i32 @llvm.aarch64.stlxr.p0i16(i64, i16*) nounwind
269 declare i32 @llvm.aarch64.stlxr.p0i32(i64, i32*) nounwind
270 declare i32 @llvm.aarch64.stlxr.p0i64(i64, i64*) nounwind