[clang] 0019226 - [3/11][POC][Clang][RISCV] Add typedef of the tuple type and define tuple type variant of vlseg2e32
via cfe-commits
cfe-commits at lists.llvm.org
Mon May 22 02:51:20 PDT 2023
Author: eopXD
Date: 2023-05-22T02:51:14-07:00
New Revision: 0019226ceef779c7d9aa55f2f56b30e948cc9251
URL: https://github.com/llvm/llvm-project/commit/0019226ceef779c7d9aa55f2f56b30e948cc9251
DIFF: https://github.com/llvm/llvm-project/commit/0019226ceef779c7d9aa55f2f56b30e948cc9251.diff
LOG: [3/11][POC][Clang][RISCV] Add typedef of the tuple type and define tuple type variant of vlseg2e32
For the cover letter of this patch-set, please checkout D146872.
Depends on D146873.
This is the 3rd patch of the patch-set. This patch originates from
D99593.
Note: This patch is a proof-of-concept and will be extended to full
coverage in the future. Currently, the old non-tuple unit-stride
segment load is not removed, and only signed integer unit-strided
segment load of NF=2, EEW=32 is defined here.
When replacing the old intrinsics, the extra `IsTuple` parameter under
various places will be redundant and removed.
Authored-by: eop Chen <eop.chen at sifive.com>
Co-Authored-by: Hsiangkai Wang <kai.wang at sifive.com>
Reviewed By: craig.topper
Differential Revision: https://reviews.llvm.org/D147731
Added:
clang/test/CodeGen/RISCV/rvv-intrinsics-autogenerated/non-policy/non-overloaded/vlseg2e32_tuple.c
Modified:
clang/include/clang/AST/ASTContext.h
clang/include/clang/Basic/riscv_vector.td
clang/include/clang/Basic/riscv_vector_common.td
clang/include/clang/Support/RISCVVIntrinsicUtils.h
clang/lib/AST/ASTContext.cpp
clang/lib/Sema/SemaRISCVVectorLookup.cpp
clang/lib/Support/RISCVVIntrinsicUtils.cpp
clang/utils/TableGen/RISCVVEmitter.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index 06ba21a3bf391..bc4a0df296d71 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -1472,9 +1472,12 @@ class ASTContext : public RefCountedBase<ASTContext> {
/// Return the unique reference to a scalable vector type of the specified
/// element type and scalable number of elements.
+ /// For RISC-V, number of fields is also provided when it fetching for
+ /// tuple type.
///
/// \pre \p EltTy must be a built-in type.
- QualType getScalableVectorType(QualType EltTy, unsigned NumElts) const;
+ QualType getScalableVectorType(QualType EltTy, unsigned NumElts,
+ unsigned NumFields = 1) const;
/// Return a WebAssembly externref type.
QualType getWebAssemblyExternrefType() const;
diff --git a/clang/include/clang/Basic/riscv_vector.td b/clang/include/clang/Basic/riscv_vector.td
index 4fd769e0680d5..278b1cef74c71 100644
--- a/clang/include/clang/Basic/riscv_vector.td
+++ b/clang/include/clang/Basic/riscv_vector.td
@@ -1503,6 +1503,58 @@ defm : RVVStridedSegLoad<"vlsseg">;
defm : RVVIndexedSegLoad<"vluxseg">;
defm : RVVIndexedSegLoad<"vloxseg">;
}
+
+multiclass RVVUnitStridedSegLoadTuple<string op> {
+ foreach type = ["i"] in {
+ defvar eew = !cond(!eq(type, "i") : "32");
+ foreach nf = [2] in {
+ let Name = op # nf # "e" # eew # "_v_tuple",
+ OverloadedName = op # nf # "e" # eew # "_tuple",
+ IRName = op # nf,
+ MaskedIRName = op # nf # "_mask",
+ NF = nf,
+ ManualCodegen = [{
+ {
+ assert(((IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) ||
+ (!IsMasked && (PolicyAttrs & RVV_VTA))) &&
+ "FIXME: Only handling default policy (TAMA) for now");
+
+ llvm::Type *ElementVectorType = cast<StructType>(ResultType)->elements()[0];
+ IntrinsicTypes = {ElementVectorType, Ops.back()->getType()};
+ SmallVector<llvm::Value*, 12> Operands;
+
+ Operands.append(NF, llvm::PoisonValue::get(ElementVectorType));
+
+ unsigned Offset = IsMasked ? 1 : 0;
+ Operands.push_back(Ops[Offset]); // Ptr
+ if (IsMasked)
+ Operands.push_back(Ops[0]);
+ Operands.push_back(Ops[Offset + 1]); // VL
+ if (IsMasked)
+ Operands.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs));
+
+ llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
+
+ llvm::Value *LoadValue = Builder.CreateCall(F, Operands, "");
+ if (ReturnValue.isNull())
+ return LoadValue;
+ else
+ return Builder.CreateStore(LoadValue, ReturnValue.getValue());
+ }
+ }] in {
+ defvar T = "(Tuple:" # nf # ")";
+ def : RVVBuiltin<"v", T # "vPCe", type>;
+ }
+ }
+ }
+}
+// TODO: Extend for policy
+let UnMaskedPolicyScheme = NonePolicy,
+ MaskedPolicyScheme = NonePolicy,
+ IsTuple = true in {
+defm : RVVUnitStridedSegLoadTuple<"vlseg">;
+}
+
let UnMaskedPolicyScheme = NonePolicy,
MaskedPolicyScheme = NonePolicy in {
defm : RVVUnitStridedSegStore<"vsseg">;
diff --git a/clang/include/clang/Basic/riscv_vector_common.td b/clang/include/clang/Basic/riscv_vector_common.td
index 6fd1dbde52be4..f98432839f1d2 100644
--- a/clang/include/clang/Basic/riscv_vector_common.td
+++ b/clang/include/clang/Basic/riscv_vector_common.td
@@ -231,6 +231,9 @@ class RVVBuiltin<string suffix, string prototype, string type_range,
// Number of fields for Load/Store Segment instructions.
int NF = 1;
+
+ // Set to true if the builtin is associated with tuple types.
+ bit IsTuple = false;
}
// This is the code emitted in the header.
diff --git a/clang/include/clang/Support/RISCVVIntrinsicUtils.h b/clang/include/clang/Support/RISCVVIntrinsicUtils.h
index 1a626e6a776a8..07c6bbad5edde 100644
--- a/clang/include/clang/Support/RISCVVIntrinsicUtils.h
+++ b/clang/include/clang/Support/RISCVVIntrinsicUtils.h
@@ -58,6 +58,7 @@ enum class VectorTypeModifier : uint8_t {
SFixedLog2LMUL1,
SFixedLog2LMUL2,
SFixedLog2LMUL3,
+ Tuple2,
};
// Similar to basic type but used to describe what's kind of type related to
@@ -243,6 +244,8 @@ class RVVType {
unsigned ElementBitwidth = 0;
VScaleVal Scale = 0;
bool Valid;
+ bool IsTuple = false;
+ unsigned NF = 0;
std::string BuiltinStr;
std::string ClangBuiltinStr;
@@ -293,10 +296,15 @@ class RVVType {
}
bool isConstant() const { return IsConstant; }
bool isPointer() const { return IsPointer; }
+ bool isTuple() const { return IsTuple; }
unsigned getElementBitwidth() const { return ElementBitwidth; }
ScalarTypeKind getScalarType() const { return ScalarType; }
VScaleVal getScale() const { return Scale; }
+ unsigned getNF() const {
+ assert(NF > 1 && NF < 8 && "Only legal NF should be fetched");
+ return NF;
+ }
private:
// Verify RVV vector type and set Valid.
@@ -373,6 +381,7 @@ class RVVIntrinsic {
std::vector<int64_t> IntrinsicTypes;
unsigned NF = 1;
Policy PolicyAttrs;
+ bool IsTuple = false;
public:
RVVIntrinsic(llvm::StringRef Name, llvm::StringRef Suffix,
@@ -383,7 +392,7 @@ class RVVIntrinsic {
const RVVTypes &Types,
const std::vector<int64_t> &IntrinsicTypes,
const std::vector<llvm::StringRef> &RequiredFeatures,
- unsigned NF, Policy PolicyAttrs);
+ unsigned NF, Policy PolicyAttrs, bool IsTuple);
~RVVIntrinsic() = default;
RVVTypePtr getOutputType() const { return OutputType; }
@@ -444,7 +453,7 @@ class RVVIntrinsic {
computeBuiltinTypes(llvm::ArrayRef<PrototypeDescriptor> Prototype,
bool IsMasked, bool HasMaskedOffOperand, bool HasVL,
unsigned NF, PolicyScheme DefaultScheme,
- Policy PolicyAttrs);
+ Policy PolicyAttrs, bool IsTuple);
static llvm::SmallVector<Policy> getSupportedUnMaskedPolicies();
static llvm::SmallVector<Policy>
@@ -512,6 +521,7 @@ struct RVVIntrinsicRecord {
bool HasMaskedOffOperand : 1;
bool HasTailPolicy : 1;
bool HasMaskPolicy : 1;
+ bool IsTuple : 1;
uint8_t UnMaskedPolicyScheme : 2;
uint8_t MaskedPolicyScheme : 2;
};
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 9c247b3c439a8..ad1e940c4bda6 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -4042,8 +4042,8 @@ QualType ASTContext::getWebAssemblyExternrefType() const {
/// getScalableVectorType - Return the unique reference to a scalable vector
/// type of the specified element type and size. VectorType must be a built-in
/// type.
-QualType ASTContext::getScalableVectorType(QualType EltTy,
- unsigned NumElts) const {
+QualType ASTContext::getScalableVectorType(QualType EltTy, unsigned NumElts,
+ unsigned NumFields) const {
if (Target->hasAArch64SVETypes()) {
uint64_t EltTySize = getTypeSize(EltTy);
#define SVE_VECTOR_TYPE(Name, MangledName, Id, SingletonId, NumEls, ElBits, \
@@ -4067,15 +4067,15 @@ QualType ASTContext::getScalableVectorType(QualType EltTy,
uint64_t EltTySize = getTypeSize(EltTy);
#define RVV_VECTOR_TYPE(Name, Id, SingletonId, NumEls, ElBits, NF, IsSigned, \
IsFP) \
- if (!EltTy->isBooleanType() && \
- ((EltTy->hasIntegerRepresentation() && \
- EltTy->hasSignedIntegerRepresentation() == IsSigned) || \
- (EltTy->hasFloatingRepresentation() && IsFP)) && \
- EltTySize == ElBits && NumElts == NumEls) \
- return SingletonId;
+ if (!EltTy->isBooleanType() && \
+ ((EltTy->hasIntegerRepresentation() && \
+ EltTy->hasSignedIntegerRepresentation() == IsSigned) || \
+ (EltTy->hasFloatingRepresentation() && IsFP)) && \
+ EltTySize == ElBits && NumElts == NumEls && NumFields == NF) \
+ return SingletonId;
#define RVV_PREDICATE_TYPE(Name, Id, SingletonId, NumEls) \
- if (EltTy->isBooleanType() && NumElts == NumEls) \
- return SingletonId;
+ if (EltTy->isBooleanType() && NumElts == NumEls) \
+ return SingletonId;
#include "clang/Basic/RISCVVTypes.def"
}
return QualType();
diff --git a/clang/lib/Sema/SemaRISCVVectorLookup.cpp b/clang/lib/Sema/SemaRISCVVectorLookup.cpp
index 981ab5f13716d..5599b9277cd79 100644
--- a/clang/lib/Sema/SemaRISCVVectorLookup.cpp
+++ b/clang/lib/Sema/SemaRISCVVectorLookup.cpp
@@ -135,8 +135,12 @@ static QualType RVVType2Qual(ASTContext &Context, const RVVType *Type) {
case Invalid:
llvm_unreachable("Unhandled type.");
}
- if (Type->isVector())
- QT = Context.getScalableVectorType(QT, *Type->getScale());
+ if (Type->isVector()) {
+ if (Type->isTuple())
+ QT = Context.getScalableVectorType(QT, *Type->getScale(), Type->getNF());
+ else
+ QT = Context.getScalableVectorType(QT, *Type->getScale());
+ }
if (Type->isConstant())
QT = Context.getConstType(QT);
@@ -214,15 +218,16 @@ void RISCVIntrinsicManagerImpl::InitIntrinsicList() {
const Policy DefaultPolicy;
llvm::SmallVector<PrototypeDescriptor> ProtoSeq =
- RVVIntrinsic::computeBuiltinTypes(BasicProtoSeq, /*IsMasked=*/false,
- /*HasMaskedOffOperand=*/false,
- Record.HasVL, Record.NF,
- UnMaskedPolicyScheme, DefaultPolicy);
+ RVVIntrinsic::computeBuiltinTypes(
+ BasicProtoSeq, /*IsMasked=*/false,
+ /*HasMaskedOffOperand=*/false, Record.HasVL, Record.NF,
+ UnMaskedPolicyScheme, DefaultPolicy, Record.IsTuple);
llvm::SmallVector<PrototypeDescriptor> ProtoMaskSeq =
RVVIntrinsic::computeBuiltinTypes(
BasicProtoSeq, /*IsMasked=*/true, Record.HasMaskedOffOperand,
- Record.HasVL, Record.NF, MaskedPolicyScheme, DefaultPolicy);
+ Record.HasVL, Record.NF, MaskedPolicyScheme, DefaultPolicy,
+ Record.IsTuple);
bool UnMaskedHasPolicy = UnMaskedPolicyScheme != PolicyScheme::SchemeNone;
bool MaskedHasPolicy = MaskedPolicyScheme != PolicyScheme::SchemeNone;
@@ -280,7 +285,7 @@ void RISCVIntrinsicManagerImpl::InitIntrinsicList() {
RVVIntrinsic::computeBuiltinTypes(
BasicProtoSeq, /*IsMasked=*/false,
/*HasMaskedOffOperand=*/false, Record.HasVL, Record.NF,
- UnMaskedPolicyScheme, P);
+ UnMaskedPolicyScheme, P, Record.IsTuple);
std::optional<RVVTypes> PolicyTypes = TypeCache.computeTypes(
BaseType, Log2LMUL, Record.NF, PolicyPrototype);
InitRVVIntrinsic(Record, SuffixStr, OverloadedSuffixStr,
@@ -301,8 +306,9 @@ void RISCVIntrinsicManagerImpl::InitIntrinsicList() {
for (auto P : SupportedMaskedPolicies) {
llvm::SmallVector<PrototypeDescriptor> PolicyPrototype =
RVVIntrinsic::computeBuiltinTypes(
- BasicProtoSeq, /*IsMasked=*/true, Record.HasMaskedOffOperand,
- Record.HasVL, Record.NF, MaskedPolicyScheme, P);
+ BasicProtoSeq, /*IsMasked=*/true,
+ Record.HasMaskedOffOperand, Record.HasVL, Record.NF,
+ MaskedPolicyScheme, P, Record.IsTuple);
std::optional<RVVTypes> PolicyTypes = TypeCache.computeTypes(
BaseType, Log2LMUL, Record.NF, PolicyPrototype);
InitRVVIntrinsic(Record, SuffixStr, OverloadedSuffixStr,
diff --git a/clang/lib/Support/RISCVVIntrinsicUtils.cpp b/clang/lib/Support/RISCVVIntrinsicUtils.cpp
index 86da7e86f8315..a41c77d40020c 100644
--- a/clang/lib/Support/RISCVVIntrinsicUtils.cpp
+++ b/clang/lib/Support/RISCVVIntrinsicUtils.cpp
@@ -113,6 +113,8 @@ bool RVVType::verifyType() const {
return false;
if (isFloat() && ElementBitwidth == 8)
return false;
+ if (IsTuple && (NF == 1 || NF > 8))
+ return false;
unsigned V = *Scale;
switch (ElementBitwidth) {
case 1:
@@ -214,6 +216,9 @@ void RVVType::initBuiltinStr() {
// vector values.
if (IsPointer)
BuiltinStr += "*";
+
+ if (IsTuple)
+ BuiltinStr = "T" + utostr(NF) + BuiltinStr;
}
void RVVType::initClangBuiltinStr() {
@@ -237,7 +242,8 @@ void RVVType::initClangBuiltinStr() {
default:
llvm_unreachable("ScalarTypeKind is invalid");
}
- ClangBuiltinStr += utostr(ElementBitwidth) + LMUL.str() + "_t";
+ ClangBuiltinStr += utostr(ElementBitwidth) + LMUL.str() +
+ (IsTuple ? "x" + utostr(NF) : "") + "_t";
}
void RVVType::initTypeStr() {
@@ -249,7 +255,8 @@ void RVVType::initTypeStr() {
auto getTypeString = [&](StringRef TypeStr) {
if (isScalar())
return Twine(TypeStr + Twine(ElementBitwidth) + "_t").str();
- return Twine("v" + TypeStr + Twine(ElementBitwidth) + LMUL.str() + "_t")
+ return Twine("v" + TypeStr + Twine(ElementBitwidth) + LMUL.str() +
+ (IsTuple ? "x" + utostr(NF) : "") + "_t")
.str();
};
@@ -542,6 +549,19 @@ PrototypeDescriptor::parsePrototypeDescriptor(
return std::nullopt;
}
+ } else if (ComplexTT.first == "Tuple") {
+ unsigned NF = 0;
+ if (ComplexTT.second.getAsInteger(10, NF)) {
+ llvm_unreachable("Invalid NF value!");
+ return std::nullopt;
+ }
+ switch (NF) {
+ case 2:
+ VTM = VectorTypeModifier::Tuple2;
+ break;
+ default:
+ llvm_unreachable("Unhandled NF");
+ }
} else {
llvm_unreachable("Illegal complex type transformers!");
}
@@ -702,6 +722,11 @@ void RVVType::applyModifier(const PrototypeDescriptor &Transformer) {
case VectorTypeModifier::SFixedLog2LMUL3:
applyFixedLog2LMUL(3, FixedLMULType::SmallerThan);
break;
+ case VectorTypeModifier::Tuple2: {
+ IsTuple = true;
+ NF = 2;
+ break;
+ }
case VectorTypeModifier::NoModifier:
break;
}
@@ -852,11 +877,12 @@ RVVIntrinsic::RVVIntrinsic(StringRef NewName, StringRef Suffix,
const RVVTypes &OutInTypes,
const std::vector<int64_t> &NewIntrinsicTypes,
const std::vector<StringRef> &RequiredFeatures,
- unsigned NF, Policy NewPolicyAttrs)
+ unsigned NF, Policy NewPolicyAttrs, bool IsTuple)
: IRName(IRName), IsMasked(IsMasked),
HasMaskedOffOperand(HasMaskedOffOperand), HasVL(HasVL), Scheme(Scheme),
SupportOverloading(SupportOverloading), HasBuiltinAlias(HasBuiltinAlias),
- ManualCodegen(ManualCodegen.str()), NF(NF), PolicyAttrs(NewPolicyAttrs) {
+ ManualCodegen(ManualCodegen.str()), NF(NF), PolicyAttrs(NewPolicyAttrs),
+ IsTuple(IsTuple) {
// Init BuiltinName, Name and OverloadedName
BuiltinName = NewName.str();
@@ -912,7 +938,7 @@ std::string RVVIntrinsic::getSuffixStr(
llvm::SmallVector<PrototypeDescriptor> RVVIntrinsic::computeBuiltinTypes(
llvm::ArrayRef<PrototypeDescriptor> Prototype, bool IsMasked,
bool HasMaskedOffOperand, bool HasVL, unsigned NF,
- PolicyScheme DefaultScheme, Policy PolicyAttrs) {
+ PolicyScheme DefaultScheme, Policy PolicyAttrs, bool IsTuple) {
SmallVector<PrototypeDescriptor> NewPrototype(Prototype.begin(),
Prototype.end());
bool HasPassthruOp = DefaultScheme == PolicyScheme::HasPassthruOperand;
@@ -938,8 +964,12 @@ llvm::SmallVector<PrototypeDescriptor> RVVIntrinsic::computeBuiltinTypes(
// to
// (void, op0 address, op1 address, ..., mask, maskedoff0, maskedoff1,
// ...)
- NewPrototype.insert(NewPrototype.begin() + NF + 1,
- PrototypeDescriptor::Mask);
+ if (IsTuple)
+ NewPrototype.insert(NewPrototype.begin() + 1,
+ PrototypeDescriptor::Mask);
+ else
+ NewPrototype.insert(NewPrototype.begin() + NF + 1,
+ PrototypeDescriptor::Mask);
} else {
// If IsMasked, insert PrototypeDescriptor:Mask as first input operand.
NewPrototype.insert(NewPrototype.begin() + 1, PrototypeDescriptor::Mask);
@@ -963,6 +993,8 @@ llvm::SmallVector<PrototypeDescriptor> RVVIntrinsic::computeBuiltinTypes(
// If HasVL, append PrototypeDescriptor:VL to last operand
if (HasVL)
NewPrototype.push_back(PrototypeDescriptor::VL);
+ if (IsTuple)
+ NewPrototype[0].VTM = static_cast<uint8_t>(VectorTypeModifier::Tuple2);
return NewPrototype;
}
@@ -1077,6 +1109,7 @@ raw_ostream &operator<<(raw_ostream &OS, const RVVIntrinsicRecord &Record) {
OS << (int)Record.HasMaskedOffOperand << ",";
OS << (int)Record.HasTailPolicy << ",";
OS << (int)Record.HasMaskPolicy << ",";
+ OS << (int)Record.IsTuple << ",";
OS << (int)Record.UnMaskedPolicyScheme << ",";
OS << (int)Record.MaskedPolicyScheme << ",";
OS << "},\n";
diff --git a/clang/test/CodeGen/RISCV/rvv-intrinsics-autogenerated/non-policy/non-overloaded/vlseg2e32_tuple.c b/clang/test/CodeGen/RISCV/rvv-intrinsics-autogenerated/non-policy/non-overloaded/vlseg2e32_tuple.c
new file mode 100644
index 0000000000000..0cb67e44ac832
--- /dev/null
+++ b/clang/test/CodeGen/RISCV/rvv-intrinsics-autogenerated/non-policy/non-overloaded/vlseg2e32_tuple.c
@@ -0,0 +1,27 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 2
+// REQUIRES: riscv-registered-target
+// RUN: %clang_cc1 -triple riscv64 -target-feature +v -target-feature +zfh \
+// RUN: -target-feature +experimental-zvfh -disable-O0-optnone \
+// RUN: -emit-llvm %s -o - | opt -S -passes=mem2reg | \
+// RUN: FileCheck --check-prefix=CHECK-RV64 %s
+#include <riscv_vector.h>
+
+// CHECK-RV64-LABEL: define dso_local { <vscale x 2 x i32>, <vscale x 2 x i32> } @test_vlseg2e32_v_tuple_i32m1
+// CHECK-RV64-SAME: (ptr noundef [[BASE:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0:[0-9]+]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call { <vscale x 2 x i32>, <vscale x 2 x i32> } @llvm.riscv.vlseg2.nxv2i32.i64(<vscale x 2 x i32> poison, <vscale x 2 x i32> poison, ptr [[BASE]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret { <vscale x 2 x i32>, <vscale x 2 x i32> } [[TMP0]]
+//
+vint32m1x2_t test_vlseg2e32_v_tuple_i32m1(const int32_t *base, size_t vl) {
+ return __riscv_vlseg2e32_v_tuple_i32m1(base, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local { <vscale x 2 x i32>, <vscale x 2 x i32> } @test_vlseg2e32_v_tuple_i32m1_m
+// CHECK-RV64-SAME: (<vscale x 2 x i1> [[MASK:%.*]], ptr noundef [[BASE:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call { <vscale x 2 x i32>, <vscale x 2 x i32> } @llvm.riscv.vlseg2.mask.nxv2i32.i64(<vscale x 2 x i32> poison, <vscale x 2 x i32> poison, ptr [[BASE]], <vscale x 2 x i1> [[MASK]], i64 [[VL]], i64 3)
+// CHECK-RV64-NEXT: ret { <vscale x 2 x i32>, <vscale x 2 x i32> } [[TMP0]]
+//
+vint32m1x2_t test_vlseg2e32_v_tuple_i32m1_m(vbool32_t mask, const int32_t *base, size_t vl) {
+ return __riscv_vlseg2e32_v_tuple_i32m1_m(mask, base, vl);
+}
diff --git a/clang/utils/TableGen/RISCVVEmitter.cpp b/clang/utils/TableGen/RISCVVEmitter.cpp
index 6228e0256d54e..7ecb6a0a87fa6 100644
--- a/clang/utils/TableGen/RISCVVEmitter.cpp
+++ b/clang/utils/TableGen/RISCVVEmitter.cpp
@@ -65,6 +65,7 @@ struct SemaRecord {
bool HasMaskedOffOperand :1;
bool HasTailPolicy : 1;
bool HasMaskPolicy : 1;
+ bool IsTuple : 1;
uint8_t UnMaskedPolicyScheme : 2;
uint8_t MaskedPolicyScheme : 2;
};
@@ -363,6 +364,16 @@ void RVVEmitter::createHeader(raw_ostream &OS) {
TypeModifier::UnsignedInteger));
printType(*UT);
}
+ // FIXME: Expand more type declaration
+ if (I == 'i' && Log2LMUL == 0) { // vint32m1x2_t
+ auto TupleT = TypeCache.computeType(
+ BT, Log2LMUL,
+ PrototypeDescriptor(BaseTypeModifier::Vector,
+ VectorTypeModifier::Tuple2,
+ TypeModifier::SignedInteger));
+ if (TupleT)
+ printType(*TupleT);
+ }
}
}
@@ -512,6 +523,7 @@ void RVVEmitter::createRVVIntrinsics(
StringRef IRName = R->getValueAsString("IRName");
StringRef MaskedIRName = R->getValueAsString("MaskedIRName");
unsigned NF = R->getValueAsInt("NF");
+ bool IsTuple = R->getValueAsBit("IsTuple");
const Policy DefaultPolicy;
SmallVector<Policy> SupportedUnMaskedPolicies =
@@ -532,10 +544,10 @@ void RVVEmitter::createRVVIntrinsics(
auto Prototype = RVVIntrinsic::computeBuiltinTypes(
BasicPrototype, /*IsMasked=*/false,
/*HasMaskedOffOperand=*/false, HasVL, NF, UnMaskedPolicyScheme,
- DefaultPolicy);
+ DefaultPolicy, IsTuple);
auto MaskedPrototype = RVVIntrinsic::computeBuiltinTypes(
BasicPrototype, /*IsMasked=*/true, HasMaskedOffOperand, HasVL, NF,
- MaskedPolicyScheme, DefaultPolicy);
+ MaskedPolicyScheme, DefaultPolicy, IsTuple);
// Create Intrinsics for each type and LMUL.
for (char I : TypeRange) {
@@ -557,14 +569,14 @@ void RVVEmitter::createRVVIntrinsics(
/*IsMasked=*/false, /*HasMaskedOffOperand=*/false, HasVL,
UnMaskedPolicyScheme, SupportOverloading, HasBuiltinAlias,
ManualCodegen, *Types, IntrinsicTypes, RequiredFeatures, NF,
- DefaultPolicy));
+ DefaultPolicy, IsTuple));
if (UnMaskedPolicyScheme != PolicyScheme::SchemeNone)
for (auto P : SupportedUnMaskedPolicies) {
SmallVector<PrototypeDescriptor> PolicyPrototype =
RVVIntrinsic::computeBuiltinTypes(
BasicPrototype, /*IsMasked=*/false,
/*HasMaskedOffOperand=*/false, HasVL, NF,
- UnMaskedPolicyScheme, P);
+ UnMaskedPolicyScheme, P, IsTuple);
std::optional<RVVTypes> PolicyTypes =
TypeCache.computeTypes(BT, Log2LMUL, NF, PolicyPrototype);
Out.push_back(std::make_unique<RVVIntrinsic>(
@@ -572,7 +584,7 @@ void RVVEmitter::createRVVIntrinsics(
/*IsMask=*/false, /*HasMaskedOffOperand=*/false, HasVL,
UnMaskedPolicyScheme, SupportOverloading, HasBuiltinAlias,
ManualCodegen, *PolicyTypes, IntrinsicTypes, RequiredFeatures,
- NF, P));
+ NF, P, IsTuple));
}
if (!HasMasked)
continue;
@@ -583,14 +595,14 @@ void RVVEmitter::createRVVIntrinsics(
Name, SuffixStr, OverloadedName, OverloadedSuffixStr, MaskedIRName,
/*IsMasked=*/true, HasMaskedOffOperand, HasVL, MaskedPolicyScheme,
SupportOverloading, HasBuiltinAlias, ManualCodegen, *MaskTypes,
- IntrinsicTypes, RequiredFeatures, NF, DefaultPolicy));
+ IntrinsicTypes, RequiredFeatures, NF, DefaultPolicy, IsTuple));
if (MaskedPolicyScheme == PolicyScheme::SchemeNone)
continue;
for (auto P : SupportedMaskedPolicies) {
SmallVector<PrototypeDescriptor> PolicyPrototype =
RVVIntrinsic::computeBuiltinTypes(
BasicPrototype, /*IsMasked=*/true, HasMaskedOffOperand, HasVL,
- NF, MaskedPolicyScheme, P);
+ NF, MaskedPolicyScheme, P, IsTuple);
std::optional<RVVTypes> PolicyTypes =
TypeCache.computeTypes(BT, Log2LMUL, NF, PolicyPrototype);
Out.push_back(std::make_unique<RVVIntrinsic>(
@@ -598,7 +610,7 @@ void RVVEmitter::createRVVIntrinsics(
MaskedIRName, /*IsMasked=*/true, HasMaskedOffOperand, HasVL,
MaskedPolicyScheme, SupportOverloading, HasBuiltinAlias,
ManualCodegen, *PolicyTypes, IntrinsicTypes, RequiredFeatures, NF,
- P));
+ P, IsTuple));
}
} // End for Log2LMULList
} // End for TypeRange
@@ -650,6 +662,7 @@ void RVVEmitter::createRVVIntrinsics(
SR.Prototype = std::move(BasicPrototype);
SR.Suffix = parsePrototypes(SuffixProto);
SR.OverloadedSuffix = parsePrototypes(OverloadedSuffixProto);
+ SR.IsTuple = IsTuple;
SemaRecords->push_back(SR);
}
@@ -691,6 +704,7 @@ void RVVEmitter::createRVVIntrinsicRecords(std::vector<RVVIntrinsicRecord> &Out,
R.HasMaskPolicy = SR.HasMaskPolicy;
R.UnMaskedPolicyScheme = SR.UnMaskedPolicyScheme;
R.MaskedPolicyScheme = SR.MaskedPolicyScheme;
+ R.IsTuple = SR.IsTuple;
assert(R.PrototypeIndex !=
static_cast<uint16_t>(SemaSignatureTable::INVALID_INDEX));
More information about the cfe-commits
mailing list