1; RUN: llc < %s -mtriple=ve | FileCheck %s
2
3;;; Test ‘shl’ instruction
4;;;
5;;; Syntax:
6;;;   <result> = shl <ty> <op1>, <op2>           ; yields ty:result
7;;;   <result> = shl nuw <ty> <op1>, <op2>       ; yields ty:result
8;;;   <result> = shl nsw <ty> <op1>, <op2>       ; yields ty:result
9;;;   <result> = shl nuw nsw <ty> <op1>, <op2>   ; yields ty:result
10;;;
11;;; Overview:
12;;;   The ‘shl’ instruction returns the first operand shifted to the left
13;;;   a specified number of bits.
14;;;
15;;; Arguments:
16;;;   Both arguments to the ‘shl’ instruction must be the same integer or
17;;;   vector of integer type. ‘op2’ is treated as an unsigned value.
18;;;
19;;; Semantics:
20;;;   The value produced is op1 * 2op2 mod 2n, where n is the width of the
21;;;   result. If op2 is (statically or dynamically) equal to or larger than
22;;;   the number of bits in op1, this instruction returns a poison value.
23;;;   If the arguments are vectors, each vector element of op1 is shifted by
24;;;   the corresponding shift amount in op2.
25;;;
26;;;   If the nuw keyword is present, then the shift produces a poison value
27;;;   if it shifts out any non-zero bits. If the nsw keyword is present,
28;;;   then the shift produces a poison value if it shifts out any bits that
29;;;   disagree with the resultant sign bit.
30;;;
31;;; Example:
32;;;   <result> = shl i32 4, %var   ; yields i32: 4 << %var
33;;;   <result> = shl i32 4, 2      ; yields i32: 16
34;;;   <result> = shl i32 1, 10     ; yields i32: 1024
35;;;   <result> = shl i32 1, 32     ; undefined
36;;;   <result> = shl <2 x i32> < i32 1, i32 1>, < i32 1, i32 2>
37;;;                                ; yields: result=<2 x i32> < i32 2, i32 4>
38;;;
39;;; Note:
40;;;   We test only i8/i16/i32/i64/i128 and unsigned of them.
41
42; Function Attrs: norecurse nounwind readnone
43define signext i8 @shl_i8_var(i8 signext %0, i8 signext %1) {
44; CHECK-LABEL: shl_i8_var:
45; CHECK:       # %bb.0:
46; CHECK-NEXT:    and %s1, %s1, (56)0
47; CHECK-NEXT:    sla.w.sx %s0, %s0, %s1
48; CHECK-NEXT:    sll %s0, %s0, 56
49; CHECK-NEXT:    sra.l %s0, %s0, 56
50; CHECK-NEXT:    b.l.t (, %s10)
51  %3 = sext i8 %0 to i32
52  %4 = zext i8 %1 to i32
53  %5 = shl i32 %3, %4
54  %6 = trunc i32 %5 to i8
55  ret i8 %6
56}
57
58; Function Attrs: norecurse nounwind readnone
59define zeroext i8 @shl_u8_var(i8 zeroext %0, i8 zeroext %1) {
60; CHECK-LABEL: shl_u8_var:
61; CHECK:       # %bb.0:
62; CHECK-NEXT:    sla.w.sx %s0, %s0, %s1
63; CHECK-NEXT:    and %s0, %s0, (56)0
64; CHECK-NEXT:    b.l.t (, %s10)
65  %3 = zext i8 %0 to i32
66  %4 = zext i8 %1 to i32
67  %5 = shl i32 %3, %4
68  %6 = trunc i32 %5 to i8
69  ret i8 %6
70}
71
72; Function Attrs: norecurse nounwind readnone
73define signext i16 @shl_i16_var(i16 signext %0, i16 signext %1) {
74; CHECK-LABEL: shl_i16_var:
75; CHECK:       # %bb.0:
76; CHECK-NEXT:    and %s1, %s1, (48)0
77; CHECK-NEXT:    sla.w.sx %s0, %s0, %s1
78; CHECK-NEXT:    sll %s0, %s0, 48
79; CHECK-NEXT:    sra.l %s0, %s0, 48
80; CHECK-NEXT:    b.l.t (, %s10)
81  %3 = sext i16 %0 to i32
82  %4 = zext i16 %1 to i32
83  %5 = shl i32 %3, %4
84  %6 = trunc i32 %5 to i16
85  ret i16 %6
86}
87
88; Function Attrs: norecurse nounwind readnone
89define zeroext i16 @shl_u16_var(i16 zeroext %0, i16 zeroext %1) {
90; CHECK-LABEL: shl_u16_var:
91; CHECK:       # %bb.0:
92; CHECK-NEXT:    sla.w.sx %s0, %s0, %s1
93; CHECK-NEXT:    and %s0, %s0, (48)0
94; CHECK-NEXT:    b.l.t (, %s10)
95  %3 = zext i16 %0 to i32
96  %4 = zext i16 %1 to i32
97  %5 = shl i32 %3, %4
98  %6 = trunc i32 %5 to i16
99  ret i16 %6
100}
101
102; Function Attrs: norecurse nounwind readnone
103define signext i32 @shl_i32_var(i32 signext %0, i32 signext %1) {
104; CHECK-LABEL: shl_i32_var:
105; CHECK:       # %bb.0:
106; CHECK-NEXT:    sla.w.sx %s0, %s0, %s1
107; CHECK-NEXT:    adds.w.sx %s0, %s0, (0)1
108; CHECK-NEXT:    b.l.t (, %s10)
109  %3 = shl i32 %0, %1
110  ret i32 %3
111}
112
113; Function Attrs: norecurse nounwind readnone
114define zeroext i32 @shl_u32_var(i32 zeroext %0, i32 zeroext %1) {
115; CHECK-LABEL: shl_u32_var:
116; CHECK:       # %bb.0:
117; CHECK-NEXT:    sla.w.sx %s0, %s0, %s1
118; CHECK-NEXT:    adds.w.zx %s0, %s0, (0)1
119; CHECK-NEXT:    b.l.t (, %s10)
120  %3 = shl i32 %0, %1
121  ret i32 %3
122}
123
124; Function Attrs: norecurse nounwind readnone
125define i64 @shl_i64_var(i64 %0, i64 %1) {
126; CHECK-LABEL: shl_i64_var:
127; CHECK:       # %bb.0:
128; CHECK-NEXT:    sll %s0, %s0, %s1
129; CHECK-NEXT:    b.l.t (, %s10)
130  %3 = shl i64 %0, %1
131  ret i64 %3
132}
133
134; Function Attrs: norecurse nounwind readnone
135define i64 @shl_u64_var(i64 %0, i64 %1) {
136; CHECK-LABEL: shl_u64_var:
137; CHECK:       # %bb.0:
138; CHECK-NEXT:    sll %s0, %s0, %s1
139; CHECK-NEXT:    b.l.t (, %s10)
140  %3 = shl i64 %0, %1
141  ret i64 %3
142}
143
144; Function Attrs: norecurse nounwind readnone
145define i128 @shl_i128_var(i128 %0, i128 %1) {
146; CHECK-LABEL: shl_i128_var:
147; CHECK:       .LBB{{[0-9]+}}_2:
148; CHECK-NEXT:    and %s2, %s2, (32)0
149; CHECK-NEXT:    lea %s3, __ashlti3@lo
150; CHECK-NEXT:    and %s3, %s3, (32)0
151; CHECK-NEXT:    lea.sl %s12, __ashlti3@hi(, %s3)
152; CHECK-NEXT:    bsic %s10, (, %s12)
153; CHECK-NEXT:    or %s11, 0, %s9
154  %3 = shl i128 %0, %1
155  ret i128 %3
156}
157
158; Function Attrs: norecurse nounwind readnone
159define i128 @shl_u128_var(i128 %0, i128 %1) {
160; CHECK-LABEL: shl_u128_var:
161; CHECK:       .LBB{{[0-9]+}}_2:
162; CHECK-NEXT:    and %s2, %s2, (32)0
163; CHECK-NEXT:    lea %s3, __ashlti3@lo
164; CHECK-NEXT:    and %s3, %s3, (32)0
165; CHECK-NEXT:    lea.sl %s12, __ashlti3@hi(, %s3)
166; CHECK-NEXT:    bsic %s10, (, %s12)
167; CHECK-NEXT:    or %s11, 0, %s9
168  %3 = shl i128 %0, %1
169  ret i128 %3
170}
171
172; Function Attrs: norecurse nounwind readnone
173define signext i8 @shl_const_i8(i8 signext %0) {
174; CHECK-LABEL: shl_const_i8:
175; CHECK:       # %bb.0:
176; CHECK-NEXT:    and %s0, %s0, (56)0
177; CHECK-NEXT:    sla.w.sx %s0, (62)1, %s0
178; CHECK-NEXT:    sll %s0, %s0, 56
179; CHECK-NEXT:    sra.l %s0, %s0, 56
180; CHECK-NEXT:    b.l.t (, %s10)
181  %2 = zext i8 %0 to i32
182  %3 = shl i32 -4, %2
183  %4 = trunc i32 %3 to i8
184  ret i8 %4
185}
186
187; Function Attrs: norecurse nounwind readnone
188define zeroext i8 @shl_const_u8(i8 zeroext %0) {
189; CHECK-LABEL: shl_const_u8:
190; CHECK:       # %bb.0:
191; CHECK-NEXT:    sla.w.sx %s0, (62)1, %s0
192; CHECK-NEXT:    lea %s1, 252
193; CHECK-NEXT:    and %s0, %s0, %s1
194; CHECK-NEXT:    b.l.t (, %s10)
195  %2 = zext i8 %0 to i32
196  %3 = shl i32 -4, %2
197  %4 = trunc i32 %3 to i8
198  ret i8 %4
199}
200
201; Function Attrs: norecurse nounwind readnone
202define signext i16 @shl_const_i16(i16 signext %0) {
203; CHECK-LABEL: shl_const_i16:
204; CHECK:       # %bb.0:
205; CHECK-NEXT:    and %s0, %s0, (48)0
206; CHECK-NEXT:    sla.w.sx %s0, (62)1, %s0
207; CHECK-NEXT:    sll %s0, %s0, 48
208; CHECK-NEXT:    sra.l %s0, %s0, 48
209; CHECK-NEXT:    b.l.t (, %s10)
210  %2 = zext i16 %0 to i32
211  %3 = shl i32 -4, %2
212  %4 = trunc i32 %3 to i16
213  ret i16 %4
214}
215
216; Function Attrs: norecurse nounwind readnone
217define zeroext i16 @shl_const_u16(i16 zeroext %0) {
218; CHECK-LABEL: shl_const_u16:
219; CHECK:       # %bb.0:
220; CHECK-NEXT:    sla.w.sx %s0, (62)1, %s0
221; CHECK-NEXT:    lea %s1, 65532
222; CHECK-NEXT:    and %s0, %s0, %s1
223; CHECK-NEXT:    b.l.t (, %s10)
224  %2 = zext i16 %0 to i32
225  %3 = shl i32 -4, %2
226  %4 = trunc i32 %3 to i16
227  ret i16 %4
228}
229
230; Function Attrs: norecurse nounwind readnone
231define signext i32 @shl_const_i32(i32 signext %0) {
232; CHECK-LABEL: shl_const_i32:
233; CHECK:       # %bb.0:
234; CHECK-NEXT:    sla.w.sx %s0, (62)1, %s0
235; CHECK-NEXT:    adds.w.sx %s0, %s0, (0)1
236; CHECK-NEXT:    b.l.t (, %s10)
237  %2 = shl i32 -4, %0
238  ret i32 %2
239}
240
241; Function Attrs: norecurse nounwind readnone
242define zeroext i32 @shl_const_u32(i32 zeroext %0) {
243; CHECK-LABEL: shl_const_u32:
244; CHECK:       # %bb.0:
245; CHECK-NEXT:    sla.w.sx %s0, (62)1, %s0
246; CHECK-NEXT:    adds.w.zx %s0, %s0, (0)1
247; CHECK-NEXT:    b.l.t (, %s10)
248  %2 = shl i32 -4, %0
249  ret i32 %2
250}
251
252; Function Attrs: norecurse nounwind readnone
253define i64 @shl_const_i64(i64 %0) {
254; CHECK-LABEL: shl_const_i64:
255; CHECK:       # %bb.0:
256; CHECK-NEXT:    sll %s0, (62)1, %s0
257; CHECK-NEXT:    b.l.t (, %s10)
258  %2 = shl i64 -4, %0
259  ret i64 %2
260}
261
262; Function Attrs: norecurse nounwind readnone
263define i64 @shl_const_u64(i64 %0) {
264; CHECK-LABEL: shl_const_u64:
265; CHECK:       # %bb.0:
266; CHECK-NEXT:    sll %s0, (62)1, %s0
267; CHECK-NEXT:    b.l.t (, %s10)
268  %2 = shl i64 -4, %0
269  ret i64 %2
270}
271
272; Function Attrs: norecurse nounwind readnone
273define i128 @shl_const_i128(i128 %0) {
274; CHECK-LABEL: shl_const_i128:
275; CHECK:       .LBB{{[0-9]+}}_2:
276; CHECK-NEXT:    and %s2, %s0, (32)0
277; CHECK-NEXT:    lea %s0, __ashlti3@lo
278; CHECK-NEXT:    and %s0, %s0, (32)0
279; CHECK-NEXT:    lea.sl %s12, __ashlti3@hi(, %s0)
280; CHECK-NEXT:    or %s0, -4, (0)1
281; CHECK-NEXT:    or %s1, -1, (0)1
282; CHECK-NEXT:    bsic %s10, (, %s12)
283; CHECK-NEXT:    or %s11, 0, %s9
284  %2 = shl i128 -4, %0
285  ret i128 %2
286}
287
288; Function Attrs: norecurse nounwind readnone
289define i128 @shl_const_u128(i128 %0) {
290; CHECK-LABEL: shl_const_u128:
291; CHECK:       .LBB{{[0-9]+}}_2:
292; CHECK-NEXT:    and %s2, %s0, (32)0
293; CHECK-NEXT:    lea %s0, __ashlti3@lo
294; CHECK-NEXT:    and %s0, %s0, (32)0
295; CHECK-NEXT:    lea.sl %s12, __ashlti3@hi(, %s0)
296; CHECK-NEXT:    or %s0, -4, (0)1
297; CHECK-NEXT:    or %s1, -1, (0)1
298; CHECK-NEXT:    bsic %s10, (, %s12)
299; CHECK-NEXT:    or %s11, 0, %s9
300  %2 = shl i128 -4, %0
301  ret i128 %2
302}
303
304; Function Attrs: norecurse nounwind readnone
305define signext i8 @shl_i8_const(i8 signext %0) {
306; CHECK-LABEL: shl_i8_const:
307; CHECK:       # %bb.0:
308; CHECK-NEXT:    sla.w.sx %s0, %s0, 3
309; CHECK-NEXT:    sll %s0, %s0, 56
310; CHECK-NEXT:    sra.l %s0, %s0, 56
311; CHECK-NEXT:    b.l.t (, %s10)
312  %2 = shl i8 %0, 3
313  ret i8 %2
314}
315
316; Function Attrs: norecurse nounwind readnone
317define zeroext i8 @shl_u8_const(i8 zeroext %0) {
318; CHECK-LABEL: shl_u8_const:
319; CHECK:       # %bb.0:
320; CHECK-NEXT:    sla.w.sx %s0, %s0, 3
321; CHECK-NEXT:    lea %s1, 248
322; CHECK-NEXT:    and %s0, %s0, %s1
323; CHECK-NEXT:    b.l.t (, %s10)
324  %2 = shl i8 %0, 3
325  ret i8 %2
326}
327
328; Function Attrs: norecurse nounwind readnone
329define signext i16 @shl_i16_const(i16 signext %0) {
330; CHECK-LABEL: shl_i16_const:
331; CHECK:       # %bb.0:
332; CHECK-NEXT:    sla.w.sx %s0, %s0, 7
333; CHECK-NEXT:    sll %s0, %s0, 48
334; CHECK-NEXT:    sra.l %s0, %s0, 48
335; CHECK-NEXT:    b.l.t (, %s10)
336  %2 = shl i16 %0, 7
337  ret i16 %2
338}
339
340; Function Attrs: norecurse nounwind readnone
341define zeroext i16 @shl_u16_const(i16 zeroext %0) {
342; CHECK-LABEL: shl_u16_const:
343; CHECK:       # %bb.0:
344; CHECK-NEXT:    sla.w.sx %s0, %s0, 7
345; CHECK-NEXT:    lea %s1, 65408
346; CHECK-NEXT:    and %s0, %s0, %s1
347; CHECK-NEXT:    b.l.t (, %s10)
348  %2 = shl i16 %0, 7
349  ret i16 %2
350}
351
352; Function Attrs: norecurse nounwind readnone
353define signext i32 @shl_i32_const(i32 signext %0) {
354; CHECK-LABEL: shl_i32_const:
355; CHECK:       # %bb.0:
356; CHECK-NEXT:    sla.w.sx %s0, %s0, 15
357; CHECK-NEXT:    adds.w.sx %s0, %s0, (0)1
358; CHECK-NEXT:    b.l.t (, %s10)
359  %2 = shl i32 %0, 15
360  ret i32 %2
361}
362
363; Function Attrs: norecurse nounwind readnone
364define zeroext i32 @shl_u32_const(i32 zeroext %0) {
365; CHECK-LABEL: shl_u32_const:
366; CHECK:       # %bb.0:
367; CHECK-NEXT:    sla.w.sx %s0, %s0, 15
368; CHECK-NEXT:    adds.w.zx %s0, %s0, (0)1
369; CHECK-NEXT:    b.l.t (, %s10)
370  %2 = shl i32 %0, 15
371  ret i32 %2
372}
373
374; Function Attrs: norecurse nounwind readnone
375define i64 @shl_i64_const(i64 %0) {
376; CHECK-LABEL: shl_i64_const:
377; CHECK:       # %bb.0:
378; CHECK-NEXT:    sll %s0, %s0, 63
379; CHECK-NEXT:    b.l.t (, %s10)
380  %2 = shl i64 %0, 63
381  ret i64 %2
382}
383
384; Function Attrs: norecurse nounwind readnone
385define i64 @shl_u64_const(i64 %0) {
386; CHECK-LABEL: shl_u64_const:
387; CHECK:       # %bb.0:
388; CHECK-NEXT:    sll %s0, %s0, 63
389; CHECK-NEXT:    b.l.t (, %s10)
390  %2 = shl i64 %0, 63
391  ret i64 %2
392}
393
394; Function Attrs: norecurse nounwind readnone
395define i128 @shl_i128_const(i128 %0) {
396; CHECK-LABEL: shl_i128_const:
397; CHECK:       # %bb.0:
398; CHECK-NEXT:    sll %s1, %s0, 63
399; CHECK-NEXT:    or %s0, 0, (0)1
400; CHECK-NEXT:    b.l.t (, %s10)
401  %2 = shl i128 %0, 127
402  ret i128 %2
403}
404
405; Function Attrs: norecurse nounwind readnone
406define i128 @shl_u128_const(i128 %0) {
407; CHECK-LABEL: shl_u128_const:
408; CHECK:       # %bb.0:
409; CHECK-NEXT:    sll %s1, %s0, 63
410; CHECK-NEXT:    or %s0, 0, (0)1
411; CHECK-NEXT:    b.l.t (, %s10)
412  %2 = shl i128 %0, 127
413  ret i128 %2
414}
415