[llvm-branch-commits] [llvm] 69c8d12 - [RISCV] Add intrinsics for vsetvli instruction

Craig Topper via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Fri Dec 18 13:01:31 PST 2020


Author: Craig Topper
Date: 2020-12-18T12:10:09-08:00
New Revision: 69c8d121f7f22e483e35a3d893052011ee70c23e

URL: https://github.com/llvm/llvm-project/commit/69c8d121f7f22e483e35a3d893052011ee70c23e
DIFF: https://github.com/llvm/llvm-project/commit/69c8d121f7f22e483e35a3d893052011ee70c23e.diff

LOG: [RISCV] Add intrinsics for vsetvli instruction

This patch adds two IR intrinsics for vsetvli instruction. One to set the vector length to a user specified value and one to set it to vlmax. The vlmax uses the X0 source register encoding.

Clang builtins will follow in a separate patch

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

Added: 
    llvm/test/CodeGen/RISCV/rvv/rv32-vsetvli-intrinsics.ll
    llvm/test/CodeGen/RISCV/rvv/rv64-vsetvli-intrinsics.ll

Modified: 
    llvm/include/llvm/IR/IntrinsicsRISCV.td
    llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
    llvm/lib/Target/RISCV/Utils/RISCVBaseInfo.cpp
    llvm/lib/Target/RISCV/Utils/RISCVBaseInfo.h

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/IR/IntrinsicsRISCV.td b/llvm/include/llvm/IR/IntrinsicsRISCV.td
index 3a089e0762f1..a6fbccdc75a0 100644
--- a/llvm/include/llvm/IR/IntrinsicsRISCV.td
+++ b/llvm/include/llvm/IR/IntrinsicsRISCV.td
@@ -79,6 +79,21 @@ class RISCVVIntrinsic {
 }
 
 let TargetPrefix = "riscv" in {
+  // We use anyint here but we only support XLen.
+  def int_riscv_vsetvli   : Intrinsic<[llvm_anyint_ty],
+                           /* AVL */  [LLVMMatchType<0>,
+                           /* VSEW */  LLVMMatchType<0>,
+                           /* VLMUL */ LLVMMatchType<0>],
+                                      [IntrNoMem, IntrHasSideEffects,
+                                       ImmArg<ArgIndex<1>>,
+                                       ImmArg<ArgIndex<2>>]>;
+  def int_riscv_vsetvlimax : Intrinsic<[llvm_anyint_ty],
+                            /* VSEW */ [LLVMMatchType<0>,
+                            /* VLMUL */ LLVMMatchType<0>],
+                                      [IntrNoMem, IntrHasSideEffects,
+                                       ImmArg<ArgIndex<0>>,
+                                       ImmArg<ArgIndex<1>>]>;
+
   // For unit stride load
   // Input: (pointer, vl)
   class RISCVUSLoad

diff  --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
index 1d7789b83fb9..f06f7ea3f2af 100644
--- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
@@ -14,6 +14,7 @@
 #include "MCTargetDesc/RISCVMCTargetDesc.h"
 #include "Utils/RISCVMatInt.h"
 #include "llvm/CodeGen/MachineFrameInfo.h"
+#include "llvm/IR/IntrinsicsRISCV.h"
 #include "llvm/Support/Alignment.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/MathExtras.h"
@@ -141,6 +142,70 @@ void RISCVDAGToDAGISel::Select(SDNode *Node) {
     }
     break;
   }
