[llvm] 42a16da - [VE] Bit operator isel

Simon Moll via llvm-commits llvm-commits at lists.llvm.org
Wed Feb 12 00:02:58 PST 2020


Author: Kazushi (Jam) Marukawa
Date: 2020-02-12T09:02:13+01:00
New Revision: 42a16dacda41be13ccd57b55fef196ca8664b11d

URL: https://github.com/llvm/llvm-project/commit/42a16dacda41be13ccd57b55fef196ca8664b11d
DIFF: https://github.com/llvm/llvm-project/commit/42a16dacda41be13ccd57b55fef196ca8664b11d.diff

LOG: [VE] Bit operator isel

Summary: Isel and tests for bswap,brev,ctpop,ctlz,ctty,rotl,rotr

Reviewed By: arsenm

Differential Revision: https://reviews.llvm.org/D74304

Added: 
    llvm/test/CodeGen/VE/bitreverse.ll
    llvm/test/CodeGen/VE/bswap.ll
    llvm/test/CodeGen/VE/ctlz.ll
    llvm/test/CodeGen/VE/ctpop.ll
    llvm/test/CodeGen/VE/cttz.ll
    llvm/test/CodeGen/VE/rotl.ll
    llvm/test/CodeGen/VE/rotr.ll

Modified: 
    llvm/lib/Target/VE/VEISelLowering.cpp
    llvm/lib/Target/VE/VEInstrInfo.td

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/VE/VEISelLowering.cpp b/llvm/lib/Target/VE/VEISelLowering.cpp
index 92d0fc2419d4..e0411dae1727 100644
--- a/llvm/lib/Target/VE/VEISelLowering.cpp
+++ b/llvm/lib/Target/VE/VEISelLowering.cpp
@@ -556,13 +556,28 @@ VETargetLowering::VETargetLowering(const TargetMachine &TM,
   setOperationAction(ISD::VAEND, MVT::Other, Expand);
   /// } VAARG handling
 
-  // VE has no REM or DIVREM operations.
-  for (MVT IntVT : MVT::integer_valuetypes()) {
+  /// Int Ops {
+  for (MVT IntVT : {MVT::i32, MVT::i64}) {
+    // VE has no REM or DIVREM operations.
     setOperationAction(ISD::UREM, IntVT, Expand);
     setOperationAction(ISD::SREM, IntVT, Expand);
     setOperationAction(ISD::SDIVREM, IntVT, Expand);
     setOperationAction(ISD::UDIVREM, IntVT, Expand);
+
+    setOperationAction(ISD::CTTZ, IntVT, Expand);
+    setOperationAction(ISD::ROTL, IntVT, Expand);
+    setOperationAction(ISD::ROTR, IntVT, Expand);
+
+    // Use isel patterns for i32 and i64
+    setOperationAction(ISD::BSWAP, IntVT, Legal);
+    setOperationAction(ISD::CTLZ, IntVT, Legal);
+    setOperationAction(ISD::CTPOP, IntVT, Legal);
+
+    // Use isel patterns for i64, Promote i32
+    LegalizeAction Act = (IntVT == MVT::i32) ? Promote : Legal;
+    setOperationAction(ISD::BITREVERSE, IntVT, Act);
   }
+  /// } Int Ops
 
   /// Conversion {
   // VE doesn't have instructions for fp<->uint, so expand them by llvm

diff  --git a/llvm/lib/Target/VE/VEInstrInfo.td b/llvm/lib/Target/VE/VEInstrInfo.td
index a64fa5f54547..f788b3232f7e 100644
--- a/llvm/lib/Target/VE/VEInstrInfo.td
+++ b/llvm/lib/Target/VE/VEInstrInfo.td
@@ -533,6 +533,41 @@ multiclass RRCMOVm<string opcStr, bits<8>opc,
   }
 }
 
