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