[llvm] [llvm][RISCV] Add RISCV vector tuple type to value types(MVT) (PR #97993)

Brandon Wu via llvm-commits llvm-commits at lists.llvm.org
Sat Aug 31 04:01:24 PDT 2024


https://github.com/4vtomat updated https://github.com/llvm/llvm-project/pull/97993

>From 8a6d23b45731888d5d803b9b09fd22ac3e18efb4 Mon Sep 17 00:00:00 2001
From: Brandon Wu <brandon.wu at sifive.com>
Date: Fri, 5 Jul 2024 01:17:29 -0700
Subject: [PATCH] [llvm][RISCV] Add RISCV vector tuple type to value types(MVT)

This patch handles the types(MVT) in `selectionDAG` for RISCV vector tuples.
As described in previous patch handling llvm types, the MVTs also have
32 variants:
```
riscv_nxv1i8x2, riscv_nxv1i8x3, riscv_nxv1i8x4, riscv_nxv1i8x5, riscv_nxv1i8x6, riscv_nxv1i8x7, riscv_nxv1i8x8,
riscv_nxv2i8x2, riscv_nxv2i8x3, riscv_nxv2i8x4, riscv_nxv2i8x5, riscv_nxv2i8x6, riscv_nxv2i8x7, riscv_nxv2i8x8,
riscv_nxv4i8x2, riscv_nxv4i8x3, riscv_nxv4i8x4, riscv_nxv4i8x5, riscv_nxv4i8x6, riscv_nxv4i8x7, riscv_nxv4i8x8,
riscv_nxv8i8x2, riscv_nxv8i8x3, riscv_nxv8i8x4, riscv_nxv8i8x5, riscv_nxv8i8x6, riscv_nxv8i8x7, riscv_nxv8i8x8,
riscv_nxv16i8x2, riscv_nxv16i8x3, riscv_nxv16i8x4,
riscv_nxv32i8x2.
```

An intuitive way to model vector tuple type is using nested scalable
vector, e.g. `nElts=NF, EltTy=nxv2i32`. However it's not compatible to
what we've done to handle scalable vector in TargetLowering, so it would
need more effort to change the code to handle this concept.
Another approach is encoding the `MinNumElts` info in `sz` of `MVT`, e.g.
`nElts=NF, sz=(NF*MinNumElts*8)`, this makes it much easier to handle and
changes less code.

This patch adopts the latter approach.
---
 llvm/include/llvm/CodeGen/ValueTypes.h        |  8 +++
 llvm/include/llvm/CodeGen/ValueTypes.td       | 65 +++++++++++++++----
 .../llvm/CodeGenTypes/MachineValueType.h      | 53 ++++++++++++---
 llvm/lib/CodeGen/ValueTypes.cpp               | 14 ++++
 llvm/utils/TableGen/Common/CodeGenTarget.cpp  |  2 +-
 llvm/utils/TableGen/VTEmitter.cpp             | 24 ++++++-
 6 files changed, 141 insertions(+), 25 deletions(-)

diff --git a/llvm/include/llvm/CodeGen/ValueTypes.h b/llvm/include/llvm/CodeGen/ValueTypes.h
index c7cad3d509750e..3db6f33a8093f0 100644
--- a/llvm/include/llvm/CodeGen/ValueTypes.h
+++ b/llvm/include/llvm/CodeGen/ValueTypes.h
@@ -175,6 +175,9 @@ namespace llvm {
       return isSimple() ? V.isScalableVector() : isExtendedScalableVector();
     }
 
+    /// Return true if this is a vector value type.
+    bool isRISCVVectorTuple() const { return V.isRISCVVectorTuple(); }
+
     bool isFixedLengthVector() const {
       return isSimple() ? V.isFixedLengthVector()
                         : isExtendedFixedLengthVector();
@@ -351,6 +354,11 @@ namespace llvm {
       return getVectorElementCount().getKnownMinValue();
     }
 
+    /// Given a RISCV vector tuple type, return the num_fields.
+    unsigned getRISCVVectorTupleNumFields() const {
+      return V.getRISCVVectorTupleNumFields();
+    }
+
     /// Return the size of the specified value type in bits.
     ///
     /// If the value type is a scalable vector type, the scalable property will
diff --git a/llvm/include/llvm/CodeGen/ValueTypes.td b/llvm/include/llvm/CodeGen/ValueTypes.td
index 0883f597dabc12..ea2c80eaf95836 100644
--- a/llvm/include/llvm/CodeGen/ValueTypes.td
+++ b/llvm/include/llvm/CodeGen/ValueTypes.td
@@ -23,6 +23,8 @@ class ValueType<int size, int value> {
   bit isFP = false;
   bit isVector = false;
   bit isScalable = false;
+  int NF = 0;
+  bit isRISCVVecTuple = false;
   // Indicates this VT should be included in the
   // [FIRST_VALUETYPE,LAST_VALUETYPE] range.
   bit isNormalValueType = true;
@@ -56,6 +58,13 @@ class VTScalableVec<int nelem, ValueType elt, int value>
   let isScalable = true;
 }
 
+class VTVecTup<int size, int nf, ValueType dummy_elt, int value>
+    : ValueType<size, value> {
+  let NF = nf;
+  let ElementType = dummy_elt;
+  let isRISCVVecTuple = true;
+}
+
 defset list<ValueType> ValueTypes = {
 
 def OtherVT : ValueType<0,   1> {  // "Other" value
@@ -273,20 +282,54 @@ def nxv2f64  : VTScalableVec<2,  f64, 187>;  // n x  2 x  f64 vector value
 def nxv4f64  : VTScalableVec<4,  f64, 188>;  // n x  4 x  f64 vector value
 def nxv8f64  : VTScalableVec<8,  f64, 189>;  // n x  8 x  f64 vector value
 
-def x86mmx    : ValueType<64,   190>;  // X86 MMX value
-def Glue      : ValueType<0,    191>;  // Pre-RA sched glue
-def isVoid    : ValueType<0,    192>;  // Produces no value
-def untyped   : ValueType<8,    193> { // Produces an untyped value
+// Sz = NF * MinNumElts * 8(bits)
+def riscv_nxv1i8x2   : VTVecTup<16, 2, i8, 190>;  // RISCV vector tuple(min_num_elts=1, nf=2)
+def riscv_nxv1i8x3   : VTVecTup<24, 3, i8, 191>;  // RISCV vector tuple(min_num_elts=1, nf=3)
+def riscv_nxv1i8x4   : VTVecTup<32, 4, i8, 192>;  // RISCV vector tuple(min_num_elts=1, nf=4)
+def riscv_nxv1i8x5   : VTVecTup<40, 5, i8, 193>;  // RISCV vector tuple(min_num_elts=1, nf=5)
+def riscv_nxv1i8x6   : VTVecTup<48, 6, i8, 194>;  // RISCV vector tuple(min_num_elts=1, nf=6)
+def riscv_nxv1i8x7   : VTVecTup<56, 7, i8, 195>;  // RISCV vector tuple(min_num_elts=1, nf=7)
+def riscv_nxv1i8x8   : VTVecTup<64, 8, i8, 196>;  // RISCV vector tuple(min_num_elts=1, nf=8)
+def riscv_nxv2i8x2   : VTVecTup<32, 2, i8, 197>;  // RISCV vector tuple(min_num_elts=2, nf=2)
+def riscv_nxv2i8x3   : VTVecTup<48, 3, i8, 198>;  // RISCV vector tuple(min_num_elts=2, nf=3)
+def riscv_nxv2i8x4   : VTVecTup<64, 4, i8, 199>;  // RISCV vector tuple(min_num_elts=2, nf=4)
+def riscv_nxv2i8x5   : VTVecTup<80, 5, i8, 200>;  // RISCV vector tuple(min_num_elts=2, nf=5)
+def riscv_nxv2i8x6   : VTVecTup<96, 6, i8, 201>;  // RISCV vector tuple(min_num_elts=2, nf=6)
+def riscv_nxv2i8x7   : VTVecTup<112, 7, i8, 202>; // RISCV vector tuple(min_num_elts=2, nf=7)
+def riscv_nxv2i8x8   : VTVecTup<128, 8, i8, 203>; // RISCV vector tuple(min_num_elts=2, nf=8)
+def riscv_nxv4i8x2   : VTVecTup<64, 2, i8, 204>;  // RISCV vector tuple(min_num_elts=4, nf=2)
+def riscv_nxv4i8x3   : VTVecTup<96, 3, i8, 205>;  // RISCV vector tuple(min_num_elts=4, nf=3)
+def riscv_nxv4i8x4   : VTVecTup<128, 4, i8, 206>; // RISCV vector tuple(min_num_elts=4, nf=4)
+def riscv_nxv4i8x5   : VTVecTup<160, 5, i8, 207>; // RISCV vector tuple(min_num_elts=4, nf=5)
+def riscv_nxv4i8x6   : VTVecTup<192, 6, i8, 208>; // RISCV vector tuple(min_num_elts=4, nf=6)
+def riscv_nxv4i8x7   : VTVecTup<224, 7, i8, 209>; // RISCV vector tuple(min_num_elts=4, nf=7)
+def riscv_nxv4i8x8   : VTVecTup<256, 8, i8, 210>; // RISCV vector tuple(min_num_elts=4, nf=8)
+def riscv_nxv8i8x2   : VTVecTup<128, 2, i8, 211>; // RISCV vector tuple(min_num_elts=8, nf=2)
+def riscv_nxv8i8x3   : VTVecTup<192, 3, i8, 212>; // RISCV vector tuple(min_num_elts=8, nf=3)
+def riscv_nxv8i8x4   : VTVecTup<256, 4, i8, 213>; // RISCV vector tuple(min_num_elts=8, nf=4)
+def riscv_nxv8i8x5   : VTVecTup<320, 5, i8, 214>; // RISCV vector tuple(min_num_elts=8, nf=5)
+def riscv_nxv8i8x6   : VTVecTup<384, 6, i8, 215>; // RISCV vector tuple(min_num_elts=8, nf=6)
+def riscv_nxv8i8x7   : VTVecTup<448, 7, i8, 216>; // RISCV vector tuple(min_num_elts=8, nf=7)
+def riscv_nxv8i8x8   : VTVecTup<512, 8, i8, 217>; // RISCV vector tuple(min_num_elts=8, nf=8)
+def riscv_nxv16i8x2  : VTVecTup<256, 2, i8, 218>; // RISCV vector tuple(min_num_elts=16, nf=2)
+def riscv_nxv16i8x3  : VTVecTup<384, 3, i8, 219>; // RISCV vector tuple(min_num_elts=16, nf=3)
+def riscv_nxv16i8x4  : VTVecTup<512, 4, i8, 220>; // RISCV vector tuple(min_num_elts=16, nf=4)
+def riscv_nxv32i8x2  : VTVecTup<512, 2, i8, 221>; // RISCV vector tuple(min_num_elts=32, nf=2)
+
+def x86mmx    : ValueType<64,   222>;  // X86 MMX value
+def Glue      : ValueType<0,    223>;  // Pre-RA sched glue
+def isVoid    : ValueType<0,    224>;  // Produces no value
+def untyped   : ValueType<8,    225> { // Produces an untyped value
   let LLVMName = "Untyped";
 }
-def funcref   : ValueType<0,    194>;  // WebAssembly's funcref type
-def externref : ValueType<0,    195>;  // WebAssembly's externref type
-def exnref    : ValueType<0,    196>;  // WebAssembly's exnref type
-def x86amx    : ValueType<8192, 197>;  // X86 AMX value
-def i64x8     : ValueType<512,  198>;  // 8 Consecutive GPRs (AArch64)
+def funcref   : ValueType<0,    226>;  // WebAssembly's funcref type
+def externref : ValueType<0,    227>;  // WebAssembly's externref type
+def exnref    : ValueType<0,    228>;  // WebAssembly's exnref type
+def x86amx    : ValueType<8192, 229>;  // X86 AMX value
+def i64x8     : ValueType<512,  230>;  // 8 Consecutive GPRs (AArch64)
 def aarch64svcount
-              : ValueType<16,  199>;  // AArch64 predicate-as-counter
-def spirvbuiltin : ValueType<0, 200>; // SPIR-V's builtin type
+              : ValueType<16,  231>;  // AArch64 predicate-as-counter
+def spirvbuiltin : ValueType<0, 232>; // SPIR-V's builtin type
 
 let isNormalValueType = false in {
 def token      : ValueType<0, 504>;  // TokenTy
diff --git a/llvm/include/llvm/CodeGenTypes/MachineValueType.h b/llvm/include/llvm/CodeGenTypes/MachineValueType.h
index 8bffdc31e5cdc5..c9a5098ef1623e 100644
--- a/llvm/include/llvm/CodeGenTypes/MachineValueType.h
+++ b/llvm/include/llvm/CodeGenTypes/MachineValueType.h
@@ -39,7 +39,8 @@ namespace llvm {
       // are considered extended value types.
       INVALID_SIMPLE_VALUE_TYPE = 0,
 
-#define GET_VT_ATTR(Ty, n, sz, Any, Int, FP, Vec, Sc, NElem, EltTy) Ty = n,
+#define GET_VT_ATTR(Ty, n, sz, Any, Int, FP, Vec, Sc, Tup, NF, NElem, EltTy) \
+    Ty = n,
 #define GET_VT_RANGES
 #include "llvm/CodeGen/GenVT.inc"
 #undef GET_VT_ATTR
@@ -114,6 +115,13 @@ namespace llvm {
               SimpleTy <= MVT::LAST_SCALABLE_VECTOR_VALUETYPE);
     }
 
+    /// Return true if this is a RISCV vector tuple type where the
+    /// runtime length is machine dependent
+    bool isRISCVVectorTuple() const {
+      return (SimpleTy >= MVT::FIRST_RISCV_VECTOR_TUPLE_VALUETYPE &&
+              SimpleTy <= MVT::LAST_RISCV_VECTOR_TUPLE_VALUETYPE);
+    }
+
     /// Return true if this is a custom target type that has a scalable size.
     bool isScalableTargetExtVT() const {
       return SimpleTy == MVT::aarch64svcount;
@@ -172,7 +180,7 @@ namespace llvm {
     /// Return true if this is an overloaded type for TableGen.
     bool isOverloaded() const {
       switch (SimpleTy) {
-#define GET_VT_ATTR(Ty, n, sz, Any, Int, FP, Vec, Sc, NElem, EltTy)          \
+#define GET_VT_ATTR(Ty, n, sz, Any, Int, FP, Vec, Sc, Tup, NF, NElem, EltTy) \
     case Ty:                                                                   \
       return Any;
 #include "llvm/CodeGen/GenVT.inc"
@@ -255,7 +263,8 @@ namespace llvm {
     MVT getVectorElementType() const {
       assert(SimpleTy >= FIRST_VALUETYPE && SimpleTy <= LAST_VALUETYPE);
       static constexpr SimpleValueType EltTyTable[] = {
-#define GET_VT_ATTR(Ty, N, Sz, Any, Int, FP, Vec, Sc, NElem, EltTy) EltTy,
+#define GET_VT_ATTR(Ty, N, Sz, Any, Int, FP, Vec, Sc, Tup, NF, NElem, EltTy) \
+    EltTy,
 #include "llvm/CodeGen/GenVT.inc"
 #undef GET_VT_ATTR
       };
@@ -268,7 +277,8 @@ namespace llvm {
     unsigned getVectorMinNumElements() const {
       assert(SimpleTy >= FIRST_VALUETYPE && SimpleTy <= LAST_VALUETYPE);
       static constexpr uint16_t NElemTable[] = {
-#define GET_VT_ATTR(Ty, N, Sz, Any, Int, FP, Vec, Sc, NElem, EltTy) NElem,
+#define GET_VT_ATTR(Ty, N, Sz, Any, Int, FP, Vec, Sc, Tup, NF, NElem, EltTy) \
+    NElem,
 #include "llvm/CodeGen/GenVT.inc"
 #undef GET_VT_ATTR
       };
@@ -297,7 +307,7 @@ namespace llvm {
     /// base size.
     TypeSize getSizeInBits() const {
       static constexpr TypeSize SizeTable[] = {
-#define GET_VT_ATTR(Ty, N, Sz, Any, Int, FP, Vec, Sc, NElem, EltTy)          \
+#define GET_VT_ATTR(Ty, N, Sz, Any, Int, FP, Vec, Sc, Tup, NF, NElem, EltTy) \
     TypeSize(Sz, Sc || Ty == aarch64svcount /* FIXME: Not in the td. */),
 #include "llvm/CodeGen/GenVT.inc"
 #undef GET_VT_ATTR
@@ -419,7 +429,7 @@ namespace llvm {
     }
 
     static MVT getFloatingPointVT(unsigned BitWidth) {
-#define GET_VT_ATTR(Ty, n, sz, Any, Int, FP, Vec, Sc, NElem, EltTy)          \
+#define GET_VT_ATTR(Ty, n, sz, Any, Int, FP, Vec, Sc, Tup, NF, NElem, EltTy) \
     if (FP == 3 && sz == BitWidth)                                             \
       return Ty;
 #include "llvm/CodeGen/GenVT.inc"
@@ -429,7 +439,7 @@ namespace llvm {
     }
 
     static MVT getIntegerVT(unsigned BitWidth) {
-#define GET_VT_ATTR(Ty, n, sz, Any, Int, FP, Vec, Sc, NElem, EltTy)          \
+#define GET_VT_ATTR(Ty, n, sz, Any, Int, FP, Vec, Sc, Tup, NF, NElem, EltTy) \
     if (Int == 3 && sz == BitWidth)                                            \
       return Ty;
 #include "llvm/CodeGen/GenVT.inc"
@@ -439,8 +449,8 @@ namespace llvm {
     }
 
     static MVT getVectorVT(MVT VT, unsigned NumElements) {
-#define GET_VT_VECATTR(Ty, Sc, nElem, ElTy)                                  \
-    if (!Sc && VT.SimpleTy == ElTy && NumElements == nElem)                    \
+#define GET_VT_VECATTR(Ty, Sc, Tup, nElem, ElTy)                             \
+    if (!Sc && !Tup && VT.SimpleTy == ElTy && NumElements == nElem)            \
       return Ty;
 #include "llvm/CodeGen/GenVT.inc"
 #undef GET_VT_VECATTR
@@ -449,7 +459,7 @@ namespace llvm {
     }
 
     static MVT getScalableVectorVT(MVT VT, unsigned NumElements) {
-#define GET_VT_VECATTR(Ty, Sc, nElem, ElTy)                                  \
+#define GET_VT_VECATTR(Ty, Sc, Tup, nElem, ElTy)                             \
     if (Sc && VT.SimpleTy == ElTy && NumElements == nElem)                     \
       return Ty;
 #include "llvm/CodeGen/GenVT.inc"
@@ -458,6 +468,29 @@ namespace llvm {
       return (MVT::SimpleValueType)(MVT::INVALID_SIMPLE_VALUE_TYPE);
     }
 
+    static MVT getRISCVVectorTupleVT(unsigned Sz, unsigned NFields) {
+#define GET_VT_ATTR(Ty, n, sz, Any, Int, FP, Vec, Sc, Tup, NF, nElem, EltTy) \
+    if (Tup && sz == Sz && NF == NFields)                                      \
+      return Ty;
+#include "llvm/CodeGen/GenVT.inc"
+#undef GET_VT_ATTR
+
+      llvm_unreachable("Invalid RISCV vector tuple type");
+    }
+
+    /// Given a RISC-V vector tuple type, return the num_fields.
+    unsigned getRISCVVectorTupleNumFields() const {
+      assert(isRISCVVectorTuple() && SimpleTy >= FIRST_VALUETYPE &&
+             SimpleTy <= LAST_VALUETYPE);
+      static constexpr uint8_t NFTable[] = {
+#define GET_VT_ATTR(Ty, N, Sz, Any, Int, FP, Vec, Sc, Tup, NF, NElem, EltTy) \
+    NF,
+#include "llvm/CodeGen/GenVT.inc"
+#undef GET_VT_ATTR
+      };
+      return NFTable[SimpleTy - FIRST_VALUETYPE];
+    }
+
     static MVT getVectorVT(MVT VT, unsigned NumElements, bool IsScalable) {
       if (IsScalable)
         return getScalableVectorVT(VT, NumElements);
diff --git a/llvm/lib/CodeGen/ValueTypes.cpp b/llvm/lib/CodeGen/ValueTypes.cpp
index c74ea5879acb54..e3c746b274dde1 100644
--- a/llvm/lib/CodeGen/ValueTypes.cpp
+++ b/llvm/lib/CodeGen/ValueTypes.cpp
@@ -162,6 +162,12 @@ TypeSize EVT::getExtendedSizeInBits() const {
 std::string EVT::getEVTString() const {
   switch (V.SimpleTy) {
   default:
+    if (isRISCVVectorTuple()) {
+      unsigned Sz = getSizeInBits();
+      unsigned NF = getRISCVVectorTupleNumFields();
+      unsigned MinNumElts = Sz / (NF * 8);
+      return "riscv_nxv" + utostr(MinNumElts) + "i8x" + utostr(NF);
+    }
     if (isVector())
       return (isScalableVector() ? "nxv" : "v") +
              utostr(getVectorElementCount().getKnownMinValue()) +
@@ -250,6 +256,14 @@ MVT MVT::getVT(Type *Ty, bool HandleUnknown){
       return MVT(MVT::aarch64svcount);
     else if (TargetExtTy->getName().starts_with("spirv."))
       return MVT(MVT::spirvbuiltin);
+    if (TargetExtTy->getName() == "riscv.vector.tuple") {
+      unsigned Sz = cast<ScalableVectorType>(TargetExtTy->getTypeParameter(0))
+                        ->getMinNumElements() *
+                    8;
+      unsigned NF = TargetExtTy->getIntParameter(0);
+
+      return MVT::getRISCVVectorTupleVT(Sz * NF, NF);
+    }
     if (HandleUnknown)
       return MVT(MVT::Other);
     llvm_unreachable("Unknown target ext type!");
diff --git a/llvm/utils/TableGen/Common/CodeGenTarget.cpp b/llvm/utils/TableGen/Common/CodeGenTarget.cpp
index 2b335c1e0f0029..8b9d97d5ad9c12 100644
--- a/llvm/utils/TableGen/Common/CodeGenTarget.cpp
+++ b/llvm/utils/TableGen/Common/CodeGenTarget.cpp
@@ -63,7 +63,7 @@ StringRef llvm::getName(MVT::SimpleValueType T) {
 StringRef llvm::getEnumName(MVT::SimpleValueType T) {
   // clang-format off
   switch (T) {
-#define GET_VT_ATTR(Ty, N, Sz, Any, Int, FP, Vec, Sc, NElem, EltTy)   \
+#define GET_VT_ATTR(Ty, N, Sz, Any, Int, FP, Vec, Sc, Tup, NF, NElem, EltTy)   \
   case MVT::Ty: return "MVT::" # Ty;
 #include "llvm/CodeGen/GenVT.inc"
   default: llvm_unreachable("ILLEGAL VALUE TYPE!");
diff --git a/llvm/utils/TableGen/VTEmitter.cpp b/llvm/utils/TableGen/VTEmitter.cpp
index eb58148e4e364a..b814f017053f9f 100644
--- a/llvm/utils/TableGen/VTEmitter.cpp
+++ b/llvm/utils/TableGen/VTEmitter.cpp
@@ -31,6 +31,17 @@ class VTEmitter {
 
 static void VTtoGetLLVMTyString(raw_ostream &OS, const Record *VT) {
   bool IsVector = VT->getValueAsBit("isVector");
+  bool IsRISCVVecTuple = VT->getValueAsBit("isRISCVVecTuple");
+
+  if (IsRISCVVecTuple) {
+    unsigned NElem = VT->getValueAsInt("nElem");
+    unsigned Sz = VT->getValueAsInt("Size");
+    OS << "TargetExtType::get(Context, \"riscv.vector.tuple\", "
+          "ScalableVectorType::get(Type::getInt8Ty(Context), "
+       << (Sz / (NElem * 8)) << "), " << NElem << ")";
+    return;
+  }
+
   if (IsVector)
     OS << (VT->getValueAsBit("isScalable") ? "Scalable" : "Fixed")
        << "VectorType::get(";
@@ -109,7 +120,7 @@ void VTEmitter::run(raw_ostream &OS) {
     }
   };
 
-  OS << "#ifdef GET_VT_ATTR // (Ty, n, sz, Any, Int, FP, Vec, Sc)\n";
+  OS << "#ifdef GET_VT_ATTR // (Ty, n, sz, Any, Int, FP, Vec, Sc, Tup, NF)\n";
   for (const auto *VT : VTsByNumber) {
     if (!VT)
       continue;
@@ -119,6 +130,8 @@ void VTEmitter::run(raw_ostream &OS) {
     bool IsFP = VT->getValueAsBit("isFP");
     bool IsVector = VT->getValueAsBit("isVector");
     bool IsScalable = VT->getValueAsBit("isScalable");
+    bool IsRISCVVecTuple = VT->getValueAsBit("isRISCVVecTuple");
+    int64_t NF = VT->getValueAsInt("NF");
     bool IsNormalValueType =  VT->getValueAsBit("isNormalValueType");
     int64_t NElem = IsVector ? VT->getValueAsInt("nElem") : 0;
     StringRef EltName = IsVector ? VT->getValueAsDef("ElementType")->getName()
@@ -133,6 +146,7 @@ void VTEmitter::run(raw_ostream &OS) {
     UpdateVTRange("FP_SCALABLE_VECTOR_VALUETYPE", Name, IsFP && IsScalable);
     UpdateVTRange("FIXEDLEN_VECTOR_VALUETYPE", Name, IsVector && !IsScalable);
     UpdateVTRange("SCALABLE_VECTOR_VALUETYPE", Name, IsScalable);
+    UpdateVTRange("RISCV_VECTOR_TUPLE_VALUETYPE", Name, IsRISCVVecTuple);
     UpdateVTRange("VECTOR_VALUETYPE", Name, IsVector);
     UpdateVTRange("INTEGER_VALUETYPE", Name, IsInteger && !IsVector);
     UpdateVTRange("FP_VALUETYPE", Name, IsFP && !IsVector);
@@ -148,6 +162,8 @@ void VTEmitter::run(raw_ostream &OS) {
        << (IsFP ? Name[0] == 'f' ? 3 : 1 : 0) << ", "
        << IsVector << ", "
        << IsScalable << ", "
+       << IsRISCVVecTuple << ", "
+       << NF << ", "
        << NElem << ", "
        << EltName << ")\n";
     // clang-format on
@@ -162,7 +178,7 @@ void VTEmitter::run(raw_ostream &OS) {
   }
   OS << "#endif\n\n";
 
-  OS << "#ifdef GET_VT_VECATTR // (Ty, Sc, nElem, ElTy)\n";
+  OS << "#ifdef GET_VT_VECATTR // (Ty, Sc, Tup, nElem, ElTy)\n";
   for (const auto *VT : VTsByNumber) {
     if (!VT || !VT->getValueAsBit("isVector"))
       continue;
@@ -172,6 +188,7 @@ void VTEmitter::run(raw_ostream &OS) {
     OS << "  GET_VT_VECATTR("
        << VT->getValueAsString("LLVMName") << ", "
        << VT->getValueAsBit("isScalable") << ", "
+       << VT->getValueAsBit("isRISCVVecTuple") << ", "
        << VT->getValueAsInt("nElem") << ", "
        << ElTy->getName() << ")\n";
     // clang-format on
@@ -185,8 +202,9 @@ void VTEmitter::run(raw_ostream &OS) {
     bool IsInteger = VT->getValueAsBit("isInteger");
     bool IsVector = VT->getValueAsBit("isVector");
     bool IsFP = VT->getValueAsBit("isFP");
+    bool IsRISCVVecTuple = VT->getValueAsBit("isRISCVVecTuple");
 
-    if (!IsInteger && !IsVector && !IsFP)
+    if (!IsInteger && !IsVector && !IsFP && !IsRISCVVecTuple)
       continue;
 
     OS << "  GET_VT_EVT(" << VT->getValueAsString("LLVMName") << ", ";



More information about the llvm-commits mailing list