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) {
351 if (GR->getFunctionDefinitionByUse(&
MI.getOperand(0))) {
353 unsigned UseOp =
UseMI.getOpcode();
354 if (UseOp == SPIRV::OpConstantFunctionPointerINTEL ||
355 UseOp == SPIRV::OpEnqueueKernel) {
356 MAI.setSkipEmission(&
MI);
362 if (
UseMI.getOpcode() != SPIRV::OpConstantFunctionPointerINTEL)
368 MAI.setSkipEmission(&
MI);
372 return TII->isTypeDeclInstr(
MI) || TII->isConstantInstr(
MI) ||
373 TII->isInlineAsmDefInstr(
MI);
382void SPIRVModuleAnalysis::visitFunPtrUse(
385 std::map<const Value *, unsigned> &GlobalToGReg,
387 const MachineOperand *OpFunDef = GR->getFunctionDefinitionByUse(FunPtrOp);
390 const MachineInstr *OpDefMI = OpFunDef->
getParent();
393 const MachineRegisterInfo &FunDefMRI = FunDefMF->
getRegInfo();
395 visitDecl(FunDefMRI, SignatureToGReg, GlobalToGReg, FunDefMF, *OpDefMI);
397 }
while (OpDefMI && (OpDefMI->
getOpcode() == SPIRV::OpFunction ||
398 OpDefMI->
getOpcode() == SPIRV::OpFunctionParameter));
400 MCRegister GlobalFunDefReg =
401 MAI.getRegisterAlias(FunDefMF, OpFunDef->
getReg());
403 "Function definition must refer to a global register");
404 MAI.setRegisterAlias(MF, OpReg, GlobalFunDefReg);
409void SPIRVModuleAnalysis::visitDecl(
411 std::map<const Value *, unsigned> &GlobalToGReg,
const MachineFunction *MF,
413 unsigned Opcode =
MI.getOpcode();
416 for (
const MachineOperand &MO :
MI.operands()) {
421 if (Opcode == SPIRV::OpConstantFunctionPointerINTEL &&
423 visitFunPtrUse(OpReg, &
MI.getOperand(2), SignatureToGReg, GlobalToGReg,
428 if (
MAI.hasRegisterAlias(MF, MO.
getReg()))
432 if (isDeclSection(MRI, *OpDefMI))
433 visitDecl(MRI, SignatureToGReg, GlobalToGReg, MF, *OpDefMI);
439 dbgs() <<
"Unexpectedly, no unique definition for the operand ";
441 dbgs() <<
"\nInstruction: ";
446 "No unique definition is found for the virtual register");
450 bool IsFunDef =
false;
451 if (TII->isSpecConstantInstr(
MI)) {
452 GReg =
MAI.getNextIDRegister();
454 }
else if (Opcode == SPIRV::OpFunction ||
455 Opcode == SPIRV::OpFunctionParameter) {
456 GReg = handleFunctionOrParameter(MF,
MI, GlobalToGReg, IsFunDef);
457 }
else if (Opcode == SPIRV::OpTypeStruct ||
458 Opcode == SPIRV::OpConstantComposite) {
459 GReg = handleTypeDeclOrConstant(
MI, SignatureToGReg);
460 const MachineInstr *NextInstr =
MI.getNextNode();
462 ((Opcode == SPIRV::OpTypeStruct &&
463 NextInstr->
getOpcode() == SPIRV::OpTypeStructContinuedINTEL) ||
464 (Opcode == SPIRV::OpConstantComposite &&
466 SPIRV::OpConstantCompositeContinuedINTEL))) {
467 MCRegister Tmp = handleTypeDeclOrConstant(*NextInstr, SignatureToGReg);
469 MAI.setSkipEmission(NextInstr);
472 }
else if (TII->isTypeDeclInstr(
MI) || TII->isConstantInstr(
MI) ||
473 TII->isInlineAsmDefInstr(
MI)) {
474 GReg = handleTypeDeclOrConstant(
MI, SignatureToGReg);
475 }
else if (Opcode == SPIRV::OpVariable) {
476 GReg = handleVariable(MF,
MI, GlobalToGReg);
479 dbgs() <<
"\nInstruction: ";
485 MAI.setRegisterAlias(MF,
MI.getOperand(0).getReg(), GReg);
487 MAI.setSkipEmission(&
MI);
490MCRegister SPIRVModuleAnalysis::handleFunctionOrParameter(
492 std::map<const Value *, unsigned> &GlobalToGReg,
bool &IsFunDef) {
493 const Value *GObj = GR->getGlobalObject(MF,
MI.getOperand(0).getReg());
494 assert(GObj &&
"Unregistered global definition");
498 assert(
F &&
"Expected a reference to a function or an argument");
499 IsFunDef = !
F->isDeclaration();
500 auto [It,
Inserted] = GlobalToGReg.try_emplace(GObj);
503 MCRegister GReg =
MAI.getNextIDRegister();
511SPIRVModuleAnalysis::handleTypeDeclOrConstant(
const MachineInstr &
MI,
514 auto [It,
Inserted] = SignatureToGReg.try_emplace(MISign);
517 MCRegister GReg =
MAI.getNextIDRegister();
523MCRegister SPIRVModuleAnalysis::handleVariable(
525 std::map<const Value *, unsigned> &GlobalToGReg) {
526 MAI.GlobalVarList.push_back(&
MI);
527 const Value *GObj = GR->getGlobalObject(MF,
MI.getOperand(0).getReg());
528 assert(GObj &&
"Unregistered global definition");
529 auto [It,
Inserted] = GlobalToGReg.try_emplace(GObj);
532 MCRegister GReg =
MAI.getNextIDRegister();
536 MAI.GlobalObjMap[GV] = GReg;
540void SPIRVModuleAnalysis::collectDeclarations(
const Module &M) {
542 std::map<const Value *, unsigned> GlobalToGReg;
543 for (
const Function &
F : M) {
544 MachineFunction *MF = MMI->getMachineFunction(
F);
547 const MachineRegisterInfo &MRI = MF->
getRegInfo();
548 unsigned PastHeader = 0;
549 for (MachineBasicBlock &
MBB : *MF) {
550 for (MachineInstr &
MI :
MBB) {
551 if (
MI.getNumOperands() == 0)
553 unsigned Opcode =
MI.getOpcode();
554 if (Opcode == SPIRV::OpFunction) {
555 if (PastHeader == 0) {
559 }
else if (Opcode == SPIRV::OpFunctionParameter) {
562 }
else if (PastHeader > 0) {
566 const MachineOperand &DefMO =
MI.getOperand(0);
568 case SPIRV::OpExtension:
569 MAI.Reqs.addExtension(SPIRV::Extension::Extension(DefMO.
getImm()));
570 MAI.setSkipEmission(&
MI);
572 case SPIRV::OpCapability:
573 MAI.Reqs.addCapability(SPIRV::Capability::Capability(DefMO.
getImm()));
574 MAI.setSkipEmission(&
MI);
579 if (DefMO.
isReg() && isDeclSection(MRI,
MI) &&
580 !
MAI.hasRegisterAlias(MF, DefMO.
getReg()))
581 visitDecl(MRI, SignatureToGReg, GlobalToGReg, MF,
MI);
585 if (Opcode == SPIRV::OpEnqueueKernel &&
MI.getNumOperands() > 8) {
586 const MachineOperand &InvokeMO =
MI.getOperand(8);
587 if (InvokeMO.
isReg()) {
589 if (!
MAI.hasRegisterAlias(MF, InvokeReg)) {
590 if (
const MachineInstr *
DefMI =
594 if (GR->getFunctionDefinitionByUse(FunPtrOp))
595 visitFunPtrUse(InvokeReg, FunPtrOp, SignatureToGReg,
614 if (
MI.getOpcode() == SPIRV::OpDecorate) {
616 auto Dec =
MI.getOperand(1).getImm();
617 if (Dec == SPIRV::Decoration::LinkageAttributes) {
618 auto Lnk =
MI.getOperand(
MI.getNumOperands() - 1).getImm();
619 if (Lnk == SPIRV::LinkageType::Import) {
624 MAI.GlobalObjMap[ImportedFunc] =
625 MAI.getRegisterAlias(
MI.getMF(), Target);
628 }
else if (
MI.getOpcode() == SPIRV::OpFunction) {
631 MCRegister GlobalReg =
MAI.getRegisterAlias(
MI.getMF(),
Reg);
633 MAI.GlobalObjMap[
F] = GlobalReg;
645 auto FoundMI = IS.insert(std::move(MISign));
646 if (!FoundMI.second) {
647 if (
MI.getOpcode() == SPIRV::OpDecorate) {
649 "Decoration instructions must have at least 2 operands");
651 "Only OpDecorate instructions can be duplicates");
656 if (
MI.getOperand(1).getImm() != SPIRV::Decoration::FPFastMathMode)
661 if (instrToSignature(*OrigMI, MAI,
true) == MISign) {
662 assert(OrigMI->getNumOperands() ==
MI.getNumOperands() &&
663 "Original instruction must have the same number of operands");
665 OrigMI->getNumOperands() == 3 &&
666 "FPFastMathMode decoration must have 3 operands for OpDecorate");
667 unsigned OrigFlags = OrigMI->getOperand(2).getImm();
668 unsigned NewFlags =
MI.getOperand(2).getImm();
669 if (OrigFlags == NewFlags)
673 unsigned FinalFlags = OrigFlags | NewFlags;
675 <<
"Warning: Conflicting FPFastMathMode decoration flags "
677 << *OrigMI <<
"Original flags: " << OrigFlags
678 <<
", new flags: " << NewFlags
679 <<
". They will be merged on a best effort basis, but not "
680 "validated. Final flags: "
681 << FinalFlags <<
"\n";
688 assert(
false &&
"No original instruction found for the duplicate "
689 "OpDecorate, but we found one in IS.");
702void SPIRVModuleAnalysis::processOtherInstrs(
const Module &M) {
704 for (
const Function &
F : M) {
705 if (
F.isDeclaration())
707 MachineFunction *MF = MMI->getMachineFunction(
F);
710 for (MachineBasicBlock &
MBB : *MF)
711 for (MachineInstr &
MI :
MBB) {
712 if (
MAI.getSkipEmission(&
MI))
714 const unsigned OpCode =
MI.getOpcode();
715 if (OpCode == SPIRV::OpString) {
717 }
else if (OpCode == SPIRV::OpExtInst &&
MI.getOperand(2).isImm() &&
718 MI.getOperand(2).getImm() ==
719 SPIRV::InstructionSet::
720 NonSemantic_Shader_DebugInfo_100) {
727 MachineOperand Ins =
MI.getOperand(3);
728 namespace NS = SPIRV::NonSemanticExtInst;
729 static constexpr int64_t GlobalNonSemanticDITy[] = {
730 NS::DebugSource, NS::DebugCompilationUnit, NS::DebugInfoNone,
731 NS::DebugTypeBasic, NS::DebugTypePointer};
732 bool IsGlobalDI =
false;
733 for (
unsigned Idx = 0; Idx < std::size(GlobalNonSemanticDITy); ++Idx)
734 IsGlobalDI |= Ins.
getImm() == GlobalNonSemanticDITy[Idx];
737 }
else if (OpCode == SPIRV::OpName || OpCode == SPIRV::OpMemberName) {
739 }
else if (OpCode == SPIRV::OpEntryPoint) {
741 }
else if (TII->isAliasingInstr(
MI)) {
743 }
else if (TII->isDecorationInstr(
MI)) {
745 collectFuncNames(
MI, &
F);
746 }
else if (TII->isConstantInstr(
MI)) {
750 }
else if (OpCode == SPIRV::OpFunction) {
751 collectFuncNames(
MI, &
F);
752 }
else if (OpCode == SPIRV::OpTypeForwardPointer) {
762void SPIRVModuleAnalysis::numberRegistersGlobally(
const Module &M) {
763 for (
const Function &
F : M) {
764 if (
F.isDeclaration())
766 MachineFunction *MF = MMI->getMachineFunction(
F);
768 for (MachineBasicBlock &
MBB : *MF) {
769 for (MachineInstr &
MI :
MBB) {
770 for (MachineOperand &
Op :
MI.operands()) {
774 if (
MAI.hasRegisterAlias(MF,
Reg))
776 MCRegister NewReg =
MAI.getNextIDRegister();
777 MAI.setRegisterAlias(MF,
Reg, NewReg);
779 if (
MI.getOpcode() != SPIRV::OpExtInst)
781 auto Set =
MI.getOperand(2).getImm();
782 auto [It,
Inserted] =
MAI.ExtInstSetMap.try_emplace(Set);
784 It->second =
MAI.getNextIDRegister();
792 SPIRV::OperandCategory::OperandCategory Category, uint32_t i,
794 addRequirements(getSymbolicOperandRequirements(Category, i, ST, *
this));
797void SPIRV::RequirementHandler::recursiveAddCapabilities(
799 for (
const auto &Cap : ToPrune) {
803 recursiveAddCapabilities(ImplicitDecls);
808 for (
const auto &Cap : ToAdd) {
809 bool IsNewlyInserted = AllCaps.insert(Cap).second;
810 if (!IsNewlyInserted)
814 recursiveAddCapabilities(ImplicitDecls);
815 MinimalCaps.push_back(Cap);
820 const SPIRV::Requirements &Req) {
824 if (Req.
Cap.has_value())
825 addCapabilities({Req.
Cap.value()});
827 addExtensions(Req.
Exts);
830 if (!MaxVersion.empty() && Req.
MinVer > MaxVersion) {
832 <<
" and <= " << MaxVersion <<
"\n");
836 if (MinVersion.empty() || Req.
MinVer > MinVersion)
841 if (!MinVersion.empty() && Req.
MaxVer < MinVersion) {
843 <<
" and >= " << MinVersion <<
"\n");
847 if (MaxVersion.empty() || Req.
MaxVer < MaxVersion)
853 const SPIRVSubtarget &ST)
const {
855 bool IsSatisfiable =
true;
856 auto TargetVer =
ST.getSPIRVVersion();
858 if (!MaxVersion.empty() && !TargetVer.empty() && MaxVersion < TargetVer) {
860 dbgs() <<
"Target SPIR-V version too high for required features\n"
861 <<
"Required max version: " << MaxVersion <<
" target version "
862 << TargetVer <<
"\n");
863 IsSatisfiable =
false;
866 if (!MinVersion.empty() && !TargetVer.empty() && MinVersion > TargetVer) {
867 LLVM_DEBUG(
dbgs() <<
"Target SPIR-V version too low for required features\n"
868 <<
"Required min version: " << MinVersion
869 <<
" target version " << TargetVer <<
"\n");
870 IsSatisfiable =
false;
873 if (!MinVersion.empty() && !MaxVersion.empty() && MinVersion > MaxVersion) {
876 <<
"Version is too low for some features and too high for others.\n"
877 <<
"Required SPIR-V min version: " << MinVersion
878 <<
" required SPIR-V max version " << MaxVersion <<
"\n");
879 IsSatisfiable =
false;
882 AvoidCapabilitiesSet AvoidCaps;
884 AvoidCaps.
S.
insert(SPIRV::Capability::Shader);
886 AvoidCaps.
S.
insert(SPIRV::Capability::Kernel);
888 for (
auto Cap : MinimalCaps) {
889 if (AvailableCaps.contains(Cap) && !AvoidCaps.
S.
contains(Cap))
893 OperandCategory::CapabilityOperand, Cap)
895 IsSatisfiable =
false;
898 for (
auto Ext : AllExtensions) {
899 if (
ST.canUseExtension(Ext))
903 OperandCategory::ExtensionOperand, Ext)
905 IsSatisfiable =
false;
914 for (
const auto Cap : ToAdd)
915 if (AvailableCaps.insert(Cap).second)
917 SPIRV::OperandCategory::CapabilityOperand, Cap));
921 const Capability::Capability
ToRemove,
922 const Capability::Capability IfPresent) {
923 if (AllCaps.contains(IfPresent))
931 addAvailableCaps({Capability::Shader, Capability::Linkage, Capability::Int8,
934 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 3)))
936 Capability::GroupNonUniformVote,
937 Capability::GroupNonUniformArithmetic,
938 Capability::GroupNonUniformBallot,
939 Capability::GroupNonUniformClustered,
940 Capability::GroupNonUniformShuffle,
941 Capability::GroupNonUniformShuffleRelative,
942 Capability::GroupNonUniformQuad});
944 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 6)))
946 Capability::DotProductInput4x8Bit,
947 Capability::DotProductInput4x8BitPacked,
948 Capability::DemoteToHelperInvocation});
951 for (
auto Extension :
ST.getAllAvailableExtensions()) {
957 if (!
ST.isShader()) {
958 initAvailableCapabilitiesForOpenCL(ST);
963 initAvailableCapabilitiesForVulkan(ST);
970void RequirementHandler::initAvailableCapabilitiesForOpenCL(
971 const SPIRVSubtarget &ST) {
974 Capability::Kernel, Capability::Vector16,
975 Capability::Groups, Capability::GenericPointer,
976 Capability::StorageImageWriteWithoutFormat,
977 Capability::StorageImageReadWithoutFormat});
978 if (
ST.hasOpenCLFullProfile())
980 if (
ST.hasOpenCLImageSupport()) {
982 Capability::Image1D, Capability::SampledBuffer,
983 Capability::ImageBuffer});
984 if (
ST.isAtLeastOpenCLVer(VersionTuple(2, 0)))
987 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 1)) &&
988 ST.isAtLeastOpenCLVer(VersionTuple(2, 2)))
990 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 4)))
991 addAvailableCaps({Capability::DenormPreserve, Capability::DenormFlushToZero,
992 Capability::SignedZeroInfNanPreserve,
993 Capability::RoundingModeRTE,
994 Capability::RoundingModeRTZ});
1001void RequirementHandler::initAvailableCapabilitiesForVulkan(
1002 const SPIRVSubtarget &ST) {
1006 Capability::Float16,
1007 Capability::Float64,
1008 Capability::GroupNonUniform,
1009 Capability::Image1D,
1010 Capability::SampledBuffer,
1011 Capability::ImageBuffer,
1012 Capability::UniformBufferArrayDynamicIndexing,
1013 Capability::SampledImageArrayDynamicIndexing,
1014 Capability::StorageBufferArrayDynamicIndexing,
1015 Capability::StorageImageArrayDynamicIndexing,
1016 Capability::DerivativeControl,
1018 Capability::ImageQuery,
1019 Capability::ImageGatherExtended,
1020 Capability::Addresses,
1021 Capability::VulkanMemoryModelKHR,
1022 Capability::StorageImageExtendedFormats,
1023 Capability::StorageImageMultisample,
1024 Capability::ImageMSArray});
1027 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 5))) {
1029 {Capability::ShaderNonUniformEXT, Capability::RuntimeDescriptorArrayEXT,
1030 Capability::InputAttachmentArrayDynamicIndexingEXT,
1031 Capability::UniformTexelBufferArrayDynamicIndexingEXT,
1032 Capability::StorageTexelBufferArrayDynamicIndexingEXT,
1033 Capability::UniformBufferArrayNonUniformIndexingEXT,
1034 Capability::SampledImageArrayNonUniformIndexingEXT,
1035 Capability::StorageBufferArrayNonUniformIndexingEXT,
1036 Capability::StorageImageArrayNonUniformIndexingEXT,
1037 Capability::InputAttachmentArrayNonUniformIndexingEXT,
1038 Capability::UniformTexelBufferArrayNonUniformIndexingEXT,
1039 Capability::StorageTexelBufferArrayNonUniformIndexingEXT});
1043 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 6)))
1045 Capability::StorageImageReadWithoutFormat});
1053static void addOpDecorateReqs(
const MachineInstr &
MI,
unsigned DecIndex,
1056 int64_t DecOp =
MI.getOperand(DecIndex).getImm();
1057 auto Dec =
static_cast<SPIRV::Decoration::Decoration
>(DecOp);
1059 SPIRV::OperandCategory::DecorationOperand, Dec, ST, Reqs));
1061 if (Dec == SPIRV::Decoration::BuiltIn) {
1062 int64_t BuiltInOp =
MI.getOperand(DecIndex + 1).getImm();
1063 auto BuiltIn =
static_cast<SPIRV::BuiltIn::BuiltIn
>(BuiltInOp);
1065 SPIRV::OperandCategory::BuiltInOperand, BuiltIn, ST, Reqs));
1066 }
else if (Dec == SPIRV::Decoration::LinkageAttributes) {
1067 int64_t LinkageOp =
MI.getOperand(
MI.getNumOperands() - 1).getImm();
1068 SPIRV::LinkageType::LinkageType LnkType =
1069 static_cast<SPIRV::LinkageType::LinkageType
>(LinkageOp);
1070 if (LnkType == SPIRV::LinkageType::LinkOnceODR)
1071 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_linkonce_odr);
1072 else if (LnkType == SPIRV::LinkageType::WeakAMD) {
1073 Reqs.
addExtension(SPIRV::Extension::SPV_AMD_weak_linkage);
1076 }
else if (Dec == SPIRV::Decoration::CacheControlLoadINTEL ||
1077 Dec == SPIRV::Decoration::CacheControlStoreINTEL) {
1078 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_cache_controls);
1079 }
else if (Dec == SPIRV::Decoration::HostAccessINTEL) {
1080 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_global_variable_host_access);
1081 }
else if (Dec == SPIRV::Decoration::InitModeINTEL ||
1082 Dec == SPIRV::Decoration::ImplementInRegisterMapINTEL) {
1084 SPIRV::Extension::SPV_INTEL_global_variable_fpga_decorations);
1085 }
else if (Dec == SPIRV::Decoration::NonUniformEXT) {
1087 }
else if (Dec == SPIRV::Decoration::FPMaxErrorDecorationINTEL) {
1089 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_fp_max_error);
1090 }
else if (Dec == SPIRV::Decoration::FPFastMathMode) {
1091 if (
ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2)) {
1093 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_float_controls2);
1102 assert(
MI.getNumOperands() >= 8 &&
"Insufficient operands for OpTypeImage");
1105 int64_t ImgFormatOp =
MI.getOperand(7).getImm();
1106 auto ImgFormat =
static_cast<SPIRV::ImageFormat::ImageFormat
>(ImgFormatOp);
1110 bool IsArrayed =
MI.getOperand(4).getImm() == 1;
1111 bool IsMultisampled =
MI.getOperand(5).getImm() == 1;
1112 bool NoSampler =
MI.getOperand(6).getImm() == 2;
1115 switch (
MI.getOperand(2).getImm()) {
1116 case SPIRV::Dim::DIM_1D:
1118 : SPIRV::Capability::Sampled1D);
1120 case SPIRV::Dim::DIM_2D:
1121 if (IsMultisampled && NoSampler)
1123 if (IsMultisampled && IsArrayed)
1126 case SPIRV::Dim::DIM_3D:
1128 case SPIRV::Dim::DIM_Cube:
1132 : SPIRV::Capability::SampledCubeArray);
1134 case SPIRV::Dim::DIM_Rect:
1136 : SPIRV::Capability::SampledRect);
1138 case SPIRV::Dim::DIM_Buffer:
1140 : SPIRV::Capability::SampledBuffer);
1142 case SPIRV::Dim::DIM_SubpassData:
1154 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_shader_image_int64);
1158 if (!
ST.isShader()) {
1159 if (
MI.getNumOperands() > 8 &&
1160 MI.getOperand(8).getImm() == SPIRV::AccessQualifier::ReadWrite)
1169 TypeDef->
getOpcode() == SPIRV::OpTypeFloat &&
1175#define ATOM_FLT_REQ_EXT_MSG(ExtName) \
1176 "The atomic float instruction requires the following SPIR-V " \
1177 "extension: SPV_EXT_shader_atomic_float" ExtName
1178static void AddAtomicVectorFloatRequirements(
const MachineInstr &
MI,
1182 MI.getMF()->getRegInfo().getVRegDef(
MI.getOperand(1).getReg());
1185 if (Rank != 2 && Rank != 4)
1187 "must be a 2-component or 4 component vector");
1192 if (EltTypeDef->
getOpcode() != SPIRV::OpTypeFloat ||
1195 "The element type for the result type of an atomic vector float "
1196 "instruction must be a 16-bit floating-point scalar");
1200 if (isBFloat16Type(EltTypeDef) &&
1203 "The element type for the result type of an atomic vector float "
1204 "instruction cannot be a bfloat16 scalar");
1205 if (!
ST.canUseExtension(SPIRV::Extension::SPV_NV_shader_atomic_fp16_vector))
1207 "The atomic float16 vector instruction requires the following SPIR-V "
1208 "extension: SPV_NV_shader_atomic_fp16_vector");
1210 Reqs.
addExtension(SPIRV::Extension::SPV_NV_shader_atomic_fp16_vector);
1211 Reqs.
addCapability(SPIRV::Capability::AtomicFloat16VectorNV);
1218 "Expect register operand in atomic float instruction");
1219 Register TypeReg =
MI.getOperand(1).getReg();
1222 if (TypeDef->
getOpcode() == SPIRV::OpTypeVector)
1223 return AddAtomicVectorFloatRequirements(
MI, Reqs, ST);
1225 if (TypeDef->
getOpcode() != SPIRV::OpTypeFloat)
1227 "floating-point type scalar");
1230 unsigned Op =
MI.getOpcode();
1231 if (
Op == SPIRV::OpAtomicFAddEXT) {
1232 if (!
ST.canUseExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float_add))
1234 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float_add);
1237 if (isBFloat16Type(TypeDef)) {
1238 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics))
1240 "The atomic bfloat16 instruction requires the following SPIR-V "
1241 "extension: SPV_INTEL_16bit_atomics",
1243 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics);
1244 Reqs.
addCapability(SPIRV::Capability::AtomicBFloat16AddINTEL);
1246 if (!
ST.canUseExtension(
1247 SPIRV::Extension::SPV_EXT_shader_atomic_float16_add))
1249 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float16_add);
1261 "Unexpected floating-point type width in atomic float instruction");
1264 if (!
ST.canUseExtension(
1265 SPIRV::Extension::SPV_EXT_shader_atomic_float_min_max))
1267 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float_min_max);
1270 if (isBFloat16Type(TypeDef)) {
1271 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics))
1273 "The atomic bfloat16 instruction requires the following SPIR-V "
1274 "extension: SPV_INTEL_16bit_atomics",
1276 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics);
1277 Reqs.
addCapability(SPIRV::Capability::AtomicBFloat16MinMaxINTEL);
1279 Reqs.
addCapability(SPIRV::Capability::AtomicFloat16MinMaxEXT);
1283 Reqs.
addCapability(SPIRV::Capability::AtomicFloat32MinMaxEXT);
1286 Reqs.
addCapability(SPIRV::Capability::AtomicFloat64MinMaxEXT);
1290 "Unexpected floating-point type width in atomic float instruction");
1296 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1300 return Dim == SPIRV::Dim::DIM_Buffer && Sampled == 1;
1304 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1308 return Dim == SPIRV::Dim::DIM_Buffer && Sampled == 2;
1312 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1316 return Dim != SPIRV::Dim::DIM_Buffer && Sampled == 1;
1320 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1324 return Dim == SPIRV::Dim::DIM_SubpassData && Sampled == 2;
1328 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1332 return Dim != SPIRV::Dim::DIM_Buffer && Sampled == 2;
1335bool isCombinedImageSampler(
MachineInstr *SampledImageInst) {
1336 if (SampledImageInst->
getOpcode() != SPIRV::OpTypeSampledImage)
1342 return isSampledImage(ImageInst);
1347 if (
MI.getOpcode() != SPIRV::OpDecorate)
1351 if (Dec == SPIRV::Decoration::NonUniformEXT)
1369 if (
StorageClass != SPIRV::StorageClass::StorageClass::UniformConstant &&
1370 StorageClass != SPIRV::StorageClass::StorageClass::Uniform &&
1371 StorageClass != SPIRV::StorageClass::StorageClass::StorageBuffer) {
1376 hasNonUniformDecoration(
Instr.getOperand(0).getReg(), MRI);
1378 auto FirstIndexReg =
Instr.getOperand(3).getReg();
1379 bool FirstIndexIsConstant =
1382 if (
StorageClass == SPIRV::StorageClass::StorageClass::StorageBuffer) {
1385 SPIRV::Capability::StorageBufferArrayNonUniformIndexingEXT);
1386 else if (!FirstIndexIsConstant)
1388 SPIRV::Capability::StorageBufferArrayDynamicIndexing);
1394 if (PointeeType->
getOpcode() != SPIRV::OpTypeImage &&
1395 PointeeType->
getOpcode() != SPIRV::OpTypeSampledImage &&
1396 PointeeType->
getOpcode() != SPIRV::OpTypeSampler) {
1400 if (isUniformTexelBuffer(PointeeType)) {
1403 SPIRV::Capability::UniformTexelBufferArrayNonUniformIndexingEXT);
1404 else if (!FirstIndexIsConstant)
1406 SPIRV::Capability::UniformTexelBufferArrayDynamicIndexingEXT);
1407 }
else if (isInputAttachment(PointeeType)) {
1410 SPIRV::Capability::InputAttachmentArrayNonUniformIndexingEXT);
1411 else if (!FirstIndexIsConstant)
1413 SPIRV::Capability::InputAttachmentArrayDynamicIndexingEXT);
1414 }
else if (isStorageTexelBuffer(PointeeType)) {
1417 SPIRV::Capability::StorageTexelBufferArrayNonUniformIndexingEXT);
1418 else if (!FirstIndexIsConstant)
1420 SPIRV::Capability::StorageTexelBufferArrayDynamicIndexingEXT);
1421 }
else if (isSampledImage(PointeeType) ||
1422 isCombinedImageSampler(PointeeType) ||
1423 PointeeType->
getOpcode() == SPIRV::OpTypeSampler) {
1426 SPIRV::Capability::SampledImageArrayNonUniformIndexingEXT);
1427 else if (!FirstIndexIsConstant)
1429 SPIRV::Capability::SampledImageArrayDynamicIndexing);
1430 }
else if (isStorageImage(PointeeType)) {
1433 SPIRV::Capability::StorageImageArrayNonUniformIndexingEXT);
1434 else if (!FirstIndexIsConstant)
1436 SPIRV::Capability::StorageImageArrayDynamicIndexing);
1440static bool isImageTypeWithUnknownFormat(
SPIRVTypeInst TypeInst) {
1441 if (TypeInst->
getOpcode() != SPIRV::OpTypeImage)
1450 if (
ST.canUseExtension(SPIRV::Extension::SPV_KHR_integer_dot_product))
1451 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_integer_dot_product);
1455 assert(
MI.getOperand(2).isReg() &&
"Unexpected operand in dot");
1459 assert(
Input->getOperand(1).isReg() &&
"Unexpected operand in dot input");
1463 if (TypeDef->
getOpcode() == SPIRV::OpTypeInt) {
1465 Reqs.
addCapability(SPIRV::Capability::DotProductInput4x8BitPacked);
1466 }
else if (TypeDef->
getOpcode() == SPIRV::OpTypeVector) {
1472 "Dot operand of 8-bit integer type requires 4 components");
1473 Reqs.
addCapability(SPIRV::Capability::DotProductInput4x8Bit);
1489 unsigned AddrSpace = ASOp.
getImm();
1490 if (AddrSpace != SPIRV::StorageClass::UniformConstant) {
1491 if (!
ST.canUseExtension(
1493 SPV_EXT_relaxed_printf_string_address_space)) {
1495 "required because printf uses a format string not "
1496 "in constant address space.",
1500 SPIRV::Extension::SPV_EXT_relaxed_printf_string_address_space);
1509 if (
MI.getNumOperands() <=
OpIdx)
1513 if (Mask & (1U <<
I))
1522 unsigned Op =
MI.getOpcode();
1524 case SPIRV::OpMemoryModel: {
1525 int64_t Addr =
MI.getOperand(0).getImm();
1528 int64_t Mem =
MI.getOperand(1).getImm();
1533 case SPIRV::OpEntryPoint: {
1534 int64_t
Exe =
MI.getOperand(0).getImm();
1539 case SPIRV::OpExecutionMode:
1540 case SPIRV::OpExecutionModeId: {
1541 int64_t
Exe =
MI.getOperand(1).getImm();
1546 case SPIRV::OpTypeMatrix:
1549 case SPIRV::OpTypeInt: {
1550 unsigned BitWidth =
MI.getOperand(1).getImm();
1558 ST.canUseExtension(SPIRV::Extension::SPV_INTEL_int4)) {
1562 if (!
ST.canUseExtension(
1563 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_integers))
1565 "OpTypeInt type with a width other than 8, 16, 32 or 64 bits "
1566 "requires the following SPIR-V extension: "
1567 "SPV_ALTERA_arbitrary_precision_integers");
1569 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_integers);
1570 Reqs.
addCapability(SPIRV::Capability::ArbitraryPrecisionIntegersALTERA);
1574 case SPIRV::OpDot: {
1577 if (isBFloat16Type(TypeDef))
1578 Reqs.
addCapability(SPIRV::Capability::BFloat16DotProductKHR);
1581 case SPIRV::OpTypeFloat: {
1582 unsigned BitWidth =
MI.getOperand(1).getImm();
1586 if (isBFloat16Type(&
MI)) {
1587 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_bfloat16))
1589 "following SPIR-V extension: SPV_KHR_bfloat16",
1599 case SPIRV::OpTypeVector: {
1600 unsigned NumComponents =
MI.getOperand(2).getImm();
1601 if (NumComponents == 8 || NumComponents == 16)
1607 if (ElemTypeDef->
getOpcode() == SPIRV::OpTypePointer &&
1608 ST.canUseExtension(SPIRV::Extension::SPV_INTEL_masked_gather_scatter)) {
1609 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_masked_gather_scatter);
1610 Reqs.
addCapability(SPIRV::Capability::MaskedGatherScatterINTEL);
1614 case SPIRV::OpTypePointer: {
1615 auto SC =
MI.getOperand(1).getImm();
1626 (TypeDef->
getOpcode() == SPIRV::OpTypeFloat) &&
1631 case SPIRV::OpExtInst: {
1632 if (
MI.getOperand(2).getImm() ==
1633 static_cast<int64_t
>(
1634 SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100)) {
1635 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_non_semantic_info);
1638 if (
MI.getOperand(3).getImm() ==
1639 static_cast<int64_t
>(SPIRV::OpenCLExtInst::printf)) {
1640 addPrintfRequirements(
MI, Reqs, ST);
1647 case SPIRV::OpAliasDomainDeclINTEL:
1648 case SPIRV::OpAliasScopeDeclINTEL:
1649 case SPIRV::OpAliasScopeListDeclINTEL: {
1650 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_memory_access_aliasing);
1651 Reqs.
addCapability(SPIRV::Capability::MemoryAccessAliasingINTEL);
1654 case SPIRV::OpBitReverse:
1655 case SPIRV::OpBitFieldInsert:
1656 case SPIRV::OpBitFieldSExtract:
1657 case SPIRV::OpBitFieldUExtract:
1658 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_bit_instructions)) {
1662 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_bit_instructions);
1665 case SPIRV::OpTypeRuntimeArray:
1668 case SPIRV::OpTypeOpaque:
1669 case SPIRV::OpTypeEvent:
1672 case SPIRV::OpTypePipe:
1673 case SPIRV::OpTypeReserveId:
1676 case SPIRV::OpTypeDeviceEvent:
1677 case SPIRV::OpTypeQueue:
1678 case SPIRV::OpBuildNDRange:
1679 case SPIRV::OpEnqueueKernel:
1682 case SPIRV::OpDecorate:
1683 case SPIRV::OpDecorateId:
1684 case SPIRV::OpDecorateString:
1685 addOpDecorateReqs(
MI, 1, Reqs, ST);
1687 case SPIRV::OpMemberDecorate:
1688 case SPIRV::OpMemberDecorateString:
1689 addOpDecorateReqs(
MI, 2, Reqs, ST);
1691 case SPIRV::OpInBoundsPtrAccessChain:
1694 case SPIRV::OpConstantSampler:
1697 case SPIRV::OpInBoundsAccessChain:
1698 case SPIRV::OpAccessChain:
1699 addOpAccessChainReqs(
MI, Reqs, ST);
1701 case SPIRV::OpTypeImage:
1702 addOpTypeImageReqs(
MI, Reqs, ST);
1704 case SPIRV::OpTypeSampler:
1705 if (!
ST.isShader()) {
1709 case SPIRV::OpTypeForwardPointer:
1713 case SPIRV::OpAtomicFlagTestAndSet:
1714 case SPIRV::OpAtomicLoad:
1715 case SPIRV::OpAtomicStore:
1716 case SPIRV::OpAtomicExchange:
1717 case SPIRV::OpAtomicCompareExchange:
1718 case SPIRV::OpAtomicIIncrement:
1719 case SPIRV::OpAtomicIDecrement:
1720 case SPIRV::OpAtomicIAdd:
1721 case SPIRV::OpAtomicISub:
1722 case SPIRV::OpAtomicUMin:
1723 case SPIRV::OpAtomicUMax:
1724 case SPIRV::OpAtomicSMin:
1725 case SPIRV::OpAtomicSMax:
1726 case SPIRV::OpAtomicAnd:
1727 case SPIRV::OpAtomicOr:
1728 case SPIRV::OpAtomicXor: {
1731 if (
Op == SPIRV::OpAtomicStore) {
1734 assert(InstrPtr &&
"Unexpected type instruction for OpAtomicStore");
1740 if (TypeDef->
getOpcode() == SPIRV::OpTypeInt) {
1745 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics))
1747 "16-bit integer atomic operations require the following SPIR-V "
1748 "extension: SPV_INTEL_16bit_atomics",
1750 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics);
1752 case SPIRV::OpAtomicLoad:
1753 case SPIRV::OpAtomicStore:
1754 case SPIRV::OpAtomicExchange:
1755 case SPIRV::OpAtomicCompareExchange:
1756 case SPIRV::OpAtomicCompareExchangeWeak:
1758 SPIRV::Capability::AtomicInt16CompareExchangeINTEL);
1765 }
else if (isBFloat16Type(TypeDef)) {
1766 if (
is_contained({SPIRV::OpAtomicLoad, SPIRV::OpAtomicStore,
1767 SPIRV::OpAtomicExchange},
1769 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics))
1771 "The atomic bfloat16 instruction requires the following SPIR-V "
1772 "extension: SPV_INTEL_16bit_atomics",
1774 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics);
1775 Reqs.
addCapability(SPIRV::Capability::AtomicBFloat16LoadStoreINTEL);
1780 case SPIRV::OpGroupNonUniformIAdd:
1781 case SPIRV::OpGroupNonUniformFAdd:
1782 case SPIRV::OpGroupNonUniformIMul:
1783 case SPIRV::OpGroupNonUniformFMul:
1784 case SPIRV::OpGroupNonUniformSMin:
1785 case SPIRV::OpGroupNonUniformUMin:
1786 case SPIRV::OpGroupNonUniformFMin:
1787 case SPIRV::OpGroupNonUniformSMax:
1788 case SPIRV::OpGroupNonUniformUMax:
1789 case SPIRV::OpGroupNonUniformFMax:
1790 case SPIRV::OpGroupNonUniformBitwiseAnd:
1791 case SPIRV::OpGroupNonUniformBitwiseOr:
1792 case SPIRV::OpGroupNonUniformBitwiseXor:
1793 case SPIRV::OpGroupNonUniformLogicalAnd:
1794 case SPIRV::OpGroupNonUniformLogicalOr:
1795 case SPIRV::OpGroupNonUniformLogicalXor: {
1797 int64_t GroupOp =
MI.getOperand(3).getImm();
1799 case SPIRV::GroupOperation::Reduce:
1800 case SPIRV::GroupOperation::InclusiveScan:
1801 case SPIRV::GroupOperation::ExclusiveScan:
1802 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformArithmetic);
1804 case SPIRV::GroupOperation::ClusteredReduce:
1805 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformClustered);
1807 case SPIRV::GroupOperation::PartitionedReduceNV:
1808 case SPIRV::GroupOperation::PartitionedInclusiveScanNV:
1809 case SPIRV::GroupOperation::PartitionedExclusiveScanNV:
1810 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformPartitionedNV);
1815 case SPIRV::OpGroupNonUniformQuadSwap:
1818 case SPIRV::OpImageQueryLod:
1821 case SPIRV::OpImageQuerySize:
1822 case SPIRV::OpImageQuerySizeLod:
1823 case SPIRV::OpImageQueryLevels:
1824 case SPIRV::OpImageQuerySamples:
1828 case SPIRV::OpImageQueryFormat: {
1829 Register ResultReg =
MI.getOperand(0).getReg();
1831 static const unsigned CompareOps[] = {
1832 SPIRV::OpIEqual, SPIRV::OpINotEqual,
1833 SPIRV::OpUGreaterThan, SPIRV::OpUGreaterThanEqual,
1834 SPIRV::OpULessThan, SPIRV::OpULessThanEqual,
1835 SPIRV::OpSGreaterThan, SPIRV::OpSGreaterThanEqual,
1836 SPIRV::OpSLessThan, SPIRV::OpSLessThanEqual};
1838 auto CheckAndAddExtension = [&](int64_t ImmVal) {
1839 if (ImmVal == 4323 || ImmVal == 4324) {
1840 if (
ST.canUseExtension(SPIRV::Extension::SPV_EXT_image_raw10_raw12))
1841 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_image_raw10_raw12);
1844 "SPV_EXT_image_raw10_raw12 extension");
1849 unsigned Opc = UseInst.getOpcode();
1851 if (
Opc == SPIRV::OpSwitch) {
1854 CheckAndAddExtension(
Op.getImm());
1856 for (
unsigned i = 1; i < UseInst.getNumOperands(); ++i) {
1859 if (ConstInst && ConstInst->
getOpcode() == SPIRV::OpConstantI) {
1862 CheckAndAddExtension(ImmVal);
1870 case SPIRV::OpGroupNonUniformShuffle:
1871 case SPIRV::OpGroupNonUniformShuffleXor:
1872 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformShuffle);
1874 case SPIRV::OpGroupNonUniformShuffleUp:
1875 case SPIRV::OpGroupNonUniformShuffleDown:
1876 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformShuffleRelative);
1878 case SPIRV::OpGroupAll:
1879 case SPIRV::OpGroupAny:
1880 case SPIRV::OpGroupBroadcast:
1881 case SPIRV::OpGroupIAdd:
1882 case SPIRV::OpGroupFAdd:
1883 case SPIRV::OpGroupFMin:
1884 case SPIRV::OpGroupUMin:
1885 case SPIRV::OpGroupSMin:
1886 case SPIRV::OpGroupFMax:
1887 case SPIRV::OpGroupUMax:
1888 case SPIRV::OpGroupSMax:
1891 case SPIRV::OpGroupNonUniformElect:
1894 case SPIRV::OpGroupNonUniformAll:
1895 case SPIRV::OpGroupNonUniformAny:
1896 case SPIRV::OpGroupNonUniformAllEqual:
1899 case SPIRV::OpGroupNonUniformBroadcast:
1900 case SPIRV::OpGroupNonUniformBroadcastFirst:
1901 case SPIRV::OpGroupNonUniformBallot:
1902 case SPIRV::OpGroupNonUniformInverseBallot:
1903 case SPIRV::OpGroupNonUniformBallotBitExtract:
1904 case SPIRV::OpGroupNonUniformBallotBitCount:
1905 case SPIRV::OpGroupNonUniformBallotFindLSB:
1906 case SPIRV::OpGroupNonUniformBallotFindMSB:
1907 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformBallot);
1909 case SPIRV::OpSubgroupShuffleINTEL:
1910 case SPIRV::OpSubgroupShuffleDownINTEL:
1911 case SPIRV::OpSubgroupShuffleUpINTEL:
1912 case SPIRV::OpSubgroupShuffleXorINTEL:
1913 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {
1914 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_subgroups);
1915 Reqs.
addCapability(SPIRV::Capability::SubgroupShuffleINTEL);
1918 case SPIRV::OpSubgroupBlockReadINTEL:
1919 case SPIRV::OpSubgroupBlockWriteINTEL:
1920 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {
1921 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_subgroups);
1922 Reqs.
addCapability(SPIRV::Capability::SubgroupBufferBlockIOINTEL);
1925 case SPIRV::OpSubgroupImageBlockReadINTEL:
1926 case SPIRV::OpSubgroupImageBlockWriteINTEL:
1927 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {
1928 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_subgroups);
1929 Reqs.
addCapability(SPIRV::Capability::SubgroupImageBlockIOINTEL);
1932 case SPIRV::OpSubgroupImageMediaBlockReadINTEL:
1933 case SPIRV::OpSubgroupImageMediaBlockWriteINTEL:
1934 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_media_block_io)) {
1935 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_media_block_io);
1936 Reqs.
addCapability(SPIRV::Capability::SubgroupImageMediaBlockIOINTEL);
1939 case SPIRV::OpAssumeTrueKHR:
1940 case SPIRV::OpExpectKHR:
1941 if (
ST.canUseExtension(SPIRV::Extension::SPV_KHR_expect_assume)) {
1942 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_expect_assume);
1946 case SPIRV::OpFmaKHR:
1947 if (
ST.canUseExtension(SPIRV::Extension::SPV_KHR_fma)) {
1952 case SPIRV::OpPtrCastToCrossWorkgroupINTEL:
1953 case SPIRV::OpCrossWorkgroupCastToPtrINTEL:
1954 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_usm_storage_classes)) {
1955 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_usm_storage_classes);
1956 Reqs.
addCapability(SPIRV::Capability::USMStorageClassesINTEL);
1959 case SPIRV::OpConstantFunctionPointerINTEL:
1960 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_function_pointers)) {
1961 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_function_pointers);
1962 Reqs.
addCapability(SPIRV::Capability::FunctionPointersINTEL);
1965 case SPIRV::OpGroupNonUniformRotateKHR:
1966 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_subgroup_rotate))
1968 "following SPIR-V extension: SPV_KHR_subgroup_rotate",
1970 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_subgroup_rotate);
1971 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformRotateKHR);
1974 case SPIRV::OpFixedCosALTERA:
1975 case SPIRV::OpFixedSinALTERA:
1976 case SPIRV::OpFixedCosPiALTERA:
1977 case SPIRV::OpFixedSinPiALTERA:
1978 case SPIRV::OpFixedExpALTERA:
1979 case SPIRV::OpFixedLogALTERA:
1980 case SPIRV::OpFixedRecipALTERA:
1981 case SPIRV::OpFixedSqrtALTERA:
1982 case SPIRV::OpFixedSinCosALTERA:
1983 case SPIRV::OpFixedSinCosPiALTERA:
1984 case SPIRV::OpFixedRsqrtALTERA:
1985 if (!
ST.canUseExtension(
1986 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_fixed_point))
1988 "following SPIR-V extension: "
1989 "SPV_ALTERA_arbitrary_precision_fixed_point",
1992 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_fixed_point);
1993 Reqs.
addCapability(SPIRV::Capability::ArbitraryPrecisionFixedPointALTERA);
1995 case SPIRV::OpGroupIMulKHR:
1996 case SPIRV::OpGroupFMulKHR:
1997 case SPIRV::OpGroupBitwiseAndKHR:
1998 case SPIRV::OpGroupBitwiseOrKHR:
1999 case SPIRV::OpGroupBitwiseXorKHR:
2000 case SPIRV::OpGroupLogicalAndKHR:
2001 case SPIRV::OpGroupLogicalOrKHR:
2002 case SPIRV::OpGroupLogicalXorKHR:
2003 if (
ST.canUseExtension(
2004 SPIRV::Extension::SPV_KHR_uniform_group_instructions)) {
2005 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_uniform_group_instructions);
2006 Reqs.
addCapability(SPIRV::Capability::GroupUniformArithmeticKHR);
2009 case SPIRV::OpReadClockKHR:
2010 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_shader_clock))
2012 "following SPIR-V extension: SPV_KHR_shader_clock",
2014 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_shader_clock);
2017 case SPIRV::OpAbortKHR:
2018 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_abort))
2020 "following SPIR-V extension: SPV_KHR_abort",
2025 case SPIRV::OpPoisonKHR:
2026 case SPIRV::OpFreezeKHR:
2027 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_poison_freeze))
2029 "following SPIR-V extension: SPV_KHR_poison_freeze",
2031 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_poison_freeze);
2034 case SPIRV::OpFunctionPointerCallINTEL:
2035 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_function_pointers)) {
2036 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_function_pointers);
2037 Reqs.
addCapability(SPIRV::Capability::FunctionPointersINTEL);
2040 case SPIRV::OpAtomicFAddEXT:
2041 case SPIRV::OpAtomicFMinEXT:
2042 case SPIRV::OpAtomicFMaxEXT:
2043 AddAtomicFloatRequirements(
MI, Reqs, ST);
2045 case SPIRV::OpConvertBF16ToFINTEL:
2046 case SPIRV::OpConvertFToBF16INTEL:
2047 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bfloat16_conversion)) {
2048 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bfloat16_conversion);
2049 Reqs.
addCapability(SPIRV::Capability::BFloat16ConversionINTEL);
2052 case SPIRV::OpRoundFToTF32INTEL:
2053 if (
ST.canUseExtension(
2054 SPIRV::Extension::SPV_INTEL_tensor_float32_conversion)) {
2055 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_tensor_float32_conversion);
2056 Reqs.
addCapability(SPIRV::Capability::TensorFloat32RoundingINTEL);
2059 case SPIRV::OpVariableLengthArrayINTEL:
2060 case SPIRV::OpSaveMemoryINTEL:
2061 case SPIRV::OpRestoreMemoryINTEL:
2062 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_variable_length_array)) {
2063 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_variable_length_array);
2064 Reqs.
addCapability(SPIRV::Capability::VariableLengthArrayINTEL);
2067 case SPIRV::OpAsmTargetINTEL:
2068 case SPIRV::OpAsmINTEL:
2069 case SPIRV::OpAsmCallINTEL:
2070 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_inline_assembly)) {
2071 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_inline_assembly);
2075 case SPIRV::OpTypeCooperativeMatrixKHR: {
2076 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix))
2078 "OpTypeCooperativeMatrixKHR type requires the "
2079 "following SPIR-V extension: SPV_KHR_cooperative_matrix",
2081 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix);
2082 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixKHR);
2085 if (isBFloat16Type(TypeDef))
2086 Reqs.
addCapability(SPIRV::Capability::BFloat16CooperativeMatrixKHR);
2089 case SPIRV::OpArithmeticFenceEXT:
2090 if (!
ST.canUseExtension(SPIRV::Extension::SPV_EXT_arithmetic_fence))
2092 "following SPIR-V extension: SPV_EXT_arithmetic_fence",
2094 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_arithmetic_fence);
2097 case SPIRV::OpControlBarrierArriveINTEL:
2098 case SPIRV::OpControlBarrierWaitINTEL:
2099 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_split_barrier)) {
2100 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_split_barrier);
2104 case SPIRV::OpCooperativeMatrixMulAddKHR: {
2105 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix))
2107 "following SPIR-V extension: "
2108 "SPV_KHR_cooperative_matrix",
2110 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix);
2111 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixKHR);
2112 constexpr unsigned MulAddMaxSize = 6;
2113 if (
MI.getNumOperands() != MulAddMaxSize)
2115 const int64_t CoopOperands =
MI.getOperand(MulAddMaxSize - 1).getImm();
2117 SPIRV::CooperativeMatrixOperands::MatrixAAndBTF32ComponentsINTEL) {
2118 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
2120 "require the following SPIR-V extension: "
2121 "SPV_INTEL_joint_matrix",
2123 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2125 SPIRV::Capability::CooperativeMatrixTF32ComponentTypeINTEL);
2128 MatrixAAndBBFloat16ComponentsINTEL ||
2130 SPIRV::CooperativeMatrixOperands::MatrixCBFloat16ComponentsINTEL ||
2132 MatrixResultBFloat16ComponentsINTEL) {
2133 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
2135 "require the following SPIR-V extension: "
2136 "SPV_INTEL_joint_matrix",
2138 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2140 SPIRV::Capability::CooperativeMatrixBFloat16ComponentTypeINTEL);
2144 case SPIRV::OpCooperativeMatrixLoadKHR:
2145 case SPIRV::OpCooperativeMatrixStoreKHR:
2146 case SPIRV::OpCooperativeMatrixLoadCheckedINTEL:
2147 case SPIRV::OpCooperativeMatrixStoreCheckedINTEL:
2148 case SPIRV::OpCooperativeMatrixPrefetchINTEL: {
2149 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix))
2151 "following SPIR-V extension: "
2152 "SPV_KHR_cooperative_matrix",
2154 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix);
2155 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixKHR);
2159 std::unordered_map<unsigned, unsigned> LayoutToInstMap = {
2160 {SPIRV::OpCooperativeMatrixLoadKHR, 3},
2161 {SPIRV::OpCooperativeMatrixStoreKHR, 2},
2162 {SPIRV::OpCooperativeMatrixLoadCheckedINTEL, 5},
2163 {SPIRV::OpCooperativeMatrixStoreCheckedINTEL, 4},
2164 {SPIRV::OpCooperativeMatrixPrefetchINTEL, 4}};
2166 const unsigned LayoutNum = LayoutToInstMap[
Op];
2167 Register RegLayout =
MI.getOperand(LayoutNum).getReg();
2170 if (MILayout->
getOpcode() == SPIRV::OpConstantI) {
2173 static_cast<unsigned>(SPIRV::CooperativeMatrixLayout::PackedINTEL)) {
2174 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
2176 "extension: SPV_INTEL_joint_matrix",
2178 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2179 Reqs.
addCapability(SPIRV::Capability::PackedCooperativeMatrixINTEL);
2184 if (
Op == SPIRV::OpCooperativeMatrixLoadKHR ||
2185 Op == SPIRV::OpCooperativeMatrixStoreKHR)
2188 std::string InstName;
2190 case SPIRV::OpCooperativeMatrixPrefetchINTEL:
2191 InstName =
"OpCooperativeMatrixPrefetchINTEL";
2193 case SPIRV::OpCooperativeMatrixLoadCheckedINTEL:
2194 InstName =
"OpCooperativeMatrixLoadCheckedINTEL";
2196 case SPIRV::OpCooperativeMatrixStoreCheckedINTEL:
2197 InstName =
"OpCooperativeMatrixStoreCheckedINTEL";
2201 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix)) {
2202 const std::string ErrorMsg =
2203 InstName +
" instruction requires the "
2204 "following SPIR-V extension: SPV_INTEL_joint_matrix";
2207 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2208 if (
Op == SPIRV::OpCooperativeMatrixPrefetchINTEL) {
2209 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixPrefetchINTEL);
2213 SPIRV::Capability::CooperativeMatrixCheckedInstructionsINTEL);
2216 case SPIRV::OpCooperativeMatrixConstructCheckedINTEL:
2217 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
2219 "instructions require the following SPIR-V extension: "
2220 "SPV_INTEL_joint_matrix",
2222 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2224 SPIRV::Capability::CooperativeMatrixCheckedInstructionsINTEL);
2226 case SPIRV::OpReadPipeBlockingALTERA:
2227 case SPIRV::OpWritePipeBlockingALTERA:
2228 if (
ST.canUseExtension(SPIRV::Extension::SPV_ALTERA_blocking_pipes)) {
2229 Reqs.
addExtension(SPIRV::Extension::SPV_ALTERA_blocking_pipes);
2233 case SPIRV::OpCooperativeMatrixGetElementCoordINTEL:
2234 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
2236 "following SPIR-V extension: SPV_INTEL_joint_matrix",
2238 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2240 SPIRV::Capability::CooperativeMatrixInvocationInstructionsINTEL);
2242 case SPIRV::OpConvertHandleToImageINTEL:
2243 case SPIRV::OpConvertHandleToSamplerINTEL:
2244 case SPIRV::OpConvertHandleToSampledImageINTEL: {
2245 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bindless_images))
2247 "instructions require the following SPIR-V extension: "
2248 "SPV_INTEL_bindless_images",
2251 SPIRV::AddressingModel::AddressingModel AddrModel = MAI.
Addr;
2253 if (
Op == SPIRV::OpConvertHandleToImageINTEL &&
2254 TyDef->
getOpcode() != SPIRV::OpTypeImage) {
2256 "OpConvertHandleToImageINTEL",
2258 }
else if (
Op == SPIRV::OpConvertHandleToSamplerINTEL &&
2259 TyDef->
getOpcode() != SPIRV::OpTypeSampler) {
2261 "OpConvertHandleToSamplerINTEL",
2263 }
else if (
Op == SPIRV::OpConvertHandleToSampledImageINTEL &&
2264 TyDef->
getOpcode() != SPIRV::OpTypeSampledImage) {
2266 "OpConvertHandleToSampledImageINTEL",
2271 if (!(Bitwidth == 32 && AddrModel == SPIRV::AddressingModel::Physical32) &&
2272 !(Bitwidth == 64 && AddrModel == SPIRV::AddressingModel::Physical64)) {
2274 "Parameter value must be a 32-bit scalar in case of "
2275 "Physical32 addressing model or a 64-bit scalar in case of "
2276 "Physical64 addressing model",
2279 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bindless_images);
2283 case SPIRV::OpSubgroup2DBlockLoadINTEL:
2284 case SPIRV::OpSubgroup2DBlockLoadTransposeINTEL:
2285 case SPIRV::OpSubgroup2DBlockLoadTransformINTEL:
2286 case SPIRV::OpSubgroup2DBlockPrefetchINTEL:
2287 case SPIRV::OpSubgroup2DBlockStoreINTEL: {
2288 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_2d_block_io))
2290 "Prefetch/Store]INTEL instructions require the "
2291 "following SPIR-V extension: SPV_INTEL_2d_block_io",
2293 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_2d_block_io);
2294 Reqs.
addCapability(SPIRV::Capability::Subgroup2DBlockIOINTEL);
2296 if (
Op == SPIRV::OpSubgroup2DBlockLoadTransposeINTEL) {
2297 Reqs.
addCapability(SPIRV::Capability::Subgroup2DBlockTransposeINTEL);
2300 if (
Op == SPIRV::OpSubgroup2DBlockLoadTransformINTEL) {
2301 Reqs.
addCapability(SPIRV::Capability::Subgroup2DBlockTransformINTEL);
2306 case SPIRV::OpKill: {
2309 case SPIRV::OpDemoteToHelperInvocation:
2310 Reqs.
addCapability(SPIRV::Capability::DemoteToHelperInvocation);
2312 if (
ST.canUseExtension(
2313 SPIRV::Extension::SPV_EXT_demote_to_helper_invocation)) {
2316 SPIRV::Extension::SPV_EXT_demote_to_helper_invocation);
2321 case SPIRV::OpSUDot:
2322 case SPIRV::OpSDotAccSat:
2323 case SPIRV::OpUDotAccSat:
2324 case SPIRV::OpSUDotAccSat:
2325 AddDotProductRequirements(
MI, Reqs, ST);
2327 case SPIRV::OpImageSampleImplicitLod:
2329 addImageOperandReqs(
MI, Reqs, ST, 4);
2331 case SPIRV::OpImageSampleExplicitLod:
2332 addImageOperandReqs(
MI, Reqs, ST, 4);
2334 case SPIRV::OpImageSampleDrefImplicitLod:
2336 addImageOperandReqs(
MI, Reqs, ST, 5);
2338 case SPIRV::OpImageSampleDrefExplicitLod:
2340 addImageOperandReqs(
MI, Reqs, ST, 5);
2342 case SPIRV::OpImageFetch:
2344 addImageOperandReqs(
MI, Reqs, ST, 4);
2346 case SPIRV::OpImageDrefGather:
2347 case SPIRV::OpImageGather:
2349 addImageOperandReqs(
MI, Reqs, ST, 5);
2351 case SPIRV::OpImageRead: {
2352 Register ImageReg =
MI.getOperand(2).getReg();
2361 if (isImageTypeWithUnknownFormat(TypeDef) &&
ST.isShader())
2362 Reqs.
addCapability(SPIRV::Capability::StorageImageReadWithoutFormat);
2365 case SPIRV::OpImageWrite: {
2366 Register ImageReg =
MI.getOperand(0).getReg();
2375 if (isImageTypeWithUnknownFormat(TypeDef) &&
ST.isShader())
2376 Reqs.
addCapability(SPIRV::Capability::StorageImageWriteWithoutFormat);
2379 case SPIRV::OpTypeStructContinuedINTEL:
2380 case SPIRV::OpConstantCompositeContinuedINTEL:
2381 case SPIRV::OpSpecConstantCompositeContinuedINTEL:
2382 case SPIRV::OpCompositeConstructContinuedINTEL: {
2383 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_long_composites))
2385 "Continued instructions require the "
2386 "following SPIR-V extension: SPV_INTEL_long_composites",
2388 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_long_composites);
2392 case SPIRV::OpArbitraryFloatEQALTERA:
2393 case SPIRV::OpArbitraryFloatGEALTERA:
2394 case SPIRV::OpArbitraryFloatGTALTERA:
2395 case SPIRV::OpArbitraryFloatLEALTERA:
2396 case SPIRV::OpArbitraryFloatLTALTERA:
2397 case SPIRV::OpArbitraryFloatCbrtALTERA:
2398 case SPIRV::OpArbitraryFloatCosALTERA:
2399 case SPIRV::OpArbitraryFloatCosPiALTERA:
2400 case SPIRV::OpArbitraryFloatExp10ALTERA:
2401 case SPIRV::OpArbitraryFloatExp2ALTERA:
2402 case SPIRV::OpArbitraryFloatExpALTERA:
2403 case SPIRV::OpArbitraryFloatExpm1ALTERA:
2404 case SPIRV::OpArbitraryFloatHypotALTERA:
2405 case SPIRV::OpArbitraryFloatLog10ALTERA:
2406 case SPIRV::OpArbitraryFloatLog1pALTERA:
2407 case SPIRV::OpArbitraryFloatLog2ALTERA:
2408 case SPIRV::OpArbitraryFloatLogALTERA:
2409 case SPIRV::OpArbitraryFloatRecipALTERA:
2410 case SPIRV::OpArbitraryFloatSinCosALTERA:
2411 case SPIRV::OpArbitraryFloatSinCosPiALTERA:
2412 case SPIRV::OpArbitraryFloatSinALTERA:
2413 case SPIRV::OpArbitraryFloatSinPiALTERA:
2414 case SPIRV::OpArbitraryFloatSqrtALTERA:
2415 case SPIRV::OpArbitraryFloatACosALTERA:
2416 case SPIRV::OpArbitraryFloatACosPiALTERA:
2417 case SPIRV::OpArbitraryFloatAddALTERA:
2418 case SPIRV::OpArbitraryFloatASinALTERA:
2419 case SPIRV::OpArbitraryFloatASinPiALTERA:
2420 case SPIRV::OpArbitraryFloatATan2ALTERA:
2421 case SPIRV::OpArbitraryFloatATanALTERA:
2422 case SPIRV::OpArbitraryFloatATanPiALTERA:
2423 case SPIRV::OpArbitraryFloatCastFromIntALTERA:
2424 case SPIRV::OpArbitraryFloatCastALTERA:
2425 case SPIRV::OpArbitraryFloatCastToIntALTERA:
2426 case SPIRV::OpArbitraryFloatDivALTERA:
2427 case SPIRV::OpArbitraryFloatMulALTERA:
2428 case SPIRV::OpArbitraryFloatPowALTERA:
2429 case SPIRV::OpArbitraryFloatPowNALTERA:
2430 case SPIRV::OpArbitraryFloatPowRALTERA:
2431 case SPIRV::OpArbitraryFloatRSqrtALTERA:
2432 case SPIRV::OpArbitraryFloatSubALTERA: {
2433 if (!
ST.canUseExtension(
2434 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_floating_point))
2436 "Floating point instructions can't be translated correctly without "
2437 "enabled SPV_ALTERA_arbitrary_precision_floating_point extension!",
2440 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_floating_point);
2442 SPIRV::Capability::ArbitraryPrecisionFloatingPointALTERA);
2445 case SPIRV::OpSubgroupMatrixMultiplyAccumulateINTEL: {
2446 if (!
ST.canUseExtension(
2447 SPIRV::Extension::SPV_INTEL_subgroup_matrix_multiply_accumulate))
2449 "OpSubgroupMatrixMultiplyAccumulateINTEL instruction requires the "
2451 "extension: SPV_INTEL_subgroup_matrix_multiply_accumulate",
2454 SPIRV::Extension::SPV_INTEL_subgroup_matrix_multiply_accumulate);
2456 SPIRV::Capability::SubgroupMatrixMultiplyAccumulateINTEL);
2459 case SPIRV::OpBitwiseFunctionINTEL: {
2460 if (!
ST.canUseExtension(
2461 SPIRV::Extension::SPV_INTEL_ternary_bitwise_function))
2463 "OpBitwiseFunctionINTEL instruction requires the following SPIR-V "
2464 "extension: SPV_INTEL_ternary_bitwise_function",
2466 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_ternary_bitwise_function);
2467 Reqs.
addCapability(SPIRV::Capability::TernaryBitwiseFunctionINTEL);
2470 case SPIRV::OpCopyMemorySized: {
2475 case SPIRV::OpPredicatedLoadINTEL:
2476 case SPIRV::OpPredicatedStoreINTEL: {
2477 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_predicated_io))
2479 "OpPredicated[Load/Store]INTEL instructions require "
2480 "the following SPIR-V extension: SPV_INTEL_predicated_io",
2482 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_predicated_io);
2486 case SPIRV::OpFAddS:
2487 case SPIRV::OpFSubS:
2488 case SPIRV::OpFMulS:
2489 case SPIRV::OpFDivS:
2490 case SPIRV::OpFRemS:
2492 case SPIRV::OpFNegate:
2493 case SPIRV::OpFAddV:
2494 case SPIRV::OpFSubV:
2495 case SPIRV::OpFMulV:
2496 case SPIRV::OpFDivV:
2497 case SPIRV::OpFRemV:
2498 case SPIRV::OpFNegateV: {
2501 if (TypeDef->
getOpcode() == SPIRV::OpTypeVector)
2503 if (isBFloat16Type(TypeDef)) {
2504 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic))
2506 "Arithmetic instructions with bfloat16 arguments require the "
2507 "following SPIR-V extension: SPV_INTEL_bfloat16_arithmetic",
2509 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic);
2510 Reqs.
addCapability(SPIRV::Capability::BFloat16ArithmeticINTEL);
2514 case SPIRV::OpOrdered:
2515 case SPIRV::OpUnordered:
2516 case SPIRV::OpFOrdEqual:
2517 case SPIRV::OpFOrdNotEqual:
2518 case SPIRV::OpFOrdLessThan:
2519 case SPIRV::OpFOrdLessThanEqual:
2520 case SPIRV::OpFOrdGreaterThan:
2521 case SPIRV::OpFOrdGreaterThanEqual:
2522 case SPIRV::OpFUnordEqual:
2523 case SPIRV::OpFUnordNotEqual:
2524 case SPIRV::OpFUnordLessThan:
2525 case SPIRV::OpFUnordLessThanEqual:
2526 case SPIRV::OpFUnordGreaterThan:
2527 case SPIRV::OpFUnordGreaterThanEqual: {
2531 if (TypeDef->
getOpcode() == SPIRV::OpTypeVector)
2533 if (isBFloat16Type(TypeDef)) {
2534 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic))
2536 "Relational instructions with bfloat16 arguments require the "
2537 "following SPIR-V extension: SPV_INTEL_bfloat16_arithmetic",
2539 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic);
2540 Reqs.
addCapability(SPIRV::Capability::BFloat16ArithmeticINTEL);
2544 case SPIRV::OpDPdxCoarse:
2545 case SPIRV::OpDPdyCoarse:
2546 case SPIRV::OpDPdxFine:
2547 case SPIRV::OpDPdyFine: {
2551 case SPIRV::OpLoopControlINTEL: {
2552 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_unstructured_loop_controls);
2553 Reqs.
addCapability(SPIRV::Capability::UnstructuredLoopControlsINTEL);
2565 SPIRV::Capability::Shader);
2577 addInstrRequirements(
MI, MAI, ST);
2580 auto Node = M.getNamedMetadata(
"spirv.ExecutionMode");
2582 bool RequireFloatControls =
false, RequireIntelFloatControls2 =
false,
2583 RequireKHRFloatControls2 =
false,
2585 bool HasIntelFloatControls2 =
2586 ST.canUseExtension(SPIRV::Extension::SPV_INTEL_float_controls2);
2587 bool HasKHRFloatControls2 =
2588 ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2);
2589 for (
unsigned i = 0; i <
Node->getNumOperands(); i++) {
2595 auto EM =
Const->getZExtValue();
2599 case SPIRV::ExecutionMode::DenormPreserve:
2600 case SPIRV::ExecutionMode::DenormFlushToZero:
2601 case SPIRV::ExecutionMode::RoundingModeRTE:
2602 case SPIRV::ExecutionMode::RoundingModeRTZ:
2603 RequireFloatControls = VerLower14;
2605 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2607 case SPIRV::ExecutionMode::RoundingModeRTPINTEL:
2608 case SPIRV::ExecutionMode::RoundingModeRTNINTEL:
2609 case SPIRV::ExecutionMode::FloatingPointModeALTINTEL:
2610 case SPIRV::ExecutionMode::FloatingPointModeIEEEINTEL:
2611 if (HasIntelFloatControls2) {
2612 RequireIntelFloatControls2 =
true;
2614 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2617 case SPIRV::ExecutionMode::FPFastMathDefault: {
2618 if (HasKHRFloatControls2) {
2619 RequireKHRFloatControls2 =
true;
2621 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2625 case SPIRV::ExecutionMode::ContractionOff:
2626 case SPIRV::ExecutionMode::SignedZeroInfNanPreserve:
2627 if (HasKHRFloatControls2) {
2628 RequireKHRFloatControls2 =
true;
2630 SPIRV::OperandCategory::ExecutionModeOperand,
2631 SPIRV::ExecutionMode::FPFastMathDefault, ST);
2634 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2639 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2644 if (RequireFloatControls &&
2645 ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls))
2647 if (RequireIntelFloatControls2)
2649 if (RequireKHRFloatControls2)
2653 if (
F.isDeclaration())
2655 if (
F.getMetadata(
"reqd_work_group_size"))
2657 SPIRV::OperandCategory::ExecutionModeOperand,
2658 SPIRV::ExecutionMode::LocalSize, ST);
2659 if (
F.getFnAttribute(
"hlsl.numthreads").isValid()) {
2661 SPIRV::OperandCategory::ExecutionModeOperand,
2662 SPIRV::ExecutionMode::LocalSize, ST);
2664 if (
F.getFnAttribute(
"enable-maximal-reconvergence").getValueAsBool()) {
2667 if (
F.getMetadata(
"work_group_size_hint"))
2669 SPIRV::OperandCategory::ExecutionModeOperand,
2670 SPIRV::ExecutionMode::LocalSizeHint, ST);
2671 if (
F.getMetadata(
"intel_reqd_sub_group_size") ||
2672 F.getMetadata(
"reqd_sub_group_size"))
2674 SPIRV::OperandCategory::ExecutionModeOperand,
2675 SPIRV::ExecutionMode::SubgroupSize, ST);
2676 if (
F.getMetadata(
"max_work_group_size"))
2678 SPIRV::OperandCategory::ExecutionModeOperand,
2679 SPIRV::ExecutionMode::MaxWorkgroupSizeINTEL, ST);
2680 if (
F.getMetadata(
"vec_type_hint"))
2682 SPIRV::OperandCategory::ExecutionModeOperand,
2683 SPIRV::ExecutionMode::VecTypeHint, ST);
2685 if (
F.hasOptNone()) {
2686 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_optnone)) {
2689 }
else if (
ST.canUseExtension(SPIRV::Extension::SPV_EXT_optnone)) {
2699 unsigned Flags = SPIRV::FPFastMathMode::None;
2700 bool CanUseKHRFloatControls2 =
2701 ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2);
2703 Flags |= SPIRV::FPFastMathMode::NotNaN;
2705 Flags |= SPIRV::FPFastMathMode::NotInf;
2707 Flags |= SPIRV::FPFastMathMode::NSZ;
2709 Flags |= SPIRV::FPFastMathMode::AllowRecip;
2711 Flags |= SPIRV::FPFastMathMode::AllowContract;
2713 if (CanUseKHRFloatControls2)
2721 Flags |= SPIRV::FPFastMathMode::NotNaN | SPIRV::FPFastMathMode::NotInf |
2722 SPIRV::FPFastMathMode::NSZ | SPIRV::FPFastMathMode::AllowRecip |
2723 SPIRV::FPFastMathMode::AllowTransform |
2724 SPIRV::FPFastMathMode::AllowReassoc |
2725 SPIRV::FPFastMathMode::AllowContract;
2727 Flags |= SPIRV::FPFastMathMode::Fast;
2730 if (CanUseKHRFloatControls2) {
2732 assert(!(Flags & SPIRV::FPFastMathMode::Fast) &&
2733 "SPIRV::FPFastMathMode::Fast is deprecated and should not be used "
2738 assert((!(Flags & SPIRV::FPFastMathMode::AllowTransform) ||
2739 ((Flags & SPIRV::FPFastMathMode::AllowReassoc &&
2740 Flags & SPIRV::FPFastMathMode::AllowContract))) &&
2741 "SPIRV::FPFastMathMode::AllowTransform requires AllowReassoc and "
2742 "AllowContract flags to be enabled as well.");
2753 return ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2);
2756static void handleMIFlagDecoration(
2761 getSymbolicOperandRequirements(SPIRV::OperandCategory::DecorationOperand,
2762 SPIRV::Decoration::NoSignedWrap, ST, Reqs)
2765 SPIRV::Decoration::NoSignedWrap, {});
2768 getSymbolicOperandRequirements(SPIRV::OperandCategory::DecorationOperand,
2769 SPIRV::Decoration::NoUnsignedWrap, ST,
2773 SPIRV::Decoration::NoUnsignedWrap, {});
2778 TII.canUseFastMathFlags(
2779 I,
ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2)) ||
2780 (
ST.isKernel() &&
I.getOpcode() == SPIRV::OpExtInst);
2784 unsigned FMFlags = getFastMathFlags(
I, ST);
2785 if (FMFlags == SPIRV::FPFastMathMode::None) {
2788 if (FPFastMathDefaultInfoVec.
empty())
2804 assert(
I.getNumOperands() >= 3 &&
"Expected at least 3 operands");
2805 Register ResReg =
I.getOpcode() == SPIRV::OpExtInst
2806 ?
I.getOperand(1).getReg()
2807 :
I.getOperand(2).getReg();
2815 if (Ty == Elem.Ty) {
2816 FMFlags = Elem.FastMathFlags;
2817 Emit = Elem.ContractionOff || Elem.SignedZeroInfNanPreserve ||
2818 Elem.FPFastMathDefault;
2823 if (FMFlags == SPIRV::FPFastMathMode::None && !Emit)
2826 if (isFastMathModeAvailable(ST)) {
2827 Register DstReg =
I.getOperand(0).getReg();
2843 for (
auto &
MBB : *MF)
2844 for (
auto &
MI :
MBB)
2845 handleMIFlagDecoration(
MI, ST,
TII, MAI.
Reqs, GR,
2862 for (
auto &
MBB : *MF) {
2863 if (!
MBB.hasName() ||
MBB.empty())
2882 for (
auto &
MBB : *MF) {
2884 MI.setDesc(
TII.get(SPIRV::OpPhi));
2887 MI.insert(
MI.operands_begin() + 1,
2888 {MachineOperand::CreateReg(ResTypeReg, false)});
2907 SPIRV::FPFastMathMode::None);
2909 SPIRV::FPFastMathMode::None);
2911 SPIRV::FPFastMathMode::None);
2918 size_t BitWidth = Ty->getScalarSizeInBits();
2922 assert(Index >= 0 && Index < 3 &&
2923 "Expected FPFastMathDefaultInfo for half, float, or double");
2924 assert(FPFastMathDefaultInfoVec.
size() == 3 &&
2925 "Expected FPFastMathDefaultInfoVec to have exactly 3 elements");
2926 return FPFastMathDefaultInfoVec[Index];
2929static void collectFPFastMathDefaults(
const Module &M,
2932 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2))
2941 auto Node = M.getNamedMetadata(
"spirv.ExecutionMode");
2945 for (
unsigned i = 0; i <
Node->getNumOperands(); i++) {
2954 if (EM == SPIRV::ExecutionMode::FPFastMathDefault) {
2956 "Expected 4 operands for FPFastMathDefault");
2967 Info.FastMathFlags = Flags;
2968 Info.FPFastMathDefault =
true;
2969 }
else if (EM == SPIRV::ExecutionMode::ContractionOff) {
2971 "Expected no operands for ContractionOff");
2978 Info.ContractionOff =
true;
2980 }
else if (EM == SPIRV::ExecutionMode::SignedZeroInfNanPreserve) {
2982 "Expected 1 operand for SignedZeroInfNanPreserve");
2983 unsigned TargetWidth =
2992 assert(Index >= 0 && Index < 3 &&
2993 "Expected FPFastMathDefaultInfo for half, float, or double");
2994 assert(FPFastMathDefaultInfoVec.
size() == 3 &&
2995 "Expected FPFastMathDefaultInfoVec to have exactly 3 elements");
2996 FPFastMathDefaultInfoVec[Index].SignedZeroInfNanPreserve =
true;
3007 SPIRVTargetMachine &TM =
3011 TII = ST->getInstrInfo();
3017 patchPhis(M, GR, *TII, MMI);
3019 addMBBNames(M, *TII, MMI, *ST,
MAI);
3020 collectFPFastMathDefaults(M,
MAI, *ST);
3021 addDecorations(M, *TII, MMI, *ST,
MAI, GR);
3023 collectReqs(M,
MAI, MMI, *ST);
3027 collectReqs(M,
MAI, MMI, *ST);
3028 collectDeclarations(M);
3031 numberRegistersGlobally(M);
3034 processOtherInstrs(M);
3038 MAI.Reqs.addCapability(SPIRV::Capability::Linkage);
3041 GR->setBound(
MAI.MaxID);
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
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