1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc < %s -mtriple=mips-linux-gnu -march=mips -mcpu=mips32 | FileCheck %s --check-prefixes=CHECK,CHECK-BE
3 ; RUN: llc < %s -mtriple=mipsel-linux-gnu -march=mipsel -mcpu=mips32 | FileCheck %s --check-prefixes=CHECK,CHECK-LE
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:
22 ; CHECK-NEXT: sll $1, $4, 3
23 ; CHECK-NEXT: andi $2, $4, 224
24 ; CHECK-NEXT: srl $2, $2, 5
26 ; CHECK-NEXT: or $2, $1, $2
27 %f = call i8 @llvm.fshl.i8(i8 %x, i8 %x, i8 3)
31 define i64 @rotl_i64_const_shift(i64 %x) {
32 ; CHECK-LABEL: rotl_i64_const_shift:
34 ; CHECK-NEXT: srl $1, $5, 29
35 ; CHECK-NEXT: sll $2, $4, 3
36 ; CHECK-NEXT: or $2, $2, $1
37 ; CHECK-NEXT: srl $1, $4, 29
38 ; CHECK-NEXT: sll $3, $5, 3
40 ; CHECK-NEXT: or $3, $3, $1
41 %f = call i64 @llvm.fshl.i64(i64 %x, i64 %x, i64 3)
45 ; When first 2 operands match, it's a rotate (by variable amount).
47 define i16 @rotl_i16(i16 %x, i16 %z) {
48 ; CHECK-LABEL: rotl_i16:
50 ; CHECK-NEXT: andi $1, $5, 15
51 ; CHECK-NEXT: sllv $1, $4, $1
52 ; CHECK-NEXT: negu $2, $5
53 ; CHECK-NEXT: andi $2, $2, 15
54 ; CHECK-NEXT: andi $3, $4, 65535
55 ; CHECK-NEXT: srlv $2, $3, $2
57 ; CHECK-NEXT: or $2, $1, $2
58 %f = call i16 @llvm.fshl.i16(i16 %x, i16 %x, i16 %z)
62 define i32 @rotl_i32(i32 %x, i32 %z) {
63 ; CHECK-LABEL: rotl_i32:
65 ; CHECK-NEXT: andi $1, $5, 31
66 ; CHECK-NEXT: sllv $1, $4, $1
67 ; CHECK-NEXT: negu $2, $5
68 ; CHECK-NEXT: andi $2, $2, 31
69 ; CHECK-NEXT: srlv $2, $4, $2
71 ; CHECK-NEXT: or $2, $1, $2
72 %f = call i32 @llvm.fshl.i32(i32 %x, i32 %x, i32 %z)
76 define i64 @rotl_i64(i64 %x, i64 %z) {
77 ; CHECK-BE-LABEL: rotl_i64:
79 ; CHECK-BE-NEXT: srl $1, $7, 5
80 ; CHECK-BE-NEXT: andi $1, $1, 1
81 ; CHECK-BE-NEXT: move $3, $4
82 ; CHECK-BE-NEXT: movn $3, $5, $1
83 ; CHECK-BE-NEXT: andi $6, $7, 31
84 ; CHECK-BE-NEXT: sllv $2, $3, $6
85 ; CHECK-BE-NEXT: movn $5, $4, $1
86 ; CHECK-BE-NEXT: srl $1, $5, 1
87 ; CHECK-BE-NEXT: not $4, $7
88 ; CHECK-BE-NEXT: andi $4, $4, 31
89 ; CHECK-BE-NEXT: srlv $1, $1, $4
90 ; CHECK-BE-NEXT: or $2, $2, $1
91 ; CHECK-BE-NEXT: sllv $1, $5, $6
92 ; CHECK-BE-NEXT: srl $3, $3, 1
93 ; CHECK-BE-NEXT: srlv $3, $3, $4
94 ; CHECK-BE-NEXT: jr $ra
95 ; CHECK-BE-NEXT: or $3, $1, $3
97 ; CHECK-LE-LABEL: rotl_i64:
99 ; CHECK-LE-NEXT: srl $1, $6, 5
100 ; CHECK-LE-NEXT: andi $1, $1, 1
101 ; CHECK-LE-NEXT: move $3, $4
102 ; CHECK-LE-NEXT: movn $3, $5, $1
103 ; CHECK-LE-NEXT: andi $7, $6, 31
104 ; CHECK-LE-NEXT: sllv $2, $3, $7
105 ; CHECK-LE-NEXT: movn $5, $4, $1
106 ; CHECK-LE-NEXT: srl $1, $5, 1
107 ; CHECK-LE-NEXT: not $4, $6
108 ; CHECK-LE-NEXT: andi $4, $4, 31
109 ; CHECK-LE-NEXT: srlv $1, $1, $4
110 ; CHECK-LE-NEXT: or $2, $2, $1
111 ; CHECK-LE-NEXT: sllv $1, $5, $7
112 ; CHECK-LE-NEXT: srl $3, $3, 1
113 ; CHECK-LE-NEXT: srlv $3, $3, $4
114 ; CHECK-LE-NEXT: jr $ra
115 ; CHECK-LE-NEXT: or $3, $1, $3
116 %f = call i64 @llvm.fshl.i64(i64 %x, i64 %x, i64 %z)
122 define <4 x i32> @rotl_v4i32(<4 x i32> %x, <4 x i32> %z) {
123 ; CHECK-LABEL: rotl_v4i32:
125 ; CHECK-NEXT: lw $1, 24($sp)
126 ; CHECK-NEXT: negu $2, $1
127 ; CHECK-NEXT: lw $3, 20($sp)
128 ; CHECK-NEXT: negu $8, $3
129 ; CHECK-NEXT: andi $8, $8, 31
130 ; CHECK-NEXT: andi $2, $2, 31
131 ; CHECK-NEXT: andi $3, $3, 31
132 ; CHECK-NEXT: andi $1, $1, 31
133 ; CHECK-NEXT: lw $9, 16($sp)
134 ; CHECK-NEXT: sllv $1, $6, $1
135 ; CHECK-NEXT: srlv $6, $6, $2
136 ; CHECK-NEXT: sllv $3, $5, $3
137 ; CHECK-NEXT: srlv $5, $5, $8
138 ; CHECK-NEXT: andi $2, $9, 31
139 ; CHECK-NEXT: sllv $2, $4, $2
140 ; CHECK-NEXT: negu $8, $9
141 ; CHECK-NEXT: andi $8, $8, 31
142 ; CHECK-NEXT: srlv $4, $4, $8
143 ; CHECK-NEXT: lw $8, 28($sp)
144 ; CHECK-NEXT: or $2, $2, $4
145 ; CHECK-NEXT: or $3, $3, $5
146 ; CHECK-NEXT: or $4, $1, $6
147 ; CHECK-NEXT: andi $1, $8, 31
148 ; CHECK-NEXT: sllv $1, $7, $1
149 ; CHECK-NEXT: negu $5, $8
150 ; CHECK-NEXT: andi $5, $5, 31
151 ; CHECK-NEXT: srlv $5, $7, $5
153 ; CHECK-NEXT: or $5, $1, $5
154 %f = call <4 x i32> @llvm.fshl.v4i32(<4 x i32> %x, <4 x i32> %x, <4 x i32> %z)
158 ; Vector rotate by constant splat amount.
160 define <4 x i32> @rotl_v4i32_rotl_const_shift(<4 x i32> %x) {
161 ; CHECK-LABEL: rotl_v4i32_rotl_const_shift:
163 ; CHECK-NEXT: srl $1, $5, 29
164 ; CHECK-NEXT: sll $3, $5, 3
165 ; CHECK-NEXT: srl $2, $4, 29
166 ; CHECK-NEXT: sll $4, $4, 3
167 ; CHECK-NEXT: or $2, $4, $2
168 ; CHECK-NEXT: or $3, $3, $1
169 ; CHECK-NEXT: srl $1, $6, 29
170 ; CHECK-NEXT: sll $4, $6, 3
171 ; CHECK-NEXT: or $4, $4, $1
172 ; CHECK-NEXT: srl $1, $7, 29
173 ; CHECK-NEXT: sll $5, $7, 3
175 ; CHECK-NEXT: or $5, $5, $1
176 %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>)
180 ; Repeat everything for funnel shift right.
182 ; When first 2 operands match, it's a rotate.
184 define i8 @rotr_i8_const_shift(i8 %x) {
185 ; CHECK-LABEL: rotr_i8_const_shift:
187 ; CHECK-NEXT: sll $1, $4, 5
188 ; CHECK-NEXT: andi $2, $4, 248
189 ; CHECK-NEXT: srl $2, $2, 3
191 ; CHECK-NEXT: or $2, $2, $1
192 %f = call i8 @llvm.fshr.i8(i8 %x, i8 %x, i8 3)
196 define i32 @rotr_i32_const_shift(i32 %x) {
197 ; CHECK-LABEL: rotr_i32_const_shift:
199 ; CHECK-NEXT: sll $1, $4, 29
200 ; CHECK-NEXT: srl $2, $4, 3
202 ; CHECK-NEXT: or $2, $2, $1
203 %f = call i32 @llvm.fshr.i32(i32 %x, i32 %x, i32 3)
207 ; When first 2 operands match, it's a rotate (by variable amount).
209 define i16 @rotr_i16(i16 %x, i16 %z) {
210 ; CHECK-LABEL: rotr_i16:
212 ; CHECK-NEXT: andi $1, $5, 15
213 ; CHECK-NEXT: andi $2, $4, 65535
214 ; CHECK-NEXT: srlv $1, $2, $1
215 ; CHECK-NEXT: negu $2, $5
216 ; CHECK-NEXT: andi $2, $2, 15
217 ; CHECK-NEXT: sllv $2, $4, $2
219 ; CHECK-NEXT: or $2, $1, $2
220 %f = call i16 @llvm.fshr.i16(i16 %x, i16 %x, i16 %z)
224 define i32 @rotr_i32(i32 %x, i32 %z) {
225 ; CHECK-LABEL: rotr_i32:
227 ; CHECK-NEXT: andi $1, $5, 31
228 ; CHECK-NEXT: srlv $1, $4, $1
229 ; CHECK-NEXT: negu $2, $5
230 ; CHECK-NEXT: andi $2, $2, 31
231 ; CHECK-NEXT: sllv $2, $4, $2
233 ; CHECK-NEXT: or $2, $1, $2
234 %f = call i32 @llvm.fshr.i32(i32 %x, i32 %x, i32 %z)
238 define i64 @rotr_i64(i64 %x, i64 %z) {
239 ; CHECK-BE-LABEL: rotr_i64:
241 ; CHECK-BE-NEXT: andi $1, $7, 32
242 ; CHECK-BE-NEXT: move $3, $5
243 ; CHECK-BE-NEXT: movz $3, $4, $1
244 ; CHECK-BE-NEXT: andi $6, $7, 31
245 ; CHECK-BE-NEXT: srlv $2, $3, $6
246 ; CHECK-BE-NEXT: movz $4, $5, $1
247 ; CHECK-BE-NEXT: sll $1, $4, 1
248 ; CHECK-BE-NEXT: not $5, $7
249 ; CHECK-BE-NEXT: andi $5, $5, 31
250 ; CHECK-BE-NEXT: sllv $1, $1, $5
251 ; CHECK-BE-NEXT: or $2, $1, $2
252 ; CHECK-BE-NEXT: srlv $1, $4, $6
253 ; CHECK-BE-NEXT: sll $3, $3, 1
254 ; CHECK-BE-NEXT: sllv $3, $3, $5
255 ; CHECK-BE-NEXT: jr $ra
256 ; CHECK-BE-NEXT: or $3, $3, $1
258 ; CHECK-LE-LABEL: rotr_i64:
260 ; CHECK-LE-NEXT: andi $1, $6, 32
261 ; CHECK-LE-NEXT: move $3, $5
262 ; CHECK-LE-NEXT: movz $3, $4, $1
263 ; CHECK-LE-NEXT: andi $7, $6, 31
264 ; CHECK-LE-NEXT: srlv $2, $3, $7
265 ; CHECK-LE-NEXT: movz $4, $5, $1
266 ; CHECK-LE-NEXT: sll $1, $4, 1
267 ; CHECK-LE-NEXT: not $5, $6
268 ; CHECK-LE-NEXT: andi $5, $5, 31
269 ; CHECK-LE-NEXT: sllv $1, $1, $5
270 ; CHECK-LE-NEXT: or $2, $1, $2
271 ; CHECK-LE-NEXT: srlv $1, $4, $7
272 ; CHECK-LE-NEXT: sll $3, $3, 1
273 ; CHECK-LE-NEXT: sllv $3, $3, $5
274 ; CHECK-LE-NEXT: jr $ra
275 ; CHECK-LE-NEXT: or $3, $3, $1
276 %f = call i64 @llvm.fshr.i64(i64 %x, i64 %x, i64 %z)
282 define <4 x i32> @rotr_v4i32(<4 x i32> %x, <4 x i32> %z) {
283 ; CHECK-LABEL: rotr_v4i32:
285 ; CHECK-NEXT: lw $1, 24($sp)
286 ; CHECK-NEXT: negu $2, $1
287 ; CHECK-NEXT: lw $3, 20($sp)
288 ; CHECK-NEXT: negu $8, $3
289 ; CHECK-NEXT: andi $8, $8, 31
290 ; CHECK-NEXT: andi $2, $2, 31
291 ; CHECK-NEXT: andi $3, $3, 31
292 ; CHECK-NEXT: andi $1, $1, 31
293 ; CHECK-NEXT: lw $9, 16($sp)
294 ; CHECK-NEXT: srlv $1, $6, $1
295 ; CHECK-NEXT: sllv $6, $6, $2
296 ; CHECK-NEXT: srlv $3, $5, $3
297 ; CHECK-NEXT: sllv $5, $5, $8
298 ; CHECK-NEXT: andi $2, $9, 31
299 ; CHECK-NEXT: srlv $2, $4, $2
300 ; CHECK-NEXT: negu $8, $9
301 ; CHECK-NEXT: andi $8, $8, 31
302 ; CHECK-NEXT: sllv $4, $4, $8
303 ; CHECK-NEXT: lw $8, 28($sp)
304 ; CHECK-NEXT: or $2, $2, $4
305 ; CHECK-NEXT: or $3, $3, $5
306 ; CHECK-NEXT: or $4, $1, $6
307 ; CHECK-NEXT: andi $1, $8, 31
308 ; CHECK-NEXT: srlv $1, $7, $1
309 ; CHECK-NEXT: negu $5, $8
310 ; CHECK-NEXT: andi $5, $5, 31
311 ; CHECK-NEXT: sllv $5, $7, $5
313 ; CHECK-NEXT: or $5, $1, $5
314 %f = call <4 x i32> @llvm.fshr.v4i32(<4 x i32> %x, <4 x i32> %x, <4 x i32> %z)
318 ; Vector rotate by constant splat amount.
320 define <4 x i32> @rotr_v4i32_const_shift(<4 x i32> %x) {
321 ; CHECK-LABEL: rotr_v4i32_const_shift:
323 ; CHECK-NEXT: sll $1, $5, 29
324 ; CHECK-NEXT: srl $3, $5, 3
325 ; CHECK-NEXT: sll $2, $4, 29
326 ; CHECK-NEXT: srl $4, $4, 3
327 ; CHECK-NEXT: or $2, $4, $2
328 ; CHECK-NEXT: or $3, $3, $1
329 ; CHECK-NEXT: sll $1, $6, 29
330 ; CHECK-NEXT: srl $4, $6, 3
331 ; CHECK-NEXT: or $4, $4, $1
332 ; CHECK-NEXT: sll $1, $7, 29
333 ; CHECK-NEXT: srl $5, $7, 3
335 ; CHECK-NEXT: or $5, $5, $1
336 %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>)
340 define i32 @rotl_i32_shift_by_bitwidth(i32 %x) {
341 ; CHECK-LABEL: rotl_i32_shift_by_bitwidth:
344 ; CHECK-NEXT: move $2, $4
345 %f = call i32 @llvm.fshl.i32(i32 %x, i32 %x, i32 32)
349 define i32 @rotr_i32_shift_by_bitwidth(i32 %x) {
350 ; CHECK-LABEL: rotr_i32_shift_by_bitwidth:
353 ; CHECK-NEXT: move $2, $4
354 %f = call i32 @llvm.fshr.i32(i32 %x, i32 %x, i32 32)
358 define <4 x i32> @rotl_v4i32_shift_by_bitwidth(<4 x i32> %x) {
359 ; CHECK-LABEL: rotl_v4i32_shift_by_bitwidth:
361 ; CHECK-NEXT: move $2, $4
362 ; CHECK-NEXT: move $3, $5
363 ; CHECK-NEXT: move $4, $6
365 ; CHECK-NEXT: move $5, $7
366 %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>)
370 define <4 x i32> @rotr_v4i32_shift_by_bitwidth(<4 x i32> %x) {
371 ; CHECK-LABEL: rotr_v4i32_shift_by_bitwidth:
373 ; CHECK-NEXT: move $2, $4
374 ; CHECK-NEXT: move $3, $5
375 ; CHECK-NEXT: move $4, $6
377 ; CHECK-NEXT: move $5, $7
378 %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>)