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; When first 2 operands match, it's a rotate.
18
19define i8 @rotl_i8_const_shift(i8 %x) {
20; CHECK-LABEL: rotl_i8_const_shift:
21; CHECK:       # %bb.0:
22; CHECK-NEXT:    sll $1, $4, 3
23; CHECK-NEXT:    andi $2, $4, 224
24; CHECK-NEXT:    srl $2, $2, 5
25; CHECK-NEXT:    jr $ra
26; CHECK-NEXT:    or $2, $1, $2
27  %f = call i8 @llvm.fshl.i8(i8 %x, i8 %x, i8 3)
28  ret i8 %f
29}
30
31define i64 @rotl_i64_const_shift(i64 %x) {
32; CHECK-LABEL: rotl_i64_const_shift:
33; CHECK:       # %bb.0:
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
39; CHECK-NEXT:    jr $ra
40; CHECK-NEXT:    or $3, $3, $1
41  %f = call i64 @llvm.fshl.i64(i64 %x, i64 %x, i64 3)
42  ret i64 %f
43}
44
45; When first 2 operands match, it's a rotate (by variable amount).
46
47define i16 @rotl_i16(i16 %x, i16 %z) {
48; CHECK-LABEL: rotl_i16:
49; CHECK:       # %bb.0:
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
56; CHECK-NEXT:    jr $ra
57; CHECK-NEXT:    or $2, $1, $2
58  %f = call i16 @llvm.fshl.i16(i16 %x, i16 %x, i16 %z)
59  ret i16 %f
60}
61
62define i32 @rotl_i32(i32 %x, i32 %z) {
63; CHECK-LABEL: rotl_i32:
64; CHECK:       # %bb.0:
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
70; CHECK-NEXT:    jr $ra
71; CHECK-NEXT:    or $2, $1, $2
72  %f = call i32 @llvm.fshl.i32(i32 %x, i32 %x, i32 %z)
73  ret i32 %f
74}
75
76define i64 @rotl_i64(i64 %x, i64 %z) {
77; CHECK-BE-LABEL: rotl_i64:
78; CHECK-BE:       # %bb.0:
79; CHECK-BE-NEXT:    srl $1, $7, 5
80; CHECK-BE-NEXT:    andi $1, $1, 1
81; CHECK-BE-NEXT:    move $3, $4
82; CHECK-BE-NEXT:    movn $3, $5, $1
83; CHECK-BE-NEXT:    andi $6, $7, 31
84; CHECK-BE-NEXT:    sllv $2, $3, $6
85; CHECK-BE-NEXT:    movn $5, $4, $1
86; CHECK-BE-NEXT:    srl $1, $5, 1
87; CHECK-BE-NEXT:    not $4, $7
88; CHECK-BE-NEXT:    andi $4, $4, 31
89; CHECK-BE-NEXT:    srlv $1, $1, $4
90; CHECK-BE-NEXT:    or $2, $2, $1
91; CHECK-BE-NEXT:    sllv $1, $5, $6
92; CHECK-BE-NEXT:    srl $3, $3, 1
93; CHECK-BE-NEXT:    srlv $3, $3, $4
94; CHECK-BE-NEXT:    jr $ra
95; CHECK-BE-NEXT:    or $3, $1, $3
96;
97; CHECK-LE-LABEL: rotl_i64:
98; CHECK-LE:       # %bb.0:
99; CHECK-LE-NEXT:    srl $1, $6, 5
100; CHECK-LE-NEXT:    andi $1, $1, 1
101; CHECK-LE-NEXT:    move $3, $4
102; CHECK-LE-NEXT:    movn $3, $5, $1
103; CHECK-LE-NEXT:    andi $7, $6, 31
104; CHECK-LE-NEXT:    sllv $2, $3, $7
105; CHECK-LE-NEXT:    movn $5, $4, $1
106; CHECK-LE-NEXT:    srl $1, $5, 1
107; CHECK-LE-NEXT:    not $4, $6
108; CHECK-LE-NEXT:    andi $4, $4, 31
109; CHECK-LE-NEXT:    srlv $1, $1, $4
110; CHECK-LE-NEXT:    or $2, $2, $1
111; CHECK-LE-NEXT:    sllv $1, $5, $7
112; CHECK-LE-NEXT:    srl $3, $3, 1
113; CHECK-LE-NEXT:    srlv $3, $3, $4
114; CHECK-LE-NEXT:    jr $ra
115; CHECK-LE-NEXT:    or $3, $1, $3
116  %f = call i64 @llvm.fshl.i64(i64 %x, i64 %x, i64 %z)
117  ret i64 %f
118}
119
120; Vector rotate.
121
122define <4 x i32> @rotl_v4i32(<4 x i32> %x, <4 x i32> %z) {
123; CHECK-LABEL: rotl_v4i32:
124; CHECK:       # %bb.0:
125; CHECK-NEXT:    lw $1, 24($sp)
126; CHECK-NEXT:    negu $2, $1
127; CHECK-NEXT:    lw $3, 20($sp)
128; CHECK-NEXT:    negu $8, $3
129; CHECK-NEXT:    andi $8, $8, 31
130; CHECK-NEXT:    andi $2, $2, 31
131; CHECK-NEXT:    andi $3, $3, 31
132; CHECK-NEXT:    andi $1, $1, 31
133; CHECK-NEXT:    lw $9, 16($sp)
134; CHECK-NEXT:    sllv $1, $6, $1
135; CHECK-NEXT:    srlv $6, $6, $2
136; CHECK-NEXT:    sllv $3, $5, $3
137; CHECK-NEXT:    srlv $5, $5, $8
138; CHECK-NEXT:    andi $2, $9, 31
139; CHECK-NEXT:    sllv $2, $4, $2
140; CHECK-NEXT:    negu $8, $9
141; CHECK-NEXT:    andi $8, $8, 31
142; CHECK-NEXT:    srlv $4, $4, $8
143; CHECK-NEXT:    lw $8, 28($sp)
144; CHECK-NEXT:    or $2, $2, $4
145; CHECK-NEXT:    or $3, $3, $5
146; CHECK-NEXT:    or $4, $1, $6
147; CHECK-NEXT:    andi $1, $8, 31
148; CHECK-NEXT:    sllv $1, $7, $1
149; CHECK-NEXT:    negu $5, $8
150; CHECK-NEXT:    andi $5, $5, 31
151; CHECK-NEXT:    srlv $5, $7, $5
152; CHECK-NEXT:    jr $ra
153; CHECK-NEXT:    or $5, $1, $5
154  %f = call <4 x i32> @llvm.fshl.v4i32(<4 x i32> %x, <4 x i32> %x, <4 x i32> %z)
155  ret <4 x i32> %f
156}
157
158; Vector rotate by constant splat amount.
159
160define <4 x i32> @rotl_v4i32_rotl_const_shift(<4 x i32> %x) {
161; CHECK-LABEL: rotl_v4i32_rotl_const_shift:
162; CHECK:       # %bb.0:
163; CHECK-NEXT:    srl $1, $5, 29
164; CHECK-NEXT:    sll $3, $5, 3
165; CHECK-NEXT:    srl $2, $4, 29
166; CHECK-NEXT:    sll $4, $4, 3
167; CHECK-NEXT:    or $2, $4, $2
168; CHECK-NEXT:    or $3, $3, $1
169; CHECK-NEXT:    srl $1, $6, 29
170; CHECK-NEXT:    sll $4, $6, 3
171; CHECK-NEXT:    or $4, $4, $1
172; CHECK-NEXT:    srl $1, $7, 29
173; CHECK-NEXT:    sll $5, $7, 3
174; CHECK-NEXT:    jr $ra
175; CHECK-NEXT:    or $5, $5, $1
176  %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>)
177  ret <4 x i32> %f
178}
179
180; Repeat everything for funnel shift right.
181
182; When first 2 operands match, it's a rotate.
183
184define i8 @rotr_i8_const_shift(i8 %x) {
185; CHECK-LABEL: rotr_i8_const_shift:
186; CHECK:       # %bb.0:
187; CHECK-NEXT:    sll $1, $4, 5
188; CHECK-NEXT:    andi $2, $4, 248
189; CHECK-NEXT:    srl $2, $2, 3
190; CHECK-NEXT:    jr $ra
191; CHECK-NEXT:    or $2, $2, $1
192  %f = call i8 @llvm.fshr.i8(i8 %x, i8 %x, i8 3)
193  ret i8 %f
194}
195
196define i32 @rotr_i32_const_shift(i32 %x) {
197; CHECK-LABEL: rotr_i32_const_shift:
198; CHECK:       # %bb.0:
199; CHECK-NEXT:    sll $1, $4, 29
200; CHECK-NEXT:    srl $2, $4, 3
201; CHECK-NEXT:    jr $ra
202; CHECK-NEXT:    or $2, $2, $1
203  %f = call i32 @llvm.fshr.i32(i32 %x, i32 %x, i32 3)
204  ret i32 %f
205}
206
207; When first 2 operands match, it's a rotate (by variable amount).
208
209define i16 @rotr_i16(i16 %x, i16 %z) {
210; CHECK-LABEL: rotr_i16:
211; CHECK:       # %bb.0:
212; CHECK-NEXT:    andi $1, $5, 15
213; CHECK-NEXT:    andi $2, $4, 65535
214; CHECK-NEXT:    srlv $1, $2, $1
215; CHECK-NEXT:    negu $2, $5
216; CHECK-NEXT:    andi $2, $2, 15
217; CHECK-NEXT:    sllv $2, $4, $2
218; CHECK-NEXT:    jr $ra
219; CHECK-NEXT:    or $2, $1, $2
220  %f = call i16 @llvm.fshr.i16(i16 %x, i16 %x, i16 %z)
221  ret i16 %f
222}
223
224define i32 @rotr_i32(i32 %x, i32 %z) {
225; CHECK-LABEL: rotr_i32:
226; CHECK:       # %bb.0:
227; CHECK-NEXT:    andi $1, $5, 31
228; CHECK-NEXT:    srlv $1, $4, $1
229; CHECK-NEXT:    negu $2, $5
230; CHECK-NEXT:    andi $2, $2, 31
231; CHECK-NEXT:    sllv $2, $4, $2
232; CHECK-NEXT:    jr $ra
233; CHECK-NEXT:    or $2, $1, $2
234  %f = call i32 @llvm.fshr.i32(i32 %x, i32 %x, i32 %z)
235  ret i32 %f
236}
237
238define i64 @rotr_i64(i64 %x, i64 %z) {
239; CHECK-BE-LABEL: rotr_i64:
240; CHECK-BE:       # %bb.0:
241; CHECK-BE-NEXT:    andi $1, $7, 32
242; CHECK-BE-NEXT:    move $3, $5
243; CHECK-BE-NEXT:    movz $3, $4, $1
244; CHECK-BE-NEXT:    andi $6, $7, 31
245; CHECK-BE-NEXT:    srlv $2, $3, $6
246; CHECK-BE-NEXT:    movz $4, $5, $1
247; CHECK-BE-NEXT:    sll $1, $4, 1
248; CHECK-BE-NEXT:    not $5, $7
249; CHECK-BE-NEXT:    andi $5, $5, 31
250; CHECK-BE-NEXT:    sllv $1, $1, $5
251; CHECK-BE-NEXT:    or $2, $1, $2
252; CHECK-BE-NEXT:    srlv $1, $4, $6
253; CHECK-BE-NEXT:    sll $3, $3, 1
254; CHECK-BE-NEXT:    sllv $3, $3, $5
255; CHECK-BE-NEXT:    jr $ra
256; CHECK-BE-NEXT:    or $3, $3, $1
257;
258; CHECK-LE-LABEL: rotr_i64:
259; CHECK-LE:       # %bb.0:
260; CHECK-LE-NEXT:    andi $1, $6, 32
261; CHECK-LE-NEXT:    move $3, $5
262; CHECK-LE-NEXT:    movz $3, $4, $1
263; CHECK-LE-NEXT:    andi $7, $6, 31
264; CHECK-LE-NEXT:    srlv $2, $3, $7
265; CHECK-LE-NEXT:    movz $4, $5, $1
266; CHECK-LE-NEXT:    sll $1, $4, 1
267; CHECK-LE-NEXT:    not $5, $6
268; CHECK-LE-NEXT:    andi $5, $5, 31
269; CHECK-LE-NEXT:    sllv $1, $1, $5
270; CHECK-LE-NEXT:    or $2, $1, $2
271; CHECK-LE-NEXT:    srlv $1, $4, $7
272; CHECK-LE-NEXT:    sll $3, $3, 1
273; CHECK-LE-NEXT:    sllv $3, $3, $5
274; CHECK-LE-NEXT:    jr $ra
275; CHECK-LE-NEXT:    or $3, $3, $1
276  %f = call i64 @llvm.fshr.i64(i64 %x, i64 %x, i64 %z)
277  ret i64 %f
278}
279
280; Vector rotate.
281
282define <4 x i32> @rotr_v4i32(<4 x i32> %x, <4 x i32> %z) {
283; CHECK-LABEL: rotr_v4i32:
284; CHECK:       # %bb.0:
285; CHECK-NEXT:    lw $1, 24($sp)
286; CHECK-NEXT:    negu $2, $1
287; CHECK-NEXT:    lw $3, 20($sp)
288; CHECK-NEXT:    negu $8, $3
289; CHECK-NEXT:    andi $8, $8, 31
290; CHECK-NEXT:    andi $2, $2, 31
291; CHECK-NEXT:    andi $3, $3, 31
292; CHECK-NEXT:    andi $1, $1, 31
293; CHECK-NEXT:    lw $9, 16($sp)
294; CHECK-NEXT:    srlv $1, $6, $1
295; CHECK-NEXT:    sllv $6, $6, $2
296; CHECK-NEXT:    srlv $3, $5, $3
297; CHECK-NEXT:    sllv $5, $5, $8
298; CHECK-NEXT:    andi $2, $9, 31
299; CHECK-NEXT:    srlv $2, $4, $2
300; CHECK-NEXT:    negu $8, $9
301; CHECK-NEXT:    andi $8, $8, 31
302; CHECK-NEXT:    sllv $4, $4, $8
303; CHECK-NEXT:    lw $8, 28($sp)
304; CHECK-NEXT:    or $2, $2, $4
305; CHECK-NEXT:    or $3, $3, $5
306; CHECK-NEXT:    or $4, $1, $6
307; CHECK-NEXT:    andi $1, $8, 31
308; CHECK-NEXT:    srlv $1, $7, $1
309; CHECK-NEXT:    negu $5, $8
310; CHECK-NEXT:    andi $5, $5, 31
311; CHECK-NEXT:    sllv $5, $7, $5
312; CHECK-NEXT:    jr $ra
313; CHECK-NEXT:    or $5, $1, $5
314  %f = call <4 x i32> @llvm.fshr.v4i32(<4 x i32> %x, <4 x i32> %x, <4 x i32> %z)
315  ret <4 x i32> %f
316}
317
318; Vector rotate by constant splat amount.
319
320define <4 x i32> @rotr_v4i32_const_shift(<4 x i32> %x) {
321; CHECK-LABEL: rotr_v4i32_const_shift:
322; CHECK:       # %bb.0:
323; CHECK-NEXT:    sll $1, $5, 29
324; CHECK-NEXT:    srl $3, $5, 3
325; CHECK-NEXT:    sll $2, $4, 29
326; CHECK-NEXT:    srl $4, $4, 3
327; CHECK-NEXT:    or $2, $4, $2
328; CHECK-NEXT:    or $3, $3, $1
329; CHECK-NEXT:    sll $1, $6, 29
330; CHECK-NEXT:    srl $4, $6, 3
331; CHECK-NEXT:    or $4, $4, $1
332; CHECK-NEXT:    sll $1, $7, 29
333; CHECK-NEXT:    srl $5, $7, 3
334; CHECK-NEXT:    jr $ra
335; CHECK-NEXT:    or $5, $5, $1
336  %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>)
337  ret <4 x i32> %f
338}
339
340define i32 @rotl_i32_shift_by_bitwidth(i32 %x) {
341; CHECK-LABEL: rotl_i32_shift_by_bitwidth:
342; CHECK:       # %bb.0:
343; CHECK-NEXT:    jr $ra
344; CHECK-NEXT:    move $2, $4
345  %f = call i32 @llvm.fshl.i32(i32 %x, i32 %x, i32 32)
346  ret i32 %f
347}
348
349define i32 @rotr_i32_shift_by_bitwidth(i32 %x) {
350; CHECK-LABEL: rotr_i32_shift_by_bitwidth:
351; CHECK:       # %bb.0:
352; CHECK-NEXT:    jr $ra
353; CHECK-NEXT:    move $2, $4
354  %f = call i32 @llvm.fshr.i32(i32 %x, i32 %x, i32 32)
355  ret i32 %f
356}
357
358define <4 x i32> @rotl_v4i32_shift_by_bitwidth(<4 x i32> %x) {
359; CHECK-LABEL: rotl_v4i32_shift_by_bitwidth:
360; CHECK:       # %bb.0:
361; CHECK-NEXT:    move $2, $4
362; CHECK-NEXT:    move $3, $5
363; CHECK-NEXT:    move $4, $6
364; CHECK-NEXT:    jr $ra
365; CHECK-NEXT:    move $5, $7
366  %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>)
367  ret <4 x i32> %f
368}
369
370define <4 x i32> @rotr_v4i32_shift_by_bitwidth(<4 x i32> %x) {
371; CHECK-LABEL: rotr_v4i32_shift_by_bitwidth:
372; CHECK:       # %bb.0:
373; CHECK-NEXT:    move $2, $4
374; CHECK-NEXT:    move $3, $5
375; CHECK-NEXT:    move $4, $6
376; CHECK-NEXT:    jr $ra
377; CHECK-NEXT:    move $5, $7
378  %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>)
379  ret <4 x i32> %f
380}
381
382