From df112d4d2926f0405d75c209823e7a337ec3fda3 Mon Sep 17 00:00:00 2001 From: Viktoria Maximova Date: Mon, 26 Feb 2024 18:37:25 +0100 Subject: [PATCH] [Backport to 11] Support SPV_INTEL_maximum_registers extension (#2344) Spec: KhronosGroup/SPIRV-Registry#235 --- .clang-tidy | 1 - include/LLVMSPIRVExtensions.inc | 1 + lib/SPIRV/SPIRVReader.cpp | 42 +++++++++ lib/SPIRV/SPIRVWriter.cpp | 87 +++++++++++++----- lib/SPIRV/SPIRVWriter.h | 1 + lib/SPIRV/libSPIRV/SPIRVEntry.cpp | 10 ++- lib/SPIRV/libSPIRV/SPIRVEntry.h | 88 ++++++++++++++----- lib/SPIRV/libSPIRV/SPIRVEnum.h | 6 ++ lib/SPIRV/libSPIRV/SPIRVIsValidEnum.h | 5 +- lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h | 8 ++ lib/SPIRV/libSPIRV/SPIRVOpCodeEnum.h | 1 + lib/SPIRV/libSPIRV/SPIRVStream.cpp | 1 + lib/SPIRV/libSPIRV/SPIRVStream.h | 1 + lib/SPIRV/libSPIRV/spirv.hpp | 9 ++ .../registerallocmode_maxreg_extension.ll | 85 ++++++++++++++++++ 15 files changed, 294 insertions(+), 52 deletions(-) create mode 100644 test/extensions/INTEL/SPV_INTEL_maximum_registers/registerallocmode_maxreg_extension.ll diff --git a/.clang-tidy b/.clang-tidy index 2b21aacf9e..b30219a588 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -16,4 +16,3 @@ CheckOptions: value: CamelCase - key: llvm-namespace-comment.ShortNamespaceLines value: '25' - diff --git a/include/LLVMSPIRVExtensions.inc b/include/LLVMSPIRVExtensions.inc index 6897bcf414..c773394898 100644 --- a/include/LLVMSPIRVExtensions.inc +++ b/include/LLVMSPIRVExtensions.inc @@ -48,3 +48,4 @@ EXT(SPV_INTEL_tensor_float32_rounding) EXT(SPV_INTEL_hw_thread_queries) EXT(SPV_EXT_relaxed_printf_string_address_space) EXT(SPV_INTEL_global_variable_decorations) +EXT(SPV_INTEL_maximum_registers) diff --git a/lib/SPIRV/SPIRVReader.cpp b/lib/SPIRV/SPIRVReader.cpp index 639152d455..11fb3a58ef 100644 --- a/lib/SPIRV/SPIRVReader.cpp +++ b/lib/SPIRV/SPIRVReader.cpp @@ -3776,6 +3776,48 @@ bool SPIRVToLLVM::transMetadata() { F->setMetadata(kSPIR2MD::NumSIMD, getMDNodeStringIntVec(Context, EM->getLiterals())); } + if (auto *EM = BF->getExecutionMode(ExecutionModeMaximumRegistersINTEL)) { + NamedMDNode *ExecModeMD = + M->getOrInsertNamedMetadata(kSPIRVMD::ExecutionMode); + + SmallVector ValueVec; + ValueVec.push_back(ConstantAsMetadata::get(F)); + ValueVec.push_back( + ConstantAsMetadata::get(getUInt32(M, EM->getExecutionMode()))); + ValueVec.push_back( + ConstantAsMetadata::get(getUInt32(M, EM->getLiterals()[0]))); + ExecModeMD->addOperand(MDNode::get(*Context, ValueVec)); + } + if (auto *EM = BF->getExecutionMode(ExecutionModeMaximumRegistersIdINTEL)) { + NamedMDNode *ExecModeMD = + M->getOrInsertNamedMetadata(kSPIRVMD::ExecutionMode); + + SmallVector ValueVec; + ValueVec.push_back(ConstantAsMetadata::get(F)); + ValueVec.push_back( + ConstantAsMetadata::get(getUInt32(M, EM->getExecutionMode()))); + + auto *ExecOp = BF->getModule()->getValue(EM->getLiterals()[0]); + ValueVec.push_back( + MDNode::get(*Context, ConstantAsMetadata::get(cast( + transValue(ExecOp, nullptr, nullptr))))); + ExecModeMD->addOperand(MDNode::get(*Context, ValueVec)); + } + if (auto *EM = + BF->getExecutionMode(ExecutionModeNamedMaximumRegistersINTEL)) { + NamedMDNode *ExecModeMD = + M->getOrInsertNamedMetadata(kSPIRVMD::ExecutionMode); + + SmallVector ValueVec; + ValueVec.push_back(ConstantAsMetadata::get(F)); + ValueVec.push_back( + ConstantAsMetadata::get(getUInt32(M, EM->getExecutionMode()))); + + assert(EM->getLiterals()[0] == 0 && + "Invalid named maximum number of registers"); + ValueVec.push_back(MDString::get(*Context, "AutoINTEL")); + ExecModeMD->addOperand(MDNode::get(*Context, ValueVec)); + } } NamedMDNode *MemoryModelMD = M->getOrInsertNamedMetadata(kSPIRVMD::MemoryModel); diff --git a/lib/SPIRV/SPIRVWriter.cpp b/lib/SPIRV/SPIRVWriter.cpp index c3d3906873..1f37bf8de1 100644 --- a/lib/SPIRV/SPIRVWriter.cpp +++ b/lib/SPIRV/SPIRVWriter.cpp @@ -686,6 +686,9 @@ SPIRVFunction *LLVMToSPIRVBase::transFunctionDecl(Function *F) { if (BM->isAllowedToUseExtension(ExtensionID::SPV_INTEL_vector_compute)) transVectorComputeMetadata(F); + if (BM->isAllowedToUseExtension(ExtensionID::SPV_INTEL_maximum_registers)) + transFunctionMetadataAsExecutionMode(BF, F); + SPIRVDBG(dbgs() << "[transFunction] " << *F << " => "; spvdbgs() << *BF << '\n';) return BF; @@ -763,6 +766,38 @@ void LLVMToSPIRVBase::transVectorComputeMetadata(Function *F) { } } +void LLVMToSPIRVBase::transFunctionMetadataAsExecutionMode(SPIRVFunction *BF, + Function *F) { + SmallVector RegisterAllocModeMDs; + F->getMetadata("RegisterAllocMode", RegisterAllocModeMDs); + + for (unsigned I = 0; I < RegisterAllocModeMDs.size(); I++) { + auto *RegisterAllocMode = RegisterAllocModeMDs[I]->getOperand(0).get(); + if (isa(RegisterAllocMode)) { + const std::string Str = getMDOperandAsString(RegisterAllocModeMDs[I], 0); + const NamedMaximumNumberOfRegisters NamedValue = + SPIRVNamedMaximumNumberOfRegistersNameMap::rmap(Str); + BF->addExecutionMode(BM->add(new SPIRVExecutionMode( + OpExecutionMode, BF, ExecutionModeNamedMaximumRegistersINTEL, + NamedValue))); + } else if (isa(RegisterAllocMode)) { + auto *RegisterAllocNodeMDOp = + getMDOperandAsMDNode(RegisterAllocModeMDs[I], 0); + const int Num = getMDOperandAsInt(RegisterAllocNodeMDOp, 0); + auto *Const = + BM->addConstant(transType(Type::getInt32Ty(F->getContext())), Num); + BF->addExecutionMode(BM->add(new SPIRVExecutionModeId( + BF, ExecutionModeMaximumRegistersIdINTEL, Const->getId()))); + } else { + const int64_t RegisterAllocVal = + mdconst::dyn_extract(RegisterAllocMode)->getZExtValue(); + BF->addExecutionMode(BM->add(new SPIRVExecutionMode( + OpExecutionMode, BF, ExecutionModeMaximumRegistersINTEL, + RegisterAllocVal))); + } + } +} + SPIRVValue *LLVMToSPIRVBase::transConstant(Value *V) { if (auto CPNull = dyn_cast(V)) return BM->addNullConstant( @@ -3857,14 +3892,14 @@ bool LLVMToSPIRVBase::transExecutionMode() { switch (EMode) { case spv::ExecutionModeContractionOff: - BF->addExecutionMode(BM->add( - new SPIRVExecutionMode(BF, static_cast(EMode)))); + BF->addExecutionMode(BM->add(new SPIRVExecutionMode( + OpExecutionMode, BF, static_cast(EMode)))); break; case spv::ExecutionModeInitializer: case spv::ExecutionModeFinalizer: if (BM->isAllowedToUseVersion(VersionNumber::SPIRV_1_1)) { - BF->addExecutionMode(BM->add( - new SPIRVExecutionMode(BF, static_cast(EMode)))); + BF->addExecutionMode(BM->add(new SPIRVExecutionMode( + OpExecutionMode, BF, static_cast(EMode)))); } else { getErrorLog().checkError(false, SPIRVEC_Requires1_1, "Initializer/Finalizer Execution Mode"); @@ -3876,7 +3911,7 @@ bool LLVMToSPIRVBase::transExecutionMode() { unsigned X, Y, Z; N.get(X).get(Y).get(Z); BF->addExecutionMode(BM->add(new SPIRVExecutionMode( - BF, static_cast(EMode), X, Y, Z))); + OpExecutionMode, BF, static_cast(EMode), X, Y, Z))); } break; case spv::ExecutionModeMaxWorkgroupSizeINTEL: { if (BM->isAllowedToUseExtension( @@ -3884,25 +3919,26 @@ bool LLVMToSPIRVBase::transExecutionMode() { unsigned X, Y, Z; N.get(X).get(Y).get(Z); BF->addExecutionMode(BM->add(new SPIRVExecutionMode( - BF, static_cast(EMode), X, Y, Z))); + OpExecutionMode, BF, static_cast(EMode), X, Y, + Z))); BM->addCapability(CapabilityKernelAttributesINTEL); } } break; case spv::ExecutionModeNoGlobalOffsetINTEL: { - if (BM->isAllowedToUseExtension( - ExtensionID::SPV_INTEL_kernel_attributes)) { - BF->addExecutionMode(BM->add( - new SPIRVExecutionMode(BF, static_cast(EMode)))); - BM->addCapability(CapabilityKernelAttributesINTEL); - } + if (!BM->isAllowedToUseExtension( + ExtensionID::SPV_INTEL_kernel_attributes)) + break; + BF->addExecutionMode(BM->add(new SPIRVExecutionMode( + OpExecutionMode, BF, static_cast(EMode)))); + BM->addCapability(CapabilityKernelAttributesINTEL); } break; case spv::ExecutionModeVecTypeHint: case spv::ExecutionModeSubgroupSize: case spv::ExecutionModeSubgroupsPerWorkgroup: { unsigned X; N.get(X); - BF->addExecutionMode(BM->add( - new SPIRVExecutionMode(BF, static_cast(EMode), X))); + BF->addExecutionMode(BM->add(new SPIRVExecutionMode( + OpExecutionMode, BF, static_cast(EMode), X))); } break; case spv::ExecutionModeNumSIMDWorkitemsINTEL: { if (BM->isAllowedToUseExtension( @@ -3920,7 +3956,7 @@ bool LLVMToSPIRVBase::transExecutionMode() { unsigned X; N.get(X); BF->addExecutionMode(BM->add(new SPIRVExecutionMode( - BF, static_cast(EMode), X))); + OpExecutionMode, BF, static_cast(EMode), X))); BM->addCapability(CapabilityFPGAKernelAttributesINTEL); } } break; @@ -3930,15 +3966,16 @@ bool LLVMToSPIRVBase::transExecutionMode() { unsigned SLMSize; N.get(SLMSize); BF->addExecutionMode(BM->add(new SPIRVExecutionMode( - BF, static_cast(EMode), SLMSize))); + OpExecutionMode, BF, static_cast(EMode), SLMSize))); } break; case spv::ExecutionModeNamedBarrierCountINTEL: { if (!BM->isAllowedToUseExtension(ExtensionID::SPV_INTEL_vector_compute)) break; unsigned NBarrierCnt = 0; N.get(NBarrierCnt); - BF->addExecutionMode(new SPIRVExecutionMode( - BF, static_cast(EMode), NBarrierCnt)); + BF->addExecutionMode(BM->add(new SPIRVExecutionMode( + OpExecutionMode, BF, static_cast(EMode), + NBarrierCnt))); BM->addExtension(ExtensionID::SPV_INTEL_vector_compute); BM->addCapability(CapabilityVectorComputeINTEL); } break; @@ -3953,7 +3990,8 @@ bool LLVMToSPIRVBase::transExecutionMode() { unsigned TargetWidth; N.get(TargetWidth); BF->addExecutionMode(BM->add(new SPIRVExecutionMode( - BF, static_cast(EMode), TargetWidth))); + OpExecutionMode, BF, static_cast(EMode), + TargetWidth))); } break; case spv::ExecutionModeRoundingModeRTPINTEL: case spv::ExecutionModeRoundingModeRTNINTEL: @@ -3965,12 +4003,13 @@ bool LLVMToSPIRVBase::transExecutionMode() { unsigned TargetWidth; N.get(TargetWidth); BF->addExecutionMode(BM->add(new SPIRVExecutionMode( - BF, static_cast(EMode), TargetWidth))); + OpExecutionMode, BF, static_cast(EMode), + TargetWidth))); } break; case spv::ExecutionModeFastCompositeKernelINTEL: { if (BM->isAllowedToUseExtension(ExtensionID::SPV_INTEL_fast_composite)) - BF->addExecutionMode(BM->add( - new SPIRVExecutionMode(BF, static_cast(EMode)))); + BF->addExecutionMode(BM->add(new SPIRVExecutionMode( + OpExecutionMode, BF, static_cast(EMode)))); } break; default: llvm_unreachable("invalid execution mode"); @@ -4015,8 +4054,8 @@ void LLVMToSPIRVBase::transFPContract() { } if (DisableContraction) { - BF->addExecutionMode(BF->getModule()->add( - new SPIRVExecutionMode(BF, spv::ExecutionModeContractionOff))); + BF->addExecutionMode(BF->getModule()->add(new SPIRVExecutionMode( + OpExecutionMode, BF, spv::ExecutionModeContractionOff))); } } } diff --git a/lib/SPIRV/SPIRVWriter.h b/lib/SPIRV/SPIRVWriter.h index 2526fabba7..306f548b39 100644 --- a/lib/SPIRV/SPIRVWriter.h +++ b/lib/SPIRV/SPIRVWriter.h @@ -107,6 +107,7 @@ class LLVMToSPIRVBase { SPIRVWord transFunctionControlMask(Function *); SPIRVFunction *transFunctionDecl(Function *F); void transVectorComputeMetadata(Function *F); + void transFunctionMetadataAsExecutionMode(SPIRVFunction *BF, Function *F); bool transGlobalVariables(); Op transBoolOpCode(SPIRVValue *Opn, Op OC); diff --git a/lib/SPIRV/libSPIRV/SPIRVEntry.cpp b/lib/SPIRV/libSPIRV/SPIRVEntry.cpp index bb34175b02..3e59cd1590 100644 --- a/lib/SPIRV/libSPIRV/SPIRVEntry.cpp +++ b/lib/SPIRV/libSPIRV/SPIRVEntry.cpp @@ -540,7 +540,7 @@ SPIRVEntryPoint::SPIRVEntryPoint(SPIRVModule *TheModule, SPIRVExecutionModelKind TheExecModel, SPIRVId TheId, const std::string &TheName, std::vector Variables) - : SPIRVAnnotation(TheModule->get(TheId), + : SPIRVAnnotation(OpEntryPoint, TheModule->get(TheId), getSizeInWords(TheName) + Variables.size() + 3), ExecModel(TheExecModel), Name(TheName), Variables(Variables) {} @@ -560,7 +560,7 @@ void SPIRVExecutionMode::encode(spv_ostream &O) const { void SPIRVExecutionMode::decode(std::istream &I) { getDecoder(I) >> Target >> ExecMode; - switch (ExecMode) { + switch (static_cast(ExecMode)) { case ExecutionModeLocalSize: case ExecutionModeLocalSizeHint: case ExecutionModeMaxWorkgroupSizeINTEL: @@ -583,6 +583,9 @@ void SPIRVExecutionMode::decode(std::istream &I) { case ExecutionModeSubgroupSize: case ExecutionModeMaxWorkDimINTEL: case ExecutionModeNumSIMDWorkitemsINTEL: + case ExecutionModeMaximumRegistersINTEL: + case ExecutionModeMaximumRegistersIdINTEL: + case ExecutionModeNamedMaximumRegistersINTEL: WordLiterals.resize(1); break; default: @@ -604,7 +607,8 @@ SPIRVForward *SPIRVAnnotationGeneric::getOrCreateTarget() const { } SPIRVName::SPIRVName(const SPIRVEntry *TheTarget, const std::string &TheStr) - : SPIRVAnnotation(TheTarget, getSizeInWords(TheStr) + 2), Str(TheStr) {} + : SPIRVAnnotation(OpName, TheTarget, getSizeInWords(TheStr) + 2), + Str(TheStr) {} void SPIRVName::encode(spv_ostream &O) const { getEncoder(O) << Target << Str; } diff --git a/lib/SPIRV/libSPIRV/SPIRVEntry.h b/lib/SPIRV/libSPIRV/SPIRVEntry.h index 96efb4cd9a..063e3c3616 100644 --- a/lib/SPIRV/libSPIRV/SPIRVEntry.h +++ b/lib/SPIRV/libSPIRV/SPIRVEntry.h @@ -514,22 +514,23 @@ class SPIRVAnnotationGeneric : public SPIRVEntryNoIdGeneric { SPIRVId Target; }; -template class SPIRVAnnotation : public SPIRVAnnotationGeneric { +class SPIRVAnnotation : public SPIRVAnnotationGeneric { public: // Complete constructor - SPIRVAnnotation(const SPIRVEntry *TheTarget, unsigned TheWordCount) + SPIRVAnnotation(Op OC, const SPIRVEntry *TheTarget, unsigned TheWordCount) : SPIRVAnnotationGeneric(TheTarget->getModule(), TheWordCount, OC, TheTarget->getId()) {} - // Incomplete constructor - SPIRVAnnotation() : SPIRVAnnotationGeneric(OC) {} + // Incomplete constructors + SPIRVAnnotation(Op OC) : SPIRVAnnotationGeneric(OC) {} + SPIRVAnnotation() : SPIRVAnnotationGeneric(OpNop) {} }; -class SPIRVEntryPoint : public SPIRVAnnotation { +class SPIRVEntryPoint : public SPIRVAnnotation { public: SPIRVEntryPoint(SPIRVModule *TheModule, SPIRVExecutionModelKind, SPIRVId TheId, const std::string &TheName, std::vector Variables); - SPIRVEntryPoint() {} + SPIRVEntryPoint() : SPIRVAnnotation(OpEntryPoint) {} _SPIRV_DCL_ENCDEC protected: @@ -540,12 +541,12 @@ class SPIRVEntryPoint : public SPIRVAnnotation { std::vector Variables; }; -class SPIRVName : public SPIRVAnnotation { +class SPIRVName : public SPIRVAnnotation { public: // Complete constructor SPIRVName(const SPIRVEntry *TheTarget, const std::string &TheStr); // Incomplete constructor - SPIRVName() {} + SPIRVName() : SPIRVAnnotation(OpName) {} protected: _SPIRV_DCL_ENCDEC @@ -554,18 +555,18 @@ class SPIRVName : public SPIRVAnnotation { std::string Str; }; -class SPIRVMemberName : public SPIRVAnnotation { +class SPIRVMemberName : public SPIRVAnnotation { public: static const SPIRVWord FixedWC = 3; // Complete constructor SPIRVMemberName(const SPIRVEntry *TheTarget, SPIRVWord TheMemberNumber, const std::string &TheStr) - : SPIRVAnnotation(TheTarget, FixedWC + getSizeInWords(TheStr)), + : SPIRVAnnotation(OpName, TheTarget, FixedWC + getSizeInWords(TheStr)), MemberNumber(TheMemberNumber), Str(TheStr) { validate(); } // Incomplete constructor - SPIRVMemberName() : MemberNumber(SPIRVWORD_MAX) {} + SPIRVMemberName() : SPIRVAnnotation(OpName), MemberNumber(SPIRVWORD_MAX) {} protected: _SPIRV_DCL_ENCDEC @@ -641,31 +642,33 @@ class SPIRVLine : public SPIRVEntry { SPIRVWord Column; }; -class SPIRVExecutionMode : public SPIRVAnnotation { +class SPIRVExecutionMode : public SPIRVAnnotation { public: // Complete constructor for LocalSize, LocalSizeHint - SPIRVExecutionMode(SPIRVEntry *TheTarget, SPIRVExecutionModeKind TheExecMode, - SPIRVWord X, SPIRVWord Y, SPIRVWord Z) - : SPIRVAnnotation(TheTarget, 6), ExecMode(TheExecMode) { + SPIRVExecutionMode(Op OC, SPIRVEntry *TheTarget, + SPIRVExecutionModeKind TheExecMode, SPIRVWord X, + SPIRVWord Y, SPIRVWord Z) + : SPIRVAnnotation(OC, TheTarget, 6), ExecMode(TheExecMode) { WordLiterals.push_back(X); WordLiterals.push_back(Y); WordLiterals.push_back(Z); updateModuleVersion(); } // Complete constructor for VecTypeHint, SubgroupSize, SubgroupsPerWorkgroup - SPIRVExecutionMode(SPIRVEntry *TheTarget, SPIRVExecutionModeKind TheExecMode, - SPIRVWord Code) - : SPIRVAnnotation(TheTarget, 4), ExecMode(TheExecMode) { + SPIRVExecutionMode(Op OC, SPIRVEntry *TheTarget, + SPIRVExecutionModeKind TheExecMode, SPIRVWord Code) + : SPIRVAnnotation(OC, TheTarget, 4), ExecMode(TheExecMode) { WordLiterals.push_back(Code); - updateModuleVersion(); } // Complete constructor for ContractionOff - SPIRVExecutionMode(SPIRVEntry *TheTarget, SPIRVExecutionModeKind TheExecMode) - : SPIRVAnnotation(TheTarget, 3), ExecMode(TheExecMode) { + SPIRVExecutionMode(Op OC, SPIRVEntry *TheTarget, + SPIRVExecutionModeKind TheExecMode) + : SPIRVAnnotation(OC, TheTarget, 3), ExecMode(TheExecMode) { updateModuleVersion(); } // Incomplete constructor - SPIRVExecutionMode() : ExecMode(ExecutionModeInvocations) {} + SPIRVExecutionMode() + : SPIRVAnnotation(OpExecutionMode), ExecMode(ExecutionModeInvocations) {} SPIRVExecutionModeKind getExecutionMode() const { return ExecMode; } const std::vector &getLiterals() const { return WordLiterals; } SPIRVCapVec getRequiredCapability() const override { @@ -685,12 +688,45 @@ class SPIRVExecutionMode : public SPIRVAnnotation { } } + llvm::Optional getRequiredExtension() const override { + switch (static_cast(ExecMode)) { + case ExecutionModeMaximumRegistersINTEL: + case ExecutionModeMaximumRegistersIdINTEL: + case ExecutionModeNamedMaximumRegistersINTEL: + return ExtensionID::SPV_INTEL_maximum_registers; + default: + return {}; + } + } + protected: _SPIRV_DCL_ENCDEC SPIRVExecutionModeKind ExecMode; std::vector WordLiterals; }; +class SPIRVExecutionModeId : public SPIRVExecutionMode { +public: + // Complete constructor for LocalSizeId, LocalSizeHintId + SPIRVExecutionModeId(SPIRVEntry *TheTarget, + SPIRVExecutionModeKind TheExecMode, SPIRVWord X, + SPIRVWord Y, SPIRVWord Z) + : SPIRVExecutionMode(OpExecutionModeId, TheTarget, TheExecMode, X, Y, Z) { + updateModuleVersion(); + } + // Complete constructor for SubgroupsPerWorkgroupId + SPIRVExecutionModeId(SPIRVEntry *TheTarget, + SPIRVExecutionModeKind TheExecMode, SPIRVWord Code) + : SPIRVExecutionMode(OpExecutionModeId, TheTarget, TheExecMode, Code) { + updateModuleVersion(); + } + // Incomplete constructor + SPIRVExecutionModeId() : SPIRVExecutionMode() {} + SPIRVWord getRequiredSPIRVVersion() const override { + return static_cast(VersionNumber::SPIRV_1_2); + } +}; + class SPIRVComponentExecutionModes { typedef std::multimap SPIRVExecutionModeMap; @@ -724,6 +760,11 @@ class SPIRVComponentExecutionModes { return IsDenorm(EMK) || IsRoundingMode(EMK) || IsFPMode(EMK) || IsOtherFP(EMK); }; + auto IsMaxRegisters = [&](auto EMK) { + return EMK == ExecutionModeMaximumRegistersINTEL || + EMK == ExecutionModeMaximumRegistersIdINTEL || + EMK == ExecutionModeNamedMaximumRegistersINTEL; + }; auto IsCompatible = [&](SPIRVExecutionMode *EM0, SPIRVExecutionMode *EM1) { if (EM0->getTargetId() != EM1->getTargetId()) return true; @@ -737,7 +778,8 @@ class SPIRVComponentExecutionModes { return true; return !(IsDenorm(EMK0) && IsDenorm(EMK1)) && !(IsRoundingMode(EMK0) && IsRoundingMode(EMK1)) && - !(IsFPMode(EMK0) && IsFPMode(EMK1)); + !(IsFPMode(EMK0) && IsFPMode(EMK1)) && + !(IsMaxRegisters(EMK0) && IsMaxRegisters(EMK1)); }; for (auto I = ExecModes.begin(); I != ExecModes.end(); ++I) { assert(IsCompatible(ExecMode, (*I).second) && diff --git a/lib/SPIRV/libSPIRV/SPIRVEnum.h b/lib/SPIRV/libSPIRV/SPIRVEnum.h index 3b819c69e4..c6d171f3d7 100644 --- a/lib/SPIRV/libSPIRV/SPIRVEnum.h +++ b/lib/SPIRV/libSPIRV/SPIRVEnum.h @@ -263,6 +263,12 @@ template <> inline void SPIRVMap::init() { {CapabilityFastCompositeINTEL}); ADD_VEC_INIT(ExecutionModeNamedBarrierCountINTEL, {CapabilityVectorComputeINTEL}); + ADD_VEC_INIT(ExecutionModeMaximumRegistersINTEL, + {CapabilityRegisterLimitsINTEL}); + ADD_VEC_INIT(ExecutionModeMaximumRegistersIdINTEL, + {CapabilityRegisterLimitsINTEL}); + ADD_VEC_INIT(ExecutionModeNamedMaximumRegistersINTEL, + {CapabilityRegisterLimitsINTEL}); } template <> inline void SPIRVMap::init() { diff --git a/lib/SPIRV/libSPIRV/SPIRVIsValidEnum.h b/lib/SPIRV/libSPIRV/SPIRVIsValidEnum.h index cce19e345f..0a8157358b 100644 --- a/lib/SPIRV/libSPIRV/SPIRVIsValidEnum.h +++ b/lib/SPIRV/libSPIRV/SPIRVIsValidEnum.h @@ -55,7 +55,7 @@ using namespace spv; namespace SPIRV { inline bool isValid(spv::ExecutionModel V) { - switch (V) { + switch (static_cast(V)) { case ExecutionModelVertex: case ExecutionModelTessellationControl: case ExecutionModelTessellationEvaluation: @@ -71,6 +71,9 @@ inline bool isValid(spv::ExecutionModel V) { case ExecutionModelClosestHitKHR: case ExecutionModelMissKHR: case ExecutionModelCallableKHR: + case ExecutionModeMaximumRegistersINTEL: + case ExecutionModeMaximumRegistersIdINTEL: + case ExecutionModeNamedMaximumRegistersINTEL: return true; default: return false; diff --git a/lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h b/lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h index 45ec47fa25..0e0a008e9f 100644 --- a/lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h +++ b/lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h @@ -566,6 +566,7 @@ template <> inline void SPIRVMap::init() { add(CapabilityAtomicFloat16AddEXT, "AtomicFloat16AddEXT"); add(CapabilityDebugInfoModuleINTEL, "DebugInfoModuleINTEL"); add(CapabilityGroupUniformArithmeticKHR, "GroupUniformArithmeticKHR"); + add(CapabilityRegisterLimitsINTEL, "RegisterLimitsINTEL"); // From spirv_internal.hpp add(CapabilityFastCompositeINTEL, "FastCompositeINTEL"); @@ -586,6 +587,13 @@ template <> inline void SPIRVMap::init() { } SPIRV_DEF_NAMEMAP(Capability, SPIRVCapabilityNameMap) +template <> +inline void SPIRVMap::init() { + add(NamedMaximumNumberOfRegistersAutoINTEL, "AutoINTEL"); +} +SPIRV_DEF_NAMEMAP(NamedMaximumNumberOfRegisters, + SPIRVNamedMaximumNumberOfRegistersNameMap); + } /* namespace SPIRV */ #endif // SPIRV_LIBSPIRV_SPIRVNAMEMAPENUM_H diff --git a/lib/SPIRV/libSPIRV/SPIRVOpCodeEnum.h b/lib/SPIRV/libSPIRV/SPIRVOpCodeEnum.h index b11f921698..f20f79e351 100644 --- a/lib/SPIRV/libSPIRV/SPIRVOpCodeEnum.h +++ b/lib/SPIRV/libSPIRV/SPIRVOpCodeEnum.h @@ -295,6 +295,7 @@ _SPIRV_OP(TypePipeStorage, 322) _SPIRV_OP(ConstantPipeStorage, 323) _SPIRV_OP(CreatePipeFromPipeStorage, 324) _SPIRV_OP(ModuleProcessed, 330) +_SPIRV_OP(ExecutionModeId, 331) _SPIRV_OP(DecorateId, 332) _SPIRV_OP(GroupNonUniformElect, 333) _SPIRV_OP(GroupNonUniformAll, 334) diff --git a/lib/SPIRV/libSPIRV/SPIRVStream.cpp b/lib/SPIRV/libSPIRV/SPIRVStream.cpp index d5b66ae8a1..2e73429999 100644 --- a/lib/SPIRV/libSPIRV/SPIRVStream.cpp +++ b/lib/SPIRV/libSPIRV/SPIRVStream.cpp @@ -134,6 +134,7 @@ SPIRV_DEF_ENCDEC(Capability) SPIRV_DEF_ENCDEC(Decoration) SPIRV_DEF_ENCDEC(OCLExtOpKind) SPIRV_DEF_ENCDEC(SPIRVDebugExtOpKind) +SPIRV_DEF_ENCDEC(NamedMaximumNumberOfRegisters) SPIRV_DEF_ENCDEC(LinkageType) // Read a string with padded 0's at the end so that they form a stream of diff --git a/lib/SPIRV/libSPIRV/SPIRVStream.h b/lib/SPIRV/libSPIRV/SPIRVStream.h index 85e7e53cb0..8df2a6f53b 100644 --- a/lib/SPIRV/libSPIRV/SPIRVStream.h +++ b/lib/SPIRV/libSPIRV/SPIRVStream.h @@ -224,6 +224,7 @@ SPIRV_DEC_ENCDEC(Capability) SPIRV_DEC_ENCDEC(Decoration) SPIRV_DEC_ENCDEC(OCLExtOpKind) SPIRV_DEC_ENCDEC(SPIRVDebugExtOpKind) +SPIRV_DEC_ENCDEC(NamedMaximumNumberOfRegisters) SPIRV_DEC_ENCDEC(LinkageType) const SPIRVEncoder &operator<<(const SPIRVEncoder &O, const std::string &Str); diff --git a/lib/SPIRV/libSPIRV/spirv.hpp b/lib/SPIRV/libSPIRV/spirv.hpp index ec2a52eb59..91078e2bcb 100644 --- a/lib/SPIRV/libSPIRV/spirv.hpp +++ b/lib/SPIRV/libSPIRV/spirv.hpp @@ -182,6 +182,9 @@ enum ExecutionMode { ExecutionModeSchedulerTargetFmaxMhzINTEL = 5903, ExecutionModeFastCompositeKernelINTEL = 6088, ExecutionModeNamedBarrierCountINTEL = 6417, + ExecutionModeMaximumRegistersINTEL = 6461, + ExecutionModeMaximumRegistersIdINTEL = 6462, + ExecutionModeNamedMaximumRegistersINTEL = 6463, ExecutionModeMax = 0x7fffffff, }; @@ -1058,6 +1061,7 @@ enum Capability { CapabilityAtomicFloat16AddEXT = 6095, CapabilityDebugInfoModuleINTEL = 6114, CapabilityGroupUniformArithmeticKHR = 6400, + CapabilityRegisterLimitsINTEL = 6460, CapabilityMax = 0x7fffffff, }; @@ -1161,6 +1165,11 @@ enum PackedVectorFormat { PackedVectorFormatMax = 0x7fffffff, }; +enum NamedMaximumNumberOfRegisters { + NamedMaximumNumberOfRegistersAutoINTEL = 0, + NamedMaximumNumberOfRegistersMax = 0x7fffffff, +}; + enum Op { OpNop = 0, OpUndef = 1, diff --git a/test/extensions/INTEL/SPV_INTEL_maximum_registers/registerallocmode_maxreg_extension.ll b/test/extensions/INTEL/SPV_INTEL_maximum_registers/registerallocmode_maxreg_extension.ll new file mode 100644 index 0000000000..471e257442 --- /dev/null +++ b/test/extensions/INTEL/SPV_INTEL_maximum_registers/registerallocmode_maxreg_extension.ll @@ -0,0 +1,85 @@ +; RUN: llvm-as %s -o %t.bc +; RUN: llvm-spirv -spirv-text --spirv-ext=+SPV_INTEL_maximum_registers %t.bc +; RUN: FileCheck < %t.spt %s --check-prefix=CHECK-SPIRV +; RUN: llvm-spirv %t.bc --spirv-ext=+SPV_INTEL_maximum_registers -o %t.spv +; RUN: llvm-spirv -r %t.spv -spirv-target-env=SPV-IR -o - | llvm-dis -o %t.rev.ll +; RUN: FileCheck < %t.rev.ll %s --check-prefix=CHECK-LLVM + +; CHECK-SPIRV: EntryPoint [[#]] [[#FUNC0:]] "main_l3" +; CHECK-SPIRV: EntryPoint [[#]] [[#FUNC1:]] "main_l6" +; CHECK-SPIRV: EntryPoint [[#]] [[#FUNC2:]] "main_l9" +; CHECK-SPIRV: EntryPoint [[#]] [[#FUNC3:]] "main_l13" +; CHECK-SPIRV: EntryPoint [[#]] [[#FUNC4:]] "main_l19" + +; CHECK-SPIRV: ExecutionMode [[#FUNC0]] 6461 2 +; CHECK-SPIRV: ExecutionMode [[#FUNC1]] 6461 1 +; CHECK-SPIRV: ExecutionMode [[#FUNC2]] 6463 0 +; CHECK-SPIRV: ExecutionModeId [[#FUNC3]] 6462 [[#Const3:]] +; CHECK-SPIRV: TypeInt [[#TypeInt:]] 32 0 +; CHECK-SPIRV: Constant [[#TypeInt]] [[#Const3]] 3 + +; CHECK-SPIRV-NOT: ExecutionMode [[#FUNC4]] + +; CHECK-LLVM: !spirv.ExecutionMode = !{![[#FLAG0:]], ![[#FLAG1:]], ![[#FLAG2:]], ![[#FLAG3:]]} +; CHECK-LLVM: ![[#FLAG0]] = !{void ()* @main_l3, i32 6461, i32 2} +; CHECK-LLVM: ![[#FLAG1]] = !{void ()* @main_l6, i32 6461, i32 1} +; CHECK-LLVM: ![[#FLAG2]] = !{void ()* @main_l9, i32 6463, !"AutoINTEL"} +; CHECK-LLVM: ![[#FLAG3]] = !{void ()* @main_l13, i32 6462, ![[#VAL:]]} +; CHECK-LLVM: ![[#VAL]] = !{i32 3} + +target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" +target triple = "spir64" + +; Function Attrs: noinline nounwind optnone +define weak dso_local spir_kernel void @main_l3() #0 !RegisterAllocMode !10 { +newFuncRoot: + ret void +} + +; Function Attrs: noinline nounwind optnone +define weak dso_local spir_kernel void @main_l6() #0 !RegisterAllocMode !11 { +newFuncRoot: + ret void +} + +; Function Attrs: noinline nounwind optnone +define weak dso_local spir_kernel void @main_l9() #0 !RegisterAllocMode !12 { +newFuncRoot: + ret void +} + +; Function Attrs: noinline nounwind optnone +define weak dso_local spir_kernel void @main_l13() #0 !RegisterAllocMode !13 { +newFuncRoot: + ret void +} + +; Function Attrs: noinline nounwind optnone +define weak dso_local spir_kernel void @main_l19() #0 { +newFuncRoot: + ret void +} + +attributes #0 = { noinline nounwind optnone } + + +!opencl.compiler.options = !{!0, !0, !0, !0, !0, !0, !0, !0, !0, !0, !0, !0, !0, !0, !0, !0, !0, !0, !0, !0, !0, !0} +!spirv.Source = !{!2, !3, !3, !3, !3, !3, !2, !3, !2, !2, !2, !2, !2, !2, !2, !2, !2, !2, !2, !2, !2, !2} +!llvm.module.flags = !{!4, !5, !6, !7, !8} +!spirv.MemoryModel = !{!9, !9, !9, !9, !9, !9} +!spirv.ExecutionMode = !{} + +!0 = !{} +!2 = !{i32 4, i32 200000} +!3 = !{i32 3, i32 200000} +!4 = !{i32 1, !"wchar_size", i32 4} +!5 = !{i32 7, !"openmp", i32 50} +!6 = !{i32 7, !"openmp-device", i32 50} +!7 = !{i32 1, !"PIC Level", i32 2} +!8 = !{i32 7, !"frame-pointer", i32 2} +!9 = !{i32 2, i32 2} +!10 = !{i32 2} +!11 = !{i32 1} +!12 = !{!"AutoINTEL"} +!13 = !{!14} +!14 = !{i32 3}