+// Multiclass for RR type instructions with only 2 operands
+//   Used by pcnt, brv
+let hasSideEffects = 0 in
+multiclass RRI2m<string opcStr, bits<8>opc, RegisterClass RC, ValueType Ty,
+                 Operand immOp2, SDPatternOperator OpNode=null_frag> {
+  def r : RR<
+    opc, (outs RC:$sx), (ins RC:$sz),
+    !strconcat(opcStr, " $sx, $sz"),
+    [(set Ty:$sx, (OpNode Ty:$sz))]> {
+    let cy = 1;
+    let cz = 1;
+  }
+  def i : RR<
+    opc, (outs RC:$sx), (ins RC:$sz),
+    !strconcat(opcStr, " $sx, $sz"),
+    [(set Ty:$sx, (OpNode Ty:$sz))]> {
+    let cy = 0;
+    let cz = 1;
+  }
+  def m0 : RR<
+    opc, (outs RC:$sx), (ins immOp2:$sz),
+    !strconcat(opcStr, " $sx, (${sz})0")> {
+    let cy = 1;
+    let cz = 0;
+    let sz{6} = 1;
+  }
+  def m1 : RR<
+    opc, (outs RC:$sx), (ins immOp2:$sz),
+    !strconcat(opcStr, " $sx, (${sz})1")> {
+    let cy = 1;
+    let cz = 0;
+  }
+}
+
+
 // Branch multiclass
 let isBranch = 1, isTerminator = 1, hasDelaySlot = 1 in
 multiclass BCRm<string opcStr, string opcStrAt, bits<8> opc,
@@ -760,6 +795,16 @@ let cx = 0 in {
   }
 }
 
+// Bits operations
+
+let cx = 0 in {
+  defm PCNT : RRI2m<"pcnt", 0x38, I64, i64, uimm6Op64, ctpop>;
+  defm BRV : RRI2m<"brv", 0x39, I64, i64, uimm6Op64, bitreverse>;
+  defm LDZ : RRI2m<"ldz", 0x67, I64, i64, uimm6Op64, ctlz>;
+  defm BSWP : RRIm<"bswp", 0x2B, I64, i64, simm7Op64, uimm6Op64>;
+}
+
+
 
 // 5.3.2.4 Shift Instructions
 
@@ -1426,6 +1471,19 @@ def : Pat<(f32 (bitconvert i32:$op)),
           (EXTRACT_SUBREG (SLLri (INSERT_SUBREG (i64 (IMPLICIT_DEF)),
             $op, sub_i32), 32), sub_f32)>;
 
+// Bits operations pattern matchings.
+def : Pat<(i32 (ctpop i32:$src)),
+          (EXTRACT_SUBREG (PCNTr (ANDrm0 (INSERT_SUBREG
+            (i64 (IMPLICIT_DEF)), $src, sub_i32), 32)), sub_i32)>;
+def : Pat<(i32 (ctlz i32:$src)),
+          (EXTRACT_SUBREG (LDZr (SLLri (INSERT_SUBREG
+            (i64 (IMPLICIT_DEF)), $src, sub_i32), 32)), sub_i32)>;
+def : Pat<(i64 (bswap i64:$src)),
+          (BSWPri $src, 0)>;
+def : Pat<(i32 (bswap i32:$src)),
+          (EXTRACT_SUBREG (BSWPri (INSERT_SUBREG
+            (i64 (IMPLICIT_DEF)), $src, sub_i32), 1), sub_i32)>;
+
 // Several special pattern matches to optimize code
 
 def : Pat<(i32 (and i32:$lhs, 0xff)),

