Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / llvm / test / CodeGen / Mips / funnel-shift.ll
blob737e95c8262a3940505d72038ae56f72d7086fdd
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 ; General case - all operands can be variables.
19 define i16 @fshl_i16(i16 %x, i16 %y, i16 %z) {
20 ; CHECK-LABEL: fshl_i16:
21 ; CHECK:       # %bb.0:
22 ; CHECK-NEXT:    andi $1, $5, 65535
23 ; CHECK-NEXT:    sll $2, $4, 16
24 ; CHECK-NEXT:    or $1, $2, $1
25 ; CHECK-NEXT:    andi $2, $6, 15
26 ; CHECK-NEXT:    sllv $1, $1, $2
27 ; CHECK-NEXT:    jr $ra
28 ; CHECK-NEXT:    srl $2, $1, 16
29   %f = call i16 @llvm.fshl.i16(i16 %x, i16 %y, i16 %z)
30   ret i16 %f
33 define i32 @fshl_i32(i32 %x, i32 %y, i32 %z) {
34 ; CHECK-LABEL: fshl_i32:
35 ; CHECK:       # %bb.0:
36 ; CHECK-NEXT:    andi $1, $6, 31
37 ; CHECK-NEXT:    sllv $1, $4, $1
38 ; CHECK-NEXT:    srl $2, $5, 1
39 ; CHECK-NEXT:    not $3, $6
40 ; CHECK-NEXT:    andi $3, $3, 31
41 ; CHECK-NEXT:    srlv $2, $2, $3
42 ; CHECK-NEXT:    jr $ra
43 ; CHECK-NEXT:    or $2, $1, $2
44   %f = call i32 @llvm.fshl.i32(i32 %x, i32 %y, i32 %z)
45   ret i32 %f
48 ; Verify that weird types are minimally supported.
49 declare i37 @llvm.fshl.i37(i37, i37, i37)
50 define i37 @fshl_i37(i37 %x, i37 %y, i37 %z) {
51 ; CHECK-BE-LABEL: fshl_i37:
52 ; CHECK-BE:       # %bb.0:
53 ; CHECK-BE-NEXT:    addiu $sp, $sp, -40
54 ; CHECK-BE-NEXT:    .cfi_def_cfa_offset 40
55 ; CHECK-BE-NEXT:    sw $ra, 36($sp) # 4-byte Folded Spill
56 ; CHECK-BE-NEXT:    sw $19, 32($sp) # 4-byte Folded Spill
57 ; CHECK-BE-NEXT:    sw $18, 28($sp) # 4-byte Folded Spill
58 ; CHECK-BE-NEXT:    sw $17, 24($sp) # 4-byte Folded Spill
59 ; CHECK-BE-NEXT:    sw $16, 20($sp) # 4-byte Folded Spill
60 ; CHECK-BE-NEXT:    .cfi_offset 31, -4
61 ; CHECK-BE-NEXT:    .cfi_offset 19, -8
62 ; CHECK-BE-NEXT:    .cfi_offset 18, -12
63 ; CHECK-BE-NEXT:    .cfi_offset 17, -16
64 ; CHECK-BE-NEXT:    .cfi_offset 16, -20
65 ; CHECK-BE-NEXT:    move $16, $7
66 ; CHECK-BE-NEXT:    move $17, $6
67 ; CHECK-BE-NEXT:    move $18, $5
68 ; CHECK-BE-NEXT:    move $19, $4
69 ; CHECK-BE-NEXT:    lw $1, 56($sp)
70 ; CHECK-BE-NEXT:    andi $4, $1, 31
71 ; CHECK-BE-NEXT:    lw $5, 60($sp)
72 ; CHECK-BE-NEXT:    addiu $6, $zero, 0
73 ; CHECK-BE-NEXT:    jal __umoddi3
74 ; CHECK-BE-NEXT:    addiu $7, $zero, 37
75 ; CHECK-BE-NEXT:    not $1, $3
76 ; CHECK-BE-NEXT:    srl $2, $3, 5
77 ; CHECK-BE-NEXT:    andi $4, $2, 1
78 ; CHECK-BE-NEXT:    movn $19, $18, $4
79 ; CHECK-BE-NEXT:    andi $3, $3, 31
80 ; CHECK-BE-NEXT:    sllv $2, $19, $3
81 ; CHECK-BE-NEXT:    andi $1, $1, 31
82 ; CHECK-BE-NEXT:    srl $5, $16, 5
83 ; CHECK-BE-NEXT:    sll $6, $17, 27
84 ; CHECK-BE-NEXT:    or $5, $6, $5
85 ; CHECK-BE-NEXT:    movn $18, $5, $4
86 ; CHECK-BE-NEXT:    srl $6, $18, 1
87 ; CHECK-BE-NEXT:    srlv $6, $6, $1
88 ; CHECK-BE-NEXT:    or $2, $2, $6
89 ; CHECK-BE-NEXT:    sllv $3, $18, $3
90 ; CHECK-BE-NEXT:    sll $6, $16, 27
91 ; CHECK-BE-NEXT:    movn $5, $6, $4
92 ; CHECK-BE-NEXT:    srl $4, $5, 1
93 ; CHECK-BE-NEXT:    srlv $1, $4, $1
94 ; CHECK-BE-NEXT:    or $3, $3, $1
95 ; CHECK-BE-NEXT:    lw $16, 20($sp) # 4-byte Folded Reload
96 ; CHECK-BE-NEXT:    lw $17, 24($sp) # 4-byte Folded Reload
97 ; CHECK-BE-NEXT:    lw $18, 28($sp) # 4-byte Folded Reload
98 ; CHECK-BE-NEXT:    lw $19, 32($sp) # 4-byte Folded Reload
99 ; CHECK-BE-NEXT:    lw $ra, 36($sp) # 4-byte Folded Reload
100 ; CHECK-BE-NEXT:    jr $ra
101 ; CHECK-BE-NEXT:    addiu $sp, $sp, 40
103 ; CHECK-LE-LABEL: fshl_i37:
104 ; CHECK-LE:       # %bb.0:
105 ; CHECK-LE-NEXT:    addiu $sp, $sp, -40
106 ; CHECK-LE-NEXT:    .cfi_def_cfa_offset 40
107 ; CHECK-LE-NEXT:    sw $ra, 36($sp) # 4-byte Folded Spill
108 ; CHECK-LE-NEXT:    sw $19, 32($sp) # 4-byte Folded Spill
109 ; CHECK-LE-NEXT:    sw $18, 28($sp) # 4-byte Folded Spill
110 ; CHECK-LE-NEXT:    sw $17, 24($sp) # 4-byte Folded Spill
111 ; CHECK-LE-NEXT:    sw $16, 20($sp) # 4-byte Folded Spill
112 ; CHECK-LE-NEXT:    .cfi_offset 31, -4
113 ; CHECK-LE-NEXT:    .cfi_offset 19, -8
114 ; CHECK-LE-NEXT:    .cfi_offset 18, -12
115 ; CHECK-LE-NEXT:    .cfi_offset 17, -16
116 ; CHECK-LE-NEXT:    .cfi_offset 16, -20
117 ; CHECK-LE-NEXT:    move $16, $7
118 ; CHECK-LE-NEXT:    move $17, $6
119 ; CHECK-LE-NEXT:    move $18, $5
120 ; CHECK-LE-NEXT:    move $19, $4
121 ; CHECK-LE-NEXT:    lw $1, 60($sp)
122 ; CHECK-LE-NEXT:    andi $5, $1, 31
123 ; CHECK-LE-NEXT:    lw $4, 56($sp)
124 ; CHECK-LE-NEXT:    addiu $6, $zero, 37
125 ; CHECK-LE-NEXT:    jal __umoddi3
126 ; CHECK-LE-NEXT:    addiu $7, $zero, 0
127 ; CHECK-LE-NEXT:    srl $1, $2, 5
128 ; CHECK-LE-NEXT:    andi $1, $1, 1
129 ; CHECK-LE-NEXT:    srl $3, $17, 5
130 ; CHECK-LE-NEXT:    sll $4, $16, 27
131 ; CHECK-LE-NEXT:    or $3, $4, $3
132 ; CHECK-LE-NEXT:    move $4, $19
133 ; CHECK-LE-NEXT:    movn $4, $3, $1
134 ; CHECK-LE-NEXT:    andi $5, $2, 31
135 ; CHECK-LE-NEXT:    sllv $6, $4, $5
136 ; CHECK-LE-NEXT:    not $2, $2
137 ; CHECK-LE-NEXT:    andi $7, $2, 31
138 ; CHECK-LE-NEXT:    sll $2, $17, 27
139 ; CHECK-LE-NEXT:    movn $3, $2, $1
140 ; CHECK-LE-NEXT:    srl $2, $3, 1
141 ; CHECK-LE-NEXT:    srlv $2, $2, $7
142 ; CHECK-LE-NEXT:    or $2, $6, $2
143 ; CHECK-LE-NEXT:    movn $18, $19, $1
144 ; CHECK-LE-NEXT:    sllv $1, $18, $5
145 ; CHECK-LE-NEXT:    srl $3, $4, 1
146 ; CHECK-LE-NEXT:    srlv $3, $3, $7
147 ; CHECK-LE-NEXT:    or $3, $1, $3
148 ; CHECK-LE-NEXT:    lw $16, 20($sp) # 4-byte Folded Reload
149 ; CHECK-LE-NEXT:    lw $17, 24($sp) # 4-byte Folded Reload
150 ; CHECK-LE-NEXT:    lw $18, 28($sp) # 4-byte Folded Reload
151 ; CHECK-LE-NEXT:    lw $19, 32($sp) # 4-byte Folded Reload
152 ; CHECK-LE-NEXT:    lw $ra, 36($sp) # 4-byte Folded Reload
153 ; CHECK-LE-NEXT:    jr $ra
154 ; CHECK-LE-NEXT:    addiu $sp, $sp, 40
155   %f = call i37 @llvm.fshl.i37(i37 %x, i37 %y, i37 %z)
156   ret i37 %f
159 ; extract(concat(0b1110000, 0b1111111) << 2) = 0b1000011
161 declare i7 @llvm.fshl.i7(i7, i7, i7)
162 define i7 @fshl_i7_const_fold() {
163 ; CHECK-LABEL: fshl_i7_const_fold:
164 ; CHECK:       # %bb.0:
165 ; CHECK-NEXT:    jr $ra
166 ; CHECK-NEXT:    addiu $2, $zero, 67
167   %f = call i7 @llvm.fshl.i7(i7 112, i7 127, i7 2)
168   ret i7 %f
171 define i8 @fshl_i8_const_fold_overshift_1() {
172 ; CHECK-LABEL: fshl_i8_const_fold_overshift_1:
173 ; CHECK:       # %bb.0:
174 ; CHECK-NEXT:    jr $ra
175 ; CHECK-NEXT:    addiu $2, $zero, 128
176   %f = call i8 @llvm.fshl.i8(i8 255, i8 0, i8 15)
177   ret i8 %f
180 define i8 @fshl_i8_const_fold_overshift_2() {
181 ; CHECK-LABEL: fshl_i8_const_fold_overshift_2:
182 ; CHECK:       # %bb.0:
183 ; CHECK-NEXT:    jr $ra
184 ; CHECK-NEXT:    addiu $2, $zero, 120
185   %f = call i8 @llvm.fshl.i8(i8 15, i8 15, i8 11)
186   ret i8 %f
189 define i8 @fshl_i8_const_fold_overshift_3() {
190 ; CHECK-LABEL: fshl_i8_const_fold_overshift_3:
191 ; CHECK:       # %bb.0:
192 ; CHECK-NEXT:    jr $ra
193 ; CHECK-NEXT:    addiu $2, $zero, 0
194   %f = call i8 @llvm.fshl.i8(i8 0, i8 225, i8 8)
195   ret i8 %f
198 ; With constant shift amount, this is 'extr'.
200 define i32 @fshl_i32_const_shift(i32 %x, i32 %y) {
201 ; CHECK-LABEL: fshl_i32_const_shift:
202 ; CHECK:       # %bb.0:
203 ; CHECK-NEXT:    srl $1, $5, 23
204 ; CHECK-NEXT:    sll $2, $4, 9
205 ; CHECK-NEXT:    jr $ra
206 ; CHECK-NEXT:    or $2, $2, $1
207   %f = call i32 @llvm.fshl.i32(i32 %x, i32 %y, i32 9)
208   ret i32 %f
211 ; Check modulo math on shift amount.
213 define i32 @fshl_i32_const_overshift(i32 %x, i32 %y) {
214 ; CHECK-LABEL: fshl_i32_const_overshift:
215 ; CHECK:       # %bb.0:
216 ; CHECK-NEXT:    srl $1, $5, 23
217 ; CHECK-NEXT:    sll $2, $4, 9
218 ; CHECK-NEXT:    jr $ra
219 ; CHECK-NEXT:    or $2, $2, $1
220   %f = call i32 @llvm.fshl.i32(i32 %x, i32 %y, i32 41)
221   ret i32 %f
224 ; 64-bit should also work.
226 define i64 @fshl_i64_const_overshift(i64 %x, i64 %y) {
227 ; CHECK-BE-LABEL: fshl_i64_const_overshift:
228 ; CHECK-BE:       # %bb.0:
229 ; CHECK-BE-NEXT:    srl $1, $6, 23
230 ; CHECK-BE-NEXT:    sll $2, $5, 9
231 ; CHECK-BE-NEXT:    or $2, $2, $1
232 ; CHECK-BE-NEXT:    srl $1, $7, 23
233 ; CHECK-BE-NEXT:    sll $3, $6, 9
234 ; CHECK-BE-NEXT:    jr $ra
235 ; CHECK-BE-NEXT:    or $3, $3, $1
237 ; CHECK-LE-LABEL: fshl_i64_const_overshift:
238 ; CHECK-LE:       # %bb.0:
239 ; CHECK-LE-NEXT:    srl $1, $6, 23
240 ; CHECK-LE-NEXT:    sll $2, $7, 9
241 ; CHECK-LE-NEXT:    or $2, $2, $1
242 ; CHECK-LE-NEXT:    srl $1, $7, 23
243 ; CHECK-LE-NEXT:    sll $3, $4, 9
244 ; CHECK-LE-NEXT:    jr $ra
245 ; CHECK-LE-NEXT:    or $3, $3, $1
246   %f = call i64 @llvm.fshl.i64(i64 %x, i64 %y, i64 105)
247   ret i64 %f
250 ; This should work without any node-specific logic.
252 define i8 @fshl_i8_const_fold() {
253 ; CHECK-LABEL: fshl_i8_const_fold:
254 ; CHECK:       # %bb.0:
255 ; CHECK-NEXT:    jr $ra
256 ; CHECK-NEXT:    addiu $2, $zero, 128
257   %f = call i8 @llvm.fshl.i8(i8 255, i8 0, i8 7)
258   ret i8 %f
261 ; Repeat everything for funnel shift right.
263 ; General case - all operands can be variables.
265 define i16 @fshr_i16(i16 %x, i16 %y, i16 %z) {
266 ; CHECK-LABEL: fshr_i16:
267 ; CHECK:       # %bb.0:
268 ; CHECK-NEXT:    andi $1, $5, 65535
269 ; CHECK-NEXT:    sll $2, $4, 16
270 ; CHECK-NEXT:    or $1, $2, $1
271 ; CHECK-NEXT:    andi $2, $6, 15
272 ; CHECK-NEXT:    jr $ra
273 ; CHECK-NEXT:    srlv $2, $1, $2
274   %f = call i16 @llvm.fshr.i16(i16 %x, i16 %y, i16 %z)
275   ret i16 %f
278 define i32 @fshr_i32(i32 %x, i32 %y, i32 %z) {
279 ; CHECK-LABEL: fshr_i32:
280 ; CHECK:       # %bb.0:
281 ; CHECK-NEXT:    andi $1, $6, 31
282 ; CHECK-NEXT:    srlv $1, $5, $1
283 ; CHECK-NEXT:    sll $2, $4, 1
284 ; CHECK-NEXT:    not $3, $6
285 ; CHECK-NEXT:    andi $3, $3, 31
286 ; CHECK-NEXT:    sllv $2, $2, $3
287 ; CHECK-NEXT:    jr $ra
288 ; CHECK-NEXT:    or $2, $2, $1
289   %f = call i32 @llvm.fshr.i32(i32 %x, i32 %y, i32 %z)
290   ret i32 %f
293 ; Verify that weird types are minimally supported.
294 declare i37 @llvm.fshr.i37(i37, i37, i37)
295 define i37 @fshr_i37(i37 %x, i37 %y, i37 %z) {
296 ; CHECK-BE-LABEL: fshr_i37:
297 ; CHECK-BE:       # %bb.0:
298 ; CHECK-BE-NEXT:    addiu $sp, $sp, -40
299 ; CHECK-BE-NEXT:    .cfi_def_cfa_offset 40
300 ; CHECK-BE-NEXT:    sw $ra, 36($sp) # 4-byte Folded Spill
301 ; CHECK-BE-NEXT:    sw $19, 32($sp) # 4-byte Folded Spill
302 ; CHECK-BE-NEXT:    sw $18, 28($sp) # 4-byte Folded Spill
303 ; CHECK-BE-NEXT:    sw $17, 24($sp) # 4-byte Folded Spill
304 ; CHECK-BE-NEXT:    sw $16, 20($sp) # 4-byte Folded Spill
305 ; CHECK-BE-NEXT:    .cfi_offset 31, -4
306 ; CHECK-BE-NEXT:    .cfi_offset 19, -8
307 ; CHECK-BE-NEXT:    .cfi_offset 18, -12
308 ; CHECK-BE-NEXT:    .cfi_offset 17, -16
309 ; CHECK-BE-NEXT:    .cfi_offset 16, -20
310 ; CHECK-BE-NEXT:    move $16, $7
311 ; CHECK-BE-NEXT:    move $17, $6
312 ; CHECK-BE-NEXT:    move $18, $5
313 ; CHECK-BE-NEXT:    move $19, $4
314 ; CHECK-BE-NEXT:    lw $1, 56($sp)
315 ; CHECK-BE-NEXT:    andi $4, $1, 31
316 ; CHECK-BE-NEXT:    lw $5, 60($sp)
317 ; CHECK-BE-NEXT:    addiu $6, $zero, 0
318 ; CHECK-BE-NEXT:    jal __umoddi3
319 ; CHECK-BE-NEXT:    addiu $7, $zero, 37
320 ; CHECK-BE-NEXT:    addiu $1, $3, 27
321 ; CHECK-BE-NEXT:    andi $3, $1, 32
322 ; CHECK-BE-NEXT:    srl $2, $16, 5
323 ; CHECK-BE-NEXT:    sll $4, $17, 27
324 ; CHECK-BE-NEXT:    or $4, $4, $2
325 ; CHECK-BE-NEXT:    movz $19, $18, $3
326 ; CHECK-BE-NEXT:    movz $18, $4, $3
327 ; CHECK-BE-NEXT:    andi $5, $1, 31
328 ; CHECK-BE-NEXT:    srlv $2, $18, $5
329 ; CHECK-BE-NEXT:    not $1, $1
330 ; CHECK-BE-NEXT:    andi $1, $1, 31
331 ; CHECK-BE-NEXT:    sll $6, $19, 1
332 ; CHECK-BE-NEXT:    sllv $6, $6, $1
333 ; CHECK-BE-NEXT:    sll $7, $16, 27
334 ; CHECK-BE-NEXT:    or $2, $6, $2
335 ; CHECK-BE-NEXT:    movz $4, $7, $3
336 ; CHECK-BE-NEXT:    srlv $3, $4, $5
337 ; CHECK-BE-NEXT:    sll $4, $18, 1
338 ; CHECK-BE-NEXT:    sllv $1, $4, $1
339 ; CHECK-BE-NEXT:    or $3, $1, $3
340 ; CHECK-BE-NEXT:    lw $16, 20($sp) # 4-byte Folded Reload
341 ; CHECK-BE-NEXT:    lw $17, 24($sp) # 4-byte Folded Reload
342 ; CHECK-BE-NEXT:    lw $18, 28($sp) # 4-byte Folded Reload
343 ; CHECK-BE-NEXT:    lw $19, 32($sp) # 4-byte Folded Reload
344 ; CHECK-BE-NEXT:    lw $ra, 36($sp) # 4-byte Folded Reload
345 ; CHECK-BE-NEXT:    jr $ra
346 ; CHECK-BE-NEXT:    addiu $sp, $sp, 40
348 ; CHECK-LE-LABEL: fshr_i37:
349 ; CHECK-LE:       # %bb.0:
350 ; CHECK-LE-NEXT:    addiu $sp, $sp, -40
351 ; CHECK-LE-NEXT:    .cfi_def_cfa_offset 40
352 ; CHECK-LE-NEXT:    sw $ra, 36($sp) # 4-byte Folded Spill
353 ; CHECK-LE-NEXT:    sw $19, 32($sp) # 4-byte Folded Spill
354 ; CHECK-LE-NEXT:    sw $18, 28($sp) # 4-byte Folded Spill
355 ; CHECK-LE-NEXT:    sw $17, 24($sp) # 4-byte Folded Spill
356 ; CHECK-LE-NEXT:    sw $16, 20($sp) # 4-byte Folded Spill
357 ; CHECK-LE-NEXT:    .cfi_offset 31, -4
358 ; CHECK-LE-NEXT:    .cfi_offset 19, -8
359 ; CHECK-LE-NEXT:    .cfi_offset 18, -12
360 ; CHECK-LE-NEXT:    .cfi_offset 17, -16
361 ; CHECK-LE-NEXT:    .cfi_offset 16, -20
362 ; CHECK-LE-NEXT:    move $16, $7
363 ; CHECK-LE-NEXT:    move $17, $6
364 ; CHECK-LE-NEXT:    move $18, $5
365 ; CHECK-LE-NEXT:    move $19, $4
366 ; CHECK-LE-NEXT:    lw $1, 60($sp)
367 ; CHECK-LE-NEXT:    andi $5, $1, 31
368 ; CHECK-LE-NEXT:    lw $4, 56($sp)
369 ; CHECK-LE-NEXT:    addiu $6, $zero, 37
370 ; CHECK-LE-NEXT:    jal __umoddi3
371 ; CHECK-LE-NEXT:    addiu $7, $zero, 0
372 ; CHECK-LE-NEXT:    addiu $1, $2, 27
373 ; CHECK-LE-NEXT:    andi $3, $1, 32
374 ; CHECK-LE-NEXT:    srl $2, $17, 5
375 ; CHECK-LE-NEXT:    sll $4, $16, 27
376 ; CHECK-LE-NEXT:    or $2, $4, $2
377 ; CHECK-LE-NEXT:    sll $4, $17, 27
378 ; CHECK-LE-NEXT:    move $5, $19
379 ; CHECK-LE-NEXT:    movz $5, $2, $3
380 ; CHECK-LE-NEXT:    movz $2, $4, $3
381 ; CHECK-LE-NEXT:    andi $4, $1, 31
382 ; CHECK-LE-NEXT:    srlv $2, $2, $4
383 ; CHECK-LE-NEXT:    not $1, $1
384 ; CHECK-LE-NEXT:    andi $1, $1, 31
385 ; CHECK-LE-NEXT:    sll $6, $5, 1
386 ; CHECK-LE-NEXT:    sllv $6, $6, $1
387 ; CHECK-LE-NEXT:    or $2, $6, $2
388 ; CHECK-LE-NEXT:    srlv $4, $5, $4
389 ; CHECK-LE-NEXT:    movz $18, $19, $3
390 ; CHECK-LE-NEXT:    sll $3, $18, 1
391 ; CHECK-LE-NEXT:    sllv $1, $3, $1
392 ; CHECK-LE-NEXT:    or $3, $1, $4
393 ; CHECK-LE-NEXT:    lw $16, 20($sp) # 4-byte Folded Reload
394 ; CHECK-LE-NEXT:    lw $17, 24($sp) # 4-byte Folded Reload
395 ; CHECK-LE-NEXT:    lw $18, 28($sp) # 4-byte Folded Reload
396 ; CHECK-LE-NEXT:    lw $19, 32($sp) # 4-byte Folded Reload
397 ; CHECK-LE-NEXT:    lw $ra, 36($sp) # 4-byte Folded Reload
398 ; CHECK-LE-NEXT:    jr $ra
399 ; CHECK-LE-NEXT:    addiu $sp, $sp, 40
400   %f = call i37 @llvm.fshr.i37(i37 %x, i37 %y, i37 %z)
401   ret i37 %f
404 ; extract(concat(0b1110000, 0b1111111) >> 2) = 0b0011111
406 declare i7 @llvm.fshr.i7(i7, i7, i7)
407 define i7 @fshr_i7_const_fold() {
408 ; CHECK-LABEL: fshr_i7_const_fold:
409 ; CHECK:       # %bb.0:
410 ; CHECK-NEXT:    jr $ra
411 ; CHECK-NEXT:    addiu $2, $zero, 31
412   %f = call i7 @llvm.fshr.i7(i7 112, i7 127, i7 2)
413   ret i7 %f
416 define i8 @fshr_i8_const_fold_overshift_1() {
417 ; CHECK-LABEL: fshr_i8_const_fold_overshift_1:
418 ; CHECK:       # %bb.0:
419 ; CHECK-NEXT:    jr $ra
420 ; CHECK-NEXT:    addiu $2, $zero, 254
421   %f = call i8 @llvm.fshr.i8(i8 255, i8 0, i8 15)
422   ret i8 %f
425 define i8 @fshr_i8_const_fold_overshift_2() {
426 ; CHECK-LABEL: fshr_i8_const_fold_overshift_2:
427 ; CHECK:       # %bb.0:
428 ; CHECK-NEXT:    jr $ra
429 ; CHECK-NEXT:    addiu $2, $zero, 225
430   %f = call i8 @llvm.fshr.i8(i8 15, i8 15, i8 11)
431   ret i8 %f
434 define i8 @fshr_i8_const_fold_overshift_3() {
435 ; CHECK-LABEL: fshr_i8_const_fold_overshift_3:
436 ; CHECK:       # %bb.0:
437 ; CHECK-NEXT:    jr $ra
438 ; CHECK-NEXT:    addiu $2, $zero, 255
439   %f = call i8 @llvm.fshr.i8(i8 0, i8 255, i8 8)
440   ret i8 %f
443 ; With constant shift amount, this is 'extr'.
445 define i32 @fshr_i32_const_shift(i32 %x, i32 %y) {
446 ; CHECK-LABEL: fshr_i32_const_shift:
447 ; CHECK:       # %bb.0:
448 ; CHECK-NEXT:    srl $1, $5, 9
449 ; CHECK-NEXT:    sll $2, $4, 23
450 ; CHECK-NEXT:    jr $ra
451 ; CHECK-NEXT:    or $2, $2, $1
452   %f = call i32 @llvm.fshr.i32(i32 %x, i32 %y, i32 9)
453   ret i32 %f
456 ; Check modulo math on shift amount. 41-32=9.
458 define i32 @fshr_i32_const_overshift(i32 %x, i32 %y) {
459 ; CHECK-LABEL: fshr_i32_const_overshift:
460 ; CHECK:       # %bb.0:
461 ; CHECK-NEXT:    srl $1, $5, 9
462 ; CHECK-NEXT:    sll $2, $4, 23
463 ; CHECK-NEXT:    jr $ra
464 ; CHECK-NEXT:    or $2, $2, $1
465   %f = call i32 @llvm.fshr.i32(i32 %x, i32 %y, i32 41)
466   ret i32 %f
469 ; 64-bit should also work. 105-64 = 41.
471 define i64 @fshr_i64_const_overshift(i64 %x, i64 %y) {
472 ; CHECK-BE-LABEL: fshr_i64_const_overshift:
473 ; CHECK-BE:       # %bb.0:
474 ; CHECK-BE-NEXT:    srl $1, $5, 9
475 ; CHECK-BE-NEXT:    sll $2, $4, 23
476 ; CHECK-BE-NEXT:    or $2, $2, $1
477 ; CHECK-BE-NEXT:    srl $1, $6, 9
478 ; CHECK-BE-NEXT:    sll $3, $5, 23
479 ; CHECK-BE-NEXT:    jr $ra
480 ; CHECK-BE-NEXT:    or $3, $3, $1
482 ; CHECK-LE-LABEL: fshr_i64_const_overshift:
483 ; CHECK-LE:       # %bb.0:
484 ; CHECK-LE-NEXT:    srl $1, $7, 9
485 ; CHECK-LE-NEXT:    sll $2, $4, 23
486 ; CHECK-LE-NEXT:    or $2, $2, $1
487 ; CHECK-LE-NEXT:    srl $1, $4, 9
488 ; CHECK-LE-NEXT:    sll $3, $5, 23
489 ; CHECK-LE-NEXT:    jr $ra
490 ; CHECK-LE-NEXT:    or $3, $3, $1
491   %f = call i64 @llvm.fshr.i64(i64 %x, i64 %y, i64 105)
492   ret i64 %f
495 ; This should work without any node-specific logic.
497 define i8 @fshr_i8_const_fold() {
498 ; CHECK-LABEL: fshr_i8_const_fold:
499 ; CHECK:       # %bb.0:
500 ; CHECK-NEXT:    jr $ra
501 ; CHECK-NEXT:    addiu $2, $zero, 254
502   %f = call i8 @llvm.fshr.i8(i8 255, i8 0, i8 7)
503   ret i8 %f
506 define i32 @fshl_i32_shift_by_bitwidth(i32 %x, i32 %y) {
507 ; CHECK-LABEL: fshl_i32_shift_by_bitwidth:
508 ; CHECK:       # %bb.0:
509 ; CHECK-NEXT:    jr $ra
510 ; CHECK-NEXT:    move $2, $4
511   %f = call i32 @llvm.fshl.i32(i32 %x, i32 %y, i32 32)
512   ret i32 %f
515 define i32 @fshr_i32_shift_by_bitwidth(i32 %x, i32 %y) {
516 ; CHECK-LABEL: fshr_i32_shift_by_bitwidth:
517 ; CHECK:       # %bb.0:
518 ; CHECK-NEXT:    jr $ra
519 ; CHECK-NEXT:    move $2, $5
520   %f = call i32 @llvm.fshr.i32(i32 %x, i32 %y, i32 32)
521   ret i32 %f
524 define <4 x i32> @fshl_v4i32_shift_by_bitwidth(<4 x i32> %x, <4 x i32> %y) {
525 ; CHECK-LABEL: fshl_v4i32_shift_by_bitwidth:
526 ; CHECK:       # %bb.0:
527 ; CHECK-NEXT:    move $2, $4
528 ; CHECK-NEXT:    move $3, $5
529 ; CHECK-NEXT:    move $4, $6
530 ; CHECK-NEXT:    jr $ra
531 ; CHECK-NEXT:    move $5, $7
532   %f = call <4 x i32> @llvm.fshl.v4i32(<4 x i32> %x, <4 x i32> %y, <4 x i32> <i32 32, i32 32, i32 32, i32 32>)
533   ret <4 x i32> %f
536 define <4 x i32> @fshr_v4i32_shift_by_bitwidth(<4 x i32> %x, <4 x i32> %y) {
537 ; CHECK-LABEL: fshr_v4i32_shift_by_bitwidth:
538 ; CHECK:       # %bb.0:
539 ; CHECK-NEXT:    lw $5, 28($sp)
540 ; CHECK-NEXT:    lw $4, 24($sp)
541 ; CHECK-NEXT:    lw $3, 20($sp)
542 ; CHECK-NEXT:    lw $2, 16($sp)
543 ; CHECK-NEXT:    jr $ra
544 ; CHECK-NEXT:    nop
545   %f = call <4 x i32> @llvm.fshr.v4i32(<4 x i32> %x, <4 x i32> %y, <4 x i32> <i32 32, i32 32, i32 32, i32 32>)
546   ret <4 x i32> %f