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")));
58 if (MdNode && OpIndex < MdNode->getNumOperands()) {
59 const auto &
Op = MdNode->getOperand(
OpIndex);
60 return mdconst::extract<ConstantInt>(
Op)->getZExtValue();
66getSymbolicOperandRequirements(SPIRV::OperandCategory::OperandCategory Category,
72 AvoidCaps.
S.
insert(SPIRV::Capability::Shader);
74 AvoidCaps.
S.
insert(SPIRV::Capability::Kernel);
79 bool MinVerOK = SPIRVVersion.
empty() || SPIRVVersion >= ReqMinVer;
81 ReqMaxVer.
empty() || SPIRVVersion.
empty() || SPIRVVersion <= ReqMaxVer;
84 if (ReqCaps.
empty()) {
85 if (ReqExts.
empty()) {
86 if (MinVerOK && MaxVerOK)
87 return {
true, {}, {}, ReqMinVer, ReqMaxVer};
90 }
else if (MinVerOK && MaxVerOK) {
91 if (ReqCaps.
size() == 1) {
92 auto Cap = ReqCaps[0];
95 SPIRV::OperandCategory::CapabilityOperand, Cap));
96 return {
true, {Cap}, std::move(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)) {
113 SPIRV::OperandCategory::CapabilityOperand, Cap));
114 return {
true, {Cap}, std::move(ReqExts), ReqMinVer, ReqMaxVer};
122 if (
llvm::all_of(ReqExts, [&ST](
const SPIRV::Extension::Extension &Ext) {
123 return ST.canUseExtension(Ext);
134void SPIRVModuleAnalysis::setBaseInfo(
const Module &M) {
147 if (
auto MemModel =
M.getNamedMetadata(
"spirv.MemoryModel")) {
148 auto MemMD = MemModel->getOperand(0);
149 MAI.
Addr =
static_cast<SPIRV::AddressingModel::AddressingModel
>(
150 getMetadataUInt(MemMD, 0));
152 static_cast<SPIRV::MemoryModel::MemoryModel
>(getMetadataUInt(MemMD, 1));
155 MAI.
Mem =
ST->isShader() ? SPIRV::MemoryModel::GLSL450
156 : SPIRV::MemoryModel::OpenCL;
157 if (
MAI.
Mem == SPIRV::MemoryModel::OpenCL) {
158 unsigned PtrSize =
ST->getPointerSize();
159 MAI.
Addr = PtrSize == 32 ? SPIRV::AddressingModel::Physical32
160 : PtrSize == 64 ? SPIRV::AddressingModel::Physical64
161 : SPIRV::AddressingModel::Logical;
164 MAI.
Addr = SPIRV::AddressingModel::Logical;
169 if (
auto VerNode =
M.getNamedMetadata(
"opencl.ocl.version")) {
170 MAI.
SrcLang = SPIRV::SourceLanguage::OpenCL_C;
173 assert(VerNode->getNumOperands() > 0 &&
"Invalid SPIR");
174 auto VersionMD = VerNode->getOperand(0);
175 unsigned MajorNum = getMetadataUInt(VersionMD, 0, 2);
176 unsigned MinorNum = getMetadataUInt(VersionMD, 1);
177 unsigned RevNum = getMetadataUInt(VersionMD, 2);
180 (std::max(1U, MajorNum) * 100 + MinorNum) * 1000 + RevNum;
186 if (!
ST->isShader()) {
187 MAI.
SrcLang = SPIRV::SourceLanguage::OpenCL_CPP;
195 if (
auto ExtNode =
M.getNamedMetadata(
"opencl.used.extensions")) {
196 for (
unsigned I = 0, E = ExtNode->getNumOperands();
I != E; ++
I) {
214 if (!
ST->isShader()) {
228 if (
UseMI.getOpcode() != SPIRV::OpDecorate &&
229 UseMI.getOpcode() != SPIRV::OpMemberDecorate)
232 for (
unsigned I = 0;
I <
UseMI.getNumOperands(); ++
I) {
250 for (
unsigned i = 0; i <
MI.getNumOperands(); ++i) {
254 if (!UseDefReg && MO.
isDef()) {
262 dbgs() <<
"Unexpectedly, no global id found for the operand ";
264 dbgs() <<
"\nInstruction: ";
283 appendDecorationsForReg(
MI.getMF()->getRegInfo(), DefReg, Signature);
290 unsigned Opcode =
MI.getOpcode();
292 case SPIRV::OpTypeForwardPointer:
295 case SPIRV::OpVariable:
296 return static_cast<SPIRV::StorageClass::StorageClass
>(
297 MI.getOperand(2).getImm()) != SPIRV::StorageClass::Function;
298 case SPIRV::OpFunction:
299 case SPIRV::OpFunctionParameter:
305 if (
UseMI.getOpcode() != SPIRV::OpConstantFunctionPointerINTEL)
322void SPIRVModuleAnalysis::visitFunPtrUse(
324 std::map<const Value *, unsigned> &GlobalToGReg,
const MachineFunction *MF,
335 visitDecl(FunDefMRI, SignatureToGReg, GlobalToGReg, FunDefMF, *OpDefMI);
337 }
while (OpDefMI && (OpDefMI->
getOpcode() == SPIRV::OpFunction ||
338 OpDefMI->
getOpcode() == SPIRV::OpFunctionParameter));
343 "Function definition must refer to a global register");
349void SPIRVModuleAnalysis::visitDecl(
351 std::map<const Value *, unsigned> &GlobalToGReg,
const MachineFunction *MF,
353 unsigned Opcode =
MI.getOpcode();
361 if (Opcode == SPIRV::OpConstantFunctionPointerINTEL &&
362 MRI.getRegClass(OpReg) == &SPIRV::pIDRegClass) {
363 visitFunPtrUse(OpReg, SignatureToGReg, GlobalToGReg, MF,
MI);
371 if (isDeclSection(
MRI, *OpDefMI))
372 visitDecl(
MRI, SignatureToGReg, GlobalToGReg, MF, *OpDefMI);
378 dbgs() <<
"Unexpectedly, no unique definition for the operand ";
380 dbgs() <<
"\nInstruction: ";
385 "No unique definition is found for the virtual register");
389 bool IsFunDef =
false;
393 }
else if (Opcode == SPIRV::OpFunction ||
394 Opcode == SPIRV::OpFunctionParameter) {
395 GReg = handleFunctionOrParameter(MF,
MI, GlobalToGReg, IsFunDef);
396 }
else if (Opcode == SPIRV::OpTypeStruct ||
397 Opcode == SPIRV::OpConstantComposite) {
398 GReg = handleTypeDeclOrConstant(
MI, SignatureToGReg);
401 ((Opcode == SPIRV::OpTypeStruct &&
402 NextInstr->
getOpcode() == SPIRV::OpTypeStructContinuedINTEL) ||
403 (Opcode == SPIRV::OpConstantComposite &&
405 SPIRV::OpConstantCompositeContinuedINTEL))) {
406 MCRegister Tmp = handleTypeDeclOrConstant(*NextInstr, SignatureToGReg);
413 GReg = handleTypeDeclOrConstant(
MI, SignatureToGReg);
414 }
else if (Opcode == SPIRV::OpVariable) {
415 GReg = handleVariable(MF,
MI, GlobalToGReg);
418 dbgs() <<
"\nInstruction: ";
429MCRegister SPIRVModuleAnalysis::handleFunctionOrParameter(
431 std::map<const Value *, unsigned> &GlobalToGReg,
bool &IsFunDef) {
433 assert(GObj &&
"Unregistered global definition");
434 const Function *
F = dyn_cast<Function>(GObj);
436 F = dyn_cast<Argument>(GObj)->getParent();
437 assert(
F &&
"Expected a reference to a function or an argument");
438 IsFunDef = !
F->isDeclaration();
439 auto [It,
Inserted] = GlobalToGReg.try_emplace(GObj);
450SPIRVModuleAnalysis::handleTypeDeclOrConstant(
const MachineInstr &
MI,
453 auto [It,
Inserted] = SignatureToGReg.try_emplace(MISign);
462MCRegister SPIRVModuleAnalysis::handleVariable(
464 std::map<const Value *, unsigned> &GlobalToGReg) {
467 assert(GObj &&
"Unregistered global definition");
468 auto [It,
Inserted] = GlobalToGReg.try_emplace(GObj);
477void SPIRVModuleAnalysis::collectDeclarations(
const Module &M) {
479 std::map<const Value *, unsigned> GlobalToGReg;
480 for (
auto F =
M.begin(), E =
M.end();
F != E; ++
F) {
485 unsigned PastHeader = 0;
488 if (
MI.getNumOperands() == 0)
490 unsigned Opcode =
MI.getOpcode();
491 if (Opcode == SPIRV::OpFunction) {
492 if (PastHeader == 0) {
496 }
else if (Opcode == SPIRV::OpFunctionParameter) {
499 }
else if (PastHeader > 0) {
505 case SPIRV::OpExtension:
509 case SPIRV::OpCapability:
516 if (DefMO.
isReg() && isDeclSection(
MRI,
MI) &&
518 visitDecl(
MRI, SignatureToGReg, GlobalToGReg, MF,
MI);
531 if (
MI.getOpcode() == SPIRV::OpDecorate) {
533 auto Dec =
MI.getOperand(1).getImm();
534 if (Dec ==
static_cast<unsigned>(SPIRV::Decoration::LinkageAttributes)) {
535 auto Lnk =
MI.getOperand(
MI.getNumOperands() - 1).getImm();
536 if (Lnk ==
static_cast<unsigned>(SPIRV::LinkageType::Import)) {
544 }
else if (
MI.getOpcode() == SPIRV::OpFunction) {
558 bool Append =
true) {
561 auto FoundMI = IS.insert(std::move(MISign));
573void SPIRVModuleAnalysis::processOtherInstrs(
const Module &M) {
575 for (
auto F =
M.begin(), E =
M.end();
F != E; ++
F) {
576 if ((*F).isDeclaration())
585 const unsigned OpCode =
MI.getOpcode();
586 if (OpCode == SPIRV::OpString) {
588 }
else if (OpCode == SPIRV::OpExtInst &&
MI.getOperand(2).isImm() &&
589 MI.getOperand(2).getImm() ==
590 SPIRV::InstructionSet::
591 NonSemantic_Shader_DebugInfo_100) {
593 namespace NS = SPIRV::NonSemanticExtInst;
594 static constexpr int64_t GlobalNonSemanticDITy[] = {
595 NS::DebugSource, NS::DebugCompilationUnit, NS::DebugInfoNone,
596 NS::DebugTypeBasic, NS::DebugTypePointer};
597 bool IsGlobalDI =
false;
598 for (
unsigned Idx = 0;
Idx < std::size(GlobalNonSemanticDITy); ++
Idx)
599 IsGlobalDI |=
Ins.getImm() == GlobalNonSemanticDITy[
Idx];
602 }
else if (OpCode == SPIRV::OpName || OpCode == SPIRV::OpMemberName) {
604 }
else if (OpCode == SPIRV::OpEntryPoint) {
606 }
else if (
TII->isAliasingInstr(
MI)) {
608 }
else if (
TII->isDecorationInstr(
MI)) {
610 collectFuncNames(
MI, &*
F);
611 }
else if (
TII->isConstantInstr(
MI)) {
615 }
else if (OpCode == SPIRV::OpFunction) {
616 collectFuncNames(
MI, &*
F);
617 }
else if (OpCode == SPIRV::OpTypeForwardPointer) {
627void SPIRVModuleAnalysis::numberRegistersGlobally(
const Module &M) {
628 for (
auto F =
M.begin(),
E =
M.end();
F !=
E; ++
F) {
629 if ((*F).isDeclaration())
644 if (
MI.getOpcode() != SPIRV::OpExtInst)
646 auto Set =
MI.getOperand(2).getImm();
657 SPIRV::OperandCategory::OperandCategory Category,
uint32_t i,
659 addRequirements(getSymbolicOperandRequirements(Category, i, ST, *
this));
662void SPIRV::RequirementHandler::recursiveAddCapabilities(
664 for (
const auto &Cap : ToPrune) {
668 recursiveAddCapabilities(ImplicitDecls);
673 for (
const auto &Cap : ToAdd) {
674 bool IsNewlyInserted = AllCaps.insert(Cap).second;
675 if (!IsNewlyInserted)
679 recursiveAddCapabilities(ImplicitDecls);
680 MinimalCaps.push_back(Cap);
689 if (Req.
Cap.has_value())
690 addCapabilities({Req.
Cap.value()});
692 addExtensions(Req.
Exts);
695 if (!MaxVersion.empty() && Req.
MinVer > MaxVersion) {
697 <<
" and <= " << MaxVersion <<
"\n");
701 if (MinVersion.empty() || Req.
MinVer > MinVersion)
706 if (!MinVersion.empty() && Req.
MaxVer < MinVersion) {
708 <<
" and >= " << MinVersion <<
"\n");
712 if (MaxVersion.empty() || Req.
MaxVer < MaxVersion)
720 bool IsSatisfiable =
true;
721 auto TargetVer =
ST.getSPIRVVersion();
723 if (!MaxVersion.empty() && !TargetVer.empty() && MaxVersion < TargetVer) {
725 dbgs() <<
"Target SPIR-V version too high for required features\n"
726 <<
"Required max version: " << MaxVersion <<
" target version "
727 << TargetVer <<
"\n");
728 IsSatisfiable =
false;
731 if (!MinVersion.empty() && !TargetVer.empty() && MinVersion > TargetVer) {
732 LLVM_DEBUG(
dbgs() <<
"Target SPIR-V version too low for required features\n"
733 <<
"Required min version: " << MinVersion
734 <<
" target version " << TargetVer <<
"\n");
735 IsSatisfiable =
false;
738 if (!MinVersion.empty() && !MaxVersion.empty() && MinVersion > MaxVersion) {
741 <<
"Version is too low for some features and too high for others.\n"
742 <<
"Required SPIR-V min version: " << MinVersion
743 <<
" required SPIR-V max version " << MaxVersion <<
"\n");
744 IsSatisfiable =
false;
749 AvoidCaps.
S.
insert(SPIRV::Capability::Shader);
751 AvoidCaps.
S.
insert(SPIRV::Capability::Kernel);
753 for (
auto Cap : MinimalCaps) {
754 if (AvailableCaps.contains(Cap) && !AvoidCaps.
S.
contains(Cap))
758 OperandCategory::CapabilityOperand, Cap)
760 IsSatisfiable =
false;
763 for (
auto Ext : AllExtensions) {
764 if (
ST.canUseExtension(Ext))
768 OperandCategory::ExtensionOperand, Ext)
770 IsSatisfiable =
false;
779 for (
const auto Cap : ToAdd)
780 if (AvailableCaps.insert(Cap).second)
782 SPIRV::OperandCategory::CapabilityOperand, Cap));
786 const Capability::Capability
ToRemove,
787 const Capability::Capability IfPresent) {
788 if (AllCaps.contains(IfPresent))
794void RequirementHandler::initAvailableCapabilities(
const SPIRVSubtarget &ST) {
796 addAvailableCaps({Capability::Shader, Capability::Linkage, Capability::Int8,
800 addAvailableCaps({Capability::GroupNonUniform,
801 Capability::GroupNonUniformVote,
802 Capability::GroupNonUniformArithmetic,
803 Capability::GroupNonUniformBallot,
804 Capability::GroupNonUniformClustered,
805 Capability::GroupNonUniformShuffle,
806 Capability::GroupNonUniformShuffleRelative});
809 addAvailableCaps({Capability::DotProduct, Capability::DotProductInputAll,
810 Capability::DotProductInput4x8Bit,
811 Capability::DotProductInput4x8BitPacked,
812 Capability::DemoteToHelperInvocation});
815 for (
auto Extension :
ST.getAllAvailableExtensions()) {
818 addAvailableCaps(EnabledCapabilities);
821 if (!
ST.isShader()) {
822 initAvailableCapabilitiesForOpenCL(ST);
827 initAvailableCapabilitiesForVulkan(ST);
834void RequirementHandler::initAvailableCapabilitiesForOpenCL(
837 addAvailableCaps({Capability::Addresses, Capability::Float16Buffer,
838 Capability::Kernel, Capability::Vector16,
839 Capability::Groups, Capability::GenericPointer,
840 Capability::StorageImageWriteWithoutFormat,
841 Capability::StorageImageReadWithoutFormat});
842 if (
ST.hasOpenCLFullProfile())
843 addAvailableCaps({Capability::Int64, Capability::Int64Atomics});
844 if (
ST.hasOpenCLImageSupport()) {
845 addAvailableCaps({Capability::ImageBasic, Capability::LiteralSampler,
846 Capability::Image1D, Capability::SampledBuffer,
847 Capability::ImageBuffer});
849 addAvailableCaps({Capability::ImageReadWrite});
853 addAvailableCaps({Capability::SubgroupDispatch, Capability::PipeStorage});
855 addAvailableCaps({Capability::DenormPreserve, Capability::DenormFlushToZero,
856 Capability::SignedZeroInfNanPreserve,
857 Capability::RoundingModeRTE,
858 Capability::RoundingModeRTZ});
860 addAvailableCaps({Capability::Float16, Capability::Float64});
865void RequirementHandler::initAvailableCapabilitiesForVulkan(
869 addAvailableCaps({Capability::Int64, Capability::Float16, Capability::Float64,
870 Capability::GroupNonUniform, Capability::Image1D,
871 Capability::SampledBuffer, Capability::ImageBuffer,
872 Capability::UniformBufferArrayDynamicIndexing,
873 Capability::SampledImageArrayDynamicIndexing,
874 Capability::StorageBufferArrayDynamicIndexing,
875 Capability::StorageImageArrayDynamicIndexing});
880 {Capability::ShaderNonUniformEXT, Capability::RuntimeDescriptorArrayEXT,
881 Capability::InputAttachmentArrayDynamicIndexingEXT,
882 Capability::UniformTexelBufferArrayDynamicIndexingEXT,
883 Capability::StorageTexelBufferArrayDynamicIndexingEXT,
884 Capability::UniformBufferArrayNonUniformIndexingEXT,
885 Capability::SampledImageArrayNonUniformIndexingEXT,
886 Capability::StorageBufferArrayNonUniformIndexingEXT,
887 Capability::StorageImageArrayNonUniformIndexingEXT,
888 Capability::InputAttachmentArrayNonUniformIndexingEXT,
889 Capability::UniformTexelBufferArrayNonUniformIndexingEXT,
890 Capability::StorageTexelBufferArrayNonUniformIndexingEXT});
895 addAvailableCaps({Capability::StorageImageWriteWithoutFormat,
896 Capability::StorageImageReadWithoutFormat});
904static void addOpDecorateReqs(
const MachineInstr &
MI,
unsigned DecIndex,
907 int64_t DecOp =
MI.getOperand(DecIndex).getImm();
908 auto Dec =
static_cast<SPIRV::Decoration::Decoration
>(DecOp);
910 SPIRV::OperandCategory::DecorationOperand, Dec, ST, Reqs));
912 if (Dec == SPIRV::Decoration::BuiltIn) {
913 int64_t BuiltInOp =
MI.getOperand(DecIndex + 1).getImm();
914 auto BuiltIn =
static_cast<SPIRV::BuiltIn::BuiltIn
>(BuiltInOp);
916 SPIRV::OperandCategory::BuiltInOperand, BuiltIn, ST, Reqs));
917 }
else if (Dec == SPIRV::Decoration::LinkageAttributes) {
918 int64_t LinkageOp =
MI.getOperand(
MI.getNumOperands() - 1).
getImm();
919 SPIRV::LinkageType::LinkageType LnkType =
920 static_cast<SPIRV::LinkageType::LinkageType
>(LinkageOp);
921 if (LnkType == SPIRV::LinkageType::LinkOnceODR)
922 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_linkonce_odr);
923 }
else if (Dec == SPIRV::Decoration::CacheControlLoadINTEL ||
924 Dec == SPIRV::Decoration::CacheControlStoreINTEL) {
925 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_cache_controls);
926 }
else if (Dec == SPIRV::Decoration::HostAccessINTEL) {
927 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_global_variable_host_access);
928 }
else if (Dec == SPIRV::Decoration::InitModeINTEL ||
929 Dec == SPIRV::Decoration::ImplementInRegisterMapINTEL) {
931 SPIRV::Extension::SPV_INTEL_global_variable_fpga_decorations);
932 }
else if (Dec == SPIRV::Decoration::NonUniformEXT) {
934 }
else if (Dec == SPIRV::Decoration::FPMaxErrorDecorationINTEL) {
936 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_fp_max_error);
944 assert(
MI.getNumOperands() >= 8 &&
"Insufficient operands for OpTypeImage");
947 int64_t ImgFormatOp =
MI.getOperand(7).getImm();
948 auto ImgFormat =
static_cast<SPIRV::ImageFormat::ImageFormat
>(ImgFormatOp);
952 bool IsArrayed =
MI.getOperand(4).getImm() == 1;
953 bool IsMultisampled =
MI.getOperand(5).getImm() == 1;
954 bool NoSampler =
MI.getOperand(6).getImm() == 2;
957 switch (
MI.getOperand(2).getImm()) {
958 case SPIRV::Dim::DIM_1D:
960 : SPIRV::Capability::Sampled1D);
962 case SPIRV::Dim::DIM_2D:
963 if (IsMultisampled && NoSampler)
966 case SPIRV::Dim::DIM_Cube:
970 : SPIRV::Capability::SampledCubeArray);
972 case SPIRV::Dim::DIM_Rect:
974 : SPIRV::Capability::SampledRect);
976 case SPIRV::Dim::DIM_Buffer:
978 : SPIRV::Capability::SampledBuffer);
980 case SPIRV::Dim::DIM_SubpassData:
986 if (!
ST.isShader()) {
987 if (
MI.getNumOperands() > 8 &&
988 MI.getOperand(8).getImm() == SPIRV::AccessQualifier::ReadWrite)
996#define ATOM_FLT_REQ_EXT_MSG(ExtName) \
997 "The atomic float instruction requires the following SPIR-V " \
998 "extension: SPV_EXT_shader_atomic_float" ExtName
1003 "Expect register operand in atomic float instruction");
1004 Register TypeReg =
MI.getOperand(1).getReg();
1005 SPIRVType *TypeDef =
MI.getMF()->getRegInfo().getVRegDef(TypeReg);
1006 if (TypeDef->
getOpcode() != SPIRV::OpTypeFloat)
1008 "floating-point type scalar");
1011 unsigned Op =
MI.getOpcode();
1012 if (
Op == SPIRV::OpAtomicFAddEXT) {
1013 if (!
ST.canUseExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float_add))
1015 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float_add);
1018 if (!
ST.canUseExtension(
1019 SPIRV::Extension::SPV_EXT_shader_atomic_float16_add))
1021 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float16_add);
1032 "Unexpected floating-point type width in atomic float instruction");
1035 if (!
ST.canUseExtension(
1036 SPIRV::Extension::SPV_EXT_shader_atomic_float_min_max))
1038 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float_min_max);
1041 Reqs.
addCapability(SPIRV::Capability::AtomicFloat16MinMaxEXT);
1044 Reqs.
addCapability(SPIRV::Capability::AtomicFloat32MinMaxEXT);
1047 Reqs.
addCapability(SPIRV::Capability::AtomicFloat64MinMaxEXT);
1051 "Unexpected floating-point type width in atomic float instruction");
1057 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1061 return Dim == SPIRV::Dim::DIM_Buffer && Sampled == 1;
1065 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1069 return Dim == SPIRV::Dim::DIM_Buffer && Sampled == 2;
1073 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1077 return Dim != SPIRV::Dim::DIM_Buffer && Sampled == 1;
1081 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1085 return Dim == SPIRV::Dim::DIM_SubpassData && Sampled == 2;
1089 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1093 return Dim != SPIRV::Dim::DIM_Buffer && Sampled == 2;
1096bool isCombinedImageSampler(
MachineInstr *SampledImageInst) {
1097 if (SampledImageInst->
getOpcode() != SPIRV::OpTypeSampledImage)
1102 auto *ImageInst =
MRI.getUniqueVRegDef(ImageReg);
1103 return isSampledImage(ImageInst);
1107 for (
const auto &
MI :
MRI.reg_instructions(Reg)) {
1108 if (
MI.getOpcode() != SPIRV::OpDecorate)
1112 if (Dec == SPIRV::Decoration::NonUniformEXT)
1130 if (
StorageClass != SPIRV::StorageClass::StorageClass::UniformConstant &&
1131 StorageClass != SPIRV::StorageClass::StorageClass::Uniform &&
1132 StorageClass != SPIRV::StorageClass::StorageClass::StorageBuffer) {
1138 if (PointeeType->
getOpcode() != SPIRV::OpTypeImage &&
1139 PointeeType->
getOpcode() != SPIRV::OpTypeSampledImage &&
1140 PointeeType->
getOpcode() != SPIRV::OpTypeSampler) {
1145 hasNonUniformDecoration(
Instr.getOperand(0).getReg(),
MRI);
1146 if (isUniformTexelBuffer(PointeeType)) {
1149 SPIRV::Capability::UniformTexelBufferArrayNonUniformIndexingEXT);
1152 SPIRV::Capability::UniformTexelBufferArrayDynamicIndexingEXT);
1153 }
else if (isInputAttachment(PointeeType)) {
1156 SPIRV::Capability::InputAttachmentArrayNonUniformIndexingEXT);
1159 SPIRV::Capability::InputAttachmentArrayDynamicIndexingEXT);
1160 }
else if (isStorageTexelBuffer(PointeeType)) {
1163 SPIRV::Capability::StorageTexelBufferArrayNonUniformIndexingEXT);
1166 SPIRV::Capability::StorageTexelBufferArrayDynamicIndexingEXT);
1167 }
else if (isSampledImage(PointeeType) ||
1168 isCombinedImageSampler(PointeeType) ||
1169 PointeeType->
getOpcode() == SPIRV::OpTypeSampler) {
1172 SPIRV::Capability::SampledImageArrayNonUniformIndexingEXT);
1175 SPIRV::Capability::SampledImageArrayDynamicIndexing);
1176 }
else if (isStorageImage(PointeeType)) {
1179 SPIRV::Capability::StorageImageArrayNonUniformIndexingEXT);
1182 SPIRV::Capability::StorageImageArrayDynamicIndexing);
1186static bool isImageTypeWithUnknownFormat(
SPIRVType *TypeInst) {
1187 if (TypeInst->
getOpcode() != SPIRV::OpTypeImage)
1196 if (
ST.canUseExtension(SPIRV::Extension::SPV_KHR_integer_dot_product))
1197 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_integer_dot_product);
1201 assert(
MI.getOperand(2).isReg() &&
"Unexpected operand in dot");
1209 if (TypeDef->
getOpcode() == SPIRV::OpTypeInt) {
1211 Reqs.
addCapability(SPIRV::Capability::DotProductInput4x8BitPacked);
1212 }
else if (TypeDef->
getOpcode() == SPIRV::OpTypeVector) {
1217 "Dot operand of 8-bit integer type requires 4 components");
1218 Reqs.
addCapability(SPIRV::Capability::DotProductInput4x8Bit);
1228 switch (
MI.getOpcode()) {
1229 case SPIRV::OpMemoryModel: {
1230 int64_t
Addr =
MI.getOperand(0).getImm();
1233 int64_t Mem =
MI.getOperand(1).getImm();
1238 case SPIRV::OpEntryPoint: {
1239 int64_t
Exe =
MI.getOperand(0).getImm();
1244 case SPIRV::OpExecutionMode:
1245 case SPIRV::OpExecutionModeId: {
1246 int64_t
Exe =
MI.getOperand(1).getImm();
1251 case SPIRV::OpTypeMatrix:
1254 case SPIRV::OpTypeInt: {
1255 unsigned BitWidth =
MI.getOperand(1).getImm();
1264 case SPIRV::OpTypeFloat: {
1265 unsigned BitWidth =
MI.getOperand(1).getImm();
1272 case SPIRV::OpTypeVector: {
1273 unsigned NumComponents =
MI.getOperand(2).getImm();
1274 if (NumComponents == 8 || NumComponents == 16)
1278 case SPIRV::OpTypePointer: {
1279 auto SC =
MI.getOperand(1).getImm();
1289 if (TypeDef->
getOpcode() == SPIRV::OpTypeFloat &&
1294 case SPIRV::OpExtInst: {
1295 if (
MI.getOperand(2).getImm() ==
1296 static_cast<int64_t
>(
1297 SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100)) {
1298 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_non_semantic_info);
1302 case SPIRV::OpAliasDomainDeclINTEL:
1303 case SPIRV::OpAliasScopeDeclINTEL:
1304 case SPIRV::OpAliasScopeListDeclINTEL: {
1305 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_memory_access_aliasing);
1306 Reqs.
addCapability(SPIRV::Capability::MemoryAccessAliasingINTEL);
1309 case SPIRV::OpBitReverse:
1310 case SPIRV::OpBitFieldInsert:
1311 case SPIRV::OpBitFieldSExtract:
1312 case SPIRV::OpBitFieldUExtract:
1313 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_bit_instructions)) {
1317 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_bit_instructions);
1320 case SPIRV::OpTypeRuntimeArray:
1323 case SPIRV::OpTypeOpaque:
1324 case SPIRV::OpTypeEvent:
1327 case SPIRV::OpTypePipe:
1328 case SPIRV::OpTypeReserveId:
1331 case SPIRV::OpTypeDeviceEvent:
1332 case SPIRV::OpTypeQueue:
1333 case SPIRV::OpBuildNDRange:
1336 case SPIRV::OpDecorate:
1337 case SPIRV::OpDecorateId:
1338 case SPIRV::OpDecorateString:
1339 addOpDecorateReqs(
MI, 1, Reqs, ST);
1341 case SPIRV::OpMemberDecorate:
1342 case SPIRV::OpMemberDecorateString:
1343 addOpDecorateReqs(
MI, 2, Reqs, ST);
1345 case SPIRV::OpInBoundsPtrAccessChain:
1348 case SPIRV::OpConstantSampler:
1351 case SPIRV::OpInBoundsAccessChain:
1352 case SPIRV::OpAccessChain:
1353 addOpAccessChainReqs(
MI, Reqs, ST);
1355 case SPIRV::OpTypeImage:
1356 addOpTypeImageReqs(
MI, Reqs, ST);
1358 case SPIRV::OpTypeSampler:
1359 if (!
ST.isShader()) {
1363 case SPIRV::OpTypeForwardPointer:
1367 case SPIRV::OpAtomicFlagTestAndSet:
1368 case SPIRV::OpAtomicLoad:
1369 case SPIRV::OpAtomicStore:
1370 case SPIRV::OpAtomicExchange:
1371 case SPIRV::OpAtomicCompareExchange:
1372 case SPIRV::OpAtomicIIncrement:
1373 case SPIRV::OpAtomicIDecrement:
1374 case SPIRV::OpAtomicIAdd:
1375 case SPIRV::OpAtomicISub:
1376 case SPIRV::OpAtomicUMin:
1377 case SPIRV::OpAtomicUMax:
1378 case SPIRV::OpAtomicSMin:
1379 case SPIRV::OpAtomicSMax:
1380 case SPIRV::OpAtomicAnd:
1381 case SPIRV::OpAtomicOr:
1382 case SPIRV::OpAtomicXor: {
1385 if (
MI.getOpcode() == SPIRV::OpAtomicStore) {
1387 InstrPtr =
MRI.getVRegDef(
MI.getOperand(3).getReg());
1388 assert(InstrPtr &&
"Unexpected type instruction for OpAtomicStore");
1393 if (TypeDef->
getOpcode() == SPIRV::OpTypeInt) {
1400 case SPIRV::OpGroupNonUniformIAdd:
1401 case SPIRV::OpGroupNonUniformFAdd:
1402 case SPIRV::OpGroupNonUniformIMul:
1403 case SPIRV::OpGroupNonUniformFMul:
1404 case SPIRV::OpGroupNonUniformSMin:
1405 case SPIRV::OpGroupNonUniformUMin:
1406 case SPIRV::OpGroupNonUniformFMin:
1407 case SPIRV::OpGroupNonUniformSMax:
1408 case SPIRV::OpGroupNonUniformUMax:
1409 case SPIRV::OpGroupNonUniformFMax:
1410 case SPIRV::OpGroupNonUniformBitwiseAnd:
1411 case SPIRV::OpGroupNonUniformBitwiseOr:
1412 case SPIRV::OpGroupNonUniformBitwiseXor:
1413 case SPIRV::OpGroupNonUniformLogicalAnd:
1414 case SPIRV::OpGroupNonUniformLogicalOr:
1415 case SPIRV::OpGroupNonUniformLogicalXor: {
1417 int64_t GroupOp =
MI.getOperand(3).getImm();
1419 case SPIRV::GroupOperation::Reduce:
1420 case SPIRV::GroupOperation::InclusiveScan:
1421 case SPIRV::GroupOperation::ExclusiveScan:
1422 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformArithmetic);
1424 case SPIRV::GroupOperation::ClusteredReduce:
1425 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformClustered);
1427 case SPIRV::GroupOperation::PartitionedReduceNV:
1428 case SPIRV::GroupOperation::PartitionedInclusiveScanNV:
1429 case SPIRV::GroupOperation::PartitionedExclusiveScanNV:
1430 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformPartitionedNV);
1435 case SPIRV::OpGroupNonUniformShuffle:
1436 case SPIRV::OpGroupNonUniformShuffleXor:
1437 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformShuffle);
1439 case SPIRV::OpGroupNonUniformShuffleUp:
1440 case SPIRV::OpGroupNonUniformShuffleDown:
1441 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformShuffleRelative);
1443 case SPIRV::OpGroupAll:
1444 case SPIRV::OpGroupAny:
1445 case SPIRV::OpGroupBroadcast:
1446 case SPIRV::OpGroupIAdd:
1447 case SPIRV::OpGroupFAdd:
1448 case SPIRV::OpGroupFMin:
1449 case SPIRV::OpGroupUMin:
1450 case SPIRV::OpGroupSMin:
1451 case SPIRV::OpGroupFMax:
1452 case SPIRV::OpGroupUMax:
1453 case SPIRV::OpGroupSMax:
1456 case SPIRV::OpGroupNonUniformElect:
1459 case SPIRV::OpGroupNonUniformAll:
1460 case SPIRV::OpGroupNonUniformAny:
1461 case SPIRV::OpGroupNonUniformAllEqual:
1464 case SPIRV::OpGroupNonUniformBroadcast:
1465 case SPIRV::OpGroupNonUniformBroadcastFirst:
1466 case SPIRV::OpGroupNonUniformBallot:
1467 case SPIRV::OpGroupNonUniformInverseBallot:
1468 case SPIRV::OpGroupNonUniformBallotBitExtract:
1469 case SPIRV::OpGroupNonUniformBallotBitCount:
1470 case SPIRV::OpGroupNonUniformBallotFindLSB:
1471 case SPIRV::OpGroupNonUniformBallotFindMSB:
1472 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformBallot);
1474 case SPIRV::OpSubgroupShuffleINTEL:
1475 case SPIRV::OpSubgroupShuffleDownINTEL:
1476 case SPIRV::OpSubgroupShuffleUpINTEL:
1477 case SPIRV::OpSubgroupShuffleXorINTEL:
1478 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {
1479 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_subgroups);
1480 Reqs.
addCapability(SPIRV::Capability::SubgroupShuffleINTEL);
1483 case SPIRV::OpSubgroupBlockReadINTEL:
1484 case SPIRV::OpSubgroupBlockWriteINTEL:
1485 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {
1486 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_subgroups);
1487 Reqs.
addCapability(SPIRV::Capability::SubgroupBufferBlockIOINTEL);
1490 case SPIRV::OpSubgroupImageBlockReadINTEL:
1491 case SPIRV::OpSubgroupImageBlockWriteINTEL:
1492 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {
1493 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_subgroups);
1494 Reqs.
addCapability(SPIRV::Capability::SubgroupImageBlockIOINTEL);
1497 case SPIRV::OpSubgroupImageMediaBlockReadINTEL:
1498 case SPIRV::OpSubgroupImageMediaBlockWriteINTEL:
1499 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_media_block_io)) {
1500 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_media_block_io);
1501 Reqs.
addCapability(SPIRV::Capability::SubgroupImageMediaBlockIOINTEL);
1504 case SPIRV::OpAssumeTrueKHR:
1505 case SPIRV::OpExpectKHR:
1506 if (
ST.canUseExtension(SPIRV::Extension::SPV_KHR_expect_assume)) {
1507 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_expect_assume);
1511 case SPIRV::OpPtrCastToCrossWorkgroupINTEL:
1512 case SPIRV::OpCrossWorkgroupCastToPtrINTEL:
1513 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_usm_storage_classes)) {
1514 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_usm_storage_classes);
1515 Reqs.
addCapability(SPIRV::Capability::USMStorageClassesINTEL);
1518 case SPIRV::OpConstantFunctionPointerINTEL:
1519 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_function_pointers)) {
1520 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_function_pointers);
1521 Reqs.
addCapability(SPIRV::Capability::FunctionPointersINTEL);
1524 case SPIRV::OpGroupNonUniformRotateKHR:
1525 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_subgroup_rotate))
1527 "following SPIR-V extension: SPV_KHR_subgroup_rotate",
1529 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_subgroup_rotate);
1530 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformRotateKHR);
1533 case SPIRV::OpGroupIMulKHR:
1534 case SPIRV::OpGroupFMulKHR:
1535 case SPIRV::OpGroupBitwiseAndKHR:
1536 case SPIRV::OpGroupBitwiseOrKHR:
1537 case SPIRV::OpGroupBitwiseXorKHR:
1538 case SPIRV::OpGroupLogicalAndKHR:
1539 case SPIRV::OpGroupLogicalOrKHR:
1540 case SPIRV::OpGroupLogicalXorKHR:
1541 if (
ST.canUseExtension(
1542 SPIRV::Extension::SPV_KHR_uniform_group_instructions)) {
1543 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_uniform_group_instructions);
1544 Reqs.
addCapability(SPIRV::Capability::GroupUniformArithmeticKHR);
1547 case SPIRV::OpReadClockKHR:
1548 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_shader_clock))
1550 "following SPIR-V extension: SPV_KHR_shader_clock",
1552 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_shader_clock);
1555 case SPIRV::OpFunctionPointerCallINTEL:
1556 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_function_pointers)) {
1557 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_function_pointers);
1558 Reqs.
addCapability(SPIRV::Capability::FunctionPointersINTEL);
1561 case SPIRV::OpAtomicFAddEXT:
1562 case SPIRV::OpAtomicFMinEXT:
1563 case SPIRV::OpAtomicFMaxEXT:
1564 AddAtomicFloatRequirements(
MI, Reqs, ST);
1566 case SPIRV::OpConvertBF16ToFINTEL:
1567 case SPIRV::OpConvertFToBF16INTEL:
1568 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bfloat16_conversion)) {
1569 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bfloat16_conversion);
1570 Reqs.
addCapability(SPIRV::Capability::BFloat16ConversionINTEL);
1573 case SPIRV::OpRoundFToTF32INTEL:
1574 if (
ST.canUseExtension(
1575 SPIRV::Extension::SPV_INTEL_tensor_float32_conversion)) {
1576 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_tensor_float32_conversion);
1577 Reqs.
addCapability(SPIRV::Capability::TensorFloat32RoundingINTEL);
1580 case SPIRV::OpVariableLengthArrayINTEL:
1581 case SPIRV::OpSaveMemoryINTEL:
1582 case SPIRV::OpRestoreMemoryINTEL:
1583 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_variable_length_array)) {
1584 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_variable_length_array);
1585 Reqs.
addCapability(SPIRV::Capability::VariableLengthArrayINTEL);
1588 case SPIRV::OpAsmTargetINTEL:
1589 case SPIRV::OpAsmINTEL:
1590 case SPIRV::OpAsmCallINTEL:
1591 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_inline_assembly)) {
1592 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_inline_assembly);
1596 case SPIRV::OpTypeCooperativeMatrixKHR:
1597 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix))
1599 "OpTypeCooperativeMatrixKHR type requires the "
1600 "following SPIR-V extension: SPV_KHR_cooperative_matrix",
1602 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix);
1603 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixKHR);
1605 case SPIRV::OpArithmeticFenceEXT:
1606 if (!
ST.canUseExtension(SPIRV::Extension::SPV_EXT_arithmetic_fence))
1608 "following SPIR-V extension: SPV_EXT_arithmetic_fence",
1610 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_arithmetic_fence);
1613 case SPIRV::OpControlBarrierArriveINTEL:
1614 case SPIRV::OpControlBarrierWaitINTEL:
1615 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_split_barrier)) {
1616 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_split_barrier);
1620 case SPIRV::OpCooperativeMatrixMulAddKHR: {
1621 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix))
1623 "following SPIR-V extension: "
1624 "SPV_KHR_cooperative_matrix",
1626 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix);
1627 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixKHR);
1628 constexpr unsigned MulAddMaxSize = 6;
1629 if (
MI.getNumOperands() != MulAddMaxSize)
1631 const int64_t CoopOperands =
MI.getOperand(MulAddMaxSize - 1).getImm();
1633 SPIRV::CooperativeMatrixOperands::MatrixAAndBTF32ComponentsINTEL) {
1634 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
1636 "require the following SPIR-V extension: "
1637 "SPV_INTEL_joint_matrix",
1639 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
1641 SPIRV::Capability::CooperativeMatrixTF32ComponentTypeINTEL);
1643 if (CoopOperands & SPIRV::CooperativeMatrixOperands::
1644 MatrixAAndBBFloat16ComponentsINTEL ||
1646 SPIRV::CooperativeMatrixOperands::MatrixCBFloat16ComponentsINTEL ||
1647 CoopOperands & SPIRV::CooperativeMatrixOperands::
1648 MatrixResultBFloat16ComponentsINTEL) {
1649 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
1651 "require the following SPIR-V extension: "
1652 "SPV_INTEL_joint_matrix",
1654 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
1656 SPIRV::Capability::CooperativeMatrixBFloat16ComponentTypeINTEL);
1660 case SPIRV::OpCooperativeMatrixLoadKHR:
1661 case SPIRV::OpCooperativeMatrixStoreKHR:
1662 case SPIRV::OpCooperativeMatrixLoadCheckedINTEL:
1663 case SPIRV::OpCooperativeMatrixStoreCheckedINTEL:
1664 case SPIRV::OpCooperativeMatrixPrefetchINTEL: {
1665 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix))
1667 "following SPIR-V extension: "
1668 "SPV_KHR_cooperative_matrix",
1670 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix);
1671 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixKHR);
1675 std::unordered_map<unsigned, unsigned> LayoutToInstMap = {
1676 {SPIRV::OpCooperativeMatrixLoadKHR, 3},
1677 {SPIRV::OpCooperativeMatrixStoreKHR, 2},
1678 {SPIRV::OpCooperativeMatrixLoadCheckedINTEL, 5},
1679 {SPIRV::OpCooperativeMatrixStoreCheckedINTEL, 4},
1680 {SPIRV::OpCooperativeMatrixPrefetchINTEL, 4}};
1682 const auto OpCode =
MI.getOpcode();
1683 const unsigned LayoutNum = LayoutToInstMap[
OpCode];
1684 Register RegLayout =
MI.getOperand(LayoutNum).getReg();
1687 if (MILayout->
getOpcode() == SPIRV::OpConstantI) {
1690 static_cast<unsigned>(SPIRV::CooperativeMatrixLayout::PackedINTEL)) {
1691 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
1693 "extension: SPV_INTEL_joint_matrix",
1695 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
1696 Reqs.
addCapability(SPIRV::Capability::PackedCooperativeMatrixINTEL);
1701 if (OpCode == SPIRV::OpCooperativeMatrixLoadKHR ||
1702 OpCode == SPIRV::OpCooperativeMatrixStoreKHR)
1705 std::string InstName;
1707 case SPIRV::OpCooperativeMatrixPrefetchINTEL:
1708 InstName =
"OpCooperativeMatrixPrefetchINTEL";
1710 case SPIRV::OpCooperativeMatrixLoadCheckedINTEL:
1711 InstName =
"OpCooperativeMatrixLoadCheckedINTEL";
1713 case SPIRV::OpCooperativeMatrixStoreCheckedINTEL:
1714 InstName =
"OpCooperativeMatrixStoreCheckedINTEL";
1718 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix)) {
1719 const std::string ErrorMsg =
1720 InstName +
" instruction requires the "
1721 "following SPIR-V extension: SPV_INTEL_joint_matrix";
1724 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
1725 if (OpCode == SPIRV::OpCooperativeMatrixPrefetchINTEL) {
1726 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixPrefetchINTEL);
1730 SPIRV::Capability::CooperativeMatrixCheckedInstructionsINTEL);
1733 case SPIRV::OpCooperativeMatrixConstructCheckedINTEL:
1734 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
1736 "instructions require the following SPIR-V extension: "
1737 "SPV_INTEL_joint_matrix",
1739 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
1741 SPIRV::Capability::CooperativeMatrixCheckedInstructionsINTEL);
1743 case SPIRV::OpCooperativeMatrixGetElementCoordINTEL:
1744 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
1746 "following SPIR-V extension: SPV_INTEL_joint_matrix",
1748 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
1750 SPIRV::Capability::CooperativeMatrixInvocationInstructionsINTEL);
1752 case SPIRV::OpConvertHandleToImageINTEL:
1753 case SPIRV::OpConvertHandleToSamplerINTEL:
1754 case SPIRV::OpConvertHandleToSampledImageINTEL:
1755 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bindless_images))
1757 "instructions require the following SPIR-V extension: "
1758 "SPV_INTEL_bindless_images",
1760 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bindless_images);
1763 case SPIRV::OpSubgroup2DBlockLoadINTEL:
1764 case SPIRV::OpSubgroup2DBlockLoadTransposeINTEL:
1765 case SPIRV::OpSubgroup2DBlockLoadTransformINTEL:
1766 case SPIRV::OpSubgroup2DBlockPrefetchINTEL:
1767 case SPIRV::OpSubgroup2DBlockStoreINTEL: {
1768 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_2d_block_io))
1770 "Prefetch/Store]INTEL instructions require the "
1771 "following SPIR-V extension: SPV_INTEL_2d_block_io",
1773 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_2d_block_io);
1774 Reqs.
addCapability(SPIRV::Capability::Subgroup2DBlockIOINTEL);
1776 const auto OpCode =
MI.getOpcode();
1777 if (OpCode == SPIRV::OpSubgroup2DBlockLoadTransposeINTEL) {
1778 Reqs.
addCapability(SPIRV::Capability::Subgroup2DBlockTransposeINTEL);
1781 if (OpCode == SPIRV::OpSubgroup2DBlockLoadTransformINTEL) {
1782 Reqs.
addCapability(SPIRV::Capability::Subgroup2DBlockTransformINTEL);
1787 case SPIRV::OpKill: {
1790 case SPIRV::OpDemoteToHelperInvocation:
1791 Reqs.
addCapability(SPIRV::Capability::DemoteToHelperInvocation);
1793 if (
ST.canUseExtension(
1794 SPIRV::Extension::SPV_EXT_demote_to_helper_invocation)) {
1797 SPIRV::Extension::SPV_EXT_demote_to_helper_invocation);
1802 case SPIRV::OpSUDot:
1803 case SPIRV::OpSDotAccSat:
1804 case SPIRV::OpUDotAccSat:
1805 case SPIRV::OpSUDotAccSat:
1806 AddDotProductRequirements(
MI, Reqs, ST);
1808 case SPIRV::OpImageRead: {
1809 Register ImageReg =
MI.getOperand(2).getReg();
1810 SPIRVType *TypeDef =
ST.getSPIRVGlobalRegistry()->getResultType(
1818 if (isImageTypeWithUnknownFormat(TypeDef) &&
ST.isShader())
1819 Reqs.
addCapability(SPIRV::Capability::StorageImageReadWithoutFormat);
1822 case SPIRV::OpImageWrite: {
1823 Register ImageReg =
MI.getOperand(0).getReg();
1824 SPIRVType *TypeDef =
ST.getSPIRVGlobalRegistry()->getResultType(
1832 if (isImageTypeWithUnknownFormat(TypeDef) &&
ST.isShader())
1833 Reqs.
addCapability(SPIRV::Capability::StorageImageWriteWithoutFormat);
1836 case SPIRV::OpTypeStructContinuedINTEL:
1837 case SPIRV::OpConstantCompositeContinuedINTEL:
1838 case SPIRV::OpSpecConstantCompositeContinuedINTEL:
1839 case SPIRV::OpCompositeConstructContinuedINTEL: {
1840 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_long_composites))
1842 "Continued instructions require the "
1843 "following SPIR-V extension: SPV_INTEL_long_composites",
1845 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_long_composites);
1849 case SPIRV::OpSubgroupMatrixMultiplyAccumulateINTEL: {
1850 if (!
ST.canUseExtension(
1851 SPIRV::Extension::SPV_INTEL_subgroup_matrix_multiply_accumulate))
1853 "OpSubgroupMatrixMultiplyAccumulateINTEL instruction requires the "
1855 "extension: SPV_INTEL_subgroup_matrix_multiply_accumulate",
1858 SPIRV::Extension::SPV_INTEL_subgroup_matrix_multiply_accumulate);
1860 SPIRV::Capability::SubgroupMatrixMultiplyAccumulateINTEL);
1863 case SPIRV::OpBitwiseFunctionINTEL: {
1864 if (!
ST.canUseExtension(
1865 SPIRV::Extension::SPV_INTEL_ternary_bitwise_function))
1867 "OpBitwiseFunctionINTEL instruction requires the following SPIR-V "
1868 "extension: SPV_INTEL_ternary_bitwise_function",
1870 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_ternary_bitwise_function);
1871 Reqs.
addCapability(SPIRV::Capability::TernaryBitwiseFunctionINTEL);
1874 case SPIRV::OpCopyMemorySized: {
1888 SPIRV::Capability::Shader);
1894 for (
auto F =
M.begin(), E =
M.end();
F != E; ++
F) {
1900 addInstrRequirements(
MI, MAI.
Reqs, ST);
1903 auto Node =
M.getNamedMetadata(
"spirv.ExecutionMode");
1905 bool RequireFloatControls =
false, RequireFloatControls2 =
false,
1907 bool HasFloatControls2 =
1908 ST.canUseExtension(SPIRV::Extension::SPV_INTEL_float_controls2);
1909 for (
unsigned i = 0; i <
Node->getNumOperands(); i++) {
1910 MDNode *MDN = cast<MDNode>(
Node->getOperand(i));
1912 if (
auto *CMeta = dyn_cast<ConstantAsMetadata>(MDOp)) {
1915 auto EM =
Const->getZExtValue();
1919 case SPIRV::ExecutionMode::DenormPreserve:
1920 case SPIRV::ExecutionMode::DenormFlushToZero:
1921 case SPIRV::ExecutionMode::SignedZeroInfNanPreserve:
1922 case SPIRV::ExecutionMode::RoundingModeRTE:
1923 case SPIRV::ExecutionMode::RoundingModeRTZ:
1924 RequireFloatControls = VerLower14;
1926 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
1928 case SPIRV::ExecutionMode::RoundingModeRTPINTEL:
1929 case SPIRV::ExecutionMode::RoundingModeRTNINTEL:
1930 case SPIRV::ExecutionMode::FloatingPointModeALTINTEL:
1931 case SPIRV::ExecutionMode::FloatingPointModeIEEEINTEL:
1932 if (HasFloatControls2) {
1933 RequireFloatControls2 =
true;
1935 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
1940 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
1945 if (RequireFloatControls &&
1946 ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls))
1948 if (RequireFloatControls2)
1951 for (
auto FI =
M.begin(), E =
M.end(); FI != E; ++FI) {
1953 if (
F.isDeclaration())
1955 if (
F.getMetadata(
"reqd_work_group_size"))
1957 SPIRV::OperandCategory::ExecutionModeOperand,
1958 SPIRV::ExecutionMode::LocalSize, ST);
1959 if (
F.getFnAttribute(
"hlsl.numthreads").isValid()) {
1961 SPIRV::OperandCategory::ExecutionModeOperand,
1962 SPIRV::ExecutionMode::LocalSize, ST);
1964 if (
F.getMetadata(
"work_group_size_hint"))
1966 SPIRV::OperandCategory::ExecutionModeOperand,
1967 SPIRV::ExecutionMode::LocalSizeHint, ST);
1968 if (
F.getMetadata(
"intel_reqd_sub_group_size"))
1970 SPIRV::OperandCategory::ExecutionModeOperand,
1971 SPIRV::ExecutionMode::SubgroupSize, ST);
1972 if (
F.getMetadata(
"vec_type_hint"))
1974 SPIRV::OperandCategory::ExecutionModeOperand,
1975 SPIRV::ExecutionMode::VecTypeHint, ST);
1977 if (
F.hasOptNone()) {
1978 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_optnone)) {
1981 }
else if (
ST.canUseExtension(SPIRV::Extension::SPV_EXT_optnone)) {
1990 unsigned Flags = SPIRV::FPFastMathMode::None;
1992 Flags |= SPIRV::FPFastMathMode::NotNaN;
1994 Flags |= SPIRV::FPFastMathMode::NotInf;
1996 Flags |= SPIRV::FPFastMathMode::NSZ;
1998 Flags |= SPIRV::FPFastMathMode::AllowRecip;
2000 Flags |= SPIRV::FPFastMathMode::Fast;
2004static bool isFastMathMathModeAvailable(
const SPIRVSubtarget &ST) {
2009 return ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2);
2016 getSymbolicOperandRequirements(SPIRV::OperandCategory::DecorationOperand,
2017 SPIRV::Decoration::NoSignedWrap, ST, Reqs)
2020 SPIRV::Decoration::NoSignedWrap, {});
2023 getSymbolicOperandRequirements(SPIRV::OperandCategory::DecorationOperand,
2024 SPIRV::Decoration::NoUnsignedWrap, ST,
2028 SPIRV::Decoration::NoUnsignedWrap, {});
2030 if (!
TII.canUseFastMathFlags(
I))
2032 unsigned FMFlags = getFastMathFlags(
I);
2033 if (FMFlags == SPIRV::FPFastMathMode::None)
2036 if (isFastMathMathModeAvailable(ST)) {
2037 Register DstReg =
I.getOperand(0).getReg();
2047 for (
auto F =
M.begin(), E =
M.end();
F != E; ++
F) {
2051 for (
auto &
MBB : *MF)
2052 for (
auto &
MI :
MBB)
2053 handleMIFlagDecoration(
MI, ST,
TII, MAI.
Reqs);
2060 for (
auto F =
M.begin(), E =
M.end();
F != E; ++
F) {
2065 for (
auto &
MBB : *MF) {
2070 MRI.setRegClass(Reg, &SPIRV::IDRegClass);
2081 for (
auto F =
M.begin(), E =
M.end();
F != E; ++
F) {
2085 for (
auto &
MBB : *MF) {
2087 MI.setDesc(
TII.get(SPIRV::OpPhi));
2090 MI.insert(
MI.operands_begin() + 1,
2091 {MachineOperand::CreateReg(ResTypeReg, false)});
2095 MF->getProperties().setNoPHIs();
2109 ST = TM.getSubtargetImpl();
2110 GR = ST->getSPIRVGlobalRegistry();
2111 TII = ST->getInstrInfo();
2113 MMI = &getAnalysis<MachineModuleInfoWrapperPass>().getMMI();
2117 patchPhis(M, GR, *
TII, MMI);
2119 addMBBNames(M, *
TII, MMI, *ST, MAI);
2120 addDecorations(M, *
TII, MMI, *ST, MAI);
2122 collectReqs(M, MAI, MMI, *ST);
2126 collectReqs(M, MAI, MMI, *ST);
2127 collectDeclarations(M);
2130 numberRegistersGlobally(M);
2133 processOtherInstrs(M);
unsigned const MachineRegisterInfo * MRI
MachineInstrBuilder & UseMI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
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)
#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.
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
Wrapper class representing physical registers. Should be passed by value.
constexpr bool isValid() const
const MDOperand & getOperand(unsigned I) const
unsigned getNumOperands() const
Return number of MDNode operands.
Tracking metadata reference owned by Metadata.
iterator_range< iterator > phis()
Returns a range that iterates over the phis in the basic block.
LLVM_ABI 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.
LLVM_ABI 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
LLVM_ABI const MachineFunction * getMF() const
Return the function that contains the basic block that this instruction belongs to.
const MachineOperand & getOperand(unsigned i) const
This class contains meta information specific to a module.
LLVM_ABI MachineFunction * getMachineFunction(const Function &F) const
Returns the MachineFunction associated to IR function F if there is one, otherwise nullptr.
MachineOperand class - Representation of each machine instruction operand.
unsigned getSubReg() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
LLVM_ABI void print(raw_ostream &os, const TargetRegisterInfo *TRI=nullptr) const
Print the MachineOperand to os.
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
A Module instance is used to store all the information related to an LLVM module.
virtual void print(raw_ostream &OS, const Module *M) const
print - Print out the internal state of the pass.
Wrapper class representing virtual and physical registers.
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...
void insert_range(Range &&R)
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.
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
iterator insert(iterator I, T &&Elt)
void push_back(const T &Elt)
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.
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 buildOpDecorate(Register Reg, MachineIRBuilder &MIRBuilder, SPIRV::Decoration::Decoration Dec, const std::vector< uint32_t > &DecArgs, StringRef StrImm)
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
CapabilityList getCapabilitiesEnabledByExtension(SPIRV::Extension::Extension Extension)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
std::set< InstrSignature > InstrTraces
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
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...
SmallVector< const MachineInstr *, 4 > GlobalVarList
DenseMap< unsigned, MCRegister > ExtInstSetMap
void setSkipEmission(const MachineInstr *MI)
DenseSet< const MachineInstr * > InstrsToDelete
bool hasRegisterAlias(const MachineFunction *MF, Register Reg)
RegisterAliasMapTy RegisterAliasTable
DenseMap< const Function *, MCRegister > FuncMap
MCRegister getRegisterAlias(const MachineFunction *MF, Register Reg)
bool getSkipEmission(const MachineInstr *MI)
MemoryModel::MemoryModel Mem
MCRegister getOrCreateMBBRegister(const MachineBasicBlock &MBB)
InstrList MS[NUM_MODULE_SECTIONS]
AddressingModel::AddressingModel Addr
void setRegisterAlias(const MachineFunction *MF, Register Reg, MCRegister AliasReg)
SourceLanguage::SourceLanguage SrcLang
MCRegister getNextIDRegister()
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