diff  --git a/llvm/test/CodeGen/VE/bitreverse.ll b/llvm/test/CodeGen/VE/bitreverse.ll
new file mode 100644
index 000000000000..fce969af657e
--- /dev/null
+++ b/llvm/test/CodeGen/VE/bitreverse.ll
@@ -0,0 +1,100 @@
+; RUN: llc < %s -mtriple=ve-unknown-unknown | FileCheck %s
+
+define i64 @func1(i64 %p) {
+; CHECK-LABEL: func1:
+; CHECK:       .LBB{{[0-9]+}}_2:
+; CHECK-NEXT:    brv %s0, %s0
+; CHECK-NEXT:    or %s11, 0, %s9
+  %r = tail call i64 @llvm.bitreverse.i64(i64 %p)
+  ret i64 %r
+}
+
+declare i64 @llvm.bitreverse.i64(i64)
+
+define i32 @func2(i32 %p) {
+; CHECK-LABEL: func2:
+; CHECK:       .LBB{{[0-9]+}}_2:
+; CHECK-NEXT:    # kill: def $sw0 killed $sw0 def $sx0
+; CHECK-NEXT:    brv %s0, %s0
+; CHECK-NEXT:    srl %s0, %s0, 32
+; CHECK-NEXT:    adds.w.sx %s0, %s0, (0)1
+; CHECK-NEXT:    or %s11, 0, %s9
+  %r = tail call i32 @llvm.bitreverse.i32(i32 %p)
+  ret i32 %r
+}
+
+declare i32 @llvm.bitreverse.i32(i32)
+
+define signext i16 @func3(i16 signext %p) {
+; CHECK-LABEL: func3:
+; CHECK:       .LBB{{[0-9]+}}_2:
+; CHECK-NEXT:    # kill: def $sw0 killed $sw0 def $sx0
+; CHECK-NEXT:    brv %s0, %s0
+; CHECK-NEXT:    sra.l %s0, %s0, 48
+; CHECK-NEXT:    adds.w.sx %s0, %s0, (0)1
+; CHECK-NEXT:    or %s11, 0, %s9
+  %r = tail call i16 @llvm.bitreverse.i16(i16 %p)
+  ret i16 %r
+}
+
+declare i16 @llvm.bitreverse.i16(i16)
+
+define signext i8 @func4(i8 signext %p) {
+; CHECK-LABEL: func4:
+; CHECK:       .LBB{{[0-9]+}}_2:
+; CHECK-NEXT:    # kill: def $sw0 killed $sw0 def $sx0
+; CHECK-NEXT:    brv %s0, %s0
+; CHECK-NEXT:    sra.l %s0, %s0, 56
+; CHECK-NEXT:    adds.w.sx %s0, %s0, (0)1
+; CHECK-NEXT:    or %s11, 0, %s9
+  %r = tail call i8 @llvm.bitreverse.i8(i8 %p)
+  ret i8 %r
+}
+
+declare i8 @llvm.bitreverse.i8(i8)
+
+define i64 @func5(i64 %p) {
+; CHECK-LABEL: func5:
+; CHECK:       .LBB{{[0-9]+}}_2:
+; CHECK-NEXT:    brv %s0, %s0
+; CHECK-NEXT:    or %s11, 0, %s9
+  %r = tail call i64 @llvm.bitreverse.i64(i64 %p)
+  ret i64 %r
+}
+
+define i32 @func6(i32 %p) {
+; CHECK-LABEL: func6:
+; CHECK:       .LBB{{[0-9]+}}_2:
+; CHECK-NEXT:    # kill: def $sw0 killed $sw0 def $sx0
+; CHECK-NEXT:    brv %s0, %s0
+; CHECK-NEXT:    srl %s0, %s0, 32
+; CHECK-NEXT:    adds.w.sx %s0, %s0, (0)1
+; CHECK-NEXT:    or %s11, 0, %s9
+  %r = tail call i32 @llvm.bitreverse.i32(i32 %p)
+  ret i32 %r
+}
+
+define zeroext i16 @func7(i16 zeroext %p) {
+; CHECK-LABEL: func7:
+; CHECK:       .LBB{{[0-9]+}}_2:
+; CHECK-NEXT:    # kill: def $sw0 killed $sw0 def $sx0
+; CHECK-NEXT:    brv %s0, %s0
+; CHECK-NEXT:    srl %s0, %s0, 48
+; CHECK-NEXT:    adds.w.sx %s0, %s0, (0)1
+; CHECK-NEXT:    or %s11, 0, %s9
+  %r = tail call i16 @llvm.bitreverse.i16(i16 %p)
+  ret i16 %r
+}
+
+define zeroext i8 @func8(i8 zeroext %p) {
+; CHECK-LABEL: func8:
+; CHECK:       .LBB{{[0-9]+}}_2:
+; CHECK-NEXT:    # kill: def $sw0 killed $sw0 def $sx0
+; CHECK-NEXT:    brv %s0, %s0
+; CHECK-NEXT:    srl %s0, %s0, 56
+; CHECK-NEXT:    adds.w.sx %s0, %s0, (0)1
+; CHECK-NEXT:    or %s11, 0, %s9
+  %r = tail call i8 @llvm.bitreverse.i8(i8 %p)
+  ret i8 %r
+}
+

