You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

415 lines
12 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

; RUN: llc < %s -mtriple=ve | FileCheck %s
;;; Test shl instruction
;;;
;;; Syntax:
;;; <result> = shl <ty> <op1>, <op2> ; yields ty:result
;;; <result> = shl nuw <ty> <op1>, <op2> ; yields ty:result
;;; <result> = shl nsw <ty> <op1>, <op2> ; yields ty:result
;;; <result> = shl nuw nsw <ty> <op1>, <op2> ; yields ty:result
;;;
;;; Overview:
;;; The shl instruction returns the first operand shifted to the left
;;; a specified number of bits.
;;;
;;; Arguments:
;;; Both arguments to the shl instruction must be the same integer or
;;; vector of integer type. op2 is treated as an unsigned value.
;;;
;;; Semantics:
;;; The value produced is op1 * 2op2 mod 2n, where n is the width of the
;;; result. If op2 is (statically or dynamically) equal to or larger than
;;; the number of bits in op1, this instruction returns a poison value.
;;; If the arguments are vectors, each vector element of op1 is shifted by
;;; the corresponding shift amount in op2.
;;;
;;; If the nuw keyword is present, then the shift produces a poison value
;;; if it shifts out any non-zero bits. If the nsw keyword is present,
;;; then the shift produces a poison value if it shifts out any bits that
;;; disagree with the resultant sign bit.
;;;
;;; Example:
;;; <result> = shl i32 4, %var ; yields i32: 4 << %var
;;; <result> = shl i32 4, 2 ; yields i32: 16
;;; <result> = shl i32 1, 10 ; yields i32: 1024
;;; <result> = shl i32 1, 32 ; undefined
;;; <result> = shl <2 x i32> < i32 1, i32 1>, < i32 1, i32 2>
;;; ; yields: result=<2 x i32> < i32 2, i32 4>
;;;
;;; Note:
;;; We test only i8/i16/i32/i64/i128 and unsigned of them.
; Function Attrs: norecurse nounwind readnone
define signext i8 @shl_i8_var(i8 signext %0, i8 signext %1) {
; CHECK-LABEL: shl_i8_var:
; CHECK: # %bb.0:
; CHECK-NEXT: and %s1, %s1, (56)0
; CHECK-NEXT: sla.w.sx %s0, %s0, %s1
; CHECK-NEXT: sll %s0, %s0, 56
; CHECK-NEXT: sra.l %s0, %s0, 56
; CHECK-NEXT: b.l.t (, %s10)
%3 = sext i8 %0 to i32
%4 = zext i8 %1 to i32
%5 = shl i32 %3, %4
%6 = trunc i32 %5 to i8
ret i8 %6
}
; Function Attrs: norecurse nounwind readnone
define zeroext i8 @shl_u8_var(i8 zeroext %0, i8 zeroext %1) {
; CHECK-LABEL: shl_u8_var:
; CHECK: # %bb.0:
; CHECK-NEXT: sla.w.sx %s0, %s0, %s1
; CHECK-NEXT: and %s0, %s0, (56)0
; CHECK-NEXT: b.l.t (, %s10)
%3 = zext i8 %0 to i32
%4 = zext i8 %1 to i32
%5 = shl i32 %3, %4
%6 = trunc i32 %5 to i8
ret i8 %6
}
; Function Attrs: norecurse nounwind readnone
define signext i16 @shl_i16_var(i16 signext %0, i16 signext %1) {
; CHECK-LABEL: shl_i16_var:
; CHECK: # %bb.0:
; CHECK-NEXT: and %s1, %s1, (48)0
; CHECK-NEXT: sla.w.sx %s0, %s0, %s1
; CHECK-NEXT: sll %s0, %s0, 48
; CHECK-NEXT: sra.l %s0, %s0, 48
; CHECK-NEXT: b.l.t (, %s10)
%3 = sext i16 %0 to i32
%4 = zext i16 %1 to i32
%5 = shl i32 %3, %4
%6 = trunc i32 %5 to i16
ret i16 %6
}
; Function Attrs: norecurse nounwind readnone
define zeroext i16 @shl_u16_var(i16 zeroext %0, i16 zeroext %1) {
; CHECK-LABEL: shl_u16_var:
; CHECK: # %bb.0:
; CHECK-NEXT: sla.w.sx %s0, %s0, %s1
; CHECK-NEXT: and %s0, %s0, (48)0
; CHECK-NEXT: b.l.t (, %s10)
%3 = zext i16 %0 to i32
%4 = zext i16 %1 to i32
%5 = shl i32 %3, %4
%6 = trunc i32 %5 to i16
ret i16 %6
}
; Function Attrs: norecurse nounwind readnone
define signext i32 @shl_i32_var(i32 signext %0, i32 signext %1) {
; CHECK-LABEL: shl_i32_var:
; CHECK: # %bb.0:
; CHECK-NEXT: sla.w.sx %s0, %s0, %s1
; CHECK-NEXT: adds.w.sx %s0, %s0, (0)1
; CHECK-NEXT: b.l.t (, %s10)
%3 = shl i32 %0, %1
ret i32 %3
}
; Function Attrs: norecurse nounwind readnone
define zeroext i32 @shl_u32_var(i32 zeroext %0, i32 zeroext %1) {
; CHECK-LABEL: shl_u32_var:
; CHECK: # %bb.0:
; CHECK-NEXT: sla.w.sx %s0, %s0, %s1
; CHECK-NEXT: adds.w.zx %s0, %s0, (0)1
; CHECK-NEXT: b.l.t (, %s10)
%3 = shl i32 %0, %1
ret i32 %3
}
; Function Attrs: norecurse nounwind readnone
define i64 @shl_i64_var(i64 %0, i64 %1) {
; CHECK-LABEL: shl_i64_var:
; CHECK: # %bb.0:
; CHECK-NEXT: sll %s0, %s0, %s1
; CHECK-NEXT: b.l.t (, %s10)
%3 = shl i64 %0, %1
ret i64 %3
}
; Function Attrs: norecurse nounwind readnone
define i64 @shl_u64_var(i64 %0, i64 %1) {
; CHECK-LABEL: shl_u64_var:
; CHECK: # %bb.0:
; CHECK-NEXT: sll %s0, %s0, %s1
; CHECK-NEXT: b.l.t (, %s10)
%3 = shl i64 %0, %1
ret i64 %3
}
; Function Attrs: norecurse nounwind readnone
define i128 @shl_i128_var(i128 %0, i128 %1) {
; CHECK-LABEL: shl_i128_var:
; CHECK: .LBB{{[0-9]+}}_2:
; CHECK-NEXT: and %s2, %s2, (32)0
; CHECK-NEXT: lea %s3, __ashlti3@lo
; CHECK-NEXT: and %s3, %s3, (32)0
; CHECK-NEXT: lea.sl %s12, __ashlti3@hi(, %s3)
; CHECK-NEXT: bsic %s10, (, %s12)
; CHECK-NEXT: or %s11, 0, %s9
%3 = shl i128 %0, %1
ret i128 %3
}
; Function Attrs: norecurse nounwind readnone
define i128 @shl_u128_var(i128 %0, i128 %1) {
; CHECK-LABEL: shl_u128_var:
; CHECK: .LBB{{[0-9]+}}_2:
; CHECK-NEXT: and %s2, %s2, (32)0
; CHECK-NEXT: lea %s3, __ashlti3@lo
; CHECK-NEXT: and %s3, %s3, (32)0
; CHECK-NEXT: lea.sl %s12, __ashlti3@hi(, %s3)
; CHECK-NEXT: bsic %s10, (, %s12)
; CHECK-NEXT: or %s11, 0, %s9
%3 = shl i128 %0, %1
ret i128 %3
}
; Function Attrs: norecurse nounwind readnone
define signext i8 @shl_const_i8(i8 signext %0) {
; CHECK-LABEL: shl_const_i8:
; CHECK: # %bb.0:
; CHECK-NEXT: and %s0, %s0, (56)0
; CHECK-NEXT: sla.w.sx %s0, (62)1, %s0
; CHECK-NEXT: sll %s0, %s0, 56
; CHECK-NEXT: sra.l %s0, %s0, 56
; CHECK-NEXT: b.l.t (, %s10)
%2 = zext i8 %0 to i32
%3 = shl i32 -4, %2
%4 = trunc i32 %3 to i8
ret i8 %4
}
; Function Attrs: norecurse nounwind readnone
define zeroext i8 @shl_const_u8(i8 zeroext %0) {
; CHECK-LABEL: shl_const_u8:
; CHECK: # %bb.0:
; CHECK-NEXT: sla.w.sx %s0, (62)1, %s0
; CHECK-NEXT: lea %s1, 252
; CHECK-NEXT: and %s0, %s0, %s1
; CHECK-NEXT: b.l.t (, %s10)
%2 = zext i8 %0 to i32
%3 = shl i32 -4, %2
%4 = trunc i32 %3 to i8
ret i8 %4
}
; Function Attrs: norecurse nounwind readnone
define signext i16 @shl_const_i16(i16 signext %0) {
; CHECK-LABEL: shl_const_i16:
; CHECK: # %bb.0:
; CHECK-NEXT: and %s0, %s0, (48)0
; CHECK-NEXT: sla.w.sx %s0, (62)1, %s0
; CHECK-NEXT: sll %s0, %s0, 48
; CHECK-NEXT: sra.l %s0, %s0, 48
; CHECK-NEXT: b.l.t (, %s10)
%2 = zext i16 %0 to i32
%3 = shl i32 -4, %2
%4 = trunc i32 %3 to i16
ret i16 %4
}
; Function Attrs: norecurse nounwind readnone
define zeroext i16 @shl_const_u16(i16 zeroext %0) {
; CHECK-LABEL: shl_const_u16:
; CHECK: # %bb.0:
; CHECK-NEXT: sla.w.sx %s0, (62)1, %s0
; CHECK-NEXT: lea %s1, 65532
; CHECK-NEXT: and %s0, %s0, %s1
; CHECK-NEXT: b.l.t (, %s10)
%2 = zext i16 %0 to i32
%3 = shl i32 -4, %2
%4 = trunc i32 %3 to i16
ret i16 %4
}
; Function Attrs: norecurse nounwind readnone
define signext i32 @shl_const_i32(i32 signext %0) {
; CHECK-LABEL: shl_const_i32:
; CHECK: # %bb.0:
; CHECK-NEXT: sla.w.sx %s0, (62)1, %s0
; CHECK-NEXT: adds.w.sx %s0, %s0, (0)1
; CHECK-NEXT: b.l.t (, %s10)
%2 = shl i32 -4, %0
ret i32 %2
}
; Function Attrs: norecurse nounwind readnone
define zeroext i32 @shl_const_u32(i32 zeroext %0) {
; CHECK-LABEL: shl_const_u32:
; CHECK: # %bb.0:
; CHECK-NEXT: sla.w.sx %s0, (62)1, %s0
; CHECK-NEXT: adds.w.zx %s0, %s0, (0)1
; CHECK-NEXT: b.l.t (, %s10)
%2 = shl i32 -4, %0
ret i32 %2
}
; Function Attrs: norecurse nounwind readnone
define i64 @shl_const_i64(i64 %0) {
; CHECK-LABEL: shl_const_i64:
; CHECK: # %bb.0:
; CHECK-NEXT: sll %s0, (62)1, %s0
; CHECK-NEXT: b.l.t (, %s10)
%2 = shl i64 -4, %0
ret i64 %2
}
; Function Attrs: norecurse nounwind readnone
define i64 @shl_const_u64(i64 %0) {
; CHECK-LABEL: shl_const_u64:
; CHECK: # %bb.0:
; CHECK-NEXT: sll %s0, (62)1, %s0
; CHECK-NEXT: b.l.t (, %s10)
%2 = shl i64 -4, %0
ret i64 %2
}
; Function Attrs: norecurse nounwind readnone
define i128 @shl_const_i128(i128 %0) {
; CHECK-LABEL: shl_const_i128:
; CHECK: .LBB{{[0-9]+}}_2:
; CHECK-NEXT: and %s2, %s0, (32)0
; CHECK-NEXT: lea %s0, __ashlti3@lo
; CHECK-NEXT: and %s0, %s0, (32)0
; CHECK-NEXT: lea.sl %s12, __ashlti3@hi(, %s0)
; CHECK-NEXT: or %s0, -4, (0)1
; CHECK-NEXT: or %s1, -1, (0)1
; CHECK-NEXT: bsic %s10, (, %s12)
; CHECK-NEXT: or %s11, 0, %s9
%2 = shl i128 -4, %0
ret i128 %2
}
; Function Attrs: norecurse nounwind readnone
define i128 @shl_const_u128(i128 %0) {
; CHECK-LABEL: shl_const_u128:
; CHECK: .LBB{{[0-9]+}}_2:
; CHECK-NEXT: and %s2, %s0, (32)0
; CHECK-NEXT: lea %s0, __ashlti3@lo
; CHECK-NEXT: and %s0, %s0, (32)0
; CHECK-NEXT: lea.sl %s12, __ashlti3@hi(, %s0)
; CHECK-NEXT: or %s0, -4, (0)1
; CHECK-NEXT: or %s1, -1, (0)1
; CHECK-NEXT: bsic %s10, (, %s12)
; CHECK-NEXT: or %s11, 0, %s9
%2 = shl i128 -4, %0
ret i128 %2
}
; Function Attrs: norecurse nounwind readnone
define signext i8 @shl_i8_const(i8 signext %0) {
; CHECK-LABEL: shl_i8_const:
; CHECK: # %bb.0:
; CHECK-NEXT: sla.w.sx %s0, %s0, 3
; CHECK-NEXT: sll %s0, %s0, 56
; CHECK-NEXT: sra.l %s0, %s0, 56
; CHECK-NEXT: b.l.t (, %s10)
%2 = shl i8 %0, 3
ret i8 %2
}
; Function Attrs: norecurse nounwind readnone
define zeroext i8 @shl_u8_const(i8 zeroext %0) {
; CHECK-LABEL: shl_u8_const:
; CHECK: # %bb.0:
; CHECK-NEXT: sla.w.sx %s0, %s0, 3
; CHECK-NEXT: lea %s1, 248
; CHECK-NEXT: and %s0, %s0, %s1
; CHECK-NEXT: b.l.t (, %s10)
%2 = shl i8 %0, 3
ret i8 %2
}
; Function Attrs: norecurse nounwind readnone
define signext i16 @shl_i16_const(i16 signext %0) {
; CHECK-LABEL: shl_i16_const:
; CHECK: # %bb.0:
; CHECK-NEXT: sla.w.sx %s0, %s0, 7
; CHECK-NEXT: sll %s0, %s0, 48
; CHECK-NEXT: sra.l %s0, %s0, 48
; CHECK-NEXT: b.l.t (, %s10)
%2 = shl i16 %0, 7
ret i16 %2
}
; Function Attrs: norecurse nounwind readnone
define zeroext i16 @shl_u16_const(i16 zeroext %0) {
; CHECK-LABEL: shl_u16_const:
; CHECK: # %bb.0:
; CHECK-NEXT: sla.w.sx %s0, %s0, 7
; CHECK-NEXT: lea %s1, 65408
; CHECK-NEXT: and %s0, %s0, %s1
; CHECK-NEXT: b.l.t (, %s10)
%2 = shl i16 %0, 7
ret i16 %2
}
; Function Attrs: norecurse nounwind readnone
define signext i32 @shl_i32_const(i32 signext %0) {
; CHECK-LABEL: shl_i32_const:
; CHECK: # %bb.0:
; CHECK-NEXT: sla.w.sx %s0, %s0, 15
; CHECK-NEXT: adds.w.sx %s0, %s0, (0)1
; CHECK-NEXT: b.l.t (, %s10)
%2 = shl i32 %0, 15
ret i32 %2
}
; Function Attrs: norecurse nounwind readnone
define zeroext i32 @shl_u32_const(i32 zeroext %0) {
; CHECK-LABEL: shl_u32_const:
; CHECK: # %bb.0:
; CHECK-NEXT: sla.w.sx %s0, %s0, 15
; CHECK-NEXT: adds.w.zx %s0, %s0, (0)1
; CHECK-NEXT: b.l.t (, %s10)
%2 = shl i32 %0, 15
ret i32 %2
}
; Function Attrs: norecurse nounwind readnone
define i64 @shl_i64_const(i64 %0) {
; CHECK-LABEL: shl_i64_const:
; CHECK: # %bb.0:
; CHECK-NEXT: sll %s0, %s0, 63
; CHECK-NEXT: b.l.t (, %s10)
%2 = shl i64 %0, 63
ret i64 %2
}
; Function Attrs: norecurse nounwind readnone
define i64 @shl_u64_const(i64 %0) {
; CHECK-LABEL: shl_u64_const:
; CHECK: # %bb.0:
; CHECK-NEXT: sll %s0, %s0, 63
; CHECK-NEXT: b.l.t (, %s10)
%2 = shl i64 %0, 63
ret i64 %2
}
; Function Attrs: norecurse nounwind readnone
define i128 @shl_i128_const(i128 %0) {
; CHECK-LABEL: shl_i128_const:
; CHECK: # %bb.0:
; CHECK-NEXT: sll %s1, %s0, 63
; CHECK-NEXT: or %s0, 0, (0)1
; CHECK-NEXT: b.l.t (, %s10)
%2 = shl i128 %0, 127
ret i128 %2
}
; Function Attrs: norecurse nounwind readnone
define i128 @shl_u128_const(i128 %0) {
; CHECK-LABEL: shl_u128_const:
; CHECK: # %bb.0:
; CHECK-NEXT: sll %s1, %s0, 63
; CHECK-NEXT: or %s0, 0, (0)1
; CHECK-NEXT: b.l.t (, %s10)
%2 = shl i128 %0, 127
ret i128 %2
}