[ORC] Add std::tuple support to SimplePackedSerialization.
[llvm-project.git] / llvm / test / CodeGen / ARM / funnel-shift-rot.ll
blob55157875d355f9338121a16c7fc5908be4745a31
1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc < %s -mtriple=arm-eabi -mattr=+v6t2 | FileCheck %s --check-prefixes=CHECK,SCALAR
3 ; RUN: llc < %s -mtriple=arm-eabi -mattr=+v6t2 -mattr=+neon | FileCheck %s --check-prefixes=CHECK,NEON
5 declare i8 @llvm.fshl.i8(i8, i8, i8)
6 declare i16 @llvm.fshl.i16(i16, i16, i16)
7 declare i32 @llvm.fshl.i32(i32, i32, i32)
8 declare i64 @llvm.fshl.i64(i64, i64, i64)
9 declare <4 x i32> @llvm.fshl.v4i32(<4 x i32>, <4 x i32>, <4 x i32>)
11 declare i8 @llvm.fshr.i8(i8, i8, i8)
12 declare i16 @llvm.fshr.i16(i16, i16, i16)
13 declare i32 @llvm.fshr.i32(i32, i32, i32)
14 declare i64 @llvm.fshr.i64(i64, i64, i64)
15 declare <4 x i32> @llvm.fshr.v4i32(<4 x i32>, <4 x i32>, <4 x i32>)
17 ; When first 2 operands match, it's a rotate.
19 define i8 @rotl_i8_const_shift(i8 %x) {
20 ; CHECK-LABEL: rotl_i8_const_shift:
21 ; CHECK:       @ %bb.0:
22 ; CHECK-NEXT:    uxtb r1, r0
23 ; CHECK-NEXT:    lsl r0, r0, #3
24 ; CHECK-NEXT:    orr r0, r0, r1, lsr #5
25 ; CHECK-NEXT:    bx lr
26   %f = call i8 @llvm.fshl.i8(i8 %x, i8 %x, i8 3)
27   ret i8 %f
30 define i64 @rotl_i64_const_shift(i64 %x) {
31 ; CHECK-LABEL: rotl_i64_const_shift:
32 ; CHECK:       @ %bb.0:
33 ; CHECK-NEXT:    lsl r2, r0, #3
34 ; CHECK-NEXT:    orr r2, r2, r1, lsr #29
35 ; CHECK-NEXT:    lsl r1, r1, #3
36 ; CHECK-NEXT:    orr r1, r1, r0, lsr #29
37 ; CHECK-NEXT:    mov r0, r2
38 ; CHECK-NEXT:    bx lr
39   %f = call i64 @llvm.fshl.i64(i64 %x, i64 %x, i64 3)
40   ret i64 %f
43 ; When first 2 operands match, it's a rotate (by variable amount).
45 define i16 @rotl_i16(i16 %x, i16 %z) {
46 ; CHECK-LABEL: rotl_i16:
47 ; CHECK:       @ %bb.0:
48 ; CHECK-NEXT:    and r2, r1, #15
49 ; CHECK-NEXT:    rsb r1, r1, #0
50 ; CHECK-NEXT:    and r1, r1, #15
51 ; CHECK-NEXT:    lsl r2, r0, r2
52 ; CHECK-NEXT:    uxth r0, r0
53 ; CHECK-NEXT:    orr r0, r2, r0, lsr r1
54 ; CHECK-NEXT:    bx lr
55   %f = call i16 @llvm.fshl.i16(i16 %x, i16 %x, i16 %z)
56   ret i16 %f
59 define i32 @rotl_i32(i32 %x, i32 %z) {
60 ; CHECK-LABEL: rotl_i32:
61 ; CHECK:       @ %bb.0:
62 ; CHECK-NEXT:    rsb r1, r1, #0
63 ; CHECK-NEXT:    ror r0, r0, r1
64 ; CHECK-NEXT:    bx lr
65   %f = call i32 @llvm.fshl.i32(i32 %x, i32 %x, i32 %z)
66   ret i32 %f
69 define i64 @rotl_i64(i64 %x, i64 %z) {
70 ; SCALAR-LABEL: rotl_i64:
71 ; SCALAR:       @ %bb.0:
72 ; SCALAR-NEXT:    .save {r4, r5, r11, lr}
73 ; SCALAR-NEXT:    push {r4, r5, r11, lr}
74 ; SCALAR-NEXT:    rsb r3, r2, #0
75 ; SCALAR-NEXT:    and r4, r2, #63
76 ; SCALAR-NEXT:    and lr, r3, #63
77 ; SCALAR-NEXT:    rsb r3, lr, #32
78 ; SCALAR-NEXT:    lsl r2, r0, r4
79 ; SCALAR-NEXT:    lsr r12, r0, lr
80 ; SCALAR-NEXT:    orr r3, r12, r1, lsl r3
81 ; SCALAR-NEXT:    subs r12, lr, #32
82 ; SCALAR-NEXT:    lsrpl r3, r1, r12
83 ; SCALAR-NEXT:    subs r5, r4, #32
84 ; SCALAR-NEXT:    movwpl r2, #0
85 ; SCALAR-NEXT:    cmp r5, #0
86 ; SCALAR-NEXT:    orr r2, r2, r3
87 ; SCALAR-NEXT:    rsb r3, r4, #32
88 ; SCALAR-NEXT:    lsr r3, r0, r3
89 ; SCALAR-NEXT:    orr r3, r3, r1, lsl r4
90 ; SCALAR-NEXT:    lslpl r3, r0, r5
91 ; SCALAR-NEXT:    lsr r0, r1, lr
92 ; SCALAR-NEXT:    cmp r12, #0
93 ; SCALAR-NEXT:    movwpl r0, #0
94 ; SCALAR-NEXT:    orr r1, r3, r0
95 ; SCALAR-NEXT:    mov r0, r2
96 ; SCALAR-NEXT:    pop {r4, r5, r11, pc}
98 ; NEON-LABEL: rotl_i64:
99 ; NEON:       @ %bb.0:
100 ; NEON-NEXT:    .save {r4, r5, r11, lr}
101 ; NEON-NEXT:    push {r4, r5, r11, lr}
102 ; NEON-NEXT:    and r12, r2, #63
103 ; NEON-NEXT:    rsb r2, r2, #0
104 ; NEON-NEXT:    rsb r3, r12, #32
105 ; NEON-NEXT:    and r4, r2, #63
106 ; NEON-NEXT:    subs lr, r12, #32
107 ; NEON-NEXT:    lsr r3, r0, r3
108 ; NEON-NEXT:    lsr r2, r1, r4
109 ; NEON-NEXT:    orr r3, r3, r1, lsl r12
110 ; NEON-NEXT:    lslpl r3, r0, lr
111 ; NEON-NEXT:    subs r5, r4, #32
112 ; NEON-NEXT:    movwpl r2, #0
113 ; NEON-NEXT:    cmp r5, #0
114 ; NEON-NEXT:    orr r2, r3, r2
115 ; NEON-NEXT:    lsr r3, r0, r4
116 ; NEON-NEXT:    rsb r4, r4, #32
117 ; NEON-NEXT:    lsl r0, r0, r12
118 ; NEON-NEXT:    orr r3, r3, r1, lsl r4
119 ; NEON-NEXT:    lsrpl r3, r1, r5
120 ; NEON-NEXT:    cmp lr, #0
121 ; NEON-NEXT:    movwpl r0, #0
122 ; NEON-NEXT:    mov r1, r2
123 ; NEON-NEXT:    orr r0, r0, r3
124 ; NEON-NEXT:    pop {r4, r5, r11, pc}
125   %f = call i64 @llvm.fshl.i64(i64 %x, i64 %x, i64 %z)
126   ret i64 %f
129 ; Vector rotate.
131 define <4 x i32> @rotl_v4i32(<4 x i32> %x, <4 x i32> %z) {
132 ; SCALAR-LABEL: rotl_v4i32:
133 ; SCALAR:       @ %bb.0:
134 ; SCALAR-NEXT:    ldr r12, [sp]
135 ; SCALAR-NEXT:    rsb r12, r12, #0
136 ; SCALAR-NEXT:    ror r0, r0, r12
137 ; SCALAR-NEXT:    ldr r12, [sp, #4]
138 ; SCALAR-NEXT:    rsb r12, r12, #0
139 ; SCALAR-NEXT:    ror r1, r1, r12
140 ; SCALAR-NEXT:    ldr r12, [sp, #8]
141 ; SCALAR-NEXT:    rsb r12, r12, #0
142 ; SCALAR-NEXT:    ror r2, r2, r12
143 ; SCALAR-NEXT:    ldr r12, [sp, #12]
144 ; SCALAR-NEXT:    rsb r12, r12, #0
145 ; SCALAR-NEXT:    ror r3, r3, r12
146 ; SCALAR-NEXT:    bx lr
148 ; NEON-LABEL: rotl_v4i32:
149 ; NEON:       @ %bb.0:
150 ; NEON-NEXT:    mov r12, sp
151 ; NEON-NEXT:    vld1.64 {d16, d17}, [r12]
152 ; NEON-NEXT:    vmov.i32 q10, #0x1f
153 ; NEON-NEXT:    vneg.s32 q9, q8
154 ; NEON-NEXT:    vmov d23, r2, r3
155 ; NEON-NEXT:    vand q9, q9, q10
156 ; NEON-NEXT:    vand q8, q8, q10
157 ; NEON-NEXT:    vmov d22, r0, r1
158 ; NEON-NEXT:    vneg.s32 q9, q9
159 ; NEON-NEXT:    vshl.u32 q8, q11, q8
160 ; NEON-NEXT:    vshl.u32 q9, q11, q9
161 ; NEON-NEXT:    vorr q8, q8, q9
162 ; NEON-NEXT:    vmov r0, r1, d16
163 ; NEON-NEXT:    vmov r2, r3, d17
164 ; NEON-NEXT:    bx lr
165   %f = call <4 x i32> @llvm.fshl.v4i32(<4 x i32> %x, <4 x i32> %x, <4 x i32> %z)
166   ret <4 x i32> %f
169 ; Vector rotate by constant splat amount.
171 define <4 x i32> @rotl_v4i32_rotl_const_shift(<4 x i32> %x) {
172 ; SCALAR-LABEL: rotl_v4i32_rotl_const_shift:
173 ; SCALAR:       @ %bb.0:
174 ; SCALAR-NEXT:    ror r0, r0, #29
175 ; SCALAR-NEXT:    ror r1, r1, #29
176 ; SCALAR-NEXT:    ror r2, r2, #29
177 ; SCALAR-NEXT:    ror r3, r3, #29
178 ; SCALAR-NEXT:    bx lr
180 ; NEON-LABEL: rotl_v4i32_rotl_const_shift:
181 ; NEON:       @ %bb.0:
182 ; NEON-NEXT:    vmov d17, r2, r3
183 ; NEON-NEXT:    vmov d16, r0, r1
184 ; NEON-NEXT:    vshr.u32 q9, q8, #29
185 ; NEON-NEXT:    vshl.i32 q8, q8, #3
186 ; NEON-NEXT:    vorr q8, q8, q9
187 ; NEON-NEXT:    vmov r0, r1, d16
188 ; NEON-NEXT:    vmov r2, r3, d17
189 ; NEON-NEXT:    bx lr
190   %f = call <4 x i32> @llvm.fshl.v4i32(<4 x i32> %x, <4 x i32> %x, <4 x i32> <i32 3, i32 3, i32 3, i32 3>)
191   ret <4 x i32> %f
194 ; Repeat everything for funnel shift right.
196 ; When first 2 operands match, it's a rotate.
198 define i8 @rotr_i8_const_shift(i8 %x) {
199 ; CHECK-LABEL: rotr_i8_const_shift:
200 ; CHECK:       @ %bb.0:
201 ; CHECK-NEXT:    uxtb r1, r0
202 ; CHECK-NEXT:    lsr r1, r1, #3
203 ; CHECK-NEXT:    orr r0, r1, r0, lsl #5
204 ; CHECK-NEXT:    bx lr
205   %f = call i8 @llvm.fshr.i8(i8 %x, i8 %x, i8 3)
206   ret i8 %f
209 define i32 @rotr_i32_const_shift(i32 %x) {
210 ; CHECK-LABEL: rotr_i32_const_shift:
211 ; CHECK:       @ %bb.0:
212 ; CHECK-NEXT:    ror r0, r0, #3
213 ; CHECK-NEXT:    bx lr
214   %f = call i32 @llvm.fshr.i32(i32 %x, i32 %x, i32 3)
215   ret i32 %f
218 ; When first 2 operands match, it's a rotate (by variable amount).
220 define i16 @rotr_i16(i16 %x, i16 %z) {
221 ; CHECK-LABEL: rotr_i16:
222 ; CHECK:       @ %bb.0:
223 ; CHECK-NEXT:    and r2, r1, #15
224 ; CHECK-NEXT:    rsb r1, r1, #0
225 ; CHECK-NEXT:    and r1, r1, #15
226 ; CHECK-NEXT:    uxth r3, r0
227 ; CHECK-NEXT:    lsr r2, r3, r2
228 ; CHECK-NEXT:    orr r0, r2, r0, lsl r1
229 ; CHECK-NEXT:    bx lr
230   %f = call i16 @llvm.fshr.i16(i16 %x, i16 %x, i16 %z)
231   ret i16 %f
234 define i32 @rotr_i32(i32 %x, i32 %z) {
235 ; CHECK-LABEL: rotr_i32:
236 ; CHECK:       @ %bb.0:
237 ; CHECK-NEXT:    ror r0, r0, r1
238 ; CHECK-NEXT:    bx lr
239   %f = call i32 @llvm.fshr.i32(i32 %x, i32 %x, i32 %z)
240   ret i32 %f
243 define i64 @rotr_i64(i64 %x, i64 %z) {
244 ; CHECK-LABEL: rotr_i64:
245 ; CHECK:       @ %bb.0:
246 ; CHECK-NEXT:    .save {r4, r5, r11, lr}
247 ; CHECK-NEXT:    push {r4, r5, r11, lr}
248 ; CHECK-NEXT:    and lr, r2, #63
249 ; CHECK-NEXT:    rsb r2, r2, #0
250 ; CHECK-NEXT:    rsb r3, lr, #32
251 ; CHECK-NEXT:    and r4, r2, #63
252 ; CHECK-NEXT:    lsr r12, r0, lr
253 ; CHECK-NEXT:    orr r3, r12, r1, lsl r3
254 ; CHECK-NEXT:    subs r12, lr, #32
255 ; CHECK-NEXT:    lsl r2, r0, r4
256 ; CHECK-NEXT:    lsrpl r3, r1, r12
257 ; CHECK-NEXT:    subs r5, r4, #32
258 ; CHECK-NEXT:    movwpl r2, #0
259 ; CHECK-NEXT:    cmp r5, #0
260 ; CHECK-NEXT:    orr r2, r3, r2
261 ; CHECK-NEXT:    rsb r3, r4, #32
262 ; CHECK-NEXT:    lsr r3, r0, r3
263 ; CHECK-NEXT:    orr r3, r3, r1, lsl r4
264 ; CHECK-NEXT:    lslpl r3, r0, r5
265 ; CHECK-NEXT:    lsr r0, r1, lr
266 ; CHECK-NEXT:    cmp r12, #0
267 ; CHECK-NEXT:    movwpl r0, #0
268 ; CHECK-NEXT:    orr r1, r0, r3
269 ; CHECK-NEXT:    mov r0, r2
270 ; CHECK-NEXT:    pop {r4, r5, r11, pc}
271   %f = call i64 @llvm.fshr.i64(i64 %x, i64 %x, i64 %z)
272   ret i64 %f
275 ; Vector rotate.
277 define <4 x i32> @rotr_v4i32(<4 x i32> %x, <4 x i32> %z) {
278 ; SCALAR-LABEL: rotr_v4i32:
279 ; SCALAR:       @ %bb.0:
280 ; SCALAR-NEXT:    ldr r12, [sp]
281 ; SCALAR-NEXT:    ror r0, r0, r12
282 ; SCALAR-NEXT:    ldr r12, [sp, #4]
283 ; SCALAR-NEXT:    ror r1, r1, r12
284 ; SCALAR-NEXT:    ldr r12, [sp, #8]
285 ; SCALAR-NEXT:    ror r2, r2, r12
286 ; SCALAR-NEXT:    ldr r12, [sp, #12]
287 ; SCALAR-NEXT:    ror r3, r3, r12
288 ; SCALAR-NEXT:    bx lr
290 ; NEON-LABEL: rotr_v4i32:
291 ; NEON:       @ %bb.0:
292 ; NEON-NEXT:    mov r12, sp
293 ; NEON-NEXT:    vld1.64 {d16, d17}, [r12]
294 ; NEON-NEXT:    vmov.i32 q9, #0x1f
295 ; NEON-NEXT:    vneg.s32 q10, q8
296 ; NEON-NEXT:    vand q8, q8, q9
297 ; NEON-NEXT:    vmov d23, r2, r3
298 ; NEON-NEXT:    vand q9, q10, q9
299 ; NEON-NEXT:    vneg.s32 q8, q8
300 ; NEON-NEXT:    vmov d22, r0, r1
301 ; NEON-NEXT:    vshl.u32 q9, q11, q9
302 ; NEON-NEXT:    vshl.u32 q8, q11, q8
303 ; NEON-NEXT:    vorr q8, q8, q9
304 ; NEON-NEXT:    vmov r0, r1, d16
305 ; NEON-NEXT:    vmov r2, r3, d17
306 ; NEON-NEXT:    bx lr
307   %f = call <4 x i32> @llvm.fshr.v4i32(<4 x i32> %x, <4 x i32> %x, <4 x i32> %z)
308   ret <4 x i32> %f
311 ; Vector rotate by constant splat amount.
313 define <4 x i32> @rotr_v4i32_const_shift(<4 x i32> %x) {
314 ; SCALAR-LABEL: rotr_v4i32_const_shift:
315 ; SCALAR:       @ %bb.0:
316 ; SCALAR-NEXT:    ror r0, r0, #3
317 ; SCALAR-NEXT:    ror r1, r1, #3
318 ; SCALAR-NEXT:    ror r2, r2, #3
319 ; SCALAR-NEXT:    ror r3, r3, #3
320 ; SCALAR-NEXT:    bx lr
322 ; NEON-LABEL: rotr_v4i32_const_shift:
323 ; NEON:       @ %bb.0:
324 ; NEON-NEXT:    vmov d17, r2, r3
325 ; NEON-NEXT:    vmov d16, r0, r1
326 ; NEON-NEXT:    vshl.i32 q9, q8, #29
327 ; NEON-NEXT:    vshr.u32 q8, q8, #3
328 ; NEON-NEXT:    vorr q8, q8, q9
329 ; NEON-NEXT:    vmov r0, r1, d16
330 ; NEON-NEXT:    vmov r2, r3, d17
331 ; NEON-NEXT:    bx lr
332   %f = call <4 x i32> @llvm.fshr.v4i32(<4 x i32> %x, <4 x i32> %x, <4 x i32> <i32 3, i32 3, i32 3, i32 3>)
333   ret <4 x i32> %f
336 define i32 @rotl_i32_shift_by_bitwidth(i32 %x) {
337 ; CHECK-LABEL: rotl_i32_shift_by_bitwidth:
338 ; CHECK:       @ %bb.0:
339 ; CHECK-NEXT:    bx lr
340   %f = call i32 @llvm.fshl.i32(i32 %x, i32 %x, i32 32)
341   ret i32 %f
344 define i32 @rotr_i32_shift_by_bitwidth(i32 %x) {
345 ; CHECK-LABEL: rotr_i32_shift_by_bitwidth:
346 ; CHECK:       @ %bb.0:
347 ; CHECK-NEXT:    bx lr
348   %f = call i32 @llvm.fshr.i32(i32 %x, i32 %x, i32 32)
349   ret i32 %f
352 define <4 x i32> @rotl_v4i32_shift_by_bitwidth(<4 x i32> %x) {
353 ; CHECK-LABEL: rotl_v4i32_shift_by_bitwidth:
354 ; CHECK:       @ %bb.0:
355 ; CHECK-NEXT:    bx lr
356   %f = call <4 x i32> @llvm.fshl.v4i32(<4 x i32> %x, <4 x i32> %x, <4 x i32> <i32 32, i32 32, i32 32, i32 32>)
357   ret <4 x i32> %f
360 define <4 x i32> @rotr_v4i32_shift_by_bitwidth(<4 x i32> %x) {
361 ; CHECK-LABEL: rotr_v4i32_shift_by_bitwidth:
362 ; CHECK:       @ %bb.0:
363 ; CHECK-NEXT:    bx lr
364   %f = call <4 x i32> @llvm.fshr.v4i32(<4 x i32> %x, <4 x i32> %x, <4 x i32> <i32 32, i32 32, i32 32, i32 32>)
365   ret <4 x i32> %f