diff  --git a/llvm/test/CodeGen/VE/bswap.ll b/llvm/test/CodeGen/VE/bswap.ll
new file mode 100644
index 000000000000..274085462856
--- /dev/null
+++ b/llvm/test/CodeGen/VE/bswap.ll
@@ -0,0 +1,71 @@
+; RUN: llc < %s -mtriple=ve-unknown-unknown | FileCheck %s
+
+define i64 @func1(i64 %p) {
+; CHECK-LABEL: func1:
+; CHECK:       .LBB{{[0-9]+}}_2:
+; CHECK-NEXT:    bswp %s0, %s0, 0
+; CHECK-NEXT:    or %s11, 0, %s9
+  %r = tail call i64 @llvm.bswap.i64(i64 %p)
+  ret i64 %r
+}
+
+declare i64 @llvm.bswap.i64(i64)
+
+define i32 @func2(i32 %p) {
+; CHECK-LABEL: func2:
+; CHECK:       .LBB{{[0-9]+}}_2:
+; CHECK-NEXT:    # kill: def $sw0 killed $sw0 def $sx0
+; CHECK-NEXT:    bswp %s0, %s0, 1
+; CHECK-NEXT:    # kill: def $sw0 killed $sw0 killed $sx0
+; CHECK-NEXT:    or %s11, 0, %s9
+  %r = tail call i32 @llvm.bswap.i32(i32 %p)
+  ret i32 %r
+}
+
+declare i32 @llvm.bswap.i32(i32)
+
+define signext i16 @func3(i16 signext %p) {
+; CHECK-LABEL: func3:
+; CHECK:       .LBB{{[0-9]+}}_2:
+; CHECK-NEXT:    # kill: def $sw0 killed $sw0 def $sx0
+; CHECK-NEXT:    bswp %s0, %s0, 1
+; CHECK-NEXT:    sra.w.sx %s0, %s0, 16
+; CHECK-NEXT:    or %s11, 0, %s9
+  %r = tail call i16 @llvm.bswap.i16(i16 %p)
+  ret i16 %r
+}
+
+declare i16 @llvm.bswap.i16(i16)
+
+define i64 @func4(i64 %p) {
+; CHECK-LABEL: func4:
+; CHECK:       .LBB{{[0-9]+}}_2:
+; CHECK-NEXT:    bswp %s0, %s0, 0
+; CHECK-NEXT:    or %s11, 0, %s9
+  %r = tail call i64 @llvm.bswap.i64(i64 %p)
+  ret i64 %r
+}
+
+define i32 @func5(i32 %p) {
+; CHECK-LABEL: func5:
+; CHECK:       .LBB{{[0-9]+}}_2:
+; CHECK-NEXT:    # kill: def $sw0 killed $sw0 def $sx0
+; CHECK-NEXT:    bswp %s0, %s0, 1
+; CHECK-NEXT:    # kill: def $sw0 killed $sw0 killed $sx0
+; CHECK-NEXT:    or %s11, 0, %s9
+  %r = tail call i32 @llvm.bswap.i32(i32 %p)
+  ret i32 %r
+}
+
+define zeroext i16 @func6(i16 zeroext %p) {
+; CHECK-LABEL: func6:
+; CHECK:       .LBB{{[0-9]+}}_2:
+; CHECK-NEXT:    # kill: def $sw0 killed $sw0 def $sx0
+; CHECK-NEXT:    bswp %s0, %s0, 1
+; CHECK-NEXT:    and %s0, %s0, (32)0
+; CHECK-NEXT:    srl %s0, %s0, 16
+; CHECK-NEXT:    # kill: def $sw0 killed $sw0 killed $sx0
+; CHECK-NEXT:    or %s11, 0, %s9
+  %r = tail call i16 @llvm.bswap.i16(i16 %p)
+  ret i16 %r
+}