+  case ISD::INTRINSIC_W_CHAIN: {
+    unsigned IntNo = cast<ConstantSDNode>(Node->getOperand(1))->getZExtValue();
+    switch (IntNo) {
+      // By default we do not custom select any intrinsic.
+    default:
+      break;
+
+    case Intrinsic::riscv_vsetvli: {
+      if (!Subtarget->hasStdExtV())
+        break;
+
+      assert(Node->getNumOperands() == 5);
+
+      RISCVVSEW VSEW =
+          static_cast<RISCVVSEW>(Node->getConstantOperandVal(3) & 0x7);
+      RISCVVLMUL VLMul =
+          static_cast<RISCVVLMUL>(Node->getConstantOperandVal(4) & 0x7);
+
+      unsigned VTypeI = RISCVVType::encodeVTYPE(
+          VLMul, VSEW, /*TailAgnostic*/ true, /*MaskAgnostic*/ false);
+      SDValue VTypeIOp = CurDAG->getTargetConstant(VTypeI, DL, XLenVT);
+
+      SDValue VLOperand = Node->getOperand(2);
+      if (auto *C = dyn_cast<ConstantSDNode>(VLOperand)) {
+        if (C->isNullValue()) {
+          VLOperand = SDValue(
+              CurDAG->getMachineNode(RISCV::ADDI, DL, XLenVT,
+                                     CurDAG->getRegister(RISCV::X0, XLenVT),
+                                     CurDAG->getTargetConstant(0, DL, XLenVT)),
+              0);
+        }
+      }
+
+      ReplaceNode(Node,
+                  CurDAG->getMachineNode(RISCV::PseudoVSETVLI, DL, XLenVT,
+                                         MVT::Other, VLOperand, VTypeIOp,
+                                         /* Chain */ Node->getOperand(0)));
+      return;
+    }
+    case Intrinsic::riscv_vsetvlimax: {
+      if (!Subtarget->hasStdExtV())
+        break;
+
+      assert(Node->getNumOperands() == 4);
+
+      RISCVVSEW VSEW =
+          static_cast<RISCVVSEW>(Node->getConstantOperandVal(2) & 0x7);
+      RISCVVLMUL VLMul =
+          static_cast<RISCVVLMUL>(Node->getConstantOperandVal(3) & 0x7);
+
+      unsigned VTypeI = RISCVVType::encodeVTYPE(
+          VLMul, VSEW, /*TailAgnostic*/ true, /*MaskAgnostic*/ false);
+      SDValue VTypeIOp = CurDAG->getTargetConstant(VTypeI, DL, XLenVT);
+
+      SDValue VLOperand = CurDAG->getRegister(RISCV::X0, XLenVT);
+      ReplaceNode(Node,
+                  CurDAG->getMachineNode(RISCV::PseudoVSETVLI, DL, XLenVT,
+                                         MVT::Other, VLOperand, VTypeIOp,
+                                         /* Chain */ Node->getOperand(0)));
+      return;
+    }
+    }
+    break;
+  }
   }
 
   // Select the default instruction.

