36#define DEBUG_TYPE "spirv-module-analysis"
40 cl::desc(
"Dump MIR with SPIR-V dependencies info"),
45 cl::desc(
"SPIR-V capabilities to avoid if there are "
46 "other options enabling a feature"),
49 "SPIR-V Shader capability")));
59 "SPIRV module analysis",
true,
true)
63 Func.getContext().diagnose(
69 unsigned DefaultVal = 0) {
70 if (MdNode && OpIndex < MdNode->getNumOperands()) {
84 AvoidCaps.
S.
insert(SPIRV::Capability::Shader);
86 AvoidCaps.
S.
insert(SPIRV::Capability::Kernel);
91 bool MinVerOK = SPIRVVersion.
empty() || SPIRVVersion >= ReqMinVer;
93 ReqMaxVer.
empty() || SPIRVVersion.
empty() || SPIRVVersion <= ReqMaxVer;
96 if (ReqCaps.
empty()) {
97 if (ReqExts.
empty()) {
98 if (MinVerOK && MaxVerOK)
99 return {
true, {}, {}, ReqMinVer, ReqMaxVer};
102 }
else if (MinVerOK && MaxVerOK) {
103 if (ReqCaps.
size() == 1) {
104 auto Cap = ReqCaps[0];
107 SPIRV::OperandCategory::CapabilityOperand, Cap));
108 return {
true, {Cap}, std::move(ReqExts), ReqMinVer, ReqMaxVer};
118 for (
auto Cap : ReqCaps)
121 for (
size_t i = 0, Sz = UseCaps.
size(); i < Sz; ++i) {
122 auto Cap = UseCaps[i];
123 if (i == Sz - 1 || !AvoidCaps.
S.
contains(Cap)) {
125 SPIRV::OperandCategory::CapabilityOperand, Cap));
126 return {
true, {Cap}, std::move(ReqExts), ReqMinVer, ReqMaxVer};
134 if (
llvm::all_of(ReqExts, [&ST](
const SPIRV::Extension::Extension &Ext) {
135 return ST.canUseExtension(Ext);
146void SPIRVModuleAnalysisImpl::setBaseInfo(
const Module &M) {
150 MAI.RegisterAliasTable.clear();
151 MAI.InstrsToDelete.clear();
152 MAI.MBBNames.clear();
153 MAI.GlobalObjMap.clear();
154 MAI.GlobalVarList.clear();
155 MAI.ExtInstSetMap.clear();
156 MAI.InstrAuxDataRecords.clear();
158 MAI.Reqs.initAvailableCapabilities(*ST);
161 if (
auto MemModel =
M.getNamedMetadata(
"spirv.MemoryModel")) {
162 auto MemMD = MemModel->getOperand(0);
163 MAI.Addr =
static_cast<SPIRV::AddressingModel::AddressingModel
>(
166 static_cast<SPIRV::MemoryModel::MemoryModel
>(
getMetadataUInt(MemMD, 1));
169 MAI.Mem = ST->isShader() ? SPIRV::MemoryModel::GLSL450
170 : SPIRV::MemoryModel::OpenCL;
171 if (MAI.Mem == SPIRV::MemoryModel::OpenCL) {
172 unsigned PtrSize = ST->getPointerSize();
173 MAI.Addr = PtrSize == 32 ? SPIRV::AddressingModel::Physical32
174 : PtrSize == 64 ? SPIRV::AddressingModel::Physical64
175 : SPIRV::AddressingModel::Logical;
178 MAI.Addr = SPIRV::AddressingModel::Logical;
183 if (
auto VerNode =
M.getNamedMetadata(
"opencl.ocl.version")) {
184 MAI.SrcLang = SPIRV::SourceLanguage::OpenCL_C;
187 assert(VerNode->getNumOperands() > 0 &&
"Invalid SPIR");
188 auto VersionMD = VerNode->getOperand(0);
194 (std::max(1U, MajorNum) * 100 + MinorNum) * 1000 + RevNum;
197 if (
auto *CxxVerNode =
M.getNamedMetadata(
"opencl.cxx.version")) {
198 assert(CxxVerNode->getNumOperands() > 0 &&
"Invalid SPIR");
199 auto *CxxMD = CxxVerNode->getOperand(0);
203 if ((MAI.SrcLangVersion == 200000 && CxxVer == 100000) ||
204 (MAI.SrcLangVersion == 300000 && CxxVer == 202100000)) {
205 MAI.SrcLang = SPIRV::SourceLanguage::CPP_for_OpenCL;
206 MAI.SrcLangVersion = CxxVer;
209 "opencl cxx version is not compatible with opencl c version!");
217 if (!ST->isShader()) {
218 MAI.SrcLang = SPIRV::SourceLanguage::OpenCL_CPP;
219 MAI.SrcLangVersion = 100000;
221 MAI.SrcLang = SPIRV::SourceLanguage::Unknown;
222 MAI.SrcLangVersion = 0;
226 if (
auto ExtNode =
M.getNamedMetadata(
"opencl.used.extensions")) {
227 for (
unsigned I = 0,
E = ExtNode->getNumOperands();
I !=
E; ++
I) {
228 MDNode *MD = ExtNode->getOperand(
I);
238 MAI.Reqs.getAndAddRequirements(SPIRV::OperandCategory::MemoryModelOperand,
240 MAI.Reqs.getAndAddRequirements(SPIRV::OperandCategory::SourceLanguageOperand,
242 MAI.Reqs.getAndAddRequirements(SPIRV::OperandCategory::AddressingModelOperand,
245 if (MAI.Mem == SPIRV::MemoryModel::VulkanKHR)
246 MAI.Reqs.addExtension(SPIRV::Extension::SPV_KHR_vulkan_memory_model);
248 if (!ST->isShader()) {
250 MAI.ExtInstSetMap[
static_cast<unsigned>(
251 SPIRV::InstructionSet::OpenCL_std)] = MAI.getNextIDRegister();
262 if (
UseMI.getOpcode() != SPIRV::OpDecorate &&
263 UseMI.getOpcode() != SPIRV::OpMemberDecorate)
266 for (
unsigned I = 0;
I <
UseMI.getNumOperands(); ++
I) {
284 for (
unsigned i = 0; i <
MI.getNumOperands(); ++i) {
293 unsigned Opcode =
MI.getOpcode();
294 if ((Opcode == SPIRV::OpDecorate) && i >= 2) {
295 unsigned DecorationID =
MI.getOperand(1).getImm();
296 if (DecorationID != SPIRV::Decoration::FuncParamAttr &&
297 DecorationID != SPIRV::Decoration::UserSemantic &&
298 DecorationID != SPIRV::Decoration::CacheControlLoadINTEL &&
299 DecorationID != SPIRV::Decoration::CacheControlStoreINTEL)
305 if (!UseDefReg && MO.
isDef()) {
313 dbgs() <<
"Unexpectedly, no global id found for the operand ";
315 dbgs() <<
"\nInstruction: ";
342 case SPIRV::OpEnqueueKernel:
344 case SPIRV::OpGetKernelNDrangeSubGroupCount:
345 case SPIRV::OpGetKernelNDrangeMaxSubGroupSize:
347 case SPIRV::OpGetKernelWorkGroupSize:
348 case SPIRV::OpGetKernelPreferredWorkGroupSizeMultiple:
357 unsigned Opcode =
MI.getOpcode();
359 case SPIRV::OpTypeForwardPointer:
362 case SPIRV::OpVariable:
363 case SPIRV::OpUntypedVariableKHR:
364 return static_cast<SPIRV::StorageClass::StorageClass
>(
365 MI.getOperand(2).
getImm()) != SPIRV::StorageClass::Function;
366 case SPIRV::OpFunction:
367 case SPIRV::OpFunctionParameter:
370 if (GR->hasConstFunPtr() && Opcode == SPIRV::OpUndef) {
378 if (GR->getFunctionDefinitionByUse(&
MI.getOperand(0))) {
380 unsigned UseOp =
UseMI.getOpcode();
381 if (UseOp == SPIRV::OpConstantFunctionPointerINTEL ||
383 MAI.setSkipEmission(&
MI);
389 if (
UseMI.getOpcode() != SPIRV::OpConstantFunctionPointerINTEL)
395 MAI.setSkipEmission(&
MI);
399 return TII->isTypeDeclInstr(
MI) || TII->isConstantInstr(
MI) ||
400 TII->isInlineAsmDefInstr(
MI);
409void SPIRVModuleAnalysisImpl::visitFunPtrUse(
412 std::map<const Value *, unsigned> &GlobalToGReg,
414 const MachineOperand *OpFunDef = GR->getFunctionDefinitionByUse(FunPtrOp);
417 const MachineInstr *OpDefMI = OpFunDef->
getParent();
420 const MachineRegisterInfo &FunDefMRI = FunDefMF->
getRegInfo();
422 visitDecl(FunDefMRI, SignatureToGReg, GlobalToGReg, FunDefMF, *OpDefMI);
424 }
while (OpDefMI && (OpDefMI->
getOpcode() == SPIRV::OpFunction ||
425 OpDefMI->
getOpcode() == SPIRV::OpFunctionParameter));
427 MCRegister GlobalFunDefReg =
428 MAI.getRegisterAlias(FunDefMF, OpFunDef->
getReg());
430 "Function definition must refer to a global register");
431 MAI.setRegisterAlias(MF, OpReg, GlobalFunDefReg);
436void SPIRVModuleAnalysisImpl::visitDecl(
438 std::map<const Value *, unsigned> &GlobalToGReg,
const MachineFunction *MF,
440 unsigned Opcode =
MI.getOpcode();
443 for (
const MachineOperand &MO :
MI.operands()) {
444 if (!MO.isReg() || MO.isDef())
448 if (Opcode == SPIRV::OpConstantFunctionPointerINTEL &&
450 visitFunPtrUse(OpReg, &
MI.getOperand(2), SignatureToGReg, GlobalToGReg,
455 if (MAI.hasRegisterAlias(MF, MO.getReg()))
459 if (isDeclSection(MRI, *OpDefMI))
460 visitDecl(MRI, SignatureToGReg, GlobalToGReg, MF, *OpDefMI);
466 dbgs() <<
"Unexpectedly, no unique definition for the operand ";
468 dbgs() <<
"\nInstruction: ";
473 "No unique definition is found for the virtual register");
477 bool IsFunDef =
false;
478 if (TII->isSpecConstantInstr(
MI)) {
479 GReg = MAI.getNextIDRegister();
481 }
else if (Opcode == SPIRV::OpFunction ||
482 Opcode == SPIRV::OpFunctionParameter) {
483 GReg = handleFunctionOrParameter(MF,
MI, GlobalToGReg, IsFunDef);
484 }
else if (Opcode == SPIRV::OpTypeStruct ||
485 Opcode == SPIRV::OpConstantComposite) {
486 GReg = handleTypeDeclOrConstant(
MI, SignatureToGReg);
487 const MachineInstr *NextInstr =
MI.getNextNode();
489 ((Opcode == SPIRV::OpTypeStruct &&
490 NextInstr->
getOpcode() == SPIRV::OpTypeStructContinuedINTEL) ||
491 (Opcode == SPIRV::OpConstantComposite &&
493 SPIRV::OpConstantCompositeContinuedINTEL))) {
494 MCRegister Tmp = handleTypeDeclOrConstant(*NextInstr, SignatureToGReg);
496 MAI.setSkipEmission(NextInstr);
499 }
else if (TII->isTypeDeclInstr(
MI) || TII->isConstantInstr(
MI) ||
500 TII->isInlineAsmDefInstr(
MI)) {
501 GReg = handleTypeDeclOrConstant(
MI, SignatureToGReg);
502 }
else if (Opcode == SPIRV::OpVariable ||
503 Opcode == SPIRV::OpUntypedVariableKHR) {
504 GReg = handleVariable(MF,
MI, GlobalToGReg);
507 dbgs() <<
"\nInstruction: ";
513 MAI.setRegisterAlias(MF,
MI.getOperand(0).getReg(), GReg);
515 MAI.setSkipEmission(&
MI);
518MCRegister SPIRVModuleAnalysisImpl::handleFunctionOrParameter(
520 std::map<const Value *, unsigned> &GlobalToGReg,
bool &IsFunDef) {
521 const Value *GObj = GR->getGlobalObject(MF,
MI.getOperand(0).getReg());
522 assert(GObj &&
"Unregistered global definition");
526 assert(
F &&
"Expected a reference to a function or an argument");
527 IsFunDef = !
F->isDeclaration();
528 auto [It,
Inserted] = GlobalToGReg.try_emplace(GObj);
531 MCRegister GReg = MAI.getNextIDRegister();
538MCRegister SPIRVModuleAnalysisImpl::handleTypeDeclOrConstant(
541 auto [It,
Inserted] = SignatureToGReg.try_emplace(MISign);
544 MCRegister GReg = MAI.getNextIDRegister();
550MCRegister SPIRVModuleAnalysisImpl::handleVariable(
552 std::map<const Value *, unsigned> &GlobalToGReg) {
553 MAI.GlobalVarList.push_back(&
MI);
554 const Value *GObj = GR->getGlobalObject(MF,
MI.getOperand(0).getReg());
555 assert(GObj &&
"Unregistered global definition");
556 auto [It,
Inserted] = GlobalToGReg.try_emplace(GObj);
559 MCRegister GReg = MAI.getNextIDRegister();
563 MAI.GlobalObjMap[GV] = GReg;
567void SPIRVModuleAnalysisImpl::collectDeclarations(
const Module &M) {
569 std::map<const Value *, unsigned> GlobalToGReg;
574 const MachineRegisterInfo &MRI = MF->
getRegInfo();
575 unsigned PastHeader = 0;
576 for (MachineBasicBlock &
MBB : *MF) {
577 for (MachineInstr &
MI :
MBB) {
578 if (
MI.getNumOperands() == 0)
580 unsigned Opcode =
MI.getOpcode();
581 if (Opcode == SPIRV::OpFunction) {
582 if (PastHeader == 0) {
586 }
else if (Opcode == SPIRV::OpFunctionParameter) {
589 }
else if (PastHeader > 0) {
593 const MachineOperand &DefMO =
MI.getOperand(0);
595 case SPIRV::OpExtension:
596 MAI.Reqs.addExtension(SPIRV::Extension::Extension(DefMO.
getImm()));
597 MAI.setSkipEmission(&
MI);
599 case SPIRV::OpCapability:
600 MAI.Reqs.addCapability(SPIRV::Capability::Capability(DefMO.
getImm()));
601 MAI.setSkipEmission(&
MI);
606 if (DefMO.
isReg() && isDeclSection(MRI,
MI) &&
607 !MAI.hasRegisterAlias(MF, DefMO.
getReg()))
608 visitDecl(MRI, SignatureToGReg, GlobalToGReg, MF,
MI);
613 const MachineOperand &InvokeMO =
MI.getOperand(InvokeIdx);
614 if (InvokeMO.
isReg()) {
616 if (!MAI.hasRegisterAlias(MF, InvokeReg)) {
617 if (
const MachineInstr *
DefMI =
621 if (GR->getFunctionDefinitionByUse(FunPtrOp))
622 visitFunPtrUse(InvokeReg, FunPtrOp, SignatureToGReg,
641 if (
MI.getOpcode() == SPIRV::OpDecorate) {
643 auto Dec =
MI.getOperand(1).getImm();
644 if (Dec == SPIRV::Decoration::LinkageAttributes) {
645 auto Lnk =
MI.getOperand(
MI.getNumOperands() - 1).getImm();
646 if (Lnk == SPIRV::LinkageType::Import) {
651 MAI.GlobalObjMap[ImportedFunc] =
652 MAI.getRegisterAlias(
MI.getMF(), Target);
655 }
else if (
MI.getOpcode() == SPIRV::OpFunction) {
658 MCRegister GlobalReg = MAI.getRegisterAlias(
MI.getMF(),
Reg);
660 MAI.GlobalObjMap[
F] = GlobalReg;
672 auto FoundMI = IS.insert(std::move(MISign));
673 if (!FoundMI.second) {
674 if (
MI.getOpcode() == SPIRV::OpDecorate) {
676 "Decoration instructions must have at least 2 operands");
678 "Only OpDecorate instructions can be duplicates");
683 if (
MI.getOperand(1).getImm() != SPIRV::Decoration::FPFastMathMode)
689 assert(OrigMI->getNumOperands() ==
MI.getNumOperands() &&
690 "Original instruction must have the same number of operands");
692 OrigMI->getNumOperands() == 3 &&
693 "FPFastMathMode decoration must have 3 operands for OpDecorate");
694 unsigned OrigFlags = OrigMI->getOperand(2).getImm();
695 unsigned NewFlags =
MI.getOperand(2).getImm();
696 if (OrigFlags == NewFlags)
700 unsigned FinalFlags = OrigFlags | NewFlags;
702 <<
"Warning: Conflicting FPFastMathMode decoration flags "
704 << *OrigMI <<
"Original flags: " << OrigFlags
705 <<
", new flags: " << NewFlags
706 <<
". They will be merged on a best effort basis, but not "
707 "validated. Final flags: "
708 << FinalFlags <<
"\n";
715 assert(
false &&
"No original instruction found for the duplicate "
716 "OpDecorate, but we found one in IS.");
729void SPIRVModuleAnalysisImpl::processOtherInstrs(
const Module &M) {
732 if (
F.isDeclaration())
737 for (MachineBasicBlock &
MBB : *MF)
738 for (MachineInstr &
MI :
MBB) {
739 if (MAI.getSkipEmission(&
MI))
741 const unsigned OpCode =
MI.getOpcode();
742 if (OpCode == SPIRV::OpString) {
744 }
else if (OpCode == SPIRV::OpExtInst &&
MI.getOperand(2).isImm() &&
745 MI.getOperand(2).getImm() ==
746 SPIRV::InstructionSet::
747 NonSemantic_Shader_DebugInfo_100) {
754 MachineOperand Ins =
MI.getOperand(3);
755 namespace NS = SPIRV::NonSemanticExtInst;
756 static constexpr int64_t GlobalNonSemanticDITy[] = {
757 NS::DebugSource, NS::DebugCompilationUnit, NS::DebugInfoNone,
758 NS::DebugTypeBasic, NS::DebugTypePointer};
759 bool IsGlobalDI =
false;
760 for (
unsigned Idx = 0;
Idx < std::size(GlobalNonSemanticDITy); ++
Idx)
761 IsGlobalDI |= Ins.
getImm() == GlobalNonSemanticDITy[
Idx];
764 }
else if (OpCode == SPIRV::OpName || OpCode == SPIRV::OpMemberName) {
766 }
else if (OpCode == SPIRV::OpEntryPoint) {
768 }
else if (TII->isAliasingInstr(
MI)) {
770 }
else if (TII->isDecorationInstr(
MI)) {
771 if (
MI.getOpcode() == SPIRV::OpDecorate &&
772 MI.getOperand(1).getImm() ==
773 static_cast<unsigned>(
774 SPIRV::Decoration::AuxDataInstructionMetadata)) {
775 MAI.setSkipEmission(&
MI);
779 StringSwitch<std::optional<AMDMD>>(Str)
780 .Case(
"amdgpu.no.fine.grained.memory",
781 AMDMD::NoFineGrainedMemory)
782 .Case(
"amdgpu.no.remote.memory", AMDMD::NoRemoteMemory)
783 .Case(
"atomic.ignore.denormal.mode",
784 AMDMD::IgnoreDenormalMode)
785 .Default(std::nullopt);
787 MAI.InstrAuxDataRecords.push_back(
788 {MF,
MI.getOperand(0).getReg(), *MaybeKind});
792 collectFuncNames(
MI, &
F);
793 }
else if (TII->isConstantInstr(
MI)) {
797 }
else if (OpCode == SPIRV::OpFunction) {
798 collectFuncNames(
MI, &
F);
799 }
else if (OpCode == SPIRV::OpTypeForwardPointer) {
807 auto AliasingTier = [](
const MachineInstr *
MI) {
808 switch (
MI->getOpcode()) {
809 case SPIRV::OpAliasDomainDeclINTEL:
811 case SPIRV::OpAliasScopeDeclINTEL:
813 case SPIRV::OpAliasScopeListDeclINTEL:
820 [&](
const MachineInstr *
LHS,
const MachineInstr *
RHS) {
821 return AliasingTier(LHS) < AliasingTier(RHS);
828void SPIRVModuleAnalysisImpl::numberRegistersGlobally(
const Module &M) {
830 if (
F.isDeclaration())
834 for (MachineBasicBlock &
MBB : *MF) {
835 for (MachineInstr &
MI :
MBB) {
836 for (MachineOperand &
Op :
MI.operands()) {
840 if (MAI.hasRegisterAlias(MF,
Reg))
842 MCRegister NewReg = MAI.getNextIDRegister();
843 MAI.setRegisterAlias(MF,
Reg, NewReg);
845 if (
MI.getOpcode() != SPIRV::OpExtInst)
847 auto Set =
MI.getOperand(2).getImm();
848 auto [It,
Inserted] = MAI.ExtInstSetMap.try_emplace(Set);
850 It->second = MAI.getNextIDRegister();
858 SPIRV::OperandCategory::OperandCategory Category,
uint32_t i,
863void SPIRV::RequirementHandler::recursiveAddCapabilities(
865 for (
const auto &Cap : ToPrune) {
869 recursiveAddCapabilities(ImplicitDecls);
874 for (
const auto &Cap : ToAdd) {
875 bool IsNewlyInserted = AllCaps.insert(Cap).second;
876 if (!IsNewlyInserted)
880 recursiveAddCapabilities(ImplicitDecls);
881 MinimalCaps.push_back(Cap);
890 if (Req.
Cap.has_value())
896 if (!MaxVersion.empty() && Req.
MinVer > MaxVersion) {
898 <<
" and <= " << MaxVersion <<
"\n");
902 if (MinVersion.empty() || Req.
MinVer > MinVersion)
907 if (!MinVersion.empty() && Req.
MaxVer < MinVersion) {
909 <<
" and >= " << MinVersion <<
"\n");
913 if (MaxVersion.empty() || Req.
MaxVer < MaxVersion)
921 bool IsSatisfiable =
true;
922 auto TargetVer = ST.getSPIRVVersion();
924 if (!MaxVersion.empty() && !TargetVer.empty() && MaxVersion < TargetVer) {
926 dbgs() <<
"Target SPIR-V version too high for required features\n"
927 <<
"Required max version: " << MaxVersion <<
" target version "
928 << TargetVer <<
"\n");
929 IsSatisfiable =
false;
932 if (!MinVersion.empty() && !TargetVer.empty() && MinVersion > TargetVer) {
933 LLVM_DEBUG(
dbgs() <<
"Target SPIR-V version too low for required features\n"
934 <<
"Required min version: " << MinVersion
935 <<
" target version " << TargetVer <<
"\n");
936 IsSatisfiable =
false;
939 if (!MinVersion.empty() && !MaxVersion.empty() && MinVersion > MaxVersion) {
942 <<
"Version is too low for some features and too high for others.\n"
943 <<
"Required SPIR-V min version: " << MinVersion
944 <<
" required SPIR-V max version " << MaxVersion <<
"\n");
945 IsSatisfiable =
false;
950 AvoidCaps.
S.
insert(SPIRV::Capability::Shader);
952 AvoidCaps.
S.
insert(SPIRV::Capability::Kernel);
954 for (
auto Cap : MinimalCaps) {
955 if (AvailableCaps.contains(Cap) && !AvoidCaps.
S.
contains(Cap))
959 OperandCategory::CapabilityOperand, Cap)
961 IsSatisfiable =
false;
964 for (
auto Ext : AllExtensions) {
965 if (ST.canUseExtension(Ext))
969 OperandCategory::ExtensionOperand, Ext)
971 IsSatisfiable =
false;
980 for (
const auto Cap : ToAdd)
981 if (AvailableCaps.insert(Cap).second)
983 SPIRV::OperandCategory::CapabilityOperand, Cap));
987 const Capability::Capability
ToRemove,
988 const Capability::Capability IfPresent) {
989 if (AllCaps.contains(IfPresent)) {
999 addAvailableCaps({Capability::Shader, Capability::Linkage, Capability::Int8,
1000 Capability::Int16});
1004 Capability::GroupNonUniformVote,
1005 Capability::GroupNonUniformArithmetic,
1006 Capability::GroupNonUniformBallot,
1007 Capability::GroupNonUniformClustered,
1008 Capability::GroupNonUniformShuffle,
1009 Capability::GroupNonUniformShuffleRelative,
1010 Capability::GroupNonUniformQuad});
1014 Capability::DotProductInput4x8Bit,
1015 Capability::DotProductInput4x8BitPacked,
1016 Capability::DemoteToHelperInvocation});
1019 for (
auto Extension : ST.getAllAvailableExtensions()) {
1025 if (!ST.isShader()) {
1026 initAvailableCapabilitiesForOpenCL(ST);
1030 if (ST.isShader()) {
1031 initAvailableCapabilitiesForVulkan(ST);
1038void RequirementHandler::initAvailableCapabilitiesForOpenCL(
1042 Capability::Kernel, Capability::Vector16,
1043 Capability::Groups, Capability::GenericPointer,
1044 Capability::StorageImageWriteWithoutFormat,
1045 Capability::StorageImageReadWithoutFormat});
1046 if (ST.hasOpenCLFullProfile())
1048 if (ST.hasOpenCLImageSupport()) {
1050 Capability::Image1D, Capability::SampledBuffer,
1051 Capability::ImageBuffer});
1052 if (
ST.isAtLeastOpenCLVer(VersionTuple(2, 0)))
1055 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 1)) &&
1056 ST.isAtLeastOpenCLVer(VersionTuple(2, 2)))
1058 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 4)))
1059 addAvailableCaps({Capability::DenormPreserve, Capability::DenormFlushToZero,
1060 Capability::SignedZeroInfNanPreserve,
1061 Capability::RoundingModeRTE,
1062 Capability::RoundingModeRTZ});
1069void RequirementHandler::initAvailableCapabilitiesForVulkan(
1070 const SPIRVSubtarget &ST) {
1074 Capability::Float16,
1075 Capability::Float64,
1076 Capability::GroupNonUniform,
1077 Capability::Image1D,
1078 Capability::SampledBuffer,
1079 Capability::ImageBuffer,
1080 Capability::UniformBufferArrayDynamicIndexing,
1081 Capability::SampledImageArrayDynamicIndexing,
1082 Capability::StorageBufferArrayDynamicIndexing,
1083 Capability::StorageImageArrayDynamicIndexing,
1084 Capability::DerivativeControl,
1086 Capability::ImageQuery,
1087 Capability::ImageGatherExtended,
1088 Capability::Addresses,
1089 Capability::VulkanMemoryModelKHR,
1090 Capability::StorageImageExtendedFormats,
1091 Capability::StorageImageMultisample,
1092 Capability::ImageMSArray});
1094 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 3)) ||
1095 ST.canUseExtension(Extension::SPV_KHR_variable_pointers))
1097 Capability::VariablePointers});
1100 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 5))) {
1102 {Capability::Int64Atomics, Capability::ShaderNonUniformEXT,
1103 Capability::RuntimeDescriptorArrayEXT,
1104 Capability::InputAttachmentArrayDynamicIndexingEXT,
1105 Capability::UniformTexelBufferArrayDynamicIndexingEXT,
1106 Capability::StorageTexelBufferArrayDynamicIndexingEXT,
1107 Capability::UniformBufferArrayNonUniformIndexingEXT,
1108 Capability::SampledImageArrayNonUniformIndexingEXT,
1109 Capability::StorageBufferArrayNonUniformIndexingEXT,
1110 Capability::StorageImageArrayNonUniformIndexingEXT,
1111 Capability::InputAttachmentArrayNonUniformIndexingEXT,
1112 Capability::UniformTexelBufferArrayNonUniformIndexingEXT,
1113 Capability::StorageTexelBufferArrayNonUniformIndexingEXT});
1117 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 6)))
1119 Capability::StorageImageReadWithoutFormat});
1130 int64_t DecOp =
MI.getOperand(DecIndex).getImm();
1131 auto Dec =
static_cast<SPIRV::Decoration::Decoration
>(DecOp);
1133 SPIRV::OperandCategory::DecorationOperand, Dec, ST, Reqs));
1135 if (Dec == SPIRV::Decoration::BuiltIn) {
1136 int64_t BuiltInOp =
MI.getOperand(DecIndex + 1).getImm();
1137 auto BuiltIn =
static_cast<SPIRV::BuiltIn::BuiltIn
>(BuiltInOp);
1139 SPIRV::OperandCategory::BuiltInOperand, BuiltIn, ST, Reqs));
1140 }
else if (Dec == SPIRV::Decoration::LinkageAttributes) {
1141 int64_t LinkageOp =
MI.getOperand(
MI.getNumOperands() - 1).getImm();
1142 SPIRV::LinkageType::LinkageType LnkType =
1143 static_cast<SPIRV::LinkageType::LinkageType
>(LinkageOp);
1144 if (LnkType == SPIRV::LinkageType::LinkOnceODR)
1145 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_linkonce_odr);
1146 else if (LnkType == SPIRV::LinkageType::WeakAMD) {
1147 Reqs.
addExtension(SPIRV::Extension::SPV_AMD_weak_linkage);
1150 }
else if (Dec == SPIRV::Decoration::CacheControlLoadINTEL ||
1151 Dec == SPIRV::Decoration::CacheControlStoreINTEL) {
1152 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_cache_controls);
1153 }
else if (Dec == SPIRV::Decoration::HostAccessINTEL) {
1154 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_global_variable_host_access);
1155 }
else if (Dec == SPIRV::Decoration::InitModeINTEL ||
1156 Dec == SPIRV::Decoration::ImplementInRegisterMapINTEL) {
1158 SPIRV::Extension::SPV_INTEL_global_variable_fpga_decorations);
1159 }
else if (Dec == SPIRV::Decoration::NonUniformEXT) {
1161 }
else if (Dec == SPIRV::Decoration::FPMaxErrorDecorationINTEL) {
1163 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_fp_max_error);
1164 }
else if (Dec == SPIRV::Decoration::FPFastMathMode) {
1165 if (ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2)) {
1167 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_float_controls2);
1176 assert(
MI.getNumOperands() >= 8 &&
"Insufficient operands for OpTypeImage");
1179 int64_t ImgFormatOp =
MI.getOperand(7).getImm();
1180 auto ImgFormat =
static_cast<SPIRV::ImageFormat::ImageFormat
>(ImgFormatOp);
1184 bool IsArrayed =
MI.getOperand(4).getImm() == 1;
1185 bool IsMultisampled =
MI.getOperand(5).getImm() == 1;
1186 bool NoSampler =
MI.getOperand(6).getImm() == 2;
1189 switch (
MI.getOperand(2).getImm()) {
1190 case SPIRV::Dim::DIM_1D:
1192 : SPIRV::Capability::Sampled1D);
1194 case SPIRV::Dim::DIM_2D:
1195 if (IsMultisampled && NoSampler)
1197 if (IsMultisampled && IsArrayed)
1200 case SPIRV::Dim::DIM_3D:
1202 case SPIRV::Dim::DIM_Cube:
1206 : SPIRV::Capability::SampledCubeArray);
1208 case SPIRV::Dim::DIM_Rect:
1210 : SPIRV::Capability::SampledRect);
1212 case SPIRV::Dim::DIM_Buffer:
1214 : SPIRV::Capability::SampledBuffer);
1216 case SPIRV::Dim::DIM_SubpassData:
1222 if (!ST.isShader()) {
1223 if (
MI.getNumOperands() > 8 &&
1224 MI.getOperand(8).getImm() == SPIRV::AccessQualifier::ReadWrite)
1233 TypeDef->
getOpcode() == SPIRV::OpTypeFloat &&
1249#define ATOM_FLT_REQ_EXT_MSG(ExtName) \
1250 "The atomic float instruction requires the following SPIR-V " \
1251 "extension: SPV_EXT_shader_atomic_float" ExtName
1256 MI.getMF()->getRegInfo().getVRegDef(
MI.getOperand(1).getReg());
1259 if (Rank != 2 && Rank != 4)
1261 "must be a 2-component or 4 component vector");
1266 if (EltTypeDef->
getOpcode() != SPIRV::OpTypeFloat ||
1269 "The element type for the result type of an atomic vector float "
1270 "instruction must be a 16-bit floating-point scalar");
1277 "The element type for the result type of an atomic vector float "
1278 "instruction cannot be a bfloat16 scalar");
1279 if (!ST.canUseExtension(SPIRV::Extension::SPV_NV_shader_atomic_fp16_vector))
1281 "The atomic float16 vector instruction requires the following SPIR-V "
1282 "extension: SPV_NV_shader_atomic_fp16_vector");
1284 Reqs.
addExtension(SPIRV::Extension::SPV_NV_shader_atomic_fp16_vector);
1285 Reqs.
addCapability(SPIRV::Capability::AtomicFloat16VectorNV);
1292 "Expect register operand in atomic float instruction");
1293 Register TypeReg =
MI.getOperand(1).getReg();
1299 if (TypeDef->
getOpcode() != SPIRV::OpTypeFloat)
1301 "floating-point type scalar");
1304 unsigned Op =
MI.getOpcode();
1305 if (
Op == SPIRV::OpAtomicFAddEXT) {
1306 if (!ST.canUseExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float_add))
1308 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float_add);
1312 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics))
1314 "The atomic bfloat16 instruction requires the following SPIR-V "
1315 "extension: SPV_INTEL_16bit_atomics",
1317 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics);
1318 Reqs.
addCapability(SPIRV::Capability::AtomicBFloat16AddINTEL);
1320 if (!ST.canUseExtension(
1321 SPIRV::Extension::SPV_EXT_shader_atomic_float16_add))
1323 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float16_add);
1335 "Unexpected floating-point type width in atomic float instruction");
1338 if (!ST.canUseExtension(
1339 SPIRV::Extension::SPV_EXT_shader_atomic_float_min_max))
1341 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float_min_max);
1345 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics))
1347 "The atomic bfloat16 instruction requires the following SPIR-V "
1348 "extension: SPV_INTEL_16bit_atomics",
1350 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics);
1351 Reqs.
addCapability(SPIRV::Capability::AtomicBFloat16MinMaxINTEL);
1353 Reqs.
addCapability(SPIRV::Capability::AtomicFloat16MinMaxEXT);
1357 Reqs.
addCapability(SPIRV::Capability::AtomicFloat32MinMaxEXT);
1360 Reqs.
addCapability(SPIRV::Capability::AtomicFloat64MinMaxEXT);
1364 "Unexpected floating-point type width in atomic float instruction");
1370 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1374 return Dim == SPIRV::Dim::DIM_Buffer && Sampled == 1;
1378 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1382 return Dim == SPIRV::Dim::DIM_Buffer && Sampled == 2;
1386 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1390 return Dim != SPIRV::Dim::DIM_Buffer && Sampled == 1;
1394 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1398 return Dim == SPIRV::Dim::DIM_SubpassData && Sampled == 2;
1402 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1406 return Dim != SPIRV::Dim::DIM_Buffer && Sampled == 2;
1410 if (SampledImageInst->
getOpcode() != SPIRV::OpTypeSampledImage)
1421 if (
MI.getOpcode() != SPIRV::OpDecorate)
1425 if (Dec == SPIRV::Decoration::NonUniformEXT)
1438 Register ResTypeReg = Instr.getOperand(1).getReg();
1443 if (
StorageClass != SPIRV::StorageClass::StorageClass::UniformConstant &&
1444 StorageClass != SPIRV::StorageClass::StorageClass::Uniform &&
1445 StorageClass != SPIRV::StorageClass::StorageClass::StorageBuffer) {
1452 auto FirstIndexReg = Instr.getOperand(3).getReg();
1453 bool FirstIndexIsConstant =
1456 if (
StorageClass == SPIRV::StorageClass::StorageClass::StorageBuffer) {
1459 SPIRV::Capability::StorageBufferArrayNonUniformIndexingEXT);
1460 else if (!FirstIndexIsConstant)
1462 SPIRV::Capability::StorageBufferArrayDynamicIndexing);
1468 if (PointeeType->
getOpcode() != SPIRV::OpTypeImage &&
1469 PointeeType->
getOpcode() != SPIRV::OpTypeSampledImage &&
1470 PointeeType->
getOpcode() != SPIRV::OpTypeSampler) {
1477 SPIRV::Capability::UniformTexelBufferArrayNonUniformIndexingEXT);
1478 else if (!FirstIndexIsConstant)
1480 SPIRV::Capability::UniformTexelBufferArrayDynamicIndexingEXT);
1484 SPIRV::Capability::InputAttachmentArrayNonUniformIndexingEXT);
1485 else if (!FirstIndexIsConstant)
1487 SPIRV::Capability::InputAttachmentArrayDynamicIndexingEXT);
1491 SPIRV::Capability::StorageTexelBufferArrayNonUniformIndexingEXT);
1492 else if (!FirstIndexIsConstant)
1494 SPIRV::Capability::StorageTexelBufferArrayDynamicIndexingEXT);
1497 PointeeType->
getOpcode() == SPIRV::OpTypeSampler) {
1500 SPIRV::Capability::SampledImageArrayNonUniformIndexingEXT);
1501 else if (!FirstIndexIsConstant)
1503 SPIRV::Capability::SampledImageArrayDynamicIndexing);
1507 SPIRV::Capability::StorageImageArrayNonUniformIndexingEXT);
1508 else if (!FirstIndexIsConstant)
1510 SPIRV::Capability::StorageImageArrayDynamicIndexing);
1515 if (TypeInst->
getOpcode() != SPIRV::OpTypeImage)
1524 if (ST.canUseExtension(SPIRV::Extension::SPV_KHR_integer_dot_product))
1525 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_integer_dot_product);
1529 assert(
MI.getOperand(2).isReg() &&
"Unexpected operand in dot");
1531 ST.getSPIRVGlobalRegistry());
1532 assert(TypeDef &&
"Unexpected type instruction for dot input");
1533 if (TypeDef->
getOpcode() == SPIRV::OpTypeInt) {
1535 Reqs.
addCapability(SPIRV::Capability::DotProductInput4x8BitPacked);
1542 "Dot operand of 8-bit integer type requires 4 components");
1543 Reqs.
addCapability(SPIRV::Capability::DotProductInput4x8Bit);
1559 unsigned AddrSpace = ASOp.
getImm();
1560 if (AddrSpace != SPIRV::StorageClass::UniformConstant) {
1561 if (!ST.canUseExtension(
1563 SPV_EXT_relaxed_printf_string_address_space)) {
1565 "required because printf uses a format string not "
1566 "in constant address space.",
1570 SPIRV::Extension::SPV_EXT_relaxed_printf_string_address_space);
1579 if (
MI.getNumOperands() <= OpIdx)
1581 uint32_t Mask =
MI.getOperand(OpIdx).getImm();
1583 if (Mask & (1U <<
I))
1594 if (ElemTypeDef->
getOpcode() == SPIRV::OpTypePointer &&
1595 ST.canUseExtension(SPIRV::Extension::SPV_INTEL_masked_gather_scatter)) {
1596 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_masked_gather_scatter);
1597 Reqs.
addCapability(SPIRV::Capability::MaskedGatherScatterINTEL);
1605 unsigned Op =
MI.getOpcode();
1607 case SPIRV::OpMemoryModel: {
1608 int64_t Addr =
MI.getOperand(0).getImm();
1611 int64_t Mem =
MI.getOperand(1).getImm();
1616 case SPIRV::OpEntryPoint: {
1617 int64_t Exe =
MI.getOperand(0).getImm();
1622 case SPIRV::OpExecutionMode:
1623 case SPIRV::OpExecutionModeId: {
1624 int64_t Exe =
MI.getOperand(1).getImm();
1629 case SPIRV::OpTypeMatrix:
1632 case SPIRV::OpTypeInt: {
1633 unsigned BitWidth =
MI.getOperand(1).getImm();
1641 ST.canUseExtension(SPIRV::Extension::SPV_INTEL_int4)) {
1645 if (!ST.canUseExtension(
1646 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_integers))
1648 "OpTypeInt type with a width other than 8, 16, 32 or 64 bits "
1649 "requires the following SPIR-V extension: "
1650 "SPV_ALTERA_arbitrary_precision_integers");
1652 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_integers);
1653 Reqs.
addCapability(SPIRV::Capability::ArbitraryPrecisionIntegersALTERA);
1657 case SPIRV::OpDot: {
1661 Reqs.
addCapability(SPIRV::Capability::BFloat16DotProductKHR);
1664 case SPIRV::OpTypeFloat: {
1665 unsigned BitWidth =
MI.getOperand(1).getImm();
1670 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_bfloat16))
1672 "following SPIR-V extension: SPV_KHR_bfloat16",
1682 case SPIRV::OpTypeVector: {
1683 unsigned NumComponents =
MI.getOperand(2).getImm();
1684 if (NumComponents == 8 || NumComponents == 16)
1689 "OpTypeVector with " +
Twine(NumComponents) +
1690 " components requires the following SPIR-V extension: "
1691 "SPV_EXT_long_vector");
1696 case SPIRV::OpTypeVectorIdEXT: {
1697 if (!ST.canUseExtension(SPIRV::Extension::SPV_EXT_long_vector))
1699 "extension: SPV_EXT_long_vector extension");
1700 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_long_vector);
1705 case SPIRV::OpTypePointer: {
1706 auto SC =
MI.getOperand(1).getImm();
1717 (TypeDef->
getOpcode() == SPIRV::OpTypeFloat) &&
1722 case SPIRV::OpExtInst: {
1723 if (
MI.getOperand(2).getImm() ==
1724 static_cast<int64_t
>(
1725 SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100)) {
1726 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_non_semantic_info);
1729 if (
MI.getOperand(3).getImm() ==
1730 static_cast<int64_t
>(SPIRV::OpenCLExtInst::printf)) {
1734 if (
MI.getOperand(2).getImm() ==
1735 static_cast<int64_t
>(SPIRV::InstructionSet::OpenCL_std)) {
1741 if (TypeDef && TypeDef->getOpcode() == SPIRV::OpTypeVector)
1742 TypeDef = MRI.
getVRegDef(TypeDef->getOperand(1).getReg());
1747 bool UsesBFloat16 = IsBFloat16(MRI.
getVRegDef(
MI.getOperand(1).getReg()));
1748 for (
unsigned I = 4,
E =
MI.getNumOperands();
I <
E && !UsesBFloat16;
1757 if (!ST.canUseExtension(
1758 SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic)) {
1760 MI,
"OpenCL Extended instructions with bfloat16 require the "
1761 "following SPIR-V extension: SPV_INTEL_bfloat16_arithmetic");
1764 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic);
1765 Reqs.
addCapability(SPIRV::Capability::BFloat16ArithmeticINTEL);
1770 case SPIRV::OpAliasDomainDeclINTEL:
1771 case SPIRV::OpAliasScopeDeclINTEL:
1772 case SPIRV::OpAliasScopeListDeclINTEL: {
1773 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_memory_access_aliasing);
1774 Reqs.
addCapability(SPIRV::Capability::MemoryAccessAliasingINTEL);
1777 case SPIRV::OpBitReverse:
1778 case SPIRV::OpBitFieldInsert:
1779 case SPIRV::OpBitFieldSExtract:
1780 case SPIRV::OpBitFieldUExtract:
1781 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_bit_instructions)) {
1785 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_bit_instructions);
1788 case SPIRV::OpTypeRuntimeArray:
1791 case SPIRV::OpTypeOpaque:
1792 case SPIRV::OpTypeEvent:
1795 case SPIRV::OpTypePipe:
1796 case SPIRV::OpTypeReserveId:
1799 case SPIRV::OpTypeDeviceEvent:
1800 case SPIRV::OpTypeQueue:
1801 case SPIRV::OpBuildNDRange:
1802 case SPIRV::OpEnqueueKernel:
1803 case SPIRV::OpGetKernelNDrangeSubGroupCount:
1804 case SPIRV::OpGetKernelNDrangeMaxSubGroupSize:
1805 case SPIRV::OpGetKernelWorkGroupSize:
1806 case SPIRV::OpGetKernelPreferredWorkGroupSizeMultiple:
1809 case SPIRV::OpDecorate:
1810 case SPIRV::OpDecorateId:
1811 case SPIRV::OpDecorateString:
1814 case SPIRV::OpMemberDecorate:
1815 case SPIRV::OpMemberDecorateString:
1818 case SPIRV::OpInBoundsPtrAccessChain:
1821 case SPIRV::OpConstantSampler:
1824 case SPIRV::OpInBoundsAccessChain:
1825 case SPIRV::OpAccessChain:
1828 case SPIRV::OpTypeImage:
1831 case SPIRV::OpTypeSampler:
1832 if (!ST.isShader()) {
1836 case SPIRV::OpTypeForwardPointer:
1840 case SPIRV::OpAtomicFlagTestAndSet:
1841 case SPIRV::OpAtomicLoad:
1842 case SPIRV::OpAtomicStore:
1843 case SPIRV::OpAtomicExchange:
1844 case SPIRV::OpAtomicCompareExchange:
1845 case SPIRV::OpAtomicCompareExchangeWeak:
1846 case SPIRV::OpAtomicIIncrement:
1847 case SPIRV::OpAtomicIDecrement:
1848 case SPIRV::OpAtomicIAdd:
1849 case SPIRV::OpAtomicISub:
1850 case SPIRV::OpAtomicUMin:
1851 case SPIRV::OpAtomicUMax:
1852 case SPIRV::OpAtomicSMin:
1853 case SPIRV::OpAtomicSMax:
1854 case SPIRV::OpAtomicAnd:
1855 case SPIRV::OpAtomicOr:
1856 case SPIRV::OpAtomicXor: {
1859 if (
Op == SPIRV::OpAtomicStore) {
1862 ST.getSPIRVGlobalRegistry());
1863 assert(TypeDef &&
"Unexpected type instruction for OpAtomicStore");
1865 assert(
MI.getOperand(1).isReg() &&
"Unexpected operand in atomic");
1869 if (TypeDef->
getOpcode() == SPIRV::OpTypeInt) {
1874 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics))
1876 "16-bit integer atomic operations require the following SPIR-V "
1877 "extension: SPV_INTEL_16bit_atomics",
1879 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics);
1881 case SPIRV::OpAtomicLoad:
1882 case SPIRV::OpAtomicStore:
1883 case SPIRV::OpAtomicExchange:
1884 case SPIRV::OpAtomicCompareExchange:
1885 case SPIRV::OpAtomicCompareExchangeWeak:
1887 SPIRV::Capability::AtomicInt16CompareExchangeINTEL);
1895 if (
is_contained({SPIRV::OpAtomicLoad, SPIRV::OpAtomicStore,
1896 SPIRV::OpAtomicExchange},
1898 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics))
1900 "The atomic bfloat16 instruction requires the following SPIR-V "
1901 "extension: SPV_INTEL_16bit_atomics",
1903 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics);
1904 Reqs.
addCapability(SPIRV::Capability::AtomicBFloat16LoadStoreINTEL);
1909 case SPIRV::OpGroupNonUniformIAdd:
1910 case SPIRV::OpGroupNonUniformFAdd:
1911 case SPIRV::OpGroupNonUniformIMul:
1912 case SPIRV::OpGroupNonUniformFMul:
1913 case SPIRV::OpGroupNonUniformSMin:
1914 case SPIRV::OpGroupNonUniformUMin:
1915 case SPIRV::OpGroupNonUniformFMin:
1916 case SPIRV::OpGroupNonUniformSMax:
1917 case SPIRV::OpGroupNonUniformUMax:
1918 case SPIRV::OpGroupNonUniformFMax:
1919 case SPIRV::OpGroupNonUniformBitwiseAnd:
1920 case SPIRV::OpGroupNonUniformBitwiseOr:
1921 case SPIRV::OpGroupNonUniformBitwiseXor:
1922 case SPIRV::OpGroupNonUniformLogicalAnd:
1923 case SPIRV::OpGroupNonUniformLogicalOr:
1924 case SPIRV::OpGroupNonUniformLogicalXor: {
1926 int64_t GroupOp =
MI.getOperand(3).getImm();
1928 case SPIRV::GroupOperation::Reduce:
1929 case SPIRV::GroupOperation::InclusiveScan:
1930 case SPIRV::GroupOperation::ExclusiveScan:
1931 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformArithmetic);
1933 case SPIRV::GroupOperation::ClusteredReduce:
1934 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformClustered);
1936 case SPIRV::GroupOperation::PartitionedReduceNV:
1937 case SPIRV::GroupOperation::PartitionedInclusiveScanNV:
1938 case SPIRV::GroupOperation::PartitionedExclusiveScanNV:
1939 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformPartitionedNV);
1944 case SPIRV::OpGroupNonUniformQuadSwap:
1947 case SPIRV::OpImageQueryLod:
1950 case SPIRV::OpImageQuerySize:
1951 case SPIRV::OpImageQuerySizeLod:
1952 case SPIRV::OpImageQueryLevels:
1953 case SPIRV::OpImageQuerySamples:
1957 case SPIRV::OpImageQueryFormat: {
1958 Register ResultReg =
MI.getOperand(0).getReg();
1960 static const unsigned CompareOps[] = {
1961 SPIRV::OpIEqual, SPIRV::OpINotEqual,
1962 SPIRV::OpUGreaterThan, SPIRV::OpUGreaterThanEqual,
1963 SPIRV::OpULessThan, SPIRV::OpULessThanEqual,
1964 SPIRV::OpSGreaterThan, SPIRV::OpSGreaterThanEqual,
1965 SPIRV::OpSLessThan, SPIRV::OpSLessThanEqual};
1967 auto CheckAndAddExtension = [&](int64_t ImmVal) {
1968 if (ImmVal == 4323 || ImmVal == 4324) {
1969 if (ST.canUseExtension(SPIRV::Extension::SPV_EXT_image_raw10_raw12))
1970 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_image_raw10_raw12);
1973 "SPV_EXT_image_raw10_raw12 extension");
1978 unsigned Opc = UseInst.getOpcode();
1980 if (
Opc == SPIRV::OpSwitch) {
1983 CheckAndAddExtension(
Op.getImm());
1985 for (
unsigned i = 1; i < UseInst.getNumOperands(); ++i) {
1988 if (ConstInst && ConstInst->
getOpcode() == SPIRV::OpConstantI) {
1991 CheckAndAddExtension(ImmVal);
1999 case SPIRV::OpGroupNonUniformShuffle:
2000 case SPIRV::OpGroupNonUniformShuffleXor:
2001 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformShuffle);
2003 case SPIRV::OpGroupNonUniformShuffleUp:
2004 case SPIRV::OpGroupNonUniformShuffleDown:
2005 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformShuffleRelative);
2007 case SPIRV::OpGroupAll:
2008 case SPIRV::OpGroupAny:
2009 case SPIRV::OpGroupBroadcast:
2010 case SPIRV::OpGroupIAdd:
2011 case SPIRV::OpGroupFAdd:
2012 case SPIRV::OpGroupFMin:
2013 case SPIRV::OpGroupUMin:
2014 case SPIRV::OpGroupSMin:
2015 case SPIRV::OpGroupFMax:
2016 case SPIRV::OpGroupUMax:
2017 case SPIRV::OpGroupSMax:
2020 case SPIRV::OpGroupNonUniformElect:
2023 case SPIRV::OpGroupNonUniformAll:
2024 case SPIRV::OpGroupNonUniformAny:
2025 case SPIRV::OpGroupNonUniformAllEqual:
2028 case SPIRV::OpGroupNonUniformBroadcast:
2029 case SPIRV::OpGroupNonUniformBroadcastFirst:
2030 case SPIRV::OpGroupNonUniformBallot:
2031 case SPIRV::OpGroupNonUniformInverseBallot:
2032 case SPIRV::OpGroupNonUniformBallotBitExtract:
2033 case SPIRV::OpGroupNonUniformBallotBitCount:
2034 case SPIRV::OpGroupNonUniformBallotFindLSB:
2035 case SPIRV::OpGroupNonUniformBallotFindMSB:
2036 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformBallot);
2038 case SPIRV::OpSubgroupShuffleINTEL:
2039 case SPIRV::OpSubgroupShuffleDownINTEL:
2040 case SPIRV::OpSubgroupShuffleUpINTEL:
2041 case SPIRV::OpSubgroupShuffleXorINTEL:
2042 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {
2043 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_subgroups);
2044 Reqs.
addCapability(SPIRV::Capability::SubgroupShuffleINTEL);
2047 case SPIRV::OpSubgroupBlockReadINTEL:
2048 case SPIRV::OpSubgroupBlockWriteINTEL:
2049 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {
2050 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_subgroups);
2051 Reqs.
addCapability(SPIRV::Capability::SubgroupBufferBlockIOINTEL);
2054 case SPIRV::OpSubgroupImageBlockReadINTEL:
2055 case SPIRV::OpSubgroupImageBlockWriteINTEL:
2056 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {
2057 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_subgroups);
2058 Reqs.
addCapability(SPIRV::Capability::SubgroupImageBlockIOINTEL);
2061 case SPIRV::OpSubgroupImageMediaBlockReadINTEL:
2062 case SPIRV::OpSubgroupImageMediaBlockWriteINTEL:
2063 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_media_block_io)) {
2064 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_media_block_io);
2065 Reqs.
addCapability(SPIRV::Capability::SubgroupImageMediaBlockIOINTEL);
2068 case SPIRV::OpAssumeTrueKHR:
2069 case SPIRV::OpExpectKHR:
2070 if (ST.canUseExtension(SPIRV::Extension::SPV_KHR_expect_assume)) {
2071 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_expect_assume);
2075 case SPIRV::OpFmaKHR:
2076 if (ST.canUseExtension(SPIRV::Extension::SPV_KHR_fma)) {
2081 case SPIRV::OpPtrCastToCrossWorkgroupINTEL:
2082 case SPIRV::OpCrossWorkgroupCastToPtrINTEL:
2083 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_usm_storage_classes)) {
2084 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_usm_storage_classes);
2085 Reqs.
addCapability(SPIRV::Capability::USMStorageClassesINTEL);
2088 case SPIRV::OpConstantFunctionPointerINTEL:
2089 case SPIRV::OpFunctionPointerCallINTEL:
2090 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_function_pointers)) {
2091 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_function_pointers);
2092 Reqs.
addCapability(SPIRV::Capability::FunctionPointersINTEL);
2095 case SPIRV::OpGroupNonUniformRotateKHR:
2096 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_subgroup_rotate))
2098 "following SPIR-V extension: SPV_KHR_subgroup_rotate",
2100 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_subgroup_rotate);
2101 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformRotateKHR);
2104 case SPIRV::OpFixedCosALTERA:
2105 case SPIRV::OpFixedSinALTERA:
2106 case SPIRV::OpFixedCosPiALTERA:
2107 case SPIRV::OpFixedSinPiALTERA:
2108 case SPIRV::OpFixedExpALTERA:
2109 case SPIRV::OpFixedLogALTERA:
2110 case SPIRV::OpFixedRecipALTERA:
2111 case SPIRV::OpFixedSqrtALTERA:
2112 case SPIRV::OpFixedSinCosALTERA:
2113 case SPIRV::OpFixedSinCosPiALTERA:
2114 case SPIRV::OpFixedRsqrtALTERA:
2115 if (!ST.canUseExtension(
2116 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_fixed_point))
2118 "following SPIR-V extension: "
2119 "SPV_ALTERA_arbitrary_precision_fixed_point",
2122 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_fixed_point);
2123 Reqs.
addCapability(SPIRV::Capability::ArbitraryPrecisionFixedPointALTERA);
2125 case SPIRV::OpGroupIMulKHR:
2126 case SPIRV::OpGroupFMulKHR:
2127 case SPIRV::OpGroupBitwiseAndKHR:
2128 case SPIRV::OpGroupBitwiseOrKHR:
2129 case SPIRV::OpGroupBitwiseXorKHR:
2130 case SPIRV::OpGroupLogicalAndKHR:
2131 case SPIRV::OpGroupLogicalOrKHR:
2132 case SPIRV::OpGroupLogicalXorKHR:
2133 if (ST.canUseExtension(
2134 SPIRV::Extension::SPV_KHR_uniform_group_instructions)) {
2135 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_uniform_group_instructions);
2136 Reqs.
addCapability(SPIRV::Capability::GroupUniformArithmeticKHR);
2139 case SPIRV::OpReadClockKHR:
2140 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_shader_clock))
2142 "following SPIR-V extension: SPV_KHR_shader_clock",
2144 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_shader_clock);
2147 case SPIRV::OpAbortKHR:
2148 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_abort))
2150 "following SPIR-V extension: SPV_KHR_abort",
2155 case SPIRV::OpPoisonKHR:
2156 case SPIRV::OpFreezeKHR:
2157 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_poison_freeze))
2159 "following SPIR-V extension: SPV_KHR_poison_freeze",
2161 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_poison_freeze);
2164 case SPIRV::OpAtomicFAddEXT:
2165 case SPIRV::OpAtomicFMinEXT:
2166 case SPIRV::OpAtomicFMaxEXT:
2169 case SPIRV::OpConvertBF16ToFINTEL:
2170 case SPIRV::OpConvertFToBF16INTEL:
2171 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bfloat16_conversion)) {
2172 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bfloat16_conversion);
2173 Reqs.
addCapability(SPIRV::Capability::BFloat16ConversionINTEL);
2176 case SPIRV::OpRoundFToTF32INTEL:
2177 if (ST.canUseExtension(
2178 SPIRV::Extension::SPV_INTEL_tensor_float32_conversion)) {
2179 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_tensor_float32_conversion);
2180 Reqs.
addCapability(SPIRV::Capability::TensorFloat32RoundingINTEL);
2183 case SPIRV::OpVariableLengthArrayINTEL:
2184 case SPIRV::OpSaveMemoryINTEL:
2185 case SPIRV::OpRestoreMemoryINTEL:
2186 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_variable_length_array)) {
2187 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_variable_length_array);
2188 Reqs.
addCapability(SPIRV::Capability::VariableLengthArrayINTEL);
2191 case SPIRV::OpUntypedVariableLengthArrayINTEL:
2192 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_variable_length_array)) {
2193 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_variable_length_array);
2194 Reqs.
addCapability(SPIRV::Capability::UntypedVariableLengthArrayINTEL);
2197 case SPIRV::OpAsmTargetINTEL:
2198 case SPIRV::OpAsmINTEL:
2199 case SPIRV::OpAsmCallINTEL:
2200 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_inline_assembly)) {
2201 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_inline_assembly);
2205 case SPIRV::OpTypeCooperativeMatrixKHR: {
2206 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix))
2208 "OpTypeCooperativeMatrixKHR type requires the "
2209 "following SPIR-V extension: SPV_KHR_cooperative_matrix",
2211 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix);
2212 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixKHR);
2216 Reqs.
addCapability(SPIRV::Capability::BFloat16CooperativeMatrixKHR);
2219 case SPIRV::OpArithmeticFenceEXT:
2220 if (!ST.canUseExtension(SPIRV::Extension::SPV_EXT_arithmetic_fence))
2222 "following SPIR-V extension: SPV_EXT_arithmetic_fence",
2224 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_arithmetic_fence);
2227 case SPIRV::OpControlBarrierArriveINTEL:
2228 case SPIRV::OpControlBarrierWaitINTEL:
2229 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_split_barrier)) {
2230 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_split_barrier);
2234 case SPIRV::OpCooperativeMatrixMulAddKHR: {
2235 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix))
2237 "following SPIR-V extension: "
2238 "SPV_KHR_cooperative_matrix",
2240 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix);
2241 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixKHR);
2242 constexpr unsigned MulAddMaxSize = 6;
2243 if (
MI.getNumOperands() != MulAddMaxSize)
2245 const int64_t CoopOperands =
MI.getOperand(MulAddMaxSize - 1).getImm();
2247 SPIRV::CooperativeMatrixOperands::MatrixAAndBTF32ComponentsINTEL) {
2248 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
2250 "require the following SPIR-V extension: "
2251 "SPV_INTEL_joint_matrix",
2253 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2255 SPIRV::Capability::CooperativeMatrixTF32ComponentTypeINTEL);
2258 MatrixAAndBBFloat16ComponentsINTEL ||
2260 SPIRV::CooperativeMatrixOperands::MatrixCBFloat16ComponentsINTEL ||
2262 MatrixResultBFloat16ComponentsINTEL) {
2263 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
2265 "require the following SPIR-V extension: "
2266 "SPV_INTEL_joint_matrix",
2268 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2270 SPIRV::Capability::CooperativeMatrixBFloat16ComponentTypeINTEL);
2274 case SPIRV::OpCooperativeMatrixLoadKHR:
2275 case SPIRV::OpCooperativeMatrixStoreKHR:
2276 case SPIRV::OpCooperativeMatrixLoadCheckedINTEL:
2277 case SPIRV::OpCooperativeMatrixStoreCheckedINTEL:
2278 case SPIRV::OpCooperativeMatrixPrefetchINTEL: {
2279 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix))
2281 "following SPIR-V extension: "
2282 "SPV_KHR_cooperative_matrix",
2284 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix);
2285 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixKHR);
2291 case SPIRV::OpCooperativeMatrixLoadKHR:
2294 case SPIRV::OpCooperativeMatrixStoreKHR:
2297 case SPIRV::OpCooperativeMatrixLoadCheckedINTEL:
2300 case SPIRV::OpCooperativeMatrixStoreCheckedINTEL:
2301 case SPIRV::OpCooperativeMatrixPrefetchINTEL:
2307 Register RegLayout =
MI.getOperand(LayoutNum).getReg();
2310 if (MILayout->
getOpcode() == SPIRV::OpConstantI) {
2313 static_cast<unsigned>(SPIRV::CooperativeMatrixLayout::PackedINTEL)) {
2314 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
2316 "extension: SPV_INTEL_joint_matrix",
2318 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2319 Reqs.
addCapability(SPIRV::Capability::PackedCooperativeMatrixINTEL);
2324 if (
Op == SPIRV::OpCooperativeMatrixLoadKHR ||
2325 Op == SPIRV::OpCooperativeMatrixStoreKHR)
2328 std::string InstName;
2330 case SPIRV::OpCooperativeMatrixPrefetchINTEL:
2331 InstName =
"OpCooperativeMatrixPrefetchINTEL";
2333 case SPIRV::OpCooperativeMatrixLoadCheckedINTEL:
2334 InstName =
"OpCooperativeMatrixLoadCheckedINTEL";
2336 case SPIRV::OpCooperativeMatrixStoreCheckedINTEL:
2337 InstName =
"OpCooperativeMatrixStoreCheckedINTEL";
2341 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix)) {
2342 const std::string ErrorMsg =
2343 InstName +
" instruction requires the "
2344 "following SPIR-V extension: SPV_INTEL_joint_matrix";
2347 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2348 if (
Op == SPIRV::OpCooperativeMatrixPrefetchINTEL) {
2349 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixPrefetchINTEL);
2353 SPIRV::Capability::CooperativeMatrixCheckedInstructionsINTEL);
2356 case SPIRV::OpCooperativeMatrixConstructCheckedINTEL:
2357 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
2359 "instructions require the following SPIR-V extension: "
2360 "SPV_INTEL_joint_matrix",
2362 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2364 SPIRV::Capability::CooperativeMatrixCheckedInstructionsINTEL);
2366 case SPIRV::OpReadPipeBlockingALTERA:
2367 case SPIRV::OpWritePipeBlockingALTERA:
2368 if (ST.canUseExtension(SPIRV::Extension::SPV_ALTERA_blocking_pipes)) {
2369 Reqs.
addExtension(SPIRV::Extension::SPV_ALTERA_blocking_pipes);
2373 case SPIRV::OpCooperativeMatrixGetElementCoordINTEL:
2374 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
2376 "following SPIR-V extension: SPV_INTEL_joint_matrix",
2378 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2380 SPIRV::Capability::CooperativeMatrixInvocationInstructionsINTEL);
2382 case SPIRV::OpConvertHandleToImageINTEL:
2383 case SPIRV::OpConvertHandleToSamplerINTEL:
2384 case SPIRV::OpConvertHandleToSampledImageINTEL: {
2385 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bindless_images))
2387 "instructions require the following SPIR-V extension: "
2388 "SPV_INTEL_bindless_images",
2391 SPIRV::AddressingModel::AddressingModel AddrModel = MAI.
Addr;
2393 if (
Op == SPIRV::OpConvertHandleToImageINTEL &&
2394 TyDef->
getOpcode() != SPIRV::OpTypeImage) {
2396 "OpConvertHandleToImageINTEL",
2398 }
else if (
Op == SPIRV::OpConvertHandleToSamplerINTEL &&
2399 TyDef->
getOpcode() != SPIRV::OpTypeSampler) {
2401 "OpConvertHandleToSamplerINTEL",
2403 }
else if (
Op == SPIRV::OpConvertHandleToSampledImageINTEL &&
2404 TyDef->
getOpcode() != SPIRV::OpTypeSampledImage) {
2406 "OpConvertHandleToSampledImageINTEL",
2412 if (!(Bitwidth == 32 && AddrModel == SPIRV::AddressingModel::Physical32) &&
2413 !(Bitwidth == 64 && AddrModel == SPIRV::AddressingModel::Physical64)) {
2415 "Parameter value must be a 32-bit scalar in case of "
2416 "Physical32 addressing model or a 64-bit scalar in case of "
2417 "Physical64 addressing model",
2420 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bindless_images);
2424 case SPIRV::OpSubgroup2DBlockLoadINTEL:
2425 case SPIRV::OpSubgroup2DBlockLoadTransposeINTEL:
2426 case SPIRV::OpSubgroup2DBlockLoadTransformINTEL:
2427 case SPIRV::OpSubgroup2DBlockPrefetchINTEL:
2428 case SPIRV::OpSubgroup2DBlockStoreINTEL: {
2429 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_2d_block_io))
2431 "Prefetch/Store]INTEL instructions require the "
2432 "following SPIR-V extension: SPV_INTEL_2d_block_io",
2434 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_2d_block_io);
2435 Reqs.
addCapability(SPIRV::Capability::Subgroup2DBlockIOINTEL);
2437 if (
Op == SPIRV::OpSubgroup2DBlockLoadTransposeINTEL) {
2438 Reqs.
addCapability(SPIRV::Capability::Subgroup2DBlockTransposeINTEL);
2441 if (
Op == SPIRV::OpSubgroup2DBlockLoadTransformINTEL) {
2442 Reqs.
addCapability(SPIRV::Capability::Subgroup2DBlockTransformINTEL);
2447 case SPIRV::OpKill: {
2450 case SPIRV::OpDemoteToHelperInvocation:
2451 Reqs.
addCapability(SPIRV::Capability::DemoteToHelperInvocation);
2453 if (ST.canUseExtension(
2454 SPIRV::Extension::SPV_EXT_demote_to_helper_invocation)) {
2457 SPIRV::Extension::SPV_EXT_demote_to_helper_invocation);
2462 case SPIRV::OpSUDot:
2463 case SPIRV::OpSDotAccSat:
2464 case SPIRV::OpUDotAccSat:
2465 case SPIRV::OpSUDotAccSat:
2468 case SPIRV::OpImageSampleImplicitLod:
2469 case SPIRV::OpImageFetch:
2473 case SPIRV::OpImageSampleExplicitLod:
2476 case SPIRV::OpImageSampleDrefImplicitLod:
2477 case SPIRV::OpImageSampleDrefExplicitLod:
2478 case SPIRV::OpImageDrefGather:
2479 case SPIRV::OpImageGather:
2483 case SPIRV::OpImageRead: {
2484 Register ImageReg =
MI.getOperand(2).getReg();
2485 SPIRVTypeInst TypeDef = ST.getSPIRVGlobalRegistry()->getResultType(
2494 Reqs.
addCapability(SPIRV::Capability::StorageImageReadWithoutFormat);
2497 case SPIRV::OpImageWrite: {
2498 Register ImageReg =
MI.getOperand(0).getReg();
2499 SPIRVTypeInst TypeDef = ST.getSPIRVGlobalRegistry()->getResultType(
2508 Reqs.
addCapability(SPIRV::Capability::StorageImageWriteWithoutFormat);
2511 case SPIRV::OpTypeStructContinuedINTEL:
2512 case SPIRV::OpConstantCompositeContinuedINTEL:
2513 case SPIRV::OpSpecConstantCompositeContinuedINTEL:
2514 case SPIRV::OpCompositeConstructContinuedINTEL: {
2515 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_long_composites))
2517 "Continued instructions require the "
2518 "following SPIR-V extension: SPV_INTEL_long_composites",
2520 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_long_composites);
2524 case SPIRV::OpArbitraryFloatEQALTERA:
2525 case SPIRV::OpArbitraryFloatGEALTERA:
2526 case SPIRV::OpArbitraryFloatGTALTERA:
2527 case SPIRV::OpArbitraryFloatLEALTERA:
2528 case SPIRV::OpArbitraryFloatLTALTERA:
2529 case SPIRV::OpArbitraryFloatCbrtALTERA:
2530 case SPIRV::OpArbitraryFloatCosALTERA:
2531 case SPIRV::OpArbitraryFloatCosPiALTERA:
2532 case SPIRV::OpArbitraryFloatExp10ALTERA:
2533 case SPIRV::OpArbitraryFloatExp2ALTERA:
2534 case SPIRV::OpArbitraryFloatExpALTERA:
2535 case SPIRV::OpArbitraryFloatExpm1ALTERA:
2536 case SPIRV::OpArbitraryFloatHypotALTERA:
2537 case SPIRV::OpArbitraryFloatLog10ALTERA:
2538 case SPIRV::OpArbitraryFloatLog1pALTERA:
2539 case SPIRV::OpArbitraryFloatLog2ALTERA:
2540 case SPIRV::OpArbitraryFloatLogALTERA:
2541 case SPIRV::OpArbitraryFloatRecipALTERA:
2542 case SPIRV::OpArbitraryFloatSinCosALTERA:
2543 case SPIRV::OpArbitraryFloatSinCosPiALTERA:
2544 case SPIRV::OpArbitraryFloatSinALTERA:
2545 case SPIRV::OpArbitraryFloatSinPiALTERA:
2546 case SPIRV::OpArbitraryFloatSqrtALTERA:
2547 case SPIRV::OpArbitraryFloatACosALTERA:
2548 case SPIRV::OpArbitraryFloatACosPiALTERA:
2549 case SPIRV::OpArbitraryFloatAddALTERA:
2550 case SPIRV::OpArbitraryFloatASinALTERA:
2551 case SPIRV::OpArbitraryFloatASinPiALTERA:
2552 case SPIRV::OpArbitraryFloatATan2ALTERA:
2553 case SPIRV::OpArbitraryFloatATanALTERA:
2554 case SPIRV::OpArbitraryFloatATanPiALTERA:
2555 case SPIRV::OpArbitraryFloatCastFromIntALTERA:
2556 case SPIRV::OpArbitraryFloatCastALTERA:
2557 case SPIRV::OpArbitraryFloatCastToIntALTERA:
2558 case SPIRV::OpArbitraryFloatDivALTERA:
2559 case SPIRV::OpArbitraryFloatMulALTERA:
2560 case SPIRV::OpArbitraryFloatPowALTERA:
2561 case SPIRV::OpArbitraryFloatPowNALTERA:
2562 case SPIRV::OpArbitraryFloatPowRALTERA:
2563 case SPIRV::OpArbitraryFloatRSqrtALTERA:
2564 case SPIRV::OpArbitraryFloatSubALTERA: {
2565 if (!ST.canUseExtension(
2566 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_floating_point))
2568 "Floating point instructions can't be translated correctly without "
2569 "enabled SPV_ALTERA_arbitrary_precision_floating_point extension!",
2572 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_floating_point);
2574 SPIRV::Capability::ArbitraryPrecisionFloatingPointALTERA);
2577 case SPIRV::OpSubgroupMatrixMultiplyAccumulateINTEL: {
2578 if (!ST.canUseExtension(
2579 SPIRV::Extension::SPV_INTEL_subgroup_matrix_multiply_accumulate))
2581 "OpSubgroupMatrixMultiplyAccumulateINTEL instruction requires the "
2583 "extension: SPV_INTEL_subgroup_matrix_multiply_accumulate",
2586 SPIRV::Extension::SPV_INTEL_subgroup_matrix_multiply_accumulate);
2588 SPIRV::Capability::SubgroupMatrixMultiplyAccumulateINTEL);
2591 case SPIRV::OpBitwiseFunctionINTEL: {
2592 if (!ST.canUseExtension(
2593 SPIRV::Extension::SPV_INTEL_ternary_bitwise_function))
2595 "OpBitwiseFunctionINTEL instruction requires the following SPIR-V "
2596 "extension: SPV_INTEL_ternary_bitwise_function",
2598 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_ternary_bitwise_function);
2599 Reqs.
addCapability(SPIRV::Capability::TernaryBitwiseFunctionINTEL);
2602 case SPIRV::OpCopyMemorySized: {
2607 case SPIRV::OpTypeUntypedPointerKHR:
2609 MI.getOperand(1).getImm(), ST);
2611 case SPIRV::OpUntypedVariableKHR:
2612 case SPIRV::OpUntypedAccessChainKHR:
2613 case SPIRV::OpUntypedInBoundsAccessChainKHR:
2614 case SPIRV::OpUntypedPtrAccessChainKHR:
2615 case SPIRV::OpUntypedInBoundsPtrAccessChainKHR:
2616 case SPIRV::OpUntypedPrefetchKHR:
2617 case SPIRV::OpUntypedGroupAsyncCopyKHR: {
2618 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_untyped_pointers))
2620 "SPIR-V extension: SPV_KHR_untyped_pointers",
2622 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_untyped_pointers);
2626 case SPIRV::OpPredicatedLoadINTEL:
2627 case SPIRV::OpPredicatedStoreINTEL: {
2628 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_predicated_io))
2630 "OpPredicated[Load/Store]INTEL instructions require "
2631 "the following SPIR-V extension: SPV_INTEL_predicated_io",
2633 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_predicated_io);
2637 case SPIRV::OpFAddS:
2638 case SPIRV::OpFSubS:
2639 case SPIRV::OpFMulS:
2640 case SPIRV::OpFDivS:
2641 case SPIRV::OpFRemS:
2643 case SPIRV::OpFNegate:
2644 case SPIRV::OpFAddV:
2645 case SPIRV::OpFSubV:
2646 case SPIRV::OpFMulV:
2647 case SPIRV::OpFDivV:
2648 case SPIRV::OpFRemV:
2649 case SPIRV::OpFNegateV: {
2655 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic))
2657 "Arithmetic instructions with bfloat16 arguments require the "
2658 "following SPIR-V extension: SPV_INTEL_bfloat16_arithmetic",
2660 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic);
2661 Reqs.
addCapability(SPIRV::Capability::BFloat16ArithmeticINTEL);
2665 case SPIRV::OpOrdered:
2666 case SPIRV::OpUnordered:
2667 case SPIRV::OpFOrdEqual:
2668 case SPIRV::OpFOrdNotEqual:
2669 case SPIRV::OpFOrdLessThan:
2670 case SPIRV::OpFOrdLessThanEqual:
2671 case SPIRV::OpFOrdGreaterThan:
2672 case SPIRV::OpFOrdGreaterThanEqual:
2673 case SPIRV::OpFUnordEqual:
2674 case SPIRV::OpFUnordNotEqual:
2675 case SPIRV::OpFUnordLessThan:
2676 case SPIRV::OpFUnordLessThanEqual:
2677 case SPIRV::OpFUnordGreaterThan:
2678 case SPIRV::OpFUnordGreaterThanEqual: {
2681 ST.getSPIRVGlobalRegistry());
2682 assert(TypeDef &&
"Unexpected type instruction for comparison operand");
2686 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic))
2688 "Relational instructions with bfloat16 arguments require the "
2689 "following SPIR-V extension: SPV_INTEL_bfloat16_arithmetic",
2691 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic);
2692 Reqs.
addCapability(SPIRV::Capability::BFloat16ArithmeticINTEL);
2696 case SPIRV::OpDPdxCoarse:
2697 case SPIRV::OpDPdyCoarse:
2698 case SPIRV::OpDPdxFine:
2699 case SPIRV::OpDPdyFine: {
2703 case SPIRV::OpLoopControlINTEL: {
2704 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_unstructured_loop_controls);
2705 Reqs.
addCapability(SPIRV::Capability::UnstructuredLoopControlsINTEL);
2717 SPIRV::Capability::Shader);
2732 auto Node = M.getNamedMetadata(
"spirv.ExecutionMode");
2734 bool RequireFloatControls =
false, RequireIntelFloatControls2 =
false,
2735 RequireKHRFloatControls2 =
false,
2736 VerLower14 = !ST.isAtLeastSPIRVVer(
VersionTuple(1, 4));
2737 bool HasIntelFloatControls2 =
2738 ST.canUseExtension(SPIRV::Extension::SPV_INTEL_float_controls2);
2739 bool HasKHRFloatControls2 =
2740 ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2);
2741 for (
unsigned i = 0; i <
Node->getNumOperands(); i++) {
2747 auto EM = Const->getZExtValue();
2751 case SPIRV::ExecutionMode::DenormPreserve:
2752 case SPIRV::ExecutionMode::DenormFlushToZero:
2753 case SPIRV::ExecutionMode::RoundingModeRTE:
2754 case SPIRV::ExecutionMode::RoundingModeRTZ:
2755 RequireFloatControls = VerLower14;
2757 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2759 case SPIRV::ExecutionMode::RoundingModeRTPINTEL:
2760 case SPIRV::ExecutionMode::RoundingModeRTNINTEL:
2761 case SPIRV::ExecutionMode::FloatingPointModeALTINTEL:
2762 case SPIRV::ExecutionMode::FloatingPointModeIEEEINTEL:
2763 if (HasIntelFloatControls2) {
2764 RequireIntelFloatControls2 =
true;
2766 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2769 case SPIRV::ExecutionMode::FPFastMathDefault: {
2770 if (HasKHRFloatControls2) {
2771 RequireKHRFloatControls2 =
true;
2773 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2777 case SPIRV::ExecutionMode::ContractionOff:
2778 case SPIRV::ExecutionMode::SignedZeroInfNanPreserve:
2779 if (HasKHRFloatControls2) {
2780 RequireKHRFloatControls2 =
true;
2782 SPIRV::OperandCategory::ExecutionModeOperand,
2783 SPIRV::ExecutionMode::FPFastMathDefault, ST);
2786 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2791 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2796 if (RequireFloatControls &&
2797 ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls))
2799 if (RequireIntelFloatControls2)
2801 if (RequireKHRFloatControls2)
2805 if (
F.isDeclaration())
2807 if (
F.getMetadata(
"reqd_work_group_size"))
2809 SPIRV::OperandCategory::ExecutionModeOperand,
2810 SPIRV::ExecutionMode::LocalSize, ST);
2811 if (
F.getFnAttribute(
"hlsl.numthreads").isValid()) {
2813 SPIRV::OperandCategory::ExecutionModeOperand,
2814 SPIRV::ExecutionMode::LocalSize, ST);
2816 if (
F.getFnAttribute(
"enable-maximal-reconvergence").getValueAsBool()) {
2819 if (
F.getMetadata(
"work_group_size_hint"))
2821 SPIRV::OperandCategory::ExecutionModeOperand,
2822 SPIRV::ExecutionMode::LocalSizeHint, ST);
2823 if (
F.getMetadata(
"intel_reqd_sub_group_size") ||
2824 F.getMetadata(
"reqd_sub_group_size"))
2826 SPIRV::OperandCategory::ExecutionModeOperand,
2827 SPIRV::ExecutionMode::SubgroupSize, ST);
2828 if (
F.getMetadata(
"max_work_group_size"))
2830 SPIRV::OperandCategory::ExecutionModeOperand,
2831 SPIRV::ExecutionMode::MaxWorkgroupSizeINTEL, ST);
2832 if (
F.getMetadata(
"vec_type_hint"))
2834 SPIRV::OperandCategory::ExecutionModeOperand,
2835 SPIRV::ExecutionMode::VecTypeHint, ST);
2837 if (
F.hasOptNone()) {
2838 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_optnone)) {
2841 }
else if (ST.canUseExtension(SPIRV::Extension::SPV_EXT_optnone)) {
2851 unsigned Flags = SPIRV::FPFastMathMode::None;
2852 bool CanUseKHRFloatControls2 =
2853 ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2);
2855 Flags |= SPIRV::FPFastMathMode::NotNaN;
2857 Flags |= SPIRV::FPFastMathMode::NotInf;
2859 Flags |= SPIRV::FPFastMathMode::NSZ;
2861 Flags |= SPIRV::FPFastMathMode::AllowRecip;
2863 Flags |= SPIRV::FPFastMathMode::AllowContract;
2865 if (CanUseKHRFloatControls2)
2873 Flags |= SPIRV::FPFastMathMode::NotNaN | SPIRV::FPFastMathMode::NotInf |
2874 SPIRV::FPFastMathMode::NSZ | SPIRV::FPFastMathMode::AllowRecip |
2875 SPIRV::FPFastMathMode::AllowTransform |
2876 SPIRV::FPFastMathMode::AllowReassoc |
2877 SPIRV::FPFastMathMode::AllowContract;
2879 Flags |= SPIRV::FPFastMathMode::Fast;
2882 if (CanUseKHRFloatControls2) {
2884 assert(!(Flags & SPIRV::FPFastMathMode::Fast) &&
2885 "SPIRV::FPFastMathMode::Fast is deprecated and should not be used "
2890 assert((!(Flags & SPIRV::FPFastMathMode::AllowTransform) ||
2891 ((Flags & SPIRV::FPFastMathMode::AllowReassoc &&
2892 Flags & SPIRV::FPFastMathMode::AllowContract))) &&
2893 "SPIRV::FPFastMathMode::AllowTransform requires AllowReassoc and "
2894 "AllowContract flags to be enabled as well.");
2905 return ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2);
2915 auto Decorate = [&](SPIRV::Decoration::Decoration Dec,
2922 if (
TII.canUseIntegerWrapDecoration(
I)) {
2925 SPIRV::OperandCategory::DecorationOperand,
2926 SPIRV::Decoration::NoSignedWrap, ST, Reqs)
2928 Decorate(SPIRV::Decoration::NoSignedWrap, {});
2931 SPIRV::OperandCategory::DecorationOperand,
2932 SPIRV::Decoration::NoUnsignedWrap, ST, Reqs)
2934 Decorate(SPIRV::Decoration::NoUnsignedWrap, {});
2939 TII.canUseFastMathFlags(
2940 I, ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2)) ||
2941 (ST.isKernel() &&
I.getOpcode() == SPIRV::OpExtInst);
2946 if (FMFlags == SPIRV::FPFastMathMode::None) {
2949 if (FPFastMathDefaultInfoVec.
empty())
2955 I.getOpcode() == SPIRV::OpExtInst ||
2956 I.getOpcode() == SPIRV::OpFunctionCall
2957 ?
I.getMF()->getRegInfo().getVRegDef(
I.getOperand(1).getReg())
2958 :
getRegType(
I.getOperand(2).getReg(), *
I.getMF(), GR);
2965 if (Ty == Elem.Ty) {
2966 FMFlags = Elem.FastMathFlags;
2967 Emit = Elem.ContractionOff || Elem.SignedZeroInfNanPreserve ||
2968 Elem.FPFastMathDefault;
2973 if (FMFlags == SPIRV::FPFastMathMode::None && !Emit)
2977 Decorate(SPIRV::Decoration::FPFastMathMode, {FMFlags});
2991 for (
const auto &
MBB : *MF) {
2992 if (!
MBB.hasName() ||
MBB.empty())
3003 auto it = FPFastMathDefaultInfoMap.
find(
F);
3004 if (it != FPFastMathDefaultInfoMap.
end())
3012 SPIRV::FPFastMathMode::None);
3014 SPIRV::FPFastMathMode::None);
3016 SPIRV::FPFastMathMode::None);
3017 return FPFastMathDefaultInfoMap[
F] = std::move(FPFastMathDefaultInfoVec);
3023 size_t BitWidth = Ty->getScalarSizeInBits();
3027 assert(Index >= 0 && Index < 3 &&
3028 "Expected FPFastMathDefaultInfo for half, float, or double");
3029 assert(FPFastMathDefaultInfoVec.
size() == 3 &&
3030 "Expected FPFastMathDefaultInfoVec to have exactly 3 elements");
3031 return FPFastMathDefaultInfoVec[Index];
3038 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2))
3047 auto Node = M.getNamedMetadata(
"spirv.ExecutionMode");
3051 for (
unsigned i = 0; i <
Node->getNumOperands(); i++) {
3056 if (OnlyF &&
F != OnlyF)
3062 if (EM == SPIRV::ExecutionMode::FPFastMathDefault) {
3064 "Expected 4 operands for FPFastMathDefault");
3075 Info.FastMathFlags = Flags;
3076 Info.FPFastMathDefault =
true;
3077 }
else if (EM == SPIRV::ExecutionMode::ContractionOff) {
3079 "Expected no operands for ContractionOff");
3086 Info.ContractionOff =
true;
3088 }
else if (EM == SPIRV::ExecutionMode::SignedZeroInfNanPreserve) {
3090 "Expected 1 operand for SignedZeroInfNanPreserve");
3091 unsigned TargetWidth =
3100 assert(Index >= 0 && Index < 3 &&
3101 "Expected FPFastMathDefaultInfo for half, float, or double");
3102 assert(FPFastMathDefaultInfoVec.
size() == 3 &&
3103 "Expected FPFastMathDefaultInfoVec to have exactly 3 elements");
3104 FPFastMathDefaultInfoVec[Index].SignedZeroInfNanPreserve =
true;
3112 : ST(&ST), GR(ST.getSPIRVGlobalRegistry()), TII(ST.getInstrInfo()),
3113 MAI(MAI), GetMF(GetMF) {}
3125 collectDeclarations(M);
3128 numberRegistersGlobally(M);
3131 processOtherInstrs(M);
3135 MAI.Reqs.addCapability(SPIRV::Capability::Linkage);
3138 GR->setBound(MAI.MaxID);
3152 [&MMI](
const Function &
F) { return MMI.getMachineFunction(F); })
3168 MachineFunctionAnalysis::Result *MFA =
3169 FAM.getCachedResult<MachineFunctionAnalysis>(
3170 const_cast<Function &>(F));
3171 assert((MFA || F.isDeclaration()) &&
3172 "Missing MachineFunction for definition");
3173 return MFA ? &MFA->getMF() : nullptr;
3190 for (
auto &
MBB : MF)
3193 FPFastMathDefaultInfoMap[&
F]);
3201 SPIRVPrepareModuleAnalysisLegacy() : MachineFunctionPass(
ID) {}
3208char SPIRVPrepareModuleAnalysisLegacy::ID = 0;
3211 "spirv-prepare-module-analysis",
3212 "SPIRV prepare module analysis",
false,
false)
3215 return new SPIRVPrepareModuleAnalysisLegacy();
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
ReachingDefInfo InstSet & ToRemove
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define clEnumValN(ENUMVAL, FLAGNAME, DESC)
static Register UseReg(const MachineOperand &MO)
const HexagonInstrInfo * TII
Promote Memory to Register
FunctionAnalysisManager FAM
ModuleAnalysisManager MAM
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
#define ATOM_FLT_REQ_EXT_MSG(ExtName)
static bool isFastMathModeAvailable(const SPIRVSubtarget &ST)
static void addMBBNames(const Module &M, MachineFunctionGetter GetMF, SPIRV::ModuleAnalysisInfo &MAI)
static void maybeAddScatterGatherReq(const MachineInstr &MI, SPIRV::RequirementHandler &Reqs, const SPIRVSubtarget &ST)
static void addImageOperandReqs(const MachineInstr &MI, SPIRV::RequirementHandler &Reqs, const SPIRVSubtarget &ST, unsigned OpIdx)
bool isStorageImage(MachineInstr *ImageInst)
bool isInputAttachment(MachineInstr *ImageInst)
static bool isBFloat16Type(SPIRVTypeInst TypeDef)
static bool handleMIFlagDecoration(MachineInstr &I, const SPIRVSubtarget &ST, const SPIRVInstrInfo &TII, SPIRV::RequirementHandler &Reqs, const SPIRVGlobalRegistry *GR, SPIRV::FPFastMathDefaultInfoVector &FPFastMathDefaultInfoVec)
bool isSampledImage(MachineInstr *ImageInst)
static cl::list< SPIRV::Capability::Capability > AvoidCapabilities("avoid-spirv-capabilities", cl::desc("SPIR-V capabilities to avoid if there are " "other options enabling a feature"), cl::Hidden, cl::values(clEnumValN(SPIRV::Capability::Shader, "Shader", "SPIR-V Shader capability")))
static unsigned getInvokeOperandIdx(unsigned Opcode)
static SPIRV::FPFastMathDefaultInfo & getFPFastMathDefaultInfo(SPIRV::FPFastMathDefaultInfoVector &FPFastMathDefaultInfoVec, const Type *Ty)
static cl::opt< bool > SPVDumpDeps("spv-dump-deps", cl::desc("Dump MIR with SPIR-V dependencies info"), cl::init(false))
static void collectFPFastMathDefaults(const Module &M, SPIRV::FPFastMathDefaultInfoMapTy &FPFastMathDefaultInfoMap, const SPIRVSubtarget &ST, const Function *OnlyF=nullptr)
static void collectOtherInstr(MachineInstr &MI, SPIRV::ModuleAnalysisInfo &MAI, SPIRV::ModuleSectionType MSType, InstrTraces &IS, bool Append=true)
void addPrintfRequirements(const MachineInstr &MI, SPIRV::RequirementHandler &Reqs, const SPIRVSubtarget &ST)
static void addOpTypeImageReqs(const MachineInstr &MI, SPIRV::RequirementHandler &Reqs, const SPIRVSubtarget &ST)
static bool isImageTypeWithUnknownFormat(SPIRVTypeInst TypeInst)
bool isUniformTexelBuffer(MachineInstr *ImageInst)
bool isStorageTexelBuffer(MachineInstr *ImageInst)
static void AddAtomicFloatRequirements(const MachineInstr &MI, SPIRV::RequirementHandler &Reqs, const SPIRVSubtarget &ST)
bool isCombinedImageSampler(MachineInstr *SampledImageInst)
bool hasNonUniformDecoration(Register Reg, const MachineRegisterInfo &MRI)
void addInstrRequirements(const MachineInstr &MI, SPIRV::ModuleAnalysisInfo &MAI, const SPIRVSubtarget &ST)
static void collectReqs(const Module &M, SPIRV::ModuleAnalysisInfo &MAI, MachineFunctionGetter GetMF, const SPIRVSubtarget &ST)
static void addOpDecorateReqs(const MachineInstr &MI, unsigned DecIndex, SPIRV::RequirementHandler &Reqs, const SPIRVSubtarget &ST)
static InstrSignature instrToSignature(const MachineInstr &MI, SPIRV::ModuleAnalysisInfo &MAI, bool UseDefReg)
static void AddDotProductRequirements(const MachineInstr &MI, SPIRV::RequirementHandler &Reqs, const SPIRVSubtarget &ST)
static SPIRV::Requirements getSymbolicOperandRequirements(SPIRV::OperandCategory::OperandCategory Category, unsigned i, const SPIRVSubtarget &ST, SPIRV::RequirementHandler &Reqs)
static SPIRVTypeInst getRegType(Register Reg, const MachineFunction &MF, const SPIRVGlobalRegistry *GR)
static unsigned getMetadataUInt(MDNode *MdNode, unsigned OpIndex, unsigned DefaultVal=0)
void addOpAccessChainReqs(const MachineInstr &Instr, SPIRV::RequirementHandler &Handler, const SPIRVSubtarget &Subtarget)
static bool prepareModuleAnalysis(MachineFunction &MF)
static void appendDecorationsForReg(const MachineRegisterInfo &MRI, Register R, InstrSignature &Signature)
static SPIRV::FPFastMathDefaultInfoVector & getOrCreateFPFastMathDefaultInfoVec(const Module &M, SPIRV::FPFastMathDefaultInfoMapTy &FPFastMathDefaultInfoMap, const Function *F)
static void AddAtomicVectorFloatRequirements(const MachineInstr &MI, SPIRV::RequirementHandler &Reqs, const SPIRVSubtarget &ST)
static unsigned getFastMathFlags(const MachineInstr &I, const SPIRVSubtarget &ST)
#define SPIRV_BACKEND_SERVICE_FUN_NAME
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
Target-Independent Code Generator Pass Configuration Options pass.
static Function * getFunction(FunctionType *Ty, const Twine &Name, Module *M)
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
Represent a constant reference to an array (0 or more elements consecutively in memory),...
bool isValid() const
Return true if the attribute is any kind of attribute.
This is the shared class of boolean and integer constants.
This is an important base class in LLVM.
iterator find(const_arg_type_t< KeyT > Val)
Diagnostic information for unsupported feature in backend.
FunctionPass class - This class is used to implement most global optimizations.
Attribute getFnAttribute(Attribute::AttrKind Kind) const
Return the attribute for the given attribute kind.
Wrapper class representing physical registers. Should be passed by value.
constexpr bool isValid() const
const MDOperand & getOperand(unsigned I) const
unsigned getNumOperands() const
Return number of MDNode operands.
Tracking metadata reference owned by Metadata.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
MachineInstrBundleIterator< MachineInstr > iterator
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
Helper class to build MachineInstr.
void setDebugLoc(const DebugLoc &DL)
Set the debug location to DL for all the next build instructions.
Register getReg(unsigned Idx) const
Get the register for the operand index.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineBasicBlock * getParent() const
unsigned getNumOperands() const
Retuns the total number of operands.
LLVM_ABI const MachineFunction * getMF() const
Return the function that contains the basic block that this instruction belongs to.
const MachineOperand & getOperand(unsigned i) const
An analysis that produces MachineModuleInfo for a module.
This class contains meta information specific to a module.
MachineOperand class - Representation of each machine instruction operand.
unsigned getSubReg() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
LLVM_ABI void print(raw_ostream &os, const TargetRegisterInfo *TRI=nullptr) const
Print the MachineOperand to os.
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
static MachineOperand CreateImm(int64_t Val)
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
LLVM_ABI LLVM_READONLY MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
iterator_range< reg_instr_iterator > reg_instructions(Register Reg) const
iterator_range< use_instr_iterator > use_instructions(Register Reg) const
LLVM_ABI LLVM_READONLY MachineInstr * getUniqueVRegDef(Register Reg) const
getUniqueVRegDef - Return the unique machine instr that defines the specified virtual register or nul...
A Module instance is used to store all the information related to an LLVM module.
AnalysisType & getAnalysis() const
getAnalysis<AnalysisType>() - This function is used by subclasses to get to the analysis information ...
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Wrapper class representing virtual and physical registers.
constexpr bool isValid() const
unsigned getScalarOrVectorBitWidth(SPIRVTypeInst Type) const
SPIRVTypeInst getResultType(Register VReg, MachineFunction *MF=nullptr)
const Type * getTypeForSPIRVType(SPIRVTypeInst Ty) const
SPIRVTypeInst getSPIRVTypeForVReg(Register VReg, const MachineFunction *MF=nullptr) const
bool isConstantInstr(const MachineInstr &MI) const
void run(const Module &M)
SPIRVModuleAnalysisImpl(const SPIRVSubtarget &ST, SPIRV::ModuleAnalysisInfo &MAI, MachineFunctionGetter GetMF)
SPIRV::ModuleAnalysisInfo Result
Result run(Module &M, ModuleAnalysisManager &MAM)
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
const SPIRVInstrInfo * getInstrInfo() const override
const SPIRVSubtarget * getSubtargetImpl() const
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
bool contains(const T &V) const
Check if the SmallSet contains the given element.
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
reference emplace_back(ArgTypes &&... Args)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
iterator insert(iterator I, T &&Elt)
void push_back(const T &Elt)
Target-Independent Code Generator Pass Configuration Options.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
bool isVectorTy() const
True if this is an instance of VectorType.
static LLVM_ABI Type * getDoubleTy(LLVMContext &C)
static LLVM_ABI Type * getFloatTy(LLVMContext &C)
static LLVM_ABI Type * getHalfTy(LLVMContext &C)
Represents a version number in the form major[.minor[.subminor[.build]]].
bool empty() const
Determine whether this version information is empty (e.g., all version components are zero).
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
DenseMap< const Function *, FPFastMathDefaultInfoVector > FPFastMathDefaultInfoMapTy
SmallVector< const MachineInstr * > InstrList
ValuesClass values(OptsTy... Options)
Helper to build a ValuesClass by forwarding a variable number of arguments as an initializer list to ...
initializer< Ty > init(const Ty &Val)
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > extract(Y &&MD)
Extract a Value from Metadata.
This is an optimization pass for GlobalISel generic memory operations.
void stable_sort(R &&Range)
std::string getStringImm(const MachineInstr &MI, unsigned StartIndex)
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
hash_code hash_value(const FixedPointSemantics &Val)
ExtensionList getSymbolicOperandExtensions(SPIRV::OperandCategory::OperandCategory Category, uint32_t Value)
CapabilityList getSymbolicOperandCapabilities(SPIRV::OperandCategory::OperandCategory Category, uint32_t Value)
SmallVector< SPIRV::Extension::Extension, 8 > ExtensionList
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
SmallVector< size_t > InstrSignature
bool requiresLongVectorEXT(unsigned NumComponents)
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
InnerAnalysisManagerProxy< FunctionAnalysisManager, Module > FunctionAnalysisManagerModuleProxy
Provide the FunctionAnalysisManager to Module proxy.
static void reportUnsupported(MachineIRBuilder &MIRBuilder, const Twine &Msg)
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
void buildOpDecorate(Register Reg, MachineIRBuilder &MIRBuilder, SPIRV::Decoration::Decoration Dec, ArrayRef< uint32_t > DecArgs, StringRef StrImm)
bool isVectorType(SPIRVTypeInst SPVTy)
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
VersionTuple getSymbolicOperandMaxVersion(SPIRV::OperandCategory::OperandCategory Category, uint32_t Value)
function_ref< MachineFunction *(const Function &)> MachineFunctionGetter
void erase(Container &C, ValueType V)
Wrapper function to remove a value from a container:
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
CapabilityList getCapabilitiesEnabledByExtension(SPIRV::Extension::Extension Extension)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
FunctionPass * createSPIRVPrepareModuleAnalysisLegacyPass()
std::string getSymbolicOperandMnemonic(SPIRV::OperandCategory::OperandCategory Category, int32_t Value)
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
DWARFExpression::Operation Op
VersionTuple getSymbolicOperandMinVersion(SPIRV::OperandCategory::OperandCategory Category, uint32_t Value)
constexpr unsigned BitWidth
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
SmallVector< SPIRV::Capability::Capability, 8 > CapabilityList
std::set< InstrSignature > InstrTraces
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
hash_code hash_combine(const Ts &...args)
Combine values into a single hash_code.
std::map< SmallVector< size_t >, unsigned > InstrGRegsMap
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
SmallSet< SPIRV::Capability::Capability, 4 > S
A special type used by analysis passes to provide an address that identifies that particular analysis...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
SPIRV::ModuleAnalysisInfo MAI
bool runOnModule(Module &M) override
runOnModule - Virtual method overriden by subclasses to process the module being operated on.
static size_t computeFPFastMathDefaultInfoVecIndex(size_t BitWidth)
void setSkipEmission(const MachineInstr *MI)
MCRegister getRegisterAlias(const MachineFunction *MF, Register Reg)
MCRegister getOrCreateMBBRegister(const MachineBasicBlock &MBB)
InstrList MS[NUM_MODULE_SECTIONS]
AddressingModel::AddressingModel Addr
SmallVector< std::pair< MCRegister, StringRef > > MBBNames
void checkSatisfiable(const SPIRVSubtarget &ST) const
void getAndAddRequirements(SPIRV::OperandCategory::OperandCategory Category, uint32_t i, const SPIRVSubtarget &ST)
void addRequirements(const Requirements &Req)
bool isCapabilityAvailable(Capability::Capability Cap) const
void removeCapabilityIf(const Capability::Capability ToRemove, const Capability::Capability IfPresent)
void addExtensions(const ExtensionList &ToAdd)
void addAvailableCaps(const CapabilityList &ToAdd)
void addExtension(Extension::Extension ToAdd)
void initAvailableCapabilities(const SPIRVSubtarget &ST)
void addCapability(Capability::Capability ToAdd)
void addCapabilities(const CapabilityList &ToAdd)
const std::optional< Capability::Capability > Cap
const VersionTuple MinVer
const VersionTuple MaxVer