diff  --git a/llvm/test/CodeGen/VE/ctlz.ll b/llvm/test/CodeGen/VE/ctlz.ll
new file mode 100644
index 000000000000..0d0b2c3f6b0a
--- /dev/null
+++ b/llvm/test/CodeGen/VE/ctlz.ll
@@ -0,0 +1,54 @@
+; RUN: llc < %s -mtriple=ve-unknown-unknown | FileCheck %s
+
+define i64 @func1(i64 %p) {
+; CHECK-LABEL: func1:
+; CHECK:       .LBB{{[0-9]+}}_2:
+; CHECK-NEXT:    ldz %s0, %s0
+; CHECK-NEXT:    or %s11, 0, %s9
+  %r = tail call i64 @llvm.ctlz.i64(i64 %p, i1 true)
+  ret i64 %r
+}
+
+declare i64 @llvm.ctlz.i64(i64, i1)
+
+define i32 @func2(i32 %p) {
+; CHECK-LABEL: func2:
+; CHECK:       .LBB{{[0-9]+}}_2:
+; CHECK-NEXT:    # kill: def $sw0 killed $sw0 def $sx0
+; CHECK-NEXT:    sll %s0, %s0, 32
+; CHECK-NEXT:    ldz %s0, %s0
+; CHECK-NEXT:    # kill: def $sw0 killed $sw0 killed $sx0
+; CHECK-NEXT:    or %s11, 0, %s9
+  %r = tail call i32 @llvm.ctlz.i32(i32 %p, i1 true)
+  ret i32 %r
+}
+
+declare i32 @llvm.ctlz.i32(i32, i1)
+
+define i16 @func3(i16 %p) {
+; CHECK-LABEL: func3:
+; CHECK:       .LBB{{[0-9]+}}_2:
+; CHECK-NEXT:    and %s0, %s0, (48)0
+; CHECK-NEXT:    sll %s0, %s0, 32
+; CHECK-NEXT:    ldz %s0, %s0
+; CHECK-NEXT:    lea %s0, -16(%s0)
+; CHECK-NEXT:    or %s11, 0, %s9
+  %r = tail call i16 @llvm.ctlz.i16(i16 %p, i1 true)
+  ret i16 %r
+}
+
+declare i16 @llvm.ctlz.i16(i16, i1)
+
+define i8 @func4(i8 %p) {
+; CHECK-LABEL: func4:
+; CHECK:       .LBB{{[0-9]+}}_2:
+; CHECK-NEXT:    and %s0, %s0, (56)0
+; CHECK-NEXT:    sll %s0, %s0, 32
+; CHECK-NEXT:    ldz %s0, %s0
+; CHECK-NEXT:    lea %s0, -24(%s0)
+; CHECK-NEXT:    or %s11, 0, %s9
+  %r = tail call i8 @llvm.ctlz.i8(i8 %p, i1 true)
+  ret i8 %r
+}
+
+declare i8 @llvm.ctlz.i8(i8, i1)

diff  --git a/llvm/test/CodeGen/VE/ctpop.ll b/llvm/test/CodeGen/VE/ctpop.ll
new file mode 100644
index 000000000000..3d25909ab25c
--- /dev/null
+++ b/llvm/test/CodeGen/VE/ctpop.ll
@@ -0,0 +1,54 @@
+; RUN: llc < %s -mtriple=ve-unknown-unknown | FileCheck %s
+
+define i64 @func1(i64 %p) {
+; CHECK-LABEL: func1:
+; CHECK:       .LBB{{[0-9]+}}_2:
+; CHECK-NEXT:    pcnt %s0, %s0
+; CHECK-NEXT:    or %s11, 0, %s9
+  %r = tail call i64 @llvm.ctpop.i64(i64 %p)
+  ret i64 %r
+}
+
+declare i64 @llvm.ctpop.i64(i64 %p)
+
+define i32 @func2(i32 %p) {
+; CHECK-LABEL: func2:
+; CHECK:       .LBB{{[0-9]+}}_2:
+; CHECK-NEXT:    # kill: def $sw0 killed $sw0 def $sx0
+; CHECK-NEXT:    and %s0, %s0, (32)0
+; CHECK-NEXT:    pcnt %s0, %s0
+; CHECK-NEXT:    # kill: def $sw0 killed $sw0 killed $sx0
+; CHECK-NEXT:    or %s11, 0, %s9
+  %r = tail call i32 @llvm.ctpop.i32(i32 %p)
+  ret i32 %r
+}
+
+declare i32 @llvm.ctpop.i32(i32 %p)
+
+define i16 @func3(i16 %p) {
+; CHECK-LABEL: func3:
+; CHECK:       .LBB{{[0-9]+}}_2:
+; CHECK-NEXT:    and %s0, %s0, (48)0
+; CHECK-NEXT:    and %s0, %s0, (32)0
+; CHECK-NEXT:    pcnt %s0, %s0
+; CHECK-NEXT:    # kill: def $sw0 killed $sw0 killed $sx0
+; CHECK-NEXT:    or %s11, 0, %s9
+  %r = tail call i16 @llvm.ctpop.i16(i16 %p)
+  ret i16 %r
+}
+
+declare i16 @llvm.ctpop.i16(i16 %p)
+
+define i8 @func4(i8 %p) {
+; CHECK-LABEL: func4:
+; CHECK:       .LBB{{[0-9]+}}_2:
+; CHECK-NEXT:    and %s0, %s0, (56)0
+; CHECK-NEXT:    and %s0, %s0, (32)0
+; CHECK-NEXT:    pcnt %s0, %s0
+; CHECK-NEXT:    # kill: def $sw0 killed $sw0 killed $sx0
+; CHECK-NEXT:    or %s11, 0, %s9
+  %r = tail call i8 @llvm.ctpop.i8(i8 %p)
+  ret i8 %r
+}
+
+declare i8 @llvm.ctpop.i8(i8)

