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