30#define DEBUG_TYPE "spirv-module-analysis"
34 cl::desc(
"Dump MIR with SPIR-V dependencies info"),
39 cl::desc(
"SPIR-V capabilities to avoid if there are "
40 "other options enabling a feature"),
43 "SPIR-V Shader capability")));
65 if (MdNode && OpIndex < MdNode->getNumOperands()) {
66 const auto &
Op = MdNode->getOperand(
OpIndex);
67 return mdconst::extract<ConstantInt>(
Op)->getZExtValue();
73getSymbolicOperandRequirements(SPIRV::OperandCategory::OperandCategory Category,
82 bool MinVerOK = SPIRVVersion.
empty() || SPIRVVersion >= ReqMinVer;
84 ReqMaxVer.
empty() || SPIRVVersion.
empty() || SPIRVVersion <= ReqMaxVer;
87 if (ReqCaps.
empty()) {
88 if (ReqExts.
empty()) {
89 if (MinVerOK && MaxVerOK)
90 return {
true, {}, {}, ReqMinVer, ReqMaxVer};
93 }
else if (MinVerOK && MaxVerOK) {
94 if (ReqCaps.
size() == 1) {
95 auto Cap = ReqCaps[0];
97 return {
true, {Cap}, ReqExts, ReqMinVer, ReqMaxVer};
106 for (
auto Cap : ReqCaps)
109 for (
size_t i = 0, Sz = UseCaps.
size(); i < Sz; ++i) {
110 auto Cap = UseCaps[i];
111 if (i == Sz - 1 || !AvoidCaps.
S.
contains(Cap))
112 return {
true, {Cap}, ReqExts, ReqMinVer, ReqMaxVer};
119 if (
llvm::all_of(ReqExts, [&ST](
const SPIRV::Extension::Extension &Ext) {
120 return ST.canUseExtension(Ext);
131void SPIRVModuleAnalysis::setBaseInfo(
const Module &M) {
144 if (
auto MemModel =
M.getNamedMetadata(
"spirv.MemoryModel")) {
145 auto MemMD = MemModel->getOperand(0);
146 MAI.
Addr =
static_cast<SPIRV::AddressingModel::AddressingModel
>(
147 getMetadataUInt(MemMD, 0));
149 static_cast<SPIRV::MemoryModel::MemoryModel
>(getMetadataUInt(MemMD, 1));
152 MAI.
Mem =
ST->isOpenCLEnv() ? SPIRV::MemoryModel::OpenCL
153 : SPIRV::MemoryModel::GLSL450;
154 if (
MAI.
Mem == SPIRV::MemoryModel::OpenCL) {
155 unsigned PtrSize =
ST->getPointerSize();
156 MAI.
Addr = PtrSize == 32 ? SPIRV::AddressingModel::Physical32
157 : PtrSize == 64 ? SPIRV::AddressingModel::Physical64
158 : SPIRV::AddressingModel::Logical;
161 MAI.
Addr = SPIRV::AddressingModel::Logical;
166 if (
auto VerNode =
M.getNamedMetadata(
"opencl.ocl.version")) {
167 MAI.
SrcLang = SPIRV::SourceLanguage::OpenCL_C;
170 assert(VerNode->getNumOperands() > 0 &&
"Invalid SPIR");
171 auto VersionMD = VerNode->getOperand(0);
172 unsigned MajorNum = getMetadataUInt(VersionMD, 0, 2);
173 unsigned MinorNum = getMetadataUInt(VersionMD, 1);
174 unsigned RevNum = getMetadataUInt(VersionMD, 2);
177 (std::max(1U, MajorNum) * 100 + MinorNum) * 1000 + RevNum;
183 if (
ST->isOpenCLEnv()) {
184 MAI.
SrcLang = SPIRV::SourceLanguage::OpenCL_CPP;
192 if (
auto ExtNode =
M.getNamedMetadata(
"opencl.used.extensions")) {
193 for (
unsigned I = 0, E = ExtNode->getNumOperands();
I != E; ++
I) {
211 if (
ST->isOpenCLEnv()) {
214 SPIRV::InstructionSet::OpenCL_std)] =
227 for (
unsigned i = 0; i <
MI.getNumOperands(); ++i) {
231 if (!UseDefReg && MO.
isDef())
236 dbgs() <<
"Unexpectedly, no global id found for the operand ";
238 dbgs() <<
"\nInstruction: ";
250 Signature.push_back(h);
257 unsigned Opcode =
MI.getOpcode();
259 case SPIRV::OpTypeForwardPointer:
262 case SPIRV::OpVariable:
263 return static_cast<SPIRV::StorageClass::StorageClass
>(
264 MI.getOperand(2).getImm()) != SPIRV::StorageClass::Function;
265 case SPIRV::OpFunction:
266 case SPIRV::OpFunctionParameter:
272 if (
UseMI.getOpcode() != SPIRV::OpConstantFunctionPointerINTEL)
289void SPIRVModuleAnalysis::visitFunPtrUse(
291 std::map<const Value *, unsigned> &GlobalToGReg,
const MachineFunction *MF,
302 visitDecl(FunDefMRI, SignatureToGReg, GlobalToGReg, FunDefMF, *OpDefMI);
304 }
while (OpDefMI && (OpDefMI->
getOpcode() == SPIRV::OpFunction ||
305 OpDefMI->
getOpcode() == SPIRV::OpFunctionParameter));
309 "Function definition must refer to a global register");
315void SPIRVModuleAnalysis::visitDecl(
317 std::map<const Value *, unsigned> &GlobalToGReg,
const MachineFunction *MF,
319 unsigned Opcode =
MI.getOpcode();
328 if (Opcode == SPIRV::OpConstantFunctionPointerINTEL &&
329 MRI.getRegClass(OpReg) == &SPIRV::pIDRegClass) {
330 visitFunPtrUse(OpReg, SignatureToGReg, GlobalToGReg, MF,
MI);
338 if (isDeclSection(
MRI, *OpDefMI))
339 visitDecl(
MRI, SignatureToGReg, GlobalToGReg, MF, *OpDefMI);
345 dbgs() <<
"Unexpectedly, no unique definition for the operand ";
347 dbgs() <<
"\nInstruction: ";
352 "No unique definition is found for the virtual register");
356 bool IsFunDef =
false;
360 }
else if (Opcode == SPIRV::OpFunction ||
361 Opcode == SPIRV::OpFunctionParameter) {
362 GReg = handleFunctionOrParameter(MF,
MI, GlobalToGReg, IsFunDef);
365 GReg = handleTypeDeclOrConstant(
MI, SignatureToGReg);
366 }
else if (Opcode == SPIRV::OpVariable) {
367 GReg = handleVariable(MF,
MI, GlobalToGReg);
370 dbgs() <<
"\nInstruction: ";
381Register SPIRVModuleAnalysis::handleFunctionOrParameter(
383 std::map<const Value *, unsigned> &GlobalToGReg,
bool &IsFunDef) {
385 assert(GObj &&
"Unregistered global definition");
386 const Function *
F = dyn_cast<Function>(GObj);
388 F = dyn_cast<Argument>(GObj)->getParent();
389 assert(
F &&
"Expected a reference to a function or an argument");
390 IsFunDef = !
F->isDeclaration();
391 auto It = GlobalToGReg.find(GObj);
392 if (It != GlobalToGReg.end())
395 GlobalToGReg[GObj] = GReg;
402SPIRVModuleAnalysis::handleTypeDeclOrConstant(
const MachineInstr &
MI,
405 auto It = SignatureToGReg.find(MISign);
406 if (It != SignatureToGReg.end())
409 SignatureToGReg[MISign] = GReg;
414Register SPIRVModuleAnalysis::handleVariable(
416 std::map<const Value *, unsigned> &GlobalToGReg) {
419 assert(GObj &&
"Unregistered global definition");
420 auto It = GlobalToGReg.find(GObj);
421 if (It != GlobalToGReg.end())
424 GlobalToGReg[GObj] = GReg;
429void SPIRVModuleAnalysis::collectDeclarations(
const Module &M) {
431 std::map<const Value *, unsigned> GlobalToGReg;
432 for (
auto F =
M.begin(), E =
M.end();
F != E; ++
F) {
437 unsigned PastHeader = 0;
440 if (
MI.getNumOperands() == 0)
442 unsigned Opcode =
MI.getOpcode();
443 if (Opcode == SPIRV::OpFunction) {
444 if (PastHeader == 0) {
448 }
else if (Opcode == SPIRV::OpFunctionParameter) {
451 }
else if (PastHeader > 0) {
457 case SPIRV::OpExtension:
461 case SPIRV::OpCapability:
468 if (DefMO.
isReg() && isDeclSection(
MRI,
MI) &&
470 visitDecl(
MRI, SignatureToGReg, GlobalToGReg, MF,
MI);
483 if (
MI.getOpcode() == SPIRV::OpDecorate) {
485 auto Dec =
MI.getOperand(1).getImm();
486 if (Dec ==
static_cast<unsigned>(SPIRV::Decoration::LinkageAttributes)) {
487 auto Lnk =
MI.getOperand(
MI.getNumOperands() - 1).getImm();
488 if (Lnk ==
static_cast<unsigned>(SPIRV::LinkageType::Import)) {
496 }
else if (
MI.getOpcode() == SPIRV::OpFunction) {
510 bool Append =
true) {
513 auto FoundMI = IS.insert(MISign);
525void SPIRVModuleAnalysis::processOtherInstrs(
const Module &M) {
527 for (
auto F =
M.begin(), E =
M.end();
F != E; ++
F) {
528 if ((*F).isDeclaration())
537 const unsigned OpCode =
MI.getOpcode();
538 if (OpCode == SPIRV::OpString) {
540 }
else if (OpCode == SPIRV::OpExtInst &&
MI.getOperand(2).isImm() &&
541 MI.getOperand(2).getImm() ==
542 SPIRV::InstructionSet::
543 NonSemantic_Shader_DebugInfo_100) {
545 namespace NS = SPIRV::NonSemanticExtInst;
546 static constexpr int64_t GlobalNonSemanticDITy[] = {
547 NS::DebugSource, NS::DebugCompilationUnit, NS::DebugInfoNone,
548 NS::DebugTypeBasic, NS::DebugTypePointer};
549 bool IsGlobalDI =
false;
550 for (
unsigned Idx = 0;
Idx < std::size(GlobalNonSemanticDITy); ++
Idx)
551 IsGlobalDI |=
Ins.getImm() == GlobalNonSemanticDITy[
Idx];
554 }
else if (OpCode == SPIRV::OpName || OpCode == SPIRV::OpMemberName) {
556 }
else if (OpCode == SPIRV::OpEntryPoint) {
558 }
else if (
TII->isDecorationInstr(
MI)) {
560 collectFuncNames(
MI, &*
F);
561 }
else if (
TII->isConstantInstr(
MI)) {
565 }
else if (OpCode == SPIRV::OpFunction) {
566 collectFuncNames(
MI, &*
F);
567 }
else if (OpCode == SPIRV::OpTypeForwardPointer) {
577void SPIRVModuleAnalysis::numberRegistersGlobally(
const Module &M) {
578 for (
auto F =
M.begin(),
E =
M.end();
F !=
E; ++
F) {
579 if ((*F).isDeclaration())
594 if (
MI.getOpcode() != SPIRV::OpExtInst)
596 auto Set =
MI.getOperand(2).getImm();
606 SPIRV::OperandCategory::OperandCategory Category,
uint32_t i,
608 addRequirements(getSymbolicOperandRequirements(Category, i, ST, *
this));
611void SPIRV::RequirementHandler::recursiveAddCapabilities(
613 for (
const auto &Cap : ToPrune) {
617 recursiveAddCapabilities(ImplicitDecls);
622 for (
const auto &Cap : ToAdd) {
623 bool IsNewlyInserted = AllCaps.insert(Cap).second;
624 if (!IsNewlyInserted)
628 recursiveAddCapabilities(ImplicitDecls);
629 MinimalCaps.push_back(Cap);
638 if (Req.
Cap.has_value())
639 addCapabilities({Req.
Cap.value()});
641 addExtensions(Req.
Exts);
644 if (!MaxVersion.empty() && Req.
MinVer > MaxVersion) {
646 <<
" and <= " << MaxVersion <<
"\n");
650 if (MinVersion.empty() || Req.
MinVer > MinVersion)
655 if (!MinVersion.empty() && Req.
MaxVer < MinVersion) {
657 <<
" and >= " << MinVersion <<
"\n");
661 if (MaxVersion.empty() || Req.
MaxVer < MaxVersion)
669 bool IsSatisfiable =
true;
670 auto TargetVer =
ST.getSPIRVVersion();
672 if (!MaxVersion.empty() && !TargetVer.empty() && MaxVersion < TargetVer) {
674 dbgs() <<
"Target SPIR-V version too high for required features\n"
675 <<
"Required max version: " << MaxVersion <<
" target version "
676 << TargetVer <<
"\n");
677 IsSatisfiable =
false;
680 if (!MinVersion.empty() && !TargetVer.empty() && MinVersion > TargetVer) {
681 LLVM_DEBUG(
dbgs() <<
"Target SPIR-V version too low for required features\n"
682 <<
"Required min version: " << MinVersion
683 <<
" target version " << TargetVer <<
"\n");
684 IsSatisfiable =
false;
687 if (!MinVersion.empty() && !MaxVersion.empty() && MinVersion > MaxVersion) {
690 <<
"Version is too low for some features and too high for others.\n"
691 <<
"Required SPIR-V min version: " << MinVersion
692 <<
" required SPIR-V max version " << MaxVersion <<
"\n");
693 IsSatisfiable =
false;
696 for (
auto Cap : MinimalCaps) {
697 if (AvailableCaps.contains(Cap))
701 OperandCategory::CapabilityOperand, Cap)
703 IsSatisfiable =
false;
706 for (
auto Ext : AllExtensions) {
707 if (
ST.canUseExtension(Ext))
711 OperandCategory::ExtensionOperand, Ext)
713 IsSatisfiable =
false;
722 for (
const auto Cap : ToAdd)
723 if (AvailableCaps.insert(Cap).second)
725 SPIRV::OperandCategory::CapabilityOperand, Cap));
729 const Capability::Capability
ToRemove,
730 const Capability::Capability IfPresent) {
731 if (AllCaps.contains(IfPresent))
737void RequirementHandler::initAvailableCapabilities(
const SPIRVSubtarget &ST) {
739 addAvailableCaps({Capability::Shader, Capability::Linkage, Capability::Int8,
743 addAvailableCaps({Capability::GroupNonUniform,
744 Capability::GroupNonUniformVote,
745 Capability::GroupNonUniformArithmetic,
746 Capability::GroupNonUniformBallot,
747 Capability::GroupNonUniformClustered,
748 Capability::GroupNonUniformShuffle,
749 Capability::GroupNonUniformShuffleRelative});
752 addAvailableCaps({Capability::DotProduct, Capability::DotProductInputAll,
753 Capability::DotProductInput4x8Bit,
754 Capability::DotProductInput4x8BitPacked,
755 Capability::DemoteToHelperInvocation});
758 for (
auto Extension :
ST.getAllAvailableExtensions()) {
761 addAvailableCaps(EnabledCapabilities);
764 if (
ST.isOpenCLEnv()) {
765 initAvailableCapabilitiesForOpenCL(ST);
769 if (
ST.isVulkanEnv()) {
770 initAvailableCapabilitiesForVulkan(ST);
777void RequirementHandler::initAvailableCapabilitiesForOpenCL(
780 addAvailableCaps({Capability::Addresses, Capability::Float16Buffer,
781 Capability::Kernel, Capability::Vector16,
782 Capability::Groups, Capability::GenericPointer,
783 Capability::StorageImageWriteWithoutFormat,
784 Capability::StorageImageReadWithoutFormat});
785 if (
ST.hasOpenCLFullProfile())
786 addAvailableCaps({Capability::Int64, Capability::Int64Atomics});
787 if (
ST.hasOpenCLImageSupport()) {
788 addAvailableCaps({Capability::ImageBasic, Capability::LiteralSampler,
789 Capability::Image1D, Capability::SampledBuffer,
790 Capability::ImageBuffer});
792 addAvailableCaps({Capability::ImageReadWrite});
796 addAvailableCaps({Capability::SubgroupDispatch, Capability::PipeStorage});
798 addAvailableCaps({Capability::DenormPreserve, Capability::DenormFlushToZero,
799 Capability::SignedZeroInfNanPreserve,
800 Capability::RoundingModeRTE,
801 Capability::RoundingModeRTZ});
803 addAvailableCaps({Capability::Float16, Capability::Float64});
808void RequirementHandler::initAvailableCapabilitiesForVulkan(
812 addAvailableCaps({Capability::Int64, Capability::Float16, Capability::Float64,
813 Capability::GroupNonUniform, Capability::Image1D,
814 Capability::SampledBuffer, Capability::ImageBuffer,
815 Capability::UniformBufferArrayDynamicIndexing,
816 Capability::SampledImageArrayDynamicIndexing,
817 Capability::StorageBufferArrayDynamicIndexing,
818 Capability::StorageImageArrayDynamicIndexing});
823 {Capability::ShaderNonUniformEXT, Capability::RuntimeDescriptorArrayEXT,
824 Capability::InputAttachmentArrayDynamicIndexingEXT,
825 Capability::UniformTexelBufferArrayDynamicIndexingEXT,
826 Capability::StorageTexelBufferArrayDynamicIndexingEXT,
827 Capability::UniformBufferArrayNonUniformIndexingEXT,
828 Capability::SampledImageArrayNonUniformIndexingEXT,
829 Capability::StorageBufferArrayNonUniformIndexingEXT,
830 Capability::StorageImageArrayNonUniformIndexingEXT,
831 Capability::InputAttachmentArrayNonUniformIndexingEXT,
832 Capability::UniformTexelBufferArrayNonUniformIndexingEXT,
833 Capability::StorageTexelBufferArrayNonUniformIndexingEXT});
838 addAvailableCaps({Capability::StorageImageWriteWithoutFormat,
839 Capability::StorageImageReadWithoutFormat});
847static void addOpDecorateReqs(
const MachineInstr &
MI,
unsigned DecIndex,
850 int64_t DecOp =
MI.getOperand(DecIndex).getImm();
851 auto Dec =
static_cast<SPIRV::Decoration::Decoration
>(DecOp);
853 SPIRV::OperandCategory::DecorationOperand, Dec, ST, Reqs));
855 if (Dec == SPIRV::Decoration::BuiltIn) {
856 int64_t BuiltInOp =
MI.getOperand(DecIndex + 1).getImm();
857 auto BuiltIn =
static_cast<SPIRV::BuiltIn::BuiltIn
>(BuiltInOp);
859 SPIRV::OperandCategory::BuiltInOperand, BuiltIn, ST, Reqs));
860 }
else if (Dec == SPIRV::Decoration::LinkageAttributes) {
861 int64_t LinkageOp =
MI.getOperand(
MI.getNumOperands() - 1).getImm();
862 SPIRV::LinkageType::LinkageType LnkType =
863 static_cast<SPIRV::LinkageType::LinkageType
>(LinkageOp);
864 if (LnkType == SPIRV::LinkageType::LinkOnceODR)
865 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_linkonce_odr);
866 }
else if (Dec == SPIRV::Decoration::CacheControlLoadINTEL ||
867 Dec == SPIRV::Decoration::CacheControlStoreINTEL) {
868 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_cache_controls);
869 }
else if (Dec == SPIRV::Decoration::HostAccessINTEL) {
870 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_global_variable_host_access);
871 }
else if (Dec == SPIRV::Decoration::InitModeINTEL ||
872 Dec == SPIRV::Decoration::ImplementInRegisterMapINTEL) {
874 SPIRV::Extension::SPV_INTEL_global_variable_fpga_decorations);
875 }
else if (Dec == SPIRV::Decoration::NonUniformEXT) {
884 assert(
MI.getNumOperands() >= 8 &&
"Insufficient operands for OpTypeImage");
887 int64_t ImgFormatOp =
MI.getOperand(7).getImm();
888 auto ImgFormat =
static_cast<SPIRV::ImageFormat::ImageFormat
>(ImgFormatOp);
892 bool IsArrayed =
MI.getOperand(4).getImm() == 1;
893 bool IsMultisampled =
MI.getOperand(5).getImm() == 1;
894 bool NoSampler =
MI.getOperand(6).getImm() == 2;
897 switch (
MI.getOperand(2).getImm()) {
898 case SPIRV::Dim::DIM_1D:
900 : SPIRV::Capability::Sampled1D);
902 case SPIRV::Dim::DIM_2D:
903 if (IsMultisampled && NoSampler)
906 case SPIRV::Dim::DIM_Cube:
910 : SPIRV::Capability::SampledCubeArray);
912 case SPIRV::Dim::DIM_Rect:
914 : SPIRV::Capability::SampledRect);
916 case SPIRV::Dim::DIM_Buffer:
918 : SPIRV::Capability::SampledBuffer);
920 case SPIRV::Dim::DIM_SubpassData:
926 if (
ST.isOpenCLEnv()) {
927 if (
MI.getNumOperands() > 8 &&
928 MI.getOperand(8).getImm() == SPIRV::AccessQualifier::ReadWrite)
936#define ATOM_FLT_REQ_EXT_MSG(ExtName) \
937 "The atomic float instruction requires the following SPIR-V " \
938 "extension: SPV_EXT_shader_atomic_float" ExtName
943 "Expect register operand in atomic float instruction");
945 SPIRVType *TypeDef =
MI.getMF()->getRegInfo().getVRegDef(TypeReg);
946 if (TypeDef->
getOpcode() != SPIRV::OpTypeFloat)
948 "floating-point type scalar");
951 unsigned Op =
MI.getOpcode();
952 if (
Op == SPIRV::OpAtomicFAddEXT) {
953 if (!
ST.canUseExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float_add))
955 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float_add);
958 if (!
ST.canUseExtension(
959 SPIRV::Extension::SPV_EXT_shader_atomic_float16_add))
961 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float16_add);
972 "Unexpected floating-point type width in atomic float instruction");
975 if (!
ST.canUseExtension(
976 SPIRV::Extension::SPV_EXT_shader_atomic_float_min_max))
978 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float_min_max);
981 Reqs.
addCapability(SPIRV::Capability::AtomicFloat16MinMaxEXT);
984 Reqs.
addCapability(SPIRV::Capability::AtomicFloat32MinMaxEXT);
987 Reqs.
addCapability(SPIRV::Capability::AtomicFloat64MinMaxEXT);
991 "Unexpected floating-point type width in atomic float instruction");
997 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1001 return Dim == SPIRV::Dim::DIM_Buffer && Sampled == 1;
1005 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1009 return Dim == SPIRV::Dim::DIM_Buffer && Sampled == 2;
1013 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1017 return Dim != SPIRV::Dim::DIM_Buffer && Sampled == 1;
1021 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1025 return Dim == SPIRV::Dim::DIM_SubpassData && Sampled == 2;
1029 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1033 return Dim != SPIRV::Dim::DIM_Buffer && Sampled == 2;
1036bool isCombinedImageSampler(
MachineInstr *SampledImageInst) {
1037 if (SampledImageInst->
getOpcode() != SPIRV::OpTypeSampledImage)
1042 auto *ImageInst =
MRI.getUniqueVRegDef(ImageReg);
1043 return isSampledImage(ImageInst);
1047 for (
const auto &
MI :
MRI.reg_instructions(Reg)) {
1048 if (
MI.getOpcode() != SPIRV::OpDecorate)
1052 if (Dec == SPIRV::Decoration::NonUniformEXT)
1070 if (
StorageClass != SPIRV::StorageClass::StorageClass::UniformConstant &&
1071 StorageClass != SPIRV::StorageClass::StorageClass::Uniform &&
1072 StorageClass != SPIRV::StorageClass::StorageClass::StorageBuffer) {
1078 if (PointeeType->
getOpcode() != SPIRV::OpTypeImage &&
1079 PointeeType->
getOpcode() != SPIRV::OpTypeSampledImage &&
1080 PointeeType->
getOpcode() != SPIRV::OpTypeSampler) {
1085 hasNonUniformDecoration(
Instr.getOperand(0).getReg(),
MRI);
1086 if (isUniformTexelBuffer(PointeeType)) {
1089 SPIRV::Capability::UniformTexelBufferArrayNonUniformIndexingEXT);
1092 SPIRV::Capability::UniformTexelBufferArrayDynamicIndexingEXT);
1093 }
else if (isInputAttachment(PointeeType)) {
1096 SPIRV::Capability::InputAttachmentArrayNonUniformIndexingEXT);
1099 SPIRV::Capability::InputAttachmentArrayDynamicIndexingEXT);
1100 }
else if (isStorageTexelBuffer(PointeeType)) {
1103 SPIRV::Capability::StorageTexelBufferArrayNonUniformIndexingEXT);
1106 SPIRV::Capability::StorageTexelBufferArrayDynamicIndexingEXT);
1107 }
else if (isSampledImage(PointeeType) ||
1108 isCombinedImageSampler(PointeeType) ||
1109 PointeeType->
getOpcode() == SPIRV::OpTypeSampler) {
1112 SPIRV::Capability::SampledImageArrayNonUniformIndexingEXT);
1115 SPIRV::Capability::SampledImageArrayDynamicIndexing);
1116 }
else if (isStorageImage(PointeeType)) {
1119 SPIRV::Capability::StorageImageArrayNonUniformIndexingEXT);
1122 SPIRV::Capability::StorageImageArrayDynamicIndexing);
1126static bool isImageTypeWithUnknownFormat(
SPIRVType *TypeInst) {
1127 if (TypeInst->
getOpcode() != SPIRV::OpTypeImage)
1136 if (
ST.canUseExtension(SPIRV::Extension::SPV_KHR_integer_dot_product))
1137 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_integer_dot_product);
1141 assert(
MI.getOperand(2).isReg() &&
"Unexpected operand in dot");
1149 if (TypeDef->
getOpcode() == SPIRV::OpTypeInt) {
1151 Reqs.
addCapability(SPIRV::Capability::DotProductInput4x8BitPacked);
1152 }
else if (TypeDef->
getOpcode() == SPIRV::OpTypeVector) {
1157 "Dot operand of 8-bit integer type requires 4 components");
1158 Reqs.
addCapability(SPIRV::Capability::DotProductInput4x8Bit);
1168 switch (
MI.getOpcode()) {
1169 case SPIRV::OpMemoryModel: {
1170 int64_t
Addr =
MI.getOperand(0).getImm();
1173 int64_t Mem =
MI.getOperand(1).getImm();
1178 case SPIRV::OpEntryPoint: {
1179 int64_t
Exe =
MI.getOperand(0).getImm();
1184 case SPIRV::OpExecutionMode:
1185 case SPIRV::OpExecutionModeId: {
1186 int64_t
Exe =
MI.getOperand(1).getImm();
1191 case SPIRV::OpTypeMatrix:
1194 case SPIRV::OpTypeInt: {
1195 unsigned BitWidth =
MI.getOperand(1).getImm();
1204 case SPIRV::OpTypeFloat: {
1205 unsigned BitWidth =
MI.getOperand(1).getImm();
1212 case SPIRV::OpTypeVector: {
1213 unsigned NumComponents =
MI.getOperand(2).getImm();
1214 if (NumComponents == 8 || NumComponents == 16)
1218 case SPIRV::OpTypePointer: {
1219 auto SC =
MI.getOperand(1).getImm();
1224 if (!
ST.isOpenCLEnv())
1229 if (TypeDef->
getOpcode() == SPIRV::OpTypeFloat &&
1234 case SPIRV::OpExtInst: {
1235 if (
MI.getOperand(2).getImm() ==
1236 static_cast<int64_t
>(
1237 SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100)) {
1238 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_non_semantic_info);
1242 case SPIRV::OpBitReverse:
1243 case SPIRV::OpBitFieldInsert:
1244 case SPIRV::OpBitFieldSExtract:
1245 case SPIRV::OpBitFieldUExtract:
1246 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_bit_instructions)) {
1250 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_bit_instructions);
1253 case SPIRV::OpTypeRuntimeArray:
1256 case SPIRV::OpTypeOpaque:
1257 case SPIRV::OpTypeEvent:
1260 case SPIRV::OpTypePipe:
1261 case SPIRV::OpTypeReserveId:
1264 case SPIRV::OpTypeDeviceEvent:
1265 case SPIRV::OpTypeQueue:
1266 case SPIRV::OpBuildNDRange:
1269 case SPIRV::OpDecorate:
1270 case SPIRV::OpDecorateId:
1271 case SPIRV::OpDecorateString:
1272 addOpDecorateReqs(
MI, 1, Reqs, ST);
1274 case SPIRV::OpMemberDecorate:
1275 case SPIRV::OpMemberDecorateString:
1276 addOpDecorateReqs(
MI, 2, Reqs, ST);
1278 case SPIRV::OpInBoundsPtrAccessChain:
1281 case SPIRV::OpConstantSampler:
1284 case SPIRV::OpInBoundsAccessChain:
1285 case SPIRV::OpAccessChain:
1286 addOpAccessChainReqs(
MI, Reqs, ST);
1288 case SPIRV::OpTypeImage:
1289 addOpTypeImageReqs(
MI, Reqs, ST);
1291 case SPIRV::OpTypeSampler:
1292 if (!
ST.isVulkanEnv()) {
1296 case SPIRV::OpTypeForwardPointer:
1300 case SPIRV::OpAtomicFlagTestAndSet:
1301 case SPIRV::OpAtomicLoad:
1302 case SPIRV::OpAtomicStore:
1303 case SPIRV::OpAtomicExchange:
1304 case SPIRV::OpAtomicCompareExchange:
1305 case SPIRV::OpAtomicIIncrement:
1306 case SPIRV::OpAtomicIDecrement:
1307 case SPIRV::OpAtomicIAdd:
1308 case SPIRV::OpAtomicISub:
1309 case SPIRV::OpAtomicUMin:
1310 case SPIRV::OpAtomicUMax:
1311 case SPIRV::OpAtomicSMin:
1312 case SPIRV::OpAtomicSMax:
1313 case SPIRV::OpAtomicAnd:
1314 case SPIRV::OpAtomicOr:
1315 case SPIRV::OpAtomicXor: {
1318 if (
MI.getOpcode() == SPIRV::OpAtomicStore) {
1320 InstrPtr =
MRI.getVRegDef(
MI.getOperand(3).getReg());
1321 assert(InstrPtr &&
"Unexpected type instruction for OpAtomicStore");
1326 if (TypeDef->
getOpcode() == SPIRV::OpTypeInt) {
1333 case SPIRV::OpGroupNonUniformIAdd:
1334 case SPIRV::OpGroupNonUniformFAdd:
1335 case SPIRV::OpGroupNonUniformIMul:
1336 case SPIRV::OpGroupNonUniformFMul:
1337 case SPIRV::OpGroupNonUniformSMin:
1338 case SPIRV::OpGroupNonUniformUMin:
1339 case SPIRV::OpGroupNonUniformFMin:
1340 case SPIRV::OpGroupNonUniformSMax:
1341 case SPIRV::OpGroupNonUniformUMax:
1342 case SPIRV::OpGroupNonUniformFMax:
1343 case SPIRV::OpGroupNonUniformBitwiseAnd:
1344 case SPIRV::OpGroupNonUniformBitwiseOr:
1345 case SPIRV::OpGroupNonUniformBitwiseXor:
1346 case SPIRV::OpGroupNonUniformLogicalAnd:
1347 case SPIRV::OpGroupNonUniformLogicalOr:
1348 case SPIRV::OpGroupNonUniformLogicalXor: {
1350 int64_t GroupOp =
MI.getOperand(3).getImm();
1352 case SPIRV::GroupOperation::Reduce:
1353 case SPIRV::GroupOperation::InclusiveScan:
1354 case SPIRV::GroupOperation::ExclusiveScan:
1355 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformArithmetic);
1357 case SPIRV::GroupOperation::ClusteredReduce:
1358 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformClustered);
1360 case SPIRV::GroupOperation::PartitionedReduceNV:
1361 case SPIRV::GroupOperation::PartitionedInclusiveScanNV:
1362 case SPIRV::GroupOperation::PartitionedExclusiveScanNV:
1363 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformPartitionedNV);
1368 case SPIRV::OpGroupNonUniformShuffle:
1369 case SPIRV::OpGroupNonUniformShuffleXor:
1370 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformShuffle);
1372 case SPIRV::OpGroupNonUniformShuffleUp:
1373 case SPIRV::OpGroupNonUniformShuffleDown:
1374 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformShuffleRelative);
1376 case SPIRV::OpGroupAll:
1377 case SPIRV::OpGroupAny:
1378 case SPIRV::OpGroupBroadcast:
1379 case SPIRV::OpGroupIAdd:
1380 case SPIRV::OpGroupFAdd:
1381 case SPIRV::OpGroupFMin:
1382 case SPIRV::OpGroupUMin:
1383 case SPIRV::OpGroupSMin:
1384 case SPIRV::OpGroupFMax:
1385 case SPIRV::OpGroupUMax:
1386 case SPIRV::OpGroupSMax:
1389 case SPIRV::OpGroupNonUniformElect:
1392 case SPIRV::OpGroupNonUniformAll:
1393 case SPIRV::OpGroupNonUniformAny:
1394 case SPIRV::OpGroupNonUniformAllEqual:
1397 case SPIRV::OpGroupNonUniformBroadcast:
1398 case SPIRV::OpGroupNonUniformBroadcastFirst:
1399 case SPIRV::OpGroupNonUniformBallot:
1400 case SPIRV::OpGroupNonUniformInverseBallot:
1401 case SPIRV::OpGroupNonUniformBallotBitExtract:
1402 case SPIRV::OpGroupNonUniformBallotBitCount:
1403 case SPIRV::OpGroupNonUniformBallotFindLSB:
1404 case SPIRV::OpGroupNonUniformBallotFindMSB:
1405 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformBallot);
1407 case SPIRV::OpSubgroupShuffleINTEL:
1408 case SPIRV::OpSubgroupShuffleDownINTEL:
1409 case SPIRV::OpSubgroupShuffleUpINTEL:
1410 case SPIRV::OpSubgroupShuffleXorINTEL:
1411 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {
1412 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_subgroups);
1413 Reqs.
addCapability(SPIRV::Capability::SubgroupShuffleINTEL);
1416 case SPIRV::OpSubgroupBlockReadINTEL:
1417 case SPIRV::OpSubgroupBlockWriteINTEL:
1418 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {
1419 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_subgroups);
1420 Reqs.
addCapability(SPIRV::Capability::SubgroupBufferBlockIOINTEL);
1423 case SPIRV::OpSubgroupImageBlockReadINTEL:
1424 case SPIRV::OpSubgroupImageBlockWriteINTEL:
1425 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {
1426 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_subgroups);
1427 Reqs.
addCapability(SPIRV::Capability::SubgroupImageBlockIOINTEL);
1430 case SPIRV::OpSubgroupImageMediaBlockReadINTEL:
1431 case SPIRV::OpSubgroupImageMediaBlockWriteINTEL:
1432 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_media_block_io)) {
1433 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_media_block_io);
1434 Reqs.
addCapability(SPIRV::Capability::SubgroupImageMediaBlockIOINTEL);
1437 case SPIRV::OpAssumeTrueKHR:
1438 case SPIRV::OpExpectKHR:
1439 if (
ST.canUseExtension(SPIRV::Extension::SPV_KHR_expect_assume)) {
1440 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_expect_assume);
1444 case SPIRV::OpPtrCastToCrossWorkgroupINTEL:
1445 case SPIRV::OpCrossWorkgroupCastToPtrINTEL:
1446 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_usm_storage_classes)) {
1447 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_usm_storage_classes);
1448 Reqs.
addCapability(SPIRV::Capability::USMStorageClassesINTEL);
1451 case SPIRV::OpConstantFunctionPointerINTEL:
1452 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_function_pointers)) {
1453 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_function_pointers);
1454 Reqs.
addCapability(SPIRV::Capability::FunctionPointersINTEL);
1457 case SPIRV::OpGroupNonUniformRotateKHR:
1458 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_subgroup_rotate))
1460 "following SPIR-V extension: SPV_KHR_subgroup_rotate",
1462 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_subgroup_rotate);
1463 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformRotateKHR);
1466 case SPIRV::OpGroupIMulKHR:
1467 case SPIRV::OpGroupFMulKHR:
1468 case SPIRV::OpGroupBitwiseAndKHR:
1469 case SPIRV::OpGroupBitwiseOrKHR:
1470 case SPIRV::OpGroupBitwiseXorKHR:
1471 case SPIRV::OpGroupLogicalAndKHR:
1472 case SPIRV::OpGroupLogicalOrKHR:
1473 case SPIRV::OpGroupLogicalXorKHR:
1474 if (
ST.canUseExtension(
1475 SPIRV::Extension::SPV_KHR_uniform_group_instructions)) {
1476 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_uniform_group_instructions);
1477 Reqs.
addCapability(SPIRV::Capability::GroupUniformArithmeticKHR);
1480 case SPIRV::OpReadClockKHR:
1481 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_shader_clock))
1483 "following SPIR-V extension: SPV_KHR_shader_clock",
1485 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_shader_clock);
1488 case SPIRV::OpFunctionPointerCallINTEL:
1489 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_function_pointers)) {
1490 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_function_pointers);
1491 Reqs.
addCapability(SPIRV::Capability::FunctionPointersINTEL);
1494 case SPIRV::OpAtomicFAddEXT:
1495 case SPIRV::OpAtomicFMinEXT:
1496 case SPIRV::OpAtomicFMaxEXT:
1497 AddAtomicFloatRequirements(
MI, Reqs, ST);
1499 case SPIRV::OpConvertBF16ToFINTEL:
1500 case SPIRV::OpConvertFToBF16INTEL:
1501 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bfloat16_conversion)) {
1502 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bfloat16_conversion);
1503 Reqs.
addCapability(SPIRV::Capability::BFloat16ConversionINTEL);
1506 case SPIRV::OpVariableLengthArrayINTEL:
1507 case SPIRV::OpSaveMemoryINTEL:
1508 case SPIRV::OpRestoreMemoryINTEL:
1509 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_variable_length_array)) {
1510 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_variable_length_array);
1511 Reqs.
addCapability(SPIRV::Capability::VariableLengthArrayINTEL);
1514 case SPIRV::OpAsmTargetINTEL:
1515 case SPIRV::OpAsmINTEL:
1516 case SPIRV::OpAsmCallINTEL:
1517 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_inline_assembly)) {
1518 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_inline_assembly);
1522 case SPIRV::OpTypeCooperativeMatrixKHR:
1523 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix))
1525 "OpTypeCooperativeMatrixKHR type requires the "
1526 "following SPIR-V extension: SPV_KHR_cooperative_matrix",
1528 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix);
1529 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixKHR);
1531 case SPIRV::OpArithmeticFenceEXT:
1532 if (!
ST.canUseExtension(SPIRV::Extension::SPV_EXT_arithmetic_fence))
1534 "following SPIR-V extension: SPV_EXT_arithmetic_fence",
1536 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_arithmetic_fence);
1539 case SPIRV::OpControlBarrierArriveINTEL:
1540 case SPIRV::OpControlBarrierWaitINTEL:
1541 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_split_barrier)) {
1542 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_split_barrier);
1546 case SPIRV::OpCooperativeMatrixMulAddKHR: {
1547 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix))
1549 "following SPIR-V extension: "
1550 "SPV_KHR_cooperative_matrix",
1552 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix);
1553 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixKHR);
1554 constexpr unsigned MulAddMaxSize = 6;
1555 if (
MI.getNumOperands() != MulAddMaxSize)
1557 const int64_t CoopOperands =
MI.getOperand(MulAddMaxSize - 1).getImm();
1559 SPIRV::CooperativeMatrixOperands::MatrixAAndBTF32ComponentsINTEL) {
1560 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
1562 "require the following SPIR-V extension: "
1563 "SPV_INTEL_joint_matrix",
1565 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
1567 SPIRV::Capability::CooperativeMatrixTF32ComponentTypeINTEL);
1569 if (CoopOperands & SPIRV::CooperativeMatrixOperands::
1570 MatrixAAndBBFloat16ComponentsINTEL ||
1572 SPIRV::CooperativeMatrixOperands::MatrixCBFloat16ComponentsINTEL ||
1573 CoopOperands & SPIRV::CooperativeMatrixOperands::
1574 MatrixResultBFloat16ComponentsINTEL) {
1575 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
1577 "require the following SPIR-V extension: "
1578 "SPV_INTEL_joint_matrix",
1580 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
1582 SPIRV::Capability::CooperativeMatrixBFloat16ComponentTypeINTEL);
1586 case SPIRV::OpCooperativeMatrixLoadKHR:
1587 case SPIRV::OpCooperativeMatrixStoreKHR:
1588 case SPIRV::OpCooperativeMatrixLoadCheckedINTEL:
1589 case SPIRV::OpCooperativeMatrixStoreCheckedINTEL:
1590 case SPIRV::OpCooperativeMatrixPrefetchINTEL: {
1591 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix))
1593 "following SPIR-V extension: "
1594 "SPV_KHR_cooperative_matrix",
1596 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix);
1597 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixKHR);
1601 std::unordered_map<unsigned, unsigned> LayoutToInstMap = {
1602 {SPIRV::OpCooperativeMatrixLoadKHR, 3},
1603 {SPIRV::OpCooperativeMatrixStoreKHR, 2},
1604 {SPIRV::OpCooperativeMatrixLoadCheckedINTEL, 5},
1605 {SPIRV::OpCooperativeMatrixStoreCheckedINTEL, 4},
1606 {SPIRV::OpCooperativeMatrixPrefetchINTEL, 4}};
1608 const auto OpCode =
MI.getOpcode();
1609 const unsigned LayoutNum = LayoutToInstMap[
OpCode];
1610 Register RegLayout =
MI.getOperand(LayoutNum).getReg();
1613 if (MILayout->
getOpcode() == SPIRV::OpConstantI) {
1616 static_cast<unsigned>(SPIRV::CooperativeMatrixLayout::PackedINTEL)) {
1617 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
1619 "extension: SPV_INTEL_joint_matrix",
1621 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
1622 Reqs.
addCapability(SPIRV::Capability::PackedCooperativeMatrixINTEL);
1627 if (OpCode == SPIRV::OpCooperativeMatrixLoadKHR ||
1628 OpCode == SPIRV::OpCooperativeMatrixStoreKHR)
1631 std::string InstName;
1633 case SPIRV::OpCooperativeMatrixPrefetchINTEL:
1634 InstName =
"OpCooperativeMatrixPrefetchINTEL";
1636 case SPIRV::OpCooperativeMatrixLoadCheckedINTEL:
1637 InstName =
"OpCooperativeMatrixLoadCheckedINTEL";
1639 case SPIRV::OpCooperativeMatrixStoreCheckedINTEL:
1640 InstName =
"OpCooperativeMatrixStoreCheckedINTEL";
1644 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix)) {
1645 const std::string ErrorMsg =
1646 InstName +
" instruction requires the "
1647 "following SPIR-V extension: SPV_INTEL_joint_matrix";
1650 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
1651 if (OpCode == SPIRV::OpCooperativeMatrixPrefetchINTEL) {
1652 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixPrefetchINTEL);
1656 SPIRV::Capability::CooperativeMatrixCheckedInstructionsINTEL);
1659 case SPIRV::OpCooperativeMatrixConstructCheckedINTEL:
1660 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
1662 "instructions require the following SPIR-V extension: "
1663 "SPV_INTEL_joint_matrix",
1665 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
1667 SPIRV::Capability::CooperativeMatrixCheckedInstructionsINTEL);
1669 case SPIRV::OpCooperativeMatrixGetElementCoordINTEL:
1670 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
1672 "following SPIR-V extension: SPV_INTEL_joint_matrix",
1674 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
1676 SPIRV::Capability::CooperativeMatrixInvocationInstructionsINTEL);
1678 case SPIRV::OpKill: {
1681 case SPIRV::OpDemoteToHelperInvocation:
1682 Reqs.
addCapability(SPIRV::Capability::DemoteToHelperInvocation);
1684 if (
ST.canUseExtension(
1685 SPIRV::Extension::SPV_EXT_demote_to_helper_invocation)) {
1688 SPIRV::Extension::SPV_EXT_demote_to_helper_invocation);
1693 AddDotProductRequirements(
MI, Reqs, ST);
1695 case SPIRV::OpImageRead: {
1696 Register ImageReg =
MI.getOperand(2).getReg();
1697 SPIRVType *TypeDef =
ST.getSPIRVGlobalRegistry()->getResultType(ImageReg);
1698 if (isImageTypeWithUnknownFormat(TypeDef))
1699 Reqs.
addCapability(SPIRV::Capability::StorageImageReadWithoutFormat);
1702 case SPIRV::OpImageWrite: {
1703 Register ImageReg =
MI.getOperand(0).getReg();
1704 SPIRVType *TypeDef =
ST.getSPIRVGlobalRegistry()->getResultType(ImageReg);
1705 if (isImageTypeWithUnknownFormat(TypeDef))
1706 Reqs.
addCapability(SPIRV::Capability::StorageImageWriteWithoutFormat);
1718 SPIRV::Capability::Shader);
1724 for (
auto F =
M.begin(), E =
M.end();
F != E; ++
F) {
1730 addInstrRequirements(
MI, MAI.
Reqs, ST);
1733 auto Node =
M.getNamedMetadata(
"spirv.ExecutionMode");
1735 bool RequireFloatControls =
false, RequireFloatControls2 =
false,
1737 bool HasFloatControls2 =
1738 ST.canUseExtension(SPIRV::Extension::SPV_INTEL_float_controls2);
1739 for (
unsigned i = 0; i <
Node->getNumOperands(); i++) {
1740 MDNode *MDN = cast<MDNode>(
Node->getOperand(i));
1742 if (
auto *CMeta = dyn_cast<ConstantAsMetadata>(MDOp)) {
1745 auto EM =
Const->getZExtValue();
1749 case SPIRV::ExecutionMode::DenormPreserve:
1750 case SPIRV::ExecutionMode::DenormFlushToZero:
1751 case SPIRV::ExecutionMode::SignedZeroInfNanPreserve:
1752 case SPIRV::ExecutionMode::RoundingModeRTE:
1753 case SPIRV::ExecutionMode::RoundingModeRTZ:
1754 RequireFloatControls = VerLower14;
1756 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
1758 case SPIRV::ExecutionMode::RoundingModeRTPINTEL:
1759 case SPIRV::ExecutionMode::RoundingModeRTNINTEL:
1760 case SPIRV::ExecutionMode::FloatingPointModeALTINTEL:
1761 case SPIRV::ExecutionMode::FloatingPointModeIEEEINTEL:
1762 if (HasFloatControls2) {
1763 RequireFloatControls2 =
true;
1765 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
1770 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
1775 if (RequireFloatControls &&
1776 ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls))
1778 if (RequireFloatControls2)
1781 for (
auto FI =
M.begin(), E =
M.end(); FI != E; ++FI) {
1783 if (
F.isDeclaration())
1785 if (
F.getMetadata(
"reqd_work_group_size"))
1787 SPIRV::OperandCategory::ExecutionModeOperand,
1788 SPIRV::ExecutionMode::LocalSize, ST);
1789 if (
F.getFnAttribute(
"hlsl.numthreads").isValid()) {
1791 SPIRV::OperandCategory::ExecutionModeOperand,
1792 SPIRV::ExecutionMode::LocalSize, ST);
1794 if (
F.getMetadata(
"work_group_size_hint"))
1796 SPIRV::OperandCategory::ExecutionModeOperand,
1797 SPIRV::ExecutionMode::LocalSizeHint, ST);
1798 if (
F.getMetadata(
"intel_reqd_sub_group_size"))
1800 SPIRV::OperandCategory::ExecutionModeOperand,
1801 SPIRV::ExecutionMode::SubgroupSize, ST);
1802 if (
F.getMetadata(
"vec_type_hint"))
1804 SPIRV::OperandCategory::ExecutionModeOperand,
1805 SPIRV::ExecutionMode::VecTypeHint, ST);
1807 if (
F.hasOptNone()) {
1808 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_optnone)) {
1811 }
else if (
ST.canUseExtension(SPIRV::Extension::SPV_EXT_optnone)) {
1820 unsigned Flags = SPIRV::FPFastMathMode::None;
1822 Flags |= SPIRV::FPFastMathMode::NotNaN;
1824 Flags |= SPIRV::FPFastMathMode::NotInf;
1826 Flags |= SPIRV::FPFastMathMode::NSZ;
1828 Flags |= SPIRV::FPFastMathMode::AllowRecip;
1830 Flags |= SPIRV::FPFastMathMode::Fast;
1838 getSymbolicOperandRequirements(SPIRV::OperandCategory::DecorationOperand,
1839 SPIRV::Decoration::NoSignedWrap, ST, Reqs)
1842 SPIRV::Decoration::NoSignedWrap, {});
1845 getSymbolicOperandRequirements(SPIRV::OperandCategory::DecorationOperand,
1846 SPIRV::Decoration::NoUnsignedWrap, ST,
1850 SPIRV::Decoration::NoUnsignedWrap, {});
1852 if (!
TII.canUseFastMathFlags(
I))
1854 unsigned FMFlags = getFastMathFlags(
I);
1855 if (FMFlags == SPIRV::FPFastMathMode::None)
1857 Register DstReg =
I.getOperand(0).getReg();
1865 for (
auto F =
M.begin(), E =
M.end();
F != E; ++
F) {
1869 for (
auto &
MBB : *MF)
1870 for (
auto &
MI :
MBB)
1871 handleMIFlagDecoration(
MI, ST,
TII, MAI.
Reqs);
1878 for (
auto F =
M.begin(), E =
M.end();
F != E; ++
F) {
1883 for (
auto &
MBB : *MF) {
1888 MRI.setRegClass(Reg, &SPIRV::IDRegClass);
1899 for (
auto F =
M.begin(), E =
M.end();
F != E; ++
F) {
1903 for (
auto &
MBB : *MF) {
1905 if (
MI.getOpcode() != TargetOpcode::PHI)
1907 MI.setDesc(
TII.get(SPIRV::OpPhi));
1910 MI.insert(
MI.operands_begin() + 1,
1911 {MachineOperand::CreateReg(ResTypeReg, false)});
1927 ST = TM.getSubtargetImpl();
1928 GR = ST->getSPIRVGlobalRegistry();
1929 TII = ST->getInstrInfo();
1931 MMI = &getAnalysis<MachineModuleInfoWrapperPass>().getMMI();
1935 patchPhis(M, GR, *
TII, MMI);
1937 addMBBNames(M, *
TII, MMI, *ST, MAI);
1938 addDecorations(M, *
TII, MMI, *ST, MAI);
1940 collectReqs(M, MAI, MMI, *ST);
1944 collectDeclarations(M);
1947 numberRegistersGlobally(M);
1950 processOtherInstrs(M);
unsigned const MachineRegisterInfo * MRI
MachineInstrBuilder & UseMI
ReachingDefAnalysis InstSet & ToRemove
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define clEnumValN(ENUMVAL, FLAGNAME, DESC)
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
const HexagonInstrInfo * TII
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
#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))
unsigned unsigned DefaultVal
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::ZeroOrMore, cl::Hidden, cl::values(clEnumValN(SPIRV::Capability::Shader, "Shader", "SPIR-V Shader capability")))
Target-Independent Code Generator Pass Configuration Options pass.
This is the shared class of boolean and integer constants.
This is an important base class in LLVM.
This class represents an Operation in the Expression.
Implements a dense probed hash-table based set.
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
const MDOperand & getOperand(unsigned I) const
unsigned getNumOperands() const
Return number of MDNode operands.
Tracking metadata reference owned by Metadata.
bool hasName() const
Check if there is a name of corresponding LLVM basic block.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
StringRef getName() const
Return the name of the corresponding LLVM basic block, or an empty string.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
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
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.
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.
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
Register getReg() const
getReg - Returns the register number.
void print(raw_ostream &os, const TargetRegisterInfo *TRI=nullptr, const TargetIntrinsicInfo *IntrinsicInfo=nullptr) const
Print the MachineOperand to os.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
A Module instance is used to store all the information related to an LLVM module.
PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...
virtual void print(raw_ostream &OS, const Module *M) const
print - Print out the internal state of the pass.
Wrapper class representing virtual and physical registers.
static Register index2VirtReg(unsigned Index)
Convert a 0-based index to a virtual register number.
constexpr bool isValid() const
SPIRVType * getSPIRVTypeForVReg(Register VReg, const MachineFunction *MF=nullptr) const
const Value * getGlobalObject(const MachineFunction *MF, Register R)
void setBound(unsigned V)
const MachineOperand * getFunctionDefinitionByUse(const MachineOperand *Use)
Register getSPIRVTypeID(const SPIRVType *SpirvType) const
bool isConstantInstr(const MachineInstr &MI) const
bool isInlineAsmDefInstr(const MachineInstr &MI) const
bool isTypeDeclInstr(const MachineInstr &MI) const
bool isSpecConstantInstr(const MachineInstr &MI) 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.
iterator insert(iterator I, T &&Elt)
void push_back(const T &Elt)
std::pair< typename Base::iterator, bool > insert(StringRef key)
Target-Independent Code Generator Pass Configuration Options.
Target - Wrapper for Target specific information.
LLVM Value Representation.
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.
@ C
The default llvm calling convention, compatible with C.
@ SC
CHAIN = SC CHAIN, Imm128 - System call.
Reg
All possible values of the reg field in the ModR/M byte.
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)
NodeAddr< InstrNode * > Instr
This is an optimization pass for GlobalISel generic memory operations.
void buildOpName(Register Target, const StringRef &Name, MachineIRBuilder &MIRBuilder)
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)
VersionTuple getSymbolicOperandMaxVersion(SPIRV::OperandCategory::OperandCategory Category, uint32_t Value)
void initializeSPIRVModuleAnalysisPass(PassRegistry &)
void buildOpDecorate(Register Reg, MachineIRBuilder &MIRBuilder, SPIRV::Decoration::Decoration Dec, const std::vector< uint32_t > &DecArgs, StringRef StrImm)
CapabilityList getCapabilitiesEnabledByExtension(SPIRV::Extension::Extension Extension)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
std::set< InstrSignature > InstrTraces
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
std::string getSymbolicOperandMnemonic(SPIRV::OperandCategory::OperandCategory Category, int32_t Value)
VersionTuple getSymbolicOperandMinVersion(SPIRV::OperandCategory::OperandCategory Category, uint32_t Value)
constexpr unsigned BitWidth
std::map< SmallVector< size_t >, unsigned > InstrGRegsMap
hash_code hash_combine(const Ts &...args)
Combine values into a single hash_code.
SmallSet< SPIRV::Capability::Capability, 4 > S
static struct SPIRV::ModuleAnalysisInfo MAI
bool runOnModule(Module &M) override
runOnModule - Virtual method overriden by subclasses to process the module being operated on.
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
Register getRegisterAlias(const MachineFunction *MF, Register Reg)
SmallVector< const MachineInstr *, 4 > GlobalVarList
DenseMap< const Function *, Register > FuncMap
void setSkipEmission(const MachineInstr *MI)
void setRegisterAlias(const MachineFunction *MF, Register Reg, Register AliasReg)
DenseSet< const MachineInstr * > InstrsToDelete
bool hasRegisterAlias(const MachineFunction *MF, Register Reg)
RegisterAliasMapTy RegisterAliasTable
Register getOrCreateMBBRegister(const MachineBasicBlock &MBB)
bool getSkipEmission(const MachineInstr *MI)
MemoryModel::MemoryModel Mem
InstrList MS[NUM_MODULE_SECTIONS]
AddressingModel::AddressingModel Addr
SourceLanguage::SourceLanguage SrcLang
DenseMap< unsigned, Register > ExtInstSetMap
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