diff  --git a/llvm/test/CodeGen/VE/cttz.ll b/llvm/test/CodeGen/VE/cttz.ll
new file mode 100644
index 000000000000..0b0399523ab7
--- /dev/null
+++ b/llvm/test/CodeGen/VE/cttz.ll
@@ -0,0 +1,63 @@
+; RUN: llc < %s -mtriple=ve-unknown-unknown | FileCheck %s
+
+define i64 @func1(i64 %p) {
+; CHECK-LABEL: func1:
+; CHECK:       .LBB{{[0-9]+}}_2:
+; CHECK-NEXT:    lea %s1, -1(%s0)
+; CHECK-NEXT:    xor %s0, -1, %s0
+; CHECK-NEXT:    and %s0, %s0, %s1
+; CHECK-NEXT:    pcnt %s0, %s0
+; CHECK-NEXT:    or %s11, 0, %s9
+  %r = tail call i64 @llvm.cttz.i64(i64 %p, i1 true)
+  ret i64 %r
+}
+
+declare i64 @llvm.cttz.i64(i64, i1)
+
+define i32 @func2(i32 %p) {
+; CHECK-LABEL: func2:
+; CHECK:       .LBB{{[0-9]+}}_2:
+; CHECK-NEXT:    lea %s1, -1(%s0)
+; CHECK-NEXT:    xor %s0, -1, %s0
+; CHECK-NEXT:    and %s0, %s0, %s1
+; CHECK-NEXT:    and %s0, %s0, (32)0
+; CHECK-NEXT:    pcnt %s0, %s0
+; CHECK-NEXT:    # kill: def $sw0 killed $sw0 killed $sx0
+; CHECK-NEXT:    or %s11, 0, %s9
+  %r = tail call i32 @llvm.cttz.i32(i32 %p, i1 true)
+  ret i32 %r
+}
+
+declare i32 @llvm.cttz.i32(i32, i1)
+
+define i16 @func3(i16 %p) {
+; CHECK-LABEL: func3:
+; CHECK:       .LBB{{[0-9]+}}_2:
+; CHECK-NEXT:    lea %s1, -1(%s0)
+; CHECK-NEXT:    xor %s0, -1, %s0
+; CHECK-NEXT:    and %s0, %s0, %s1
+; CHECK-NEXT:    and %s0, %s0, (32)0
+; CHECK-NEXT:    pcnt %s0, %s0
+; CHECK-NEXT:    # kill: def $sw0 killed $sw0 killed $sx0
+; CHECK-NEXT:    or %s11, 0, %s9
+  %r = tail call i16 @llvm.cttz.i16(i16 %p, i1 true)
+  ret i16 %r
+}
+
+declare i16 @llvm.cttz.i16(i16, i1)
+
+define i8 @func4(i8 %p) {
+; CHECK-LABEL: func4:
+; CHECK:       .LBB{{[0-9]+}}_2:
+; CHECK-NEXT:    lea %s1, -1(%s0)
+; CHECK-NEXT:    xor %s0, -1, %s0
+; CHECK-NEXT:    and %s0, %s0, %s1
+; CHECK-NEXT:    and %s0, %s0, (32)0
+; CHECK-NEXT:    pcnt %s0, %s0
+; CHECK-NEXT:    # kill: def $sw0 killed $sw0 killed $sx0
+; CHECK-NEXT:    or %s11, 0, %s9
+  %r = tail call i8 @llvm.cttz.i8(i8 %p, i1 true)
+  ret i8 %r
+}
+
+declare i8 @llvm.cttz.i8(i8, i1)

