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:
1356 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformArithmetic);
1357 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformBallot);
1359 case SPIRV::GroupOperation::ClusteredReduce:
1360 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformClustered);
1362 case SPIRV::GroupOperation::PartitionedReduceNV:
1363 case SPIRV::GroupOperation::PartitionedInclusiveScanNV:
1364 case SPIRV::GroupOperation::PartitionedExclusiveScanNV:
1365 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformPartitionedNV);
1370 case SPIRV::OpGroupNonUniformShuffle:
1371 case SPIRV::OpGroupNonUniformShuffleXor:
1372 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformShuffle);
1374 case SPIRV::OpGroupNonUniformShuffleUp:
1375 case SPIRV::OpGroupNonUniformShuffleDown:
1376 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformShuffleRelative);
1378 case SPIRV::OpGroupAll:
1379 case SPIRV::OpGroupAny:
1380 case SPIRV::OpGroupBroadcast:
1381 case SPIRV::OpGroupIAdd:
1382 case SPIRV::OpGroupFAdd:
1383 case SPIRV::OpGroupFMin:
1384 case SPIRV::OpGroupUMin:
1385 case SPIRV::OpGroupSMin:
1386 case SPIRV::OpGroupFMax:
1387 case SPIRV::OpGroupUMax:
1388 case SPIRV::OpGroupSMax:
1391 case SPIRV::OpGroupNonUniformElect:
1394 case SPIRV::OpGroupNonUniformAll:
1395 case SPIRV::OpGroupNonUniformAny:
1396 case SPIRV::OpGroupNonUniformAllEqual:
1399 case SPIRV::OpGroupNonUniformBroadcast:
1400 case SPIRV::OpGroupNonUniformBroadcastFirst:
1401 case SPIRV::OpGroupNonUniformBallot:
1402 case SPIRV::OpGroupNonUniformInverseBallot:
1403 case SPIRV::OpGroupNonUniformBallotBitExtract:
1404 case SPIRV::OpGroupNonUniformBallotBitCount:
1405 case SPIRV::OpGroupNonUniformBallotFindLSB:
1406 case SPIRV::OpGroupNonUniformBallotFindMSB:
1407 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformBallot);
1409 case SPIRV::OpSubgroupShuffleINTEL:
1410 case SPIRV::OpSubgroupShuffleDownINTEL:
1411 case SPIRV::OpSubgroupShuffleUpINTEL:
1412 case SPIRV::OpSubgroupShuffleXorINTEL:
1413 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {
1414 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_subgroups);
1415 Reqs.
addCapability(SPIRV::Capability::SubgroupShuffleINTEL);
1418 case SPIRV::OpSubgroupBlockReadINTEL:
1419 case SPIRV::OpSubgroupBlockWriteINTEL:
1420 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {
1421 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_subgroups);
1422 Reqs.
addCapability(SPIRV::Capability::SubgroupBufferBlockIOINTEL);
1425 case SPIRV::OpSubgroupImageBlockReadINTEL:
1426 case SPIRV::OpSubgroupImageBlockWriteINTEL:
1427 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {
1428 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_subgroups);
1429 Reqs.
addCapability(SPIRV::Capability::SubgroupImageBlockIOINTEL);
1432 case SPIRV::OpSubgroupImageMediaBlockReadINTEL:
1433 case SPIRV::OpSubgroupImageMediaBlockWriteINTEL:
1434 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_media_block_io)) {
1435 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_media_block_io);
1436 Reqs.
addCapability(SPIRV::Capability::SubgroupImageMediaBlockIOINTEL);
1439 case SPIRV::OpAssumeTrueKHR:
1440 case SPIRV::OpExpectKHR:
1441 if (
ST.canUseExtension(SPIRV::Extension::SPV_KHR_expect_assume)) {
1442 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_expect_assume);
1446 case SPIRV::OpPtrCastToCrossWorkgroupINTEL:
1447 case SPIRV::OpCrossWorkgroupCastToPtrINTEL:
1448 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_usm_storage_classes)) {
1449 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_usm_storage_classes);
1450 Reqs.
addCapability(SPIRV::Capability::USMStorageClassesINTEL);
1453 case SPIRV::OpConstantFunctionPointerINTEL:
1454 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_function_pointers)) {
1455 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_function_pointers);
1456 Reqs.
addCapability(SPIRV::Capability::FunctionPointersINTEL);
1459 case SPIRV::OpGroupNonUniformRotateKHR:
1460 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_subgroup_rotate))
1462 "following SPIR-V extension: SPV_KHR_subgroup_rotate",
1464 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_subgroup_rotate);
1465 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformRotateKHR);
1468 case SPIRV::OpGroupIMulKHR:
1469 case SPIRV::OpGroupFMulKHR:
1470 case SPIRV::OpGroupBitwiseAndKHR:
1471 case SPIRV::OpGroupBitwiseOrKHR:
1472 case SPIRV::OpGroupBitwiseXorKHR:
1473 case SPIRV::OpGroupLogicalAndKHR:
1474 case SPIRV::OpGroupLogicalOrKHR:
1475 case SPIRV::OpGroupLogicalXorKHR:
1476 if (
ST.canUseExtension(
1477 SPIRV::Extension::SPV_KHR_uniform_group_instructions)) {
1478 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_uniform_group_instructions);
1479 Reqs.
addCapability(SPIRV::Capability::GroupUniformArithmeticKHR);
1482 case SPIRV::OpReadClockKHR:
1483 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_shader_clock))
1485 "following SPIR-V extension: SPV_KHR_shader_clock",
1487 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_shader_clock);
1490 case SPIRV::OpFunctionPointerCallINTEL:
1491 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_function_pointers)) {
1492 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_function_pointers);
1493 Reqs.
addCapability(SPIRV::Capability::FunctionPointersINTEL);
1496 case SPIRV::OpAtomicFAddEXT:
1497 case SPIRV::OpAtomicFMinEXT:
1498 case SPIRV::OpAtomicFMaxEXT:
1499 AddAtomicFloatRequirements(
MI, Reqs, ST);
1501 case SPIRV::OpConvertBF16ToFINTEL:
1502 case SPIRV::OpConvertFToBF16INTEL:
1503 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bfloat16_conversion)) {
1504 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bfloat16_conversion);
1505 Reqs.
addCapability(SPIRV::Capability::BFloat16ConversionINTEL);
1508 case SPIRV::OpVariableLengthArrayINTEL:
1509 case SPIRV::OpSaveMemoryINTEL:
1510 case SPIRV::OpRestoreMemoryINTEL:
1511 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_variable_length_array)) {
1512 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_variable_length_array);
1513 Reqs.
addCapability(SPIRV::Capability::VariableLengthArrayINTEL);
1516 case SPIRV::OpAsmTargetINTEL:
1517 case SPIRV::OpAsmINTEL:
1518 case SPIRV::OpAsmCallINTEL:
1519 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_inline_assembly)) {
1520 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_inline_assembly);
1524 case SPIRV::OpTypeCooperativeMatrixKHR:
1525 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix))
1527 "OpTypeCooperativeMatrixKHR type requires the "
1528 "following SPIR-V extension: SPV_KHR_cooperative_matrix",
1530 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix);
1531 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixKHR);
1533 case SPIRV::OpArithmeticFenceEXT:
1534 if (!
ST.canUseExtension(SPIRV::Extension::SPV_EXT_arithmetic_fence))
1536 "following SPIR-V extension: SPV_EXT_arithmetic_fence",
1538 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_arithmetic_fence);
1541 case SPIRV::OpControlBarrierArriveINTEL:
1542 case SPIRV::OpControlBarrierWaitINTEL:
1543 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_split_barrier)) {
1544 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_split_barrier);
1548 case SPIRV::OpCooperativeMatrixMulAddKHR: {
1549 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix))
1551 "following SPIR-V extension: "
1552 "SPV_KHR_cooperative_matrix",
1554 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix);
1555 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixKHR);
1556 constexpr unsigned MulAddMaxSize = 6;
1557 if (
MI.getNumOperands() != MulAddMaxSize)
1559 const int64_t CoopOperands =
MI.getOperand(MulAddMaxSize - 1).getImm();
1561 SPIRV::CooperativeMatrixOperands::MatrixAAndBTF32ComponentsINTEL) {
1562 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
1564 "require the following SPIR-V extension: "
1565 "SPV_INTEL_joint_matrix",
1567 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
1569 SPIRV::Capability::CooperativeMatrixTF32ComponentTypeINTEL);
1571 if (CoopOperands & SPIRV::CooperativeMatrixOperands::
1572 MatrixAAndBBFloat16ComponentsINTEL ||
1574 SPIRV::CooperativeMatrixOperands::MatrixCBFloat16ComponentsINTEL ||
1575 CoopOperands & SPIRV::CooperativeMatrixOperands::
1576 MatrixResultBFloat16ComponentsINTEL) {
1577 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
1579 "require the following SPIR-V extension: "
1580 "SPV_INTEL_joint_matrix",
1582 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
1584 SPIRV::Capability::CooperativeMatrixBFloat16ComponentTypeINTEL);
1588 case SPIRV::OpCooperativeMatrixLoadKHR:
1589 case SPIRV::OpCooperativeMatrixStoreKHR:
1590 case SPIRV::OpCooperativeMatrixLoadCheckedINTEL:
1591 case SPIRV::OpCooperativeMatrixStoreCheckedINTEL:
1592 case SPIRV::OpCooperativeMatrixPrefetchINTEL: {
1593 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix))
1595 "following SPIR-V extension: "
1596 "SPV_KHR_cooperative_matrix",
1598 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix);
1599 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixKHR);
1603 std::unordered_map<unsigned, unsigned> LayoutToInstMap = {
1604 {SPIRV::OpCooperativeMatrixLoadKHR, 3},
1605 {SPIRV::OpCooperativeMatrixStoreKHR, 2},
1606 {SPIRV::OpCooperativeMatrixLoadCheckedINTEL, 5},
1607 {SPIRV::OpCooperativeMatrixStoreCheckedINTEL, 4},
1608 {SPIRV::OpCooperativeMatrixPrefetchINTEL, 4}};
1610 const auto OpCode =
MI.getOpcode();
1611 const unsigned LayoutNum = LayoutToInstMap[
OpCode];
1612 Register RegLayout =
MI.getOperand(LayoutNum).getReg();
1615 if (MILayout->
getOpcode() == SPIRV::OpConstantI) {
1618 static_cast<unsigned>(SPIRV::CooperativeMatrixLayout::PackedINTEL)) {
1619 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
1621 "extension: SPV_INTEL_joint_matrix",
1623 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
1624 Reqs.
addCapability(SPIRV::Capability::PackedCooperativeMatrixINTEL);
1629 if (OpCode == SPIRV::OpCooperativeMatrixLoadKHR ||
1630 OpCode == SPIRV::OpCooperativeMatrixStoreKHR)
1633 std::string InstName;
1635 case SPIRV::OpCooperativeMatrixPrefetchINTEL:
1636 InstName =
"OpCooperativeMatrixPrefetchINTEL";
1638 case SPIRV::OpCooperativeMatrixLoadCheckedINTEL:
1639 InstName =
"OpCooperativeMatrixLoadCheckedINTEL";
1641 case SPIRV::OpCooperativeMatrixStoreCheckedINTEL:
1642 InstName =
"OpCooperativeMatrixStoreCheckedINTEL";
1646 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix)) {
1647 const std::string ErrorMsg =
1648 InstName +
" instruction requires the "
1649 "following SPIR-V extension: SPV_INTEL_joint_matrix";
1652 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
1653 if (OpCode == SPIRV::OpCooperativeMatrixPrefetchINTEL) {
1654 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixPrefetchINTEL);
1658 SPIRV::Capability::CooperativeMatrixCheckedInstructionsINTEL);
1661 case SPIRV::OpCooperativeMatrixConstructCheckedINTEL:
1662 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
1664 "instructions require the following SPIR-V extension: "
1665 "SPV_INTEL_joint_matrix",
1667 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
1669 SPIRV::Capability::CooperativeMatrixCheckedInstructionsINTEL);
1671 case SPIRV::OpCooperativeMatrixGetElementCoordINTEL:
1672 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
1674 "following SPIR-V extension: SPV_INTEL_joint_matrix",
1676 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
1678 SPIRV::Capability::CooperativeMatrixInvocationInstructionsINTEL);
1680 case SPIRV::OpKill: {
1683 case SPIRV::OpDemoteToHelperInvocation:
1684 Reqs.
addCapability(SPIRV::Capability::DemoteToHelperInvocation);
1686 if (
ST.canUseExtension(
1687 SPIRV::Extension::SPV_EXT_demote_to_helper_invocation)) {
1690 SPIRV::Extension::SPV_EXT_demote_to_helper_invocation);
1695 AddDotProductRequirements(
MI, Reqs, ST);
1697 case SPIRV::OpImageRead: {
1698 Register ImageReg =
MI.getOperand(2).getReg();
1699 SPIRVType *TypeDef =
ST.getSPIRVGlobalRegistry()->getResultType(ImageReg);
1700 if (isImageTypeWithUnknownFormat(TypeDef))
1701 Reqs.
addCapability(SPIRV::Capability::StorageImageReadWithoutFormat);
1704 case SPIRV::OpImageWrite: {
1705 Register ImageReg =
MI.getOperand(0).getReg();
1706 SPIRVType *TypeDef =
ST.getSPIRVGlobalRegistry()->getResultType(ImageReg);
1707 if (isImageTypeWithUnknownFormat(TypeDef))
1708 Reqs.
addCapability(SPIRV::Capability::StorageImageWriteWithoutFormat);
1720 SPIRV::Capability::Shader);
1726 for (
auto F =
M.begin(), E =
M.end();
F != E; ++
F) {
1732 addInstrRequirements(
MI, MAI.
Reqs, ST);
1735 auto Node =
M.getNamedMetadata(
"spirv.ExecutionMode");
1737 bool RequireFloatControls =
false, RequireFloatControls2 =
false,
1739 bool HasFloatControls2 =
1740 ST.canUseExtension(SPIRV::Extension::SPV_INTEL_float_controls2);
1741 for (
unsigned i = 0; i <
Node->getNumOperands(); i++) {
1742 MDNode *MDN = cast<MDNode>(
Node->getOperand(i));
1744 if (
auto *CMeta = dyn_cast<ConstantAsMetadata>(MDOp)) {
1747 auto EM =
Const->getZExtValue();
1751 case SPIRV::ExecutionMode::DenormPreserve:
1752 case SPIRV::ExecutionMode::DenormFlushToZero:
1753 case SPIRV::ExecutionMode::SignedZeroInfNanPreserve:
1754 case SPIRV::ExecutionMode::RoundingModeRTE:
1755 case SPIRV::ExecutionMode::RoundingModeRTZ:
1756 RequireFloatControls = VerLower14;
1758 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
1760 case SPIRV::ExecutionMode::RoundingModeRTPINTEL:
1761 case SPIRV::ExecutionMode::RoundingModeRTNINTEL:
1762 case SPIRV::ExecutionMode::FloatingPointModeALTINTEL:
1763 case SPIRV::ExecutionMode::FloatingPointModeIEEEINTEL:
1764 if (HasFloatControls2) {
1765 RequireFloatControls2 =
true;
1767 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
1772 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
1777 if (RequireFloatControls &&
1778 ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls))
1780 if (RequireFloatControls2)
1783 for (
auto FI =
M.begin(), E =
M.end(); FI != E; ++FI) {
1785 if (
F.isDeclaration())
1787 if (
F.getMetadata(
"reqd_work_group_size"))
1789 SPIRV::OperandCategory::ExecutionModeOperand,
1790 SPIRV::ExecutionMode::LocalSize, ST);
1791 if (
F.getFnAttribute(
"hlsl.numthreads").isValid()) {
1793 SPIRV::OperandCategory::ExecutionModeOperand,
1794 SPIRV::ExecutionMode::LocalSize, ST);
1796 if (
F.getMetadata(
"work_group_size_hint"))
1798 SPIRV::OperandCategory::ExecutionModeOperand,
1799 SPIRV::ExecutionMode::LocalSizeHint, ST);
1800 if (
F.getMetadata(
"intel_reqd_sub_group_size"))
1802 SPIRV::OperandCategory::ExecutionModeOperand,
1803 SPIRV::ExecutionMode::SubgroupSize, ST);
1804 if (
F.getMetadata(
"vec_type_hint"))
1806 SPIRV::OperandCategory::ExecutionModeOperand,
1807 SPIRV::ExecutionMode::VecTypeHint, ST);
1809 if (
F.hasOptNone()) {
1810 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_optnone)) {
1813 }
else if (
ST.canUseExtension(SPIRV::Extension::SPV_EXT_optnone)) {
1822 unsigned Flags = SPIRV::FPFastMathMode::None;
1824 Flags |= SPIRV::FPFastMathMode::NotNaN;
1826 Flags |= SPIRV::FPFastMathMode::NotInf;
1828 Flags |= SPIRV::FPFastMathMode::NSZ;
1830 Flags |= SPIRV::FPFastMathMode::AllowRecip;
1832 Flags |= SPIRV::FPFastMathMode::Fast;
1840 getSymbolicOperandRequirements(SPIRV::OperandCategory::DecorationOperand,
1841 SPIRV::Decoration::NoSignedWrap, ST, Reqs)
1844 SPIRV::Decoration::NoSignedWrap, {});
1847 getSymbolicOperandRequirements(SPIRV::OperandCategory::DecorationOperand,
1848 SPIRV::Decoration::NoUnsignedWrap, ST,
1852 SPIRV::Decoration::NoUnsignedWrap, {});
1854 if (!
TII.canUseFastMathFlags(
I))
1856 unsigned FMFlags = getFastMathFlags(
I);
1857 if (FMFlags == SPIRV::FPFastMathMode::None)
1859 Register DstReg =
I.getOperand(0).getReg();
1867 for (
auto F =
M.begin(), E =
M.end();
F != E; ++
F) {
1871 for (
auto &
MBB : *MF)
1872 for (
auto &
MI :
MBB)
1873 handleMIFlagDecoration(
MI, ST,
TII, MAI.
Reqs);
1880 for (
auto F =
M.begin(), E =
M.end();
F != E; ++
F) {
1885 for (
auto &
MBB : *MF) {
1890 MRI.setRegClass(Reg, &SPIRV::IDRegClass);
1901 for (
auto F =
M.begin(), E =
M.end();
F != E; ++
F) {
1905 for (
auto &
MBB : *MF) {
1907 if (
MI.getOpcode() != TargetOpcode::PHI)
1909 MI.setDesc(
TII.get(SPIRV::OpPhi));
1912 MI.insert(
MI.operands_begin() + 1,
1913 {MachineOperand::CreateReg(ResTypeReg, false)});
1929 ST = TM.getSubtargetImpl();
1930 GR = ST->getSPIRVGlobalRegistry();
1931 TII = ST->getInstrInfo();
1933 MMI = &getAnalysis<MachineModuleInfoWrapperPass>().getMMI();
1937 patchPhis(M, GR, *
TII, MMI);
1939 addMBBNames(M, *
TII, MMI, *ST, MAI);
1940 addDecorations(M, *
TII, MMI, *ST, MAI);
1942 collectReqs(M, MAI, MMI, *ST);
1946 collectDeclarations(M);
1949 numberRegistersGlobally(M);
1952 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