35#define DEBUG_TYPE "spirv-module-analysis"
39 cl::desc(
"Dump MIR with SPIR-V dependencies info"),
44 cl::desc(
"SPIR-V capabilities to avoid if there are "
45 "other options enabling a feature"),
48 "SPIR-V Shader capability")));
58 "SPIRV module analysis",
true,
true)
62 Func.getContext().diagnose(
68 unsigned DefaultVal = 0) {
69 if (MdNode && OpIndex < MdNode->getNumOperands()) {
83 AvoidCaps.
S.
insert(SPIRV::Capability::Shader);
85 AvoidCaps.
S.
insert(SPIRV::Capability::Kernel);
90 bool MinVerOK = SPIRVVersion.
empty() || SPIRVVersion >= ReqMinVer;
92 ReqMaxVer.
empty() || SPIRVVersion.
empty() || SPIRVVersion <= ReqMaxVer;
95 if (ReqCaps.
empty()) {
96 if (ReqExts.
empty()) {
97 if (MinVerOK && MaxVerOK)
98 return {
true, {}, {}, ReqMinVer, ReqMaxVer};
101 }
else if (MinVerOK && MaxVerOK) {
102 if (ReqCaps.
size() == 1) {
103 auto Cap = ReqCaps[0];
106 SPIRV::OperandCategory::CapabilityOperand, Cap));
107 return {
true, {Cap}, std::move(ReqExts), ReqMinVer, ReqMaxVer};
117 for (
auto Cap : ReqCaps)
120 for (
size_t i = 0, Sz = UseCaps.
size(); i < Sz; ++i) {
121 auto Cap = UseCaps[i];
122 if (i == Sz - 1 || !AvoidCaps.
S.
contains(Cap)) {
124 SPIRV::OperandCategory::CapabilityOperand, Cap));
125 return {
true, {Cap}, std::move(ReqExts), ReqMinVer, ReqMaxVer};
133 if (
llvm::all_of(ReqExts, [&ST](
const SPIRV::Extension::Extension &Ext) {
134 return ST.canUseExtension(Ext);
145void SPIRVModuleAnalysisImpl::setBaseInfo(
const Module &M) {
149 MAI.RegisterAliasTable.clear();
150 MAI.InstrsToDelete.clear();
151 MAI.MBBNames.clear();
152 MAI.GlobalObjMap.clear();
153 MAI.GlobalVarList.clear();
154 MAI.ExtInstSetMap.clear();
156 MAI.Reqs.initAvailableCapabilities(*ST);
159 if (
auto MemModel =
M.getNamedMetadata(
"spirv.MemoryModel")) {
160 auto MemMD = MemModel->getOperand(0);
161 MAI.Addr =
static_cast<SPIRV::AddressingModel::AddressingModel
>(
164 static_cast<SPIRV::MemoryModel::MemoryModel
>(
getMetadataUInt(MemMD, 1));
167 MAI.Mem = ST->isShader() ? SPIRV::MemoryModel::GLSL450
168 : SPIRV::MemoryModel::OpenCL;
169 if (MAI.Mem == SPIRV::MemoryModel::OpenCL) {
170 unsigned PtrSize = ST->getPointerSize();
171 MAI.Addr = PtrSize == 32 ? SPIRV::AddressingModel::Physical32
172 : PtrSize == 64 ? SPIRV::AddressingModel::Physical64
173 : SPIRV::AddressingModel::Logical;
176 MAI.Addr = SPIRV::AddressingModel::Logical;
181 if (
auto VerNode =
M.getNamedMetadata(
"opencl.ocl.version")) {
182 MAI.SrcLang = SPIRV::SourceLanguage::OpenCL_C;
185 assert(VerNode->getNumOperands() > 0 &&
"Invalid SPIR");
186 auto VersionMD = VerNode->getOperand(0);
192 (std::max(1U, MajorNum) * 100 + MinorNum) * 1000 + RevNum;
195 if (
auto *CxxVerNode =
M.getNamedMetadata(
"opencl.cxx.version")) {
196 assert(CxxVerNode->getNumOperands() > 0 &&
"Invalid SPIR");
197 auto *CxxMD = CxxVerNode->getOperand(0);
201 if ((MAI.SrcLangVersion == 200000 && CxxVer == 100000) ||
202 (MAI.SrcLangVersion == 300000 && CxxVer == 202100000)) {
203 MAI.SrcLang = SPIRV::SourceLanguage::CPP_for_OpenCL;
204 MAI.SrcLangVersion = CxxVer;
207 "opencl cxx version is not compatible with opencl c version!");
215 if (!ST->isShader()) {
216 MAI.SrcLang = SPIRV::SourceLanguage::OpenCL_CPP;
217 MAI.SrcLangVersion = 100000;
219 MAI.SrcLang = SPIRV::SourceLanguage::Unknown;
220 MAI.SrcLangVersion = 0;
224 if (
auto ExtNode =
M.getNamedMetadata(
"opencl.used.extensions")) {
225 for (
unsigned I = 0,
E = ExtNode->getNumOperands();
I !=
E; ++
I) {
226 MDNode *MD = ExtNode->getOperand(
I);
236 MAI.Reqs.getAndAddRequirements(SPIRV::OperandCategory::MemoryModelOperand,
238 MAI.Reqs.getAndAddRequirements(SPIRV::OperandCategory::SourceLanguageOperand,
240 MAI.Reqs.getAndAddRequirements(SPIRV::OperandCategory::AddressingModelOperand,
243 if (MAI.Mem == SPIRV::MemoryModel::VulkanKHR)
244 MAI.Reqs.addExtension(SPIRV::Extension::SPV_KHR_vulkan_memory_model);
246 if (!ST->isShader()) {
248 MAI.ExtInstSetMap[
static_cast<unsigned>(
249 SPIRV::InstructionSet::OpenCL_std)] = MAI.getNextIDRegister();
260 if (
UseMI.getOpcode() != SPIRV::OpDecorate &&
261 UseMI.getOpcode() != SPIRV::OpMemberDecorate)
264 for (
unsigned I = 0;
I <
UseMI.getNumOperands(); ++
I) {
282 for (
unsigned i = 0; i <
MI.getNumOperands(); ++i) {
291 unsigned Opcode =
MI.getOpcode();
292 if ((Opcode == SPIRV::OpDecorate) && i >= 2) {
293 unsigned DecorationID =
MI.getOperand(1).getImm();
294 if (DecorationID != SPIRV::Decoration::FuncParamAttr &&
295 DecorationID != SPIRV::Decoration::UserSemantic &&
296 DecorationID != SPIRV::Decoration::CacheControlLoadINTEL &&
297 DecorationID != SPIRV::Decoration::CacheControlStoreINTEL)
303 if (!UseDefReg && MO.
isDef()) {
311 dbgs() <<
"Unexpectedly, no global id found for the operand ";
313 dbgs() <<
"\nInstruction: ";
340 case SPIRV::OpEnqueueKernel:
342 case SPIRV::OpGetKernelNDrangeSubGroupCount:
343 case SPIRV::OpGetKernelNDrangeMaxSubGroupSize:
345 case SPIRV::OpGetKernelWorkGroupSize:
346 case SPIRV::OpGetKernelPreferredWorkGroupSizeMultiple:
355 unsigned Opcode =
MI.getOpcode();
357 case SPIRV::OpTypeForwardPointer:
360 case SPIRV::OpVariable:
361 case SPIRV::OpUntypedVariableKHR:
362 return static_cast<SPIRV::StorageClass::StorageClass
>(
363 MI.getOperand(2).
getImm()) != SPIRV::StorageClass::Function;
364 case SPIRV::OpFunction:
365 case SPIRV::OpFunctionParameter:
368 if (GR->hasConstFunPtr() && Opcode == SPIRV::OpUndef) {
376 if (GR->getFunctionDefinitionByUse(&
MI.getOperand(0))) {
378 unsigned UseOp =
UseMI.getOpcode();
379 if (UseOp == SPIRV::OpConstantFunctionPointerINTEL ||
381 MAI.setSkipEmission(&
MI);
387 if (
UseMI.getOpcode() != SPIRV::OpConstantFunctionPointerINTEL)
393 MAI.setSkipEmission(&
MI);
397 return TII->isTypeDeclInstr(
MI) || TII->isConstantInstr(
MI) ||
398 TII->isInlineAsmDefInstr(
MI);
407void SPIRVModuleAnalysisImpl::visitFunPtrUse(
410 std::map<const Value *, unsigned> &GlobalToGReg,
412 const MachineOperand *OpFunDef = GR->getFunctionDefinitionByUse(FunPtrOp);
415 const MachineInstr *OpDefMI = OpFunDef->
getParent();
418 const MachineRegisterInfo &FunDefMRI = FunDefMF->
getRegInfo();
420 visitDecl(FunDefMRI, SignatureToGReg, GlobalToGReg, FunDefMF, *OpDefMI);
422 }
while (OpDefMI && (OpDefMI->
getOpcode() == SPIRV::OpFunction ||
423 OpDefMI->
getOpcode() == SPIRV::OpFunctionParameter));
425 MCRegister GlobalFunDefReg =
426 MAI.getRegisterAlias(FunDefMF, OpFunDef->
getReg());
428 "Function definition must refer to a global register");
429 MAI.setRegisterAlias(MF, OpReg, GlobalFunDefReg);
434void SPIRVModuleAnalysisImpl::visitDecl(
436 std::map<const Value *, unsigned> &GlobalToGReg,
const MachineFunction *MF,
438 unsigned Opcode =
MI.getOpcode();
441 for (
const MachineOperand &MO :
MI.operands()) {
442 if (!MO.isReg() || MO.isDef())
446 if (Opcode == SPIRV::OpConstantFunctionPointerINTEL &&
448 visitFunPtrUse(OpReg, &
MI.getOperand(2), SignatureToGReg, GlobalToGReg,
453 if (MAI.hasRegisterAlias(MF, MO.getReg()))
457 if (isDeclSection(MRI, *OpDefMI))
458 visitDecl(MRI, SignatureToGReg, GlobalToGReg, MF, *OpDefMI);
464 dbgs() <<
"Unexpectedly, no unique definition for the operand ";
466 dbgs() <<
"\nInstruction: ";
471 "No unique definition is found for the virtual register");
475 bool IsFunDef =
false;
476 if (TII->isSpecConstantInstr(
MI)) {
477 GReg = MAI.getNextIDRegister();
479 }
else if (Opcode == SPIRV::OpFunction ||
480 Opcode == SPIRV::OpFunctionParameter) {
481 GReg = handleFunctionOrParameter(MF,
MI, GlobalToGReg, IsFunDef);
482 }
else if (Opcode == SPIRV::OpTypeStruct ||
483 Opcode == SPIRV::OpConstantComposite) {
484 GReg = handleTypeDeclOrConstant(
MI, SignatureToGReg);
485 const MachineInstr *NextInstr =
MI.getNextNode();
487 ((Opcode == SPIRV::OpTypeStruct &&
488 NextInstr->
getOpcode() == SPIRV::OpTypeStructContinuedINTEL) ||
489 (Opcode == SPIRV::OpConstantComposite &&
491 SPIRV::OpConstantCompositeContinuedINTEL))) {
492 MCRegister Tmp = handleTypeDeclOrConstant(*NextInstr, SignatureToGReg);
494 MAI.setSkipEmission(NextInstr);
497 }
else if (TII->isTypeDeclInstr(
MI) || TII->isConstantInstr(
MI) ||
498 TII->isInlineAsmDefInstr(
MI)) {
499 GReg = handleTypeDeclOrConstant(
MI, SignatureToGReg);
500 }
else if (Opcode == SPIRV::OpVariable ||
501 Opcode == SPIRV::OpUntypedVariableKHR) {
502 GReg = handleVariable(MF,
MI, GlobalToGReg);
505 dbgs() <<
"\nInstruction: ";
511 MAI.setRegisterAlias(MF,
MI.getOperand(0).getReg(), GReg);
513 MAI.setSkipEmission(&
MI);
516MCRegister SPIRVModuleAnalysisImpl::handleFunctionOrParameter(
518 std::map<const Value *, unsigned> &GlobalToGReg,
bool &IsFunDef) {
519 const Value *GObj = GR->getGlobalObject(MF,
MI.getOperand(0).getReg());
520 assert(GObj &&
"Unregistered global definition");
524 assert(
F &&
"Expected a reference to a function or an argument");
525 IsFunDef = !
F->isDeclaration();
526 auto [It,
Inserted] = GlobalToGReg.try_emplace(GObj);
529 MCRegister GReg = MAI.getNextIDRegister();
536MCRegister SPIRVModuleAnalysisImpl::handleTypeDeclOrConstant(
539 auto [It,
Inserted] = SignatureToGReg.try_emplace(MISign);
542 MCRegister GReg = MAI.getNextIDRegister();
548MCRegister SPIRVModuleAnalysisImpl::handleVariable(
550 std::map<const Value *, unsigned> &GlobalToGReg) {
551 MAI.GlobalVarList.push_back(&
MI);
552 const Value *GObj = GR->getGlobalObject(MF,
MI.getOperand(0).getReg());
553 assert(GObj &&
"Unregistered global definition");
554 auto [It,
Inserted] = GlobalToGReg.try_emplace(GObj);
557 MCRegister GReg = MAI.getNextIDRegister();
561 MAI.GlobalObjMap[GV] = GReg;
565void SPIRVModuleAnalysisImpl::collectDeclarations(
const Module &M) {
567 std::map<const Value *, unsigned> GlobalToGReg;
572 const MachineRegisterInfo &MRI = MF->
getRegInfo();
573 unsigned PastHeader = 0;
574 for (MachineBasicBlock &
MBB : *MF) {
575 for (MachineInstr &
MI :
MBB) {
576 if (
MI.getNumOperands() == 0)
578 unsigned Opcode =
MI.getOpcode();
579 if (Opcode == SPIRV::OpFunction) {
580 if (PastHeader == 0) {
584 }
else if (Opcode == SPIRV::OpFunctionParameter) {
587 }
else if (PastHeader > 0) {
591 const MachineOperand &DefMO =
MI.getOperand(0);
593 case SPIRV::OpExtension:
594 MAI.Reqs.addExtension(SPIRV::Extension::Extension(DefMO.
getImm()));
595 MAI.setSkipEmission(&
MI);
597 case SPIRV::OpCapability:
598 MAI.Reqs.addCapability(SPIRV::Capability::Capability(DefMO.
getImm()));
599 MAI.setSkipEmission(&
MI);
604 if (DefMO.
isReg() && isDeclSection(MRI,
MI) &&
605 !MAI.hasRegisterAlias(MF, DefMO.
getReg()))
606 visitDecl(MRI, SignatureToGReg, GlobalToGReg, MF,
MI);
611 const MachineOperand &InvokeMO =
MI.getOperand(InvokeIdx);
612 if (InvokeMO.
isReg()) {
614 if (!MAI.hasRegisterAlias(MF, InvokeReg)) {
615 if (
const MachineInstr *
DefMI =
619 if (GR->getFunctionDefinitionByUse(FunPtrOp))
620 visitFunPtrUse(InvokeReg, FunPtrOp, SignatureToGReg,
639 if (
MI.getOpcode() == SPIRV::OpDecorate) {
641 auto Dec =
MI.getOperand(1).getImm();
642 if (Dec == SPIRV::Decoration::LinkageAttributes) {
643 auto Lnk =
MI.getOperand(
MI.getNumOperands() - 1).getImm();
644 if (Lnk == SPIRV::LinkageType::Import) {
649 MAI.GlobalObjMap[ImportedFunc] =
650 MAI.getRegisterAlias(
MI.getMF(), Target);
653 }
else if (
MI.getOpcode() == SPIRV::OpFunction) {
656 MCRegister GlobalReg = MAI.getRegisterAlias(
MI.getMF(),
Reg);
658 MAI.GlobalObjMap[
F] = GlobalReg;
670 auto FoundMI = IS.insert(std::move(MISign));
671 if (!FoundMI.second) {
672 if (
MI.getOpcode() == SPIRV::OpDecorate) {
674 "Decoration instructions must have at least 2 operands");
676 "Only OpDecorate instructions can be duplicates");
681 if (
MI.getOperand(1).getImm() != SPIRV::Decoration::FPFastMathMode)
687 assert(OrigMI->getNumOperands() ==
MI.getNumOperands() &&
688 "Original instruction must have the same number of operands");
690 OrigMI->getNumOperands() == 3 &&
691 "FPFastMathMode decoration must have 3 operands for OpDecorate");
692 unsigned OrigFlags = OrigMI->getOperand(2).getImm();
693 unsigned NewFlags =
MI.getOperand(2).getImm();
694 if (OrigFlags == NewFlags)
698 unsigned FinalFlags = OrigFlags | NewFlags;
700 <<
"Warning: Conflicting FPFastMathMode decoration flags "
702 << *OrigMI <<
"Original flags: " << OrigFlags
703 <<
", new flags: " << NewFlags
704 <<
". They will be merged on a best effort basis, but not "
705 "validated. Final flags: "
706 << FinalFlags <<
"\n";
713 assert(
false &&
"No original instruction found for the duplicate "
714 "OpDecorate, but we found one in IS.");
727void SPIRVModuleAnalysisImpl::processOtherInstrs(
const Module &M) {
730 if (
F.isDeclaration())
735 for (MachineBasicBlock &
MBB : *MF)
736 for (MachineInstr &
MI :
MBB) {
737 if (MAI.getSkipEmission(&
MI))
739 const unsigned OpCode =
MI.getOpcode();
740 if (OpCode == SPIRV::OpString) {
742 }
else if (OpCode == SPIRV::OpExtInst &&
MI.getOperand(2).isImm() &&
743 MI.getOperand(2).getImm() ==
744 SPIRV::InstructionSet::
745 NonSemantic_Shader_DebugInfo_100) {
752 MachineOperand Ins =
MI.getOperand(3);
753 namespace NS = SPIRV::NonSemanticExtInst;
754 static constexpr int64_t GlobalNonSemanticDITy[] = {
755 NS::DebugSource, NS::DebugCompilationUnit, NS::DebugInfoNone,
756 NS::DebugTypeBasic, NS::DebugTypePointer};
757 bool IsGlobalDI =
false;
758 for (
unsigned Idx = 0;
Idx < std::size(GlobalNonSemanticDITy); ++
Idx)
759 IsGlobalDI |= Ins.
getImm() == GlobalNonSemanticDITy[
Idx];
762 }
else if (OpCode == SPIRV::OpName || OpCode == SPIRV::OpMemberName) {
764 }
else if (OpCode == SPIRV::OpEntryPoint) {
766 }
else if (TII->isAliasingInstr(
MI)) {
768 }
else if (TII->isDecorationInstr(
MI)) {
770 collectFuncNames(
MI, &
F);
771 }
else if (TII->isConstantInstr(
MI)) {
775 }
else if (OpCode == SPIRV::OpFunction) {
776 collectFuncNames(
MI, &
F);
777 }
else if (OpCode == SPIRV::OpTypeForwardPointer) {
785 auto AliasingTier = [](
const MachineInstr *
MI) {
786 switch (
MI->getOpcode()) {
787 case SPIRV::OpAliasDomainDeclINTEL:
789 case SPIRV::OpAliasScopeDeclINTEL:
791 case SPIRV::OpAliasScopeListDeclINTEL:
798 [&](
const MachineInstr *
LHS,
const MachineInstr *
RHS) {
799 return AliasingTier(LHS) < AliasingTier(RHS);
806void SPIRVModuleAnalysisImpl::numberRegistersGlobally(
const Module &M) {
808 if (
F.isDeclaration())
812 for (MachineBasicBlock &
MBB : *MF) {
813 for (MachineInstr &
MI :
MBB) {
814 for (MachineOperand &
Op :
MI.operands()) {
818 if (MAI.hasRegisterAlias(MF,
Reg))
820 MCRegister NewReg = MAI.getNextIDRegister();
821 MAI.setRegisterAlias(MF,
Reg, NewReg);
823 if (
MI.getOpcode() != SPIRV::OpExtInst)
825 auto Set =
MI.getOperand(2).getImm();
826 auto [It,
Inserted] = MAI.ExtInstSetMap.try_emplace(Set);
828 It->second = MAI.getNextIDRegister();
836 SPIRV::OperandCategory::OperandCategory Category,
uint32_t i,
841void SPIRV::RequirementHandler::recursiveAddCapabilities(
843 for (
const auto &Cap : ToPrune) {
847 recursiveAddCapabilities(ImplicitDecls);
852 for (
const auto &Cap : ToAdd) {
853 bool IsNewlyInserted = AllCaps.insert(Cap).second;
854 if (!IsNewlyInserted)
858 recursiveAddCapabilities(ImplicitDecls);
859 MinimalCaps.push_back(Cap);
868 if (Req.
Cap.has_value())
874 if (!MaxVersion.empty() && Req.
MinVer > MaxVersion) {
876 <<
" and <= " << MaxVersion <<
"\n");
880 if (MinVersion.empty() || Req.
MinVer > MinVersion)
885 if (!MinVersion.empty() && Req.
MaxVer < MinVersion) {
887 <<
" and >= " << MinVersion <<
"\n");
891 if (MaxVersion.empty() || Req.
MaxVer < MaxVersion)
899 bool IsSatisfiable =
true;
900 auto TargetVer = ST.getSPIRVVersion();
902 if (!MaxVersion.empty() && !TargetVer.empty() && MaxVersion < TargetVer) {
904 dbgs() <<
"Target SPIR-V version too high for required features\n"
905 <<
"Required max version: " << MaxVersion <<
" target version "
906 << TargetVer <<
"\n");
907 IsSatisfiable =
false;
910 if (!MinVersion.empty() && !TargetVer.empty() && MinVersion > TargetVer) {
911 LLVM_DEBUG(
dbgs() <<
"Target SPIR-V version too low for required features\n"
912 <<
"Required min version: " << MinVersion
913 <<
" target version " << TargetVer <<
"\n");
914 IsSatisfiable =
false;
917 if (!MinVersion.empty() && !MaxVersion.empty() && MinVersion > MaxVersion) {
920 <<
"Version is too low for some features and too high for others.\n"
921 <<
"Required SPIR-V min version: " << MinVersion
922 <<
" required SPIR-V max version " << MaxVersion <<
"\n");
923 IsSatisfiable =
false;
928 AvoidCaps.
S.
insert(SPIRV::Capability::Shader);
930 AvoidCaps.
S.
insert(SPIRV::Capability::Kernel);
932 for (
auto Cap : MinimalCaps) {
933 if (AvailableCaps.contains(Cap) && !AvoidCaps.
S.
contains(Cap))
937 OperandCategory::CapabilityOperand, Cap)
939 IsSatisfiable =
false;
942 for (
auto Ext : AllExtensions) {
943 if (ST.canUseExtension(Ext))
947 OperandCategory::ExtensionOperand, Ext)
949 IsSatisfiable =
false;
958 for (
const auto Cap : ToAdd)
959 if (AvailableCaps.insert(Cap).second)
961 SPIRV::OperandCategory::CapabilityOperand, Cap));
965 const Capability::Capability
ToRemove,
966 const Capability::Capability IfPresent) {
967 if (AllCaps.contains(IfPresent)) {
977 addAvailableCaps({Capability::Shader, Capability::Linkage, Capability::Int8,
982 Capability::GroupNonUniformVote,
983 Capability::GroupNonUniformArithmetic,
984 Capability::GroupNonUniformBallot,
985 Capability::GroupNonUniformClustered,
986 Capability::GroupNonUniformShuffle,
987 Capability::GroupNonUniformShuffleRelative,
988 Capability::GroupNonUniformQuad});
992 Capability::DotProductInput4x8Bit,
993 Capability::DotProductInput4x8BitPacked,
994 Capability::DemoteToHelperInvocation});
997 for (
auto Extension : ST.getAllAvailableExtensions()) {
1003 if (!ST.isShader()) {
1004 initAvailableCapabilitiesForOpenCL(ST);
1008 if (ST.isShader()) {
1009 initAvailableCapabilitiesForVulkan(ST);
1016void RequirementHandler::initAvailableCapabilitiesForOpenCL(
1020 Capability::Kernel, Capability::Vector16,
1021 Capability::Groups, Capability::GenericPointer,
1022 Capability::StorageImageWriteWithoutFormat,
1023 Capability::StorageImageReadWithoutFormat});
1024 if (ST.hasOpenCLFullProfile())
1026 if (ST.hasOpenCLImageSupport()) {
1028 Capability::Image1D, Capability::SampledBuffer,
1029 Capability::ImageBuffer});
1030 if (
ST.isAtLeastOpenCLVer(VersionTuple(2, 0)))
1033 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 1)) &&
1034 ST.isAtLeastOpenCLVer(VersionTuple(2, 2)))
1036 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 4)))
1037 addAvailableCaps({Capability::DenormPreserve, Capability::DenormFlushToZero,
1038 Capability::SignedZeroInfNanPreserve,
1039 Capability::RoundingModeRTE,
1040 Capability::RoundingModeRTZ});
1047void RequirementHandler::initAvailableCapabilitiesForVulkan(
1048 const SPIRVSubtarget &ST) {
1052 Capability::Float16,
1053 Capability::Float64,
1054 Capability::GroupNonUniform,
1055 Capability::Image1D,
1056 Capability::SampledBuffer,
1057 Capability::ImageBuffer,
1058 Capability::UniformBufferArrayDynamicIndexing,
1059 Capability::SampledImageArrayDynamicIndexing,
1060 Capability::StorageBufferArrayDynamicIndexing,
1061 Capability::StorageImageArrayDynamicIndexing,
1062 Capability::DerivativeControl,
1064 Capability::ImageQuery,
1065 Capability::ImageGatherExtended,
1066 Capability::Addresses,
1067 Capability::VulkanMemoryModelKHR,
1068 Capability::StorageImageExtendedFormats,
1069 Capability::StorageImageMultisample,
1070 Capability::ImageMSArray});
1072 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 3)) ||
1073 ST.canUseExtension(Extension::SPV_KHR_variable_pointers))
1075 Capability::VariablePointers});
1078 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 5))) {
1080 {Capability::Int64Atomics, Capability::ShaderNonUniformEXT,
1081 Capability::RuntimeDescriptorArrayEXT,
1082 Capability::InputAttachmentArrayDynamicIndexingEXT,
1083 Capability::UniformTexelBufferArrayDynamicIndexingEXT,
1084 Capability::StorageTexelBufferArrayDynamicIndexingEXT,
1085 Capability::UniformBufferArrayNonUniformIndexingEXT,
1086 Capability::SampledImageArrayNonUniformIndexingEXT,
1087 Capability::StorageBufferArrayNonUniformIndexingEXT,
1088 Capability::StorageImageArrayNonUniformIndexingEXT,
1089 Capability::InputAttachmentArrayNonUniformIndexingEXT,
1090 Capability::UniformTexelBufferArrayNonUniformIndexingEXT,
1091 Capability::StorageTexelBufferArrayNonUniformIndexingEXT});
1095 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 6)))
1097 Capability::StorageImageReadWithoutFormat});
1108 int64_t DecOp =
MI.getOperand(DecIndex).getImm();
1109 auto Dec =
static_cast<SPIRV::Decoration::Decoration
>(DecOp);
1111 SPIRV::OperandCategory::DecorationOperand, Dec, ST, Reqs));
1113 if (Dec == SPIRV::Decoration::BuiltIn) {
1114 int64_t BuiltInOp =
MI.getOperand(DecIndex + 1).getImm();
1115 auto BuiltIn =
static_cast<SPIRV::BuiltIn::BuiltIn
>(BuiltInOp);
1117 SPIRV::OperandCategory::BuiltInOperand, BuiltIn, ST, Reqs));
1118 }
else if (Dec == SPIRV::Decoration::LinkageAttributes) {
1119 int64_t LinkageOp =
MI.getOperand(
MI.getNumOperands() - 1).getImm();
1120 SPIRV::LinkageType::LinkageType LnkType =
1121 static_cast<SPIRV::LinkageType::LinkageType
>(LinkageOp);
1122 if (LnkType == SPIRV::LinkageType::LinkOnceODR)
1123 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_linkonce_odr);
1124 else if (LnkType == SPIRV::LinkageType::WeakAMD) {
1125 Reqs.
addExtension(SPIRV::Extension::SPV_AMD_weak_linkage);
1128 }
else if (Dec == SPIRV::Decoration::CacheControlLoadINTEL ||
1129 Dec == SPIRV::Decoration::CacheControlStoreINTEL) {
1130 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_cache_controls);
1131 }
else if (Dec == SPIRV::Decoration::HostAccessINTEL) {
1132 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_global_variable_host_access);
1133 }
else if (Dec == SPIRV::Decoration::InitModeINTEL ||
1134 Dec == SPIRV::Decoration::ImplementInRegisterMapINTEL) {
1136 SPIRV::Extension::SPV_INTEL_global_variable_fpga_decorations);
1137 }
else if (Dec == SPIRV::Decoration::NonUniformEXT) {
1139 }
else if (Dec == SPIRV::Decoration::FPMaxErrorDecorationINTEL) {
1141 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_fp_max_error);
1142 }
else if (Dec == SPIRV::Decoration::FPFastMathMode) {
1143 if (ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2)) {
1145 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_float_controls2);
1154 assert(
MI.getNumOperands() >= 8 &&
"Insufficient operands for OpTypeImage");
1157 int64_t ImgFormatOp =
MI.getOperand(7).getImm();
1158 auto ImgFormat =
static_cast<SPIRV::ImageFormat::ImageFormat
>(ImgFormatOp);
1162 bool IsArrayed =
MI.getOperand(4).getImm() == 1;
1163 bool IsMultisampled =
MI.getOperand(5).getImm() == 1;
1164 bool NoSampler =
MI.getOperand(6).getImm() == 2;
1167 switch (
MI.getOperand(2).getImm()) {
1168 case SPIRV::Dim::DIM_1D:
1170 : SPIRV::Capability::Sampled1D);
1172 case SPIRV::Dim::DIM_2D:
1173 if (IsMultisampled && NoSampler)
1175 if (IsMultisampled && IsArrayed)
1178 case SPIRV::Dim::DIM_3D:
1180 case SPIRV::Dim::DIM_Cube:
1184 : SPIRV::Capability::SampledCubeArray);
1186 case SPIRV::Dim::DIM_Rect:
1188 : SPIRV::Capability::SampledRect);
1190 case SPIRV::Dim::DIM_Buffer:
1192 : SPIRV::Capability::SampledBuffer);
1194 case SPIRV::Dim::DIM_SubpassData:
1200 if (!ST.isShader()) {
1201 if (
MI.getNumOperands() > 8 &&
1202 MI.getOperand(8).getImm() == SPIRV::AccessQualifier::ReadWrite)
1211 TypeDef->
getOpcode() == SPIRV::OpTypeFloat &&
1217#define ATOM_FLT_REQ_EXT_MSG(ExtName) \
1218 "The atomic float instruction requires the following SPIR-V " \
1219 "extension: SPV_EXT_shader_atomic_float" ExtName
1224 MI.getMF()->getRegInfo().getVRegDef(
MI.getOperand(1).getReg());
1227 if (Rank != 2 && Rank != 4)
1229 "must be a 2-component or 4 component vector");
1234 if (EltTypeDef->
getOpcode() != SPIRV::OpTypeFloat ||
1237 "The element type for the result type of an atomic vector float "
1238 "instruction must be a 16-bit floating-point scalar");
1245 "The element type for the result type of an atomic vector float "
1246 "instruction cannot be a bfloat16 scalar");
1247 if (!ST.canUseExtension(SPIRV::Extension::SPV_NV_shader_atomic_fp16_vector))
1249 "The atomic float16 vector instruction requires the following SPIR-V "
1250 "extension: SPV_NV_shader_atomic_fp16_vector");
1252 Reqs.
addExtension(SPIRV::Extension::SPV_NV_shader_atomic_fp16_vector);
1253 Reqs.
addCapability(SPIRV::Capability::AtomicFloat16VectorNV);
1260 "Expect register operand in atomic float instruction");
1261 Register TypeReg =
MI.getOperand(1).getReg();
1267 if (TypeDef->
getOpcode() != SPIRV::OpTypeFloat)
1269 "floating-point type scalar");
1272 unsigned Op =
MI.getOpcode();
1273 if (
Op == SPIRV::OpAtomicFAddEXT) {
1274 if (!ST.canUseExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float_add))
1276 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float_add);
1280 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics))
1282 "The atomic bfloat16 instruction requires the following SPIR-V "
1283 "extension: SPV_INTEL_16bit_atomics",
1285 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics);
1286 Reqs.
addCapability(SPIRV::Capability::AtomicBFloat16AddINTEL);
1288 if (!ST.canUseExtension(
1289 SPIRV::Extension::SPV_EXT_shader_atomic_float16_add))
1291 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float16_add);
1303 "Unexpected floating-point type width in atomic float instruction");
1306 if (!ST.canUseExtension(
1307 SPIRV::Extension::SPV_EXT_shader_atomic_float_min_max))
1309 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float_min_max);
1313 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics))
1315 "The atomic bfloat16 instruction requires the following SPIR-V "
1316 "extension: SPV_INTEL_16bit_atomics",
1318 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics);
1319 Reqs.
addCapability(SPIRV::Capability::AtomicBFloat16MinMaxINTEL);
1321 Reqs.
addCapability(SPIRV::Capability::AtomicFloat16MinMaxEXT);
1325 Reqs.
addCapability(SPIRV::Capability::AtomicFloat32MinMaxEXT);
1328 Reqs.
addCapability(SPIRV::Capability::AtomicFloat64MinMaxEXT);
1332 "Unexpected floating-point type width in atomic float instruction");
1338 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1342 return Dim == SPIRV::Dim::DIM_Buffer && Sampled == 1;
1346 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1350 return Dim == SPIRV::Dim::DIM_Buffer && Sampled == 2;
1354 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1358 return Dim != SPIRV::Dim::DIM_Buffer && Sampled == 1;
1362 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1366 return Dim == SPIRV::Dim::DIM_SubpassData && Sampled == 2;
1370 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1374 return Dim != SPIRV::Dim::DIM_Buffer && Sampled == 2;
1378 if (SampledImageInst->
getOpcode() != SPIRV::OpTypeSampledImage)
1389 if (
MI.getOpcode() != SPIRV::OpDecorate)
1393 if (Dec == SPIRV::Decoration::NonUniformEXT)
1406 Register ResTypeReg = Instr.getOperand(1).getReg();
1411 if (
StorageClass != SPIRV::StorageClass::StorageClass::UniformConstant &&
1412 StorageClass != SPIRV::StorageClass::StorageClass::Uniform &&
1413 StorageClass != SPIRV::StorageClass::StorageClass::StorageBuffer) {
1420 auto FirstIndexReg = Instr.getOperand(3).getReg();
1421 bool FirstIndexIsConstant =
1424 if (
StorageClass == SPIRV::StorageClass::StorageClass::StorageBuffer) {
1427 SPIRV::Capability::StorageBufferArrayNonUniformIndexingEXT);
1428 else if (!FirstIndexIsConstant)
1430 SPIRV::Capability::StorageBufferArrayDynamicIndexing);
1436 if (PointeeType->
getOpcode() != SPIRV::OpTypeImage &&
1437 PointeeType->
getOpcode() != SPIRV::OpTypeSampledImage &&
1438 PointeeType->
getOpcode() != SPIRV::OpTypeSampler) {
1445 SPIRV::Capability::UniformTexelBufferArrayNonUniformIndexingEXT);
1446 else if (!FirstIndexIsConstant)
1448 SPIRV::Capability::UniformTexelBufferArrayDynamicIndexingEXT);
1452 SPIRV::Capability::InputAttachmentArrayNonUniformIndexingEXT);
1453 else if (!FirstIndexIsConstant)
1455 SPIRV::Capability::InputAttachmentArrayDynamicIndexingEXT);
1459 SPIRV::Capability::StorageTexelBufferArrayNonUniformIndexingEXT);
1460 else if (!FirstIndexIsConstant)
1462 SPIRV::Capability::StorageTexelBufferArrayDynamicIndexingEXT);
1465 PointeeType->
getOpcode() == SPIRV::OpTypeSampler) {
1468 SPIRV::Capability::SampledImageArrayNonUniformIndexingEXT);
1469 else if (!FirstIndexIsConstant)
1471 SPIRV::Capability::SampledImageArrayDynamicIndexing);
1475 SPIRV::Capability::StorageImageArrayNonUniformIndexingEXT);
1476 else if (!FirstIndexIsConstant)
1478 SPIRV::Capability::StorageImageArrayDynamicIndexing);
1483 if (TypeInst->
getOpcode() != SPIRV::OpTypeImage)
1492 if (ST.canUseExtension(SPIRV::Extension::SPV_KHR_integer_dot_product))
1493 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_integer_dot_product);
1497 assert(
MI.getOperand(2).isReg() &&
"Unexpected operand in dot");
1498 SPIRVTypeInst TypeDef = ST.getSPIRVGlobalRegistry()->getSPIRVTypeForVReg(
1499 MI.getOperand(2).getReg(),
MI.getMF());
1500 if (TypeDef->
getOpcode() == SPIRV::OpTypeInt) {
1502 Reqs.
addCapability(SPIRV::Capability::DotProductInput4x8BitPacked);
1509 "Dot operand of 8-bit integer type requires 4 components");
1510 Reqs.
addCapability(SPIRV::Capability::DotProductInput4x8Bit);
1526 unsigned AddrSpace = ASOp.
getImm();
1527 if (AddrSpace != SPIRV::StorageClass::UniformConstant) {
1528 if (!ST.canUseExtension(
1530 SPV_EXT_relaxed_printf_string_address_space)) {
1532 "required because printf uses a format string not "
1533 "in constant address space.",
1537 SPIRV::Extension::SPV_EXT_relaxed_printf_string_address_space);
1546 if (
MI.getNumOperands() <= OpIdx)
1548 uint32_t Mask =
MI.getOperand(OpIdx).getImm();
1550 if (Mask & (1U <<
I))
1561 if (ElemTypeDef->
getOpcode() == SPIRV::OpTypePointer &&
1562 ST.canUseExtension(SPIRV::Extension::SPV_INTEL_masked_gather_scatter)) {
1563 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_masked_gather_scatter);
1564 Reqs.
addCapability(SPIRV::Capability::MaskedGatherScatterINTEL);
1572 unsigned Op =
MI.getOpcode();
1574 case SPIRV::OpMemoryModel: {
1575 int64_t Addr =
MI.getOperand(0).getImm();
1578 int64_t Mem =
MI.getOperand(1).getImm();
1583 case SPIRV::OpEntryPoint: {
1584 int64_t Exe =
MI.getOperand(0).getImm();
1589 case SPIRV::OpExecutionMode:
1590 case SPIRV::OpExecutionModeId: {
1591 int64_t Exe =
MI.getOperand(1).getImm();
1596 case SPIRV::OpTypeMatrix:
1599 case SPIRV::OpTypeInt: {
1600 unsigned BitWidth =
MI.getOperand(1).getImm();
1608 ST.canUseExtension(SPIRV::Extension::SPV_INTEL_int4)) {
1612 if (!ST.canUseExtension(
1613 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_integers))
1615 "OpTypeInt type with a width other than 8, 16, 32 or 64 bits "
1616 "requires the following SPIR-V extension: "
1617 "SPV_ALTERA_arbitrary_precision_integers");
1619 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_integers);
1620 Reqs.
addCapability(SPIRV::Capability::ArbitraryPrecisionIntegersALTERA);
1624 case SPIRV::OpDot: {
1628 Reqs.
addCapability(SPIRV::Capability::BFloat16DotProductKHR);
1631 case SPIRV::OpTypeFloat: {
1632 unsigned BitWidth =
MI.getOperand(1).getImm();
1637 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_bfloat16))
1639 "following SPIR-V extension: SPV_KHR_bfloat16",
1649 case SPIRV::OpTypeVector: {
1650 unsigned NumComponents =
MI.getOperand(2).getImm();
1651 if (NumComponents == 8 || NumComponents == 16)
1656 "OpTypeVector with " +
Twine(NumComponents) +
1657 " components requires the following SPIR-V extension: "
1658 "SPV_EXT_long_vector");
1663 case SPIRV::OpTypeVectorIdEXT: {
1664 if (!ST.canUseExtension(SPIRV::Extension::SPV_EXT_long_vector))
1666 "extension: SPV_EXT_long_vector extension");
1667 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_long_vector);
1672 case SPIRV::OpTypePointer: {
1673 auto SC =
MI.getOperand(1).getImm();
1684 (TypeDef->
getOpcode() == SPIRV::OpTypeFloat) &&
1689 case SPIRV::OpExtInst: {
1690 if (
MI.getOperand(2).getImm() ==
1691 static_cast<int64_t
>(
1692 SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100)) {
1693 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_non_semantic_info);
1696 if (
MI.getOperand(3).getImm() ==
1697 static_cast<int64_t
>(SPIRV::OpenCLExtInst::printf)) {
1701 if (
MI.getOperand(2).getImm() ==
1702 static_cast<int64_t
>(SPIRV::InstructionSet::OpenCL_std)) {
1708 if (TypeDef && TypeDef->getOpcode() == SPIRV::OpTypeVector)
1709 TypeDef = MRI.
getVRegDef(TypeDef->getOperand(1).getReg());
1714 bool UsesBFloat16 = IsBFloat16(MRI.
getVRegDef(
MI.getOperand(1).getReg()));
1715 for (
unsigned I = 4,
E =
MI.getNumOperands();
I <
E && !UsesBFloat16;
1724 if (!ST.canUseExtension(
1725 SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic)) {
1727 MI,
"OpenCL Extended instructions with bfloat16 require the "
1728 "following SPIR-V extension: SPV_INTEL_bfloat16_arithmetic");
1731 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic);
1732 Reqs.
addCapability(SPIRV::Capability::BFloat16ArithmeticINTEL);
1737 case SPIRV::OpAliasDomainDeclINTEL:
1738 case SPIRV::OpAliasScopeDeclINTEL:
1739 case SPIRV::OpAliasScopeListDeclINTEL: {
1740 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_memory_access_aliasing);
1741 Reqs.
addCapability(SPIRV::Capability::MemoryAccessAliasingINTEL);
1744 case SPIRV::OpBitReverse:
1745 case SPIRV::OpBitFieldInsert:
1746 case SPIRV::OpBitFieldSExtract:
1747 case SPIRV::OpBitFieldUExtract:
1748 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_bit_instructions)) {
1752 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_bit_instructions);
1755 case SPIRV::OpTypeRuntimeArray:
1758 case SPIRV::OpTypeOpaque:
1759 case SPIRV::OpTypeEvent:
1762 case SPIRV::OpTypePipe:
1763 case SPIRV::OpTypeReserveId:
1766 case SPIRV::OpTypeDeviceEvent:
1767 case SPIRV::OpTypeQueue:
1768 case SPIRV::OpBuildNDRange:
1769 case SPIRV::OpEnqueueKernel:
1770 case SPIRV::OpGetKernelNDrangeSubGroupCount:
1771 case SPIRV::OpGetKernelNDrangeMaxSubGroupSize:
1772 case SPIRV::OpGetKernelWorkGroupSize:
1773 case SPIRV::OpGetKernelPreferredWorkGroupSizeMultiple:
1776 case SPIRV::OpDecorate:
1777 case SPIRV::OpDecorateId:
1778 case SPIRV::OpDecorateString:
1781 case SPIRV::OpMemberDecorate:
1782 case SPIRV::OpMemberDecorateString:
1785 case SPIRV::OpInBoundsPtrAccessChain:
1788 case SPIRV::OpConstantSampler:
1791 case SPIRV::OpInBoundsAccessChain:
1792 case SPIRV::OpAccessChain:
1795 case SPIRV::OpTypeImage:
1798 case SPIRV::OpTypeSampler:
1799 if (!ST.isShader()) {
1803 case SPIRV::OpTypeForwardPointer:
1807 case SPIRV::OpAtomicFlagTestAndSet:
1808 case SPIRV::OpAtomicLoad:
1809 case SPIRV::OpAtomicStore:
1810 case SPIRV::OpAtomicExchange:
1811 case SPIRV::OpAtomicCompareExchange:
1812 case SPIRV::OpAtomicCompareExchangeWeak:
1813 case SPIRV::OpAtomicIIncrement:
1814 case SPIRV::OpAtomicIDecrement:
1815 case SPIRV::OpAtomicIAdd:
1816 case SPIRV::OpAtomicISub:
1817 case SPIRV::OpAtomicUMin:
1818 case SPIRV::OpAtomicUMax:
1819 case SPIRV::OpAtomicSMin:
1820 case SPIRV::OpAtomicSMax:
1821 case SPIRV::OpAtomicAnd:
1822 case SPIRV::OpAtomicOr:
1823 case SPIRV::OpAtomicXor: {
1826 if (
Op == SPIRV::OpAtomicStore) {
1828 TypeDef = ST.getSPIRVGlobalRegistry()->getSPIRVTypeForVReg(
1829 MI.getOperand(3).getReg(),
MI.getMF());
1830 assert(TypeDef &&
"Unexpected type instruction for OpAtomicStore");
1832 assert(
MI.getOperand(1).isReg() &&
"Unexpected operand in atomic");
1836 if (TypeDef->
getOpcode() == SPIRV::OpTypeInt) {
1841 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics))
1843 "16-bit integer atomic operations require the following SPIR-V "
1844 "extension: SPV_INTEL_16bit_atomics",
1846 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics);
1848 case SPIRV::OpAtomicLoad:
1849 case SPIRV::OpAtomicStore:
1850 case SPIRV::OpAtomicExchange:
1851 case SPIRV::OpAtomicCompareExchange:
1852 case SPIRV::OpAtomicCompareExchangeWeak:
1854 SPIRV::Capability::AtomicInt16CompareExchangeINTEL);
1862 if (
is_contained({SPIRV::OpAtomicLoad, SPIRV::OpAtomicStore,
1863 SPIRV::OpAtomicExchange},
1865 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics))
1867 "The atomic bfloat16 instruction requires the following SPIR-V "
1868 "extension: SPV_INTEL_16bit_atomics",
1870 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics);
1871 Reqs.
addCapability(SPIRV::Capability::AtomicBFloat16LoadStoreINTEL);
1876 case SPIRV::OpGroupNonUniformIAdd:
1877 case SPIRV::OpGroupNonUniformFAdd:
1878 case SPIRV::OpGroupNonUniformIMul:
1879 case SPIRV::OpGroupNonUniformFMul:
1880 case SPIRV::OpGroupNonUniformSMin:
1881 case SPIRV::OpGroupNonUniformUMin:
1882 case SPIRV::OpGroupNonUniformFMin:
1883 case SPIRV::OpGroupNonUniformSMax:
1884 case SPIRV::OpGroupNonUniformUMax:
1885 case SPIRV::OpGroupNonUniformFMax:
1886 case SPIRV::OpGroupNonUniformBitwiseAnd:
1887 case SPIRV::OpGroupNonUniformBitwiseOr:
1888 case SPIRV::OpGroupNonUniformBitwiseXor:
1889 case SPIRV::OpGroupNonUniformLogicalAnd:
1890 case SPIRV::OpGroupNonUniformLogicalOr:
1891 case SPIRV::OpGroupNonUniformLogicalXor: {
1893 int64_t GroupOp =
MI.getOperand(3).getImm();
1895 case SPIRV::GroupOperation::Reduce:
1896 case SPIRV::GroupOperation::InclusiveScan:
1897 case SPIRV::GroupOperation::ExclusiveScan:
1898 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformArithmetic);
1900 case SPIRV::GroupOperation::ClusteredReduce:
1901 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformClustered);
1903 case SPIRV::GroupOperation::PartitionedReduceNV:
1904 case SPIRV::GroupOperation::PartitionedInclusiveScanNV:
1905 case SPIRV::GroupOperation::PartitionedExclusiveScanNV:
1906 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformPartitionedNV);
1911 case SPIRV::OpGroupNonUniformQuadSwap:
1914 case SPIRV::OpImageQueryLod:
1917 case SPIRV::OpImageQuerySize:
1918 case SPIRV::OpImageQuerySizeLod:
1919 case SPIRV::OpImageQueryLevels:
1920 case SPIRV::OpImageQuerySamples:
1924 case SPIRV::OpImageQueryFormat: {
1925 Register ResultReg =
MI.getOperand(0).getReg();
1927 static const unsigned CompareOps[] = {
1928 SPIRV::OpIEqual, SPIRV::OpINotEqual,
1929 SPIRV::OpUGreaterThan, SPIRV::OpUGreaterThanEqual,
1930 SPIRV::OpULessThan, SPIRV::OpULessThanEqual,
1931 SPIRV::OpSGreaterThan, SPIRV::OpSGreaterThanEqual,
1932 SPIRV::OpSLessThan, SPIRV::OpSLessThanEqual};
1934 auto CheckAndAddExtension = [&](int64_t ImmVal) {
1935 if (ImmVal == 4323 || ImmVal == 4324) {
1936 if (ST.canUseExtension(SPIRV::Extension::SPV_EXT_image_raw10_raw12))
1937 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_image_raw10_raw12);
1940 "SPV_EXT_image_raw10_raw12 extension");
1945 unsigned Opc = UseInst.getOpcode();
1947 if (
Opc == SPIRV::OpSwitch) {
1950 CheckAndAddExtension(
Op.getImm());
1952 for (
unsigned i = 1; i < UseInst.getNumOperands(); ++i) {
1955 if (ConstInst && ConstInst->
getOpcode() == SPIRV::OpConstantI) {
1958 CheckAndAddExtension(ImmVal);
1966 case SPIRV::OpGroupNonUniformShuffle:
1967 case SPIRV::OpGroupNonUniformShuffleXor:
1968 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformShuffle);
1970 case SPIRV::OpGroupNonUniformShuffleUp:
1971 case SPIRV::OpGroupNonUniformShuffleDown:
1972 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformShuffleRelative);
1974 case SPIRV::OpGroupAll:
1975 case SPIRV::OpGroupAny:
1976 case SPIRV::OpGroupBroadcast:
1977 case SPIRV::OpGroupIAdd:
1978 case SPIRV::OpGroupFAdd:
1979 case SPIRV::OpGroupFMin:
1980 case SPIRV::OpGroupUMin:
1981 case SPIRV::OpGroupSMin:
1982 case SPIRV::OpGroupFMax:
1983 case SPIRV::OpGroupUMax:
1984 case SPIRV::OpGroupSMax:
1987 case SPIRV::OpGroupNonUniformElect:
1990 case SPIRV::OpGroupNonUniformAll:
1991 case SPIRV::OpGroupNonUniformAny:
1992 case SPIRV::OpGroupNonUniformAllEqual:
1995 case SPIRV::OpGroupNonUniformBroadcast:
1996 case SPIRV::OpGroupNonUniformBroadcastFirst:
1997 case SPIRV::OpGroupNonUniformBallot:
1998 case SPIRV::OpGroupNonUniformInverseBallot:
1999 case SPIRV::OpGroupNonUniformBallotBitExtract:
2000 case SPIRV::OpGroupNonUniformBallotBitCount:
2001 case SPIRV::OpGroupNonUniformBallotFindLSB:
2002 case SPIRV::OpGroupNonUniformBallotFindMSB:
2003 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformBallot);
2005 case SPIRV::OpSubgroupShuffleINTEL:
2006 case SPIRV::OpSubgroupShuffleDownINTEL:
2007 case SPIRV::OpSubgroupShuffleUpINTEL:
2008 case SPIRV::OpSubgroupShuffleXorINTEL:
2009 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {
2010 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_subgroups);
2011 Reqs.
addCapability(SPIRV::Capability::SubgroupShuffleINTEL);
2014 case SPIRV::OpSubgroupBlockReadINTEL:
2015 case SPIRV::OpSubgroupBlockWriteINTEL:
2016 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {
2017 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_subgroups);
2018 Reqs.
addCapability(SPIRV::Capability::SubgroupBufferBlockIOINTEL);
2021 case SPIRV::OpSubgroupImageBlockReadINTEL:
2022 case SPIRV::OpSubgroupImageBlockWriteINTEL:
2023 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {
2024 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_subgroups);
2025 Reqs.
addCapability(SPIRV::Capability::SubgroupImageBlockIOINTEL);
2028 case SPIRV::OpSubgroupImageMediaBlockReadINTEL:
2029 case SPIRV::OpSubgroupImageMediaBlockWriteINTEL:
2030 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_media_block_io)) {
2031 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_media_block_io);
2032 Reqs.
addCapability(SPIRV::Capability::SubgroupImageMediaBlockIOINTEL);
2035 case SPIRV::OpAssumeTrueKHR:
2036 case SPIRV::OpExpectKHR:
2037 if (ST.canUseExtension(SPIRV::Extension::SPV_KHR_expect_assume)) {
2038 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_expect_assume);
2042 case SPIRV::OpFmaKHR:
2043 if (ST.canUseExtension(SPIRV::Extension::SPV_KHR_fma)) {
2048 case SPIRV::OpPtrCastToCrossWorkgroupINTEL:
2049 case SPIRV::OpCrossWorkgroupCastToPtrINTEL:
2050 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_usm_storage_classes)) {
2051 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_usm_storage_classes);
2052 Reqs.
addCapability(SPIRV::Capability::USMStorageClassesINTEL);
2055 case SPIRV::OpConstantFunctionPointerINTEL:
2056 case SPIRV::OpFunctionPointerCallINTEL:
2057 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_function_pointers)) {
2058 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_function_pointers);
2059 Reqs.
addCapability(SPIRV::Capability::FunctionPointersINTEL);
2062 case SPIRV::OpGroupNonUniformRotateKHR:
2063 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_subgroup_rotate))
2065 "following SPIR-V extension: SPV_KHR_subgroup_rotate",
2067 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_subgroup_rotate);
2068 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformRotateKHR);
2071 case SPIRV::OpFixedCosALTERA:
2072 case SPIRV::OpFixedSinALTERA:
2073 case SPIRV::OpFixedCosPiALTERA:
2074 case SPIRV::OpFixedSinPiALTERA:
2075 case SPIRV::OpFixedExpALTERA:
2076 case SPIRV::OpFixedLogALTERA:
2077 case SPIRV::OpFixedRecipALTERA:
2078 case SPIRV::OpFixedSqrtALTERA:
2079 case SPIRV::OpFixedSinCosALTERA:
2080 case SPIRV::OpFixedSinCosPiALTERA:
2081 case SPIRV::OpFixedRsqrtALTERA:
2082 if (!ST.canUseExtension(
2083 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_fixed_point))
2085 "following SPIR-V extension: "
2086 "SPV_ALTERA_arbitrary_precision_fixed_point",
2089 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_fixed_point);
2090 Reqs.
addCapability(SPIRV::Capability::ArbitraryPrecisionFixedPointALTERA);
2092 case SPIRV::OpGroupIMulKHR:
2093 case SPIRV::OpGroupFMulKHR:
2094 case SPIRV::OpGroupBitwiseAndKHR:
2095 case SPIRV::OpGroupBitwiseOrKHR:
2096 case SPIRV::OpGroupBitwiseXorKHR:
2097 case SPIRV::OpGroupLogicalAndKHR:
2098 case SPIRV::OpGroupLogicalOrKHR:
2099 case SPIRV::OpGroupLogicalXorKHR:
2100 if (ST.canUseExtension(
2101 SPIRV::Extension::SPV_KHR_uniform_group_instructions)) {
2102 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_uniform_group_instructions);
2103 Reqs.
addCapability(SPIRV::Capability::GroupUniformArithmeticKHR);
2106 case SPIRV::OpReadClockKHR:
2107 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_shader_clock))
2109 "following SPIR-V extension: SPV_KHR_shader_clock",
2111 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_shader_clock);
2114 case SPIRV::OpAbortKHR:
2115 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_abort))
2117 "following SPIR-V extension: SPV_KHR_abort",
2122 case SPIRV::OpPoisonKHR:
2123 case SPIRV::OpFreezeKHR:
2124 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_poison_freeze))
2126 "following SPIR-V extension: SPV_KHR_poison_freeze",
2128 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_poison_freeze);
2131 case SPIRV::OpAtomicFAddEXT:
2132 case SPIRV::OpAtomicFMinEXT:
2133 case SPIRV::OpAtomicFMaxEXT:
2136 case SPIRV::OpConvertBF16ToFINTEL:
2137 case SPIRV::OpConvertFToBF16INTEL:
2138 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bfloat16_conversion)) {
2139 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bfloat16_conversion);
2140 Reqs.
addCapability(SPIRV::Capability::BFloat16ConversionINTEL);
2143 case SPIRV::OpRoundFToTF32INTEL:
2144 if (ST.canUseExtension(
2145 SPIRV::Extension::SPV_INTEL_tensor_float32_conversion)) {
2146 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_tensor_float32_conversion);
2147 Reqs.
addCapability(SPIRV::Capability::TensorFloat32RoundingINTEL);
2150 case SPIRV::OpVariableLengthArrayINTEL:
2151 case SPIRV::OpSaveMemoryINTEL:
2152 case SPIRV::OpRestoreMemoryINTEL:
2153 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_variable_length_array)) {
2154 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_variable_length_array);
2155 Reqs.
addCapability(SPIRV::Capability::VariableLengthArrayINTEL);
2158 case SPIRV::OpUntypedVariableLengthArrayINTEL:
2159 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_variable_length_array)) {
2160 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_variable_length_array);
2161 Reqs.
addCapability(SPIRV::Capability::UntypedVariableLengthArrayINTEL);
2164 case SPIRV::OpAsmTargetINTEL:
2165 case SPIRV::OpAsmINTEL:
2166 case SPIRV::OpAsmCallINTEL:
2167 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_inline_assembly)) {
2168 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_inline_assembly);
2172 case SPIRV::OpTypeCooperativeMatrixKHR: {
2173 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix))
2175 "OpTypeCooperativeMatrixKHR type requires the "
2176 "following SPIR-V extension: SPV_KHR_cooperative_matrix",
2178 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix);
2179 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixKHR);
2183 Reqs.
addCapability(SPIRV::Capability::BFloat16CooperativeMatrixKHR);
2186 case SPIRV::OpArithmeticFenceEXT:
2187 if (!ST.canUseExtension(SPIRV::Extension::SPV_EXT_arithmetic_fence))
2189 "following SPIR-V extension: SPV_EXT_arithmetic_fence",
2191 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_arithmetic_fence);
2194 case SPIRV::OpControlBarrierArriveINTEL:
2195 case SPIRV::OpControlBarrierWaitINTEL:
2196 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_split_barrier)) {
2197 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_split_barrier);
2201 case SPIRV::OpCooperativeMatrixMulAddKHR: {
2202 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix))
2204 "following SPIR-V extension: "
2205 "SPV_KHR_cooperative_matrix",
2207 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix);
2208 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixKHR);
2209 constexpr unsigned MulAddMaxSize = 6;
2210 if (
MI.getNumOperands() != MulAddMaxSize)
2212 const int64_t CoopOperands =
MI.getOperand(MulAddMaxSize - 1).getImm();
2214 SPIRV::CooperativeMatrixOperands::MatrixAAndBTF32ComponentsINTEL) {
2215 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
2217 "require the following SPIR-V extension: "
2218 "SPV_INTEL_joint_matrix",
2220 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2222 SPIRV::Capability::CooperativeMatrixTF32ComponentTypeINTEL);
2225 MatrixAAndBBFloat16ComponentsINTEL ||
2227 SPIRV::CooperativeMatrixOperands::MatrixCBFloat16ComponentsINTEL ||
2229 MatrixResultBFloat16ComponentsINTEL) {
2230 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
2232 "require the following SPIR-V extension: "
2233 "SPV_INTEL_joint_matrix",
2235 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2237 SPIRV::Capability::CooperativeMatrixBFloat16ComponentTypeINTEL);
2241 case SPIRV::OpCooperativeMatrixLoadKHR:
2242 case SPIRV::OpCooperativeMatrixStoreKHR:
2243 case SPIRV::OpCooperativeMatrixLoadCheckedINTEL:
2244 case SPIRV::OpCooperativeMatrixStoreCheckedINTEL:
2245 case SPIRV::OpCooperativeMatrixPrefetchINTEL: {
2246 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix))
2248 "following SPIR-V extension: "
2249 "SPV_KHR_cooperative_matrix",
2251 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix);
2252 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixKHR);
2258 case SPIRV::OpCooperativeMatrixLoadKHR:
2261 case SPIRV::OpCooperativeMatrixStoreKHR:
2264 case SPIRV::OpCooperativeMatrixLoadCheckedINTEL:
2267 case SPIRV::OpCooperativeMatrixStoreCheckedINTEL:
2268 case SPIRV::OpCooperativeMatrixPrefetchINTEL:
2274 Register RegLayout =
MI.getOperand(LayoutNum).getReg();
2277 if (MILayout->
getOpcode() == SPIRV::OpConstantI) {
2280 static_cast<unsigned>(SPIRV::CooperativeMatrixLayout::PackedINTEL)) {
2281 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
2283 "extension: SPV_INTEL_joint_matrix",
2285 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2286 Reqs.
addCapability(SPIRV::Capability::PackedCooperativeMatrixINTEL);
2291 if (
Op == SPIRV::OpCooperativeMatrixLoadKHR ||
2292 Op == SPIRV::OpCooperativeMatrixStoreKHR)
2295 std::string InstName;
2297 case SPIRV::OpCooperativeMatrixPrefetchINTEL:
2298 InstName =
"OpCooperativeMatrixPrefetchINTEL";
2300 case SPIRV::OpCooperativeMatrixLoadCheckedINTEL:
2301 InstName =
"OpCooperativeMatrixLoadCheckedINTEL";
2303 case SPIRV::OpCooperativeMatrixStoreCheckedINTEL:
2304 InstName =
"OpCooperativeMatrixStoreCheckedINTEL";
2308 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix)) {
2309 const std::string ErrorMsg =
2310 InstName +
" instruction requires the "
2311 "following SPIR-V extension: SPV_INTEL_joint_matrix";
2314 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2315 if (
Op == SPIRV::OpCooperativeMatrixPrefetchINTEL) {
2316 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixPrefetchINTEL);
2320 SPIRV::Capability::CooperativeMatrixCheckedInstructionsINTEL);
2323 case SPIRV::OpCooperativeMatrixConstructCheckedINTEL:
2324 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
2326 "instructions require the following SPIR-V extension: "
2327 "SPV_INTEL_joint_matrix",
2329 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2331 SPIRV::Capability::CooperativeMatrixCheckedInstructionsINTEL);
2333 case SPIRV::OpReadPipeBlockingALTERA:
2334 case SPIRV::OpWritePipeBlockingALTERA:
2335 if (ST.canUseExtension(SPIRV::Extension::SPV_ALTERA_blocking_pipes)) {
2336 Reqs.
addExtension(SPIRV::Extension::SPV_ALTERA_blocking_pipes);
2340 case SPIRV::OpCooperativeMatrixGetElementCoordINTEL:
2341 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
2343 "following SPIR-V extension: SPV_INTEL_joint_matrix",
2345 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2347 SPIRV::Capability::CooperativeMatrixInvocationInstructionsINTEL);
2349 case SPIRV::OpConvertHandleToImageINTEL:
2350 case SPIRV::OpConvertHandleToSamplerINTEL:
2351 case SPIRV::OpConvertHandleToSampledImageINTEL: {
2352 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bindless_images))
2354 "instructions require the following SPIR-V extension: "
2355 "SPV_INTEL_bindless_images",
2358 SPIRV::AddressingModel::AddressingModel AddrModel = MAI.
Addr;
2360 if (
Op == SPIRV::OpConvertHandleToImageINTEL &&
2361 TyDef->
getOpcode() != SPIRV::OpTypeImage) {
2363 "OpConvertHandleToImageINTEL",
2365 }
else if (
Op == SPIRV::OpConvertHandleToSamplerINTEL &&
2366 TyDef->
getOpcode() != SPIRV::OpTypeSampler) {
2368 "OpConvertHandleToSamplerINTEL",
2370 }
else if (
Op == SPIRV::OpConvertHandleToSampledImageINTEL &&
2371 TyDef->
getOpcode() != SPIRV::OpTypeSampledImage) {
2373 "OpConvertHandleToSampledImageINTEL",
2378 if (!(Bitwidth == 32 && AddrModel == SPIRV::AddressingModel::Physical32) &&
2379 !(Bitwidth == 64 && AddrModel == SPIRV::AddressingModel::Physical64)) {
2381 "Parameter value must be a 32-bit scalar in case of "
2382 "Physical32 addressing model or a 64-bit scalar in case of "
2383 "Physical64 addressing model",
2386 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bindless_images);
2390 case SPIRV::OpSubgroup2DBlockLoadINTEL:
2391 case SPIRV::OpSubgroup2DBlockLoadTransposeINTEL:
2392 case SPIRV::OpSubgroup2DBlockLoadTransformINTEL:
2393 case SPIRV::OpSubgroup2DBlockPrefetchINTEL:
2394 case SPIRV::OpSubgroup2DBlockStoreINTEL: {
2395 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_2d_block_io))
2397 "Prefetch/Store]INTEL instructions require the "
2398 "following SPIR-V extension: SPV_INTEL_2d_block_io",
2400 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_2d_block_io);
2401 Reqs.
addCapability(SPIRV::Capability::Subgroup2DBlockIOINTEL);
2403 if (
Op == SPIRV::OpSubgroup2DBlockLoadTransposeINTEL) {
2404 Reqs.
addCapability(SPIRV::Capability::Subgroup2DBlockTransposeINTEL);
2407 if (
Op == SPIRV::OpSubgroup2DBlockLoadTransformINTEL) {
2408 Reqs.
addCapability(SPIRV::Capability::Subgroup2DBlockTransformINTEL);
2413 case SPIRV::OpKill: {
2416 case SPIRV::OpDemoteToHelperInvocation:
2417 Reqs.
addCapability(SPIRV::Capability::DemoteToHelperInvocation);
2419 if (ST.canUseExtension(
2420 SPIRV::Extension::SPV_EXT_demote_to_helper_invocation)) {
2423 SPIRV::Extension::SPV_EXT_demote_to_helper_invocation);
2428 case SPIRV::OpSUDot:
2429 case SPIRV::OpSDotAccSat:
2430 case SPIRV::OpUDotAccSat:
2431 case SPIRV::OpSUDotAccSat:
2434 case SPIRV::OpImageSampleImplicitLod:
2435 case SPIRV::OpImageFetch:
2439 case SPIRV::OpImageSampleExplicitLod:
2442 case SPIRV::OpImageSampleDrefImplicitLod:
2443 case SPIRV::OpImageSampleDrefExplicitLod:
2444 case SPIRV::OpImageDrefGather:
2445 case SPIRV::OpImageGather:
2449 case SPIRV::OpImageRead: {
2450 Register ImageReg =
MI.getOperand(2).getReg();
2451 SPIRVTypeInst TypeDef = ST.getSPIRVGlobalRegistry()->getResultType(
2460 Reqs.
addCapability(SPIRV::Capability::StorageImageReadWithoutFormat);
2463 case SPIRV::OpImageWrite: {
2464 Register ImageReg =
MI.getOperand(0).getReg();
2465 SPIRVTypeInst TypeDef = ST.getSPIRVGlobalRegistry()->getResultType(
2474 Reqs.
addCapability(SPIRV::Capability::StorageImageWriteWithoutFormat);
2477 case SPIRV::OpTypeStructContinuedINTEL:
2478 case SPIRV::OpConstantCompositeContinuedINTEL:
2479 case SPIRV::OpSpecConstantCompositeContinuedINTEL:
2480 case SPIRV::OpCompositeConstructContinuedINTEL: {
2481 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_long_composites))
2483 "Continued instructions require the "
2484 "following SPIR-V extension: SPV_INTEL_long_composites",
2486 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_long_composites);
2490 case SPIRV::OpArbitraryFloatEQALTERA:
2491 case SPIRV::OpArbitraryFloatGEALTERA:
2492 case SPIRV::OpArbitraryFloatGTALTERA:
2493 case SPIRV::OpArbitraryFloatLEALTERA:
2494 case SPIRV::OpArbitraryFloatLTALTERA:
2495 case SPIRV::OpArbitraryFloatCbrtALTERA:
2496 case SPIRV::OpArbitraryFloatCosALTERA:
2497 case SPIRV::OpArbitraryFloatCosPiALTERA:
2498 case SPIRV::OpArbitraryFloatExp10ALTERA:
2499 case SPIRV::OpArbitraryFloatExp2ALTERA:
2500 case SPIRV::OpArbitraryFloatExpALTERA:
2501 case SPIRV::OpArbitraryFloatExpm1ALTERA:
2502 case SPIRV::OpArbitraryFloatHypotALTERA:
2503 case SPIRV::OpArbitraryFloatLog10ALTERA:
2504 case SPIRV::OpArbitraryFloatLog1pALTERA:
2505 case SPIRV::OpArbitraryFloatLog2ALTERA:
2506 case SPIRV::OpArbitraryFloatLogALTERA:
2507 case SPIRV::OpArbitraryFloatRecipALTERA:
2508 case SPIRV::OpArbitraryFloatSinCosALTERA:
2509 case SPIRV::OpArbitraryFloatSinCosPiALTERA:
2510 case SPIRV::OpArbitraryFloatSinALTERA:
2511 case SPIRV::OpArbitraryFloatSinPiALTERA:
2512 case SPIRV::OpArbitraryFloatSqrtALTERA:
2513 case SPIRV::OpArbitraryFloatACosALTERA:
2514 case SPIRV::OpArbitraryFloatACosPiALTERA:
2515 case SPIRV::OpArbitraryFloatAddALTERA:
2516 case SPIRV::OpArbitraryFloatASinALTERA:
2517 case SPIRV::OpArbitraryFloatASinPiALTERA:
2518 case SPIRV::OpArbitraryFloatATan2ALTERA:
2519 case SPIRV::OpArbitraryFloatATanALTERA:
2520 case SPIRV::OpArbitraryFloatATanPiALTERA:
2521 case SPIRV::OpArbitraryFloatCastFromIntALTERA:
2522 case SPIRV::OpArbitraryFloatCastALTERA:
2523 case SPIRV::OpArbitraryFloatCastToIntALTERA:
2524 case SPIRV::OpArbitraryFloatDivALTERA:
2525 case SPIRV::OpArbitraryFloatMulALTERA:
2526 case SPIRV::OpArbitraryFloatPowALTERA:
2527 case SPIRV::OpArbitraryFloatPowNALTERA:
2528 case SPIRV::OpArbitraryFloatPowRALTERA:
2529 case SPIRV::OpArbitraryFloatRSqrtALTERA:
2530 case SPIRV::OpArbitraryFloatSubALTERA: {
2531 if (!ST.canUseExtension(
2532 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_floating_point))
2534 "Floating point instructions can't be translated correctly without "
2535 "enabled SPV_ALTERA_arbitrary_precision_floating_point extension!",
2538 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_floating_point);
2540 SPIRV::Capability::ArbitraryPrecisionFloatingPointALTERA);
2543 case SPIRV::OpSubgroupMatrixMultiplyAccumulateINTEL: {
2544 if (!ST.canUseExtension(
2545 SPIRV::Extension::SPV_INTEL_subgroup_matrix_multiply_accumulate))
2547 "OpSubgroupMatrixMultiplyAccumulateINTEL instruction requires the "
2549 "extension: SPV_INTEL_subgroup_matrix_multiply_accumulate",
2552 SPIRV::Extension::SPV_INTEL_subgroup_matrix_multiply_accumulate);
2554 SPIRV::Capability::SubgroupMatrixMultiplyAccumulateINTEL);
2557 case SPIRV::OpBitwiseFunctionINTEL: {
2558 if (!ST.canUseExtension(
2559 SPIRV::Extension::SPV_INTEL_ternary_bitwise_function))
2561 "OpBitwiseFunctionINTEL instruction requires the following SPIR-V "
2562 "extension: SPV_INTEL_ternary_bitwise_function",
2564 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_ternary_bitwise_function);
2565 Reqs.
addCapability(SPIRV::Capability::TernaryBitwiseFunctionINTEL);
2568 case SPIRV::OpCopyMemorySized: {
2573 case SPIRV::OpTypeUntypedPointerKHR:
2575 MI.getOperand(1).getImm(), ST);
2577 case SPIRV::OpUntypedVariableKHR:
2578 case SPIRV::OpUntypedAccessChainKHR:
2579 case SPIRV::OpUntypedInBoundsAccessChainKHR:
2580 case SPIRV::OpUntypedPtrAccessChainKHR:
2581 case SPIRV::OpUntypedInBoundsPtrAccessChainKHR:
2582 case SPIRV::OpUntypedPrefetchKHR:
2583 case SPIRV::OpUntypedGroupAsyncCopyKHR: {
2584 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_untyped_pointers))
2586 "SPIR-V extension: SPV_KHR_untyped_pointers",
2588 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_untyped_pointers);
2592 case SPIRV::OpPredicatedLoadINTEL:
2593 case SPIRV::OpPredicatedStoreINTEL: {
2594 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_predicated_io))
2596 "OpPredicated[Load/Store]INTEL instructions require "
2597 "the following SPIR-V extension: SPV_INTEL_predicated_io",
2599 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_predicated_io);
2603 case SPIRV::OpFAddS:
2604 case SPIRV::OpFSubS:
2605 case SPIRV::OpFMulS:
2606 case SPIRV::OpFDivS:
2607 case SPIRV::OpFRemS:
2609 case SPIRV::OpFNegate:
2610 case SPIRV::OpFAddV:
2611 case SPIRV::OpFSubV:
2612 case SPIRV::OpFMulV:
2613 case SPIRV::OpFDivV:
2614 case SPIRV::OpFRemV:
2615 case SPIRV::OpFNegateV: {
2621 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic))
2623 "Arithmetic instructions with bfloat16 arguments require the "
2624 "following SPIR-V extension: SPV_INTEL_bfloat16_arithmetic",
2626 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic);
2627 Reqs.
addCapability(SPIRV::Capability::BFloat16ArithmeticINTEL);
2631 case SPIRV::OpOrdered:
2632 case SPIRV::OpUnordered:
2633 case SPIRV::OpFOrdEqual:
2634 case SPIRV::OpFOrdNotEqual:
2635 case SPIRV::OpFOrdLessThan:
2636 case SPIRV::OpFOrdLessThanEqual:
2637 case SPIRV::OpFOrdGreaterThan:
2638 case SPIRV::OpFOrdGreaterThanEqual:
2639 case SPIRV::OpFUnordEqual:
2640 case SPIRV::OpFUnordNotEqual:
2641 case SPIRV::OpFUnordLessThan:
2642 case SPIRV::OpFUnordLessThanEqual:
2643 case SPIRV::OpFUnordGreaterThan:
2644 case SPIRV::OpFUnordGreaterThanEqual: {
2646 SPIRVTypeInst TypeDef = ST.getSPIRVGlobalRegistry()->getSPIRVTypeForVReg(
2647 MI.getOperand(2).getReg(),
MI.getMF());
2651 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic))
2653 "Relational instructions with bfloat16 arguments require the "
2654 "following SPIR-V extension: SPV_INTEL_bfloat16_arithmetic",
2656 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic);
2657 Reqs.
addCapability(SPIRV::Capability::BFloat16ArithmeticINTEL);
2661 case SPIRV::OpDPdxCoarse:
2662 case SPIRV::OpDPdyCoarse:
2663 case SPIRV::OpDPdxFine:
2664 case SPIRV::OpDPdyFine: {
2668 case SPIRV::OpLoopControlINTEL: {
2669 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_unstructured_loop_controls);
2670 Reqs.
addCapability(SPIRV::Capability::UnstructuredLoopControlsINTEL);
2682 SPIRV::Capability::Shader);
2697 auto Node = M.getNamedMetadata(
"spirv.ExecutionMode");
2699 bool RequireFloatControls =
false, RequireIntelFloatControls2 =
false,
2700 RequireKHRFloatControls2 =
false,
2701 VerLower14 = !ST.isAtLeastSPIRVVer(
VersionTuple(1, 4));
2702 bool HasIntelFloatControls2 =
2703 ST.canUseExtension(SPIRV::Extension::SPV_INTEL_float_controls2);
2704 bool HasKHRFloatControls2 =
2705 ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2);
2706 for (
unsigned i = 0; i <
Node->getNumOperands(); i++) {
2712 auto EM = Const->getZExtValue();
2716 case SPIRV::ExecutionMode::DenormPreserve:
2717 case SPIRV::ExecutionMode::DenormFlushToZero:
2718 case SPIRV::ExecutionMode::RoundingModeRTE:
2719 case SPIRV::ExecutionMode::RoundingModeRTZ:
2720 RequireFloatControls = VerLower14;
2722 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2724 case SPIRV::ExecutionMode::RoundingModeRTPINTEL:
2725 case SPIRV::ExecutionMode::RoundingModeRTNINTEL:
2726 case SPIRV::ExecutionMode::FloatingPointModeALTINTEL:
2727 case SPIRV::ExecutionMode::FloatingPointModeIEEEINTEL:
2728 if (HasIntelFloatControls2) {
2729 RequireIntelFloatControls2 =
true;
2731 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2734 case SPIRV::ExecutionMode::FPFastMathDefault: {
2735 if (HasKHRFloatControls2) {
2736 RequireKHRFloatControls2 =
true;
2738 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2742 case SPIRV::ExecutionMode::ContractionOff:
2743 case SPIRV::ExecutionMode::SignedZeroInfNanPreserve:
2744 if (HasKHRFloatControls2) {
2745 RequireKHRFloatControls2 =
true;
2747 SPIRV::OperandCategory::ExecutionModeOperand,
2748 SPIRV::ExecutionMode::FPFastMathDefault, ST);
2751 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2756 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2761 if (RequireFloatControls &&
2762 ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls))
2764 if (RequireIntelFloatControls2)
2766 if (RequireKHRFloatControls2)
2770 if (
F.isDeclaration())
2772 if (
F.getMetadata(
"reqd_work_group_size"))
2774 SPIRV::OperandCategory::ExecutionModeOperand,
2775 SPIRV::ExecutionMode::LocalSize, ST);
2776 if (
F.getFnAttribute(
"hlsl.numthreads").isValid()) {
2778 SPIRV::OperandCategory::ExecutionModeOperand,
2779 SPIRV::ExecutionMode::LocalSize, ST);
2781 if (
F.getFnAttribute(
"enable-maximal-reconvergence").getValueAsBool()) {
2784 if (
F.getMetadata(
"work_group_size_hint"))
2786 SPIRV::OperandCategory::ExecutionModeOperand,
2787 SPIRV::ExecutionMode::LocalSizeHint, ST);
2788 if (
F.getMetadata(
"intel_reqd_sub_group_size") ||
2789 F.getMetadata(
"reqd_sub_group_size"))
2791 SPIRV::OperandCategory::ExecutionModeOperand,
2792 SPIRV::ExecutionMode::SubgroupSize, ST);
2793 if (
F.getMetadata(
"max_work_group_size"))
2795 SPIRV::OperandCategory::ExecutionModeOperand,
2796 SPIRV::ExecutionMode::MaxWorkgroupSizeINTEL, ST);
2797 if (
F.getMetadata(
"vec_type_hint"))
2799 SPIRV::OperandCategory::ExecutionModeOperand,
2800 SPIRV::ExecutionMode::VecTypeHint, ST);
2802 if (
F.hasOptNone()) {
2803 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_optnone)) {
2806 }
else if (ST.canUseExtension(SPIRV::Extension::SPV_EXT_optnone)) {
2816 unsigned Flags = SPIRV::FPFastMathMode::None;
2817 bool CanUseKHRFloatControls2 =
2818 ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2);
2820 Flags |= SPIRV::FPFastMathMode::NotNaN;
2822 Flags |= SPIRV::FPFastMathMode::NotInf;
2824 Flags |= SPIRV::FPFastMathMode::NSZ;
2826 Flags |= SPIRV::FPFastMathMode::AllowRecip;
2828 Flags |= SPIRV::FPFastMathMode::AllowContract;
2830 if (CanUseKHRFloatControls2)
2838 Flags |= SPIRV::FPFastMathMode::NotNaN | SPIRV::FPFastMathMode::NotInf |
2839 SPIRV::FPFastMathMode::NSZ | SPIRV::FPFastMathMode::AllowRecip |
2840 SPIRV::FPFastMathMode::AllowTransform |
2841 SPIRV::FPFastMathMode::AllowReassoc |
2842 SPIRV::FPFastMathMode::AllowContract;
2844 Flags |= SPIRV::FPFastMathMode::Fast;
2847 if (CanUseKHRFloatControls2) {
2849 assert(!(Flags & SPIRV::FPFastMathMode::Fast) &&
2850 "SPIRV::FPFastMathMode::Fast is deprecated and should not be used "
2855 assert((!(Flags & SPIRV::FPFastMathMode::AllowTransform) ||
2856 ((Flags & SPIRV::FPFastMathMode::AllowReassoc &&
2857 Flags & SPIRV::FPFastMathMode::AllowContract))) &&
2858 "SPIRV::FPFastMathMode::AllowTransform requires AllowReassoc and "
2859 "AllowContract flags to be enabled as well.");
2870 return ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2);
2880 auto Decorate = [&](SPIRV::Decoration::Decoration Dec,
2887 if (
TII.canUseIntegerWrapDecoration(
I)) {
2890 SPIRV::OperandCategory::DecorationOperand,
2891 SPIRV::Decoration::NoSignedWrap, ST, Reqs)
2893 Decorate(SPIRV::Decoration::NoSignedWrap, {});
2896 SPIRV::OperandCategory::DecorationOperand,
2897 SPIRV::Decoration::NoUnsignedWrap, ST, Reqs)
2899 Decorate(SPIRV::Decoration::NoUnsignedWrap, {});
2904 TII.canUseFastMathFlags(
2905 I, ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2)) ||
2906 (ST.isKernel() &&
I.getOpcode() == SPIRV::OpExtInst);
2911 if (FMFlags == SPIRV::FPFastMathMode::None) {
2914 if (FPFastMathDefaultInfoVec.
empty())
2930 assert(
I.getNumOperands() >= 3 &&
"Expected at least 3 operands");
2931 Register ResReg =
I.getOpcode() == SPIRV::OpExtInst
2932 ?
I.getOperand(1).getReg()
2933 :
I.getOperand(2).getReg();
2941 if (Ty == Elem.Ty) {
2942 FMFlags = Elem.FastMathFlags;
2943 Emit = Elem.ContractionOff || Elem.SignedZeroInfNanPreserve ||
2944 Elem.FPFastMathDefault;
2949 if (FMFlags == SPIRV::FPFastMathMode::None && !Emit)
2953 Decorate(SPIRV::Decoration::FPFastMathMode, {FMFlags});
2967 for (
const auto &
MBB : *MF) {
2968 if (!
MBB.hasName() ||
MBB.empty())
2979 auto it = FPFastMathDefaultInfoMap.
find(
F);
2980 if (it != FPFastMathDefaultInfoMap.
end())
2988 SPIRV::FPFastMathMode::None);
2990 SPIRV::FPFastMathMode::None);
2992 SPIRV::FPFastMathMode::None);
2993 return FPFastMathDefaultInfoMap[
F] = std::move(FPFastMathDefaultInfoVec);
2999 size_t BitWidth = Ty->getScalarSizeInBits();
3003 assert(Index >= 0 && Index < 3 &&
3004 "Expected FPFastMathDefaultInfo for half, float, or double");
3005 assert(FPFastMathDefaultInfoVec.
size() == 3 &&
3006 "Expected FPFastMathDefaultInfoVec to have exactly 3 elements");
3007 return FPFastMathDefaultInfoVec[Index];
3014 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2))
3023 auto Node = M.getNamedMetadata(
"spirv.ExecutionMode");
3027 for (
unsigned i = 0; i <
Node->getNumOperands(); i++) {
3032 if (OnlyF &&
F != OnlyF)
3038 if (EM == SPIRV::ExecutionMode::FPFastMathDefault) {
3040 "Expected 4 operands for FPFastMathDefault");
3051 Info.FastMathFlags = Flags;
3052 Info.FPFastMathDefault =
true;
3053 }
else if (EM == SPIRV::ExecutionMode::ContractionOff) {
3055 "Expected no operands for ContractionOff");
3062 Info.ContractionOff =
true;
3064 }
else if (EM == SPIRV::ExecutionMode::SignedZeroInfNanPreserve) {
3066 "Expected 1 operand for SignedZeroInfNanPreserve");
3067 unsigned TargetWidth =
3076 assert(Index >= 0 && Index < 3 &&
3077 "Expected FPFastMathDefaultInfo for half, float, or double");
3078 assert(FPFastMathDefaultInfoVec.
size() == 3 &&
3079 "Expected FPFastMathDefaultInfoVec to have exactly 3 elements");
3080 FPFastMathDefaultInfoVec[Index].SignedZeroInfNanPreserve =
true;
3088 : ST(&ST), GR(ST.getSPIRVGlobalRegistry()), TII(ST.getInstrInfo()),
3089 MAI(MAI), GetMF(GetMF) {}
3101 collectDeclarations(M);
3104 numberRegistersGlobally(M);
3107 processOtherInstrs(M);
3111 MAI.Reqs.addCapability(SPIRV::Capability::Linkage);
3114 GR->setBound(MAI.MaxID);
3128 [&MMI](
const Function &
F) { return MMI.getMachineFunction(F); })
3144 MachineFunctionAnalysis::Result *MFA =
3145 FAM.getCachedResult<MachineFunctionAnalysis>(
3146 const_cast<Function &>(F));
3147 assert((MFA || F.isDeclaration()) &&
3148 "Missing MachineFunction for definition");
3149 return MFA ? &MFA->getMF() : nullptr;
3166 for (
auto &
MBB : MF)
3169 FPFastMathDefaultInfoMap[&
F]);
3177 SPIRVPrepareModuleAnalysisLegacy() : MachineFunctionPass(
ID) {}
3184char SPIRVPrepareModuleAnalysisLegacy::ID = 0;
3187 "spirv-prepare-module-analysis",
3188 "SPIRV prepare module analysis",
false,
false)
3191 return new SPIRVPrepareModuleAnalysisLegacy();
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
ReachingDefInfo InstSet & ToRemove
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define clEnumValN(ENUMVAL, FLAGNAME, DESC)
static Register UseReg(const MachineOperand &MO)
const HexagonInstrInfo * TII
Promote Memory to Register
FunctionAnalysisManager FAM
ModuleAnalysisManager MAM
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
#define ATOM_FLT_REQ_EXT_MSG(ExtName)
static bool isFastMathModeAvailable(const SPIRVSubtarget &ST)
static void addMBBNames(const Module &M, MachineFunctionGetter GetMF, SPIRV::ModuleAnalysisInfo &MAI)
static void maybeAddScatterGatherReq(const MachineInstr &MI, SPIRV::RequirementHandler &Reqs, const SPIRVSubtarget &ST)
static void addImageOperandReqs(const MachineInstr &MI, SPIRV::RequirementHandler &Reqs, const SPIRVSubtarget &ST, unsigned OpIdx)
bool isStorageImage(MachineInstr *ImageInst)
bool isInputAttachment(MachineInstr *ImageInst)
static bool isBFloat16Type(SPIRVTypeInst TypeDef)
static bool handleMIFlagDecoration(MachineInstr &I, const SPIRVSubtarget &ST, const SPIRVInstrInfo &TII, SPIRV::RequirementHandler &Reqs, const SPIRVGlobalRegistry *GR, SPIRV::FPFastMathDefaultInfoVector &FPFastMathDefaultInfoVec)
bool isSampledImage(MachineInstr *ImageInst)
static cl::list< SPIRV::Capability::Capability > AvoidCapabilities("avoid-spirv-capabilities", cl::desc("SPIR-V capabilities to avoid if there are " "other options enabling a feature"), cl::Hidden, cl::values(clEnumValN(SPIRV::Capability::Shader, "Shader", "SPIR-V Shader capability")))
static unsigned getInvokeOperandIdx(unsigned Opcode)
static SPIRV::FPFastMathDefaultInfo & getFPFastMathDefaultInfo(SPIRV::FPFastMathDefaultInfoVector &FPFastMathDefaultInfoVec, const Type *Ty)
static cl::opt< bool > SPVDumpDeps("spv-dump-deps", cl::desc("Dump MIR with SPIR-V dependencies info"), cl::init(false))
static void collectFPFastMathDefaults(const Module &M, SPIRV::FPFastMathDefaultInfoMapTy &FPFastMathDefaultInfoMap, const SPIRVSubtarget &ST, const Function *OnlyF=nullptr)
static void collectOtherInstr(MachineInstr &MI, SPIRV::ModuleAnalysisInfo &MAI, SPIRV::ModuleSectionType MSType, InstrTraces &IS, bool Append=true)
void addPrintfRequirements(const MachineInstr &MI, SPIRV::RequirementHandler &Reqs, const SPIRVSubtarget &ST)
static void addOpTypeImageReqs(const MachineInstr &MI, SPIRV::RequirementHandler &Reqs, const SPIRVSubtarget &ST)
static bool isImageTypeWithUnknownFormat(SPIRVTypeInst TypeInst)
bool isUniformTexelBuffer(MachineInstr *ImageInst)
bool isStorageTexelBuffer(MachineInstr *ImageInst)
static void AddAtomicFloatRequirements(const MachineInstr &MI, SPIRV::RequirementHandler &Reqs, const SPIRVSubtarget &ST)
bool isCombinedImageSampler(MachineInstr *SampledImageInst)
bool hasNonUniformDecoration(Register Reg, const MachineRegisterInfo &MRI)
void addInstrRequirements(const MachineInstr &MI, SPIRV::ModuleAnalysisInfo &MAI, const SPIRVSubtarget &ST)
static void collectReqs(const Module &M, SPIRV::ModuleAnalysisInfo &MAI, MachineFunctionGetter GetMF, const SPIRVSubtarget &ST)
static void addOpDecorateReqs(const MachineInstr &MI, unsigned DecIndex, SPIRV::RequirementHandler &Reqs, const SPIRVSubtarget &ST)
static InstrSignature instrToSignature(const MachineInstr &MI, SPIRV::ModuleAnalysisInfo &MAI, bool UseDefReg)
static void AddDotProductRequirements(const MachineInstr &MI, SPIRV::RequirementHandler &Reqs, const SPIRVSubtarget &ST)
static SPIRV::Requirements getSymbolicOperandRequirements(SPIRV::OperandCategory::OperandCategory Category, unsigned i, const SPIRVSubtarget &ST, SPIRV::RequirementHandler &Reqs)
static unsigned getMetadataUInt(MDNode *MdNode, unsigned OpIndex, unsigned DefaultVal=0)
void addOpAccessChainReqs(const MachineInstr &Instr, SPIRV::RequirementHandler &Handler, const SPIRVSubtarget &Subtarget)
static bool prepareModuleAnalysis(MachineFunction &MF)
static void appendDecorationsForReg(const MachineRegisterInfo &MRI, Register R, InstrSignature &Signature)
static SPIRV::FPFastMathDefaultInfoVector & getOrCreateFPFastMathDefaultInfoVec(const Module &M, SPIRV::FPFastMathDefaultInfoMapTy &FPFastMathDefaultInfoMap, const Function *F)
static void AddAtomicVectorFloatRequirements(const MachineInstr &MI, SPIRV::RequirementHandler &Reqs, const SPIRVSubtarget &ST)
static unsigned getFastMathFlags(const MachineInstr &I, const SPIRVSubtarget &ST)
#define SPIRV_BACKEND_SERVICE_FUN_NAME
Target-Independent Code Generator Pass Configuration Options pass.
static Function * getFunction(FunctionType *Ty, const Twine &Name, Module *M)
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
Represent a constant reference to an array (0 or more elements consecutively in memory),...
bool isValid() const
Return true if the attribute is any kind of attribute.
This is the shared class of boolean and integer constants.
This is an important base class in LLVM.
iterator find(const_arg_type_t< KeyT > Val)
Diagnostic information for unsupported feature in backend.
FunctionPass class - This class is used to implement most global optimizations.
Attribute getFnAttribute(Attribute::AttrKind Kind) const
Return the attribute for the given attribute kind.
Wrapper class representing physical registers. Should be passed by value.
constexpr bool isValid() const
const MDOperand & getOperand(unsigned I) const
unsigned getNumOperands() const
Return number of MDNode operands.
Tracking metadata reference owned by Metadata.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
MachineInstrBundleIterator< MachineInstr > iterator
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
Helper class to build MachineInstr.
void setDebugLoc(const DebugLoc &DL)
Set the debug location to DL for all the next build instructions.
Register getReg(unsigned Idx) const
Get the register for the operand index.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineBasicBlock * getParent() const
unsigned getNumOperands() const
Retuns the total number of operands.
LLVM_ABI const MachineFunction * getMF() const
Return the function that contains the basic block that this instruction belongs to.
const MachineOperand & getOperand(unsigned i) const
An analysis that produces MachineModuleInfo for a module.
This class contains meta information specific to a module.
MachineOperand class - Representation of each machine instruction operand.
unsigned getSubReg() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
LLVM_ABI void print(raw_ostream &os, const TargetRegisterInfo *TRI=nullptr) const
Print the MachineOperand to os.
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
static MachineOperand CreateImm(int64_t Val)
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
LLVM_ABI LLVM_READONLY MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
iterator_range< reg_instr_iterator > reg_instructions(Register Reg) const
iterator_range< use_instr_iterator > use_instructions(Register Reg) const
LLVM_ABI LLVM_READONLY MachineInstr * getUniqueVRegDef(Register Reg) const
getUniqueVRegDef - Return the unique machine instr that defines the specified virtual register or nul...
A Module instance is used to store all the information related to an LLVM module.
AnalysisType & getAnalysis() const
getAnalysis<AnalysisType>() - This function is used by subclasses to get to the analysis information ...
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Wrapper class representing virtual and physical registers.
constexpr bool isValid() const
unsigned getScalarOrVectorBitWidth(SPIRVTypeInst Type) const
SPIRVTypeInst getResultType(Register VReg, MachineFunction *MF=nullptr)
const Type * getTypeForSPIRVType(SPIRVTypeInst Ty) const
SPIRVTypeInst getSPIRVTypeForVReg(Register VReg, const MachineFunction *MF=nullptr) const
bool isConstantInstr(const MachineInstr &MI) const
void run(const Module &M)
SPIRVModuleAnalysisImpl(const SPIRVSubtarget &ST, SPIRV::ModuleAnalysisInfo &MAI, MachineFunctionGetter GetMF)
SPIRV::ModuleAnalysisInfo Result
Result run(Module &M, ModuleAnalysisManager &MAM)
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
const SPIRVInstrInfo * getInstrInfo() const override
const SPIRVSubtarget * getSubtargetImpl() const
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
bool contains(const T &V) const
Check if the SmallSet contains the given element.
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
reference emplace_back(ArgTypes &&... Args)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
iterator insert(iterator I, T &&Elt)
void push_back(const T &Elt)
Target-Independent Code Generator Pass Configuration Options.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
bool isVectorTy() const
True if this is an instance of VectorType.
static LLVM_ABI Type * getDoubleTy(LLVMContext &C)
static LLVM_ABI Type * getFloatTy(LLVMContext &C)
static LLVM_ABI Type * getHalfTy(LLVMContext &C)
Represents a version number in the form major[.minor[.subminor[.build]]].
bool empty() const
Determine whether this version information is empty (e.g., all version components are zero).
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
DenseMap< const Function *, FPFastMathDefaultInfoVector > FPFastMathDefaultInfoMapTy
SmallVector< const MachineInstr * > InstrList
ValuesClass values(OptsTy... Options)
Helper to build a ValuesClass by forwarding a variable number of arguments as an initializer list to ...
initializer< Ty > init(const Ty &Val)
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > extract(Y &&MD)
Extract a Value from Metadata.
This is an optimization pass for GlobalISel generic memory operations.
void stable_sort(R &&Range)
std::string getStringImm(const MachineInstr &MI, unsigned StartIndex)
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
hash_code hash_value(const FixedPointSemantics &Val)
ExtensionList getSymbolicOperandExtensions(SPIRV::OperandCategory::OperandCategory Category, uint32_t Value)
CapabilityList getSymbolicOperandCapabilities(SPIRV::OperandCategory::OperandCategory Category, uint32_t Value)
SmallVector< SPIRV::Extension::Extension, 8 > ExtensionList
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
SmallVector< size_t > InstrSignature
bool requiresLongVectorEXT(unsigned NumComponents)
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
InnerAnalysisManagerProxy< FunctionAnalysisManager, Module > FunctionAnalysisManagerModuleProxy
Provide the FunctionAnalysisManager to Module proxy.
static void reportUnsupported(MachineIRBuilder &MIRBuilder, const Twine &Msg)
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
void buildOpDecorate(Register Reg, MachineIRBuilder &MIRBuilder, SPIRV::Decoration::Decoration Dec, ArrayRef< uint32_t > DecArgs, StringRef StrImm)
bool isVectorType(SPIRVTypeInst SPVTy)
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
VersionTuple getSymbolicOperandMaxVersion(SPIRV::OperandCategory::OperandCategory Category, uint32_t Value)
function_ref< MachineFunction *(const Function &)> MachineFunctionGetter
void erase(Container &C, ValueType V)
Wrapper function to remove a value from a container:
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
CapabilityList getCapabilitiesEnabledByExtension(SPIRV::Extension::Extension Extension)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
FunctionPass * createSPIRVPrepareModuleAnalysisLegacyPass()
std::string getSymbolicOperandMnemonic(SPIRV::OperandCategory::OperandCategory Category, int32_t Value)
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
DWARFExpression::Operation Op
VersionTuple getSymbolicOperandMinVersion(SPIRV::OperandCategory::OperandCategory Category, uint32_t Value)
constexpr unsigned BitWidth
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
SmallVector< SPIRV::Capability::Capability, 8 > CapabilityList
std::set< InstrSignature > InstrTraces
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
hash_code hash_combine(const Ts &...args)
Combine values into a single hash_code.
std::map< SmallVector< size_t >, unsigned > InstrGRegsMap
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
SmallSet< SPIRV::Capability::Capability, 4 > S
A special type used by analysis passes to provide an address that identifies that particular analysis...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
SPIRV::ModuleAnalysisInfo MAI
bool runOnModule(Module &M) override
runOnModule - Virtual method overriden by subclasses to process the module being operated on.
static size_t computeFPFastMathDefaultInfoVecIndex(size_t BitWidth)
void setSkipEmission(const MachineInstr *MI)
MCRegister getRegisterAlias(const MachineFunction *MF, Register Reg)
MCRegister getOrCreateMBBRegister(const MachineBasicBlock &MBB)
InstrList MS[NUM_MODULE_SECTIONS]
AddressingModel::AddressingModel Addr
SmallVector< std::pair< MCRegister, StringRef > > MBBNames
void checkSatisfiable(const SPIRVSubtarget &ST) const
void getAndAddRequirements(SPIRV::OperandCategory::OperandCategory Category, uint32_t i, const SPIRVSubtarget &ST)
void addRequirements(const Requirements &Req)
bool isCapabilityAvailable(Capability::Capability Cap) const
void removeCapabilityIf(const Capability::Capability ToRemove, const Capability::Capability IfPresent)
void addExtensions(const ExtensionList &ToAdd)
void addAvailableCaps(const CapabilityList &ToAdd)
void addExtension(Extension::Extension ToAdd)
void initAvailableCapabilities(const SPIRVSubtarget &ST)
void addCapability(Capability::Capability ToAdd)
void addCapabilities(const CapabilityList &ToAdd)
const std::optional< Capability::Capability > Cap
const VersionTuple MinVer
const VersionTuple MaxVer