diff  --git a/llvm/lib/Target/RISCV/Utils/RISCVBaseInfo.cpp b/llvm/lib/Target/RISCV/Utils/RISCVBaseInfo.cpp
index cb2b3ee58384..fa36234d0f5f 100644
--- a/llvm/lib/Target/RISCV/Utils/RISCVBaseInfo.cpp
+++ b/llvm/lib/Target/RISCV/Utils/RISCVBaseInfo.cpp
@@ -109,6 +109,8 @@ void RISCVVType::printVType(unsigned VType, raw_ostream &OS) {
   OS << "e" << Sew;
 
   switch (VLMUL) {
+  case RISCVVLMUL::LMUL_RESERVED:
+    llvm_unreachable("Unexpected LMUL value!");
   case RISCVVLMUL::LMUL_1:
   case RISCVVLMUL::LMUL_2:
   case RISCVVLMUL::LMUL_4:

diff  --git a/llvm/lib/Target/RISCV/Utils/RISCVBaseInfo.h b/llvm/lib/Target/RISCV/Utils/RISCVBaseInfo.h
index 15c63750a1b9..b610661a3a84 100644
--- a/llvm/lib/Target/RISCV/Utils/RISCVBaseInfo.h
+++ b/llvm/lib/Target/RISCV/Utils/RISCVBaseInfo.h
@@ -346,7 +346,8 @@ enum class RISCVVLMUL {
   LMUL_2,
   LMUL_4,
   LMUL_8,
-  LMUL_F8 = 5,
+  LMUL_RESERVED,
+  LMUL_F8,
   LMUL_F4,
   LMUL_F2
 };

diff  --git a/llvm/test/CodeGen/RISCV/rvv/rv32-vsetvli-intrinsics.ll b/llvm/test/CodeGen/RISCV/rvv/rv32-vsetvli-intrinsics.ll
new file mode 100644
index 000000000000..d724d0df9692
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/rvv/rv32-vsetvli-intrinsics.ll
@@ -0,0 +1,33 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=riscv32 -mattr=+experimental-v -verify-machineinstrs < %s | FileCheck %s
+
+declare i32 @llvm.riscv.vsetvli.i32(i32, i32, i32)
+declare i32 @llvm.riscv.vsetvlimax.i32(i32, i32)
+
+define void @test_vsetvli_e64mf8(i32 %avl) nounwind {
+; CHECK-LABEL: test_vsetvli_e64mf8:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    vsetvli a0, a0, e64,mf8,ta,mu
+; CHECK-NEXT:    ret
+  call i32 @llvm.riscv.vsetvli.i32(i32 %avl, i32 3, i32 5)
+  ret void
+}
+
+define void @test_vsetvli_e8mf2_zero_avl() nounwind {
+; CHECK-LABEL: test_vsetvli_e8mf2_zero_avl:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    mv a0, zero
+; CHECK-NEXT:    vsetvli a0, a0, e8,mf2,ta,mu
+; CHECK-NEXT:    ret
+  call i32 @llvm.riscv.vsetvli.i32(i32 0, i32 0, i32 7)
+  ret void
+}
+
+define void @test_vsetvlimax_e64m8() nounwind {
+; CHECK-LABEL: test_vsetvlimax_e64m8:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    vsetvli a0, zero, e64,m8,ta,mu
+; CHECK-NEXT:    ret
+  call i32 @llvm.riscv.vsetvlimax.i32(i32 3, i32 3)
+  ret void
+}

diff  --git a/llvm/test/CodeGen/RISCV/rvv/rv64-vsetvli-intrinsics.ll b/llvm/test/CodeGen/RISCV/rvv/rv64-vsetvli-intrinsics.ll
new file mode 100644
index 000000000000..c28058c16efb
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/rvv/rv64-vsetvli-intrinsics.ll
@@ -0,0 +1,51 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=riscv64 -mattr=+experimental-v -verify-machineinstrs < %s | FileCheck %s
+
+declare i64 @llvm.riscv.vsetvli.i64(i64, i64, i64)
+declare i64 @llvm.riscv.vsetvlimax.i64(i64, i64)
+
+define void @test_vsetvli_e8m1(i64 %avl) nounwind {
+; CHECK-LABEL: test_vsetvli_e8m1:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    vsetvli a0, a0, e8,m1,ta,mu
+; CHECK-NEXT:    ret
+  call i64 @llvm.riscv.vsetvli.i64(i64 %avl, i64 0, i64 0)
+  ret void
+}
+
+define void @test_vsetvli_e16mf4(i64 %avl) nounwind {
+; CHECK-LABEL: test_vsetvli_e16mf4:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    vsetvli a0, a0, e16,mf4,ta,mu
+; CHECK-NEXT:    ret
+  call i64 @llvm.riscv.vsetvli.i64(i64 %avl, i64 1, i64 6)
+  ret void
+}
+
+define void @test_vsetvli_e32mf8_zero_avl() nounwind {
+; CHECK-LABEL: test_vsetvli_e32mf8_zero_avl:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    mv a0, zero
+; CHECK-NEXT:    vsetvli a0, a0, e16,mf4,ta,mu
+; CHECK-NEXT:    ret
+  call i64 @llvm.riscv.vsetvli.i64(i64 0, i64 1, i64 6)
+  ret void
+}
+
+define void @test_vsetvlimax_e32m2() nounwind {
+; CHECK-LABEL: test_vsetvlimax_e32m2:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    vsetvli a0, zero, e32,m2,ta,mu
+; CHECK-NEXT:    ret
+  call i64 @llvm.riscv.vsetvlimax.i64(i64 2, i64 1)
+  ret void
+}
+
+define void @test_vsetvlimax_e64m4() nounwind {
+; CHECK-LABEL: test_vsetvlimax_e64m4:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    vsetvli a0, zero, e64,m4,ta,mu
+; CHECK-NEXT:    ret
+  call i64 @llvm.riscv.vsetvlimax.i64(i64 3, i64 2)
+  ret void
+}


        


More information about the llvm-branch-commits mailing list