34#define DEBUG_TYPE "spirv-module-analysis"
38 cl::desc(
"Dump MIR with SPIR-V dependencies info"),
43 cl::desc(
"SPIR-V capabilities to avoid if there are "
44 "other options enabling a feature"),
47 "SPIR-V Shader capability")));
61 unsigned DefaultVal = 0) {
63 const auto &
Op = MdNode->getOperand(
OpIndex);
70getSymbolicOperandRequirements(SPIRV::OperandCategory::OperandCategory Category,
76 AvoidCaps.
S.
insert(SPIRV::Capability::Shader);
78 AvoidCaps.
S.
insert(SPIRV::Capability::Kernel);
83 bool MinVerOK = SPIRVVersion.
empty() || SPIRVVersion >= ReqMinVer;
85 ReqMaxVer.
empty() || SPIRVVersion.
empty() || SPIRVVersion <= ReqMaxVer;
88 if (ReqCaps.
empty()) {
89 if (ReqExts.
empty()) {
90 if (MinVerOK && MaxVerOK)
91 return {
true, {}, {}, ReqMinVer, ReqMaxVer};
94 }
else if (MinVerOK && MaxVerOK) {
95 if (ReqCaps.
size() == 1) {
96 auto Cap = ReqCaps[0];
99 SPIRV::OperandCategory::CapabilityOperand, Cap));
100 return {
true, {Cap}, std::move(ReqExts), ReqMinVer, ReqMaxVer};
110 for (
auto Cap : ReqCaps)
113 for (
size_t i = 0, Sz = UseCaps.
size(); i < Sz; ++i) {
114 auto Cap = UseCaps[i];
115 if (i == Sz - 1 || !AvoidCaps.
S.
contains(Cap)) {
117 SPIRV::OperandCategory::CapabilityOperand, Cap));
118 return {
true, {Cap}, std::move(ReqExts), ReqMinVer, ReqMaxVer};
126 if (
llvm::all_of(ReqExts, [&ST](
const SPIRV::Extension::Extension &Ext) {
127 return ST.canUseExtension(Ext);
138void SPIRVModuleAnalysis::setBaseInfo(
const Module &M) {
142 MAI.RegisterAliasTable.clear();
143 MAI.InstrsToDelete.clear();
144 MAI.GlobalObjMap.clear();
145 MAI.GlobalVarList.clear();
146 MAI.ExtInstSetMap.clear();
148 MAI.Reqs.initAvailableCapabilities(*ST);
151 if (
auto MemModel =
M.getNamedMetadata(
"spirv.MemoryModel")) {
152 auto MemMD = MemModel->getOperand(0);
153 MAI.Addr =
static_cast<SPIRV::AddressingModel::AddressingModel
>(
154 getMetadataUInt(MemMD, 0));
156 static_cast<SPIRV::MemoryModel::MemoryModel
>(getMetadataUInt(MemMD, 1));
159 MAI.Mem = ST->isShader() ? SPIRV::MemoryModel::GLSL450
160 : SPIRV::MemoryModel::OpenCL;
161 if (
MAI.Mem == SPIRV::MemoryModel::OpenCL) {
162 unsigned PtrSize = ST->getPointerSize();
163 MAI.Addr = PtrSize == 32 ? SPIRV::AddressingModel::Physical32
164 : PtrSize == 64 ? SPIRV::AddressingModel::Physical64
165 : SPIRV::AddressingModel::Logical;
168 MAI.Addr = SPIRV::AddressingModel::Logical;
173 if (
auto VerNode =
M.getNamedMetadata(
"opencl.ocl.version")) {
174 MAI.SrcLang = SPIRV::SourceLanguage::OpenCL_C;
177 assert(VerNode->getNumOperands() > 0 &&
"Invalid SPIR");
178 auto VersionMD = VerNode->getOperand(0);
179 unsigned MajorNum = getMetadataUInt(VersionMD, 0, 2);
180 unsigned MinorNum = getMetadataUInt(VersionMD, 1);
181 unsigned RevNum = getMetadataUInt(VersionMD, 2);
184 (std::max(1U, MajorNum) * 100 + MinorNum) * 1000 + RevNum;
187 if (
auto *CxxVerNode =
M.getNamedMetadata(
"opencl.cxx.version")) {
188 assert(CxxVerNode->getNumOperands() > 0 &&
"Invalid SPIR");
189 auto *CxxMD = CxxVerNode->getOperand(0);
191 (getMetadataUInt(CxxMD, 0) * 100 + getMetadataUInt(CxxMD, 1)) * 1000 +
192 getMetadataUInt(CxxMD, 2);
193 if ((
MAI.SrcLangVersion == 200000 && CxxVer == 100000) ||
194 (
MAI.SrcLangVersion == 300000 && CxxVer == 202100000)) {
195 MAI.SrcLang = SPIRV::SourceLanguage::CPP_for_OpenCL;
196 MAI.SrcLangVersion = CxxVer;
199 "opencl cxx version is not compatible with opencl c version!");
207 if (!ST->isShader()) {
208 MAI.SrcLang = SPIRV::SourceLanguage::OpenCL_CPP;
209 MAI.SrcLangVersion = 100000;
211 MAI.SrcLang = SPIRV::SourceLanguage::Unknown;
212 MAI.SrcLangVersion = 0;
216 if (
auto ExtNode =
M.getNamedMetadata(
"opencl.used.extensions")) {
217 for (
unsigned I = 0,
E = ExtNode->getNumOperands();
I !=
E; ++
I) {
218 MDNode *MD = ExtNode->getOperand(
I);
228 MAI.Reqs.getAndAddRequirements(SPIRV::OperandCategory::MemoryModelOperand,
230 MAI.Reqs.getAndAddRequirements(SPIRV::OperandCategory::SourceLanguageOperand,
232 MAI.Reqs.getAndAddRequirements(SPIRV::OperandCategory::AddressingModelOperand,
235 if (
MAI.Mem == SPIRV::MemoryModel::VulkanKHR)
236 MAI.Reqs.addExtension(SPIRV::Extension::SPV_KHR_vulkan_memory_model);
238 if (!ST->isShader()) {
240 MAI.ExtInstSetMap[
static_cast<unsigned>(
241 SPIRV::InstructionSet::OpenCL_std)] =
MAI.getNextIDRegister();
252 if (
UseMI.getOpcode() != SPIRV::OpDecorate &&
253 UseMI.getOpcode() != SPIRV::OpMemberDecorate)
256 for (
unsigned I = 0;
I <
UseMI.getNumOperands(); ++
I) {
274 for (
unsigned i = 0; i <
MI.getNumOperands(); ++i) {
283 unsigned Opcode =
MI.getOpcode();
284 if ((Opcode == SPIRV::OpDecorate) && i >= 2) {
285 unsigned DecorationID =
MI.getOperand(1).getImm();
286 if (DecorationID != SPIRV::Decoration::FuncParamAttr &&
287 DecorationID != SPIRV::Decoration::UserSemantic &&
288 DecorationID != SPIRV::Decoration::CacheControlLoadINTEL &&
289 DecorationID != SPIRV::Decoration::CacheControlStoreINTEL)
295 if (!UseDefReg && MO.
isDef()) {
303 dbgs() <<
"Unexpectedly, no global id found for the operand ";
305 dbgs() <<
"\nInstruction: ";
324 appendDecorationsForReg(
MI.getMF()->getRegInfo(), DefReg, Signature);
331 unsigned Opcode =
MI.getOpcode();
333 case SPIRV::OpTypeForwardPointer:
336 case SPIRV::OpVariable:
337 return static_cast<SPIRV::StorageClass::StorageClass
>(
338 MI.getOperand(2).
getImm()) != SPIRV::StorageClass::Function;
339 case SPIRV::OpFunction:
340 case SPIRV::OpFunctionParameter:
343 if (GR->hasConstFunPtr() && Opcode == SPIRV::OpUndef) {
346 if (
UseMI.getOpcode() != SPIRV::OpConstantFunctionPointerINTEL)
352 MAI.setSkipEmission(&
MI);
356 return TII->isTypeDeclInstr(
MI) || TII->isConstantInstr(
MI) ||
357 TII->isInlineAsmDefInstr(
MI);
363void SPIRVModuleAnalysis::visitFunPtrUse(
365 std::map<const Value *, unsigned> &GlobalToGReg,
const MachineFunction *MF,
367 const MachineOperand *OpFunDef =
368 GR->getFunctionDefinitionByUse(&
MI.getOperand(2));
371 const MachineInstr *OpDefMI = OpFunDef->
getParent();
374 const MachineRegisterInfo &FunDefMRI = FunDefMF->
getRegInfo();
376 visitDecl(FunDefMRI, SignatureToGReg, GlobalToGReg, FunDefMF, *OpDefMI);
378 }
while (OpDefMI && (OpDefMI->
getOpcode() == SPIRV::OpFunction ||
379 OpDefMI->
getOpcode() == SPIRV::OpFunctionParameter));
381 MCRegister GlobalFunDefReg =
382 MAI.getRegisterAlias(FunDefMF, OpFunDef->
getReg());
384 "Function definition must refer to a global register");
385 MAI.setRegisterAlias(MF, OpReg, GlobalFunDefReg);
390void SPIRVModuleAnalysis::visitDecl(
392 std::map<const Value *, unsigned> &GlobalToGReg,
const MachineFunction *MF,
394 unsigned Opcode =
MI.getOpcode();
397 for (
const MachineOperand &MO :
MI.operands()) {
402 if (Opcode == SPIRV::OpConstantFunctionPointerINTEL &&
404 visitFunPtrUse(OpReg, SignatureToGReg, GlobalToGReg, MF,
MI);
408 if (
MAI.hasRegisterAlias(MF, MO.
getReg()))
412 if (isDeclSection(MRI, *OpDefMI))
413 visitDecl(MRI, SignatureToGReg, GlobalToGReg, MF, *OpDefMI);
419 dbgs() <<
"Unexpectedly, no unique definition for the operand ";
421 dbgs() <<
"\nInstruction: ";
426 "No unique definition is found for the virtual register");
430 bool IsFunDef =
false;
431 if (TII->isSpecConstantInstr(
MI)) {
432 GReg =
MAI.getNextIDRegister();
434 }
else if (Opcode == SPIRV::OpFunction ||
435 Opcode == SPIRV::OpFunctionParameter) {
436 GReg = handleFunctionOrParameter(MF,
MI, GlobalToGReg, IsFunDef);
437 }
else if (Opcode == SPIRV::OpTypeStruct ||
438 Opcode == SPIRV::OpConstantComposite) {
439 GReg = handleTypeDeclOrConstant(
MI, SignatureToGReg);
440 const MachineInstr *NextInstr =
MI.getNextNode();
442 ((Opcode == SPIRV::OpTypeStruct &&
443 NextInstr->
getOpcode() == SPIRV::OpTypeStructContinuedINTEL) ||
444 (Opcode == SPIRV::OpConstantComposite &&
446 SPIRV::OpConstantCompositeContinuedINTEL))) {
447 MCRegister Tmp = handleTypeDeclOrConstant(*NextInstr, SignatureToGReg);
449 MAI.setSkipEmission(NextInstr);
452 }
else if (TII->isTypeDeclInstr(
MI) || TII->isConstantInstr(
MI) ||
453 TII->isInlineAsmDefInstr(
MI)) {
454 GReg = handleTypeDeclOrConstant(
MI, SignatureToGReg);
455 }
else if (Opcode == SPIRV::OpVariable) {
456 GReg = handleVariable(MF,
MI, GlobalToGReg);
459 dbgs() <<
"\nInstruction: ";
465 MAI.setRegisterAlias(MF,
MI.getOperand(0).getReg(), GReg);
467 MAI.setSkipEmission(&
MI);
470MCRegister SPIRVModuleAnalysis::handleFunctionOrParameter(
472 std::map<const Value *, unsigned> &GlobalToGReg,
bool &IsFunDef) {
473 const Value *GObj = GR->getGlobalObject(MF,
MI.getOperand(0).getReg());
474 assert(GObj &&
"Unregistered global definition");
478 assert(
F &&
"Expected a reference to a function or an argument");
479 IsFunDef = !
F->isDeclaration();
480 auto [It,
Inserted] = GlobalToGReg.try_emplace(GObj);
483 MCRegister GReg =
MAI.getNextIDRegister();
491SPIRVModuleAnalysis::handleTypeDeclOrConstant(
const MachineInstr &
MI,
494 auto [It,
Inserted] = SignatureToGReg.try_emplace(MISign);
497 MCRegister GReg =
MAI.getNextIDRegister();
503MCRegister SPIRVModuleAnalysis::handleVariable(
505 std::map<const Value *, unsigned> &GlobalToGReg) {
506 MAI.GlobalVarList.push_back(&
MI);
507 const Value *GObj = GR->getGlobalObject(MF,
MI.getOperand(0).getReg());
508 assert(GObj &&
"Unregistered global definition");
509 auto [It,
Inserted] = GlobalToGReg.try_emplace(GObj);
512 MCRegister GReg =
MAI.getNextIDRegister();
516 MAI.GlobalObjMap[GV] = GReg;
520void SPIRVModuleAnalysis::collectDeclarations(
const Module &M) {
522 std::map<const Value *, unsigned> GlobalToGReg;
523 for (
const Function &
F : M) {
524 MachineFunction *MF = MMI->getMachineFunction(
F);
527 const MachineRegisterInfo &MRI = MF->
getRegInfo();
528 unsigned PastHeader = 0;
529 for (MachineBasicBlock &
MBB : *MF) {
530 for (MachineInstr &
MI :
MBB) {
531 if (
MI.getNumOperands() == 0)
533 unsigned Opcode =
MI.getOpcode();
534 if (Opcode == SPIRV::OpFunction) {
535 if (PastHeader == 0) {
539 }
else if (Opcode == SPIRV::OpFunctionParameter) {
542 }
else if (PastHeader > 0) {
546 const MachineOperand &DefMO =
MI.getOperand(0);
548 case SPIRV::OpExtension:
549 MAI.Reqs.addExtension(SPIRV::Extension::Extension(DefMO.
getImm()));
550 MAI.setSkipEmission(&
MI);
552 case SPIRV::OpCapability:
553 MAI.Reqs.addCapability(SPIRV::Capability::Capability(DefMO.
getImm()));
554 MAI.setSkipEmission(&
MI);
559 if (DefMO.
isReg() && isDeclSection(MRI,
MI) &&
560 !
MAI.hasRegisterAlias(MF, DefMO.
getReg()))
561 visitDecl(MRI, SignatureToGReg, GlobalToGReg, MF,
MI);
574 if (
MI.getOpcode() == SPIRV::OpDecorate) {
576 auto Dec =
MI.getOperand(1).getImm();
577 if (Dec == SPIRV::Decoration::LinkageAttributes) {
578 auto Lnk =
MI.getOperand(
MI.getNumOperands() - 1).getImm();
579 if (Lnk == SPIRV::LinkageType::Import) {
584 MAI.GlobalObjMap[ImportedFunc] =
585 MAI.getRegisterAlias(
MI.getMF(), Target);
588 }
else if (
MI.getOpcode() == SPIRV::OpFunction) {
591 MCRegister GlobalReg =
MAI.getRegisterAlias(
MI.getMF(),
Reg);
593 MAI.GlobalObjMap[
F] = GlobalReg;
605 auto FoundMI = IS.insert(std::move(MISign));
606 if (!FoundMI.second) {
607 if (
MI.getOpcode() == SPIRV::OpDecorate) {
609 "Decoration instructions must have at least 2 operands");
611 "Only OpDecorate instructions can be duplicates");
616 if (
MI.getOperand(1).getImm() != SPIRV::Decoration::FPFastMathMode)
621 if (instrToSignature(*OrigMI, MAI,
true) == MISign) {
622 assert(OrigMI->getNumOperands() ==
MI.getNumOperands() &&
623 "Original instruction must have the same number of operands");
625 OrigMI->getNumOperands() == 3 &&
626 "FPFastMathMode decoration must have 3 operands for OpDecorate");
627 unsigned OrigFlags = OrigMI->getOperand(2).getImm();
628 unsigned NewFlags =
MI.getOperand(2).getImm();
629 if (OrigFlags == NewFlags)
633 unsigned FinalFlags = OrigFlags | NewFlags;
635 <<
"Warning: Conflicting FPFastMathMode decoration flags "
637 << *OrigMI <<
"Original flags: " << OrigFlags
638 <<
", new flags: " << NewFlags
639 <<
". They will be merged on a best effort basis, but not "
640 "validated. Final flags: "
641 << FinalFlags <<
"\n";
648 assert(
false &&
"No original instruction found for the duplicate "
649 "OpDecorate, but we found one in IS.");
662void SPIRVModuleAnalysis::processOtherInstrs(
const Module &M) {
664 for (
const Function &
F : M) {
665 if (
F.isDeclaration())
667 MachineFunction *MF = MMI->getMachineFunction(
F);
670 for (MachineBasicBlock &
MBB : *MF)
671 for (MachineInstr &
MI :
MBB) {
672 if (
MAI.getSkipEmission(&
MI))
674 const unsigned OpCode =
MI.getOpcode();
675 if (OpCode == SPIRV::OpString) {
677 }
else if (OpCode == SPIRV::OpExtInst &&
MI.getOperand(2).isImm() &&
678 MI.getOperand(2).getImm() ==
679 SPIRV::InstructionSet::
680 NonSemantic_Shader_DebugInfo_100) {
681 MachineOperand Ins =
MI.getOperand(3);
682 namespace NS = SPIRV::NonSemanticExtInst;
683 static constexpr int64_t GlobalNonSemanticDITy[] = {
684 NS::DebugSource, NS::DebugCompilationUnit, NS::DebugInfoNone,
685 NS::DebugTypeBasic, NS::DebugTypePointer};
686 bool IsGlobalDI =
false;
687 for (
unsigned Idx = 0; Idx < std::size(GlobalNonSemanticDITy); ++Idx)
688 IsGlobalDI |= Ins.
getImm() == GlobalNonSemanticDITy[Idx];
691 }
else if (OpCode == SPIRV::OpName || OpCode == SPIRV::OpMemberName) {
693 }
else if (OpCode == SPIRV::OpEntryPoint) {
695 }
else if (TII->isAliasingInstr(
MI)) {
697 }
else if (TII->isDecorationInstr(
MI)) {
699 collectFuncNames(
MI, &
F);
700 }
else if (TII->isConstantInstr(
MI)) {
704 }
else if (OpCode == SPIRV::OpFunction) {
705 collectFuncNames(
MI, &
F);
706 }
else if (OpCode == SPIRV::OpTypeForwardPointer) {
716void SPIRVModuleAnalysis::numberRegistersGlobally(
const Module &M) {
717 for (
const Function &
F : M) {
718 if (
F.isDeclaration())
720 MachineFunction *MF = MMI->getMachineFunction(
F);
722 for (MachineBasicBlock &
MBB : *MF) {
723 for (MachineInstr &
MI :
MBB) {
724 for (MachineOperand &
Op :
MI.operands()) {
728 if (
MAI.hasRegisterAlias(MF,
Reg))
730 MCRegister NewReg =
MAI.getNextIDRegister();
731 MAI.setRegisterAlias(MF,
Reg, NewReg);
733 if (
MI.getOpcode() != SPIRV::OpExtInst)
735 auto Set =
MI.getOperand(2).getImm();
736 auto [It,
Inserted] =
MAI.ExtInstSetMap.try_emplace(Set);
738 It->second =
MAI.getNextIDRegister();
746 SPIRV::OperandCategory::OperandCategory Category, uint32_t i,
748 addRequirements(getSymbolicOperandRequirements(Category, i, ST, *
this));
751void SPIRV::RequirementHandler::recursiveAddCapabilities(
753 for (
const auto &Cap : ToPrune) {
757 recursiveAddCapabilities(ImplicitDecls);
762 for (
const auto &Cap : ToAdd) {
763 bool IsNewlyInserted = AllCaps.insert(Cap).second;
764 if (!IsNewlyInserted)
768 recursiveAddCapabilities(ImplicitDecls);
769 MinimalCaps.push_back(Cap);
774 const SPIRV::Requirements &Req) {
778 if (Req.
Cap.has_value())
779 addCapabilities({Req.
Cap.value()});
781 addExtensions(Req.
Exts);
784 if (!MaxVersion.empty() && Req.
MinVer > MaxVersion) {
786 <<
" and <= " << MaxVersion <<
"\n");
790 if (MinVersion.empty() || Req.
MinVer > MinVersion)
795 if (!MinVersion.empty() && Req.
MaxVer < MinVersion) {
797 <<
" and >= " << MinVersion <<
"\n");
801 if (MaxVersion.empty() || Req.
MaxVer < MaxVersion)
807 const SPIRVSubtarget &ST)
const {
809 bool IsSatisfiable =
true;
810 auto TargetVer =
ST.getSPIRVVersion();
812 if (!MaxVersion.empty() && !TargetVer.empty() && MaxVersion < TargetVer) {
814 dbgs() <<
"Target SPIR-V version too high for required features\n"
815 <<
"Required max version: " << MaxVersion <<
" target version "
816 << TargetVer <<
"\n");
817 IsSatisfiable =
false;
820 if (!MinVersion.empty() && !TargetVer.empty() && MinVersion > TargetVer) {
821 LLVM_DEBUG(
dbgs() <<
"Target SPIR-V version too low for required features\n"
822 <<
"Required min version: " << MinVersion
823 <<
" target version " << TargetVer <<
"\n");
824 IsSatisfiable =
false;
827 if (!MinVersion.empty() && !MaxVersion.empty() && MinVersion > MaxVersion) {
830 <<
"Version is too low for some features and too high for others.\n"
831 <<
"Required SPIR-V min version: " << MinVersion
832 <<
" required SPIR-V max version " << MaxVersion <<
"\n");
833 IsSatisfiable =
false;
836 AvoidCapabilitiesSet AvoidCaps;
838 AvoidCaps.
S.
insert(SPIRV::Capability::Shader);
840 AvoidCaps.
S.
insert(SPIRV::Capability::Kernel);
842 for (
auto Cap : MinimalCaps) {
843 if (AvailableCaps.contains(Cap) && !AvoidCaps.
S.
contains(Cap))
847 OperandCategory::CapabilityOperand, Cap)
849 IsSatisfiable =
false;
852 for (
auto Ext : AllExtensions) {
853 if (
ST.canUseExtension(Ext))
857 OperandCategory::ExtensionOperand, Ext)
859 IsSatisfiable =
false;
868 for (
const auto Cap : ToAdd)
869 if (AvailableCaps.insert(Cap).second)
871 SPIRV::OperandCategory::CapabilityOperand, Cap));
875 const Capability::Capability
ToRemove,
876 const Capability::Capability IfPresent) {
877 if (AllCaps.contains(IfPresent))
885 addAvailableCaps({Capability::Shader, Capability::Linkage, Capability::Int8,
888 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 3)))
890 Capability::GroupNonUniformVote,
891 Capability::GroupNonUniformArithmetic,
892 Capability::GroupNonUniformBallot,
893 Capability::GroupNonUniformClustered,
894 Capability::GroupNonUniformShuffle,
895 Capability::GroupNonUniformShuffleRelative,
896 Capability::GroupNonUniformQuad});
898 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 6)))
900 Capability::DotProductInput4x8Bit,
901 Capability::DotProductInput4x8BitPacked,
902 Capability::DemoteToHelperInvocation});
905 for (
auto Extension :
ST.getAllAvailableExtensions()) {
911 if (!
ST.isShader()) {
912 initAvailableCapabilitiesForOpenCL(ST);
917 initAvailableCapabilitiesForVulkan(ST);
924void RequirementHandler::initAvailableCapabilitiesForOpenCL(
925 const SPIRVSubtarget &ST) {
928 Capability::Kernel, Capability::Vector16,
929 Capability::Groups, Capability::GenericPointer,
930 Capability::StorageImageWriteWithoutFormat,
931 Capability::StorageImageReadWithoutFormat});
932 if (
ST.hasOpenCLFullProfile())
934 if (
ST.hasOpenCLImageSupport()) {
936 Capability::Image1D, Capability::SampledBuffer,
937 Capability::ImageBuffer});
938 if (
ST.isAtLeastOpenCLVer(VersionTuple(2, 0)))
941 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 1)) &&
942 ST.isAtLeastOpenCLVer(VersionTuple(2, 2)))
944 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 4)))
945 addAvailableCaps({Capability::DenormPreserve, Capability::DenormFlushToZero,
946 Capability::SignedZeroInfNanPreserve,
947 Capability::RoundingModeRTE,
948 Capability::RoundingModeRTZ});
955void RequirementHandler::initAvailableCapabilitiesForVulkan(
956 const SPIRVSubtarget &ST) {
959 addAvailableCaps({Capability::Int64, Capability::Float16, Capability::Float64,
960 Capability::GroupNonUniform, Capability::Image1D,
961 Capability::SampledBuffer, Capability::ImageBuffer,
962 Capability::UniformBufferArrayDynamicIndexing,
963 Capability::SampledImageArrayDynamicIndexing,
964 Capability::StorageBufferArrayDynamicIndexing,
965 Capability::StorageImageArrayDynamicIndexing,
966 Capability::DerivativeControl, Capability::MinLod,
967 Capability::ImageQuery, Capability::ImageGatherExtended,
968 Capability::Addresses, Capability::VulkanMemoryModelKHR});
971 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 5))) {
973 {Capability::ShaderNonUniformEXT, Capability::RuntimeDescriptorArrayEXT,
974 Capability::InputAttachmentArrayDynamicIndexingEXT,
975 Capability::UniformTexelBufferArrayDynamicIndexingEXT,
976 Capability::StorageTexelBufferArrayDynamicIndexingEXT,
977 Capability::UniformBufferArrayNonUniformIndexingEXT,
978 Capability::SampledImageArrayNonUniformIndexingEXT,
979 Capability::StorageBufferArrayNonUniformIndexingEXT,
980 Capability::StorageImageArrayNonUniformIndexingEXT,
981 Capability::InputAttachmentArrayNonUniformIndexingEXT,
982 Capability::UniformTexelBufferArrayNonUniformIndexingEXT,
983 Capability::StorageTexelBufferArrayNonUniformIndexingEXT});
987 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 6)))
989 Capability::StorageImageReadWithoutFormat});
997static void addOpDecorateReqs(
const MachineInstr &
MI,
unsigned DecIndex,
1000 int64_t DecOp =
MI.getOperand(DecIndex).getImm();
1001 auto Dec =
static_cast<SPIRV::Decoration::Decoration
>(DecOp);
1003 SPIRV::OperandCategory::DecorationOperand, Dec, ST, Reqs));
1005 if (Dec == SPIRV::Decoration::BuiltIn) {
1006 int64_t BuiltInOp =
MI.getOperand(DecIndex + 1).getImm();
1007 auto BuiltIn =
static_cast<SPIRV::BuiltIn::BuiltIn
>(BuiltInOp);
1009 SPIRV::OperandCategory::BuiltInOperand, BuiltIn, ST, Reqs));
1010 }
else if (Dec == SPIRV::Decoration::LinkageAttributes) {
1011 int64_t LinkageOp =
MI.getOperand(
MI.getNumOperands() - 1).getImm();
1012 SPIRV::LinkageType::LinkageType LnkType =
1013 static_cast<SPIRV::LinkageType::LinkageType
>(LinkageOp);
1014 if (LnkType == SPIRV::LinkageType::LinkOnceODR)
1015 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_linkonce_odr);
1016 }
else if (Dec == SPIRV::Decoration::CacheControlLoadINTEL ||
1017 Dec == SPIRV::Decoration::CacheControlStoreINTEL) {
1018 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_cache_controls);
1019 }
else if (Dec == SPIRV::Decoration::HostAccessINTEL) {
1020 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_global_variable_host_access);
1021 }
else if (Dec == SPIRV::Decoration::InitModeINTEL ||
1022 Dec == SPIRV::Decoration::ImplementInRegisterMapINTEL) {
1024 SPIRV::Extension::SPV_INTEL_global_variable_fpga_decorations);
1025 }
else if (Dec == SPIRV::Decoration::NonUniformEXT) {
1027 }
else if (Dec == SPIRV::Decoration::FPMaxErrorDecorationINTEL) {
1029 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_fp_max_error);
1030 }
else if (Dec == SPIRV::Decoration::FPFastMathMode) {
1031 if (
ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2)) {
1033 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_float_controls2);
1042 assert(
MI.getNumOperands() >= 8 &&
"Insufficient operands for OpTypeImage");
1045 int64_t ImgFormatOp =
MI.getOperand(7).getImm();
1046 auto ImgFormat =
static_cast<SPIRV::ImageFormat::ImageFormat
>(ImgFormatOp);
1050 bool IsArrayed =
MI.getOperand(4).getImm() == 1;
1051 bool IsMultisampled =
MI.getOperand(5).getImm() == 1;
1052 bool NoSampler =
MI.getOperand(6).getImm() == 2;
1055 switch (
MI.getOperand(2).getImm()) {
1056 case SPIRV::Dim::DIM_1D:
1058 : SPIRV::Capability::Sampled1D);
1060 case SPIRV::Dim::DIM_2D:
1061 if (IsMultisampled && NoSampler)
1064 case SPIRV::Dim::DIM_Cube:
1068 : SPIRV::Capability::SampledCubeArray);
1070 case SPIRV::Dim::DIM_Rect:
1072 : SPIRV::Capability::SampledRect);
1074 case SPIRV::Dim::DIM_Buffer:
1076 : SPIRV::Capability::SampledBuffer);
1078 case SPIRV::Dim::DIM_SubpassData:
1084 if (!
ST.isShader()) {
1085 if (
MI.getNumOperands() > 8 &&
1086 MI.getOperand(8).getImm() == SPIRV::AccessQualifier::ReadWrite)
1095 TypeDef->
getOpcode() == SPIRV::OpTypeFloat &&
1101#define ATOM_FLT_REQ_EXT_MSG(ExtName) \
1102 "The atomic float instruction requires the following SPIR-V " \
1103 "extension: SPV_EXT_shader_atomic_float" ExtName
1104static void AddAtomicVectorFloatRequirements(
const MachineInstr &
MI,
1108 MI.getMF()->getRegInfo().getVRegDef(
MI.getOperand(1).getReg());
1111 if (Rank != 2 && Rank != 4)
1113 "must be a 2-component or 4 component vector");
1118 if (EltTypeDef->
getOpcode() != SPIRV::OpTypeFloat ||
1121 "The element type for the result type of an atomic vector float "
1122 "instruction must be a 16-bit floating-point scalar");
1124 if (isBFloat16Type(EltTypeDef))
1126 "The element type for the result type of an atomic vector float "
1127 "instruction cannot be a bfloat16 scalar");
1128 if (!
ST.canUseExtension(SPIRV::Extension::SPV_NV_shader_atomic_fp16_vector))
1130 "The atomic float16 vector instruction requires the following SPIR-V "
1131 "extension: SPV_NV_shader_atomic_fp16_vector");
1133 Reqs.
addExtension(SPIRV::Extension::SPV_NV_shader_atomic_fp16_vector);
1134 Reqs.
addCapability(SPIRV::Capability::AtomicFloat16VectorNV);
1141 "Expect register operand in atomic float instruction");
1142 Register TypeReg =
MI.getOperand(1).getReg();
1145 if (TypeDef->
getOpcode() == SPIRV::OpTypeVector)
1146 return AddAtomicVectorFloatRequirements(
MI, Reqs, ST);
1148 if (TypeDef->
getOpcode() != SPIRV::OpTypeFloat)
1150 "floating-point type scalar");
1153 unsigned Op =
MI.getOpcode();
1154 if (
Op == SPIRV::OpAtomicFAddEXT) {
1155 if (!
ST.canUseExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float_add))
1157 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float_add);
1160 if (isBFloat16Type(TypeDef)) {
1161 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics))
1163 "The atomic bfloat16 instruction requires the following SPIR-V "
1164 "extension: SPV_INTEL_16bit_atomics",
1166 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics);
1167 Reqs.
addCapability(SPIRV::Capability::AtomicBFloat16AddINTEL);
1169 if (!
ST.canUseExtension(
1170 SPIRV::Extension::SPV_EXT_shader_atomic_float16_add))
1172 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float16_add);
1184 "Unexpected floating-point type width in atomic float instruction");
1187 if (!
ST.canUseExtension(
1188 SPIRV::Extension::SPV_EXT_shader_atomic_float_min_max))
1190 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float_min_max);
1193 if (isBFloat16Type(TypeDef)) {
1194 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics))
1196 "The atomic bfloat16 instruction requires the following SPIR-V "
1197 "extension: SPV_INTEL_16bit_atomics",
1199 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics);
1200 Reqs.
addCapability(SPIRV::Capability::AtomicBFloat16MinMaxINTEL);
1202 Reqs.
addCapability(SPIRV::Capability::AtomicFloat16MinMaxEXT);
1206 Reqs.
addCapability(SPIRV::Capability::AtomicFloat32MinMaxEXT);
1209 Reqs.
addCapability(SPIRV::Capability::AtomicFloat64MinMaxEXT);
1213 "Unexpected floating-point type width in atomic float instruction");
1219 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1223 return Dim == SPIRV::Dim::DIM_Buffer && Sampled == 1;
1227 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1231 return Dim == SPIRV::Dim::DIM_Buffer && Sampled == 2;
1235 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1239 return Dim != SPIRV::Dim::DIM_Buffer && Sampled == 1;
1243 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1247 return Dim == SPIRV::Dim::DIM_SubpassData && Sampled == 2;
1251 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1255 return Dim != SPIRV::Dim::DIM_Buffer && Sampled == 2;
1258bool isCombinedImageSampler(
MachineInstr *SampledImageInst) {
1259 if (SampledImageInst->
getOpcode() != SPIRV::OpTypeSampledImage)
1265 return isSampledImage(ImageInst);
1270 if (
MI.getOpcode() != SPIRV::OpDecorate)
1274 if (Dec == SPIRV::Decoration::NonUniformEXT)
1292 if (
StorageClass != SPIRV::StorageClass::StorageClass::UniformConstant &&
1293 StorageClass != SPIRV::StorageClass::StorageClass::Uniform &&
1294 StorageClass != SPIRV::StorageClass::StorageClass::StorageBuffer) {
1299 hasNonUniformDecoration(
Instr.getOperand(0).getReg(), MRI);
1301 auto FirstIndexReg =
Instr.getOperand(3).getReg();
1302 bool FirstIndexIsConstant =
1305 if (
StorageClass == SPIRV::StorageClass::StorageClass::StorageBuffer) {
1308 SPIRV::Capability::StorageBufferArrayNonUniformIndexingEXT);
1309 else if (!FirstIndexIsConstant)
1311 SPIRV::Capability::StorageBufferArrayDynamicIndexing);
1317 if (PointeeType->
getOpcode() != SPIRV::OpTypeImage &&
1318 PointeeType->
getOpcode() != SPIRV::OpTypeSampledImage &&
1319 PointeeType->
getOpcode() != SPIRV::OpTypeSampler) {
1323 if (isUniformTexelBuffer(PointeeType)) {
1326 SPIRV::Capability::UniformTexelBufferArrayNonUniformIndexingEXT);
1327 else if (!FirstIndexIsConstant)
1329 SPIRV::Capability::UniformTexelBufferArrayDynamicIndexingEXT);
1330 }
else if (isInputAttachment(PointeeType)) {
1333 SPIRV::Capability::InputAttachmentArrayNonUniformIndexingEXT);
1334 else if (!FirstIndexIsConstant)
1336 SPIRV::Capability::InputAttachmentArrayDynamicIndexingEXT);
1337 }
else if (isStorageTexelBuffer(PointeeType)) {
1340 SPIRV::Capability::StorageTexelBufferArrayNonUniformIndexingEXT);
1341 else if (!FirstIndexIsConstant)
1343 SPIRV::Capability::StorageTexelBufferArrayDynamicIndexingEXT);
1344 }
else if (isSampledImage(PointeeType) ||
1345 isCombinedImageSampler(PointeeType) ||
1346 PointeeType->
getOpcode() == SPIRV::OpTypeSampler) {
1349 SPIRV::Capability::SampledImageArrayNonUniformIndexingEXT);
1350 else if (!FirstIndexIsConstant)
1352 SPIRV::Capability::SampledImageArrayDynamicIndexing);
1353 }
else if (isStorageImage(PointeeType)) {
1356 SPIRV::Capability::StorageImageArrayNonUniformIndexingEXT);
1357 else if (!FirstIndexIsConstant)
1359 SPIRV::Capability::StorageImageArrayDynamicIndexing);
1363static bool isImageTypeWithUnknownFormat(
SPIRVTypeInst TypeInst) {
1364 if (TypeInst->
getOpcode() != SPIRV::OpTypeImage)
1373 if (
ST.canUseExtension(SPIRV::Extension::SPV_KHR_integer_dot_product))
1374 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_integer_dot_product);
1378 assert(
MI.getOperand(2).isReg() &&
"Unexpected operand in dot");
1382 assert(
Input->getOperand(1).isReg() &&
"Unexpected operand in dot input");
1386 if (TypeDef->
getOpcode() == SPIRV::OpTypeInt) {
1388 Reqs.
addCapability(SPIRV::Capability::DotProductInput4x8BitPacked);
1389 }
else if (TypeDef->
getOpcode() == SPIRV::OpTypeVector) {
1395 "Dot operand of 8-bit integer type requires 4 components");
1396 Reqs.
addCapability(SPIRV::Capability::DotProductInput4x8Bit);
1411 unsigned AddrSpace = ASOp.
getImm();
1412 if (AddrSpace != SPIRV::StorageClass::UniformConstant) {
1413 if (!
ST.canUseExtension(
1415 SPV_EXT_relaxed_printf_string_address_space)) {
1417 "required because printf uses a format string not "
1418 "in constant address space.",
1422 SPIRV::Extension::SPV_EXT_relaxed_printf_string_address_space);
1431 if (
MI.getNumOperands() <=
OpIdx)
1435 if (Mask & (1U <<
I))
1444 unsigned Op =
MI.getOpcode();
1446 case SPIRV::OpMemoryModel: {
1447 int64_t Addr =
MI.getOperand(0).getImm();
1450 int64_t Mem =
MI.getOperand(1).getImm();
1455 case SPIRV::OpEntryPoint: {
1456 int64_t
Exe =
MI.getOperand(0).getImm();
1461 case SPIRV::OpExecutionMode:
1462 case SPIRV::OpExecutionModeId: {
1463 int64_t
Exe =
MI.getOperand(1).getImm();
1468 case SPIRV::OpTypeMatrix:
1471 case SPIRV::OpTypeInt: {
1472 unsigned BitWidth =
MI.getOperand(1).getImm();
1480 ST.canUseExtension(SPIRV::Extension::SPV_INTEL_int4)) {
1484 if (!
ST.canUseExtension(
1485 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_integers))
1487 "OpTypeInt type with a width other than 8, 16, 32 or 64 bits "
1488 "requires the following SPIR-V extension: "
1489 "SPV_ALTERA_arbitrary_precision_integers");
1491 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_integers);
1492 Reqs.
addCapability(SPIRV::Capability::ArbitraryPrecisionIntegersALTERA);
1496 case SPIRV::OpDot: {
1499 if (isBFloat16Type(TypeDef))
1500 Reqs.
addCapability(SPIRV::Capability::BFloat16DotProductKHR);
1503 case SPIRV::OpTypeFloat: {
1504 unsigned BitWidth =
MI.getOperand(1).getImm();
1508 if (isBFloat16Type(&
MI)) {
1509 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_bfloat16))
1511 "following SPIR-V extension: SPV_KHR_bfloat16",
1521 case SPIRV::OpTypeVector: {
1522 unsigned NumComponents =
MI.getOperand(2).getImm();
1523 if (NumComponents == 8 || NumComponents == 16)
1529 if (ElemTypeDef->
getOpcode() == SPIRV::OpTypePointer &&
1530 ST.canUseExtension(SPIRV::Extension::SPV_INTEL_masked_gather_scatter)) {
1531 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_masked_gather_scatter);
1532 Reqs.
addCapability(SPIRV::Capability::MaskedGatherScatterINTEL);
1536 case SPIRV::OpTypePointer: {
1537 auto SC =
MI.getOperand(1).getImm();
1548 (TypeDef->
getOpcode() == SPIRV::OpTypeFloat) &&
1553 case SPIRV::OpExtInst: {
1554 if (
MI.getOperand(2).getImm() ==
1555 static_cast<int64_t
>(
1556 SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100)) {
1557 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_non_semantic_info);
1560 if (
MI.getOperand(3).getImm() ==
1561 static_cast<int64_t
>(SPIRV::OpenCLExtInst::printf)) {
1562 addPrintfRequirements(
MI, Reqs, ST);
1569 case SPIRV::OpAliasDomainDeclINTEL:
1570 case SPIRV::OpAliasScopeDeclINTEL:
1571 case SPIRV::OpAliasScopeListDeclINTEL: {
1572 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_memory_access_aliasing);
1573 Reqs.
addCapability(SPIRV::Capability::MemoryAccessAliasingINTEL);
1576 case SPIRV::OpBitReverse:
1577 case SPIRV::OpBitFieldInsert:
1578 case SPIRV::OpBitFieldSExtract:
1579 case SPIRV::OpBitFieldUExtract:
1580 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_bit_instructions)) {
1584 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_bit_instructions);
1587 case SPIRV::OpTypeRuntimeArray:
1590 case SPIRV::OpTypeOpaque:
1591 case SPIRV::OpTypeEvent:
1594 case SPIRV::OpTypePipe:
1595 case SPIRV::OpTypeReserveId:
1598 case SPIRV::OpTypeDeviceEvent:
1599 case SPIRV::OpTypeQueue:
1600 case SPIRV::OpBuildNDRange:
1603 case SPIRV::OpDecorate:
1604 case SPIRV::OpDecorateId:
1605 case SPIRV::OpDecorateString:
1606 addOpDecorateReqs(
MI, 1, Reqs, ST);
1608 case SPIRV::OpMemberDecorate:
1609 case SPIRV::OpMemberDecorateString:
1610 addOpDecorateReqs(
MI, 2, Reqs, ST);
1612 case SPIRV::OpInBoundsPtrAccessChain:
1615 case SPIRV::OpConstantSampler:
1618 case SPIRV::OpInBoundsAccessChain:
1619 case SPIRV::OpAccessChain:
1620 addOpAccessChainReqs(
MI, Reqs, ST);
1622 case SPIRV::OpTypeImage:
1623 addOpTypeImageReqs(
MI, Reqs, ST);
1625 case SPIRV::OpTypeSampler:
1626 if (!
ST.isShader()) {
1630 case SPIRV::OpTypeForwardPointer:
1634 case SPIRV::OpAtomicFlagTestAndSet:
1635 case SPIRV::OpAtomicLoad:
1636 case SPIRV::OpAtomicStore:
1637 case SPIRV::OpAtomicExchange:
1638 case SPIRV::OpAtomicCompareExchange:
1639 case SPIRV::OpAtomicIIncrement:
1640 case SPIRV::OpAtomicIDecrement:
1641 case SPIRV::OpAtomicIAdd:
1642 case SPIRV::OpAtomicISub:
1643 case SPIRV::OpAtomicUMin:
1644 case SPIRV::OpAtomicUMax:
1645 case SPIRV::OpAtomicSMin:
1646 case SPIRV::OpAtomicSMax:
1647 case SPIRV::OpAtomicAnd:
1648 case SPIRV::OpAtomicOr:
1649 case SPIRV::OpAtomicXor: {
1652 if (
Op == SPIRV::OpAtomicStore) {
1655 assert(InstrPtr &&
"Unexpected type instruction for OpAtomicStore");
1661 if (TypeDef->
getOpcode() == SPIRV::OpTypeInt) {
1666 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics))
1668 "16-bit integer atomic operations require the following SPIR-V "
1669 "extension: SPV_INTEL_16bit_atomics",
1671 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics);
1673 case SPIRV::OpAtomicLoad:
1674 case SPIRV::OpAtomicStore:
1675 case SPIRV::OpAtomicExchange:
1676 case SPIRV::OpAtomicCompareExchange:
1677 case SPIRV::OpAtomicCompareExchangeWeak:
1679 SPIRV::Capability::AtomicInt16CompareExchangeINTEL);
1686 }
else if (isBFloat16Type(TypeDef)) {
1687 if (
is_contained({SPIRV::OpAtomicLoad, SPIRV::OpAtomicStore,
1688 SPIRV::OpAtomicExchange},
1690 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics))
1692 "The atomic bfloat16 instruction requires the following SPIR-V "
1693 "extension: SPV_INTEL_16bit_atomics",
1695 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics);
1696 Reqs.
addCapability(SPIRV::Capability::AtomicBFloat16LoadStoreINTEL);
1701 case SPIRV::OpGroupNonUniformIAdd:
1702 case SPIRV::OpGroupNonUniformFAdd:
1703 case SPIRV::OpGroupNonUniformIMul:
1704 case SPIRV::OpGroupNonUniformFMul:
1705 case SPIRV::OpGroupNonUniformSMin:
1706 case SPIRV::OpGroupNonUniformUMin:
1707 case SPIRV::OpGroupNonUniformFMin:
1708 case SPIRV::OpGroupNonUniformSMax:
1709 case SPIRV::OpGroupNonUniformUMax:
1710 case SPIRV::OpGroupNonUniformFMax:
1711 case SPIRV::OpGroupNonUniformBitwiseAnd:
1712 case SPIRV::OpGroupNonUniformBitwiseOr:
1713 case SPIRV::OpGroupNonUniformBitwiseXor:
1714 case SPIRV::OpGroupNonUniformLogicalAnd:
1715 case SPIRV::OpGroupNonUniformLogicalOr:
1716 case SPIRV::OpGroupNonUniformLogicalXor: {
1718 int64_t GroupOp =
MI.getOperand(3).getImm();
1720 case SPIRV::GroupOperation::Reduce:
1721 case SPIRV::GroupOperation::InclusiveScan:
1722 case SPIRV::GroupOperation::ExclusiveScan:
1723 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformArithmetic);
1725 case SPIRV::GroupOperation::ClusteredReduce:
1726 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformClustered);
1728 case SPIRV::GroupOperation::PartitionedReduceNV:
1729 case SPIRV::GroupOperation::PartitionedInclusiveScanNV:
1730 case SPIRV::GroupOperation::PartitionedExclusiveScanNV:
1731 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformPartitionedNV);
1736 case SPIRV::OpGroupNonUniformQuadSwap:
1739 case SPIRV::OpImageQueryLod:
1742 case SPIRV::OpImageQuerySize:
1743 case SPIRV::OpImageQuerySizeLod:
1744 case SPIRV::OpImageQueryLevels:
1745 case SPIRV::OpImageQuerySamples:
1749 case SPIRV::OpImageQueryFormat: {
1750 Register ResultReg =
MI.getOperand(0).getReg();
1752 static const unsigned CompareOps[] = {
1753 SPIRV::OpIEqual, SPIRV::OpINotEqual,
1754 SPIRV::OpUGreaterThan, SPIRV::OpUGreaterThanEqual,
1755 SPIRV::OpULessThan, SPIRV::OpULessThanEqual,
1756 SPIRV::OpSGreaterThan, SPIRV::OpSGreaterThanEqual,
1757 SPIRV::OpSLessThan, SPIRV::OpSLessThanEqual};
1759 auto CheckAndAddExtension = [&](int64_t ImmVal) {
1760 if (ImmVal == 4323 || ImmVal == 4324) {
1761 if (
ST.canUseExtension(SPIRV::Extension::SPV_EXT_image_raw10_raw12))
1762 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_image_raw10_raw12);
1765 "SPV_EXT_image_raw10_raw12 extension");
1770 unsigned Opc = UseInst.getOpcode();
1772 if (
Opc == SPIRV::OpSwitch) {
1775 CheckAndAddExtension(
Op.getImm());
1777 for (
unsigned i = 1; i < UseInst.getNumOperands(); ++i) {
1780 if (ConstInst && ConstInst->
getOpcode() == SPIRV::OpConstantI) {
1783 CheckAndAddExtension(ImmVal);
1791 case SPIRV::OpGroupNonUniformShuffle:
1792 case SPIRV::OpGroupNonUniformShuffleXor:
1793 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformShuffle);
1795 case SPIRV::OpGroupNonUniformShuffleUp:
1796 case SPIRV::OpGroupNonUniformShuffleDown:
1797 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformShuffleRelative);
1799 case SPIRV::OpGroupAll:
1800 case SPIRV::OpGroupAny:
1801 case SPIRV::OpGroupBroadcast:
1802 case SPIRV::OpGroupIAdd:
1803 case SPIRV::OpGroupFAdd:
1804 case SPIRV::OpGroupFMin:
1805 case SPIRV::OpGroupUMin:
1806 case SPIRV::OpGroupSMin:
1807 case SPIRV::OpGroupFMax:
1808 case SPIRV::OpGroupUMax:
1809 case SPIRV::OpGroupSMax:
1812 case SPIRV::OpGroupNonUniformElect:
1815 case SPIRV::OpGroupNonUniformAll:
1816 case SPIRV::OpGroupNonUniformAny:
1817 case SPIRV::OpGroupNonUniformAllEqual:
1820 case SPIRV::OpGroupNonUniformBroadcast:
1821 case SPIRV::OpGroupNonUniformBroadcastFirst:
1822 case SPIRV::OpGroupNonUniformBallot:
1823 case SPIRV::OpGroupNonUniformInverseBallot:
1824 case SPIRV::OpGroupNonUniformBallotBitExtract:
1825 case SPIRV::OpGroupNonUniformBallotBitCount:
1826 case SPIRV::OpGroupNonUniformBallotFindLSB:
1827 case SPIRV::OpGroupNonUniformBallotFindMSB:
1828 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformBallot);
1830 case SPIRV::OpSubgroupShuffleINTEL:
1831 case SPIRV::OpSubgroupShuffleDownINTEL:
1832 case SPIRV::OpSubgroupShuffleUpINTEL:
1833 case SPIRV::OpSubgroupShuffleXorINTEL:
1834 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {
1835 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_subgroups);
1836 Reqs.
addCapability(SPIRV::Capability::SubgroupShuffleINTEL);
1839 case SPIRV::OpSubgroupBlockReadINTEL:
1840 case SPIRV::OpSubgroupBlockWriteINTEL:
1841 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {
1842 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_subgroups);
1843 Reqs.
addCapability(SPIRV::Capability::SubgroupBufferBlockIOINTEL);
1846 case SPIRV::OpSubgroupImageBlockReadINTEL:
1847 case SPIRV::OpSubgroupImageBlockWriteINTEL:
1848 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {
1849 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_subgroups);
1850 Reqs.
addCapability(SPIRV::Capability::SubgroupImageBlockIOINTEL);
1853 case SPIRV::OpSubgroupImageMediaBlockReadINTEL:
1854 case SPIRV::OpSubgroupImageMediaBlockWriteINTEL:
1855 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_media_block_io)) {
1856 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_media_block_io);
1857 Reqs.
addCapability(SPIRV::Capability::SubgroupImageMediaBlockIOINTEL);
1860 case SPIRV::OpAssumeTrueKHR:
1861 case SPIRV::OpExpectKHR:
1862 if (
ST.canUseExtension(SPIRV::Extension::SPV_KHR_expect_assume)) {
1863 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_expect_assume);
1867 case SPIRV::OpFmaKHR:
1868 if (
ST.canUseExtension(SPIRV::Extension::SPV_KHR_fma)) {
1873 case SPIRV::OpPtrCastToCrossWorkgroupINTEL:
1874 case SPIRV::OpCrossWorkgroupCastToPtrINTEL:
1875 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_usm_storage_classes)) {
1876 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_usm_storage_classes);
1877 Reqs.
addCapability(SPIRV::Capability::USMStorageClassesINTEL);
1880 case SPIRV::OpConstantFunctionPointerINTEL:
1881 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_function_pointers)) {
1882 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_function_pointers);
1883 Reqs.
addCapability(SPIRV::Capability::FunctionPointersINTEL);
1886 case SPIRV::OpGroupNonUniformRotateKHR:
1887 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_subgroup_rotate))
1889 "following SPIR-V extension: SPV_KHR_subgroup_rotate",
1891 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_subgroup_rotate);
1892 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformRotateKHR);
1895 case SPIRV::OpFixedCosALTERA:
1896 case SPIRV::OpFixedSinALTERA:
1897 case SPIRV::OpFixedCosPiALTERA:
1898 case SPIRV::OpFixedSinPiALTERA:
1899 case SPIRV::OpFixedExpALTERA:
1900 case SPIRV::OpFixedLogALTERA:
1901 case SPIRV::OpFixedRecipALTERA:
1902 case SPIRV::OpFixedSqrtALTERA:
1903 case SPIRV::OpFixedSinCosALTERA:
1904 case SPIRV::OpFixedSinCosPiALTERA:
1905 case SPIRV::OpFixedRsqrtALTERA:
1906 if (!
ST.canUseExtension(
1907 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_fixed_point))
1909 "following SPIR-V extension: "
1910 "SPV_ALTERA_arbitrary_precision_fixed_point",
1913 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_fixed_point);
1914 Reqs.
addCapability(SPIRV::Capability::ArbitraryPrecisionFixedPointALTERA);
1916 case SPIRV::OpGroupIMulKHR:
1917 case SPIRV::OpGroupFMulKHR:
1918 case SPIRV::OpGroupBitwiseAndKHR:
1919 case SPIRV::OpGroupBitwiseOrKHR:
1920 case SPIRV::OpGroupBitwiseXorKHR:
1921 case SPIRV::OpGroupLogicalAndKHR:
1922 case SPIRV::OpGroupLogicalOrKHR:
1923 case SPIRV::OpGroupLogicalXorKHR:
1924 if (
ST.canUseExtension(
1925 SPIRV::Extension::SPV_KHR_uniform_group_instructions)) {
1926 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_uniform_group_instructions);
1927 Reqs.
addCapability(SPIRV::Capability::GroupUniformArithmeticKHR);
1930 case SPIRV::OpReadClockKHR:
1931 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_shader_clock))
1933 "following SPIR-V extension: SPV_KHR_shader_clock",
1935 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_shader_clock);
1938 case SPIRV::OpFunctionPointerCallINTEL:
1939 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_function_pointers)) {
1940 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_function_pointers);
1941 Reqs.
addCapability(SPIRV::Capability::FunctionPointersINTEL);
1944 case SPIRV::OpAtomicFAddEXT:
1945 case SPIRV::OpAtomicFMinEXT:
1946 case SPIRV::OpAtomicFMaxEXT:
1947 AddAtomicFloatRequirements(
MI, Reqs, ST);
1949 case SPIRV::OpConvertBF16ToFINTEL:
1950 case SPIRV::OpConvertFToBF16INTEL:
1951 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bfloat16_conversion)) {
1952 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bfloat16_conversion);
1953 Reqs.
addCapability(SPIRV::Capability::BFloat16ConversionINTEL);
1956 case SPIRV::OpRoundFToTF32INTEL:
1957 if (
ST.canUseExtension(
1958 SPIRV::Extension::SPV_INTEL_tensor_float32_conversion)) {
1959 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_tensor_float32_conversion);
1960 Reqs.
addCapability(SPIRV::Capability::TensorFloat32RoundingINTEL);
1963 case SPIRV::OpVariableLengthArrayINTEL:
1964 case SPIRV::OpSaveMemoryINTEL:
1965 case SPIRV::OpRestoreMemoryINTEL:
1966 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_variable_length_array)) {
1967 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_variable_length_array);
1968 Reqs.
addCapability(SPIRV::Capability::VariableLengthArrayINTEL);
1971 case SPIRV::OpAsmTargetINTEL:
1972 case SPIRV::OpAsmINTEL:
1973 case SPIRV::OpAsmCallINTEL:
1974 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_inline_assembly)) {
1975 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_inline_assembly);
1979 case SPIRV::OpTypeCooperativeMatrixKHR: {
1980 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix))
1982 "OpTypeCooperativeMatrixKHR type requires the "
1983 "following SPIR-V extension: SPV_KHR_cooperative_matrix",
1985 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix);
1986 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixKHR);
1989 if (isBFloat16Type(TypeDef))
1990 Reqs.
addCapability(SPIRV::Capability::BFloat16CooperativeMatrixKHR);
1993 case SPIRV::OpArithmeticFenceEXT:
1994 if (!
ST.canUseExtension(SPIRV::Extension::SPV_EXT_arithmetic_fence))
1996 "following SPIR-V extension: SPV_EXT_arithmetic_fence",
1998 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_arithmetic_fence);
2001 case SPIRV::OpControlBarrierArriveINTEL:
2002 case SPIRV::OpControlBarrierWaitINTEL:
2003 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_split_barrier)) {
2004 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_split_barrier);
2008 case SPIRV::OpCooperativeMatrixMulAddKHR: {
2009 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix))
2011 "following SPIR-V extension: "
2012 "SPV_KHR_cooperative_matrix",
2014 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix);
2015 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixKHR);
2016 constexpr unsigned MulAddMaxSize = 6;
2017 if (
MI.getNumOperands() != MulAddMaxSize)
2019 const int64_t CoopOperands =
MI.getOperand(MulAddMaxSize - 1).getImm();
2021 SPIRV::CooperativeMatrixOperands::MatrixAAndBTF32ComponentsINTEL) {
2022 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
2024 "require the following SPIR-V extension: "
2025 "SPV_INTEL_joint_matrix",
2027 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2029 SPIRV::Capability::CooperativeMatrixTF32ComponentTypeINTEL);
2032 MatrixAAndBBFloat16ComponentsINTEL ||
2034 SPIRV::CooperativeMatrixOperands::MatrixCBFloat16ComponentsINTEL ||
2036 MatrixResultBFloat16ComponentsINTEL) {
2037 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
2039 "require the following SPIR-V extension: "
2040 "SPV_INTEL_joint_matrix",
2042 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2044 SPIRV::Capability::CooperativeMatrixBFloat16ComponentTypeINTEL);
2048 case SPIRV::OpCooperativeMatrixLoadKHR:
2049 case SPIRV::OpCooperativeMatrixStoreKHR:
2050 case SPIRV::OpCooperativeMatrixLoadCheckedINTEL:
2051 case SPIRV::OpCooperativeMatrixStoreCheckedINTEL:
2052 case SPIRV::OpCooperativeMatrixPrefetchINTEL: {
2053 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix))
2055 "following SPIR-V extension: "
2056 "SPV_KHR_cooperative_matrix",
2058 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix);
2059 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixKHR);
2063 std::unordered_map<unsigned, unsigned> LayoutToInstMap = {
2064 {SPIRV::OpCooperativeMatrixLoadKHR, 3},
2065 {SPIRV::OpCooperativeMatrixStoreKHR, 2},
2066 {SPIRV::OpCooperativeMatrixLoadCheckedINTEL, 5},
2067 {SPIRV::OpCooperativeMatrixStoreCheckedINTEL, 4},
2068 {SPIRV::OpCooperativeMatrixPrefetchINTEL, 4}};
2070 const unsigned LayoutNum = LayoutToInstMap[
Op];
2071 Register RegLayout =
MI.getOperand(LayoutNum).getReg();
2074 if (MILayout->
getOpcode() == SPIRV::OpConstantI) {
2077 static_cast<unsigned>(SPIRV::CooperativeMatrixLayout::PackedINTEL)) {
2078 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
2080 "extension: SPV_INTEL_joint_matrix",
2082 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2083 Reqs.
addCapability(SPIRV::Capability::PackedCooperativeMatrixINTEL);
2088 if (
Op == SPIRV::OpCooperativeMatrixLoadKHR ||
2089 Op == SPIRV::OpCooperativeMatrixStoreKHR)
2092 std::string InstName;
2094 case SPIRV::OpCooperativeMatrixPrefetchINTEL:
2095 InstName =
"OpCooperativeMatrixPrefetchINTEL";
2097 case SPIRV::OpCooperativeMatrixLoadCheckedINTEL:
2098 InstName =
"OpCooperativeMatrixLoadCheckedINTEL";
2100 case SPIRV::OpCooperativeMatrixStoreCheckedINTEL:
2101 InstName =
"OpCooperativeMatrixStoreCheckedINTEL";
2105 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix)) {
2106 const std::string ErrorMsg =
2107 InstName +
" instruction requires the "
2108 "following SPIR-V extension: SPV_INTEL_joint_matrix";
2111 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2112 if (
Op == SPIRV::OpCooperativeMatrixPrefetchINTEL) {
2113 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixPrefetchINTEL);
2117 SPIRV::Capability::CooperativeMatrixCheckedInstructionsINTEL);
2120 case SPIRV::OpCooperativeMatrixConstructCheckedINTEL:
2121 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
2123 "instructions require the following SPIR-V extension: "
2124 "SPV_INTEL_joint_matrix",
2126 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2128 SPIRV::Capability::CooperativeMatrixCheckedInstructionsINTEL);
2130 case SPIRV::OpReadPipeBlockingALTERA:
2131 case SPIRV::OpWritePipeBlockingALTERA:
2132 if (
ST.canUseExtension(SPIRV::Extension::SPV_ALTERA_blocking_pipes)) {
2133 Reqs.
addExtension(SPIRV::Extension::SPV_ALTERA_blocking_pipes);
2137 case SPIRV::OpCooperativeMatrixGetElementCoordINTEL:
2138 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
2140 "following SPIR-V extension: SPV_INTEL_joint_matrix",
2142 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2144 SPIRV::Capability::CooperativeMatrixInvocationInstructionsINTEL);
2146 case SPIRV::OpConvertHandleToImageINTEL:
2147 case SPIRV::OpConvertHandleToSamplerINTEL:
2148 case SPIRV::OpConvertHandleToSampledImageINTEL: {
2149 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bindless_images))
2151 "instructions require the following SPIR-V extension: "
2152 "SPV_INTEL_bindless_images",
2155 SPIRV::AddressingModel::AddressingModel AddrModel = MAI.
Addr;
2157 if (
Op == SPIRV::OpConvertHandleToImageINTEL &&
2158 TyDef->
getOpcode() != SPIRV::OpTypeImage) {
2160 "OpConvertHandleToImageINTEL",
2162 }
else if (
Op == SPIRV::OpConvertHandleToSamplerINTEL &&
2163 TyDef->
getOpcode() != SPIRV::OpTypeSampler) {
2165 "OpConvertHandleToSamplerINTEL",
2167 }
else if (
Op == SPIRV::OpConvertHandleToSampledImageINTEL &&
2168 TyDef->
getOpcode() != SPIRV::OpTypeSampledImage) {
2170 "OpConvertHandleToSampledImageINTEL",
2175 if (!(Bitwidth == 32 && AddrModel == SPIRV::AddressingModel::Physical32) &&
2176 !(Bitwidth == 64 && AddrModel == SPIRV::AddressingModel::Physical64)) {
2178 "Parameter value must be a 32-bit scalar in case of "
2179 "Physical32 addressing model or a 64-bit scalar in case of "
2180 "Physical64 addressing model",
2183 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bindless_images);
2187 case SPIRV::OpSubgroup2DBlockLoadINTEL:
2188 case SPIRV::OpSubgroup2DBlockLoadTransposeINTEL:
2189 case SPIRV::OpSubgroup2DBlockLoadTransformINTEL:
2190 case SPIRV::OpSubgroup2DBlockPrefetchINTEL:
2191 case SPIRV::OpSubgroup2DBlockStoreINTEL: {
2192 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_2d_block_io))
2194 "Prefetch/Store]INTEL instructions require the "
2195 "following SPIR-V extension: SPV_INTEL_2d_block_io",
2197 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_2d_block_io);
2198 Reqs.
addCapability(SPIRV::Capability::Subgroup2DBlockIOINTEL);
2200 if (
Op == SPIRV::OpSubgroup2DBlockLoadTransposeINTEL) {
2201 Reqs.
addCapability(SPIRV::Capability::Subgroup2DBlockTransposeINTEL);
2204 if (
Op == SPIRV::OpSubgroup2DBlockLoadTransformINTEL) {
2205 Reqs.
addCapability(SPIRV::Capability::Subgroup2DBlockTransformINTEL);
2210 case SPIRV::OpKill: {
2213 case SPIRV::OpDemoteToHelperInvocation:
2214 Reqs.
addCapability(SPIRV::Capability::DemoteToHelperInvocation);
2216 if (
ST.canUseExtension(
2217 SPIRV::Extension::SPV_EXT_demote_to_helper_invocation)) {
2220 SPIRV::Extension::SPV_EXT_demote_to_helper_invocation);
2225 case SPIRV::OpSUDot:
2226 case SPIRV::OpSDotAccSat:
2227 case SPIRV::OpUDotAccSat:
2228 case SPIRV::OpSUDotAccSat:
2229 AddDotProductRequirements(
MI, Reqs, ST);
2231 case SPIRV::OpImageSampleImplicitLod:
2233 addImageOperandReqs(
MI, Reqs, ST, 4);
2235 case SPIRV::OpImageSampleExplicitLod:
2236 addImageOperandReqs(
MI, Reqs, ST, 4);
2238 case SPIRV::OpImageSampleDrefImplicitLod:
2240 addImageOperandReqs(
MI, Reqs, ST, 5);
2242 case SPIRV::OpImageSampleDrefExplicitLod:
2244 addImageOperandReqs(
MI, Reqs, ST, 5);
2246 case SPIRV::OpImageFetch:
2248 addImageOperandReqs(
MI, Reqs, ST, 4);
2250 case SPIRV::OpImageDrefGather:
2251 case SPIRV::OpImageGather:
2253 addImageOperandReqs(
MI, Reqs, ST, 5);
2255 case SPIRV::OpImageRead: {
2256 Register ImageReg =
MI.getOperand(2).getReg();
2265 if (isImageTypeWithUnknownFormat(TypeDef) &&
ST.isShader())
2266 Reqs.
addCapability(SPIRV::Capability::StorageImageReadWithoutFormat);
2269 case SPIRV::OpImageWrite: {
2270 Register ImageReg =
MI.getOperand(0).getReg();
2279 if (isImageTypeWithUnknownFormat(TypeDef) &&
ST.isShader())
2280 Reqs.
addCapability(SPIRV::Capability::StorageImageWriteWithoutFormat);
2283 case SPIRV::OpTypeStructContinuedINTEL:
2284 case SPIRV::OpConstantCompositeContinuedINTEL:
2285 case SPIRV::OpSpecConstantCompositeContinuedINTEL:
2286 case SPIRV::OpCompositeConstructContinuedINTEL: {
2287 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_long_composites))
2289 "Continued instructions require the "
2290 "following SPIR-V extension: SPV_INTEL_long_composites",
2292 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_long_composites);
2296 case SPIRV::OpArbitraryFloatEQALTERA:
2297 case SPIRV::OpArbitraryFloatGEALTERA:
2298 case SPIRV::OpArbitraryFloatGTALTERA:
2299 case SPIRV::OpArbitraryFloatLEALTERA:
2300 case SPIRV::OpArbitraryFloatLTALTERA:
2301 case SPIRV::OpArbitraryFloatCbrtALTERA:
2302 case SPIRV::OpArbitraryFloatCosALTERA:
2303 case SPIRV::OpArbitraryFloatCosPiALTERA:
2304 case SPIRV::OpArbitraryFloatExp10ALTERA:
2305 case SPIRV::OpArbitraryFloatExp2ALTERA:
2306 case SPIRV::OpArbitraryFloatExpALTERA:
2307 case SPIRV::OpArbitraryFloatExpm1ALTERA:
2308 case SPIRV::OpArbitraryFloatHypotALTERA:
2309 case SPIRV::OpArbitraryFloatLog10ALTERA:
2310 case SPIRV::OpArbitraryFloatLog1pALTERA:
2311 case SPIRV::OpArbitraryFloatLog2ALTERA:
2312 case SPIRV::OpArbitraryFloatLogALTERA:
2313 case SPIRV::OpArbitraryFloatRecipALTERA:
2314 case SPIRV::OpArbitraryFloatSinCosALTERA:
2315 case SPIRV::OpArbitraryFloatSinCosPiALTERA:
2316 case SPIRV::OpArbitraryFloatSinALTERA:
2317 case SPIRV::OpArbitraryFloatSinPiALTERA:
2318 case SPIRV::OpArbitraryFloatSqrtALTERA:
2319 case SPIRV::OpArbitraryFloatACosALTERA:
2320 case SPIRV::OpArbitraryFloatACosPiALTERA:
2321 case SPIRV::OpArbitraryFloatAddALTERA:
2322 case SPIRV::OpArbitraryFloatASinALTERA:
2323 case SPIRV::OpArbitraryFloatASinPiALTERA:
2324 case SPIRV::OpArbitraryFloatATan2ALTERA:
2325 case SPIRV::OpArbitraryFloatATanALTERA:
2326 case SPIRV::OpArbitraryFloatATanPiALTERA:
2327 case SPIRV::OpArbitraryFloatCastFromIntALTERA:
2328 case SPIRV::OpArbitraryFloatCastALTERA:
2329 case SPIRV::OpArbitraryFloatCastToIntALTERA:
2330 case SPIRV::OpArbitraryFloatDivALTERA:
2331 case SPIRV::OpArbitraryFloatMulALTERA:
2332 case SPIRV::OpArbitraryFloatPowALTERA:
2333 case SPIRV::OpArbitraryFloatPowNALTERA:
2334 case SPIRV::OpArbitraryFloatPowRALTERA:
2335 case SPIRV::OpArbitraryFloatRSqrtALTERA:
2336 case SPIRV::OpArbitraryFloatSubALTERA: {
2337 if (!
ST.canUseExtension(
2338 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_floating_point))
2340 "Floating point instructions can't be translated correctly without "
2341 "enabled SPV_ALTERA_arbitrary_precision_floating_point extension!",
2344 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_floating_point);
2346 SPIRV::Capability::ArbitraryPrecisionFloatingPointALTERA);
2349 case SPIRV::OpSubgroupMatrixMultiplyAccumulateINTEL: {
2350 if (!
ST.canUseExtension(
2351 SPIRV::Extension::SPV_INTEL_subgroup_matrix_multiply_accumulate))
2353 "OpSubgroupMatrixMultiplyAccumulateINTEL instruction requires the "
2355 "extension: SPV_INTEL_subgroup_matrix_multiply_accumulate",
2358 SPIRV::Extension::SPV_INTEL_subgroup_matrix_multiply_accumulate);
2360 SPIRV::Capability::SubgroupMatrixMultiplyAccumulateINTEL);
2363 case SPIRV::OpBitwiseFunctionINTEL: {
2364 if (!
ST.canUseExtension(
2365 SPIRV::Extension::SPV_INTEL_ternary_bitwise_function))
2367 "OpBitwiseFunctionINTEL instruction requires the following SPIR-V "
2368 "extension: SPV_INTEL_ternary_bitwise_function",
2370 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_ternary_bitwise_function);
2371 Reqs.
addCapability(SPIRV::Capability::TernaryBitwiseFunctionINTEL);
2374 case SPIRV::OpCopyMemorySized: {
2379 case SPIRV::OpPredicatedLoadINTEL:
2380 case SPIRV::OpPredicatedStoreINTEL: {
2381 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_predicated_io))
2383 "OpPredicated[Load/Store]INTEL instructions require "
2384 "the following SPIR-V extension: SPV_INTEL_predicated_io",
2386 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_predicated_io);
2390 case SPIRV::OpFAddS:
2391 case SPIRV::OpFSubS:
2392 case SPIRV::OpFMulS:
2393 case SPIRV::OpFDivS:
2394 case SPIRV::OpFRemS:
2396 case SPIRV::OpFNegate:
2397 case SPIRV::OpFAddV:
2398 case SPIRV::OpFSubV:
2399 case SPIRV::OpFMulV:
2400 case SPIRV::OpFDivV:
2401 case SPIRV::OpFRemV:
2402 case SPIRV::OpFNegateV: {
2405 if (TypeDef->
getOpcode() == SPIRV::OpTypeVector)
2407 if (isBFloat16Type(TypeDef)) {
2408 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic))
2410 "Arithmetic instructions with bfloat16 arguments require the "
2411 "following SPIR-V extension: SPV_INTEL_bfloat16_arithmetic",
2413 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic);
2414 Reqs.
addCapability(SPIRV::Capability::BFloat16ArithmeticINTEL);
2418 case SPIRV::OpOrdered:
2419 case SPIRV::OpUnordered:
2420 case SPIRV::OpFOrdEqual:
2421 case SPIRV::OpFOrdNotEqual:
2422 case SPIRV::OpFOrdLessThan:
2423 case SPIRV::OpFOrdLessThanEqual:
2424 case SPIRV::OpFOrdGreaterThan:
2425 case SPIRV::OpFOrdGreaterThanEqual:
2426 case SPIRV::OpFUnordEqual:
2427 case SPIRV::OpFUnordNotEqual:
2428 case SPIRV::OpFUnordLessThan:
2429 case SPIRV::OpFUnordLessThanEqual:
2430 case SPIRV::OpFUnordGreaterThan:
2431 case SPIRV::OpFUnordGreaterThanEqual: {
2435 if (TypeDef->
getOpcode() == SPIRV::OpTypeVector)
2437 if (isBFloat16Type(TypeDef)) {
2438 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic))
2440 "Relational instructions with bfloat16 arguments require the "
2441 "following SPIR-V extension: SPV_INTEL_bfloat16_arithmetic",
2443 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic);
2444 Reqs.
addCapability(SPIRV::Capability::BFloat16ArithmeticINTEL);
2448 case SPIRV::OpDPdxCoarse:
2449 case SPIRV::OpDPdyCoarse:
2450 case SPIRV::OpDPdxFine:
2451 case SPIRV::OpDPdyFine: {
2455 case SPIRV::OpLoopControlINTEL: {
2456 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_unstructured_loop_controls);
2457 Reqs.
addCapability(SPIRV::Capability::UnstructuredLoopControlsINTEL);
2469 SPIRV::Capability::Shader);
2481 addInstrRequirements(
MI, MAI, ST);
2484 auto Node = M.getNamedMetadata(
"spirv.ExecutionMode");
2486 bool RequireFloatControls =
false, RequireIntelFloatControls2 =
false,
2487 RequireKHRFloatControls2 =
false,
2489 bool HasIntelFloatControls2 =
2490 ST.canUseExtension(SPIRV::Extension::SPV_INTEL_float_controls2);
2491 bool HasKHRFloatControls2 =
2492 ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2);
2493 for (
unsigned i = 0; i <
Node->getNumOperands(); i++) {
2499 auto EM =
Const->getZExtValue();
2503 case SPIRV::ExecutionMode::DenormPreserve:
2504 case SPIRV::ExecutionMode::DenormFlushToZero:
2505 case SPIRV::ExecutionMode::RoundingModeRTE:
2506 case SPIRV::ExecutionMode::RoundingModeRTZ:
2507 RequireFloatControls = VerLower14;
2509 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2511 case SPIRV::ExecutionMode::RoundingModeRTPINTEL:
2512 case SPIRV::ExecutionMode::RoundingModeRTNINTEL:
2513 case SPIRV::ExecutionMode::FloatingPointModeALTINTEL:
2514 case SPIRV::ExecutionMode::FloatingPointModeIEEEINTEL:
2515 if (HasIntelFloatControls2) {
2516 RequireIntelFloatControls2 =
true;
2518 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2521 case SPIRV::ExecutionMode::FPFastMathDefault: {
2522 if (HasKHRFloatControls2) {
2523 RequireKHRFloatControls2 =
true;
2525 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2529 case SPIRV::ExecutionMode::ContractionOff:
2530 case SPIRV::ExecutionMode::SignedZeroInfNanPreserve:
2531 if (HasKHRFloatControls2) {
2532 RequireKHRFloatControls2 =
true;
2534 SPIRV::OperandCategory::ExecutionModeOperand,
2535 SPIRV::ExecutionMode::FPFastMathDefault, ST);
2538 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2543 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2548 if (RequireFloatControls &&
2549 ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls))
2551 if (RequireIntelFloatControls2)
2553 if (RequireKHRFloatControls2)
2557 if (
F.isDeclaration())
2559 if (
F.getMetadata(
"reqd_work_group_size"))
2561 SPIRV::OperandCategory::ExecutionModeOperand,
2562 SPIRV::ExecutionMode::LocalSize, ST);
2563 if (
F.getFnAttribute(
"hlsl.numthreads").isValid()) {
2565 SPIRV::OperandCategory::ExecutionModeOperand,
2566 SPIRV::ExecutionMode::LocalSize, ST);
2568 if (
F.getFnAttribute(
"enable-maximal-reconvergence").getValueAsBool()) {
2571 if (
F.getMetadata(
"work_group_size_hint"))
2573 SPIRV::OperandCategory::ExecutionModeOperand,
2574 SPIRV::ExecutionMode::LocalSizeHint, ST);
2575 if (
F.getMetadata(
"intel_reqd_sub_group_size"))
2577 SPIRV::OperandCategory::ExecutionModeOperand,
2578 SPIRV::ExecutionMode::SubgroupSize, ST);
2579 if (
F.getMetadata(
"max_work_group_size"))
2581 SPIRV::OperandCategory::ExecutionModeOperand,
2582 SPIRV::ExecutionMode::MaxWorkgroupSizeINTEL, ST);
2583 if (
F.getMetadata(
"vec_type_hint"))
2585 SPIRV::OperandCategory::ExecutionModeOperand,
2586 SPIRV::ExecutionMode::VecTypeHint, ST);
2588 if (
F.hasOptNone()) {
2589 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_optnone)) {
2592 }
else if (
ST.canUseExtension(SPIRV::Extension::SPV_EXT_optnone)) {
2602 unsigned Flags = SPIRV::FPFastMathMode::None;
2603 bool CanUseKHRFloatControls2 =
2604 ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2);
2606 Flags |= SPIRV::FPFastMathMode::NotNaN;
2608 Flags |= SPIRV::FPFastMathMode::NotInf;
2610 Flags |= SPIRV::FPFastMathMode::NSZ;
2612 Flags |= SPIRV::FPFastMathMode::AllowRecip;
2614 Flags |= SPIRV::FPFastMathMode::AllowContract;
2616 if (CanUseKHRFloatControls2)
2624 Flags |= SPIRV::FPFastMathMode::NotNaN | SPIRV::FPFastMathMode::NotInf |
2625 SPIRV::FPFastMathMode::NSZ | SPIRV::FPFastMathMode::AllowRecip |
2626 SPIRV::FPFastMathMode::AllowTransform |
2627 SPIRV::FPFastMathMode::AllowReassoc |
2628 SPIRV::FPFastMathMode::AllowContract;
2630 Flags |= SPIRV::FPFastMathMode::Fast;
2633 if (CanUseKHRFloatControls2) {
2635 assert(!(Flags & SPIRV::FPFastMathMode::Fast) &&
2636 "SPIRV::FPFastMathMode::Fast is deprecated and should not be used "
2641 assert((!(Flags & SPIRV::FPFastMathMode::AllowTransform) ||
2642 ((Flags & SPIRV::FPFastMathMode::AllowReassoc &&
2643 Flags & SPIRV::FPFastMathMode::AllowContract))) &&
2644 "SPIRV::FPFastMathMode::AllowTransform requires AllowReassoc and "
2645 "AllowContract flags to be enabled as well.");
2656 return ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2);
2659static void handleMIFlagDecoration(
2664 getSymbolicOperandRequirements(SPIRV::OperandCategory::DecorationOperand,
2665 SPIRV::Decoration::NoSignedWrap, ST, Reqs)
2668 SPIRV::Decoration::NoSignedWrap, {});
2671 getSymbolicOperandRequirements(SPIRV::OperandCategory::DecorationOperand,
2672 SPIRV::Decoration::NoUnsignedWrap, ST,
2676 SPIRV::Decoration::NoUnsignedWrap, {});
2681 TII.canUseFastMathFlags(
2682 I,
ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2)) ||
2683 (
ST.isKernel() &&
I.getOpcode() == SPIRV::OpExtInst);
2687 unsigned FMFlags = getFastMathFlags(
I, ST);
2688 if (FMFlags == SPIRV::FPFastMathMode::None) {
2691 if (FPFastMathDefaultInfoVec.
empty())
2707 assert(
I.getNumOperands() >= 3 &&
"Expected at least 3 operands");
2708 Register ResReg =
I.getOpcode() == SPIRV::OpExtInst
2709 ?
I.getOperand(1).getReg()
2710 :
I.getOperand(2).getReg();
2718 if (Ty == Elem.Ty) {
2719 FMFlags = Elem.FastMathFlags;
2720 Emit = Elem.ContractionOff || Elem.SignedZeroInfNanPreserve ||
2721 Elem.FPFastMathDefault;
2726 if (FMFlags == SPIRV::FPFastMathMode::None && !Emit)
2729 if (isFastMathModeAvailable(ST)) {
2730 Register DstReg =
I.getOperand(0).getReg();
2746 for (
auto &
MBB : *MF)
2747 for (
auto &
MI :
MBB)
2748 handleMIFlagDecoration(
MI, ST,
TII, MAI.
Reqs, GR,
2765 for (
auto &
MBB : *MF) {
2766 if (!
MBB.hasName() ||
MBB.empty())
2785 for (
auto &
MBB : *MF) {
2787 MI.setDesc(
TII.get(SPIRV::OpPhi));
2790 MI.insert(
MI.operands_begin() + 1,
2791 {MachineOperand::CreateReg(ResTypeReg, false)});
2810 SPIRV::FPFastMathMode::None);
2812 SPIRV::FPFastMathMode::None);
2814 SPIRV::FPFastMathMode::None);
2821 size_t BitWidth = Ty->getScalarSizeInBits();
2825 assert(Index >= 0 && Index < 3 &&
2826 "Expected FPFastMathDefaultInfo for half, float, or double");
2827 assert(FPFastMathDefaultInfoVec.
size() == 3 &&
2828 "Expected FPFastMathDefaultInfoVec to have exactly 3 elements");
2829 return FPFastMathDefaultInfoVec[Index];
2832static void collectFPFastMathDefaults(
const Module &M,
2835 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2))
2844 auto Node = M.getNamedMetadata(
"spirv.ExecutionMode");
2848 for (
unsigned i = 0; i <
Node->getNumOperands(); i++) {
2857 if (EM == SPIRV::ExecutionMode::FPFastMathDefault) {
2859 "Expected 4 operands for FPFastMathDefault");
2870 Info.FastMathFlags = Flags;
2871 Info.FPFastMathDefault =
true;
2872 }
else if (EM == SPIRV::ExecutionMode::ContractionOff) {
2874 "Expected no operands for ContractionOff");
2881 Info.ContractionOff =
true;
2883 }
else if (EM == SPIRV::ExecutionMode::SignedZeroInfNanPreserve) {
2885 "Expected 1 operand for SignedZeroInfNanPreserve");
2886 unsigned TargetWidth =
2895 assert(Index >= 0 && Index < 3 &&
2896 "Expected FPFastMathDefaultInfo for half, float, or double");
2897 assert(FPFastMathDefaultInfoVec.
size() == 3 &&
2898 "Expected FPFastMathDefaultInfoVec to have exactly 3 elements");
2899 FPFastMathDefaultInfoVec[Index].SignedZeroInfNanPreserve =
true;
2910 SPIRVTargetMachine &TM =
2914 TII = ST->getInstrInfo();
2920 patchPhis(M, GR, *TII, MMI);
2922 addMBBNames(M, *TII, MMI, *ST,
MAI);
2923 collectFPFastMathDefaults(M,
MAI, *ST);
2924 addDecorations(M, *TII, MMI, *ST,
MAI, GR);
2926 collectReqs(M,
MAI, MMI, *ST);
2930 collectReqs(M,
MAI, MMI, *ST);
2931 collectDeclarations(M);
2934 numberRegistersGlobally(M);
2937 processOtherInstrs(M);
2941 MAI.Reqs.addCapability(SPIRV::Capability::Linkage);
2944 GR->setBound(
MAI.MaxID);
MachineInstrBuilder & UseMI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
ReachingDefInfo InstSet & ToRemove
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
MachineInstr unsigned OpIdx
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
static SPIRV::FPFastMathDefaultInfoVector & getOrCreateFPFastMathDefaultInfoVec(const Module &M, DenseMap< Function *, SPIRV::FPFastMathDefaultInfoVector > &FPFastMathDefaultInfoMap, Function *F)
static SPIRV::FPFastMathDefaultInfo & getFPFastMathDefaultInfo(SPIRV::FPFastMathDefaultInfoVector &FPFastMathDefaultInfoVec, const Type *Ty)
#define ATOM_FLT_REQ_EXT_MSG(ExtName)
static cl::opt< bool > SPVDumpDeps("spv-dump-deps", cl::desc("Dump MIR with SPIR-V dependencies info"), cl::Optional, cl::init(false))
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")))
#define SPIRV_BACKEND_SERVICE_FUN_NAME
Target-Independent Code Generator Pass Configuration Options pass.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
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.
Attribute getFnAttribute(Attribute::AttrKind Kind) const
Return the attribute for the given attribute kind.
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
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.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
const MachineFunctionProperties & getProperties() const
Get the function properties.
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
This class contains meta information specific to a module.
LLVM_ABI MachineFunction * getMachineFunction(const Function &F) const
Returns the MachineFunction associated to IR function F if there is one, otherwise nullptr.
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 MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
LLVM_ABI void setRegClass(Register Reg, const TargetRegisterClass *RC)
setRegClass - Set the register class of the specified virtual register.
LLVM_ABI Register createGenericVirtualRegister(LLT Ty, StringRef Name="")
Create and return a new generic virtual register with low-level type Ty.
iterator_range< reg_instr_iterator > reg_instructions(Register Reg) const
iterator_range< use_instr_iterator > use_instructions(Register Reg) const
LLVM_ABI 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.
virtual void print(raw_ostream &OS, const Module *M) const
print - Print out the internal state of the pass.
AnalysisType & getAnalysis() const
getAnalysis<AnalysisType>() - This function is used by subclasses to get to the analysis information ...
Wrapper class representing virtual and physical registers.
constexpr bool isValid() const
unsigned getScalarOrVectorBitWidth(SPIRVTypeInst Type) const
const Type * getTypeForSPIRVType(SPIRVTypeInst Ty) const
Register getSPIRVTypeID(SPIRVTypeInst SpirvType) const
SPIRVTypeInst getSPIRVTypeForVReg(Register VReg, const MachineFunction *MF=nullptr) const
bool isConstantInstr(const MachineInstr &MI) const
const SPIRVInstrInfo * getInstrInfo() const override
SPIRVGlobalRegistry * getSPIRVGlobalRegistry() const
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)
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.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
@ C
The default llvm calling convention, compatible with C.
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.
NodeAddr< InstrNode * > Instr
This is an optimization pass for GlobalISel generic memory operations.
void buildOpName(Register Target, const StringRef &Name, MachineIRBuilder &MIRBuilder)
FunctionAddr VTableAddr Value
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
VersionTuple getSymbolicOperandMaxVersion(SPIRV::OperandCategory::OperandCategory Category, uint32_t Value)
void buildOpDecorate(Register Reg, MachineIRBuilder &MIRBuilder, SPIRV::Decoration::Decoration Dec, const std::vector< uint32_t > &DecArgs, StringRef StrImm)
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)
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
hash_code hash_combine(const Ts &...args)
Combine values into a single hash_code.
std::map< SmallVector< size_t >, unsigned > InstrGRegsMap
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
SmallSet< SPIRV::Capability::Capability, 4 > S
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
void setRegisterAlias(const MachineFunction *MF, Register Reg, MCRegister AliasReg)
DenseMap< const Function *, SPIRV::FPFastMathDefaultInfoVector > FPFastMathDefaultInfoMap
void addCapabilities(const CapabilityList &ToAdd)
bool isCapabilityAvailable(Capability::Capability Cap) const
void checkSatisfiable(const SPIRVSubtarget &ST) const
void getAndAddRequirements(SPIRV::OperandCategory::OperandCategory Category, uint32_t i, const SPIRVSubtarget &ST)
void addExtension(Extension::Extension ToAdd)
void initAvailableCapabilities(const SPIRVSubtarget &ST)
void removeCapabilityIf(const Capability::Capability ToRemove, const Capability::Capability IfPresent)
void addCapability(Capability::Capability ToAdd)
void addAvailableCaps(const CapabilityList &ToAdd)
void addRequirements(const Requirements &Req)
const std::optional< Capability::Capability > Cap
const VersionTuple MinVer
const VersionTuple MaxVer