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