diff --git a/clang/include/clang/Sema/RISCVIntrinsicManager.h b/clang/include/clang/Sema/RISCVIntrinsicManager.h index 731bc3ae1c9d2..2a3dd1e7c4697 100644 --- a/clang/include/clang/Sema/RISCVIntrinsicManager.h +++ b/clang/include/clang/Sema/RISCVIntrinsicManager.h @@ -28,6 +28,8 @@ class RISCVIntrinsicManager { virtual ~RISCVIntrinsicManager() = default; + virtual void InitIntrinsicList() = 0; + // Create RISC-V intrinsic and insert into symbol table and return true if // found, otherwise return false. virtual bool CreateIntrinsicIfFound(LookupResult &LR, IdentifierInfo *II, diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index ba873b0187454..d1ff688c2a21d 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -937,6 +937,8 @@ bool Sema::LookupBuiltin(LookupResult &R) { if (!RVIntrinsicManager) RVIntrinsicManager = CreateRISCVIntrinsicManager(*this); + RVIntrinsicManager->InitIntrinsicList(); + if (RVIntrinsicManager->CreateIntrinsicIfFound(R, II, PP)) return true; } diff --git a/clang/lib/Sema/SemaRISCVVectorLookup.cpp b/clang/lib/Sema/SemaRISCVVectorLookup.cpp index 5f172d7275c08..fc3086c7d78f0 100644 --- a/clang/lib/Sema/SemaRISCVVectorLookup.cpp +++ b/clang/lib/Sema/SemaRISCVVectorLookup.cpp @@ -158,6 +158,8 @@ class RISCVIntrinsicManagerImpl : public sema::RISCVIntrinsicManager { Sema &S; ASTContext &Context; RVVTypeCache TypeCache; + bool ConstructedRISCVVBuiltins; + bool ConstructedRISCVSiFiveVectorBuiltins; // List of all RVV intrinsic. std::vector IntrinsicList; @@ -166,8 +168,6 @@ class RISCVIntrinsicManagerImpl : public sema::RISCVIntrinsicManager { // Mapping function name to RVVOverloadIntrinsicDef. StringMap OverloadIntrinsics; - // Create IntrinsicList - void InitIntrinsicList(); // Create RVVIntrinsicDef. void InitRVVIntrinsic(const RVVIntrinsicRecord &Record, StringRef SuffixStr, @@ -179,11 +179,18 @@ class RISCVIntrinsicManagerImpl : public sema::RISCVIntrinsicManager { Preprocessor &PP, unsigned Index, bool IsOverload); + void ConstructRVVIntrinsics(ArrayRef Recs, + IntrinsicKind K); + public: RISCVIntrinsicManagerImpl(clang::Sema &S) : S(S), Context(S.Context) { - InitIntrinsicList(); + ConstructedRISCVVBuiltins = false; + ConstructedRISCVSiFiveVectorBuiltins = false; } + // Initialize IntrinsicList + void InitIntrinsicList() override; + // Create RISC-V vector intrinsic and insert into symbol table if found, and // return true, otherwise return false. bool CreateIntrinsicIfFound(LookupResult &LR, IdentifierInfo *II, @@ -191,139 +198,145 @@ class RISCVIntrinsicManagerImpl : public sema::RISCVIntrinsicManager { }; } // namespace -void RISCVIntrinsicManagerImpl::InitIntrinsicList() { +void RISCVIntrinsicManagerImpl::ConstructRVVIntrinsics( + ArrayRef Recs, IntrinsicKind K) { const TargetInfo &TI = Context.getTargetInfo(); bool HasRV64 = TI.hasFeature("64bit"); bool HasFullMultiply = TI.hasFeature("v"); - - auto ConstructRVVIntrinsics = [&](ArrayRef Recs, - IntrinsicKind K) { - // Construction of RVVIntrinsicRecords need to sync with createRVVIntrinsics - // in RISCVVEmitter.cpp. - for (auto &Record : Recs) { - // Create Intrinsics for each type and LMUL. - BasicType BaseType = BasicType::Unknown; - ArrayRef BasicProtoSeq = - ProtoSeq2ArrayRef(K, Record.PrototypeIndex, Record.PrototypeLength); - ArrayRef SuffixProto = - ProtoSeq2ArrayRef(K, Record.SuffixIndex, Record.SuffixLength); - ArrayRef OverloadedSuffixProto = ProtoSeq2ArrayRef( - K, Record.OverloadedSuffixIndex, Record.OverloadedSuffixSize); - - PolicyScheme UnMaskedPolicyScheme = - static_cast(Record.UnMaskedPolicyScheme); - PolicyScheme MaskedPolicyScheme = - static_cast(Record.MaskedPolicyScheme); - - const Policy DefaultPolicy; - - llvm::SmallVector ProtoSeq = - RVVIntrinsic::computeBuiltinTypes( - BasicProtoSeq, /*IsMasked=*/false, - /*HasMaskedOffOperand=*/false, Record.HasVL, Record.NF, - UnMaskedPolicyScheme, DefaultPolicy, Record.IsTuple); - - llvm::SmallVector ProtoMaskSeq = - RVVIntrinsic::computeBuiltinTypes( - BasicProtoSeq, /*IsMasked=*/true, Record.HasMaskedOffOperand, - Record.HasVL, Record.NF, MaskedPolicyScheme, DefaultPolicy, - Record.IsTuple); - - bool UnMaskedHasPolicy = UnMaskedPolicyScheme != PolicyScheme::SchemeNone; - bool MaskedHasPolicy = MaskedPolicyScheme != PolicyScheme::SchemeNone; - SmallVector SupportedUnMaskedPolicies = - RVVIntrinsic::getSupportedUnMaskedPolicies(); - SmallVector SupportedMaskedPolicies = - RVVIntrinsic::getSupportedMaskedPolicies(Record.HasTailPolicy, - Record.HasMaskPolicy); - - for (unsigned int TypeRangeMaskShift = 0; - TypeRangeMaskShift <= static_cast(BasicType::MaxOffset); - ++TypeRangeMaskShift) { - unsigned int BaseTypeI = 1 << TypeRangeMaskShift; - BaseType = static_cast(BaseTypeI); - - if ((BaseTypeI & Record.TypeRangeMask) != BaseTypeI) + // Construction of RVVIntrinsicRecords need to sync with createRVVIntrinsics + // in RISCVVEmitter.cpp. + for (auto &Record : Recs) { + // Create Intrinsics for each type and LMUL. + BasicType BaseType = BasicType::Unknown; + ArrayRef BasicProtoSeq = + ProtoSeq2ArrayRef(K, Record.PrototypeIndex, Record.PrototypeLength); + ArrayRef SuffixProto = + ProtoSeq2ArrayRef(K, Record.SuffixIndex, Record.SuffixLength); + ArrayRef OverloadedSuffixProto = ProtoSeq2ArrayRef( + K, Record.OverloadedSuffixIndex, Record.OverloadedSuffixSize); + + PolicyScheme UnMaskedPolicyScheme = + static_cast(Record.UnMaskedPolicyScheme); + PolicyScheme MaskedPolicyScheme = + static_cast(Record.MaskedPolicyScheme); + + const Policy DefaultPolicy; + + llvm::SmallVector ProtoSeq = + RVVIntrinsic::computeBuiltinTypes( + BasicProtoSeq, /*IsMasked=*/false, + /*HasMaskedOffOperand=*/false, Record.HasVL, Record.NF, + UnMaskedPolicyScheme, DefaultPolicy, Record.IsTuple); + + llvm::SmallVector ProtoMaskSeq = + RVVIntrinsic::computeBuiltinTypes( + BasicProtoSeq, /*IsMasked=*/true, Record.HasMaskedOffOperand, + Record.HasVL, Record.NF, MaskedPolicyScheme, DefaultPolicy, + Record.IsTuple); + + bool UnMaskedHasPolicy = UnMaskedPolicyScheme != PolicyScheme::SchemeNone; + bool MaskedHasPolicy = MaskedPolicyScheme != PolicyScheme::SchemeNone; + SmallVector SupportedUnMaskedPolicies = + RVVIntrinsic::getSupportedUnMaskedPolicies(); + SmallVector SupportedMaskedPolicies = + RVVIntrinsic::getSupportedMaskedPolicies(Record.HasTailPolicy, + Record.HasMaskPolicy); + + for (unsigned int TypeRangeMaskShift = 0; + TypeRangeMaskShift <= static_cast(BasicType::MaxOffset); + ++TypeRangeMaskShift) { + unsigned int BaseTypeI = 1 << TypeRangeMaskShift; + BaseType = static_cast(BaseTypeI); + + if ((BaseTypeI & Record.TypeRangeMask) != BaseTypeI) + continue; + + // Check requirement. + if (((Record.RequiredExtensions & RVV_REQ_RV64) == RVV_REQ_RV64) && + !HasRV64) + continue; + + if ((BaseType == BasicType::Int64) && + ((Record.RequiredExtensions & RVV_REQ_FullMultiply) == + RVV_REQ_FullMultiply) && + !HasFullMultiply) + continue; + + // Expanded with different LMUL. + for (int Log2LMUL = -3; Log2LMUL <= 3; Log2LMUL++) { + if (!(Record.Log2LMULMask & (1 << (Log2LMUL + 3)))) continue; - // Check requirement. - if (((Record.RequiredExtensions & RVV_REQ_RV64) == RVV_REQ_RV64) && - !HasRV64) - continue; + std::optional Types = + TypeCache.computeTypes(BaseType, Log2LMUL, Record.NF, ProtoSeq); - if ((BaseType == BasicType::Int64) && - ((Record.RequiredExtensions & RVV_REQ_FullMultiply) == - RVV_REQ_FullMultiply) && - !HasFullMultiply) + // Ignored to create new intrinsic if there are any illegal types. + if (!Types.has_value()) continue; - // Expanded with different LMUL. - for (int Log2LMUL = -3; Log2LMUL <= 3; Log2LMUL++) { - if (!(Record.Log2LMULMask & (1 << (Log2LMUL + 3)))) - continue; - - std::optional Types = - TypeCache.computeTypes(BaseType, Log2LMUL, Record.NF, ProtoSeq); - - // Ignored to create new intrinsic if there are any illegal types. - if (!Types.has_value()) - continue; - - std::string SuffixStr = RVVIntrinsic::getSuffixStr( - TypeCache, BaseType, Log2LMUL, SuffixProto); - std::string OverloadedSuffixStr = RVVIntrinsic::getSuffixStr( - TypeCache, BaseType, Log2LMUL, OverloadedSuffixProto); - - // Create non-masked intrinsic. - InitRVVIntrinsic(Record, SuffixStr, OverloadedSuffixStr, false, *Types, - UnMaskedHasPolicy, DefaultPolicy); - - // Create non-masked policy intrinsic. - if (Record.UnMaskedPolicyScheme != PolicyScheme::SchemeNone) { - for (auto P : SupportedUnMaskedPolicies) { - llvm::SmallVector PolicyPrototype = - RVVIntrinsic::computeBuiltinTypes( - BasicProtoSeq, /*IsMasked=*/false, - /*HasMaskedOffOperand=*/false, Record.HasVL, Record.NF, - UnMaskedPolicyScheme, P, Record.IsTuple); - std::optional PolicyTypes = TypeCache.computeTypes( - BaseType, Log2LMUL, Record.NF, PolicyPrototype); - InitRVVIntrinsic(Record, SuffixStr, OverloadedSuffixStr, - /*IsMask=*/false, *PolicyTypes, UnMaskedHasPolicy, - P); - } - } - if (!Record.HasMasked) - continue; - // Create masked intrinsic. - std::optional MaskTypes = - TypeCache.computeTypes(BaseType, Log2LMUL, Record.NF, ProtoMaskSeq); - InitRVVIntrinsic(Record, SuffixStr, OverloadedSuffixStr, true, - *MaskTypes, MaskedHasPolicy, DefaultPolicy); - if (Record.MaskedPolicyScheme == PolicyScheme::SchemeNone) - continue; - // Create masked policy intrinsic. - for (auto P : SupportedMaskedPolicies) { + std::string SuffixStr = RVVIntrinsic::getSuffixStr( + TypeCache, BaseType, Log2LMUL, SuffixProto); + std::string OverloadedSuffixStr = RVVIntrinsic::getSuffixStr( + TypeCache, BaseType, Log2LMUL, OverloadedSuffixProto); + + // Create non-masked intrinsic. + InitRVVIntrinsic(Record, SuffixStr, OverloadedSuffixStr, false, *Types, + UnMaskedHasPolicy, DefaultPolicy); + + // Create non-masked policy intrinsic. + if (Record.UnMaskedPolicyScheme != PolicyScheme::SchemeNone) { + for (auto P : SupportedUnMaskedPolicies) { llvm::SmallVector PolicyPrototype = RVVIntrinsic::computeBuiltinTypes( - BasicProtoSeq, /*IsMasked=*/true, - Record.HasMaskedOffOperand, Record.HasVL, Record.NF, - MaskedPolicyScheme, P, Record.IsTuple); + BasicProtoSeq, /*IsMasked=*/false, + /*HasMaskedOffOperand=*/false, Record.HasVL, Record.NF, + UnMaskedPolicyScheme, P, Record.IsTuple); std::optional PolicyTypes = TypeCache.computeTypes( BaseType, Log2LMUL, Record.NF, PolicyPrototype); InitRVVIntrinsic(Record, SuffixStr, OverloadedSuffixStr, - /*IsMask=*/true, *PolicyTypes, MaskedHasPolicy, P); + /*IsMask=*/false, *PolicyTypes, UnMaskedHasPolicy, + P); } - } // End for different LMUL - } // End for different TypeRange - } - }; - if (S.DeclareRISCVVBuiltins) + } + if (!Record.HasMasked) + continue; + // Create masked intrinsic. + std::optional MaskTypes = + TypeCache.computeTypes(BaseType, Log2LMUL, Record.NF, ProtoMaskSeq); + InitRVVIntrinsic(Record, SuffixStr, OverloadedSuffixStr, true, + *MaskTypes, MaskedHasPolicy, DefaultPolicy); + if (Record.MaskedPolicyScheme == PolicyScheme::SchemeNone) + continue; + // Create masked policy intrinsic. + for (auto P : SupportedMaskedPolicies) { + llvm::SmallVector PolicyPrototype = + RVVIntrinsic::computeBuiltinTypes( + BasicProtoSeq, /*IsMasked=*/true, Record.HasMaskedOffOperand, + Record.HasVL, Record.NF, MaskedPolicyScheme, P, + Record.IsTuple); + std::optional PolicyTypes = TypeCache.computeTypes( + BaseType, Log2LMUL, Record.NF, PolicyPrototype); + InitRVVIntrinsic(Record, SuffixStr, OverloadedSuffixStr, + /*IsMask=*/true, *PolicyTypes, MaskedHasPolicy, P); + } + } // End for different LMUL + } // End for different TypeRange + } +} + +void RISCVIntrinsicManagerImpl::InitIntrinsicList() { + + if (S.DeclareRISCVVBuiltins && !ConstructedRISCVVBuiltins) { + ConstructedRISCVVBuiltins = true; ConstructRVVIntrinsics(RVVIntrinsicRecords, IntrinsicKind::RVV); - if (S.DeclareRISCVSiFiveVectorBuiltins) + } + if (S.DeclareRISCVSiFiveVectorBuiltins && + !ConstructedRISCVSiFiveVectorBuiltins) { + ConstructedRISCVSiFiveVectorBuiltins = true; ConstructRVVIntrinsics(RVSiFiveVectorIntrinsicRecords, IntrinsicKind::SIFIVE_VECTOR); + } } // Compute name and signatures for intrinsic with practical types. diff --git a/clang/test/CodeGen/RISCV/rvv-intrinsics-handcrafted/xsfvcp.cpp b/clang/test/CodeGen/RISCV/rvv-intrinsics-handcrafted/xsfvcp.cpp new file mode 100644 index 0000000000000..d6dce4f020332 --- /dev/null +++ b/clang/test/CodeGen/RISCV/rvv-intrinsics-handcrafted/xsfvcp.cpp @@ -0,0 +1,15 @@ +// REQUIRES: riscv-registered-target +// RUN: %clang_cc1 -triple riscv64 -target-feature +f -target-feature +d \ +// RUN: -target-feature +v \ +// RUN: -target-feature +xsfvcp \ +// RUN: -fsyntax-only -verify %s +// expected-no-diagnostics + +#include + +#define p27_26 (0b11) +#define p11_7 (0b11111) + +void test_sf_vc_xv_se_u64m1(vuint64m1_t vs2, uint64_t rs1, size_t vl) { + __riscv_sf_vc_xv_se_u64m1(p27_26, p11_7, vs2, rs1, vl); +}