diff  --git a/llvm/test/CodeGen/VE/rotl.ll b/llvm/test/CodeGen/VE/rotl.ll
new file mode 100644
index 000000000000..e7c498f1d34d
--- /dev/null
+++ b/llvm/test/CodeGen/VE/rotl.ll
@@ -0,0 +1,37 @@
+; RUN: llc < %s -mtriple=ve-unknown-unknown | FileCheck %s
+
+define i64 @func1(i64 %a, i32 %b) {
+; CHECK-LABEL: func1:
+; CHECK:       .LBB{{[0-9]+}}_2:
+; CHECK-NEXT:    sll %s2, %s0, %s1
+; CHECK-NEXT:    lea %s3, 64
+; CHECK-NEXT:    subs.w.sx %s1, %s3, %s1
+; CHECK-NEXT:    srl %s0, %s0, %s1
+; CHECK-NEXT:    or %s0, %s0, %s2
+; CHECK-NEXT:    or %s11, 0, %s9
+  %b64 = zext i32 %b to i64
+  %a.sl = shl i64 %a, %b64
+  %b.inv = sub nsw i32 64, %b
+  %b.inv64 = zext i32 %b.inv to i64
+  %a.sr = lshr i64 %a, %b.inv64
+  %r = or i64 %a.sr, %a.sl
+  ret i64 %r
+}
+
+define i32 @func2(i32 %a, i32 %b) {
+; CHECK-LABEL: func2:
+; CHECK:       .LBB{{[0-9]+}}_2:
+; CHECK-NEXT:    # kill: def $sw0 killed $sw0 def $sx0
+; CHECK-NEXT:    sla.w.sx %s2, %s0, %s1
+; CHECK-NEXT:    subs.w.sx %s1, 32, %s1
+; CHECK-NEXT:    and %s0, %s0, (32)0
+; CHECK-NEXT:    srl %s0, %s0, %s1
+; CHECK-NEXT:    or %s0, %s0, %s2
+; CHECK-NEXT:    or %s11, 0, %s9
+  %a.sl = shl i32 %a, %b
+  %b.inv = sub nsw i32 32, %b
+  %a.sr = lshr i32 %a, %b.inv
+  %r = or i32 %a.sr, %a.sl
+  ret i32 %r
+}
+

diff  --git a/llvm/test/CodeGen/VE/rotr.ll b/llvm/test/CodeGen/VE/rotr.ll
new file mode 100644
index 000000000000..40734a3d5178
--- /dev/null
+++ b/llvm/test/CodeGen/VE/rotr.ll
@@ -0,0 +1,36 @@
+; RUN: llc < %s -mtriple=ve-unknown-unknown | FileCheck %s
+
+define i64 @func1(i64 %a, i32 %b) {
+; CHECK-LABEL: func1:
+; CHECK:       .LBB{{[0-9]+}}_2:
+; CHECK-NEXT:    srl %s2, %s0, %s1
+; CHECK-NEXT:    lea %s3, 64
+; CHECK-NEXT:    subs.w.sx %s1, %s3, %s1
+; CHECK-NEXT:    sll %s0, %s0, %s1
+; CHECK-NEXT:    or %s0, %s0, %s2
+; CHECK-NEXT:    or %s11, 0, %s9
+  %b64 = zext i32 %b to i64
+  %a.lr = lshr i64 %a, %b64
+  %b.inv = sub nsw i32 64, %b
+  %b.inv64 = zext i32 %b.inv to i64
+  %a.sl = shl i64 %a, %b.inv64
+  %r = or i64 %a.sl, %a.lr
+  ret i64 %r
+}
+
+define i32 @func2(i32 %a, i32 %b) {
+; CHECK-LABEL: func2:
+; CHECK:       .LBB{{[0-9]+}}_2:
+; CHECK-NEXT:    # kill: def $sw0 killed $sw0 def $sx0
+; CHECK-NEXT:    and %s2, %s0, (32)0
+; CHECK-NEXT:    srl %s2, %s2, %s1
+; CHECK-NEXT:    subs.w.sx %s1, 32, %s1
+; CHECK-NEXT:    sla.w.sx %s0, %s0, %s1
+; CHECK-NEXT:    or %s0, %s0, %s2
+; CHECK-NEXT:    or %s11, 0, %s9
+  %a.lr = lshr i32 %a, %b
+  %b.inv = sub nsw i32 32, %b
+  %a.sl = shl i32 %a, %b.inv
+  %r = or i32 %a.sl, %a.lr
+  ret i32 %r
+}


        


More information about the llvm-commits mailing list