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