Revert r354244 "[DAGCombiner] Eliminate dead stores to stack."
[llvm-complete.git] / test / CodeGen / AArch64 / arm64-rev.ll
blob9b864c3a66cc78a285ca0ba74073637e3a4e9354
1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc < %s -mtriple=aarch64-eabi -aarch64-neon-syntax=apple | FileCheck %s
3 ; RUN: llc < %s -global-isel -global-isel-abort=2 -pass-remarks-missed=gisel* -mtriple=aarch64-eabi -aarch64-neon-syntax=apple | FileCheck %s --check-prefixes=FALLBACK,GISEL
5 ; FALLBACK-NOT: remark{{.*}}test_rev_w
6 define i32 @test_rev_w(i32 %a) nounwind {
7 ; CHECK-LABEL: test_rev_w:
8 ; CHECK:       // %bb.0: // %entry
9 ; CHECK-NEXT:    rev w0, w0
10 ; CHECK-NEXT:    ret
11 ; GISEL-LABEL: test_rev_w:
12 ; GISEL:       // %bb.0: // %entry
13 ; GISEL-NEXT:    rev w0, w0
14 ; GISEL-NEXT:    ret
15 entry:
16   %0 = tail call i32 @llvm.bswap.i32(i32 %a)
17   ret i32 %0
20 ; FALLBACK-NOT: remark{{.*}}test_rev_x
21 define i64 @test_rev_x(i64 %a) nounwind {
22 ; CHECK-LABEL: test_rev_x:
23 ; CHECK:       // %bb.0: // %entry
24 ; CHECK-NEXT:    rev x0, x0
25 ; CHECK-NEXT:    ret
26 ; GISEL-LABEL: test_rev_x:
27 ; GISEL:       // %bb.0: // %entry
28 ; GISEL-NEXT:    rev x0, x0
29 ; GISEL-NEXT:    ret
30 entry:
31   %0 = tail call i64 @llvm.bswap.i64(i64 %a)
32   ret i64 %0
35 ; Canonicalize (srl (bswap x), 16) to (rotr (bswap x), 16) if the high 16-bits
36 ; of %a are zero. This optimizes rev + lsr 16 to rev16.
37 define i32 @test_rev_w_srl16(i16 %a) {
38 ; CHECK-LABEL: test_rev_w_srl16:
39 ; CHECK:       // %bb.0: // %entry
40 ; CHECK-NEXT:    and w8, w0, #0xffff
41 ; CHECK-NEXT:    rev16 w0, w8
42 ; CHECK-NEXT:    ret
43 entry:
44   %0 = zext i16 %a to i32
45   %1 = tail call i32 @llvm.bswap.i32(i32 %0)
46   %2 = lshr i32 %1, 16
47   ret i32 %2
50 ; Canonicalize (srl (bswap x), 32) to (rotr (bswap x), 32) if the high 32-bits
51 ; of %a are zero. This optimizes rev + lsr 32 to rev32.
52 define i64 @test_rev_x_srl32(i32 %a) {
53 ; CHECK-LABEL: test_rev_x_srl32:
54 ; CHECK:       // %bb.0: // %entry
55 ; CHECK-NEXT:    mov w8, w0
56 ; CHECK-NEXT:    rev32 x0, x8
57 ; CHECK-NEXT:    ret
58 entry:
59   %0 = zext i32 %a to i64
60   %1 = tail call i64 @llvm.bswap.i64(i64 %0)
61   %2 = lshr i64 %1, 32
62   ret i64 %2
65 declare i32 @llvm.bswap.i32(i32) nounwind readnone
66 declare i64 @llvm.bswap.i64(i64) nounwind readnone
68 define i32 @test_rev16_w(i32 %X) nounwind {
69 ; CHECK-LABEL: test_rev16_w:
70 ; CHECK:       // %bb.0: // %entry
71 ; CHECK-NEXT:    rev16 w0, w0
72 ; CHECK-NEXT:    ret
73 entry:
74   %tmp1 = lshr i32 %X, 8
75   %X15 = bitcast i32 %X to i32
76   %tmp4 = shl i32 %X15, 8
77   %tmp2 = and i32 %tmp1, 16711680
78   %tmp5 = and i32 %tmp4, -16777216
79   %tmp9 = and i32 %tmp1, 255
80   %tmp13 = and i32 %tmp4, 65280
81   %tmp6 = or i32 %tmp5, %tmp2
82   %tmp10 = or i32 %tmp6, %tmp13
83   %tmp14 = or i32 %tmp10, %tmp9
84   ret i32 %tmp14
87 ; 64-bit REV16 is *not* a swap then a 16-bit rotation:
88 ;   01234567 ->(bswap) 76543210 ->(rotr) 10765432
89 ;   01234567 ->(rev16) 10325476
90 define i64 @test_rev16_x(i64 %a) nounwind {
91 ; CHECK-LABEL: test_rev16_x:
92 ; CHECK:       // %bb.0: // %entry
93 ; CHECK-NEXT:    rev x8, x0
94 ; CHECK-NEXT:    ror x0, x8, #16
95 ; CHECK-NEXT:    ret
96 entry:
97   %0 = tail call i64 @llvm.bswap.i64(i64 %a)
98   %1 = lshr i64 %0, 16
99   %2 = shl i64 %0, 48
100   %3 = or i64 %1, %2
101   ret i64 %3
104 define i64 @test_rev32_x(i64 %a) nounwind {
105 ; CHECK-LABEL: test_rev32_x:
106 ; CHECK:       // %bb.0: // %entry
107 ; CHECK-NEXT:    rev32 x0, x0
108 ; CHECK-NEXT:    ret
109 entry:
110   %0 = tail call i64 @llvm.bswap.i64(i64 %a)
111   %1 = lshr i64 %0, 32
112   %2 = shl i64 %0, 32
113   %3 = or i64 %1, %2
114   ret i64 %3
117 define <8 x i8> @test_vrev64D8(<8 x i8>* %A) nounwind {
118 ; CHECK-LABEL: test_vrev64D8:
119 ; CHECK:       // %bb.0:
120 ; CHECK-NEXT:    ldr d0, [x0]
121 ; CHECK-NEXT:    rev64.8b v0, v0
122 ; CHECK-NEXT:    ret
123         %tmp1 = load <8 x i8>, <8 x i8>* %A
124         %tmp2 = shufflevector <8 x i8> %tmp1, <8 x i8> undef, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
125         ret <8 x i8> %tmp2
128 define <4 x i16> @test_vrev64D16(<4 x i16>* %A) nounwind {
129 ; CHECK-LABEL: test_vrev64D16:
130 ; CHECK:       // %bb.0:
131 ; CHECK-NEXT:    ldr d0, [x0]
132 ; CHECK-NEXT:    rev64.4h v0, v0
133 ; CHECK-NEXT:    ret
134         %tmp1 = load <4 x i16>, <4 x i16>* %A
135         %tmp2 = shufflevector <4 x i16> %tmp1, <4 x i16> undef, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
136         ret <4 x i16> %tmp2
139 define <2 x i32> @test_vrev64D32(<2 x i32>* %A) nounwind {
140 ; CHECK-LABEL: test_vrev64D32:
141 ; CHECK:       // %bb.0:
142 ; CHECK-NEXT:    ldr d0, [x0]
143 ; CHECK-NEXT:    rev64.2s v0, v0
144 ; CHECK-NEXT:    ret
145         %tmp1 = load <2 x i32>, <2 x i32>* %A
146         %tmp2 = shufflevector <2 x i32> %tmp1, <2 x i32> undef, <2 x i32> <i32 1, i32 0>
147         ret <2 x i32> %tmp2
150 define <2 x float> @test_vrev64Df(<2 x float>* %A) nounwind {
151 ; CHECK-LABEL: test_vrev64Df:
152 ; CHECK:       // %bb.0:
153 ; CHECK-NEXT:    ldr d0, [x0]
154 ; CHECK-NEXT:    rev64.2s v0, v0
155 ; CHECK-NEXT:    ret
156         %tmp1 = load <2 x float>, <2 x float>* %A
157         %tmp2 = shufflevector <2 x float> %tmp1, <2 x float> undef, <2 x i32> <i32 1, i32 0>
158         ret <2 x float> %tmp2
161 define <16 x i8> @test_vrev64Q8(<16 x i8>* %A) nounwind {
162 ; CHECK-LABEL: test_vrev64Q8:
163 ; CHECK:       // %bb.0:
164 ; CHECK-NEXT:    ldr q0, [x0]
165 ; CHECK-NEXT:    rev64.16b v0, v0
166 ; CHECK-NEXT:    ret
167         %tmp1 = load <16 x i8>, <16 x i8>* %A
168         %tmp2 = shufflevector <16 x i8> %tmp1, <16 x i8> undef, <16 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0, i32 15, i32 14, i32 13, i32 12, i32 11, i32 10, i32 9, i32 8>
169         ret <16 x i8> %tmp2
172 define <8 x i16> @test_vrev64Q16(<8 x i16>* %A) nounwind {
173 ; CHECK-LABEL: test_vrev64Q16:
174 ; CHECK:       // %bb.0:
175 ; CHECK-NEXT:    ldr q0, [x0]
176 ; CHECK-NEXT:    rev64.8h v0, v0
177 ; CHECK-NEXT:    ret
178         %tmp1 = load <8 x i16>, <8 x i16>* %A
179         %tmp2 = shufflevector <8 x i16> %tmp1, <8 x i16> undef, <8 x i32> <i32 3, i32 2, i32 1, i32 0, i32 7, i32 6, i32 5, i32 4>
180         ret <8 x i16> %tmp2
183 define <4 x i32> @test_vrev64Q32(<4 x i32>* %A) nounwind {
184 ; CHECK-LABEL: test_vrev64Q32:
185 ; CHECK:       // %bb.0:
186 ; CHECK-NEXT:    ldr q0, [x0]
187 ; CHECK-NEXT:    rev64.4s v0, v0
188 ; CHECK-NEXT:    ret
189         %tmp1 = load <4 x i32>, <4 x i32>* %A
190         %tmp2 = shufflevector <4 x i32> %tmp1, <4 x i32> undef, <4 x i32> <i32 1, i32 0, i32 3, i32 2>
191         ret <4 x i32> %tmp2
194 define <4 x float> @test_vrev64Qf(<4 x float>* %A) nounwind {
195 ; CHECK-LABEL: test_vrev64Qf:
196 ; CHECK:       // %bb.0:
197 ; CHECK-NEXT:    ldr q0, [x0]
198 ; CHECK-NEXT:    rev64.4s v0, v0
199 ; CHECK-NEXT:    ret
200         %tmp1 = load <4 x float>, <4 x float>* %A
201         %tmp2 = shufflevector <4 x float> %tmp1, <4 x float> undef, <4 x i32> <i32 1, i32 0, i32 3, i32 2>
202         ret <4 x float> %tmp2
205 define <8 x i8> @test_vrev32D8(<8 x i8>* %A) nounwind {
206 ; CHECK-LABEL: test_vrev32D8:
207 ; CHECK:       // %bb.0:
208 ; CHECK-NEXT:    ldr d0, [x0]
209 ; CHECK-NEXT:    rev32.8b v0, v0
210 ; CHECK-NEXT:    ret
211         %tmp1 = load <8 x i8>, <8 x i8>* %A
212         %tmp2 = shufflevector <8 x i8> %tmp1, <8 x i8> undef, <8 x i32> <i32 3, i32 2, i32 1, i32 0, i32 7, i32 6, i32 5, i32 4>
213         ret <8 x i8> %tmp2
216 define <4 x i16> @test_vrev32D16(<4 x i16>* %A) nounwind {
217 ; CHECK-LABEL: test_vrev32D16:
218 ; CHECK:       // %bb.0:
219 ; CHECK-NEXT:    ldr d0, [x0]
220 ; CHECK-NEXT:    rev32.4h v0, v0
221 ; CHECK-NEXT:    ret
222         %tmp1 = load <4 x i16>, <4 x i16>* %A
223         %tmp2 = shufflevector <4 x i16> %tmp1, <4 x i16> undef, <4 x i32> <i32 1, i32 0, i32 3, i32 2>
224         ret <4 x i16> %tmp2
227 define <16 x i8> @test_vrev32Q8(<16 x i8>* %A) nounwind {
228 ; CHECK-LABEL: test_vrev32Q8:
229 ; CHECK:       // %bb.0:
230 ; CHECK-NEXT:    ldr q0, [x0]
231 ; CHECK-NEXT:    rev32.16b v0, v0
232 ; CHECK-NEXT:    ret
233         %tmp1 = load <16 x i8>, <16 x i8>* %A
234         %tmp2 = shufflevector <16 x i8> %tmp1, <16 x i8> undef, <16 x i32> <i32 3, i32 2, i32 1, i32 0, i32 7, i32 6, i32 5, i32 4, i32 11, i32 10, i32 9, i32 8, i32 15, i32 14, i32 13, i32 12>
235         ret <16 x i8> %tmp2
238 define <8 x i16> @test_vrev32Q16(<8 x i16>* %A) nounwind {
239 ; CHECK-LABEL: test_vrev32Q16:
240 ; CHECK:       // %bb.0:
241 ; CHECK-NEXT:    ldr q0, [x0]
242 ; CHECK-NEXT:    rev32.8h v0, v0
243 ; CHECK-NEXT:    ret
244         %tmp1 = load <8 x i16>, <8 x i16>* %A
245         %tmp2 = shufflevector <8 x i16> %tmp1, <8 x i16> undef, <8 x i32> <i32 1, i32 0, i32 3, i32 2, i32 5, i32 4, i32 7, i32 6>
246         ret <8 x i16> %tmp2
249 define <8 x i8> @test_vrev16D8(<8 x i8>* %A) nounwind {
250 ; CHECK-LABEL: test_vrev16D8:
251 ; CHECK:       // %bb.0:
252 ; CHECK-NEXT:    ldr d0, [x0]
253 ; CHECK-NEXT:    rev16.8b v0, v0
254 ; CHECK-NEXT:    ret
255         %tmp1 = load <8 x i8>, <8 x i8>* %A
256         %tmp2 = shufflevector <8 x i8> %tmp1, <8 x i8> undef, <8 x i32> <i32 1, i32 0, i32 3, i32 2, i32 5, i32 4, i32 7, i32 6>
257         ret <8 x i8> %tmp2
260 define <16 x i8> @test_vrev16Q8(<16 x i8>* %A) nounwind {
261 ; CHECK-LABEL: test_vrev16Q8:
262 ; CHECK:       // %bb.0:
263 ; CHECK-NEXT:    ldr q0, [x0]
264 ; CHECK-NEXT:    rev16.16b v0, v0
265 ; CHECK-NEXT:    ret
266         %tmp1 = load <16 x i8>, <16 x i8>* %A
267         %tmp2 = shufflevector <16 x i8> %tmp1, <16 x i8> undef, <16 x i32> <i32 1, i32 0, i32 3, i32 2, i32 5, i32 4, i32 7, i32 6, i32 9, i32 8, i32 11, i32 10, i32 13, i32 12, i32 15, i32 14>
268         ret <16 x i8> %tmp2
271 ; Undef shuffle indices should not prevent matching to VREV:
273 define <8 x i8> @test_vrev64D8_undef(<8 x i8>* %A) nounwind {
274 ; CHECK-LABEL: test_vrev64D8_undef:
275 ; CHECK:       // %bb.0:
276 ; CHECK-NEXT:    ldr d0, [x0]
277 ; CHECK-NEXT:    rev64.8b v0, v0
278 ; CHECK-NEXT:    ret
279         %tmp1 = load <8 x i8>, <8 x i8>* %A
280         %tmp2 = shufflevector <8 x i8> %tmp1, <8 x i8> undef, <8 x i32> <i32 7, i32 undef, i32 undef, i32 4, i32 3, i32 2, i32 1, i32 0>
281         ret <8 x i8> %tmp2
284 define <8 x i16> @test_vrev32Q16_undef(<8 x i16>* %A) nounwind {
285 ; CHECK-LABEL: test_vrev32Q16_undef:
286 ; CHECK:       // %bb.0:
287 ; CHECK-NEXT:    ldr q0, [x0]
288 ; CHECK-NEXT:    rev32.8h v0, v0
289 ; CHECK-NEXT:    ret
290         %tmp1 = load <8 x i16>, <8 x i16>* %A
291         %tmp2 = shufflevector <8 x i16> %tmp1, <8 x i16> undef, <8 x i32> <i32 undef, i32 0, i32 undef, i32 2, i32 5, i32 4, i32 7, i32 undef>
292         ret <8 x i16> %tmp2
295 ; vrev <4 x i16> should use REV32 and not REV64
296 define void @test_vrev64(<4 x i16>* nocapture %source, <2 x i16>* nocapture %dst) nounwind ssp {
297 ; CHECK-LABEL: test_vrev64:
298 ; CHECK:       // %bb.0: // %entry
299 ; CHECK-NEXT:    ldr q0, [x0]
300 ; CHECK-NEXT:    add x8, x1, #2 // =2
301 ; CHECK-NEXT:    st1.h { v0 }[5], [x8]
302 ; CHECK-NEXT:    st1.h { v0 }[6], [x1]
303 ; CHECK-NEXT:    ret
304 entry:
305   %0 = bitcast <4 x i16>* %source to <8 x i16>*
306   %tmp2 = load <8 x i16>, <8 x i16>* %0, align 4
307   %tmp3 = extractelement <8 x i16> %tmp2, i32 6
308   %tmp5 = insertelement <2 x i16> undef, i16 %tmp3, i32 0
309   %tmp9 = extractelement <8 x i16> %tmp2, i32 5
310   %tmp11 = insertelement <2 x i16> %tmp5, i16 %tmp9, i32 1
311   store <2 x i16> %tmp11, <2 x i16>* %dst, align 4
312   ret void
315 ; Test vrev of float4
316 define void @float_vrev64(float* nocapture %source, <4 x float>* nocapture %dest) nounwind noinline ssp {
317 ; CHECK-LABEL: float_vrev64:
318 ; CHECK:       // %bb.0: // %entry
319 ; CHECK-NEXT:    ldr q0, [x0]
320 ; CHECK-NEXT:    movi.2d v1, #0000000000000000
321 ; CHECK-NEXT:    dup.4s v1, v1[0]
322 ; CHECK-NEXT:    ext.16b v0, v0, v1, #12
323 ; CHECK-NEXT:    rev64.4s v0, v0
324 ; CHECK-NEXT:    str q0, [x1, #176]
325 ; CHECK-NEXT:    ret
326 entry:
327   %0 = bitcast float* %source to <4 x float>*
328   %tmp2 = load <4 x float>, <4 x float>* %0, align 4
329   %tmp5 = shufflevector <4 x float> <float 0.000000e+00, float undef, float undef, float undef>, <4 x float> %tmp2, <4 x i32> <i32 0, i32 7, i32 0, i32 0>
330   %arrayidx8 = getelementptr inbounds <4 x float>, <4 x float>* %dest, i32 11
331   store <4 x float> %tmp5, <4 x float>* %arrayidx8, align 4
332   ret void
336 define <4 x i32> @test_vrev32_bswap(<4 x i32> %source) nounwind {
337 ; CHECK-LABEL: test_vrev32_bswap:
338 ; CHECK:       // %bb.0:
339 ; CHECK-NEXT:    rev32.16b v0, v0
340 ; CHECK-NEXT:    ret
341   %bswap = call <4 x i32> @llvm.bswap.v4i32(<4 x i32> %source)
342   ret <4 x i32> %bswap
345 declare <4 x i32> @llvm.bswap.v4i32(<4 x i32>) nounwind readnone