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);
366void SPIRVModuleAnalysis::visitFunPtrUse(
369 std::map<const Value *, unsigned> &GlobalToGReg,
371 const MachineOperand *OpFunDef = GR->getFunctionDefinitionByUse(FunPtrOp);
374 const MachineInstr *OpDefMI = OpFunDef->
getParent();
377 const MachineRegisterInfo &FunDefMRI = FunDefMF->
getRegInfo();
379 visitDecl(FunDefMRI, SignatureToGReg, GlobalToGReg, FunDefMF, *OpDefMI);
381 }
while (OpDefMI && (OpDefMI->
getOpcode() == SPIRV::OpFunction ||
382 OpDefMI->
getOpcode() == SPIRV::OpFunctionParameter));
384 MCRegister GlobalFunDefReg =
385 MAI.getRegisterAlias(FunDefMF, OpFunDef->
getReg());
387 "Function definition must refer to a global register");
388 MAI.setRegisterAlias(MF, OpReg, GlobalFunDefReg);
393void SPIRVModuleAnalysis::visitDecl(
395 std::map<const Value *, unsigned> &GlobalToGReg,
const MachineFunction *MF,
397 unsigned Opcode =
MI.getOpcode();
400 for (
const MachineOperand &MO :
MI.operands()) {
405 if (Opcode == SPIRV::OpConstantFunctionPointerINTEL &&
407 visitFunPtrUse(OpReg, &
MI.getOperand(2), SignatureToGReg, GlobalToGReg,
412 if (
MAI.hasRegisterAlias(MF, MO.
getReg()))
416 if (isDeclSection(MRI, *OpDefMI))
417 visitDecl(MRI, SignatureToGReg, GlobalToGReg, MF, *OpDefMI);
423 dbgs() <<
"Unexpectedly, no unique definition for the operand ";
425 dbgs() <<
"\nInstruction: ";
430 "No unique definition is found for the virtual register");
434 bool IsFunDef =
false;
435 if (TII->isSpecConstantInstr(
MI)) {
436 GReg =
MAI.getNextIDRegister();
438 }
else if (Opcode == SPIRV::OpFunction ||
439 Opcode == SPIRV::OpFunctionParameter) {
440 GReg = handleFunctionOrParameter(MF,
MI, GlobalToGReg, IsFunDef);
441 }
else if (Opcode == SPIRV::OpTypeStruct ||
442 Opcode == SPIRV::OpConstantComposite) {
443 GReg = handleTypeDeclOrConstant(
MI, SignatureToGReg);
444 const MachineInstr *NextInstr =
MI.getNextNode();
446 ((Opcode == SPIRV::OpTypeStruct &&
447 NextInstr->
getOpcode() == SPIRV::OpTypeStructContinuedINTEL) ||
448 (Opcode == SPIRV::OpConstantComposite &&
450 SPIRV::OpConstantCompositeContinuedINTEL))) {
451 MCRegister Tmp = handleTypeDeclOrConstant(*NextInstr, SignatureToGReg);
453 MAI.setSkipEmission(NextInstr);
456 }
else if (TII->isTypeDeclInstr(
MI) || TII->isConstantInstr(
MI) ||
457 TII->isInlineAsmDefInstr(
MI)) {
458 GReg = handleTypeDeclOrConstant(
MI, SignatureToGReg);
459 }
else if (Opcode == SPIRV::OpVariable) {
460 GReg = handleVariable(MF,
MI, GlobalToGReg);
463 dbgs() <<
"\nInstruction: ";
469 MAI.setRegisterAlias(MF,
MI.getOperand(0).getReg(), GReg);
471 MAI.setSkipEmission(&
MI);
474MCRegister SPIRVModuleAnalysis::handleFunctionOrParameter(
476 std::map<const Value *, unsigned> &GlobalToGReg,
bool &IsFunDef) {
477 const Value *GObj = GR->getGlobalObject(MF,
MI.getOperand(0).getReg());
478 assert(GObj &&
"Unregistered global definition");
482 assert(
F &&
"Expected a reference to a function or an argument");
483 IsFunDef = !
F->isDeclaration();
484 auto [It,
Inserted] = GlobalToGReg.try_emplace(GObj);
487 MCRegister GReg =
MAI.getNextIDRegister();
495SPIRVModuleAnalysis::handleTypeDeclOrConstant(
const MachineInstr &
MI,
498 auto [It,
Inserted] = SignatureToGReg.try_emplace(MISign);
501 MCRegister GReg =
MAI.getNextIDRegister();
507MCRegister SPIRVModuleAnalysis::handleVariable(
509 std::map<const Value *, unsigned> &GlobalToGReg) {
510 MAI.GlobalVarList.push_back(&
MI);
511 const Value *GObj = GR->getGlobalObject(MF,
MI.getOperand(0).getReg());
512 assert(GObj &&
"Unregistered global definition");
513 auto [It,
Inserted] = GlobalToGReg.try_emplace(GObj);
516 MCRegister GReg =
MAI.getNextIDRegister();
520 MAI.GlobalObjMap[GV] = GReg;
524void SPIRVModuleAnalysis::collectDeclarations(
const Module &M) {
526 std::map<const Value *, unsigned> GlobalToGReg;
527 for (
const Function &
F : M) {
528 MachineFunction *MF = MMI->getMachineFunction(
F);
531 const MachineRegisterInfo &MRI = MF->
getRegInfo();
532 unsigned PastHeader = 0;
533 for (MachineBasicBlock &
MBB : *MF) {
534 for (MachineInstr &
MI :
MBB) {
535 if (
MI.getNumOperands() == 0)
537 unsigned Opcode =
MI.getOpcode();
538 if (Opcode == SPIRV::OpFunction) {
539 if (PastHeader == 0) {
543 }
else if (Opcode == SPIRV::OpFunctionParameter) {
546 }
else if (PastHeader > 0) {
550 const MachineOperand &DefMO =
MI.getOperand(0);
552 case SPIRV::OpExtension:
553 MAI.Reqs.addExtension(SPIRV::Extension::Extension(DefMO.
getImm()));
554 MAI.setSkipEmission(&
MI);
556 case SPIRV::OpCapability:
557 MAI.Reqs.addCapability(SPIRV::Capability::Capability(DefMO.
getImm()));
558 MAI.setSkipEmission(&
MI);
563 if (DefMO.
isReg() && isDeclSection(MRI,
MI) &&
564 !
MAI.hasRegisterAlias(MF, DefMO.
getReg()))
565 visitDecl(MRI, SignatureToGReg, GlobalToGReg, MF,
MI);
578 if (
MI.getOpcode() == SPIRV::OpDecorate) {
580 auto Dec =
MI.getOperand(1).getImm();
581 if (Dec == SPIRV::Decoration::LinkageAttributes) {
582 auto Lnk =
MI.getOperand(
MI.getNumOperands() - 1).getImm();
583 if (Lnk == SPIRV::LinkageType::Import) {
588 MAI.GlobalObjMap[ImportedFunc] =
589 MAI.getRegisterAlias(
MI.getMF(), Target);
592 }
else if (
MI.getOpcode() == SPIRV::OpFunction) {
595 MCRegister GlobalReg =
MAI.getRegisterAlias(
MI.getMF(),
Reg);
597 MAI.GlobalObjMap[
F] = GlobalReg;
609 auto FoundMI = IS.insert(std::move(MISign));
610 if (!FoundMI.second) {
611 if (
MI.getOpcode() == SPIRV::OpDecorate) {
613 "Decoration instructions must have at least 2 operands");
615 "Only OpDecorate instructions can be duplicates");
620 if (
MI.getOperand(1).getImm() != SPIRV::Decoration::FPFastMathMode)
625 if (instrToSignature(*OrigMI, MAI,
true) == MISign) {
626 assert(OrigMI->getNumOperands() ==
MI.getNumOperands() &&
627 "Original instruction must have the same number of operands");
629 OrigMI->getNumOperands() == 3 &&
630 "FPFastMathMode decoration must have 3 operands for OpDecorate");
631 unsigned OrigFlags = OrigMI->getOperand(2).getImm();
632 unsigned NewFlags =
MI.getOperand(2).getImm();
633 if (OrigFlags == NewFlags)
637 unsigned FinalFlags = OrigFlags | NewFlags;
639 <<
"Warning: Conflicting FPFastMathMode decoration flags "
641 << *OrigMI <<
"Original flags: " << OrigFlags
642 <<
", new flags: " << NewFlags
643 <<
". They will be merged on a best effort basis, but not "
644 "validated. Final flags: "
645 << FinalFlags <<
"\n";
652 assert(
false &&
"No original instruction found for the duplicate "
653 "OpDecorate, but we found one in IS.");
666void SPIRVModuleAnalysis::processOtherInstrs(
const Module &M) {
668 for (
const Function &
F : M) {
669 if (
F.isDeclaration())
671 MachineFunction *MF = MMI->getMachineFunction(
F);
674 for (MachineBasicBlock &
MBB : *MF)
675 for (MachineInstr &
MI :
MBB) {
676 if (
MAI.getSkipEmission(&
MI))
678 const unsigned OpCode =
MI.getOpcode();
679 if (OpCode == SPIRV::OpString) {
681 }
else if (OpCode == SPIRV::OpExtInst &&
MI.getOperand(2).isImm() &&
682 MI.getOperand(2).getImm() ==
683 SPIRV::InstructionSet::
684 NonSemantic_Shader_DebugInfo_100) {
691 MachineOperand Ins =
MI.getOperand(3);
692 namespace NS = SPIRV::NonSemanticExtInst;
693 static constexpr int64_t GlobalNonSemanticDITy[] = {
694 NS::DebugSource, NS::DebugCompilationUnit, NS::DebugInfoNone,
695 NS::DebugTypeBasic, NS::DebugTypePointer};
696 bool IsGlobalDI =
false;
697 for (
unsigned Idx = 0; Idx < std::size(GlobalNonSemanticDITy); ++Idx)
698 IsGlobalDI |= Ins.
getImm() == GlobalNonSemanticDITy[Idx];
701 }
else if (OpCode == SPIRV::OpName || OpCode == SPIRV::OpMemberName) {
703 }
else if (OpCode == SPIRV::OpEntryPoint) {
705 }
else if (TII->isAliasingInstr(
MI)) {
707 }
else if (TII->isDecorationInstr(
MI)) {
709 collectFuncNames(
MI, &
F);
710 }
else if (TII->isConstantInstr(
MI)) {
714 }
else if (OpCode == SPIRV::OpFunction) {
715 collectFuncNames(
MI, &
F);
716 }
else if (OpCode == SPIRV::OpTypeForwardPointer) {
726void SPIRVModuleAnalysis::numberRegistersGlobally(
const Module &M) {
727 for (
const Function &
F : M) {
728 if (
F.isDeclaration())
730 MachineFunction *MF = MMI->getMachineFunction(
F);
732 for (MachineBasicBlock &
MBB : *MF) {
733 for (MachineInstr &
MI :
MBB) {
734 for (MachineOperand &
Op :
MI.operands()) {
738 if (
MAI.hasRegisterAlias(MF,
Reg))
740 MCRegister NewReg =
MAI.getNextIDRegister();
741 MAI.setRegisterAlias(MF,
Reg, NewReg);
743 if (
MI.getOpcode() != SPIRV::OpExtInst)
745 auto Set =
MI.getOperand(2).getImm();
746 auto [It,
Inserted] =
MAI.ExtInstSetMap.try_emplace(Set);
748 It->second =
MAI.getNextIDRegister();
756 SPIRV::OperandCategory::OperandCategory Category, uint32_t i,
758 addRequirements(getSymbolicOperandRequirements(Category, i, ST, *
this));
761void SPIRV::RequirementHandler::recursiveAddCapabilities(
763 for (
const auto &Cap : ToPrune) {
767 recursiveAddCapabilities(ImplicitDecls);
772 for (
const auto &Cap : ToAdd) {
773 bool IsNewlyInserted = AllCaps.insert(Cap).second;
774 if (!IsNewlyInserted)
778 recursiveAddCapabilities(ImplicitDecls);
779 MinimalCaps.push_back(Cap);
784 const SPIRV::Requirements &Req) {
788 if (Req.
Cap.has_value())
789 addCapabilities({Req.
Cap.value()});
791 addExtensions(Req.
Exts);
794 if (!MaxVersion.empty() && Req.
MinVer > MaxVersion) {
796 <<
" and <= " << MaxVersion <<
"\n");
800 if (MinVersion.empty() || Req.
MinVer > MinVersion)
805 if (!MinVersion.empty() && Req.
MaxVer < MinVersion) {
807 <<
" and >= " << MinVersion <<
"\n");
811 if (MaxVersion.empty() || Req.
MaxVer < MaxVersion)
817 const SPIRVSubtarget &ST)
const {
819 bool IsSatisfiable =
true;
820 auto TargetVer =
ST.getSPIRVVersion();
822 if (!MaxVersion.empty() && !TargetVer.empty() && MaxVersion < TargetVer) {
824 dbgs() <<
"Target SPIR-V version too high for required features\n"
825 <<
"Required max version: " << MaxVersion <<
" target version "
826 << TargetVer <<
"\n");
827 IsSatisfiable =
false;
830 if (!MinVersion.empty() && !TargetVer.empty() && MinVersion > TargetVer) {
831 LLVM_DEBUG(
dbgs() <<
"Target SPIR-V version too low for required features\n"
832 <<
"Required min version: " << MinVersion
833 <<
" target version " << TargetVer <<
"\n");
834 IsSatisfiable =
false;
837 if (!MinVersion.empty() && !MaxVersion.empty() && MinVersion > MaxVersion) {
840 <<
"Version is too low for some features and too high for others.\n"
841 <<
"Required SPIR-V min version: " << MinVersion
842 <<
" required SPIR-V max version " << MaxVersion <<
"\n");
843 IsSatisfiable =
false;
846 AvoidCapabilitiesSet AvoidCaps;
848 AvoidCaps.
S.
insert(SPIRV::Capability::Shader);
850 AvoidCaps.
S.
insert(SPIRV::Capability::Kernel);
852 for (
auto Cap : MinimalCaps) {
853 if (AvailableCaps.contains(Cap) && !AvoidCaps.
S.
contains(Cap))
857 OperandCategory::CapabilityOperand, Cap)
859 IsSatisfiable =
false;
862 for (
auto Ext : AllExtensions) {
863 if (
ST.canUseExtension(Ext))
867 OperandCategory::ExtensionOperand, Ext)
869 IsSatisfiable =
false;
878 for (
const auto Cap : ToAdd)
879 if (AvailableCaps.insert(Cap).second)
881 SPIRV::OperandCategory::CapabilityOperand, Cap));
885 const Capability::Capability
ToRemove,
886 const Capability::Capability IfPresent) {
887 if (AllCaps.contains(IfPresent))
895 addAvailableCaps({Capability::Shader, Capability::Linkage, Capability::Int8,
898 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 3)))
900 Capability::GroupNonUniformVote,
901 Capability::GroupNonUniformArithmetic,
902 Capability::GroupNonUniformBallot,
903 Capability::GroupNonUniformClustered,
904 Capability::GroupNonUniformShuffle,
905 Capability::GroupNonUniformShuffleRelative,
906 Capability::GroupNonUniformQuad});
908 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 6)))
910 Capability::DotProductInput4x8Bit,
911 Capability::DotProductInput4x8BitPacked,
912 Capability::DemoteToHelperInvocation});
915 for (
auto Extension :
ST.getAllAvailableExtensions()) {
921 if (!
ST.isShader()) {
922 initAvailableCapabilitiesForOpenCL(ST);
927 initAvailableCapabilitiesForVulkan(ST);
934void RequirementHandler::initAvailableCapabilitiesForOpenCL(
935 const SPIRVSubtarget &ST) {
938 Capability::Kernel, Capability::Vector16,
939 Capability::Groups, Capability::GenericPointer,
940 Capability::StorageImageWriteWithoutFormat,
941 Capability::StorageImageReadWithoutFormat});
942 if (
ST.hasOpenCLFullProfile())
944 if (
ST.hasOpenCLImageSupport()) {
946 Capability::Image1D, Capability::SampledBuffer,
947 Capability::ImageBuffer});
948 if (
ST.isAtLeastOpenCLVer(VersionTuple(2, 0)))
951 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 1)) &&
952 ST.isAtLeastOpenCLVer(VersionTuple(2, 2)))
954 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 4)))
955 addAvailableCaps({Capability::DenormPreserve, Capability::DenormFlushToZero,
956 Capability::SignedZeroInfNanPreserve,
957 Capability::RoundingModeRTE,
958 Capability::RoundingModeRTZ});
965void RequirementHandler::initAvailableCapabilitiesForVulkan(
966 const SPIRVSubtarget &ST) {
972 Capability::GroupNonUniform,
974 Capability::SampledBuffer,
975 Capability::ImageBuffer,
976 Capability::UniformBufferArrayDynamicIndexing,
977 Capability::SampledImageArrayDynamicIndexing,
978 Capability::StorageBufferArrayDynamicIndexing,
979 Capability::StorageImageArrayDynamicIndexing,
980 Capability::DerivativeControl,
982 Capability::ImageQuery,
983 Capability::ImageGatherExtended,
984 Capability::Addresses,
985 Capability::VulkanMemoryModelKHR,
986 Capability::StorageImageExtendedFormats,
987 Capability::StorageImageMultisample,
988 Capability::ImageMSArray});
991 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 5))) {
993 {Capability::ShaderNonUniformEXT, Capability::RuntimeDescriptorArrayEXT,
994 Capability::InputAttachmentArrayDynamicIndexingEXT,
995 Capability::UniformTexelBufferArrayDynamicIndexingEXT,
996 Capability::StorageTexelBufferArrayDynamicIndexingEXT,
997 Capability::UniformBufferArrayNonUniformIndexingEXT,
998 Capability::SampledImageArrayNonUniformIndexingEXT,
999 Capability::StorageBufferArrayNonUniformIndexingEXT,
1000 Capability::StorageImageArrayNonUniformIndexingEXT,
1001 Capability::InputAttachmentArrayNonUniformIndexingEXT,
1002 Capability::UniformTexelBufferArrayNonUniformIndexingEXT,
1003 Capability::StorageTexelBufferArrayNonUniformIndexingEXT});
1007 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 6)))
1009 Capability::StorageImageReadWithoutFormat});
1017static void addOpDecorateReqs(
const MachineInstr &
MI,
unsigned DecIndex,
1020 int64_t DecOp =
MI.getOperand(DecIndex).getImm();
1021 auto Dec =
static_cast<SPIRV::Decoration::Decoration
>(DecOp);
1023 SPIRV::OperandCategory::DecorationOperand, Dec, ST, Reqs));
1025 if (Dec == SPIRV::Decoration::BuiltIn) {
1026 int64_t BuiltInOp =
MI.getOperand(DecIndex + 1).getImm();
1027 auto BuiltIn =
static_cast<SPIRV::BuiltIn::BuiltIn
>(BuiltInOp);
1029 SPIRV::OperandCategory::BuiltInOperand, BuiltIn, ST, Reqs));
1030 }
else if (Dec == SPIRV::Decoration::LinkageAttributes) {
1031 int64_t LinkageOp =
MI.getOperand(
MI.getNumOperands() - 1).getImm();
1032 SPIRV::LinkageType::LinkageType LnkType =
1033 static_cast<SPIRV::LinkageType::LinkageType
>(LinkageOp);
1034 if (LnkType == SPIRV::LinkageType::LinkOnceODR)
1035 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_linkonce_odr);
1036 else if (LnkType == SPIRV::LinkageType::WeakAMD) {
1037 Reqs.
addExtension(SPIRV::Extension::SPV_AMD_weak_linkage);
1040 }
else if (Dec == SPIRV::Decoration::CacheControlLoadINTEL ||
1041 Dec == SPIRV::Decoration::CacheControlStoreINTEL) {
1042 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_cache_controls);
1043 }
else if (Dec == SPIRV::Decoration::HostAccessINTEL) {
1044 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_global_variable_host_access);
1045 }
else if (Dec == SPIRV::Decoration::InitModeINTEL ||
1046 Dec == SPIRV::Decoration::ImplementInRegisterMapINTEL) {
1048 SPIRV::Extension::SPV_INTEL_global_variable_fpga_decorations);
1049 }
else if (Dec == SPIRV::Decoration::NonUniformEXT) {
1051 }
else if (Dec == SPIRV::Decoration::FPMaxErrorDecorationINTEL) {
1053 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_fp_max_error);
1054 }
else if (Dec == SPIRV::Decoration::FPFastMathMode) {
1055 if (
ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2)) {
1057 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_float_controls2);
1066 assert(
MI.getNumOperands() >= 8 &&
"Insufficient operands for OpTypeImage");
1069 int64_t ImgFormatOp =
MI.getOperand(7).getImm();
1070 auto ImgFormat =
static_cast<SPIRV::ImageFormat::ImageFormat
>(ImgFormatOp);
1074 bool IsArrayed =
MI.getOperand(4).getImm() == 1;
1075 bool IsMultisampled =
MI.getOperand(5).getImm() == 1;
1076 bool NoSampler =
MI.getOperand(6).getImm() == 2;
1079 switch (
MI.getOperand(2).getImm()) {
1080 case SPIRV::Dim::DIM_1D:
1082 : SPIRV::Capability::Sampled1D);
1084 case SPIRV::Dim::DIM_2D:
1085 if (IsMultisampled && NoSampler)
1087 if (IsMultisampled && IsArrayed)
1090 case SPIRV::Dim::DIM_3D:
1092 case SPIRV::Dim::DIM_Cube:
1096 : SPIRV::Capability::SampledCubeArray);
1098 case SPIRV::Dim::DIM_Rect:
1100 : SPIRV::Capability::SampledRect);
1102 case SPIRV::Dim::DIM_Buffer:
1104 : SPIRV::Capability::SampledBuffer);
1106 case SPIRV::Dim::DIM_SubpassData:
1118 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_shader_image_int64);
1122 if (!
ST.isShader()) {
1123 if (
MI.getNumOperands() > 8 &&
1124 MI.getOperand(8).getImm() == SPIRV::AccessQualifier::ReadWrite)
1133 TypeDef->
getOpcode() == SPIRV::OpTypeFloat &&
1139#define ATOM_FLT_REQ_EXT_MSG(ExtName) \
1140 "The atomic float instruction requires the following SPIR-V " \
1141 "extension: SPV_EXT_shader_atomic_float" ExtName
1142static void AddAtomicVectorFloatRequirements(
const MachineInstr &
MI,
1146 MI.getMF()->getRegInfo().getVRegDef(
MI.getOperand(1).getReg());
1149 if (Rank != 2 && Rank != 4)
1151 "must be a 2-component or 4 component vector");
1156 if (EltTypeDef->
getOpcode() != SPIRV::OpTypeFloat ||
1159 "The element type for the result type of an atomic vector float "
1160 "instruction must be a 16-bit floating-point scalar");
1162 if (isBFloat16Type(EltTypeDef))
1164 "The element type for the result type of an atomic vector float "
1165 "instruction cannot be a bfloat16 scalar");
1166 if (!
ST.canUseExtension(SPIRV::Extension::SPV_NV_shader_atomic_fp16_vector))
1168 "The atomic float16 vector instruction requires the following SPIR-V "
1169 "extension: SPV_NV_shader_atomic_fp16_vector");
1171 Reqs.
addExtension(SPIRV::Extension::SPV_NV_shader_atomic_fp16_vector);
1172 Reqs.
addCapability(SPIRV::Capability::AtomicFloat16VectorNV);
1179 "Expect register operand in atomic float instruction");
1180 Register TypeReg =
MI.getOperand(1).getReg();
1183 if (TypeDef->
getOpcode() == SPIRV::OpTypeVector)
1184 return AddAtomicVectorFloatRequirements(
MI, Reqs, ST);
1186 if (TypeDef->
getOpcode() != SPIRV::OpTypeFloat)
1188 "floating-point type scalar");
1191 unsigned Op =
MI.getOpcode();
1192 if (
Op == SPIRV::OpAtomicFAddEXT) {
1193 if (!
ST.canUseExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float_add))
1195 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float_add);
1198 if (isBFloat16Type(TypeDef)) {
1199 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics))
1201 "The atomic bfloat16 instruction requires the following SPIR-V "
1202 "extension: SPV_INTEL_16bit_atomics",
1204 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics);
1205 Reqs.
addCapability(SPIRV::Capability::AtomicBFloat16AddINTEL);
1207 if (!
ST.canUseExtension(
1208 SPIRV::Extension::SPV_EXT_shader_atomic_float16_add))
1210 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float16_add);
1222 "Unexpected floating-point type width in atomic float instruction");
1225 if (!
ST.canUseExtension(
1226 SPIRV::Extension::SPV_EXT_shader_atomic_float_min_max))
1228 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float_min_max);
1231 if (isBFloat16Type(TypeDef)) {
1232 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics))
1234 "The atomic bfloat16 instruction requires the following SPIR-V "
1235 "extension: SPV_INTEL_16bit_atomics",
1237 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics);
1238 Reqs.
addCapability(SPIRV::Capability::AtomicBFloat16MinMaxINTEL);
1240 Reqs.
addCapability(SPIRV::Capability::AtomicFloat16MinMaxEXT);
1244 Reqs.
addCapability(SPIRV::Capability::AtomicFloat32MinMaxEXT);
1247 Reqs.
addCapability(SPIRV::Capability::AtomicFloat64MinMaxEXT);
1251 "Unexpected floating-point type width in atomic float instruction");
1257 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1261 return Dim == SPIRV::Dim::DIM_Buffer && Sampled == 1;
1265 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1269 return Dim == SPIRV::Dim::DIM_Buffer && Sampled == 2;
1273 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1277 return Dim != SPIRV::Dim::DIM_Buffer && Sampled == 1;
1281 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1285 return Dim == SPIRV::Dim::DIM_SubpassData && Sampled == 2;
1289 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1293 return Dim != SPIRV::Dim::DIM_Buffer && Sampled == 2;
1296bool isCombinedImageSampler(
MachineInstr *SampledImageInst) {
1297 if (SampledImageInst->
getOpcode() != SPIRV::OpTypeSampledImage)
1303 return isSampledImage(ImageInst);
1308 if (
MI.getOpcode() != SPIRV::OpDecorate)
1312 if (Dec == SPIRV::Decoration::NonUniformEXT)
1330 if (
StorageClass != SPIRV::StorageClass::StorageClass::UniformConstant &&
1331 StorageClass != SPIRV::StorageClass::StorageClass::Uniform &&
1332 StorageClass != SPIRV::StorageClass::StorageClass::StorageBuffer) {
1337 hasNonUniformDecoration(
Instr.getOperand(0).getReg(), MRI);
1339 auto FirstIndexReg =
Instr.getOperand(3).getReg();
1340 bool FirstIndexIsConstant =
1343 if (
StorageClass == SPIRV::StorageClass::StorageClass::StorageBuffer) {
1346 SPIRV::Capability::StorageBufferArrayNonUniformIndexingEXT);
1347 else if (!FirstIndexIsConstant)
1349 SPIRV::Capability::StorageBufferArrayDynamicIndexing);
1355 if (PointeeType->
getOpcode() != SPIRV::OpTypeImage &&
1356 PointeeType->
getOpcode() != SPIRV::OpTypeSampledImage &&
1357 PointeeType->
getOpcode() != SPIRV::OpTypeSampler) {
1361 if (isUniformTexelBuffer(PointeeType)) {
1364 SPIRV::Capability::UniformTexelBufferArrayNonUniformIndexingEXT);
1365 else if (!FirstIndexIsConstant)
1367 SPIRV::Capability::UniformTexelBufferArrayDynamicIndexingEXT);
1368 }
else if (isInputAttachment(PointeeType)) {
1371 SPIRV::Capability::InputAttachmentArrayNonUniformIndexingEXT);
1372 else if (!FirstIndexIsConstant)
1374 SPIRV::Capability::InputAttachmentArrayDynamicIndexingEXT);
1375 }
else if (isStorageTexelBuffer(PointeeType)) {
1378 SPIRV::Capability::StorageTexelBufferArrayNonUniformIndexingEXT);
1379 else if (!FirstIndexIsConstant)
1381 SPIRV::Capability::StorageTexelBufferArrayDynamicIndexingEXT);
1382 }
else if (isSampledImage(PointeeType) ||
1383 isCombinedImageSampler(PointeeType) ||
1384 PointeeType->
getOpcode() == SPIRV::OpTypeSampler) {
1387 SPIRV::Capability::SampledImageArrayNonUniformIndexingEXT);
1388 else if (!FirstIndexIsConstant)
1390 SPIRV::Capability::SampledImageArrayDynamicIndexing);
1391 }
else if (isStorageImage(PointeeType)) {
1394 SPIRV::Capability::StorageImageArrayNonUniformIndexingEXT);
1395 else if (!FirstIndexIsConstant)
1397 SPIRV::Capability::StorageImageArrayDynamicIndexing);
1401static bool isImageTypeWithUnknownFormat(
SPIRVTypeInst TypeInst) {
1402 if (TypeInst->
getOpcode() != SPIRV::OpTypeImage)
1411 if (
ST.canUseExtension(SPIRV::Extension::SPV_KHR_integer_dot_product))
1412 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_integer_dot_product);
1416 assert(
MI.getOperand(2).isReg() &&
"Unexpected operand in dot");
1420 assert(
Input->getOperand(1).isReg() &&
"Unexpected operand in dot input");
1424 if (TypeDef->
getOpcode() == SPIRV::OpTypeInt) {
1426 Reqs.
addCapability(SPIRV::Capability::DotProductInput4x8BitPacked);
1427 }
else if (TypeDef->
getOpcode() == SPIRV::OpTypeVector) {
1433 "Dot operand of 8-bit integer type requires 4 components");
1434 Reqs.
addCapability(SPIRV::Capability::DotProductInput4x8Bit);
1449 unsigned AddrSpace = ASOp.
getImm();
1450 if (AddrSpace != SPIRV::StorageClass::UniformConstant) {
1451 if (!
ST.canUseExtension(
1453 SPV_EXT_relaxed_printf_string_address_space)) {
1455 "required because printf uses a format string not "
1456 "in constant address space.",
1460 SPIRV::Extension::SPV_EXT_relaxed_printf_string_address_space);
1469 if (
MI.getNumOperands() <=
OpIdx)
1473 if (Mask & (1U <<
I))
1482 unsigned Op =
MI.getOpcode();
1484 case SPIRV::OpMemoryModel: {
1485 int64_t Addr =
MI.getOperand(0).getImm();
1488 int64_t Mem =
MI.getOperand(1).getImm();
1493 case SPIRV::OpEntryPoint: {
1494 int64_t
Exe =
MI.getOperand(0).getImm();
1499 case SPIRV::OpExecutionMode:
1500 case SPIRV::OpExecutionModeId: {
1501 int64_t
Exe =
MI.getOperand(1).getImm();
1506 case SPIRV::OpTypeMatrix:
1509 case SPIRV::OpTypeInt: {
1510 unsigned BitWidth =
MI.getOperand(1).getImm();
1518 ST.canUseExtension(SPIRV::Extension::SPV_INTEL_int4)) {
1522 if (!
ST.canUseExtension(
1523 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_integers))
1525 "OpTypeInt type with a width other than 8, 16, 32 or 64 bits "
1526 "requires the following SPIR-V extension: "
1527 "SPV_ALTERA_arbitrary_precision_integers");
1529 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_integers);
1530 Reqs.
addCapability(SPIRV::Capability::ArbitraryPrecisionIntegersALTERA);
1534 case SPIRV::OpDot: {
1537 if (isBFloat16Type(TypeDef))
1538 Reqs.
addCapability(SPIRV::Capability::BFloat16DotProductKHR);
1541 case SPIRV::OpTypeFloat: {
1542 unsigned BitWidth =
MI.getOperand(1).getImm();
1546 if (isBFloat16Type(&
MI)) {
1547 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_bfloat16))
1549 "following SPIR-V extension: SPV_KHR_bfloat16",
1559 case SPIRV::OpTypeVector: {
1560 unsigned NumComponents =
MI.getOperand(2).getImm();
1561 if (NumComponents == 8 || NumComponents == 16)
1567 if (ElemTypeDef->
getOpcode() == SPIRV::OpTypePointer &&
1568 ST.canUseExtension(SPIRV::Extension::SPV_INTEL_masked_gather_scatter)) {
1569 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_masked_gather_scatter);
1570 Reqs.
addCapability(SPIRV::Capability::MaskedGatherScatterINTEL);
1574 case SPIRV::OpTypePointer: {
1575 auto SC =
MI.getOperand(1).getImm();
1586 (TypeDef->
getOpcode() == SPIRV::OpTypeFloat) &&
1591 case SPIRV::OpExtInst: {
1592 if (
MI.getOperand(2).getImm() ==
1593 static_cast<int64_t
>(
1594 SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100)) {
1595 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_non_semantic_info);
1598 if (
MI.getOperand(3).getImm() ==
1599 static_cast<int64_t
>(SPIRV::OpenCLExtInst::printf)) {
1600 addPrintfRequirements(
MI, Reqs, ST);
1607 case SPIRV::OpAliasDomainDeclINTEL:
1608 case SPIRV::OpAliasScopeDeclINTEL:
1609 case SPIRV::OpAliasScopeListDeclINTEL: {
1610 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_memory_access_aliasing);
1611 Reqs.
addCapability(SPIRV::Capability::MemoryAccessAliasingINTEL);
1614 case SPIRV::OpBitReverse:
1615 case SPIRV::OpBitFieldInsert:
1616 case SPIRV::OpBitFieldSExtract:
1617 case SPIRV::OpBitFieldUExtract:
1618 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_bit_instructions)) {
1622 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_bit_instructions);
1625 case SPIRV::OpTypeRuntimeArray:
1628 case SPIRV::OpTypeOpaque:
1629 case SPIRV::OpTypeEvent:
1632 case SPIRV::OpTypePipe:
1633 case SPIRV::OpTypeReserveId:
1636 case SPIRV::OpTypeDeviceEvent:
1637 case SPIRV::OpTypeQueue:
1638 case SPIRV::OpBuildNDRange:
1641 case SPIRV::OpDecorate:
1642 case SPIRV::OpDecorateId:
1643 case SPIRV::OpDecorateString:
1644 addOpDecorateReqs(
MI, 1, Reqs, ST);
1646 case SPIRV::OpMemberDecorate:
1647 case SPIRV::OpMemberDecorateString:
1648 addOpDecorateReqs(
MI, 2, Reqs, ST);
1650 case SPIRV::OpInBoundsPtrAccessChain:
1653 case SPIRV::OpConstantSampler:
1656 case SPIRV::OpInBoundsAccessChain:
1657 case SPIRV::OpAccessChain:
1658 addOpAccessChainReqs(
MI, Reqs, ST);
1660 case SPIRV::OpTypeImage:
1661 addOpTypeImageReqs(
MI, Reqs, ST);
1663 case SPIRV::OpTypeSampler:
1664 if (!
ST.isShader()) {
1668 case SPIRV::OpTypeForwardPointer:
1672 case SPIRV::OpAtomicFlagTestAndSet:
1673 case SPIRV::OpAtomicLoad:
1674 case SPIRV::OpAtomicStore:
1675 case SPIRV::OpAtomicExchange:
1676 case SPIRV::OpAtomicCompareExchange:
1677 case SPIRV::OpAtomicIIncrement:
1678 case SPIRV::OpAtomicIDecrement:
1679 case SPIRV::OpAtomicIAdd:
1680 case SPIRV::OpAtomicISub:
1681 case SPIRV::OpAtomicUMin:
1682 case SPIRV::OpAtomicUMax:
1683 case SPIRV::OpAtomicSMin:
1684 case SPIRV::OpAtomicSMax:
1685 case SPIRV::OpAtomicAnd:
1686 case SPIRV::OpAtomicOr:
1687 case SPIRV::OpAtomicXor: {
1690 if (
Op == SPIRV::OpAtomicStore) {
1693 assert(InstrPtr &&
"Unexpected type instruction for OpAtomicStore");
1699 if (TypeDef->
getOpcode() == SPIRV::OpTypeInt) {
1704 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics))
1706 "16-bit integer atomic operations require the following SPIR-V "
1707 "extension: SPV_INTEL_16bit_atomics",
1709 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics);
1711 case SPIRV::OpAtomicLoad:
1712 case SPIRV::OpAtomicStore:
1713 case SPIRV::OpAtomicExchange:
1714 case SPIRV::OpAtomicCompareExchange:
1715 case SPIRV::OpAtomicCompareExchangeWeak:
1717 SPIRV::Capability::AtomicInt16CompareExchangeINTEL);
1724 }
else if (isBFloat16Type(TypeDef)) {
1725 if (
is_contained({SPIRV::OpAtomicLoad, SPIRV::OpAtomicStore,
1726 SPIRV::OpAtomicExchange},
1728 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics))
1730 "The atomic bfloat16 instruction requires the following SPIR-V "
1731 "extension: SPV_INTEL_16bit_atomics",
1733 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics);
1734 Reqs.
addCapability(SPIRV::Capability::AtomicBFloat16LoadStoreINTEL);
1739 case SPIRV::OpGroupNonUniformIAdd:
1740 case SPIRV::OpGroupNonUniformFAdd:
1741 case SPIRV::OpGroupNonUniformIMul:
1742 case SPIRV::OpGroupNonUniformFMul:
1743 case SPIRV::OpGroupNonUniformSMin:
1744 case SPIRV::OpGroupNonUniformUMin:
1745 case SPIRV::OpGroupNonUniformFMin:
1746 case SPIRV::OpGroupNonUniformSMax:
1747 case SPIRV::OpGroupNonUniformUMax:
1748 case SPIRV::OpGroupNonUniformFMax:
1749 case SPIRV::OpGroupNonUniformBitwiseAnd:
1750 case SPIRV::OpGroupNonUniformBitwiseOr:
1751 case SPIRV::OpGroupNonUniformBitwiseXor:
1752 case SPIRV::OpGroupNonUniformLogicalAnd:
1753 case SPIRV::OpGroupNonUniformLogicalOr:
1754 case SPIRV::OpGroupNonUniformLogicalXor: {
1756 int64_t GroupOp =
MI.getOperand(3).getImm();
1758 case SPIRV::GroupOperation::Reduce:
1759 case SPIRV::GroupOperation::InclusiveScan:
1760 case SPIRV::GroupOperation::ExclusiveScan:
1761 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformArithmetic);
1763 case SPIRV::GroupOperation::ClusteredReduce:
1764 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformClustered);
1766 case SPIRV::GroupOperation::PartitionedReduceNV:
1767 case SPIRV::GroupOperation::PartitionedInclusiveScanNV:
1768 case SPIRV::GroupOperation::PartitionedExclusiveScanNV:
1769 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformPartitionedNV);
1774 case SPIRV::OpGroupNonUniformQuadSwap:
1777 case SPIRV::OpImageQueryLod:
1780 case SPIRV::OpImageQuerySize:
1781 case SPIRV::OpImageQuerySizeLod:
1782 case SPIRV::OpImageQueryLevels:
1783 case SPIRV::OpImageQuerySamples:
1787 case SPIRV::OpImageQueryFormat: {
1788 Register ResultReg =
MI.getOperand(0).getReg();
1790 static const unsigned CompareOps[] = {
1791 SPIRV::OpIEqual, SPIRV::OpINotEqual,
1792 SPIRV::OpUGreaterThan, SPIRV::OpUGreaterThanEqual,
1793 SPIRV::OpULessThan, SPIRV::OpULessThanEqual,
1794 SPIRV::OpSGreaterThan, SPIRV::OpSGreaterThanEqual,
1795 SPIRV::OpSLessThan, SPIRV::OpSLessThanEqual};
1797 auto CheckAndAddExtension = [&](int64_t ImmVal) {
1798 if (ImmVal == 4323 || ImmVal == 4324) {
1799 if (
ST.canUseExtension(SPIRV::Extension::SPV_EXT_image_raw10_raw12))
1800 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_image_raw10_raw12);
1803 "SPV_EXT_image_raw10_raw12 extension");
1808 unsigned Opc = UseInst.getOpcode();
1810 if (
Opc == SPIRV::OpSwitch) {
1813 CheckAndAddExtension(
Op.getImm());
1815 for (
unsigned i = 1; i < UseInst.getNumOperands(); ++i) {
1818 if (ConstInst && ConstInst->
getOpcode() == SPIRV::OpConstantI) {
1821 CheckAndAddExtension(ImmVal);
1829 case SPIRV::OpGroupNonUniformShuffle:
1830 case SPIRV::OpGroupNonUniformShuffleXor:
1831 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformShuffle);
1833 case SPIRV::OpGroupNonUniformShuffleUp:
1834 case SPIRV::OpGroupNonUniformShuffleDown:
1835 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformShuffleRelative);
1837 case SPIRV::OpGroupAll:
1838 case SPIRV::OpGroupAny:
1839 case SPIRV::OpGroupBroadcast:
1840 case SPIRV::OpGroupIAdd:
1841 case SPIRV::OpGroupFAdd:
1842 case SPIRV::OpGroupFMin:
1843 case SPIRV::OpGroupUMin:
1844 case SPIRV::OpGroupSMin:
1845 case SPIRV::OpGroupFMax:
1846 case SPIRV::OpGroupUMax:
1847 case SPIRV::OpGroupSMax:
1850 case SPIRV::OpGroupNonUniformElect:
1853 case SPIRV::OpGroupNonUniformAll:
1854 case SPIRV::OpGroupNonUniformAny:
1855 case SPIRV::OpGroupNonUniformAllEqual:
1858 case SPIRV::OpGroupNonUniformBroadcast:
1859 case SPIRV::OpGroupNonUniformBroadcastFirst:
1860 case SPIRV::OpGroupNonUniformBallot:
1861 case SPIRV::OpGroupNonUniformInverseBallot:
1862 case SPIRV::OpGroupNonUniformBallotBitExtract:
1863 case SPIRV::OpGroupNonUniformBallotBitCount:
1864 case SPIRV::OpGroupNonUniformBallotFindLSB:
1865 case SPIRV::OpGroupNonUniformBallotFindMSB:
1866 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformBallot);
1868 case SPIRV::OpSubgroupShuffleINTEL:
1869 case SPIRV::OpSubgroupShuffleDownINTEL:
1870 case SPIRV::OpSubgroupShuffleUpINTEL:
1871 case SPIRV::OpSubgroupShuffleXorINTEL:
1872 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {
1873 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_subgroups);
1874 Reqs.
addCapability(SPIRV::Capability::SubgroupShuffleINTEL);
1877 case SPIRV::OpSubgroupBlockReadINTEL:
1878 case SPIRV::OpSubgroupBlockWriteINTEL:
1879 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {
1880 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_subgroups);
1881 Reqs.
addCapability(SPIRV::Capability::SubgroupBufferBlockIOINTEL);
1884 case SPIRV::OpSubgroupImageBlockReadINTEL:
1885 case SPIRV::OpSubgroupImageBlockWriteINTEL:
1886 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {
1887 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_subgroups);
1888 Reqs.
addCapability(SPIRV::Capability::SubgroupImageBlockIOINTEL);
1891 case SPIRV::OpSubgroupImageMediaBlockReadINTEL:
1892 case SPIRV::OpSubgroupImageMediaBlockWriteINTEL:
1893 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_media_block_io)) {
1894 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_media_block_io);
1895 Reqs.
addCapability(SPIRV::Capability::SubgroupImageMediaBlockIOINTEL);
1898 case SPIRV::OpAssumeTrueKHR:
1899 case SPIRV::OpExpectKHR:
1900 if (
ST.canUseExtension(SPIRV::Extension::SPV_KHR_expect_assume)) {
1901 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_expect_assume);
1905 case SPIRV::OpFmaKHR:
1906 if (
ST.canUseExtension(SPIRV::Extension::SPV_KHR_fma)) {
1911 case SPIRV::OpPtrCastToCrossWorkgroupINTEL:
1912 case SPIRV::OpCrossWorkgroupCastToPtrINTEL:
1913 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_usm_storage_classes)) {
1914 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_usm_storage_classes);
1915 Reqs.
addCapability(SPIRV::Capability::USMStorageClassesINTEL);
1918 case SPIRV::OpConstantFunctionPointerINTEL:
1919 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_function_pointers)) {
1920 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_function_pointers);
1921 Reqs.
addCapability(SPIRV::Capability::FunctionPointersINTEL);
1924 case SPIRV::OpGroupNonUniformRotateKHR:
1925 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_subgroup_rotate))
1927 "following SPIR-V extension: SPV_KHR_subgroup_rotate",
1929 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_subgroup_rotate);
1930 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformRotateKHR);
1933 case SPIRV::OpFixedCosALTERA:
1934 case SPIRV::OpFixedSinALTERA:
1935 case SPIRV::OpFixedCosPiALTERA:
1936 case SPIRV::OpFixedSinPiALTERA:
1937 case SPIRV::OpFixedExpALTERA:
1938 case SPIRV::OpFixedLogALTERA:
1939 case SPIRV::OpFixedRecipALTERA:
1940 case SPIRV::OpFixedSqrtALTERA:
1941 case SPIRV::OpFixedSinCosALTERA:
1942 case SPIRV::OpFixedSinCosPiALTERA:
1943 case SPIRV::OpFixedRsqrtALTERA:
1944 if (!
ST.canUseExtension(
1945 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_fixed_point))
1947 "following SPIR-V extension: "
1948 "SPV_ALTERA_arbitrary_precision_fixed_point",
1951 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_fixed_point);
1952 Reqs.
addCapability(SPIRV::Capability::ArbitraryPrecisionFixedPointALTERA);
1954 case SPIRV::OpGroupIMulKHR:
1955 case SPIRV::OpGroupFMulKHR:
1956 case SPIRV::OpGroupBitwiseAndKHR:
1957 case SPIRV::OpGroupBitwiseOrKHR:
1958 case SPIRV::OpGroupBitwiseXorKHR:
1959 case SPIRV::OpGroupLogicalAndKHR:
1960 case SPIRV::OpGroupLogicalOrKHR:
1961 case SPIRV::OpGroupLogicalXorKHR:
1962 if (
ST.canUseExtension(
1963 SPIRV::Extension::SPV_KHR_uniform_group_instructions)) {
1964 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_uniform_group_instructions);
1965 Reqs.
addCapability(SPIRV::Capability::GroupUniformArithmeticKHR);
1968 case SPIRV::OpReadClockKHR:
1969 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_shader_clock))
1971 "following SPIR-V extension: SPV_KHR_shader_clock",
1973 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_shader_clock);
1976 case SPIRV::OpAbortKHR:
1977 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_abort))
1979 "following SPIR-V extension: SPV_KHR_abort",
1984 case SPIRV::OpFunctionPointerCallINTEL:
1985 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_function_pointers)) {
1986 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_function_pointers);
1987 Reqs.
addCapability(SPIRV::Capability::FunctionPointersINTEL);
1990 case SPIRV::OpAtomicFAddEXT:
1991 case SPIRV::OpAtomicFMinEXT:
1992 case SPIRV::OpAtomicFMaxEXT:
1993 AddAtomicFloatRequirements(
MI, Reqs, ST);
1995 case SPIRV::OpConvertBF16ToFINTEL:
1996 case SPIRV::OpConvertFToBF16INTEL:
1997 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bfloat16_conversion)) {
1998 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bfloat16_conversion);
1999 Reqs.
addCapability(SPIRV::Capability::BFloat16ConversionINTEL);
2002 case SPIRV::OpRoundFToTF32INTEL:
2003 if (
ST.canUseExtension(
2004 SPIRV::Extension::SPV_INTEL_tensor_float32_conversion)) {
2005 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_tensor_float32_conversion);
2006 Reqs.
addCapability(SPIRV::Capability::TensorFloat32RoundingINTEL);
2009 case SPIRV::OpVariableLengthArrayINTEL:
2010 case SPIRV::OpSaveMemoryINTEL:
2011 case SPIRV::OpRestoreMemoryINTEL:
2012 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_variable_length_array)) {
2013 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_variable_length_array);
2014 Reqs.
addCapability(SPIRV::Capability::VariableLengthArrayINTEL);
2017 case SPIRV::OpAsmTargetINTEL:
2018 case SPIRV::OpAsmINTEL:
2019 case SPIRV::OpAsmCallINTEL:
2020 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_inline_assembly)) {
2021 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_inline_assembly);
2025 case SPIRV::OpTypeCooperativeMatrixKHR: {
2026 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix))
2028 "OpTypeCooperativeMatrixKHR type requires the "
2029 "following SPIR-V extension: SPV_KHR_cooperative_matrix",
2031 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix);
2032 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixKHR);
2035 if (isBFloat16Type(TypeDef))
2036 Reqs.
addCapability(SPIRV::Capability::BFloat16CooperativeMatrixKHR);
2039 case SPIRV::OpArithmeticFenceEXT:
2040 if (!
ST.canUseExtension(SPIRV::Extension::SPV_EXT_arithmetic_fence))
2042 "following SPIR-V extension: SPV_EXT_arithmetic_fence",
2044 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_arithmetic_fence);
2047 case SPIRV::OpControlBarrierArriveINTEL:
2048 case SPIRV::OpControlBarrierWaitINTEL:
2049 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_split_barrier)) {
2050 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_split_barrier);
2054 case SPIRV::OpCooperativeMatrixMulAddKHR: {
2055 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix))
2057 "following SPIR-V extension: "
2058 "SPV_KHR_cooperative_matrix",
2060 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix);
2061 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixKHR);
2062 constexpr unsigned MulAddMaxSize = 6;
2063 if (
MI.getNumOperands() != MulAddMaxSize)
2065 const int64_t CoopOperands =
MI.getOperand(MulAddMaxSize - 1).getImm();
2067 SPIRV::CooperativeMatrixOperands::MatrixAAndBTF32ComponentsINTEL) {
2068 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
2070 "require the following SPIR-V extension: "
2071 "SPV_INTEL_joint_matrix",
2073 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2075 SPIRV::Capability::CooperativeMatrixTF32ComponentTypeINTEL);
2078 MatrixAAndBBFloat16ComponentsINTEL ||
2080 SPIRV::CooperativeMatrixOperands::MatrixCBFloat16ComponentsINTEL ||
2082 MatrixResultBFloat16ComponentsINTEL) {
2083 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
2085 "require the following SPIR-V extension: "
2086 "SPV_INTEL_joint_matrix",
2088 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2090 SPIRV::Capability::CooperativeMatrixBFloat16ComponentTypeINTEL);
2094 case SPIRV::OpCooperativeMatrixLoadKHR:
2095 case SPIRV::OpCooperativeMatrixStoreKHR:
2096 case SPIRV::OpCooperativeMatrixLoadCheckedINTEL:
2097 case SPIRV::OpCooperativeMatrixStoreCheckedINTEL:
2098 case SPIRV::OpCooperativeMatrixPrefetchINTEL: {
2099 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix))
2101 "following SPIR-V extension: "
2102 "SPV_KHR_cooperative_matrix",
2104 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix);
2105 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixKHR);
2109 std::unordered_map<unsigned, unsigned> LayoutToInstMap = {
2110 {SPIRV::OpCooperativeMatrixLoadKHR, 3},
2111 {SPIRV::OpCooperativeMatrixStoreKHR, 2},
2112 {SPIRV::OpCooperativeMatrixLoadCheckedINTEL, 5},
2113 {SPIRV::OpCooperativeMatrixStoreCheckedINTEL, 4},
2114 {SPIRV::OpCooperativeMatrixPrefetchINTEL, 4}};
2116 const unsigned LayoutNum = LayoutToInstMap[
Op];
2117 Register RegLayout =
MI.getOperand(LayoutNum).getReg();
2120 if (MILayout->
getOpcode() == SPIRV::OpConstantI) {
2123 static_cast<unsigned>(SPIRV::CooperativeMatrixLayout::PackedINTEL)) {
2124 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
2126 "extension: SPV_INTEL_joint_matrix",
2128 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2129 Reqs.
addCapability(SPIRV::Capability::PackedCooperativeMatrixINTEL);
2134 if (
Op == SPIRV::OpCooperativeMatrixLoadKHR ||
2135 Op == SPIRV::OpCooperativeMatrixStoreKHR)
2138 std::string InstName;
2140 case SPIRV::OpCooperativeMatrixPrefetchINTEL:
2141 InstName =
"OpCooperativeMatrixPrefetchINTEL";
2143 case SPIRV::OpCooperativeMatrixLoadCheckedINTEL:
2144 InstName =
"OpCooperativeMatrixLoadCheckedINTEL";
2146 case SPIRV::OpCooperativeMatrixStoreCheckedINTEL:
2147 InstName =
"OpCooperativeMatrixStoreCheckedINTEL";
2151 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix)) {
2152 const std::string ErrorMsg =
2153 InstName +
" instruction requires the "
2154 "following SPIR-V extension: SPV_INTEL_joint_matrix";
2157 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2158 if (
Op == SPIRV::OpCooperativeMatrixPrefetchINTEL) {
2159 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixPrefetchINTEL);
2163 SPIRV::Capability::CooperativeMatrixCheckedInstructionsINTEL);
2166 case SPIRV::OpCooperativeMatrixConstructCheckedINTEL:
2167 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
2169 "instructions require the following SPIR-V extension: "
2170 "SPV_INTEL_joint_matrix",
2172 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2174 SPIRV::Capability::CooperativeMatrixCheckedInstructionsINTEL);
2176 case SPIRV::OpReadPipeBlockingALTERA:
2177 case SPIRV::OpWritePipeBlockingALTERA:
2178 if (
ST.canUseExtension(SPIRV::Extension::SPV_ALTERA_blocking_pipes)) {
2179 Reqs.
addExtension(SPIRV::Extension::SPV_ALTERA_blocking_pipes);
2183 case SPIRV::OpCooperativeMatrixGetElementCoordINTEL:
2184 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
2186 "following SPIR-V extension: SPV_INTEL_joint_matrix",
2188 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2190 SPIRV::Capability::CooperativeMatrixInvocationInstructionsINTEL);
2192 case SPIRV::OpConvertHandleToImageINTEL:
2193 case SPIRV::OpConvertHandleToSamplerINTEL:
2194 case SPIRV::OpConvertHandleToSampledImageINTEL: {
2195 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bindless_images))
2197 "instructions require the following SPIR-V extension: "
2198 "SPV_INTEL_bindless_images",
2201 SPIRV::AddressingModel::AddressingModel AddrModel = MAI.
Addr;
2203 if (
Op == SPIRV::OpConvertHandleToImageINTEL &&
2204 TyDef->
getOpcode() != SPIRV::OpTypeImage) {
2206 "OpConvertHandleToImageINTEL",
2208 }
else if (
Op == SPIRV::OpConvertHandleToSamplerINTEL &&
2209 TyDef->
getOpcode() != SPIRV::OpTypeSampler) {
2211 "OpConvertHandleToSamplerINTEL",
2213 }
else if (
Op == SPIRV::OpConvertHandleToSampledImageINTEL &&
2214 TyDef->
getOpcode() != SPIRV::OpTypeSampledImage) {
2216 "OpConvertHandleToSampledImageINTEL",
2221 if (!(Bitwidth == 32 && AddrModel == SPIRV::AddressingModel::Physical32) &&
2222 !(Bitwidth == 64 && AddrModel == SPIRV::AddressingModel::Physical64)) {
2224 "Parameter value must be a 32-bit scalar in case of "
2225 "Physical32 addressing model or a 64-bit scalar in case of "
2226 "Physical64 addressing model",
2229 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bindless_images);
2233 case SPIRV::OpSubgroup2DBlockLoadINTEL:
2234 case SPIRV::OpSubgroup2DBlockLoadTransposeINTEL:
2235 case SPIRV::OpSubgroup2DBlockLoadTransformINTEL:
2236 case SPIRV::OpSubgroup2DBlockPrefetchINTEL:
2237 case SPIRV::OpSubgroup2DBlockStoreINTEL: {
2238 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_2d_block_io))
2240 "Prefetch/Store]INTEL instructions require the "
2241 "following SPIR-V extension: SPV_INTEL_2d_block_io",
2243 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_2d_block_io);
2244 Reqs.
addCapability(SPIRV::Capability::Subgroup2DBlockIOINTEL);
2246 if (
Op == SPIRV::OpSubgroup2DBlockLoadTransposeINTEL) {
2247 Reqs.
addCapability(SPIRV::Capability::Subgroup2DBlockTransposeINTEL);
2250 if (
Op == SPIRV::OpSubgroup2DBlockLoadTransformINTEL) {
2251 Reqs.
addCapability(SPIRV::Capability::Subgroup2DBlockTransformINTEL);
2256 case SPIRV::OpKill: {
2259 case SPIRV::OpDemoteToHelperInvocation:
2260 Reqs.
addCapability(SPIRV::Capability::DemoteToHelperInvocation);
2262 if (
ST.canUseExtension(
2263 SPIRV::Extension::SPV_EXT_demote_to_helper_invocation)) {
2266 SPIRV::Extension::SPV_EXT_demote_to_helper_invocation);
2271 case SPIRV::OpSUDot:
2272 case SPIRV::OpSDotAccSat:
2273 case SPIRV::OpUDotAccSat:
2274 case SPIRV::OpSUDotAccSat:
2275 AddDotProductRequirements(
MI, Reqs, ST);
2277 case SPIRV::OpImageSampleImplicitLod:
2279 addImageOperandReqs(
MI, Reqs, ST, 4);
2281 case SPIRV::OpImageSampleExplicitLod:
2282 addImageOperandReqs(
MI, Reqs, ST, 4);
2284 case SPIRV::OpImageSampleDrefImplicitLod:
2286 addImageOperandReqs(
MI, Reqs, ST, 5);
2288 case SPIRV::OpImageSampleDrefExplicitLod:
2290 addImageOperandReqs(
MI, Reqs, ST, 5);
2292 case SPIRV::OpImageFetch:
2294 addImageOperandReqs(
MI, Reqs, ST, 4);
2296 case SPIRV::OpImageDrefGather:
2297 case SPIRV::OpImageGather:
2299 addImageOperandReqs(
MI, Reqs, ST, 5);
2301 case SPIRV::OpImageRead: {
2302 Register ImageReg =
MI.getOperand(2).getReg();
2311 if (isImageTypeWithUnknownFormat(TypeDef) &&
ST.isShader())
2312 Reqs.
addCapability(SPIRV::Capability::StorageImageReadWithoutFormat);
2315 case SPIRV::OpImageWrite: {
2316 Register ImageReg =
MI.getOperand(0).getReg();
2325 if (isImageTypeWithUnknownFormat(TypeDef) &&
ST.isShader())
2326 Reqs.
addCapability(SPIRV::Capability::StorageImageWriteWithoutFormat);
2329 case SPIRV::OpTypeStructContinuedINTEL:
2330 case SPIRV::OpConstantCompositeContinuedINTEL:
2331 case SPIRV::OpSpecConstantCompositeContinuedINTEL:
2332 case SPIRV::OpCompositeConstructContinuedINTEL: {
2333 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_long_composites))
2335 "Continued instructions require the "
2336 "following SPIR-V extension: SPV_INTEL_long_composites",
2338 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_long_composites);
2342 case SPIRV::OpArbitraryFloatEQALTERA:
2343 case SPIRV::OpArbitraryFloatGEALTERA:
2344 case SPIRV::OpArbitraryFloatGTALTERA:
2345 case SPIRV::OpArbitraryFloatLEALTERA:
2346 case SPIRV::OpArbitraryFloatLTALTERA:
2347 case SPIRV::OpArbitraryFloatCbrtALTERA:
2348 case SPIRV::OpArbitraryFloatCosALTERA:
2349 case SPIRV::OpArbitraryFloatCosPiALTERA:
2350 case SPIRV::OpArbitraryFloatExp10ALTERA:
2351 case SPIRV::OpArbitraryFloatExp2ALTERA:
2352 case SPIRV::OpArbitraryFloatExpALTERA:
2353 case SPIRV::OpArbitraryFloatExpm1ALTERA:
2354 case SPIRV::OpArbitraryFloatHypotALTERA:
2355 case SPIRV::OpArbitraryFloatLog10ALTERA:
2356 case SPIRV::OpArbitraryFloatLog1pALTERA:
2357 case SPIRV::OpArbitraryFloatLog2ALTERA:
2358 case SPIRV::OpArbitraryFloatLogALTERA:
2359 case SPIRV::OpArbitraryFloatRecipALTERA:
2360 case SPIRV::OpArbitraryFloatSinCosALTERA:
2361 case SPIRV::OpArbitraryFloatSinCosPiALTERA:
2362 case SPIRV::OpArbitraryFloatSinALTERA:
2363 case SPIRV::OpArbitraryFloatSinPiALTERA:
2364 case SPIRV::OpArbitraryFloatSqrtALTERA:
2365 case SPIRV::OpArbitraryFloatACosALTERA:
2366 case SPIRV::OpArbitraryFloatACosPiALTERA:
2367 case SPIRV::OpArbitraryFloatAddALTERA:
2368 case SPIRV::OpArbitraryFloatASinALTERA:
2369 case SPIRV::OpArbitraryFloatASinPiALTERA:
2370 case SPIRV::OpArbitraryFloatATan2ALTERA:
2371 case SPIRV::OpArbitraryFloatATanALTERA:
2372 case SPIRV::OpArbitraryFloatATanPiALTERA:
2373 case SPIRV::OpArbitraryFloatCastFromIntALTERA:
2374 case SPIRV::OpArbitraryFloatCastALTERA:
2375 case SPIRV::OpArbitraryFloatCastToIntALTERA:
2376 case SPIRV::OpArbitraryFloatDivALTERA:
2377 case SPIRV::OpArbitraryFloatMulALTERA:
2378 case SPIRV::OpArbitraryFloatPowALTERA:
2379 case SPIRV::OpArbitraryFloatPowNALTERA:
2380 case SPIRV::OpArbitraryFloatPowRALTERA:
2381 case SPIRV::OpArbitraryFloatRSqrtALTERA:
2382 case SPIRV::OpArbitraryFloatSubALTERA: {
2383 if (!
ST.canUseExtension(
2384 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_floating_point))
2386 "Floating point instructions can't be translated correctly without "
2387 "enabled SPV_ALTERA_arbitrary_precision_floating_point extension!",
2390 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_floating_point);
2392 SPIRV::Capability::ArbitraryPrecisionFloatingPointALTERA);
2395 case SPIRV::OpSubgroupMatrixMultiplyAccumulateINTEL: {
2396 if (!
ST.canUseExtension(
2397 SPIRV::Extension::SPV_INTEL_subgroup_matrix_multiply_accumulate))
2399 "OpSubgroupMatrixMultiplyAccumulateINTEL instruction requires the "
2401 "extension: SPV_INTEL_subgroup_matrix_multiply_accumulate",
2404 SPIRV::Extension::SPV_INTEL_subgroup_matrix_multiply_accumulate);
2406 SPIRV::Capability::SubgroupMatrixMultiplyAccumulateINTEL);
2409 case SPIRV::OpBitwiseFunctionINTEL: {
2410 if (!
ST.canUseExtension(
2411 SPIRV::Extension::SPV_INTEL_ternary_bitwise_function))
2413 "OpBitwiseFunctionINTEL instruction requires the following SPIR-V "
2414 "extension: SPV_INTEL_ternary_bitwise_function",
2416 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_ternary_bitwise_function);
2417 Reqs.
addCapability(SPIRV::Capability::TernaryBitwiseFunctionINTEL);
2420 case SPIRV::OpCopyMemorySized: {
2425 case SPIRV::OpPredicatedLoadINTEL:
2426 case SPIRV::OpPredicatedStoreINTEL: {
2427 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_predicated_io))
2429 "OpPredicated[Load/Store]INTEL instructions require "
2430 "the following SPIR-V extension: SPV_INTEL_predicated_io",
2432 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_predicated_io);
2436 case SPIRV::OpFAddS:
2437 case SPIRV::OpFSubS:
2438 case SPIRV::OpFMulS:
2439 case SPIRV::OpFDivS:
2440 case SPIRV::OpFRemS:
2442 case SPIRV::OpFNegate:
2443 case SPIRV::OpFAddV:
2444 case SPIRV::OpFSubV:
2445 case SPIRV::OpFMulV:
2446 case SPIRV::OpFDivV:
2447 case SPIRV::OpFRemV:
2448 case SPIRV::OpFNegateV: {
2451 if (TypeDef->
getOpcode() == SPIRV::OpTypeVector)
2453 if (isBFloat16Type(TypeDef)) {
2454 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic))
2456 "Arithmetic instructions with bfloat16 arguments require the "
2457 "following SPIR-V extension: SPV_INTEL_bfloat16_arithmetic",
2459 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic);
2460 Reqs.
addCapability(SPIRV::Capability::BFloat16ArithmeticINTEL);
2464 case SPIRV::OpOrdered:
2465 case SPIRV::OpUnordered:
2466 case SPIRV::OpFOrdEqual:
2467 case SPIRV::OpFOrdNotEqual:
2468 case SPIRV::OpFOrdLessThan:
2469 case SPIRV::OpFOrdLessThanEqual:
2470 case SPIRV::OpFOrdGreaterThan:
2471 case SPIRV::OpFOrdGreaterThanEqual:
2472 case SPIRV::OpFUnordEqual:
2473 case SPIRV::OpFUnordNotEqual:
2474 case SPIRV::OpFUnordLessThan:
2475 case SPIRV::OpFUnordLessThanEqual:
2476 case SPIRV::OpFUnordGreaterThan:
2477 case SPIRV::OpFUnordGreaterThanEqual: {
2481 if (TypeDef->
getOpcode() == SPIRV::OpTypeVector)
2483 if (isBFloat16Type(TypeDef)) {
2484 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic))
2486 "Relational instructions with bfloat16 arguments require the "
2487 "following SPIR-V extension: SPV_INTEL_bfloat16_arithmetic",
2489 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic);
2490 Reqs.
addCapability(SPIRV::Capability::BFloat16ArithmeticINTEL);
2494 case SPIRV::OpDPdxCoarse:
2495 case SPIRV::OpDPdyCoarse:
2496 case SPIRV::OpDPdxFine:
2497 case SPIRV::OpDPdyFine: {
2501 case SPIRV::OpLoopControlINTEL: {
2502 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_unstructured_loop_controls);
2503 Reqs.
addCapability(SPIRV::Capability::UnstructuredLoopControlsINTEL);
2515 SPIRV::Capability::Shader);
2527 addInstrRequirements(
MI, MAI, ST);
2530 auto Node = M.getNamedMetadata(
"spirv.ExecutionMode");
2532 bool RequireFloatControls =
false, RequireIntelFloatControls2 =
false,
2533 RequireKHRFloatControls2 =
false,
2535 bool HasIntelFloatControls2 =
2536 ST.canUseExtension(SPIRV::Extension::SPV_INTEL_float_controls2);
2537 bool HasKHRFloatControls2 =
2538 ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2);
2539 for (
unsigned i = 0; i <
Node->getNumOperands(); i++) {
2545 auto EM =
Const->getZExtValue();
2549 case SPIRV::ExecutionMode::DenormPreserve:
2550 case SPIRV::ExecutionMode::DenormFlushToZero:
2551 case SPIRV::ExecutionMode::RoundingModeRTE:
2552 case SPIRV::ExecutionMode::RoundingModeRTZ:
2553 RequireFloatControls = VerLower14;
2555 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2557 case SPIRV::ExecutionMode::RoundingModeRTPINTEL:
2558 case SPIRV::ExecutionMode::RoundingModeRTNINTEL:
2559 case SPIRV::ExecutionMode::FloatingPointModeALTINTEL:
2560 case SPIRV::ExecutionMode::FloatingPointModeIEEEINTEL:
2561 if (HasIntelFloatControls2) {
2562 RequireIntelFloatControls2 =
true;
2564 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2567 case SPIRV::ExecutionMode::FPFastMathDefault: {
2568 if (HasKHRFloatControls2) {
2569 RequireKHRFloatControls2 =
true;
2571 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2575 case SPIRV::ExecutionMode::ContractionOff:
2576 case SPIRV::ExecutionMode::SignedZeroInfNanPreserve:
2577 if (HasKHRFloatControls2) {
2578 RequireKHRFloatControls2 =
true;
2580 SPIRV::OperandCategory::ExecutionModeOperand,
2581 SPIRV::ExecutionMode::FPFastMathDefault, ST);
2584 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2589 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2594 if (RequireFloatControls &&
2595 ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls))
2597 if (RequireIntelFloatControls2)
2599 if (RequireKHRFloatControls2)
2603 if (
F.isDeclaration())
2605 if (
F.getMetadata(
"reqd_work_group_size"))
2607 SPIRV::OperandCategory::ExecutionModeOperand,
2608 SPIRV::ExecutionMode::LocalSize, ST);
2609 if (
F.getFnAttribute(
"hlsl.numthreads").isValid()) {
2611 SPIRV::OperandCategory::ExecutionModeOperand,
2612 SPIRV::ExecutionMode::LocalSize, ST);
2614 if (
F.getFnAttribute(
"enable-maximal-reconvergence").getValueAsBool()) {
2617 if (
F.getMetadata(
"work_group_size_hint"))
2619 SPIRV::OperandCategory::ExecutionModeOperand,
2620 SPIRV::ExecutionMode::LocalSizeHint, ST);
2621 if (
F.getMetadata(
"intel_reqd_sub_group_size"))
2623 SPIRV::OperandCategory::ExecutionModeOperand,
2624 SPIRV::ExecutionMode::SubgroupSize, ST);
2625 if (
F.getMetadata(
"max_work_group_size"))
2627 SPIRV::OperandCategory::ExecutionModeOperand,
2628 SPIRV::ExecutionMode::MaxWorkgroupSizeINTEL, ST);
2629 if (
F.getMetadata(
"vec_type_hint"))
2631 SPIRV::OperandCategory::ExecutionModeOperand,
2632 SPIRV::ExecutionMode::VecTypeHint, ST);
2634 if (
F.hasOptNone()) {
2635 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_optnone)) {
2638 }
else if (
ST.canUseExtension(SPIRV::Extension::SPV_EXT_optnone)) {
2648 unsigned Flags = SPIRV::FPFastMathMode::None;
2649 bool CanUseKHRFloatControls2 =
2650 ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2);
2652 Flags |= SPIRV::FPFastMathMode::NotNaN;
2654 Flags |= SPIRV::FPFastMathMode::NotInf;
2656 Flags |= SPIRV::FPFastMathMode::NSZ;
2658 Flags |= SPIRV::FPFastMathMode::AllowRecip;
2660 Flags |= SPIRV::FPFastMathMode::AllowContract;
2662 if (CanUseKHRFloatControls2)
2670 Flags |= SPIRV::FPFastMathMode::NotNaN | SPIRV::FPFastMathMode::NotInf |
2671 SPIRV::FPFastMathMode::NSZ | SPIRV::FPFastMathMode::AllowRecip |
2672 SPIRV::FPFastMathMode::AllowTransform |
2673 SPIRV::FPFastMathMode::AllowReassoc |
2674 SPIRV::FPFastMathMode::AllowContract;
2676 Flags |= SPIRV::FPFastMathMode::Fast;
2679 if (CanUseKHRFloatControls2) {
2681 assert(!(Flags & SPIRV::FPFastMathMode::Fast) &&
2682 "SPIRV::FPFastMathMode::Fast is deprecated and should not be used "
2687 assert((!(Flags & SPIRV::FPFastMathMode::AllowTransform) ||
2688 ((Flags & SPIRV::FPFastMathMode::AllowReassoc &&
2689 Flags & SPIRV::FPFastMathMode::AllowContract))) &&
2690 "SPIRV::FPFastMathMode::AllowTransform requires AllowReassoc and "
2691 "AllowContract flags to be enabled as well.");
2702 return ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2);
2705static void handleMIFlagDecoration(
2710 getSymbolicOperandRequirements(SPIRV::OperandCategory::DecorationOperand,
2711 SPIRV::Decoration::NoSignedWrap, ST, Reqs)
2714 SPIRV::Decoration::NoSignedWrap, {});
2717 getSymbolicOperandRequirements(SPIRV::OperandCategory::DecorationOperand,
2718 SPIRV::Decoration::NoUnsignedWrap, ST,
2722 SPIRV::Decoration::NoUnsignedWrap, {});
2727 TII.canUseFastMathFlags(
2728 I,
ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2)) ||
2729 (
ST.isKernel() &&
I.getOpcode() == SPIRV::OpExtInst);
2733 unsigned FMFlags = getFastMathFlags(
I, ST);
2734 if (FMFlags == SPIRV::FPFastMathMode::None) {
2737 if (FPFastMathDefaultInfoVec.
empty())
2753 assert(
I.getNumOperands() >= 3 &&
"Expected at least 3 operands");
2754 Register ResReg =
I.getOpcode() == SPIRV::OpExtInst
2755 ?
I.getOperand(1).getReg()
2756 :
I.getOperand(2).getReg();
2764 if (Ty == Elem.Ty) {
2765 FMFlags = Elem.FastMathFlags;
2766 Emit = Elem.ContractionOff || Elem.SignedZeroInfNanPreserve ||
2767 Elem.FPFastMathDefault;
2772 if (FMFlags == SPIRV::FPFastMathMode::None && !Emit)
2775 if (isFastMathModeAvailable(ST)) {
2776 Register DstReg =
I.getOperand(0).getReg();
2792 for (
auto &
MBB : *MF)
2793 for (
auto &
MI :
MBB)
2794 handleMIFlagDecoration(
MI, ST,
TII, MAI.
Reqs, GR,
2811 for (
auto &
MBB : *MF) {
2812 if (!
MBB.hasName() ||
MBB.empty())
2831 for (
auto &
MBB : *MF) {
2833 MI.setDesc(
TII.get(SPIRV::OpPhi));
2836 MI.insert(
MI.operands_begin() + 1,
2837 {MachineOperand::CreateReg(ResTypeReg, false)});
2856 SPIRV::FPFastMathMode::None);
2858 SPIRV::FPFastMathMode::None);
2860 SPIRV::FPFastMathMode::None);
2867 size_t BitWidth = Ty->getScalarSizeInBits();
2871 assert(Index >= 0 && Index < 3 &&
2872 "Expected FPFastMathDefaultInfo for half, float, or double");
2873 assert(FPFastMathDefaultInfoVec.
size() == 3 &&
2874 "Expected FPFastMathDefaultInfoVec to have exactly 3 elements");
2875 return FPFastMathDefaultInfoVec[Index];
2878static void collectFPFastMathDefaults(
const Module &M,
2881 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2))
2890 auto Node = M.getNamedMetadata(
"spirv.ExecutionMode");
2894 for (
unsigned i = 0; i <
Node->getNumOperands(); i++) {
2903 if (EM == SPIRV::ExecutionMode::FPFastMathDefault) {
2905 "Expected 4 operands for FPFastMathDefault");
2916 Info.FastMathFlags = Flags;
2917 Info.FPFastMathDefault =
true;
2918 }
else if (EM == SPIRV::ExecutionMode::ContractionOff) {
2920 "Expected no operands for ContractionOff");
2927 Info.ContractionOff =
true;
2929 }
else if (EM == SPIRV::ExecutionMode::SignedZeroInfNanPreserve) {
2931 "Expected 1 operand for SignedZeroInfNanPreserve");
2932 unsigned TargetWidth =
2941 assert(Index >= 0 && Index < 3 &&
2942 "Expected FPFastMathDefaultInfo for half, float, or double");
2943 assert(FPFastMathDefaultInfoVec.
size() == 3 &&
2944 "Expected FPFastMathDefaultInfoVec to have exactly 3 elements");
2945 FPFastMathDefaultInfoVec[Index].SignedZeroInfNanPreserve =
true;
2956 SPIRVTargetMachine &TM =
2960 TII = ST->getInstrInfo();
2966 patchPhis(M, GR, *TII, MMI);
2968 addMBBNames(M, *TII, MMI, *ST,
MAI);
2969 collectFPFastMathDefaults(M,
MAI, *ST);
2970 addDecorations(M, *TII, MMI, *ST,
MAI, GR);
2972 collectReqs(M,
MAI, MMI, *ST);
2976 collectReqs(M,
MAI, MMI, *ST);
2977 collectDeclarations(M);
2980 numberRegistersGlobally(M);
2983 processOtherInstrs(M);
2987 MAI.Reqs.addCapability(SPIRV::Capability::Linkage);
2990 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
bool isTypeIntN(unsigned N=0) 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