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