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,
79 AvoidCaps.
S.
insert(SPIRV::Capability::Shader);
84 bool MinVerOK = SPIRVVersion.
empty() || SPIRVVersion >= ReqMinVer;
86 ReqMaxVer.
empty() || SPIRVVersion.
empty() || SPIRVVersion <= ReqMaxVer;
89 if (ReqCaps.
empty()) {
90 if (ReqExts.
empty()) {
91 if (MinVerOK && MaxVerOK)
92 return {
true, {}, {}, ReqMinVer, ReqMaxVer};
95 }
else if (MinVerOK && MaxVerOK) {
96 if (ReqCaps.
size() == 1) {
97 auto Cap = ReqCaps[0];
99 return {
true, {Cap}, ReqExts, ReqMinVer, ReqMaxVer};
108 for (
auto Cap : ReqCaps)
111 for (
size_t i = 0, Sz = UseCaps.
size(); i < Sz; ++i) {
112 auto Cap = UseCaps[i];
113 if (i == Sz - 1 || !AvoidCaps.
S.
contains(Cap))
114 return {
true, {Cap}, ReqExts, ReqMinVer, ReqMaxVer};
121 if (
llvm::all_of(ReqExts, [&ST](
const SPIRV::Extension::Extension &Ext) {
122 return ST.canUseExtension(Ext);
133void SPIRVModuleAnalysis::setBaseInfo(
const Module &M) {
146 if (
auto MemModel =
M.getNamedMetadata(
"spirv.MemoryModel")) {
147 auto MemMD = MemModel->getOperand(0);
148 MAI.
Addr =
static_cast<SPIRV::AddressingModel::AddressingModel
>(
149 getMetadataUInt(MemMD, 0));
151 static_cast<SPIRV::MemoryModel::MemoryModel
>(getMetadataUInt(MemMD, 1));
154 MAI.
Mem =
ST->isOpenCLEnv() ? SPIRV::MemoryModel::OpenCL
155 : SPIRV::MemoryModel::GLSL450;
156 if (
MAI.
Mem == SPIRV::MemoryModel::OpenCL) {
157 unsigned PtrSize =
ST->getPointerSize();
158 MAI.
Addr = PtrSize == 32 ? SPIRV::AddressingModel::Physical32
159 : PtrSize == 64 ? SPIRV::AddressingModel::Physical64
160 : SPIRV::AddressingModel::Logical;
163 MAI.
Addr = SPIRV::AddressingModel::Logical;
168 if (
auto VerNode =
M.getNamedMetadata(
"opencl.ocl.version")) {
169 MAI.
SrcLang = SPIRV::SourceLanguage::OpenCL_C;
172 assert(VerNode->getNumOperands() > 0 &&
"Invalid SPIR");
173 auto VersionMD = VerNode->getOperand(0);
174 unsigned MajorNum = getMetadataUInt(VersionMD, 0, 2);
175 unsigned MinorNum = getMetadataUInt(VersionMD, 1);
176 unsigned RevNum = getMetadataUInt(VersionMD, 2);
179 (std::max(1U, MajorNum) * 100 + MinorNum) * 1000 + RevNum;
185 if (
ST->isOpenCLEnv()) {
186 MAI.
SrcLang = SPIRV::SourceLanguage::OpenCL_CPP;
194 if (
auto ExtNode =
M.getNamedMetadata(
"opencl.used.extensions")) {
195 for (
unsigned I = 0, E = ExtNode->getNumOperands();
I != E; ++
I) {
213 if (
ST->isOpenCLEnv()) {
216 SPIRV::InstructionSet::OpenCL_std)] =
229 for (
unsigned i = 0; i <
MI.getNumOperands(); ++i) {
233 if (!UseDefReg && MO.
isDef())
238 dbgs() <<
"Unexpectedly, no global id found for the operand ";
240 dbgs() <<
"\nInstruction: ";
252 Signature.push_back(h);
259 unsigned Opcode =
MI.getOpcode();
261 case SPIRV::OpTypeForwardPointer:
264 case SPIRV::OpVariable:
265 return static_cast<SPIRV::StorageClass::StorageClass
>(
266 MI.getOperand(2).getImm()) != SPIRV::StorageClass::Function;
267 case SPIRV::OpFunction:
268 case SPIRV::OpFunctionParameter:
274 if (
UseMI.getOpcode() != SPIRV::OpConstantFunctionPointerINTEL)
291void SPIRVModuleAnalysis::visitFunPtrUse(
293 std::map<const Value *, unsigned> &GlobalToGReg,
const MachineFunction *MF,
304 visitDecl(FunDefMRI, SignatureToGReg, GlobalToGReg, FunDefMF, *OpDefMI);
306 }
while (OpDefMI && (OpDefMI->
getOpcode() == SPIRV::OpFunction ||
307 OpDefMI->
getOpcode() == SPIRV::OpFunctionParameter));
311 "Function definition must refer to a global register");
317void SPIRVModuleAnalysis::visitDecl(
319 std::map<const Value *, unsigned> &GlobalToGReg,
const MachineFunction *MF,
321 unsigned Opcode =
MI.getOpcode();
330 if (Opcode == SPIRV::OpConstantFunctionPointerINTEL &&
331 MRI.getRegClass(OpReg) == &SPIRV::pIDRegClass) {
332 visitFunPtrUse(OpReg, SignatureToGReg, GlobalToGReg, MF,
MI);
340 if (isDeclSection(
MRI, *OpDefMI))
341 visitDecl(
MRI, SignatureToGReg, GlobalToGReg, MF, *OpDefMI);
347 dbgs() <<
"Unexpectedly, no unique definition for the operand ";
349 dbgs() <<
"\nInstruction: ";
354 "No unique definition is found for the virtual register");
358 bool IsFunDef =
false;
362 }
else if (Opcode == SPIRV::OpFunction ||
363 Opcode == SPIRV::OpFunctionParameter) {
364 GReg = handleFunctionOrParameter(MF,
MI, GlobalToGReg, IsFunDef);
367 GReg = handleTypeDeclOrConstant(
MI, SignatureToGReg);
368 }
else if (Opcode == SPIRV::OpVariable) {
369 GReg = handleVariable(MF,
MI, GlobalToGReg);
372 dbgs() <<
"\nInstruction: ";
383Register SPIRVModuleAnalysis::handleFunctionOrParameter(
385 std::map<const Value *, unsigned> &GlobalToGReg,
bool &IsFunDef) {
387 assert(GObj &&
"Unregistered global definition");
388 const Function *
F = dyn_cast<Function>(GObj);
390 F = dyn_cast<Argument>(GObj)->getParent();
391 assert(
F &&
"Expected a reference to a function or an argument");
392 IsFunDef = !
F->isDeclaration();
393 auto It = GlobalToGReg.find(GObj);
394 if (It != GlobalToGReg.end())
397 GlobalToGReg[GObj] = GReg;
404SPIRVModuleAnalysis::handleTypeDeclOrConstant(
const MachineInstr &
MI,
407 auto It = SignatureToGReg.find(MISign);
408 if (It != SignatureToGReg.end())
411 SignatureToGReg[MISign] = GReg;
416Register SPIRVModuleAnalysis::handleVariable(
418 std::map<const Value *, unsigned> &GlobalToGReg) {
421 assert(GObj &&
"Unregistered global definition");
422 auto It = GlobalToGReg.find(GObj);
423 if (It != GlobalToGReg.end())
426 GlobalToGReg[GObj] = GReg;
431void SPIRVModuleAnalysis::collectDeclarations(
const Module &M) {
433 std::map<const Value *, unsigned> GlobalToGReg;
434 for (
auto F =
M.begin(), E =
M.end();
F != E; ++
F) {
439 unsigned PastHeader = 0;
442 if (
MI.getNumOperands() == 0)
444 unsigned Opcode =
MI.getOpcode();
445 if (Opcode == SPIRV::OpFunction) {
446 if (PastHeader == 0) {
450 }
else if (Opcode == SPIRV::OpFunctionParameter) {
453 }
else if (PastHeader > 0) {
459 case SPIRV::OpExtension:
463 case SPIRV::OpCapability:
470 if (DefMO.
isReg() && isDeclSection(
MRI,
MI) &&
472 visitDecl(
MRI, SignatureToGReg, GlobalToGReg, MF,
MI);
485 if (
MI.getOpcode() == SPIRV::OpDecorate) {
487 auto Dec =
MI.getOperand(1).getImm();
488 if (Dec ==
static_cast<unsigned>(SPIRV::Decoration::LinkageAttributes)) {
489 auto Lnk =
MI.getOperand(
MI.getNumOperands() - 1).getImm();
490 if (Lnk ==
static_cast<unsigned>(SPIRV::LinkageType::Import)) {
498 }
else if (
MI.getOpcode() == SPIRV::OpFunction) {
512 bool Append =
true) {
515 auto FoundMI = IS.insert(MISign);
527void SPIRVModuleAnalysis::processOtherInstrs(
const Module &M) {
529 for (
auto F =
M.begin(), E =
M.end();
F != E; ++
F) {
530 if ((*F).isDeclaration())
539 const unsigned OpCode =
MI.getOpcode();
540 if (OpCode == SPIRV::OpString) {
542 }
else if (OpCode == SPIRV::OpExtInst &&
MI.getOperand(2).isImm() &&
543 MI.getOperand(2).getImm() ==
544 SPIRV::InstructionSet::
545 NonSemantic_Shader_DebugInfo_100) {
547 namespace NS = SPIRV::NonSemanticExtInst;
548 static constexpr int64_t GlobalNonSemanticDITy[] = {
549 NS::DebugSource, NS::DebugCompilationUnit, NS::DebugInfoNone,
550 NS::DebugTypeBasic, NS::DebugTypePointer};
551 bool IsGlobalDI =
false;
552 for (
unsigned Idx = 0;
Idx < std::size(GlobalNonSemanticDITy); ++
Idx)
553 IsGlobalDI |=
Ins.getImm() == GlobalNonSemanticDITy[
Idx];
556 }
else if (OpCode == SPIRV::OpName || OpCode == SPIRV::OpMemberName) {
558 }
else if (OpCode == SPIRV::OpEntryPoint) {
560 }
else if (
TII->isDecorationInstr(
MI)) {
562 collectFuncNames(
MI, &*
F);
563 }
else if (
TII->isConstantInstr(
MI)) {
567 }
else if (OpCode == SPIRV::OpFunction) {
568 collectFuncNames(
MI, &*
F);
569 }
else if (OpCode == SPIRV::OpTypeForwardPointer) {
579void SPIRVModuleAnalysis::numberRegistersGlobally(
const Module &M) {
580 for (
auto F =
M.begin(),
E =
M.end();
F !=
E; ++
F) {
581 if ((*F).isDeclaration())
596 if (
MI.getOpcode() != SPIRV::OpExtInst)
598 auto Set =
MI.getOperand(2).getImm();
608 SPIRV::OperandCategory::OperandCategory Category,
uint32_t i,
610 addRequirements(getSymbolicOperandRequirements(Category, i, ST, *
this));
613void SPIRV::RequirementHandler::recursiveAddCapabilities(
615 for (
const auto &Cap : ToPrune) {
619 recursiveAddCapabilities(ImplicitDecls);
624 for (
const auto &Cap : ToAdd) {
625 bool IsNewlyInserted = AllCaps.insert(Cap).second;
626 if (!IsNewlyInserted)
630 recursiveAddCapabilities(ImplicitDecls);
631 MinimalCaps.push_back(Cap);
640 if (Req.
Cap.has_value())
641 addCapabilities({Req.
Cap.value()});
643 addExtensions(Req.
Exts);
646 if (!MaxVersion.empty() && Req.
MinVer > MaxVersion) {
648 <<
" and <= " << MaxVersion <<
"\n");
652 if (MinVersion.empty() || Req.
MinVer > MinVersion)
657 if (!MinVersion.empty() && Req.
MaxVer < MinVersion) {
659 <<
" and >= " << MinVersion <<
"\n");
663 if (MaxVersion.empty() || Req.
MaxVer < MaxVersion)
671 bool IsSatisfiable =
true;
672 auto TargetVer =
ST.getSPIRVVersion();
674 if (!MaxVersion.empty() && !TargetVer.empty() && MaxVersion < TargetVer) {
676 dbgs() <<
"Target SPIR-V version too high for required features\n"
677 <<
"Required max version: " << MaxVersion <<
" target version "
678 << TargetVer <<
"\n");
679 IsSatisfiable =
false;
682 if (!MinVersion.empty() && !TargetVer.empty() && MinVersion > TargetVer) {
683 LLVM_DEBUG(
dbgs() <<
"Target SPIR-V version too low for required features\n"
684 <<
"Required min version: " << MinVersion
685 <<
" target version " << TargetVer <<
"\n");
686 IsSatisfiable =
false;
689 if (!MinVersion.empty() && !MaxVersion.empty() && MinVersion > MaxVersion) {
692 <<
"Version is too low for some features and too high for others.\n"
693 <<
"Required SPIR-V min version: " << MinVersion
694 <<
" required SPIR-V max version " << MaxVersion <<
"\n");
695 IsSatisfiable =
false;
698 for (
auto Cap : MinimalCaps) {
699 if (AvailableCaps.contains(Cap))
703 OperandCategory::CapabilityOperand, Cap)
705 IsSatisfiable =
false;
708 for (
auto Ext : AllExtensions) {
709 if (
ST.canUseExtension(Ext))
713 OperandCategory::ExtensionOperand, Ext)
715 IsSatisfiable =
false;
724 for (
const auto Cap : ToAdd)
725 if (AvailableCaps.insert(Cap).second)
727 SPIRV::OperandCategory::CapabilityOperand, Cap));
731 const Capability::Capability
ToRemove,
732 const Capability::Capability IfPresent) {
733 if (AllCaps.contains(IfPresent))
739void RequirementHandler::initAvailableCapabilities(
const SPIRVSubtarget &ST) {
741 addAvailableCaps({Capability::Shader, Capability::Linkage, Capability::Int8,
745 addAvailableCaps({Capability::GroupNonUniform,
746 Capability::GroupNonUniformVote,
747 Capability::GroupNonUniformArithmetic,
748 Capability::GroupNonUniformBallot,
749 Capability::GroupNonUniformClustered,
750 Capability::GroupNonUniformShuffle,
751 Capability::GroupNonUniformShuffleRelative});
754 addAvailableCaps({Capability::DotProduct, Capability::DotProductInputAll,
755 Capability::DotProductInput4x8Bit,
756 Capability::DotProductInput4x8BitPacked,
757 Capability::DemoteToHelperInvocation});
760 for (
auto Extension :
ST.getAllAvailableExtensions()) {
763 addAvailableCaps(EnabledCapabilities);
766 if (
ST.isOpenCLEnv()) {
767 initAvailableCapabilitiesForOpenCL(ST);
771 if (
ST.isVulkanEnv()) {
772 initAvailableCapabilitiesForVulkan(ST);
779void RequirementHandler::initAvailableCapabilitiesForOpenCL(
782 addAvailableCaps({Capability::Addresses, Capability::Float16Buffer,
783 Capability::Kernel, Capability::Vector16,
784 Capability::Groups, Capability::GenericPointer,
785 Capability::StorageImageWriteWithoutFormat,
786 Capability::StorageImageReadWithoutFormat});
787 if (
ST.hasOpenCLFullProfile())
788 addAvailableCaps({Capability::Int64, Capability::Int64Atomics});
789 if (
ST.hasOpenCLImageSupport()) {
790 addAvailableCaps({Capability::ImageBasic, Capability::LiteralSampler,
791 Capability::Image1D, Capability::SampledBuffer,
792 Capability::ImageBuffer});
794 addAvailableCaps({Capability::ImageReadWrite});
798 addAvailableCaps({Capability::SubgroupDispatch, Capability::PipeStorage});
800 addAvailableCaps({Capability::DenormPreserve, Capability::DenormFlushToZero,
801 Capability::SignedZeroInfNanPreserve,
802 Capability::RoundingModeRTE,
803 Capability::RoundingModeRTZ});
805 addAvailableCaps({Capability::Float16, Capability::Float64});
810void RequirementHandler::initAvailableCapabilitiesForVulkan(
814 addAvailableCaps({Capability::Int64, Capability::Float16, Capability::Float64,
815 Capability::GroupNonUniform, Capability::Image1D,
816 Capability::SampledBuffer, Capability::ImageBuffer,
817 Capability::UniformBufferArrayDynamicIndexing,
818 Capability::SampledImageArrayDynamicIndexing,
819 Capability::StorageBufferArrayDynamicIndexing,
820 Capability::StorageImageArrayDynamicIndexing});
825 {Capability::ShaderNonUniformEXT, Capability::RuntimeDescriptorArrayEXT,
826 Capability::InputAttachmentArrayDynamicIndexingEXT,
827 Capability::UniformTexelBufferArrayDynamicIndexingEXT,
828 Capability::StorageTexelBufferArrayDynamicIndexingEXT,
829 Capability::UniformBufferArrayNonUniformIndexingEXT,
830 Capability::SampledImageArrayNonUniformIndexingEXT,
831 Capability::StorageBufferArrayNonUniformIndexingEXT,
832 Capability::StorageImageArrayNonUniformIndexingEXT,
833 Capability::InputAttachmentArrayNonUniformIndexingEXT,
834 Capability::UniformTexelBufferArrayNonUniformIndexingEXT,
835 Capability::StorageTexelBufferArrayNonUniformIndexingEXT});
840 addAvailableCaps({Capability::StorageImageWriteWithoutFormat,
841 Capability::StorageImageReadWithoutFormat});
849static void addOpDecorateReqs(
const MachineInstr &
MI,
unsigned DecIndex,
852 int64_t DecOp =
MI.getOperand(DecIndex).getImm();
853 auto Dec =
static_cast<SPIRV::Decoration::Decoration
>(DecOp);
855 SPIRV::OperandCategory::DecorationOperand, Dec, ST, Reqs));
857 if (Dec == SPIRV::Decoration::BuiltIn) {
858 int64_t BuiltInOp =
MI.getOperand(DecIndex + 1).getImm();
859 auto BuiltIn =
static_cast<SPIRV::BuiltIn::BuiltIn
>(BuiltInOp);
861 SPIRV::OperandCategory::BuiltInOperand, BuiltIn, ST, Reqs));
862 }
else if (Dec == SPIRV::Decoration::LinkageAttributes) {
863 int64_t LinkageOp =
MI.getOperand(
MI.getNumOperands() - 1).getImm();
864 SPIRV::LinkageType::LinkageType LnkType =
865 static_cast<SPIRV::LinkageType::LinkageType
>(LinkageOp);
866 if (LnkType == SPIRV::LinkageType::LinkOnceODR)
867 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_linkonce_odr);
868 }
else if (Dec == SPIRV::Decoration::CacheControlLoadINTEL ||
869 Dec == SPIRV::Decoration::CacheControlStoreINTEL) {
870 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_cache_controls);
871 }
else if (Dec == SPIRV::Decoration::HostAccessINTEL) {
872 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_global_variable_host_access);
873 }
else if (Dec == SPIRV::Decoration::InitModeINTEL ||
874 Dec == SPIRV::Decoration::ImplementInRegisterMapINTEL) {
876 SPIRV::Extension::SPV_INTEL_global_variable_fpga_decorations);
877 }
else if (Dec == SPIRV::Decoration::NonUniformEXT) {
886 assert(
MI.getNumOperands() >= 8 &&
"Insufficient operands for OpTypeImage");
889 int64_t ImgFormatOp =
MI.getOperand(7).getImm();
890 auto ImgFormat =
static_cast<SPIRV::ImageFormat::ImageFormat
>(ImgFormatOp);
894 bool IsArrayed =
MI.getOperand(4).getImm() == 1;
895 bool IsMultisampled =
MI.getOperand(5).getImm() == 1;
896 bool NoSampler =
MI.getOperand(6).getImm() == 2;
899 switch (
MI.getOperand(2).getImm()) {
900 case SPIRV::Dim::DIM_1D:
902 : SPIRV::Capability::Sampled1D);
904 case SPIRV::Dim::DIM_2D:
905 if (IsMultisampled && NoSampler)
908 case SPIRV::Dim::DIM_Cube:
912 : SPIRV::Capability::SampledCubeArray);
914 case SPIRV::Dim::DIM_Rect:
916 : SPIRV::Capability::SampledRect);
918 case SPIRV::Dim::DIM_Buffer:
920 : SPIRV::Capability::SampledBuffer);
922 case SPIRV::Dim::DIM_SubpassData:
928 if (
ST.isOpenCLEnv()) {
929 if (
MI.getNumOperands() > 8 &&
930 MI.getOperand(8).getImm() == SPIRV::AccessQualifier::ReadWrite)
938#define ATOM_FLT_REQ_EXT_MSG(ExtName) \
939 "The atomic float instruction requires the following SPIR-V " \
940 "extension: SPV_EXT_shader_atomic_float" ExtName
945 "Expect register operand in atomic float instruction");
947 SPIRVType *TypeDef =
MI.getMF()->getRegInfo().getVRegDef(TypeReg);
948 if (TypeDef->
getOpcode() != SPIRV::OpTypeFloat)
950 "floating-point type scalar");
953 unsigned Op =
MI.getOpcode();
954 if (
Op == SPIRV::OpAtomicFAddEXT) {
955 if (!
ST.canUseExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float_add))
957 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float_add);
960 if (!
ST.canUseExtension(
961 SPIRV::Extension::SPV_EXT_shader_atomic_float16_add))
963 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float16_add);
974 "Unexpected floating-point type width in atomic float instruction");
977 if (!
ST.canUseExtension(
978 SPIRV::Extension::SPV_EXT_shader_atomic_float_min_max))
980 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float_min_max);
983 Reqs.
addCapability(SPIRV::Capability::AtomicFloat16MinMaxEXT);
986 Reqs.
addCapability(SPIRV::Capability::AtomicFloat32MinMaxEXT);
989 Reqs.
addCapability(SPIRV::Capability::AtomicFloat64MinMaxEXT);
993 "Unexpected floating-point type width in atomic float instruction");
999 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1003 return Dim == SPIRV::Dim::DIM_Buffer && Sampled == 1;
1007 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1011 return Dim == SPIRV::Dim::DIM_Buffer && Sampled == 2;
1015 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1019 return Dim != SPIRV::Dim::DIM_Buffer && Sampled == 1;
1023 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1027 return Dim == SPIRV::Dim::DIM_SubpassData && Sampled == 2;
1031 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1035 return Dim != SPIRV::Dim::DIM_Buffer && Sampled == 2;
1038bool isCombinedImageSampler(
MachineInstr *SampledImageInst) {
1039 if (SampledImageInst->
getOpcode() != SPIRV::OpTypeSampledImage)
1044 auto *ImageInst =
MRI.getUniqueVRegDef(ImageReg);
1045 return isSampledImage(ImageInst);
1049 for (
const auto &
MI :
MRI.reg_instructions(Reg)) {
1050 if (
MI.getOpcode() != SPIRV::OpDecorate)
1054 if (Dec == SPIRV::Decoration::NonUniformEXT)
1072 if (
StorageClass != SPIRV::StorageClass::StorageClass::UniformConstant &&
1073 StorageClass != SPIRV::StorageClass::StorageClass::Uniform &&
1074 StorageClass != SPIRV::StorageClass::StorageClass::StorageBuffer) {
1080 if (PointeeType->
getOpcode() != SPIRV::OpTypeImage &&
1081 PointeeType->
getOpcode() != SPIRV::OpTypeSampledImage &&
1082 PointeeType->
getOpcode() != SPIRV::OpTypeSampler) {
1087 hasNonUniformDecoration(
Instr.getOperand(0).getReg(),
MRI);
1088 if (isUniformTexelBuffer(PointeeType)) {
1091 SPIRV::Capability::UniformTexelBufferArrayNonUniformIndexingEXT);
1094 SPIRV::Capability::UniformTexelBufferArrayDynamicIndexingEXT);
1095 }
else if (isInputAttachment(PointeeType)) {
1098 SPIRV::Capability::InputAttachmentArrayNonUniformIndexingEXT);
1101 SPIRV::Capability::InputAttachmentArrayDynamicIndexingEXT);
1102 }
else if (isStorageTexelBuffer(PointeeType)) {
1105 SPIRV::Capability::StorageTexelBufferArrayNonUniformIndexingEXT);
1108 SPIRV::Capability::StorageTexelBufferArrayDynamicIndexingEXT);
1109 }
else if (isSampledImage(PointeeType) ||
1110 isCombinedImageSampler(PointeeType) ||
1111 PointeeType->
getOpcode() == SPIRV::OpTypeSampler) {
1114 SPIRV::Capability::SampledImageArrayNonUniformIndexingEXT);
1117 SPIRV::Capability::SampledImageArrayDynamicIndexing);
1118 }
else if (isStorageImage(PointeeType)) {
1121 SPIRV::Capability::StorageImageArrayNonUniformIndexingEXT);
1124 SPIRV::Capability::StorageImageArrayDynamicIndexing);
1128static bool isImageTypeWithUnknownFormat(
SPIRVType *TypeInst) {
1129 if (TypeInst->
getOpcode() != SPIRV::OpTypeImage)
1138 if (
ST.canUseExtension(SPIRV::Extension::SPV_KHR_integer_dot_product))
1139 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_integer_dot_product);
1143 assert(
MI.getOperand(2).isReg() &&
"Unexpected operand in dot");
1151 if (TypeDef->
getOpcode() == SPIRV::OpTypeInt) {
1153 Reqs.
addCapability(SPIRV::Capability::DotProductInput4x8BitPacked);
1154 }
else if (TypeDef->
getOpcode() == SPIRV::OpTypeVector) {
1159 "Dot operand of 8-bit integer type requires 4 components");
1160 Reqs.
addCapability(SPIRV::Capability::DotProductInput4x8Bit);
1170 switch (
MI.getOpcode()) {
1171 case SPIRV::OpMemoryModel: {
1172 int64_t
Addr =
MI.getOperand(0).getImm();
1175 int64_t Mem =
MI.getOperand(1).getImm();
1180 case SPIRV::OpEntryPoint: {
1181 int64_t
Exe =
MI.getOperand(0).getImm();
1186 case SPIRV::OpExecutionMode:
1187 case SPIRV::OpExecutionModeId: {
1188 int64_t
Exe =
MI.getOperand(1).getImm();
1193 case SPIRV::OpTypeMatrix:
1196 case SPIRV::OpTypeInt: {
1197 unsigned BitWidth =
MI.getOperand(1).getImm();
1206 case SPIRV::OpTypeFloat: {
1207 unsigned BitWidth =
MI.getOperand(1).getImm();
1214 case SPIRV::OpTypeVector: {
1215 unsigned NumComponents =
MI.getOperand(2).getImm();
1216 if (NumComponents == 8 || NumComponents == 16)
1220 case SPIRV::OpTypePointer: {
1221 auto SC =
MI.getOperand(1).getImm();
1226 if (!
ST.isOpenCLEnv())
1231 if (TypeDef->
getOpcode() == SPIRV::OpTypeFloat &&
1236 case SPIRV::OpExtInst: {
1237 if (
MI.getOperand(2).getImm() ==
1238 static_cast<int64_t
>(
1239 SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100)) {
1240 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_non_semantic_info);
1244 case SPIRV::OpBitReverse:
1245 case SPIRV::OpBitFieldInsert:
1246 case SPIRV::OpBitFieldSExtract:
1247 case SPIRV::OpBitFieldUExtract:
1248 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_bit_instructions)) {
1252 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_bit_instructions);
1255 case SPIRV::OpTypeRuntimeArray:
1258 case SPIRV::OpTypeOpaque:
1259 case SPIRV::OpTypeEvent:
1262 case SPIRV::OpTypePipe:
1263 case SPIRV::OpTypeReserveId:
1266 case SPIRV::OpTypeDeviceEvent:
1267 case SPIRV::OpTypeQueue:
1268 case SPIRV::OpBuildNDRange:
1271 case SPIRV::OpDecorate:
1272 case SPIRV::OpDecorateId:
1273 case SPIRV::OpDecorateString:
1274 addOpDecorateReqs(
MI, 1, Reqs, ST);
1276 case SPIRV::OpMemberDecorate:
1277 case SPIRV::OpMemberDecorateString:
1278 addOpDecorateReqs(
MI, 2, Reqs, ST);
1280 case SPIRV::OpInBoundsPtrAccessChain:
1283 case SPIRV::OpConstantSampler:
1286 case SPIRV::OpInBoundsAccessChain:
1287 case SPIRV::OpAccessChain:
1288 addOpAccessChainReqs(
MI, Reqs, ST);
1290 case SPIRV::OpTypeImage:
1291 addOpTypeImageReqs(
MI, Reqs, ST);
1293 case SPIRV::OpTypeSampler:
1294 if (!
ST.isVulkanEnv()) {
1298 case SPIRV::OpTypeForwardPointer:
1302 case SPIRV::OpAtomicFlagTestAndSet:
1303 case SPIRV::OpAtomicLoad:
1304 case SPIRV::OpAtomicStore:
1305 case SPIRV::OpAtomicExchange:
1306 case SPIRV::OpAtomicCompareExchange:
1307 case SPIRV::OpAtomicIIncrement:
1308 case SPIRV::OpAtomicIDecrement:
1309 case SPIRV::OpAtomicIAdd:
1310 case SPIRV::OpAtomicISub:
1311 case SPIRV::OpAtomicUMin:
1312 case SPIRV::OpAtomicUMax:
1313 case SPIRV::OpAtomicSMin:
1314 case SPIRV::OpAtomicSMax:
1315 case SPIRV::OpAtomicAnd:
1316 case SPIRV::OpAtomicOr:
1317 case SPIRV::OpAtomicXor: {
1320 if (
MI.getOpcode() == SPIRV::OpAtomicStore) {
1322 InstrPtr =
MRI.getVRegDef(
MI.getOperand(3).getReg());
1323 assert(InstrPtr &&
"Unexpected type instruction for OpAtomicStore");
1328 if (TypeDef->
getOpcode() == SPIRV::OpTypeInt) {
1335 case SPIRV::OpGroupNonUniformIAdd:
1336 case SPIRV::OpGroupNonUniformFAdd:
1337 case SPIRV::OpGroupNonUniformIMul:
1338 case SPIRV::OpGroupNonUniformFMul:
1339 case SPIRV::OpGroupNonUniformSMin:
1340 case SPIRV::OpGroupNonUniformUMin:
1341 case SPIRV::OpGroupNonUniformFMin:
1342 case SPIRV::OpGroupNonUniformSMax:
1343 case SPIRV::OpGroupNonUniformUMax:
1344 case SPIRV::OpGroupNonUniformFMax:
1345 case SPIRV::OpGroupNonUniformBitwiseAnd:
1346 case SPIRV::OpGroupNonUniformBitwiseOr:
1347 case SPIRV::OpGroupNonUniformBitwiseXor:
1348 case SPIRV::OpGroupNonUniformLogicalAnd:
1349 case SPIRV::OpGroupNonUniformLogicalOr:
1350 case SPIRV::OpGroupNonUniformLogicalXor: {
1352 int64_t GroupOp =
MI.getOperand(3).getImm();
1354 case SPIRV::GroupOperation::Reduce:
1355 case SPIRV::GroupOperation::InclusiveScan:
1356 case SPIRV::GroupOperation::ExclusiveScan:
1357 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformArithmetic);
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(
1701 if (isImageTypeWithUnknownFormat(TypeDef))
1702 Reqs.
addCapability(SPIRV::Capability::StorageImageReadWithoutFormat);
1705 case SPIRV::OpImageWrite: {
1706 Register ImageReg =
MI.getOperand(0).getReg();
1707 SPIRVType *TypeDef =
ST.getSPIRVGlobalRegistry()->getResultType(
1709 if (isImageTypeWithUnknownFormat(TypeDef))
1710 Reqs.
addCapability(SPIRV::Capability::StorageImageWriteWithoutFormat);
1722 SPIRV::Capability::Shader);
1728 for (
auto F =
M.begin(), E =
M.end();
F != E; ++
F) {
1734 addInstrRequirements(
MI, MAI.
Reqs, ST);
1737 auto Node =
M.getNamedMetadata(
"spirv.ExecutionMode");
1739 bool RequireFloatControls =
false, RequireFloatControls2 =
false,
1741 bool HasFloatControls2 =
1742 ST.canUseExtension(SPIRV::Extension::SPV_INTEL_float_controls2);
1743 for (
unsigned i = 0; i <
Node->getNumOperands(); i++) {
1744 MDNode *MDN = cast<MDNode>(
Node->getOperand(i));
1746 if (
auto *CMeta = dyn_cast<ConstantAsMetadata>(MDOp)) {
1749 auto EM =
Const->getZExtValue();
1753 case SPIRV::ExecutionMode::DenormPreserve:
1754 case SPIRV::ExecutionMode::DenormFlushToZero:
1755 case SPIRV::ExecutionMode::SignedZeroInfNanPreserve:
1756 case SPIRV::ExecutionMode::RoundingModeRTE:
1757 case SPIRV::ExecutionMode::RoundingModeRTZ:
1758 RequireFloatControls = VerLower14;
1760 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
1762 case SPIRV::ExecutionMode::RoundingModeRTPINTEL:
1763 case SPIRV::ExecutionMode::RoundingModeRTNINTEL:
1764 case SPIRV::ExecutionMode::FloatingPointModeALTINTEL:
1765 case SPIRV::ExecutionMode::FloatingPointModeIEEEINTEL:
1766 if (HasFloatControls2) {
1767 RequireFloatControls2 =
true;
1769 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
1774 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
1779 if (RequireFloatControls &&
1780 ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls))
1782 if (RequireFloatControls2)
1785 for (
auto FI =
M.begin(), E =
M.end(); FI != E; ++FI) {
1787 if (
F.isDeclaration())
1789 if (
F.getMetadata(
"reqd_work_group_size"))
1791 SPIRV::OperandCategory::ExecutionModeOperand,
1792 SPIRV::ExecutionMode::LocalSize, ST);
1793 if (
F.getFnAttribute(
"hlsl.numthreads").isValid()) {
1795 SPIRV::OperandCategory::ExecutionModeOperand,
1796 SPIRV::ExecutionMode::LocalSize, ST);
1798 if (
F.getMetadata(
"work_group_size_hint"))
1800 SPIRV::OperandCategory::ExecutionModeOperand,
1801 SPIRV::ExecutionMode::LocalSizeHint, ST);
1802 if (
F.getMetadata(
"intel_reqd_sub_group_size"))
1804 SPIRV::OperandCategory::ExecutionModeOperand,
1805 SPIRV::ExecutionMode::SubgroupSize, ST);
1806 if (
F.getMetadata(
"vec_type_hint"))
1808 SPIRV::OperandCategory::ExecutionModeOperand,
1809 SPIRV::ExecutionMode::VecTypeHint, ST);
1811 if (
F.hasOptNone()) {
1812 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_optnone)) {
1815 }
else if (
ST.canUseExtension(SPIRV::Extension::SPV_EXT_optnone)) {
1824 unsigned Flags = SPIRV::FPFastMathMode::None;
1826 Flags |= SPIRV::FPFastMathMode::NotNaN;
1828 Flags |= SPIRV::FPFastMathMode::NotInf;
1830 Flags |= SPIRV::FPFastMathMode::NSZ;
1832 Flags |= SPIRV::FPFastMathMode::AllowRecip;
1834 Flags |= SPIRV::FPFastMathMode::Fast;
1842 getSymbolicOperandRequirements(SPIRV::OperandCategory::DecorationOperand,
1843 SPIRV::Decoration::NoSignedWrap, ST, Reqs)
1846 SPIRV::Decoration::NoSignedWrap, {});
1849 getSymbolicOperandRequirements(SPIRV::OperandCategory::DecorationOperand,
1850 SPIRV::Decoration::NoUnsignedWrap, ST,
1854 SPIRV::Decoration::NoUnsignedWrap, {});
1856 if (!
TII.canUseFastMathFlags(
I))
1858 unsigned FMFlags = getFastMathFlags(
I);
1859 if (FMFlags == SPIRV::FPFastMathMode::None)
1861 Register DstReg =
I.getOperand(0).getReg();
1869 for (
auto F =
M.begin(), E =
M.end();
F != E; ++
F) {
1873 for (
auto &
MBB : *MF)
1874 for (
auto &
MI :
MBB)
1875 handleMIFlagDecoration(
MI, ST,
TII, MAI.
Reqs);
1882 for (
auto F =
M.begin(), E =
M.end();
F != E; ++
F) {
1887 for (
auto &
MBB : *MF) {
1892 MRI.setRegClass(Reg, &SPIRV::IDRegClass);
1903 for (
auto F =
M.begin(), E =
M.end();
F != E; ++
F) {
1907 for (
auto &
MBB : *MF) {
1909 if (
MI.getOpcode() != TargetOpcode::PHI)
1911 MI.setDesc(
TII.get(SPIRV::OpPhi));
1914 MI.insert(
MI.operands_begin() + 1,
1915 {MachineOperand::CreateReg(ResTypeReg, false)});
1931 ST = TM.getSubtargetImpl();
1932 GR = ST->getSPIRVGlobalRegistry();
1933 TII = ST->getInstrInfo();
1935 MMI = &getAnalysis<MachineModuleInfoWrapperPass>().getMMI();
1939 patchPhis(M, GR, *
TII, MMI);
1941 addMBBNames(M, *
TII, MMI, *ST, MAI);
1942 addDecorations(M, *
TII, MMI, *ST, MAI);
1944 collectReqs(M, MAI, MMI, *ST);
1948 collectDeclarations(M);
1951 numberRegistersGlobally(M);
1954 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