xref: /llvm-project/llvm/test/CodeGen/AArch64/bitreverse.ll (revision 3bb0c73ab50121f518c8d66154283cfd50d6d31a)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc -mtriple=aarch64 %s -o - | FileCheck %s --check-prefixes=CHECK,SDAG
3; RUN: llc -mtriple=aarch64 -global-isel -global-isel-abort=1 %s -o - | FileCheck %s --check-prefixes=CHECK,GISEL
4
5; These tests just check that the plumbing is in place for @llvm.bitreverse.
6
7declare <2 x i16> @llvm.bitreverse.v2i16(<2 x i16>) readnone
8
9define <2 x i16> @f(<2 x i16> %a) {
10; SDAG-LABEL: f:
11; SDAG:       // %bb.0:
12; SDAG-NEXT:    rev32 v0.8b, v0.8b
13; SDAG-NEXT:    rbit v0.8b, v0.8b
14; SDAG-NEXT:    ushr v0.2s, v0.2s, #16
15; SDAG-NEXT:    ret
16;
17; GISEL-LABEL: f:
18; GISEL:       // %bb.0:
19; GISEL-NEXT:    uzp1 v0.4h, v0.4h, v0.4h
20; GISEL-NEXT:    mov w8, #61680 // =0xf0f0
21; GISEL-NEXT:    dup v1.2s, w8
22; GISEL-NEXT:    mov w8, #4 // =0x4
23; GISEL-NEXT:    fmov s3, w8
24; GISEL-NEXT:    rev16 v0.8b, v0.8b
25; GISEL-NEXT:    mov v3.h[1], w8
26; GISEL-NEXT:    mov w8, #52428 // =0xcccc
27; GISEL-NEXT:    ushll v2.4s, v0.4h, #0
28; GISEL-NEXT:    neg v4.4h, v3.4h
29; GISEL-NEXT:    and v2.8b, v2.8b, v1.8b
30; GISEL-NEXT:    uzp1 v2.4h, v2.4h, v0.4h
31; GISEL-NEXT:    ushl v0.4h, v0.4h, v3.4h
32; GISEL-NEXT:    ushll v0.4s, v0.4h, #0
33; GISEL-NEXT:    ushl v2.4h, v2.4h, v4.4h
34; GISEL-NEXT:    and v0.8b, v0.8b, v1.8b
35; GISEL-NEXT:    ushll v1.4s, v2.4h, #0
36; GISEL-NEXT:    dup v2.2s, w8
37; GISEL-NEXT:    mov w8, #2 // =0x2
38; GISEL-NEXT:    orr v0.8b, v1.8b, v0.8b
39; GISEL-NEXT:    fmov s1, w8
40; GISEL-NEXT:    and v3.8b, v0.8b, v2.8b
41; GISEL-NEXT:    uzp1 v0.4h, v0.4h, v0.4h
42; GISEL-NEXT:    mov v1.h[1], w8
43; GISEL-NEXT:    mov w8, #43690 // =0xaaaa
44; GISEL-NEXT:    uzp1 v3.4h, v3.4h, v0.4h
45; GISEL-NEXT:    neg v4.4h, v1.4h
46; GISEL-NEXT:    ushl v0.4h, v0.4h, v1.4h
47; GISEL-NEXT:    ushll v0.4s, v0.4h, #0
48; GISEL-NEXT:    ushl v1.4h, v3.4h, v4.4h
49; GISEL-NEXT:    and v0.8b, v0.8b, v2.8b
50; GISEL-NEXT:    dup v2.2s, w8
51; GISEL-NEXT:    mov w8, #1 // =0x1
52; GISEL-NEXT:    ushll v1.4s, v1.4h, #0
53; GISEL-NEXT:    orr v0.8b, v1.8b, v0.8b
54; GISEL-NEXT:    fmov s1, w8
55; GISEL-NEXT:    and v3.8b, v0.8b, v2.8b
56; GISEL-NEXT:    uzp1 v0.4h, v0.4h, v0.4h
57; GISEL-NEXT:    mov v1.h[1], w8
58; GISEL-NEXT:    uzp1 v3.4h, v3.4h, v0.4h
59; GISEL-NEXT:    neg v4.4h, v1.4h
60; GISEL-NEXT:    ushl v0.4h, v0.4h, v1.4h
61; GISEL-NEXT:    ushll v0.4s, v0.4h, #0
62; GISEL-NEXT:    ushl v1.4h, v3.4h, v4.4h
63; GISEL-NEXT:    and v0.8b, v0.8b, v2.8b
64; GISEL-NEXT:    ushll v1.4s, v1.4h, #0
65; GISEL-NEXT:    orr v0.8b, v1.8b, v0.8b
66; GISEL-NEXT:    ret
67  %b = call <2 x i16> @llvm.bitreverse.v2i16(<2 x i16> %a)
68  ret <2 x i16> %b
69}
70
71declare i8 @llvm.bitreverse.i8(i8) readnone
72
73define i8 @g(i8 %a) {
74; CHECK-LABEL: g:
75; CHECK:       // %bb.0:
76; CHECK-NEXT:    rbit w8, w0
77; CHECK-NEXT:    lsr w0, w8, #24
78; CHECK-NEXT:    ret
79  %b = call i8 @llvm.bitreverse.i8(i8 %a)
80  ret i8 %b
81}
82
83declare i16 @llvm.bitreverse.i16(i16) readnone
84
85define i16 @g_16(i16 %a) {
86; CHECK-LABEL: g_16:
87; CHECK:       // %bb.0:
88; CHECK-NEXT:    rbit w8, w0
89; CHECK-NEXT:    lsr w0, w8, #16
90; CHECK-NEXT:    ret
91  %b = call i16 @llvm.bitreverse.i16(i16 %a)
92  ret i16 %b
93}
94
95declare i32 @llvm.bitreverse.i32(i32) readnone
96
97define i32 @g_32(i32 %a) {
98; CHECK-LABEL: g_32:
99; CHECK:       // %bb.0:
100; CHECK-NEXT:    rbit w0, w0
101; CHECK-NEXT:    ret
102  %b = call i32 @llvm.bitreverse.i32(i32 %a)
103  ret i32 %b
104}
105
106declare i64 @llvm.bitreverse.i64(i64) readnone
107
108define i64 @g_64(i64 %a) {
109; CHECK-LABEL: g_64:
110; CHECK:       // %bb.0:
111; CHECK-NEXT:    rbit x0, x0
112; CHECK-NEXT:    ret
113  %b = call i64 @llvm.bitreverse.i64(i64 %a)
114  ret i64 %b
115}
116
117declare <8 x i8> @llvm.bitreverse.v8i8(<8 x i8>) readnone
118
119define <8 x i8> @g_vec(<8 x i8> %a) {
120; CHECK-LABEL: g_vec:
121; CHECK:       // %bb.0:
122; CHECK-NEXT:    rbit v0.8b, v0.8b
123; CHECK-NEXT:    ret
124  %b = call <8 x i8> @llvm.bitreverse.v8i8(<8 x i8> %a)
125  ret <8 x i8> %b
126}
127
128declare <16 x i8> @llvm.bitreverse.v16i8(<16 x i8>) readnone
129
130define <16 x i8> @g_vec_16x8(<16 x i8> %a) {
131; CHECK-LABEL: g_vec_16x8:
132; CHECK:       // %bb.0:
133; CHECK-NEXT:    rbit v0.16b, v0.16b
134; CHECK-NEXT:    ret
135  %b = call <16 x i8> @llvm.bitreverse.v16i8(<16 x i8> %a)
136  ret <16 x i8> %b
137}
138
139declare <4 x i16> @llvm.bitreverse.v4i16(<4 x i16>) readnone
140
141define <4 x i16> @g_vec_4x16(<4 x i16> %a) {
142; SDAG-LABEL: g_vec_4x16:
143; SDAG:       // %bb.0:
144; SDAG-NEXT:    rev16 v0.8b, v0.8b
145; SDAG-NEXT:    rbit v0.8b, v0.8b
146; SDAG-NEXT:    ret
147;
148; GISEL-LABEL: g_vec_4x16:
149; GISEL:       // %bb.0:
150; GISEL-NEXT:    movi v1.8b, #240
151; GISEL-NEXT:    rev16 v0.8b, v0.8b
152; GISEL-NEXT:    and v2.8b, v0.8b, v1.8b
153; GISEL-NEXT:    shl v0.4h, v0.4h, #4
154; GISEL-NEXT:    ushr v2.4h, v2.4h, #4
155; GISEL-NEXT:    and v0.8b, v0.8b, v1.8b
156; GISEL-NEXT:    movi v1.8b, #204
157; GISEL-NEXT:    orr v0.8b, v2.8b, v0.8b
158; GISEL-NEXT:    and v2.8b, v0.8b, v1.8b
159; GISEL-NEXT:    shl v0.4h, v0.4h, #2
160; GISEL-NEXT:    ushr v2.4h, v2.4h, #2
161; GISEL-NEXT:    and v0.8b, v0.8b, v1.8b
162; GISEL-NEXT:    movi v1.8b, #170
163; GISEL-NEXT:    orr v0.8b, v2.8b, v0.8b
164; GISEL-NEXT:    and v2.8b, v0.8b, v1.8b
165; GISEL-NEXT:    shl v0.4h, v0.4h, #1
166; GISEL-NEXT:    ushr v2.4h, v2.4h, #1
167; GISEL-NEXT:    and v0.8b, v0.8b, v1.8b
168; GISEL-NEXT:    orr v0.8b, v2.8b, v0.8b
169; GISEL-NEXT:    ret
170  %b = call <4 x i16> @llvm.bitreverse.v4i16(<4 x i16> %a)
171  ret <4 x i16> %b
172}
173
174declare <8 x i16> @llvm.bitreverse.v8i16(<8 x i16>) readnone
175
176define <8 x i16> @g_vec_8x16(<8 x i16> %a) {
177; SDAG-LABEL: g_vec_8x16:
178; SDAG:       // %bb.0:
179; SDAG-NEXT:    rev16 v0.16b, v0.16b
180; SDAG-NEXT:    rbit v0.16b, v0.16b
181; SDAG-NEXT:    ret
182;
183; GISEL-LABEL: g_vec_8x16:
184; GISEL:       // %bb.0:
185; GISEL-NEXT:    movi v1.16b, #240
186; GISEL-NEXT:    rev16 v0.16b, v0.16b
187; GISEL-NEXT:    and v2.16b, v0.16b, v1.16b
188; GISEL-NEXT:    shl v0.8h, v0.8h, #4
189; GISEL-NEXT:    ushr v2.8h, v2.8h, #4
190; GISEL-NEXT:    and v0.16b, v0.16b, v1.16b
191; GISEL-NEXT:    movi v1.16b, #204
192; GISEL-NEXT:    orr v0.16b, v2.16b, v0.16b
193; GISEL-NEXT:    and v2.16b, v0.16b, v1.16b
194; GISEL-NEXT:    shl v0.8h, v0.8h, #2
195; GISEL-NEXT:    ushr v2.8h, v2.8h, #2
196; GISEL-NEXT:    and v0.16b, v0.16b, v1.16b
197; GISEL-NEXT:    movi v1.16b, #170
198; GISEL-NEXT:    orr v0.16b, v2.16b, v0.16b
199; GISEL-NEXT:    and v2.16b, v0.16b, v1.16b
200; GISEL-NEXT:    shl v0.8h, v0.8h, #1
201; GISEL-NEXT:    ushr v2.8h, v2.8h, #1
202; GISEL-NEXT:    and v0.16b, v0.16b, v1.16b
203; GISEL-NEXT:    orr v0.16b, v2.16b, v0.16b
204; GISEL-NEXT:    ret
205  %b = call <8 x i16> @llvm.bitreverse.v8i16(<8 x i16> %a)
206  ret <8 x i16> %b
207}
208
209declare <2 x i32> @llvm.bitreverse.v2i32(<2 x i32>) readnone
210
211define <2 x i32> @g_vec_2x32(<2 x i32> %a) {
212; SDAG-LABEL: g_vec_2x32:
213; SDAG:       // %bb.0:
214; SDAG-NEXT:    rev32 v0.8b, v0.8b
215; SDAG-NEXT:    rbit v0.8b, v0.8b
216; SDAG-NEXT:    ret
217;
218; GISEL-LABEL: g_vec_2x32:
219; GISEL:       // %bb.0:
220; GISEL-NEXT:    movi v1.8b, #240
221; GISEL-NEXT:    rev32 v0.8b, v0.8b
222; GISEL-NEXT:    and v2.8b, v0.8b, v1.8b
223; GISEL-NEXT:    shl v0.2s, v0.2s, #4
224; GISEL-NEXT:    ushr v2.2s, v2.2s, #4
225; GISEL-NEXT:    and v0.8b, v0.8b, v1.8b
226; GISEL-NEXT:    movi v1.8b, #204
227; GISEL-NEXT:    orr v0.8b, v2.8b, v0.8b
228; GISEL-NEXT:    and v2.8b, v0.8b, v1.8b
229; GISEL-NEXT:    shl v0.2s, v0.2s, #2
230; GISEL-NEXT:    ushr v2.2s, v2.2s, #2
231; GISEL-NEXT:    and v0.8b, v0.8b, v1.8b
232; GISEL-NEXT:    movi v1.8b, #170
233; GISEL-NEXT:    orr v0.8b, v2.8b, v0.8b
234; GISEL-NEXT:    and v2.8b, v0.8b, v1.8b
235; GISEL-NEXT:    shl v0.2s, v0.2s, #1
236; GISEL-NEXT:    ushr v2.2s, v2.2s, #1
237; GISEL-NEXT:    and v0.8b, v0.8b, v1.8b
238; GISEL-NEXT:    orr v0.8b, v2.8b, v0.8b
239; GISEL-NEXT:    ret
240  %b = call <2 x i32> @llvm.bitreverse.v2i32(<2 x i32> %a)
241  ret <2 x i32> %b
242}
243
244declare <4 x i32> @llvm.bitreverse.v4i32(<4 x i32>) readnone
245
246define <4 x i32> @g_vec_4x32(<4 x i32> %a) {
247; SDAG-LABEL: g_vec_4x32:
248; SDAG:       // %bb.0:
249; SDAG-NEXT:    rev32 v0.16b, v0.16b
250; SDAG-NEXT:    rbit v0.16b, v0.16b
251; SDAG-NEXT:    ret
252;
253; GISEL-LABEL: g_vec_4x32:
254; GISEL:       // %bb.0:
255; GISEL-NEXT:    movi v1.16b, #240
256; GISEL-NEXT:    rev32 v0.16b, v0.16b
257; GISEL-NEXT:    and v2.16b, v0.16b, v1.16b
258; GISEL-NEXT:    shl v0.4s, v0.4s, #4
259; GISEL-NEXT:    ushr v2.4s, v2.4s, #4
260; GISEL-NEXT:    and v0.16b, v0.16b, v1.16b
261; GISEL-NEXT:    movi v1.16b, #204
262; GISEL-NEXT:    orr v0.16b, v2.16b, v0.16b
263; GISEL-NEXT:    and v2.16b, v0.16b, v1.16b
264; GISEL-NEXT:    shl v0.4s, v0.4s, #2
265; GISEL-NEXT:    ushr v2.4s, v2.4s, #2
266; GISEL-NEXT:    and v0.16b, v0.16b, v1.16b
267; GISEL-NEXT:    movi v1.16b, #170
268; GISEL-NEXT:    orr v0.16b, v2.16b, v0.16b
269; GISEL-NEXT:    and v2.16b, v0.16b, v1.16b
270; GISEL-NEXT:    shl v0.4s, v0.4s, #1
271; GISEL-NEXT:    ushr v2.4s, v2.4s, #1
272; GISEL-NEXT:    and v0.16b, v0.16b, v1.16b
273; GISEL-NEXT:    orr v0.16b, v2.16b, v0.16b
274; GISEL-NEXT:    ret
275  %b = call <4 x i32> @llvm.bitreverse.v4i32(<4 x i32> %a)
276  ret <4 x i32> %b
277}
278
279declare <1 x i64> @llvm.bitreverse.v1i64(<1 x i64>) readnone
280
281define <1 x i64> @g_vec_1x64(<1 x i64> %a) {
282; SDAG-LABEL: g_vec_1x64:
283; SDAG:       // %bb.0:
284; SDAG-NEXT:    rev64 v0.8b, v0.8b
285; SDAG-NEXT:    rbit v0.8b, v0.8b
286; SDAG-NEXT:    ret
287;
288; GISEL-LABEL: g_vec_1x64:
289; GISEL:       // %bb.0:
290; GISEL-NEXT:    fmov x8, d0
291; GISEL-NEXT:    rbit x8, x8
292; GISEL-NEXT:    fmov d0, x8
293; GISEL-NEXT:    ret
294  %b = call <1 x i64> @llvm.bitreverse.v1i64(<1 x i64> %a)
295  ret <1 x i64> %b
296}
297
298declare <2 x i64> @llvm.bitreverse.v2i64(<2 x i64>) readnone
299
300define <2 x i64> @g_vec_2x64(<2 x i64> %a) {
301; SDAG-LABEL: g_vec_2x64:
302; SDAG:       // %bb.0:
303; SDAG-NEXT:    rev64 v0.16b, v0.16b
304; SDAG-NEXT:    rbit v0.16b, v0.16b
305; SDAG-NEXT:    ret
306;
307; GISEL-LABEL: g_vec_2x64:
308; GISEL:       // %bb.0:
309; GISEL-NEXT:    movi v1.16b, #240
310; GISEL-NEXT:    rev64 v0.16b, v0.16b
311; GISEL-NEXT:    and v2.16b, v0.16b, v1.16b
312; GISEL-NEXT:    shl v0.2d, v0.2d, #4
313; GISEL-NEXT:    ushr v2.2d, v2.2d, #4
314; GISEL-NEXT:    and v0.16b, v0.16b, v1.16b
315; GISEL-NEXT:    movi v1.16b, #204
316; GISEL-NEXT:    orr v0.16b, v2.16b, v0.16b
317; GISEL-NEXT:    and v2.16b, v0.16b, v1.16b
318; GISEL-NEXT:    shl v0.2d, v0.2d, #2
319; GISEL-NEXT:    ushr v2.2d, v2.2d, #2
320; GISEL-NEXT:    and v0.16b, v0.16b, v1.16b
321; GISEL-NEXT:    movi v1.16b, #170
322; GISEL-NEXT:    orr v0.16b, v2.16b, v0.16b
323; GISEL-NEXT:    and v2.16b, v0.16b, v1.16b
324; GISEL-NEXT:    shl v0.2d, v0.2d, #1
325; GISEL-NEXT:    ushr v2.2d, v2.2d, #1
326; GISEL-NEXT:    and v0.16b, v0.16b, v1.16b
327; GISEL-NEXT:    orr v0.16b, v2.16b, v0.16b
328; GISEL-NEXT:    ret
329  %b = call <2 x i64> @llvm.bitreverse.v2i64(<2 x i64> %a)
330  ret <2 x i64> %b
331}
332