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: negu $1, $7
80 ; CHECK-BE-NEXT: andi $3, $1, 63
81 ; CHECK-BE-NEXT: srlv $6, $4, $3
82 ; CHECK-BE-NEXT: andi $1, $1, 32
83 ; CHECK-BE-NEXT: andi $2, $7, 63
84 ; CHECK-BE-NEXT: move $8, $6
85 ; CHECK-BE-NEXT: movn $8, $zero, $1
86 ; CHECK-BE-NEXT: sllv $9, $4, $2
87 ; CHECK-BE-NEXT: srl $10, $5, 1
88 ; CHECK-BE-NEXT: not $11, $2
89 ; CHECK-BE-NEXT: srlv $10, $10, $11
90 ; CHECK-BE-NEXT: or $9, $9, $10
91 ; CHECK-BE-NEXT: sllv $10, $5, $2
92 ; CHECK-BE-NEXT: andi $7, $7, 32
93 ; CHECK-BE-NEXT: movn $9, $10, $7
94 ; CHECK-BE-NEXT: or $2, $9, $8
95 ; CHECK-BE-NEXT: srlv $5, $5, $3
96 ; CHECK-BE-NEXT: not $3, $3
97 ; CHECK-BE-NEXT: sll $4, $4, 1
98 ; CHECK-BE-NEXT: sllv $3, $4, $3
99 ; CHECK-BE-NEXT: or $3, $3, $5
100 ; CHECK-BE-NEXT: movn $3, $6, $1
101 ; CHECK-BE-NEXT: movn $10, $zero, $7
102 ; CHECK-BE-NEXT: jr $ra
103 ; CHECK-BE-NEXT: or $3, $10, $3
105 ; CHECK-LE-LABEL: rotl_i64:
107 ; CHECK-LE-NEXT: negu $1, $6
108 ; CHECK-LE-NEXT: andi $2, $1, 63
109 ; CHECK-LE-NEXT: srlv $7, $5, $2
110 ; CHECK-LE-NEXT: andi $1, $1, 32
111 ; CHECK-LE-NEXT: andi $3, $6, 63
112 ; CHECK-LE-NEXT: move $8, $7
113 ; CHECK-LE-NEXT: movn $8, $zero, $1
114 ; CHECK-LE-NEXT: sllv $9, $5, $3
115 ; CHECK-LE-NEXT: srl $10, $4, 1
116 ; CHECK-LE-NEXT: not $11, $3
117 ; CHECK-LE-NEXT: srlv $10, $10, $11
118 ; CHECK-LE-NEXT: or $9, $9, $10
119 ; CHECK-LE-NEXT: sllv $10, $4, $3
120 ; CHECK-LE-NEXT: andi $6, $6, 32
121 ; CHECK-LE-NEXT: movn $9, $10, $6
122 ; CHECK-LE-NEXT: or $3, $9, $8
123 ; CHECK-LE-NEXT: srlv $4, $4, $2
124 ; CHECK-LE-NEXT: not $2, $2
125 ; CHECK-LE-NEXT: sll $5, $5, 1
126 ; CHECK-LE-NEXT: sllv $2, $5, $2
127 ; CHECK-LE-NEXT: or $2, $2, $4
128 ; CHECK-LE-NEXT: movn $2, $7, $1
129 ; CHECK-LE-NEXT: movn $10, $zero, $6
130 ; CHECK-LE-NEXT: jr $ra
131 ; CHECK-LE-NEXT: or $2, $10, $2
132 %f = call i64 @llvm.fshl.i64(i64 %x, i64 %x, i64 %z)
138 define <4 x i32> @rotl_v4i32(<4 x i32> %x, <4 x i32> %z) {
139 ; CHECK-LABEL: rotl_v4i32:
141 ; CHECK-NEXT: lw $1, 24($sp)
142 ; CHECK-NEXT: negu $2, $1
143 ; CHECK-NEXT: lw $3, 20($sp)
144 ; CHECK-NEXT: negu $8, $3
145 ; CHECK-NEXT: andi $8, $8, 31
146 ; CHECK-NEXT: andi $2, $2, 31
147 ; CHECK-NEXT: andi $3, $3, 31
148 ; CHECK-NEXT: andi $1, $1, 31
149 ; CHECK-NEXT: lw $9, 16($sp)
150 ; CHECK-NEXT: sllv $1, $6, $1
151 ; CHECK-NEXT: srlv $6, $6, $2
152 ; CHECK-NEXT: sllv $3, $5, $3
153 ; CHECK-NEXT: srlv $5, $5, $8
154 ; CHECK-NEXT: andi $2, $9, 31
155 ; CHECK-NEXT: sllv $2, $4, $2
156 ; CHECK-NEXT: negu $8, $9
157 ; CHECK-NEXT: andi $8, $8, 31
158 ; CHECK-NEXT: srlv $4, $4, $8
159 ; CHECK-NEXT: lw $8, 28($sp)
160 ; CHECK-NEXT: or $2, $2, $4
161 ; CHECK-NEXT: or $3, $3, $5
162 ; CHECK-NEXT: or $4, $1, $6
163 ; CHECK-NEXT: andi $1, $8, 31
164 ; CHECK-NEXT: sllv $1, $7, $1
165 ; CHECK-NEXT: negu $5, $8
166 ; CHECK-NEXT: andi $5, $5, 31
167 ; CHECK-NEXT: srlv $5, $7, $5
169 ; CHECK-NEXT: or $5, $1, $5
170 %f = call <4 x i32> @llvm.fshl.v4i32(<4 x i32> %x, <4 x i32> %x, <4 x i32> %z)
174 ; Vector rotate by constant splat amount.
176 define <4 x i32> @rotl_v4i32_rotl_const_shift(<4 x i32> %x) {
177 ; CHECK-LABEL: rotl_v4i32_rotl_const_shift:
179 ; CHECK-NEXT: srl $1, $5, 29
180 ; CHECK-NEXT: sll $3, $5, 3
181 ; CHECK-NEXT: srl $2, $4, 29
182 ; CHECK-NEXT: sll $4, $4, 3
183 ; CHECK-NEXT: or $2, $4, $2
184 ; CHECK-NEXT: or $3, $3, $1
185 ; CHECK-NEXT: srl $1, $6, 29
186 ; CHECK-NEXT: sll $4, $6, 3
187 ; CHECK-NEXT: or $4, $4, $1
188 ; CHECK-NEXT: srl $1, $7, 29
189 ; CHECK-NEXT: sll $5, $7, 3
191 ; CHECK-NEXT: or $5, $5, $1
192 %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>)
196 ; Repeat everything for funnel shift right.
198 ; When first 2 operands match, it's a rotate.
200 define i8 @rotr_i8_const_shift(i8 %x) {
201 ; CHECK-LABEL: rotr_i8_const_shift:
203 ; CHECK-NEXT: sll $1, $4, 5
204 ; CHECK-NEXT: andi $2, $4, 248
205 ; CHECK-NEXT: srl $2, $2, 3
207 ; CHECK-NEXT: or $2, $2, $1
208 %f = call i8 @llvm.fshr.i8(i8 %x, i8 %x, i8 3)
212 define i32 @rotr_i32_const_shift(i32 %x) {
213 ; CHECK-LABEL: rotr_i32_const_shift:
215 ; CHECK-NEXT: sll $1, $4, 29
216 ; CHECK-NEXT: srl $2, $4, 3
218 ; CHECK-NEXT: or $2, $2, $1
219 %f = call i32 @llvm.fshr.i32(i32 %x, i32 %x, i32 3)
223 ; When first 2 operands match, it's a rotate (by variable amount).
225 define i16 @rotr_i16(i16 %x, i16 %z) {
226 ; CHECK-LABEL: rotr_i16:
228 ; CHECK-NEXT: andi $1, $5, 15
229 ; CHECK-NEXT: andi $2, $4, 65535
230 ; CHECK-NEXT: srlv $1, $2, $1
231 ; CHECK-NEXT: negu $2, $5
232 ; CHECK-NEXT: andi $2, $2, 15
233 ; CHECK-NEXT: sllv $2, $4, $2
235 ; CHECK-NEXT: or $2, $1, $2
236 %f = call i16 @llvm.fshr.i16(i16 %x, i16 %x, i16 %z)
240 define i32 @rotr_i32(i32 %x, i32 %z) {
241 ; CHECK-LABEL: rotr_i32:
243 ; CHECK-NEXT: andi $1, $5, 31
244 ; CHECK-NEXT: srlv $1, $4, $1
245 ; CHECK-NEXT: negu $2, $5
246 ; CHECK-NEXT: andi $2, $2, 31
247 ; CHECK-NEXT: sllv $2, $4, $2
249 ; CHECK-NEXT: or $2, $1, $2
250 %f = call i32 @llvm.fshr.i32(i32 %x, i32 %x, i32 %z)
254 define i64 @rotr_i64(i64 %x, i64 %z) {
255 ; CHECK-BE-LABEL: rotr_i64:
257 ; CHECK-BE-NEXT: negu $1, $7
258 ; CHECK-BE-NEXT: andi $2, $1, 63
259 ; CHECK-BE-NEXT: sllv $6, $5, $2
260 ; CHECK-BE-NEXT: andi $1, $1, 32
261 ; CHECK-BE-NEXT: andi $3, $7, 63
262 ; CHECK-BE-NEXT: move $8, $6
263 ; CHECK-BE-NEXT: movn $8, $zero, $1
264 ; CHECK-BE-NEXT: srlv $9, $5, $3
265 ; CHECK-BE-NEXT: sll $10, $4, 1
266 ; CHECK-BE-NEXT: not $11, $3
267 ; CHECK-BE-NEXT: sllv $10, $10, $11
268 ; CHECK-BE-NEXT: or $9, $10, $9
269 ; CHECK-BE-NEXT: srlv $10, $4, $3
270 ; CHECK-BE-NEXT: andi $7, $7, 32
271 ; CHECK-BE-NEXT: movn $9, $10, $7
272 ; CHECK-BE-NEXT: or $3, $9, $8
273 ; CHECK-BE-NEXT: sllv $4, $4, $2
274 ; CHECK-BE-NEXT: not $2, $2
275 ; CHECK-BE-NEXT: srl $5, $5, 1
276 ; CHECK-BE-NEXT: srlv $2, $5, $2
277 ; CHECK-BE-NEXT: or $2, $4, $2
278 ; CHECK-BE-NEXT: movn $2, $6, $1
279 ; CHECK-BE-NEXT: movn $10, $zero, $7
280 ; CHECK-BE-NEXT: jr $ra
281 ; CHECK-BE-NEXT: or $2, $10, $2
283 ; CHECK-LE-LABEL: rotr_i64:
285 ; CHECK-LE-NEXT: negu $1, $6
286 ; CHECK-LE-NEXT: andi $3, $1, 63
287 ; CHECK-LE-NEXT: sllv $7, $4, $3
288 ; CHECK-LE-NEXT: andi $1, $1, 32
289 ; CHECK-LE-NEXT: andi $2, $6, 63
290 ; CHECK-LE-NEXT: move $8, $7
291 ; CHECK-LE-NEXT: movn $8, $zero, $1
292 ; CHECK-LE-NEXT: srlv $9, $4, $2
293 ; CHECK-LE-NEXT: sll $10, $5, 1
294 ; CHECK-LE-NEXT: not $11, $2
295 ; CHECK-LE-NEXT: sllv $10, $10, $11
296 ; CHECK-LE-NEXT: or $9, $10, $9
297 ; CHECK-LE-NEXT: srlv $10, $5, $2
298 ; CHECK-LE-NEXT: andi $6, $6, 32
299 ; CHECK-LE-NEXT: movn $9, $10, $6
300 ; CHECK-LE-NEXT: or $2, $9, $8
301 ; CHECK-LE-NEXT: sllv $5, $5, $3
302 ; CHECK-LE-NEXT: not $3, $3
303 ; CHECK-LE-NEXT: srl $4, $4, 1
304 ; CHECK-LE-NEXT: srlv $3, $4, $3
305 ; CHECK-LE-NEXT: or $3, $5, $3
306 ; CHECK-LE-NEXT: movn $3, $7, $1
307 ; CHECK-LE-NEXT: movn $10, $zero, $6
308 ; CHECK-LE-NEXT: jr $ra
309 ; CHECK-LE-NEXT: or $3, $10, $3
310 %f = call i64 @llvm.fshr.i64(i64 %x, i64 %x, i64 %z)
316 define <4 x i32> @rotr_v4i32(<4 x i32> %x, <4 x i32> %z) {
317 ; CHECK-LABEL: rotr_v4i32:
319 ; CHECK-NEXT: lw $1, 24($sp)
320 ; CHECK-NEXT: negu $2, $1
321 ; CHECK-NEXT: lw $3, 20($sp)
322 ; CHECK-NEXT: negu $8, $3
323 ; CHECK-NEXT: andi $8, $8, 31
324 ; CHECK-NEXT: andi $2, $2, 31
325 ; CHECK-NEXT: andi $3, $3, 31
326 ; CHECK-NEXT: andi $1, $1, 31
327 ; CHECK-NEXT: lw $9, 16($sp)
328 ; CHECK-NEXT: srlv $1, $6, $1
329 ; CHECK-NEXT: sllv $6, $6, $2
330 ; CHECK-NEXT: srlv $3, $5, $3
331 ; CHECK-NEXT: sllv $5, $5, $8
332 ; CHECK-NEXT: andi $2, $9, 31
333 ; CHECK-NEXT: srlv $2, $4, $2
334 ; CHECK-NEXT: negu $8, $9
335 ; CHECK-NEXT: andi $8, $8, 31
336 ; CHECK-NEXT: sllv $4, $4, $8
337 ; CHECK-NEXT: lw $8, 28($sp)
338 ; CHECK-NEXT: or $2, $2, $4
339 ; CHECK-NEXT: or $3, $3, $5
340 ; CHECK-NEXT: or $4, $1, $6
341 ; CHECK-NEXT: andi $1, $8, 31
342 ; CHECK-NEXT: srlv $1, $7, $1
343 ; CHECK-NEXT: negu $5, $8
344 ; CHECK-NEXT: andi $5, $5, 31
345 ; CHECK-NEXT: sllv $5, $7, $5
347 ; CHECK-NEXT: or $5, $1, $5
348 %f = call <4 x i32> @llvm.fshr.v4i32(<4 x i32> %x, <4 x i32> %x, <4 x i32> %z)
352 ; Vector rotate by constant splat amount.
354 define <4 x i32> @rotr_v4i32_const_shift(<4 x i32> %x) {
355 ; CHECK-LABEL: rotr_v4i32_const_shift:
357 ; CHECK-NEXT: sll $1, $5, 29
358 ; CHECK-NEXT: srl $3, $5, 3
359 ; CHECK-NEXT: sll $2, $4, 29
360 ; CHECK-NEXT: srl $4, $4, 3
361 ; CHECK-NEXT: or $2, $4, $2
362 ; CHECK-NEXT: or $3, $3, $1
363 ; CHECK-NEXT: sll $1, $6, 29
364 ; CHECK-NEXT: srl $4, $6, 3
365 ; CHECK-NEXT: or $4, $4, $1
366 ; CHECK-NEXT: sll $1, $7, 29
367 ; CHECK-NEXT: srl $5, $7, 3
369 ; CHECK-NEXT: or $5, $5, $1
370 %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>)
374 define i32 @rotl_i32_shift_by_bitwidth(i32 %x) {
375 ; CHECK-LABEL: rotl_i32_shift_by_bitwidth:
378 ; CHECK-NEXT: move $2, $4
379 %f = call i32 @llvm.fshl.i32(i32 %x, i32 %x, i32 32)
383 define i32 @rotr_i32_shift_by_bitwidth(i32 %x) {
384 ; CHECK-LABEL: rotr_i32_shift_by_bitwidth:
387 ; CHECK-NEXT: move $2, $4
388 %f = call i32 @llvm.fshr.i32(i32 %x, i32 %x, i32 32)
392 define <4 x i32> @rotl_v4i32_shift_by_bitwidth(<4 x i32> %x) {
393 ; CHECK-LABEL: rotl_v4i32_shift_by_bitwidth:
395 ; CHECK-NEXT: move $2, $4
396 ; CHECK-NEXT: move $3, $5
397 ; CHECK-NEXT: move $4, $6
399 ; CHECK-NEXT: move $5, $7
400 %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>)
404 define <4 x i32> @rotr_v4i32_shift_by_bitwidth(<4 x i32> %x) {
405 ; CHECK-LABEL: rotr_v4i32_shift_by_bitwidth:
407 ; CHECK-NEXT: move $2, $4
408 ; CHECK-NEXT: move $3, $5
409 ; CHECK-NEXT: move $4, $6
411 ; CHECK-NEXT: move $5, $7
412 %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>)