1 ; RUN: llc < %s -mtriple=ve | FileCheck %s
3 ;;; Test both ‘lshr’ and `ashr` instructions
8 ;;; <result> = lshr <ty> <op1>, <op2> ; yields ty:result
9 ;;; <result> = lshr exact <ty> <op1>, <op2> ; yields ty:result
12 ;;; The ‘lshr’ instruction (logical shift right) returns the first operand
13 ;;; shifted to the right a specified number of bits with zero fill.
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.
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.
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.
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>
39 ;;; ‘ashr’ Instruction
42 ;;; <result> = ashr <ty> <op1>, <op2> ; yields ty:result
43 ;;; <result> = ashr exact <ty> <op1>, <op2> ; yields ty:result
46 ;;; The ‘ashr’ instruction (arithmetic shift right) returns the first operand
47 ;;; shifted to the right a specified number of bits with sign extension.
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.
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.
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.
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>
74 ;;; We test only i8/i16/i32/i64/i128 and unsigned of them.
76 ; Function Attrs: norecurse nounwind readnone
77 define signext i8 @shl_i8_var(i8 signext %0, i8 signext %1) {
78 ; CHECK-LABEL: shl_i8_var:
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
87 %6 = trunc i32 %5 to i8
91 ; Function Attrs: norecurse nounwind readnone
92 define zeroext i8 @shl_u8_var(i8 zeroext %0, i8 zeroext %1) {
93 ; CHECK-LABEL: shl_u8_var:
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
102 %6 = trunc i32 %5 to i8
106 ; Function Attrs: norecurse nounwind readnone
107 define signext i16 @shl_i16_var(i16 signext %0, i16 signext %1) {
108 ; CHECK-LABEL: shl_i16_var:
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
117 %6 = trunc i32 %5 to i16
121 ; Function Attrs: norecurse nounwind readnone
122 define zeroext i16 @shl_u16_var(i16 zeroext %0, i16 zeroext %1) {
123 ; CHECK-LABEL: shl_u16_var:
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
132 %6 = trunc i32 %5 to i16
136 ; Function Attrs: norecurse nounwind readnone
137 define signext i32 @shl_i32_var(i32 signext %0, i32 signext %1) {
138 ; CHECK-LABEL: shl_i32_var:
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)
147 ; Function Attrs: norecurse nounwind readnone
148 define zeroext i32 @shl_u32_var(i32 zeroext %0, i32 zeroext %1) {
149 ; CHECK-LABEL: shl_u32_var:
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)
159 ; Function Attrs: norecurse nounwind readnone
160 define i64 @shl_i64_var(i64 %0, i64 %1) {
161 ; CHECK-LABEL: shl_i64_var:
163 ; CHECK-NEXT: sra.l %s0, %s0, %s1
164 ; CHECK-NEXT: b.l.t (, %s10)
169 ; Function Attrs: norecurse nounwind readnone
170 define i64 @shl_u64_var(i64 %0, i64 %1) {
171 ; CHECK-LABEL: shl_u64_var:
173 ; CHECK-NEXT: srl %s0, %s0, %s1
174 ; CHECK-NEXT: b.l.t (, %s10)
179 ; Function Attrs: norecurse nounwind readnone
180 define 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
193 ; Function Attrs: norecurse nounwind readnone
194 define 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
207 ; Function Attrs: norecurse nounwind readnone
208 define signext i8 @shl_const_i8(i8 signext %0) {
209 ; CHECK-LABEL: shl_const_i8:
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
217 %4 = trunc i32 %3 to i8
221 ; Function Attrs: norecurse nounwind readnone
222 define zeroext i8 @shl_const_u8(i8 zeroext %0) {
223 ; CHECK-LABEL: shl_const_u8:
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
230 %4 = trunc i32 %3 to i8
234 ; Function Attrs: norecurse nounwind readnone
235 define signext i16 @shl_const_i16(i16 signext %0) {
236 ; CHECK-LABEL: shl_const_i16:
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
244 %4 = trunc i32 %3 to i16
248 ; Function Attrs: norecurse nounwind readnone
249 define zeroext i16 @shl_const_u16(i16 zeroext %0) {
250 ; CHECK-LABEL: shl_const_u16:
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
257 %4 = trunc i32 %3 to i16
261 ; Function Attrs: norecurse nounwind readnone
262 define signext i32 @shl_const_i32(i32 signext %0) {
263 ; CHECK-LABEL: shl_const_i32:
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)
272 ; Function Attrs: norecurse nounwind readnone
273 define zeroext i32 @shl_const_u32(i32 zeroext %0) {
274 ; CHECK-LABEL: shl_const_u32:
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)
283 ; Function Attrs: norecurse nounwind readnone
284 define i64 @shl_const_i64(i64 %0) {
285 ; CHECK-LABEL: shl_const_i64:
287 ; CHECK-NEXT: sra.l %s0, (62)1, %s0
288 ; CHECK-NEXT: b.l.t (, %s10)
293 ; Function Attrs: norecurse nounwind readnone
294 define i64 @shl_const_u64(i64 %0) {
295 ; CHECK-LABEL: shl_const_u64:
297 ; CHECK-NEXT: sra.l %s0, (62)1, %s0
298 ; CHECK-NEXT: b.l.t (, %s10)
303 ; Function Attrs: norecurse nounwind readnone
304 define 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
319 ; Function Attrs: norecurse nounwind readnone
320 define 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
335 ; Function Attrs: norecurse nounwind readnone
336 define signext i8 @shl_i8_const(i8 signext %0) {
337 ; CHECK-LABEL: shl_i8_const:
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)
346 ; Function Attrs: norecurse nounwind readnone
347 define zeroext i8 @shl_u8_const(i8 zeroext %0) {
348 ; CHECK-LABEL: shl_u8_const:
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)
358 ; Function Attrs: norecurse nounwind readnone
359 define signext i16 @shl_i16_const(i16 signext %0) {
360 ; CHECK-LABEL: shl_i16_const:
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)
369 ; Function Attrs: norecurse nounwind readnone
370 define zeroext i16 @shl_u16_const(i16 zeroext %0) {
371 ; CHECK-LABEL: shl_u16_const:
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)
381 ; Function Attrs: norecurse nounwind readnone
382 define signext i32 @shl_i32_const(i32 signext %0) {
383 ; CHECK-LABEL: shl_i32_const:
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)
392 ; Function Attrs: norecurse nounwind readnone
393 define zeroext i32 @shl_u32_const(i32 zeroext %0) {
394 ; CHECK-LABEL: shl_u32_const:
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)
404 ; Function Attrs: norecurse nounwind readnone
405 define i64 @shl_i64_const(i64 %0) {
406 ; CHECK-LABEL: shl_i64_const:
408 ; CHECK-NEXT: sra.l %s0, %s0, 63
409 ; CHECK-NEXT: b.l.t (, %s10)
414 ; Function Attrs: norecurse nounwind readnone
415 define i64 @shl_u64_const(i64 %0) {
416 ; CHECK-LABEL: shl_u64_const:
418 ; CHECK-NEXT: srl %s0, %s0, 63
419 ; CHECK-NEXT: b.l.t (, %s10)
424 ; Function Attrs: norecurse nounwind readnone
425 define i128 @shl_i128_const(i128 %0) {
426 ; CHECK-LABEL: shl_i128_const:
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
435 ; Function Attrs: norecurse nounwind readnone
436 define i128 @shl_u128_const(i128 %0) {
437 ; CHECK-LABEL: shl_u128_const:
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