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,
1085 Capability::SampleRateShading,
1087 Capability::ImageQuery,
1088 Capability::ImageGatherExtended,
1089 Capability::Addresses,
1090 Capability::VulkanMemoryModelKHR,
1091 Capability::StorageImageExtendedFormats,
1092 Capability::StorageImageMultisample,
1093 Capability::ImageMSArray});
1095 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 3)) ||
1096 ST.canUseExtension(Extension::SPV_KHR_variable_pointers))
1098 Capability::VariablePointers});
1101 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 5))) {
1103 {Capability::Int64Atomics, Capability::ShaderNonUniformEXT,
1104 Capability::RuntimeDescriptorArrayEXT,
1105 Capability::InputAttachmentArrayDynamicIndexingEXT,
1106 Capability::UniformTexelBufferArrayDynamicIndexingEXT,
1107 Capability::StorageTexelBufferArrayDynamicIndexingEXT,
1108 Capability::UniformBufferArrayNonUniformIndexingEXT,
1109 Capability::SampledImageArrayNonUniformIndexingEXT,
1110 Capability::StorageBufferArrayNonUniformIndexingEXT,
1111 Capability::StorageImageArrayNonUniformIndexingEXT,
1112 Capability::InputAttachmentArrayNonUniformIndexingEXT,
1113 Capability::UniformTexelBufferArrayNonUniformIndexingEXT,
1114 Capability::StorageTexelBufferArrayNonUniformIndexingEXT});
1118 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 6)))
1120 Capability::StorageImageReadWithoutFormat});
1131 int64_t DecOp =
MI.getOperand(DecIndex).getImm();
1132 auto Dec =
static_cast<SPIRV::Decoration::Decoration
>(DecOp);
1134 SPIRV::OperandCategory::DecorationOperand, Dec, ST, Reqs));
1136 if (Dec == SPIRV::Decoration::BuiltIn) {
1137 int64_t BuiltInOp =
MI.getOperand(DecIndex + 1).getImm();
1138 auto BuiltIn =
static_cast<SPIRV::BuiltIn::BuiltIn
>(BuiltInOp);
1139 if ((BuiltIn == SPIRV::BuiltIn::BaryCoordKHR ||
1140 BuiltIn == SPIRV::BuiltIn::BaryCoordNoPerspKHR) &&
1141 !ST.canUseExtension(
1142 SPIRV::Extension::SPV_KHR_fragment_shader_barycentric))
1144 "Barycentric built-ins require the following SPIR-V extension: "
1145 "SPV_KHR_fragment_shader_barycentric",
1148 SPIRV::OperandCategory::BuiltInOperand, BuiltIn, ST, Reqs));
1149 }
else if (Dec == SPIRV::Decoration::LinkageAttributes) {
1150 int64_t LinkageOp =
MI.getOperand(
MI.getNumOperands() - 1).getImm();
1151 SPIRV::LinkageType::LinkageType LnkType =
1152 static_cast<SPIRV::LinkageType::LinkageType
>(LinkageOp);
1153 if (LnkType == SPIRV::LinkageType::LinkOnceODR)
1154 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_linkonce_odr);
1155 else if (LnkType == SPIRV::LinkageType::WeakAMD) {
1156 Reqs.
addExtension(SPIRV::Extension::SPV_AMD_weak_linkage);
1159 }
else if (Dec == SPIRV::Decoration::CacheControlLoadINTEL ||
1160 Dec == SPIRV::Decoration::CacheControlStoreINTEL) {
1161 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_cache_controls);
1162 }
else if (Dec == SPIRV::Decoration::HostAccessINTEL) {
1163 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_global_variable_host_access);
1164 }
else if (Dec == SPIRV::Decoration::InitModeINTEL ||
1165 Dec == SPIRV::Decoration::ImplementInRegisterMapINTEL) {
1167 SPIRV::Extension::SPV_INTEL_global_variable_fpga_decorations);
1168 }
else if (Dec == SPIRV::Decoration::NonUniformEXT) {
1170 }
else if (Dec == SPIRV::Decoration::FPMaxErrorDecorationINTEL) {
1172 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_fp_max_error);
1173 }
else if (Dec == SPIRV::Decoration::FPFastMathMode) {
1174 if (ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2)) {
1176 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_float_controls2);
1185 assert(
MI.getNumOperands() >= 8 &&
"Insufficient operands for OpTypeImage");
1188 int64_t ImgFormatOp =
MI.getOperand(7).getImm();
1189 auto ImgFormat =
static_cast<SPIRV::ImageFormat::ImageFormat
>(ImgFormatOp);
1193 bool IsArrayed =
MI.getOperand(4).getImm() == 1;
1194 bool IsMultisampled =
MI.getOperand(5).getImm() == 1;
1195 bool NoSampler =
MI.getOperand(6).getImm() == 2;
1198 switch (
MI.getOperand(2).getImm()) {
1199 case SPIRV::Dim::DIM_1D:
1201 : SPIRV::Capability::Sampled1D);
1203 case SPIRV::Dim::DIM_2D:
1204 if (IsMultisampled && NoSampler)
1206 if (IsMultisampled && IsArrayed)
1209 case SPIRV::Dim::DIM_3D:
1211 case SPIRV::Dim::DIM_Cube:
1215 : SPIRV::Capability::SampledCubeArray);
1217 case SPIRV::Dim::DIM_Rect:
1219 : SPIRV::Capability::SampledRect);
1221 case SPIRV::Dim::DIM_Buffer:
1223 : SPIRV::Capability::SampledBuffer);
1225 case SPIRV::Dim::DIM_SubpassData:
1231 if (!ST.isShader()) {
1232 if (
MI.getNumOperands() > 8 &&
1233 MI.getOperand(8).getImm() == SPIRV::AccessQualifier::ReadWrite)
1242 TypeDef->
getOpcode() == SPIRV::OpTypeFloat &&
1258#define ATOM_FLT_REQ_EXT_MSG(ExtName) \
1259 "The atomic float instruction requires the following SPIR-V " \
1260 "extension: SPV_EXT_shader_atomic_float" ExtName
1265 MI.getMF()->getRegInfo().getVRegDef(
MI.getOperand(1).getReg());
1268 if (Rank != 2 && Rank != 4)
1270 "must be a 2-component or 4 component vector");
1275 if (EltTypeDef->
getOpcode() != SPIRV::OpTypeFloat ||
1278 "The element type for the result type of an atomic vector float "
1279 "instruction must be a 16-bit floating-point scalar");
1286 "The element type for the result type of an atomic vector float "
1287 "instruction cannot be a bfloat16 scalar");
1288 if (!ST.canUseExtension(SPIRV::Extension::SPV_NV_shader_atomic_fp16_vector))
1290 "The atomic float16 vector instruction requires the following SPIR-V "
1291 "extension: SPV_NV_shader_atomic_fp16_vector");
1293 Reqs.
addExtension(SPIRV::Extension::SPV_NV_shader_atomic_fp16_vector);
1294 Reqs.
addCapability(SPIRV::Capability::AtomicFloat16VectorNV);
1301 "Expect register operand in atomic float instruction");
1302 Register TypeReg =
MI.getOperand(1).getReg();
1308 if (TypeDef->
getOpcode() != SPIRV::OpTypeFloat)
1310 "floating-point type scalar");
1313 unsigned Op =
MI.getOpcode();
1314 if (
Op == SPIRV::OpAtomicFAddEXT) {
1315 if (!ST.canUseExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float_add))
1317 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float_add);
1321 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics))
1323 "The atomic bfloat16 instruction requires the following SPIR-V "
1324 "extension: SPV_INTEL_16bit_atomics",
1326 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics);
1327 Reqs.
addCapability(SPIRV::Capability::AtomicBFloat16AddINTEL);
1329 if (!ST.canUseExtension(
1330 SPIRV::Extension::SPV_EXT_shader_atomic_float16_add))
1332 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float16_add);
1344 "Unexpected floating-point type width in atomic float instruction");
1347 if (!ST.canUseExtension(
1348 SPIRV::Extension::SPV_EXT_shader_atomic_float_min_max))
1350 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float_min_max);
1354 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics))
1356 "The atomic bfloat16 instruction requires the following SPIR-V "
1357 "extension: SPV_INTEL_16bit_atomics",
1359 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics);
1360 Reqs.
addCapability(SPIRV::Capability::AtomicBFloat16MinMaxINTEL);
1362 Reqs.
addCapability(SPIRV::Capability::AtomicFloat16MinMaxEXT);
1366 Reqs.
addCapability(SPIRV::Capability::AtomicFloat32MinMaxEXT);
1369 Reqs.
addCapability(SPIRV::Capability::AtomicFloat64MinMaxEXT);
1373 "Unexpected floating-point type width in atomic float instruction");
1379 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1383 return Dim == SPIRV::Dim::DIM_Buffer && Sampled == 1;
1387 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1391 return Dim == SPIRV::Dim::DIM_Buffer && Sampled == 2;
1395 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1399 return Dim != SPIRV::Dim::DIM_Buffer && Sampled == 1;
1403 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1407 return Dim == SPIRV::Dim::DIM_SubpassData && Sampled == 2;
1411 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1415 return Dim != SPIRV::Dim::DIM_Buffer && Sampled == 2;
1419 if (SampledImageInst->
getOpcode() != SPIRV::OpTypeSampledImage)
1430 if (
MI.getOpcode() != SPIRV::OpDecorate)
1434 if (Dec == SPIRV::Decoration::NonUniformEXT)
1447 Register ResTypeReg = Instr.getOperand(1).getReg();
1452 if (
StorageClass != SPIRV::StorageClass::StorageClass::UniformConstant &&
1453 StorageClass != SPIRV::StorageClass::StorageClass::Uniform &&
1454 StorageClass != SPIRV::StorageClass::StorageClass::StorageBuffer) {
1461 auto FirstIndexReg = Instr.getOperand(3).getReg();
1462 bool FirstIndexIsConstant =
1465 if (
StorageClass == SPIRV::StorageClass::StorageClass::StorageBuffer) {
1468 SPIRV::Capability::StorageBufferArrayNonUniformIndexingEXT);
1469 else if (!FirstIndexIsConstant)
1471 SPIRV::Capability::StorageBufferArrayDynamicIndexing);
1477 if (PointeeType->
getOpcode() != SPIRV::OpTypeImage &&
1478 PointeeType->
getOpcode() != SPIRV::OpTypeSampledImage &&
1479 PointeeType->
getOpcode() != SPIRV::OpTypeSampler) {
1486 SPIRV::Capability::UniformTexelBufferArrayNonUniformIndexingEXT);
1487 else if (!FirstIndexIsConstant)
1489 SPIRV::Capability::UniformTexelBufferArrayDynamicIndexingEXT);
1493 SPIRV::Capability::InputAttachmentArrayNonUniformIndexingEXT);
1494 else if (!FirstIndexIsConstant)
1496 SPIRV::Capability::InputAttachmentArrayDynamicIndexingEXT);
1500 SPIRV::Capability::StorageTexelBufferArrayNonUniformIndexingEXT);
1501 else if (!FirstIndexIsConstant)
1503 SPIRV::Capability::StorageTexelBufferArrayDynamicIndexingEXT);
1506 PointeeType->
getOpcode() == SPIRV::OpTypeSampler) {
1509 SPIRV::Capability::SampledImageArrayNonUniformIndexingEXT);
1510 else if (!FirstIndexIsConstant)
1512 SPIRV::Capability::SampledImageArrayDynamicIndexing);
1516 SPIRV::Capability::StorageImageArrayNonUniformIndexingEXT);
1517 else if (!FirstIndexIsConstant)
1519 SPIRV::Capability::StorageImageArrayDynamicIndexing);
1524 if (TypeInst->
getOpcode() != SPIRV::OpTypeImage)
1533 if (ST.canUseExtension(SPIRV::Extension::SPV_KHR_integer_dot_product))
1534 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_integer_dot_product);
1538 assert(
MI.getOperand(2).isReg() &&
"Unexpected operand in dot");
1540 ST.getSPIRVGlobalRegistry());
1541 assert(TypeDef &&
"Unexpected type instruction for dot input");
1542 if (TypeDef->
getOpcode() == SPIRV::OpTypeInt) {
1544 Reqs.
addCapability(SPIRV::Capability::DotProductInput4x8BitPacked);
1551 "Dot operand of 8-bit integer type requires 4 components");
1552 Reqs.
addCapability(SPIRV::Capability::DotProductInput4x8Bit);
1568 unsigned AddrSpace = ASOp.
getImm();
1569 if (AddrSpace != SPIRV::StorageClass::UniformConstant) {
1570 if (!ST.canUseExtension(
1572 SPV_EXT_relaxed_printf_string_address_space)) {
1574 "required because printf uses a format string not "
1575 "in constant address space.",
1579 SPIRV::Extension::SPV_EXT_relaxed_printf_string_address_space);
1588 if (
MI.getNumOperands() <= OpIdx)
1590 uint32_t Mask =
MI.getOperand(OpIdx).getImm();
1592 if (Mask & (1U <<
I))
1603 if (ElemTypeDef->
getOpcode() == SPIRV::OpTypePointer &&
1604 ST.canUseExtension(SPIRV::Extension::SPV_INTEL_masked_gather_scatter)) {
1605 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_masked_gather_scatter);
1606 Reqs.
addCapability(SPIRV::Capability::MaskedGatherScatterINTEL);
1614 unsigned Op =
MI.getOpcode();
1616 case SPIRV::OpMemoryModel: {
1617 int64_t Addr =
MI.getOperand(0).getImm();
1620 int64_t Mem =
MI.getOperand(1).getImm();
1625 case SPIRV::OpEntryPoint: {
1626 int64_t Exe =
MI.getOperand(0).getImm();
1631 case SPIRV::OpExecutionMode:
1632 case SPIRV::OpExecutionModeId: {
1633 int64_t Exe =
MI.getOperand(1).getImm();
1638 case SPIRV::OpTypeMatrix:
1641 case SPIRV::OpTypeInt: {
1642 unsigned BitWidth =
MI.getOperand(1).getImm();
1650 ST.canUseExtension(SPIRV::Extension::SPV_INTEL_int4)) {
1654 if (!ST.canUseExtension(
1655 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_integers))
1657 "OpTypeInt type with a width other than 8, 16, 32 or 64 bits "
1658 "requires the following SPIR-V extension: "
1659 "SPV_ALTERA_arbitrary_precision_integers");
1661 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_integers);
1662 Reqs.
addCapability(SPIRV::Capability::ArbitraryPrecisionIntegersALTERA);
1666 case SPIRV::OpDot: {
1670 Reqs.
addCapability(SPIRV::Capability::BFloat16DotProductKHR);
1673 case SPIRV::OpTypeFloat: {
1674 unsigned BitWidth =
MI.getOperand(1).getImm();
1679 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_bfloat16))
1681 "following SPIR-V extension: SPV_KHR_bfloat16",
1691 case SPIRV::OpTypeVector: {
1692 unsigned NumComponents =
MI.getOperand(2).getImm();
1693 if (NumComponents == 8 || NumComponents == 16)
1698 "OpTypeVector with " +
Twine(NumComponents) +
1699 " components requires the following SPIR-V extension: "
1700 "SPV_EXT_long_vector");
1705 case SPIRV::OpTypeVectorIdEXT: {
1706 if (!ST.canUseExtension(SPIRV::Extension::SPV_EXT_long_vector))
1708 "extension: SPV_EXT_long_vector extension");
1709 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_long_vector);
1714 case SPIRV::OpTypePointer: {
1715 auto SC =
MI.getOperand(1).getImm();
1726 (TypeDef->
getOpcode() == SPIRV::OpTypeFloat) &&
1731 case SPIRV::OpExtInst: {
1732 if (
MI.getOperand(2).getImm() ==
1733 static_cast<int64_t
>(
1734 SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100)) {
1735 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_non_semantic_info);
1738 if (
MI.getOperand(3).getImm() ==
1739 static_cast<int64_t
>(SPIRV::OpenCLExtInst::printf)) {
1743 if (
MI.getOperand(2).getImm() ==
1744 static_cast<int64_t
>(SPIRV::InstructionSet::OpenCL_std)) {
1750 if (TypeDef && TypeDef->getOpcode() == SPIRV::OpTypeVector)
1751 TypeDef = MRI.
getVRegDef(TypeDef->getOperand(1).getReg());
1756 bool UsesBFloat16 = IsBFloat16(MRI.
getVRegDef(
MI.getOperand(1).getReg()));
1757 for (
unsigned I = 4,
E =
MI.getNumOperands();
I <
E && !UsesBFloat16;
1766 if (!ST.canUseExtension(
1767 SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic)) {
1769 MI,
"OpenCL Extended instructions with bfloat16 require the "
1770 "following SPIR-V extension: SPV_INTEL_bfloat16_arithmetic");
1773 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic);
1774 Reqs.
addCapability(SPIRV::Capability::BFloat16ArithmeticINTEL);
1779 case SPIRV::OpAliasDomainDeclINTEL:
1780 case SPIRV::OpAliasScopeDeclINTEL:
1781 case SPIRV::OpAliasScopeListDeclINTEL: {
1782 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_memory_access_aliasing);
1783 Reqs.
addCapability(SPIRV::Capability::MemoryAccessAliasingINTEL);
1786 case SPIRV::OpBitReverse:
1787 case SPIRV::OpBitFieldInsert:
1788 case SPIRV::OpBitFieldSExtract:
1789 case SPIRV::OpBitFieldUExtract:
1790 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_bit_instructions)) {
1794 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_bit_instructions);
1797 case SPIRV::OpTypeRuntimeArray:
1800 case SPIRV::OpTypeOpaque:
1801 case SPIRV::OpTypeEvent:
1804 case SPIRV::OpTypePipe:
1805 case SPIRV::OpTypeReserveId:
1808 case SPIRV::OpTypeDeviceEvent:
1809 case SPIRV::OpTypeQueue:
1810 case SPIRV::OpBuildNDRange:
1811 case SPIRV::OpEnqueueKernel:
1812 case SPIRV::OpGetKernelNDrangeSubGroupCount:
1813 case SPIRV::OpGetKernelNDrangeMaxSubGroupSize:
1814 case SPIRV::OpGetKernelWorkGroupSize:
1815 case SPIRV::OpGetKernelPreferredWorkGroupSizeMultiple:
1818 case SPIRV::OpDecorate:
1819 case SPIRV::OpDecorateId:
1820 case SPIRV::OpDecorateString:
1823 case SPIRV::OpMemberDecorate:
1824 case SPIRV::OpMemberDecorateString:
1827 case SPIRV::OpInBoundsPtrAccessChain:
1830 case SPIRV::OpConstantSampler:
1833 case SPIRV::OpInBoundsAccessChain:
1834 case SPIRV::OpAccessChain:
1837 case SPIRV::OpTypeImage:
1840 case SPIRV::OpTypeSampler:
1841 if (!ST.isShader()) {
1845 case SPIRV::OpTypeForwardPointer:
1849 case SPIRV::OpAtomicFlagTestAndSet:
1850 case SPIRV::OpAtomicLoad:
1851 case SPIRV::OpAtomicStore:
1852 case SPIRV::OpAtomicExchange:
1853 case SPIRV::OpAtomicCompareExchange:
1854 case SPIRV::OpAtomicCompareExchangeWeak:
1855 case SPIRV::OpAtomicIIncrement:
1856 case SPIRV::OpAtomicIDecrement:
1857 case SPIRV::OpAtomicIAdd:
1858 case SPIRV::OpAtomicISub:
1859 case SPIRV::OpAtomicUMin:
1860 case SPIRV::OpAtomicUMax:
1861 case SPIRV::OpAtomicSMin:
1862 case SPIRV::OpAtomicSMax:
1863 case SPIRV::OpAtomicAnd:
1864 case SPIRV::OpAtomicOr:
1865 case SPIRV::OpAtomicXor: {
1868 if (
Op == SPIRV::OpAtomicStore) {
1871 ST.getSPIRVGlobalRegistry());
1872 assert(TypeDef &&
"Unexpected type instruction for OpAtomicStore");
1874 assert(
MI.getOperand(1).isReg() &&
"Unexpected operand in atomic");
1878 if (TypeDef->
getOpcode() == SPIRV::OpTypeInt) {
1883 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics))
1885 "16-bit integer atomic operations require the following SPIR-V "
1886 "extension: SPV_INTEL_16bit_atomics",
1888 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics);
1890 case SPIRV::OpAtomicLoad:
1891 case SPIRV::OpAtomicStore:
1892 case SPIRV::OpAtomicExchange:
1893 case SPIRV::OpAtomicCompareExchange:
1894 case SPIRV::OpAtomicCompareExchangeWeak:
1896 SPIRV::Capability::AtomicInt16CompareExchangeINTEL);
1904 if (
is_contained({SPIRV::OpAtomicLoad, SPIRV::OpAtomicStore,
1905 SPIRV::OpAtomicExchange},
1907 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics))
1909 "The atomic bfloat16 instruction requires the following SPIR-V "
1910 "extension: SPV_INTEL_16bit_atomics",
1912 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics);
1913 Reqs.
addCapability(SPIRV::Capability::AtomicBFloat16LoadStoreINTEL);
1918 case SPIRV::OpGroupNonUniformIAdd:
1919 case SPIRV::OpGroupNonUniformFAdd:
1920 case SPIRV::OpGroupNonUniformIMul:
1921 case SPIRV::OpGroupNonUniformFMul:
1922 case SPIRV::OpGroupNonUniformSMin:
1923 case SPIRV::OpGroupNonUniformUMin:
1924 case SPIRV::OpGroupNonUniformFMin:
1925 case SPIRV::OpGroupNonUniformSMax:
1926 case SPIRV::OpGroupNonUniformUMax:
1927 case SPIRV::OpGroupNonUniformFMax:
1928 case SPIRV::OpGroupNonUniformBitwiseAnd:
1929 case SPIRV::OpGroupNonUniformBitwiseOr:
1930 case SPIRV::OpGroupNonUniformBitwiseXor:
1931 case SPIRV::OpGroupNonUniformLogicalAnd:
1932 case SPIRV::OpGroupNonUniformLogicalOr:
1933 case SPIRV::OpGroupNonUniformLogicalXor: {
1935 int64_t GroupOp =
MI.getOperand(3).getImm();
1937 case SPIRV::GroupOperation::Reduce:
1938 case SPIRV::GroupOperation::InclusiveScan:
1939 case SPIRV::GroupOperation::ExclusiveScan:
1940 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformArithmetic);
1942 case SPIRV::GroupOperation::ClusteredReduce:
1943 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformClustered);
1945 case SPIRV::GroupOperation::PartitionedReduceNV:
1946 case SPIRV::GroupOperation::PartitionedInclusiveScanNV:
1947 case SPIRV::GroupOperation::PartitionedExclusiveScanNV:
1948 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformPartitionedNV);
1953 case SPIRV::OpGroupNonUniformQuadSwap:
1956 case SPIRV::OpImageQueryLod:
1959 case SPIRV::OpImageQuerySize:
1960 case SPIRV::OpImageQuerySizeLod:
1961 case SPIRV::OpImageQueryLevels:
1962 case SPIRV::OpImageQuerySamples:
1966 case SPIRV::OpImageQueryFormat: {
1967 Register ResultReg =
MI.getOperand(0).getReg();
1969 static const unsigned CompareOps[] = {
1970 SPIRV::OpIEqual, SPIRV::OpINotEqual,
1971 SPIRV::OpUGreaterThan, SPIRV::OpUGreaterThanEqual,
1972 SPIRV::OpULessThan, SPIRV::OpULessThanEqual,
1973 SPIRV::OpSGreaterThan, SPIRV::OpSGreaterThanEqual,
1974 SPIRV::OpSLessThan, SPIRV::OpSLessThanEqual};
1976 auto CheckAndAddExtension = [&](int64_t ImmVal) {
1977 if (ImmVal == 4323 || ImmVal == 4324) {
1978 if (ST.canUseExtension(SPIRV::Extension::SPV_EXT_image_raw10_raw12))
1979 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_image_raw10_raw12);
1982 "SPV_EXT_image_raw10_raw12 extension");
1987 unsigned Opc = UseInst.getOpcode();
1989 if (
Opc == SPIRV::OpSwitch) {
1992 CheckAndAddExtension(
Op.getImm());
1994 for (
unsigned i = 1; i < UseInst.getNumOperands(); ++i) {
1997 if (ConstInst && ConstInst->
getOpcode() == SPIRV::OpConstantI) {
2000 CheckAndAddExtension(ImmVal);
2008 case SPIRV::OpGroupNonUniformShuffle:
2009 case SPIRV::OpGroupNonUniformShuffleXor:
2010 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformShuffle);
2012 case SPIRV::OpGroupNonUniformShuffleUp:
2013 case SPIRV::OpGroupNonUniformShuffleDown:
2014 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformShuffleRelative);
2016 case SPIRV::OpGroupAll:
2017 case SPIRV::OpGroupAny:
2018 case SPIRV::OpGroupBroadcast:
2019 case SPIRV::OpGroupIAdd:
2020 case SPIRV::OpGroupFAdd:
2021 case SPIRV::OpGroupFMin:
2022 case SPIRV::OpGroupUMin:
2023 case SPIRV::OpGroupSMin:
2024 case SPIRV::OpGroupFMax:
2025 case SPIRV::OpGroupUMax:
2026 case SPIRV::OpGroupSMax:
2029 case SPIRV::OpGroupNonUniformElect:
2032 case SPIRV::OpGroupNonUniformAll:
2033 case SPIRV::OpGroupNonUniformAny:
2034 case SPIRV::OpGroupNonUniformAllEqual:
2037 case SPIRV::OpGroupNonUniformBroadcast:
2038 case SPIRV::OpGroupNonUniformBroadcastFirst:
2039 case SPIRV::OpGroupNonUniformBallot:
2040 case SPIRV::OpGroupNonUniformInverseBallot:
2041 case SPIRV::OpGroupNonUniformBallotBitExtract:
2042 case SPIRV::OpGroupNonUniformBallotBitCount:
2043 case SPIRV::OpGroupNonUniformBallotFindLSB:
2044 case SPIRV::OpGroupNonUniformBallotFindMSB:
2045 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformBallot);
2047 case SPIRV::OpSubgroupShuffleINTEL:
2048 case SPIRV::OpSubgroupShuffleDownINTEL:
2049 case SPIRV::OpSubgroupShuffleUpINTEL:
2050 case SPIRV::OpSubgroupShuffleXorINTEL:
2051 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {
2052 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_subgroups);
2053 Reqs.
addCapability(SPIRV::Capability::SubgroupShuffleINTEL);
2056 case SPIRV::OpSubgroupBlockReadINTEL:
2057 case SPIRV::OpSubgroupBlockWriteINTEL:
2058 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {
2059 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_subgroups);
2060 Reqs.
addCapability(SPIRV::Capability::SubgroupBufferBlockIOINTEL);
2063 case SPIRV::OpSubgroupImageBlockReadINTEL:
2064 case SPIRV::OpSubgroupImageBlockWriteINTEL:
2065 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {
2066 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_subgroups);
2067 Reqs.
addCapability(SPIRV::Capability::SubgroupImageBlockIOINTEL);
2070 case SPIRV::OpSubgroupImageMediaBlockReadINTEL:
2071 case SPIRV::OpSubgroupImageMediaBlockWriteINTEL:
2072 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_media_block_io)) {
2073 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_media_block_io);
2074 Reqs.
addCapability(SPIRV::Capability::SubgroupImageMediaBlockIOINTEL);
2077 case SPIRV::OpAssumeTrueKHR:
2078 case SPIRV::OpExpectKHR:
2079 if (ST.canUseExtension(SPIRV::Extension::SPV_KHR_expect_assume)) {
2080 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_expect_assume);
2084 case SPIRV::OpFmaKHR:
2085 if (ST.canUseExtension(SPIRV::Extension::SPV_KHR_fma)) {
2090 case SPIRV::OpPtrCastToCrossWorkgroupINTEL:
2091 case SPIRV::OpCrossWorkgroupCastToPtrINTEL:
2092 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_usm_storage_classes)) {
2093 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_usm_storage_classes);
2094 Reqs.
addCapability(SPIRV::Capability::USMStorageClassesINTEL);
2097 case SPIRV::OpConstantFunctionPointerINTEL:
2098 case SPIRV::OpFunctionPointerCallINTEL:
2099 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_function_pointers)) {
2100 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_function_pointers);
2101 Reqs.
addCapability(SPIRV::Capability::FunctionPointersINTEL);
2104 case SPIRV::OpGroupNonUniformRotateKHR:
2105 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_subgroup_rotate))
2107 "following SPIR-V extension: SPV_KHR_subgroup_rotate",
2109 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_subgroup_rotate);
2110 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformRotateKHR);
2113 case SPIRV::OpFixedCosALTERA:
2114 case SPIRV::OpFixedSinALTERA:
2115 case SPIRV::OpFixedCosPiALTERA:
2116 case SPIRV::OpFixedSinPiALTERA:
2117 case SPIRV::OpFixedExpALTERA:
2118 case SPIRV::OpFixedLogALTERA:
2119 case SPIRV::OpFixedRecipALTERA:
2120 case SPIRV::OpFixedSqrtALTERA:
2121 case SPIRV::OpFixedSinCosALTERA:
2122 case SPIRV::OpFixedSinCosPiALTERA:
2123 case SPIRV::OpFixedRsqrtALTERA:
2124 if (!ST.canUseExtension(
2125 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_fixed_point))
2127 "following SPIR-V extension: "
2128 "SPV_ALTERA_arbitrary_precision_fixed_point",
2131 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_fixed_point);
2132 Reqs.
addCapability(SPIRV::Capability::ArbitraryPrecisionFixedPointALTERA);
2134 case SPIRV::OpGroupIMulKHR:
2135 case SPIRV::OpGroupFMulKHR:
2136 case SPIRV::OpGroupBitwiseAndKHR:
2137 case SPIRV::OpGroupBitwiseOrKHR:
2138 case SPIRV::OpGroupBitwiseXorKHR:
2139 case SPIRV::OpGroupLogicalAndKHR:
2140 case SPIRV::OpGroupLogicalOrKHR:
2141 case SPIRV::OpGroupLogicalXorKHR:
2142 if (ST.canUseExtension(
2143 SPIRV::Extension::SPV_KHR_uniform_group_instructions)) {
2144 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_uniform_group_instructions);
2145 Reqs.
addCapability(SPIRV::Capability::GroupUniformArithmeticKHR);
2148 case SPIRV::OpReadClockKHR:
2149 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_shader_clock))
2151 "following SPIR-V extension: SPV_KHR_shader_clock",
2153 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_shader_clock);
2156 case SPIRV::OpAbortKHR:
2157 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_abort))
2159 "following SPIR-V extension: SPV_KHR_abort",
2164 case SPIRV::OpPoisonKHR:
2165 case SPIRV::OpFreezeKHR:
2166 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_poison_freeze))
2168 "following SPIR-V extension: SPV_KHR_poison_freeze",
2170 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_poison_freeze);
2173 case SPIRV::OpAtomicFAddEXT:
2174 case SPIRV::OpAtomicFMinEXT:
2175 case SPIRV::OpAtomicFMaxEXT:
2178 case SPIRV::OpConvertBF16ToFINTEL:
2179 case SPIRV::OpConvertFToBF16INTEL:
2180 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bfloat16_conversion)) {
2181 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bfloat16_conversion);
2182 Reqs.
addCapability(SPIRV::Capability::BFloat16ConversionINTEL);
2185 case SPIRV::OpRoundFToTF32INTEL:
2186 if (ST.canUseExtension(
2187 SPIRV::Extension::SPV_INTEL_tensor_float32_conversion)) {
2188 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_tensor_float32_conversion);
2189 Reqs.
addCapability(SPIRV::Capability::TensorFloat32RoundingINTEL);
2192 case SPIRV::OpVariableLengthArrayINTEL:
2193 case SPIRV::OpSaveMemoryINTEL:
2194 case SPIRV::OpRestoreMemoryINTEL:
2195 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_variable_length_array)) {
2196 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_variable_length_array);
2197 Reqs.
addCapability(SPIRV::Capability::VariableLengthArrayINTEL);
2200 case SPIRV::OpUntypedVariableLengthArrayINTEL:
2201 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_variable_length_array)) {
2202 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_variable_length_array);
2203 Reqs.
addCapability(SPIRV::Capability::UntypedVariableLengthArrayINTEL);
2206 case SPIRV::OpAsmTargetINTEL:
2207 case SPIRV::OpAsmINTEL:
2208 case SPIRV::OpAsmCallINTEL:
2209 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_inline_assembly)) {
2210 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_inline_assembly);
2214 case SPIRV::OpTypeCooperativeMatrixKHR: {
2215 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix))
2217 "OpTypeCooperativeMatrixKHR type requires the "
2218 "following SPIR-V extension: SPV_KHR_cooperative_matrix",
2220 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix);
2221 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixKHR);
2225 Reqs.
addCapability(SPIRV::Capability::BFloat16CooperativeMatrixKHR);
2228 case SPIRV::OpArithmeticFenceEXT:
2229 if (!ST.canUseExtension(SPIRV::Extension::SPV_EXT_arithmetic_fence))
2231 "following SPIR-V extension: SPV_EXT_arithmetic_fence",
2233 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_arithmetic_fence);
2236 case SPIRV::OpControlBarrierArriveINTEL:
2237 case SPIRV::OpControlBarrierWaitINTEL:
2238 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_split_barrier)) {
2239 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_split_barrier);
2243 case SPIRV::OpCooperativeMatrixMulAddKHR: {
2244 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix))
2246 "following SPIR-V extension: "
2247 "SPV_KHR_cooperative_matrix",
2249 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix);
2250 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixKHR);
2251 constexpr unsigned MulAddMaxSize = 6;
2252 if (
MI.getNumOperands() != MulAddMaxSize)
2254 const int64_t CoopOperands =
MI.getOperand(MulAddMaxSize - 1).getImm();
2256 SPIRV::CooperativeMatrixOperands::MatrixAAndBTF32ComponentsINTEL) {
2257 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
2259 "require the following SPIR-V extension: "
2260 "SPV_INTEL_joint_matrix",
2262 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2264 SPIRV::Capability::CooperativeMatrixTF32ComponentTypeINTEL);
2267 MatrixAAndBBFloat16ComponentsINTEL ||
2269 SPIRV::CooperativeMatrixOperands::MatrixCBFloat16ComponentsINTEL ||
2271 MatrixResultBFloat16ComponentsINTEL) {
2272 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
2274 "require the following SPIR-V extension: "
2275 "SPV_INTEL_joint_matrix",
2277 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2279 SPIRV::Capability::CooperativeMatrixBFloat16ComponentTypeINTEL);
2283 case SPIRV::OpCooperativeMatrixLoadKHR:
2284 case SPIRV::OpCooperativeMatrixStoreKHR:
2285 case SPIRV::OpCooperativeMatrixLoadCheckedINTEL:
2286 case SPIRV::OpCooperativeMatrixStoreCheckedINTEL:
2287 case SPIRV::OpCooperativeMatrixPrefetchINTEL: {
2288 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix))
2290 "following SPIR-V extension: "
2291 "SPV_KHR_cooperative_matrix",
2293 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix);
2294 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixKHR);
2300 case SPIRV::OpCooperativeMatrixLoadKHR:
2303 case SPIRV::OpCooperativeMatrixStoreKHR:
2306 case SPIRV::OpCooperativeMatrixLoadCheckedINTEL:
2309 case SPIRV::OpCooperativeMatrixStoreCheckedINTEL:
2310 case SPIRV::OpCooperativeMatrixPrefetchINTEL:
2316 Register RegLayout =
MI.getOperand(LayoutNum).getReg();
2319 if (MILayout->
getOpcode() == SPIRV::OpConstantI) {
2322 static_cast<unsigned>(SPIRV::CooperativeMatrixLayout::PackedINTEL)) {
2323 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
2325 "extension: SPV_INTEL_joint_matrix",
2327 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2328 Reqs.
addCapability(SPIRV::Capability::PackedCooperativeMatrixINTEL);
2333 if (
Op == SPIRV::OpCooperativeMatrixLoadKHR ||
2334 Op == SPIRV::OpCooperativeMatrixStoreKHR)
2337 std::string InstName;
2339 case SPIRV::OpCooperativeMatrixPrefetchINTEL:
2340 InstName =
"OpCooperativeMatrixPrefetchINTEL";
2342 case SPIRV::OpCooperativeMatrixLoadCheckedINTEL:
2343 InstName =
"OpCooperativeMatrixLoadCheckedINTEL";
2345 case SPIRV::OpCooperativeMatrixStoreCheckedINTEL:
2346 InstName =
"OpCooperativeMatrixStoreCheckedINTEL";
2350 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix)) {
2351 const std::string ErrorMsg =
2352 InstName +
" instruction requires the "
2353 "following SPIR-V extension: SPV_INTEL_joint_matrix";
2356 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2357 if (
Op == SPIRV::OpCooperativeMatrixPrefetchINTEL) {
2358 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixPrefetchINTEL);
2362 SPIRV::Capability::CooperativeMatrixCheckedInstructionsINTEL);
2365 case SPIRV::OpCooperativeMatrixConstructCheckedINTEL:
2366 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
2368 "instructions require the following SPIR-V extension: "
2369 "SPV_INTEL_joint_matrix",
2371 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2373 SPIRV::Capability::CooperativeMatrixCheckedInstructionsINTEL);
2375 case SPIRV::OpReadPipeBlockingALTERA:
2376 case SPIRV::OpWritePipeBlockingALTERA:
2377 if (ST.canUseExtension(SPIRV::Extension::SPV_ALTERA_blocking_pipes)) {
2378 Reqs.
addExtension(SPIRV::Extension::SPV_ALTERA_blocking_pipes);
2382 case SPIRV::OpCooperativeMatrixGetElementCoordINTEL:
2383 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
2385 "following SPIR-V extension: SPV_INTEL_joint_matrix",
2387 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2389 SPIRV::Capability::CooperativeMatrixInvocationInstructionsINTEL);
2391 case SPIRV::OpConvertHandleToImageINTEL:
2392 case SPIRV::OpConvertHandleToSamplerINTEL:
2393 case SPIRV::OpConvertHandleToSampledImageINTEL: {
2394 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bindless_images))
2396 "instructions require the following SPIR-V extension: "
2397 "SPV_INTEL_bindless_images",
2400 SPIRV::AddressingModel::AddressingModel AddrModel = MAI.
Addr;
2402 if (
Op == SPIRV::OpConvertHandleToImageINTEL &&
2403 TyDef->
getOpcode() != SPIRV::OpTypeImage) {
2405 "OpConvertHandleToImageINTEL",
2407 }
else if (
Op == SPIRV::OpConvertHandleToSamplerINTEL &&
2408 TyDef->
getOpcode() != SPIRV::OpTypeSampler) {
2410 "OpConvertHandleToSamplerINTEL",
2412 }
else if (
Op == SPIRV::OpConvertHandleToSampledImageINTEL &&
2413 TyDef->
getOpcode() != SPIRV::OpTypeSampledImage) {
2415 "OpConvertHandleToSampledImageINTEL",
2421 if (!(Bitwidth == 32 && AddrModel == SPIRV::AddressingModel::Physical32) &&
2422 !(Bitwidth == 64 && AddrModel == SPIRV::AddressingModel::Physical64)) {
2424 "Parameter value must be a 32-bit scalar in case of "
2425 "Physical32 addressing model or a 64-bit scalar in case of "
2426 "Physical64 addressing model",
2429 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bindless_images);
2433 case SPIRV::OpSubgroup2DBlockLoadINTEL:
2434 case SPIRV::OpSubgroup2DBlockLoadTransposeINTEL:
2435 case SPIRV::OpSubgroup2DBlockLoadTransformINTEL:
2436 case SPIRV::OpSubgroup2DBlockPrefetchINTEL:
2437 case SPIRV::OpSubgroup2DBlockStoreINTEL: {
2438 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_2d_block_io))
2440 "Prefetch/Store]INTEL instructions require the "
2441 "following SPIR-V extension: SPV_INTEL_2d_block_io",
2443 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_2d_block_io);
2444 Reqs.
addCapability(SPIRV::Capability::Subgroup2DBlockIOINTEL);
2446 if (
Op == SPIRV::OpSubgroup2DBlockLoadTransposeINTEL) {
2447 Reqs.
addCapability(SPIRV::Capability::Subgroup2DBlockTransposeINTEL);
2450 if (
Op == SPIRV::OpSubgroup2DBlockLoadTransformINTEL) {
2451 Reqs.
addCapability(SPIRV::Capability::Subgroup2DBlockTransformINTEL);
2456 case SPIRV::OpKill: {
2459 case SPIRV::OpDemoteToHelperInvocation:
2460 Reqs.
addCapability(SPIRV::Capability::DemoteToHelperInvocation);
2462 if (ST.canUseExtension(
2463 SPIRV::Extension::SPV_EXT_demote_to_helper_invocation)) {
2466 SPIRV::Extension::SPV_EXT_demote_to_helper_invocation);
2471 case SPIRV::OpSUDot:
2472 case SPIRV::OpSDotAccSat:
2473 case SPIRV::OpUDotAccSat:
2474 case SPIRV::OpSUDotAccSat:
2477 case SPIRV::OpImageSampleImplicitLod:
2478 case SPIRV::OpImageFetch:
2482 case SPIRV::OpImageSampleExplicitLod:
2485 case SPIRV::OpImageSampleDrefImplicitLod:
2486 case SPIRV::OpImageSampleDrefExplicitLod:
2487 case SPIRV::OpImageDrefGather:
2488 case SPIRV::OpImageGather:
2492 case SPIRV::OpImageRead: {
2493 Register ImageReg =
MI.getOperand(2).getReg();
2494 SPIRVTypeInst TypeDef = ST.getSPIRVGlobalRegistry()->getResultType(
2503 Reqs.
addCapability(SPIRV::Capability::StorageImageReadWithoutFormat);
2506 case SPIRV::OpImageWrite: {
2507 Register ImageReg =
MI.getOperand(0).getReg();
2508 SPIRVTypeInst TypeDef = ST.getSPIRVGlobalRegistry()->getResultType(
2517 Reqs.
addCapability(SPIRV::Capability::StorageImageWriteWithoutFormat);
2520 case SPIRV::OpTypeStructContinuedINTEL:
2521 case SPIRV::OpConstantCompositeContinuedINTEL:
2522 case SPIRV::OpSpecConstantCompositeContinuedINTEL:
2523 case SPIRV::OpCompositeConstructContinuedINTEL: {
2524 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_long_composites))
2526 "Continued instructions require the "
2527 "following SPIR-V extension: SPV_INTEL_long_composites",
2529 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_long_composites);
2533 case SPIRV::OpArbitraryFloatEQALTERA:
2534 case SPIRV::OpArbitraryFloatGEALTERA:
2535 case SPIRV::OpArbitraryFloatGTALTERA:
2536 case SPIRV::OpArbitraryFloatLEALTERA:
2537 case SPIRV::OpArbitraryFloatLTALTERA:
2538 case SPIRV::OpArbitraryFloatCbrtALTERA:
2539 case SPIRV::OpArbitraryFloatCosALTERA:
2540 case SPIRV::OpArbitraryFloatCosPiALTERA:
2541 case SPIRV::OpArbitraryFloatExp10ALTERA:
2542 case SPIRV::OpArbitraryFloatExp2ALTERA:
2543 case SPIRV::OpArbitraryFloatExpALTERA:
2544 case SPIRV::OpArbitraryFloatExpm1ALTERA:
2545 case SPIRV::OpArbitraryFloatHypotALTERA:
2546 case SPIRV::OpArbitraryFloatLog10ALTERA:
2547 case SPIRV::OpArbitraryFloatLog1pALTERA:
2548 case SPIRV::OpArbitraryFloatLog2ALTERA:
2549 case SPIRV::OpArbitraryFloatLogALTERA:
2550 case SPIRV::OpArbitraryFloatRecipALTERA:
2551 case SPIRV::OpArbitraryFloatSinCosALTERA:
2552 case SPIRV::OpArbitraryFloatSinCosPiALTERA:
2553 case SPIRV::OpArbitraryFloatSinALTERA:
2554 case SPIRV::OpArbitraryFloatSinPiALTERA:
2555 case SPIRV::OpArbitraryFloatSqrtALTERA:
2556 case SPIRV::OpArbitraryFloatACosALTERA:
2557 case SPIRV::OpArbitraryFloatACosPiALTERA:
2558 case SPIRV::OpArbitraryFloatAddALTERA:
2559 case SPIRV::OpArbitraryFloatASinALTERA:
2560 case SPIRV::OpArbitraryFloatASinPiALTERA:
2561 case SPIRV::OpArbitraryFloatATan2ALTERA:
2562 case SPIRV::OpArbitraryFloatATanALTERA:
2563 case SPIRV::OpArbitraryFloatATanPiALTERA:
2564 case SPIRV::OpArbitraryFloatCastFromIntALTERA:
2565 case SPIRV::OpArbitraryFloatCastALTERA:
2566 case SPIRV::OpArbitraryFloatCastToIntALTERA:
2567 case SPIRV::OpArbitraryFloatDivALTERA:
2568 case SPIRV::OpArbitraryFloatMulALTERA:
2569 case SPIRV::OpArbitraryFloatPowALTERA:
2570 case SPIRV::OpArbitraryFloatPowNALTERA:
2571 case SPIRV::OpArbitraryFloatPowRALTERA:
2572 case SPIRV::OpArbitraryFloatRSqrtALTERA:
2573 case SPIRV::OpArbitraryFloatSubALTERA: {
2574 if (!ST.canUseExtension(
2575 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_floating_point))
2577 "Floating point instructions can't be translated correctly without "
2578 "enabled SPV_ALTERA_arbitrary_precision_floating_point extension!",
2581 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_floating_point);
2583 SPIRV::Capability::ArbitraryPrecisionFloatingPointALTERA);
2586 case SPIRV::OpSubgroupMatrixMultiplyAccumulateINTEL: {
2587 if (!ST.canUseExtension(
2588 SPIRV::Extension::SPV_INTEL_subgroup_matrix_multiply_accumulate))
2590 "OpSubgroupMatrixMultiplyAccumulateINTEL instruction requires the "
2592 "extension: SPV_INTEL_subgroup_matrix_multiply_accumulate",
2595 SPIRV::Extension::SPV_INTEL_subgroup_matrix_multiply_accumulate);
2597 SPIRV::Capability::SubgroupMatrixMultiplyAccumulateINTEL);
2600 case SPIRV::OpBitwiseFunctionINTEL: {
2601 if (!ST.canUseExtension(
2602 SPIRV::Extension::SPV_INTEL_ternary_bitwise_function))
2604 "OpBitwiseFunctionINTEL instruction requires the following SPIR-V "
2605 "extension: SPV_INTEL_ternary_bitwise_function",
2607 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_ternary_bitwise_function);
2608 Reqs.
addCapability(SPIRV::Capability::TernaryBitwiseFunctionINTEL);
2611 case SPIRV::OpCopyMemorySized: {
2616 case SPIRV::OpTypeUntypedPointerKHR:
2618 MI.getOperand(1).getImm(), ST);
2620 case SPIRV::OpUntypedVariableKHR:
2621 case SPIRV::OpUntypedAccessChainKHR:
2622 case SPIRV::OpUntypedInBoundsAccessChainKHR:
2623 case SPIRV::OpUntypedPtrAccessChainKHR:
2624 case SPIRV::OpUntypedInBoundsPtrAccessChainKHR:
2625 case SPIRV::OpUntypedPrefetchKHR:
2626 case SPIRV::OpUntypedGroupAsyncCopyKHR: {
2627 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_untyped_pointers))
2629 "SPIR-V extension: SPV_KHR_untyped_pointers",
2631 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_untyped_pointers);
2635 case SPIRV::OpPredicatedLoadINTEL:
2636 case SPIRV::OpPredicatedStoreINTEL: {
2637 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_predicated_io))
2639 "OpPredicated[Load/Store]INTEL instructions require "
2640 "the following SPIR-V extension: SPV_INTEL_predicated_io",
2642 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_predicated_io);
2646 case SPIRV::OpFAddS:
2647 case SPIRV::OpFSubS:
2648 case SPIRV::OpFMulS:
2649 case SPIRV::OpFDivS:
2650 case SPIRV::OpFRemS:
2652 case SPIRV::OpFNegate:
2653 case SPIRV::OpFAddV:
2654 case SPIRV::OpFSubV:
2655 case SPIRV::OpFMulV:
2656 case SPIRV::OpFDivV:
2657 case SPIRV::OpFRemV:
2658 case SPIRV::OpFNegateV: {
2664 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic))
2666 "Arithmetic instructions with bfloat16 arguments require the "
2667 "following SPIR-V extension: SPV_INTEL_bfloat16_arithmetic",
2669 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic);
2670 Reqs.
addCapability(SPIRV::Capability::BFloat16ArithmeticINTEL);
2674 case SPIRV::OpOrdered:
2675 case SPIRV::OpUnordered:
2676 case SPIRV::OpFOrdEqual:
2677 case SPIRV::OpFOrdNotEqual:
2678 case SPIRV::OpFOrdLessThan:
2679 case SPIRV::OpFOrdLessThanEqual:
2680 case SPIRV::OpFOrdGreaterThan:
2681 case SPIRV::OpFOrdGreaterThanEqual:
2682 case SPIRV::OpFUnordEqual:
2683 case SPIRV::OpFUnordNotEqual:
2684 case SPIRV::OpFUnordLessThan:
2685 case SPIRV::OpFUnordLessThanEqual:
2686 case SPIRV::OpFUnordGreaterThan:
2687 case SPIRV::OpFUnordGreaterThanEqual: {
2690 ST.getSPIRVGlobalRegistry());
2691 assert(TypeDef &&
"Unexpected type instruction for comparison operand");
2695 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic))
2697 "Relational instructions with bfloat16 arguments require the "
2698 "following SPIR-V extension: SPV_INTEL_bfloat16_arithmetic",
2700 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic);
2701 Reqs.
addCapability(SPIRV::Capability::BFloat16ArithmeticINTEL);
2705 case SPIRV::OpDPdxCoarse:
2706 case SPIRV::OpDPdyCoarse:
2707 case SPIRV::OpDPdxFine:
2708 case SPIRV::OpDPdyFine: {
2712 case SPIRV::OpLoopControlINTEL: {
2713 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_unstructured_loop_controls);
2714 Reqs.
addCapability(SPIRV::Capability::UnstructuredLoopControlsINTEL);
2726 SPIRV::Capability::Shader);
2741 auto Node = M.getNamedMetadata(
"spirv.ExecutionMode");
2743 bool RequireFloatControls =
false, RequireIntelFloatControls2 =
false,
2744 RequireKHRFloatControls2 =
false,
2745 VerLower14 = !ST.isAtLeastSPIRVVer(
VersionTuple(1, 4));
2746 bool HasIntelFloatControls2 =
2747 ST.canUseExtension(SPIRV::Extension::SPV_INTEL_float_controls2);
2748 bool HasKHRFloatControls2 =
2749 ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2);
2750 for (
unsigned i = 0; i <
Node->getNumOperands(); i++) {
2756 auto EM = Const->getZExtValue();
2760 case SPIRV::ExecutionMode::DenormPreserve:
2761 case SPIRV::ExecutionMode::DenormFlushToZero:
2762 case SPIRV::ExecutionMode::RoundingModeRTE:
2763 case SPIRV::ExecutionMode::RoundingModeRTZ:
2764 RequireFloatControls = VerLower14;
2766 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2768 case SPIRV::ExecutionMode::RoundingModeRTPINTEL:
2769 case SPIRV::ExecutionMode::RoundingModeRTNINTEL:
2770 case SPIRV::ExecutionMode::FloatingPointModeALTINTEL:
2771 case SPIRV::ExecutionMode::FloatingPointModeIEEEINTEL:
2772 if (HasIntelFloatControls2) {
2773 RequireIntelFloatControls2 =
true;
2775 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2778 case SPIRV::ExecutionMode::FPFastMathDefault: {
2779 if (HasKHRFloatControls2) {
2780 RequireKHRFloatControls2 =
true;
2782 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2786 case SPIRV::ExecutionMode::ContractionOff:
2787 case SPIRV::ExecutionMode::SignedZeroInfNanPreserve:
2788 if (HasKHRFloatControls2) {
2789 RequireKHRFloatControls2 =
true;
2791 SPIRV::OperandCategory::ExecutionModeOperand,
2792 SPIRV::ExecutionMode::FPFastMathDefault, ST);
2795 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2800 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2805 if (RequireFloatControls &&
2806 ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls))
2808 if (RequireIntelFloatControls2)
2810 if (RequireKHRFloatControls2)
2814 if (
F.isDeclaration())
2816 if (
F.getMetadata(
"reqd_work_group_size"))
2818 SPIRV::OperandCategory::ExecutionModeOperand,
2819 SPIRV::ExecutionMode::LocalSize, ST);
2820 if (
F.getFnAttribute(
"hlsl.numthreads").isValid()) {
2822 SPIRV::OperandCategory::ExecutionModeOperand,
2823 SPIRV::ExecutionMode::LocalSize, ST);
2825 if (
F.getFnAttribute(
"enable-maximal-reconvergence").getValueAsBool()) {
2828 if (
F.getMetadata(
"work_group_size_hint"))
2830 SPIRV::OperandCategory::ExecutionModeOperand,
2831 SPIRV::ExecutionMode::LocalSizeHint, ST);
2832 if (
F.getMetadata(
"intel_reqd_sub_group_size") ||
2833 F.getMetadata(
"reqd_sub_group_size"))
2835 SPIRV::OperandCategory::ExecutionModeOperand,
2836 SPIRV::ExecutionMode::SubgroupSize, ST);
2837 if (
F.getMetadata(
"max_work_group_size"))
2839 SPIRV::OperandCategory::ExecutionModeOperand,
2840 SPIRV::ExecutionMode::MaxWorkgroupSizeINTEL, ST);
2841 if (
F.getMetadata(
"vec_type_hint"))
2843 SPIRV::OperandCategory::ExecutionModeOperand,
2844 SPIRV::ExecutionMode::VecTypeHint, ST);
2846 if (
F.hasOptNone()) {
2847 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_optnone)) {
2850 }
else if (ST.canUseExtension(SPIRV::Extension::SPV_EXT_optnone)) {
2860 unsigned Flags = SPIRV::FPFastMathMode::None;
2861 bool CanUseKHRFloatControls2 =
2862 ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2);
2864 Flags |= SPIRV::FPFastMathMode::NotNaN;
2866 Flags |= SPIRV::FPFastMathMode::NotInf;
2868 Flags |= SPIRV::FPFastMathMode::NSZ;
2870 Flags |= SPIRV::FPFastMathMode::AllowRecip;
2872 Flags |= SPIRV::FPFastMathMode::AllowContract;
2874 if (CanUseKHRFloatControls2)
2882 Flags |= SPIRV::FPFastMathMode::NotNaN | SPIRV::FPFastMathMode::NotInf |
2883 SPIRV::FPFastMathMode::NSZ | SPIRV::FPFastMathMode::AllowRecip |
2884 SPIRV::FPFastMathMode::AllowTransform |
2885 SPIRV::FPFastMathMode::AllowReassoc |
2886 SPIRV::FPFastMathMode::AllowContract;
2888 Flags |= SPIRV::FPFastMathMode::Fast;
2891 if (CanUseKHRFloatControls2) {
2893 assert(!(Flags & SPIRV::FPFastMathMode::Fast) &&
2894 "SPIRV::FPFastMathMode::Fast is deprecated and should not be used "
2899 assert((!(Flags & SPIRV::FPFastMathMode::AllowTransform) ||
2900 ((Flags & SPIRV::FPFastMathMode::AllowReassoc &&
2901 Flags & SPIRV::FPFastMathMode::AllowContract))) &&
2902 "SPIRV::FPFastMathMode::AllowTransform requires AllowReassoc and "
2903 "AllowContract flags to be enabled as well.");
2914 return ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2);
2924 auto Decorate = [&](SPIRV::Decoration::Decoration Dec,
2931 if (
TII.canUseIntegerWrapDecoration(
I)) {
2934 SPIRV::OperandCategory::DecorationOperand,
2935 SPIRV::Decoration::NoSignedWrap, ST, Reqs)
2937 Decorate(SPIRV::Decoration::NoSignedWrap, {});
2940 SPIRV::OperandCategory::DecorationOperand,
2941 SPIRV::Decoration::NoUnsignedWrap, ST, Reqs)
2943 Decorate(SPIRV::Decoration::NoUnsignedWrap, {});
2948 TII.canUseFastMathFlags(
2949 I, ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2)) ||
2950 (ST.isKernel() &&
I.getOpcode() == SPIRV::OpExtInst);
2955 if (FMFlags == SPIRV::FPFastMathMode::None) {
2958 if (FPFastMathDefaultInfoVec.
empty())
2964 I.getOpcode() == SPIRV::OpExtInst ||
2965 I.getOpcode() == SPIRV::OpFunctionCall
2966 ?
I.getMF()->getRegInfo().getVRegDef(
I.getOperand(1).getReg())
2967 :
getRegType(
I.getOperand(2).getReg(), *
I.getMF(), GR);
2974 if (Ty == Elem.Ty) {
2975 FMFlags = Elem.FastMathFlags;
2976 Emit = Elem.ContractionOff || Elem.SignedZeroInfNanPreserve ||
2977 Elem.FPFastMathDefault;
2982 if (FMFlags == SPIRV::FPFastMathMode::None && !Emit)
2986 Decorate(SPIRV::Decoration::FPFastMathMode, {FMFlags});
3000 for (
const auto &
MBB : *MF) {
3001 if (!
MBB.hasName() ||
MBB.empty())
3012 auto it = FPFastMathDefaultInfoMap.
find(
F);
3013 if (it != FPFastMathDefaultInfoMap.
end())
3021 SPIRV::FPFastMathMode::None);
3023 SPIRV::FPFastMathMode::None);
3025 SPIRV::FPFastMathMode::None);
3026 return FPFastMathDefaultInfoMap[
F] = std::move(FPFastMathDefaultInfoVec);
3032 size_t BitWidth = Ty->getScalarSizeInBits();
3036 assert(Index >= 0 && Index < 3 &&
3037 "Expected FPFastMathDefaultInfo for half, float, or double");
3038 assert(FPFastMathDefaultInfoVec.
size() == 3 &&
3039 "Expected FPFastMathDefaultInfoVec to have exactly 3 elements");
3040 return FPFastMathDefaultInfoVec[Index];
3047 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2))
3056 auto Node = M.getNamedMetadata(
"spirv.ExecutionMode");
3060 for (
unsigned i = 0; i <
Node->getNumOperands(); i++) {
3065 if (OnlyF &&
F != OnlyF)
3071 if (EM == SPIRV::ExecutionMode::FPFastMathDefault) {
3073 "Expected 4 operands for FPFastMathDefault");
3084 Info.FastMathFlags = Flags;
3085 Info.FPFastMathDefault =
true;
3086 }
else if (EM == SPIRV::ExecutionMode::ContractionOff) {
3088 "Expected no operands for ContractionOff");
3095 Info.ContractionOff =
true;
3097 }
else if (EM == SPIRV::ExecutionMode::SignedZeroInfNanPreserve) {
3099 "Expected 1 operand for SignedZeroInfNanPreserve");
3100 unsigned TargetWidth =
3109 assert(Index >= 0 && Index < 3 &&
3110 "Expected FPFastMathDefaultInfo for half, float, or double");
3111 assert(FPFastMathDefaultInfoVec.
size() == 3 &&
3112 "Expected FPFastMathDefaultInfoVec to have exactly 3 elements");
3113 FPFastMathDefaultInfoVec[Index].SignedZeroInfNanPreserve =
true;
3121 : ST(&ST), GR(ST.getSPIRVGlobalRegistry()), TII(ST.getInstrInfo()),
3122 MAI(MAI), GetMF(GetMF) {}
3134 collectDeclarations(M);
3137 numberRegistersGlobally(M);
3140 processOtherInstrs(M);
3144 MAI.Reqs.addCapability(SPIRV::Capability::Linkage);
3147 GR->setBound(MAI.MaxID);
3161 [&MMI](
const Function &
F) { return MMI.getMachineFunction(F); })
3177 MachineFunctionAnalysis::Result *MFA =
3178 FAM.getCachedResult<MachineFunctionAnalysis>(
3179 const_cast<Function &>(F));
3180 assert((MFA || F.isDeclaration()) &&
3181 "Missing MachineFunction for definition");
3182 return MFA ? &MFA->getMF() : nullptr;
3199 for (
auto &
MBB : MF)
3202 FPFastMathDefaultInfoMap[&
F]);
3210 SPIRVPrepareModuleAnalysisLegacy() : MachineFunctionPass(
ID) {}
3217char SPIRVPrepareModuleAnalysisLegacy::ID = 0;
3220 "spirv-prepare-module-analysis",
3221 "SPIRV prepare module analysis",
false,
false)
3224 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