1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc < %s -mtriple=powerpc64le-- | FileCheck %s
3
4declare i8 @llvm.fshl.i8(i8, i8, i8)
5declare i16 @llvm.fshl.i16(i16, i16, i16)
6declare i32 @llvm.fshl.i32(i32, i32, i32)
7declare i64 @llvm.fshl.i64(i64, i64, i64)
8declare <4 x i32> @llvm.fshl.v4i32(<4 x i32>, <4 x i32>, <4 x i32>)
9
10declare i8 @llvm.fshr.i8(i8, i8, i8)
11declare i16 @llvm.fshr.i16(i16, i16, i16)
12declare i32 @llvm.fshr.i32(i32, i32, i32)
13declare i64 @llvm.fshr.i64(i64, i64, i64)
14declare <4 x i32> @llvm.fshr.v4i32(<4 x i32>, <4 x i32>, <4 x i32>)
15
16; General case - all operands can be variables.
17
18define i32 @fshl_i32(i32 %x, i32 %y, i32 %z) {
19; CHECK-LABEL: fshl_i32:
20; CHECK:       # %bb.0:
21; CHECK-NEXT:    andi. 5, 5, 31
22; CHECK-NEXT:    subfic 6, 5, 32
23; CHECK-NEXT:    slw 5, 3, 5
24; CHECK-NEXT:    srw 4, 4, 6
25; CHECK-NEXT:    or 4, 5, 4
26; CHECK-NEXT:    iseleq 3, 3, 4
27; CHECK-NEXT:    blr
28  %f = call i32 @llvm.fshl.i32(i32 %x, i32 %y, i32 %z)
29  ret i32 %f
30}
31
32define i64 @fshl_i64(i64 %x, i64 %y, i64 %z) {
33; CHECK-LABEL: fshl_i64:
34; CHECK:       # %bb.0:
35; CHECK-NEXT:    andi. 5, 5, 63
36; CHECK-NEXT:    subfic 6, 5, 64
37; CHECK-NEXT:    sld 5, 3, 5
38; CHECK-NEXT:    srd 4, 4, 6
39; CHECK-NEXT:    or 4, 5, 4
40; CHECK-NEXT:    iseleq 3, 3, 4
41; CHECK-NEXT:    blr
42  %f = call i64 @llvm.fshl.i64(i64 %x, i64 %y, i64 %z)
43  ret i64 %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-LABEL: fshl_i37:
50; CHECK:       # %bb.0:
51; CHECK-NEXT:    lis 6, -8857
52; CHECK-NEXT:    clrldi 5, 5, 27
53; CHECK-NEXT:    ori 6, 6, 51366
54; CHECK-NEXT:    clrldi 4, 4, 27
55; CHECK-NEXT:    sldi 6, 6, 32
56; CHECK-NEXT:    oris 6, 6, 3542
57; CHECK-NEXT:    ori 6, 6, 31883
58; CHECK-NEXT:    mulhdu 6, 5, 6
59; CHECK-NEXT:    rldicl 6, 6, 59, 5
60; CHECK-NEXT:    mulli 6, 6, 37
61; CHECK-NEXT:    sub. 5, 5, 6
62; CHECK-NEXT:    subfic 6, 5, 37
63; CHECK-NEXT:    sld 5, 3, 5
64; CHECK-NEXT:    srd 4, 4, 6
65; CHECK-NEXT:    or 4, 5, 4
66; CHECK-NEXT:    iseleq 3, 3, 4
67; CHECK-NEXT:    blr
68  %f = call i37 @llvm.fshl.i37(i37 %x, i37 %y, i37 %z)
69  ret i37 %f
70}
71
72; extract(concat(0b1110000, 0b1111111) << 2) = 0b1000011
73
74declare i7 @llvm.fshl.i7(i7, i7, i7)
75define i7 @fshl_i7_const_fold() {
76; CHECK-LABEL: fshl_i7_const_fold:
77; CHECK:       # %bb.0:
78; CHECK-NEXT:    li 3, 67
79; CHECK-NEXT:    blr
80  %f = call i7 @llvm.fshl.i7(i7 112, i7 127, i7 2)
81  ret i7 %f
82}
83
84; With constant shift amount, this is rotate + insert (missing extended mnemonics).
85
86define i32 @fshl_i32_const_shift(i32 %x, i32 %y) {
87; CHECK-LABEL: fshl_i32_const_shift:
88; CHECK:       # %bb.0:
89; CHECK-NEXT:    rotlwi 4, 4, 9
90; CHECK-NEXT:    rlwimi 4, 3, 9, 0, 22
91; CHECK-NEXT:    mr 3, 4
92; CHECK-NEXT:    blr
93  %f = call i32 @llvm.fshl.i32(i32 %x, i32 %y, i32 9)
94  ret i32 %f
95}
96
97; Check modulo math on shift amount.
98
99define i32 @fshl_i32_const_overshift(i32 %x, i32 %y) {
100; CHECK-LABEL: fshl_i32_const_overshift:
101; CHECK:       # %bb.0:
102; CHECK-NEXT:    rotlwi 4, 4, 9
103; CHECK-NEXT:    rlwimi 4, 3, 9, 0, 22
104; CHECK-NEXT:    mr 3, 4
105; CHECK-NEXT:    blr
106  %f = call i32 @llvm.fshl.i32(i32 %x, i32 %y, i32 41)
107  ret i32 %f
108}
109
110; 64-bit should also work.
111
112define i64 @fshl_i64_const_overshift(i64 %x, i64 %y) {
113; CHECK-LABEL: fshl_i64_const_overshift:
114; CHECK:       # %bb.0:
115; CHECK-NEXT:    rotldi 4, 4, 41
116; CHECK-NEXT:    rldimi 4, 3, 41, 0
117; CHECK-NEXT:    mr 3, 4
118; CHECK-NEXT:    blr
119  %f = call i64 @llvm.fshl.i64(i64 %x, i64 %y, i64 105)
120  ret i64 %f
121}
122
123; This should work without any node-specific logic.
124
125define i8 @fshl_i8_const_fold() {
126; CHECK-LABEL: fshl_i8_const_fold:
127; CHECK:       # %bb.0:
128; CHECK-NEXT:    li 3, 128
129; CHECK-NEXT:    blr
130  %f = call i8 @llvm.fshl.i8(i8 255, i8 0, i8 7)
131  ret i8 %f
132}
133
134; Repeat everything for funnel shift right.
135
136; General case - all operands can be variables.
137
138define i32 @fshr_i32(i32 %x, i32 %y, i32 %z) {
139; CHECK-LABEL: fshr_i32:
140; CHECK:       # %bb.0:
141; CHECK-NEXT:    andi. 5, 5, 31
142; CHECK-NEXT:    subfic 6, 5, 32
143; CHECK-NEXT:    srw 5, 4, 5
144; CHECK-NEXT:    slw 3, 3, 6
145; CHECK-NEXT:    or 3, 3, 5
146; CHECK-NEXT:    iseleq 3, 4, 3
147; CHECK-NEXT:    blr
148  %f = call i32 @llvm.fshr.i32(i32 %x, i32 %y, i32 %z)
149  ret i32 %f
150}
151
152define i64 @fshr_i64(i64 %x, i64 %y, i64 %z) {
153; CHECK-LABEL: fshr_i64:
154; CHECK:       # %bb.0:
155; CHECK-NEXT:    andi. 5, 5, 63
156; CHECK-NEXT:    subfic 6, 5, 64
157; CHECK-NEXT:    srd 5, 4, 5
158; CHECK-NEXT:    sld 3, 3, 6
159; CHECK-NEXT:    or 3, 3, 5
160; CHECK-NEXT:    iseleq 3, 4, 3
161; CHECK-NEXT:    blr
162  %f = call i64 @llvm.fshr.i64(i64 %x, i64 %y, i64 %z)
163  ret i64 %f
164}
165
166; Verify that weird types are minimally supported.
167declare i37 @llvm.fshr.i37(i37, i37, i37)
168define i37 @fshr_i37(i37 %x, i37 %y, i37 %z) {
169; CHECK-LABEL: fshr_i37:
170; CHECK:       # %bb.0:
171; CHECK-NEXT:    lis 6, -8857
172; CHECK-NEXT:    clrldi 5, 5, 27
173; CHECK-NEXT:    ori 6, 6, 51366
174; CHECK-NEXT:    sldi 6, 6, 32
175; CHECK-NEXT:    oris 6, 6, 3542
176; CHECK-NEXT:    ori 6, 6, 31883
177; CHECK-NEXT:    mulhdu 6, 5, 6
178; CHECK-NEXT:    rldicl 6, 6, 59, 5
179; CHECK-NEXT:    mulli 6, 6, 37
180; CHECK-NEXT:    sub. 5, 5, 6
181; CHECK-NEXT:    clrldi 6, 4, 27
182; CHECK-NEXT:    subfic 7, 5, 37
183; CHECK-NEXT:    srd 5, 6, 5
184; CHECK-NEXT:    sld 3, 3, 7
185; CHECK-NEXT:    or 3, 3, 5
186; CHECK-NEXT:    iseleq 3, 4, 3
187; CHECK-NEXT:    blr
188  %f = call i37 @llvm.fshr.i37(i37 %x, i37 %y, i37 %z)
189  ret i37 %f
190}
191
192; extract(concat(0b1110000, 0b1111111) >> 2) = 0b0011111
193
194declare i7 @llvm.fshr.i7(i7, i7, i7)
195define i7 @fshr_i7_const_fold() {
196; CHECK-LABEL: fshr_i7_const_fold:
197; CHECK:       # %bb.0:
198; CHECK-NEXT:    li 3, 31
199; CHECK-NEXT:    blr
200  %f = call i7 @llvm.fshr.i7(i7 112, i7 127, i7 2)
201  ret i7 %f
202}
203
204; With constant shift amount, this is rotate + insert (missing extended mnemonics).
205
206define i32 @fshr_i32_const_shift(i32 %x, i32 %y) {
207; CHECK-LABEL: fshr_i32_const_shift:
208; CHECK:       # %bb.0:
209; CHECK-NEXT:    rotlwi 4, 4, 23
210; CHECK-NEXT:    rlwimi 4, 3, 23, 0, 8
211; CHECK-NEXT:    mr 3, 4
212; CHECK-NEXT:    blr
213  %f = call i32 @llvm.fshr.i32(i32 %x, i32 %y, i32 9)
214  ret i32 %f
215}
216
217; Check modulo math on shift amount. 41-32=9.
218
219define i32 @fshr_i32_const_overshift(i32 %x, i32 %y) {
220; CHECK-LABEL: fshr_i32_const_overshift:
221; CHECK:       # %bb.0:
222; CHECK-NEXT:    rotlwi 4, 4, 23
223; CHECK-NEXT:    rlwimi 4, 3, 23, 0, 8
224; CHECK-NEXT:    mr 3, 4
225; CHECK-NEXT:    blr
226  %f = call i32 @llvm.fshr.i32(i32 %x, i32 %y, i32 41)
227  ret i32 %f
228}
229
230; 64-bit should also work. 105-64 = 41.
231
232define i64 @fshr_i64_const_overshift(i64 %x, i64 %y) {
233; CHECK-LABEL: fshr_i64_const_overshift:
234; CHECK:       # %bb.0:
235; CHECK-NEXT:    rotldi 4, 4, 23
236; CHECK-NEXT:    rldimi 4, 3, 23, 0
237; CHECK-NEXT:    mr 3, 4
238; CHECK-NEXT:    blr
239  %f = call i64 @llvm.fshr.i64(i64 %x, i64 %y, i64 105)
240  ret i64 %f
241}
242
243; This should work without any node-specific logic.
244
245define i8 @fshr_i8_const_fold() {
246; CHECK-LABEL: fshr_i8_const_fold:
247; CHECK:       # %bb.0:
248; CHECK-NEXT:    li 3, 254
249; CHECK-NEXT:    blr
250  %f = call i8 @llvm.fshr.i8(i8 255, i8 0, i8 7)
251  ret i8 %f
252}
253
254define i32 @fshl_i32_shift_by_bitwidth(i32 %x, i32 %y) {
255; CHECK-LABEL: fshl_i32_shift_by_bitwidth:
256; CHECK:       # %bb.0:
257; CHECK-NEXT:    blr
258  %f = call i32 @llvm.fshl.i32(i32 %x, i32 %y, i32 32)
259  ret i32 %f
260}
261
262define i32 @fshr_i32_shift_by_bitwidth(i32 %x, i32 %y) {
263; CHECK-LABEL: fshr_i32_shift_by_bitwidth:
264; CHECK:       # %bb.0:
265; CHECK-NEXT:    mr 3, 4
266; CHECK-NEXT:    blr
267  %f = call i32 @llvm.fshr.i32(i32 %x, i32 %y, i32 32)
268  ret i32 %f
269}
270
271define <4 x i32> @fshl_v4i32_shift_by_bitwidth(<4 x i32> %x, <4 x i32> %y) {
272; CHECK-LABEL: fshl_v4i32_shift_by_bitwidth:
273; CHECK:       # %bb.0:
274; CHECK-NEXT:    blr
275  %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>)
276  ret <4 x i32> %f
277}
278
279define <4 x i32> @fshr_v4i32_shift_by_bitwidth(<4 x i32> %x, <4 x i32> %y) {
280; CHECK-LABEL: fshr_v4i32_shift_by_bitwidth:
281; CHECK:       # %bb.0:
282; CHECK-NEXT:    vmr 2, 3
283; CHECK-NEXT:    blr
284  %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>)
285  ret <4 x i32> %f
286}
287
288