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