30#define DEBUG_TYPE "spirv-module-analysis"
34 cl::desc(
"Dump MIR with SPIR-V dependencies info"),
39 cl::desc(
"SPIR-V capabilities to avoid if there are "
40 "other options enabling a feature"),
43 "SPIR-V Shader capability")));
65 if (MdNode && OpIndex < MdNode->getNumOperands()) {
66 const auto &
Op = MdNode->getOperand(
OpIndex);
67 return mdconst::extract<ConstantInt>(
Op)->getZExtValue();
73getSymbolicOperandRequirements(SPIRV::OperandCategory::OperandCategory Category,
82 bool MinVerOK = SPIRVVersion.
empty() || SPIRVVersion >= ReqMinVer;
84 ReqMaxVer.
empty() || SPIRVVersion.
empty() || SPIRVVersion <= ReqMaxVer;
87 if (ReqCaps.
empty()) {
88 if (ReqExts.
empty()) {
89 if (MinVerOK && MaxVerOK)
90 return {
true, {}, {}, ReqMinVer, ReqMaxVer};
93 }
else if (MinVerOK && MaxVerOK) {
94 if (ReqCaps.
size() == 1) {
95 auto Cap = ReqCaps[0];
97 return {
true, {Cap}, ReqExts, ReqMinVer, ReqMaxVer};
106 for (
auto Cap : ReqCaps)
109 for (
size_t i = 0, Sz = UseCaps.
size(); i < Sz; ++i) {
110 auto Cap = UseCaps[i];
111 if (i == Sz - 1 || !AvoidCaps.
S.
contains(Cap))
112 return {
true, {Cap}, ReqExts, ReqMinVer, ReqMaxVer};
119 if (
llvm::all_of(ReqExts, [&ST](
const SPIRV::Extension::Extension &Ext) {
120 return ST.canUseExtension(Ext);
131void SPIRVModuleAnalysis::setBaseInfo(
const Module &M) {
144 if (
auto MemModel =
M.getNamedMetadata(
"spirv.MemoryModel")) {
145 auto MemMD = MemModel->getOperand(0);
146 MAI.
Addr =
static_cast<SPIRV::AddressingModel::AddressingModel
>(
147 getMetadataUInt(MemMD, 0));
149 static_cast<SPIRV::MemoryModel::MemoryModel
>(getMetadataUInt(MemMD, 1));
152 MAI.
Mem =
ST->isOpenCLEnv() ? SPIRV::MemoryModel::OpenCL
153 : SPIRV::MemoryModel::GLSL450;
154 if (
MAI.
Mem == SPIRV::MemoryModel::OpenCL) {
155 unsigned PtrSize =
ST->getPointerSize();
156 MAI.
Addr = PtrSize == 32 ? SPIRV::AddressingModel::Physical32
157 : PtrSize == 64 ? SPIRV::AddressingModel::Physical64
158 : SPIRV::AddressingModel::Logical;
161 MAI.
Addr = SPIRV::AddressingModel::Logical;
166 if (
auto VerNode =
M.getNamedMetadata(
"opencl.ocl.version")) {
167 MAI.
SrcLang = SPIRV::SourceLanguage::OpenCL_C;
170 assert(VerNode->getNumOperands() > 0 &&
"Invalid SPIR");
171 auto VersionMD = VerNode->getOperand(0);
172 unsigned MajorNum = getMetadataUInt(VersionMD, 0, 2);
173 unsigned MinorNum = getMetadataUInt(VersionMD, 1);
174 unsigned RevNum = getMetadataUInt(VersionMD, 2);
177 (std::max(1U, MajorNum) * 100 + MinorNum) * 1000 + RevNum;
183 if (
ST->isOpenCLEnv()) {
184 MAI.
SrcLang = SPIRV::SourceLanguage::OpenCL_CPP;
192 if (
auto ExtNode =
M.getNamedMetadata(
"opencl.used.extensions")) {
193 for (
unsigned I = 0, E = ExtNode->getNumOperands();
I != E; ++
I) {
211 if (
ST->isOpenCLEnv()) {
214 SPIRV::InstructionSet::OpenCL_std)] =
223 bool DoInsert =
true) {
226 assert(
MI &&
"There should be an instruction that defines the register");
232void SPIRVModuleAnalysis::collectGlobalEntities(
233 const std::vector<SPIRV::DTSortableEntry *> &DepsGraph,
236 bool UsePreOrder =
false) {
238 for (
const auto *E : DepsGraph) {
242 RecHoistUtil = [MSType, UsePreOrder, &Visited, &Pred,
244 if (Visited.count(E) || !Pred(E))
253 for (
auto *S : E->getDeps())
264 collectDefInstr(Reg, MF, &
MAI, MSType, IsFirst);
271 for (
auto *S : E->getDeps())
282void SPIRVModuleAnalysis::processDefInstrs(
const Module &M) {
283 std::vector<SPIRV::DTSortableEntry *> DepsGraph;
287 collectGlobalEntities(
291 for (
auto F =
M.begin(), E =
M.end();
F != E; ++
F) {
298 if (
MI.getOpcode() == SPIRV::OpExtension) {
300 auto Ext = SPIRV::Extension::Extension(
MI.getOperand(0).getImm());
303 }
else if (
MI.getOpcode() == SPIRV::OpCapability) {
304 auto Cap = SPIRV::Capability::Capability(
MI.getOperand(0).getImm());
312 collectGlobalEntities(
323 if (
MI.getOpcode() == SPIRV::OpDecorate) {
325 auto Dec =
MI.getOperand(1).getImm();
326 if (Dec ==
static_cast<unsigned>(SPIRV::Decoration::LinkageAttributes)) {
327 auto Lnk =
MI.getOperand(
MI.getNumOperands() - 1).getImm();
328 if (Lnk ==
static_cast<unsigned>(SPIRV::LinkageType::Import)) {
336 }
else if (
MI.getOpcode() == SPIRV::OpFunction) {
349void SPIRVModuleAnalysis::collectFuncPtrs() {
351 if (
MI->getOpcode() == SPIRV::OpConstantFunctionPointerINTEL)
360 "Constant function pointer must refer to function definition");
361 Register FunDefReg = FunDef->getReg();
365 "Function definition must refer to a global register");
380 InstrSignature Signature;
381 for (
unsigned i = 0; i <
MI.getNumOperands(); ++i) {
392 Signature.push_back(h);
402 bool Append =
true) {
405 auto FoundMI = IS.insert(MISign);
417void SPIRVModuleAnalysis::processOtherInstrs(
const Module &M) {
419 for (
auto F =
M.begin(), E =
M.end();
F != E; ++
F) {
420 if ((*F).isDeclaration())
429 const unsigned OpCode =
MI.getOpcode();
430 if (OpCode == SPIRV::OpString) {
432 }
else if (OpCode == SPIRV::OpExtInst &&
MI.getOperand(2).isImm() &&
433 MI.getOperand(2).getImm() ==
434 SPIRV::InstructionSet::
435 NonSemantic_Shader_DebugInfo_100) {
437 namespace NS = SPIRV::NonSemanticExtInst;
438 static constexpr int64_t GlobalNonSemanticDITy[] = {
439 NS::DebugSource, NS::DebugCompilationUnit, NS::DebugInfoNone,
440 NS::DebugTypeBasic, NS::DebugTypePointer};
441 bool IsGlobalDI =
false;
442 for (
unsigned Idx = 0;
Idx < std::size(GlobalNonSemanticDITy); ++
Idx)
443 IsGlobalDI |=
Ins.getImm() == GlobalNonSemanticDITy[
Idx];
446 }
else if (OpCode == SPIRV::OpName || OpCode == SPIRV::OpMemberName) {
448 }
else if (OpCode == SPIRV::OpEntryPoint) {
450 }
else if (
TII->isDecorationInstr(
MI)) {
452 collectFuncNames(
MI, &*
F);
453 }
else if (
TII->isConstantInstr(
MI)) {
457 }
else if (OpCode == SPIRV::OpFunction) {
458 collectFuncNames(
MI, &*
F);
459 }
else if (OpCode == SPIRV::OpTypeForwardPointer) {
469void SPIRVModuleAnalysis::numberRegistersGlobally(
const Module &M) {
470 for (
auto F =
M.begin(),
E =
M.end();
F !=
E; ++
F) {
471 if ((*F).isDeclaration())
486 if (
MI.getOpcode() != SPIRV::OpExtInst)
488 auto Set =
MI.getOperand(2).getImm();
498 SPIRV::OperandCategory::OperandCategory Category,
uint32_t i,
500 addRequirements(getSymbolicOperandRequirements(Category, i, ST, *
this));
503void SPIRV::RequirementHandler::recursiveAddCapabilities(
505 for (
const auto &Cap : ToPrune) {
509 recursiveAddCapabilities(ImplicitDecls);
514 for (
const auto &Cap : ToAdd) {
515 bool IsNewlyInserted = AllCaps.insert(Cap).second;
516 if (!IsNewlyInserted)
520 recursiveAddCapabilities(ImplicitDecls);
521 MinimalCaps.push_back(Cap);
530 if (Req.
Cap.has_value())
531 addCapabilities({Req.
Cap.value()});
533 addExtensions(Req.
Exts);
536 if (!MaxVersion.empty() && Req.
MinVer > MaxVersion) {
538 <<
" and <= " << MaxVersion <<
"\n");
542 if (MinVersion.empty() || Req.
MinVer > MinVersion)
547 if (!MinVersion.empty() && Req.
MaxVer < MinVersion) {
549 <<
" and >= " << MinVersion <<
"\n");
553 if (MaxVersion.empty() || Req.
MaxVer < MaxVersion)
561 bool IsSatisfiable =
true;
562 auto TargetVer = ST.getSPIRVVersion();
564 if (!MaxVersion.empty() && !TargetVer.empty() && MaxVersion < TargetVer) {
566 dbgs() <<
"Target SPIR-V version too high for required features\n"
567 <<
"Required max version: " << MaxVersion <<
" target version "
568 << TargetVer <<
"\n");
569 IsSatisfiable =
false;
572 if (!MinVersion.empty() && !TargetVer.empty() && MinVersion > TargetVer) {
573 LLVM_DEBUG(
dbgs() <<
"Target SPIR-V version too low for required features\n"
574 <<
"Required min version: " << MinVersion
575 <<
" target version " << TargetVer <<
"\n");
576 IsSatisfiable =
false;
579 if (!MinVersion.empty() && !MaxVersion.empty() && MinVersion > MaxVersion) {
582 <<
"Version is too low for some features and too high for others.\n"
583 <<
"Required SPIR-V min version: " << MinVersion
584 <<
" required SPIR-V max version " << MaxVersion <<
"\n");
585 IsSatisfiable =
false;
588 for (
auto Cap : MinimalCaps) {
589 if (AvailableCaps.contains(Cap))
593 OperandCategory::CapabilityOperand, Cap)
595 IsSatisfiable =
false;
598 for (
auto Ext : AllExtensions) {
599 if (ST.canUseExtension(Ext))
603 OperandCategory::ExtensionOperand, Ext)
605 IsSatisfiable =
false;
614 for (
const auto Cap : ToAdd)
615 if (AvailableCaps.insert(Cap).second)
617 SPIRV::OperandCategory::CapabilityOperand, Cap));
621 const Capability::Capability
ToRemove,
622 const Capability::Capability IfPresent) {
623 if (AllCaps.contains(IfPresent))
631 addAvailableCaps({Capability::Shader, Capability::Linkage, Capability::Int8,
635 addAvailableCaps({Capability::GroupNonUniform,
636 Capability::GroupNonUniformVote,
637 Capability::GroupNonUniformArithmetic,
638 Capability::GroupNonUniformBallot,
639 Capability::GroupNonUniformClustered,
640 Capability::GroupNonUniformShuffle,
641 Capability::GroupNonUniformShuffleRelative});
644 addAvailableCaps({Capability::DotProduct, Capability::DotProductInputAll,
645 Capability::DotProductInput4x8Bit,
646 Capability::DotProductInput4x8BitPacked,
647 Capability::DemoteToHelperInvocation});
650 for (
auto Extension : ST.getAllAvailableExtensions()) {
653 addAvailableCaps(EnabledCapabilities);
656 if (ST.isOpenCLEnv()) {
657 initAvailableCapabilitiesForOpenCL(ST);
661 if (ST.isVulkanEnv()) {
662 initAvailableCapabilitiesForVulkan(ST);
669void RequirementHandler::initAvailableCapabilitiesForOpenCL(
672 addAvailableCaps({Capability::Addresses, Capability::Float16Buffer,
673 Capability::Kernel, Capability::Vector16,
674 Capability::Groups, Capability::GenericPointer,
675 Capability::StorageImageWriteWithoutFormat,
676 Capability::StorageImageReadWithoutFormat});
677 if (ST.hasOpenCLFullProfile())
678 addAvailableCaps({Capability::Int64, Capability::Int64Atomics});
679 if (ST.hasOpenCLImageSupport()) {
680 addAvailableCaps({Capability::ImageBasic, Capability::LiteralSampler,
681 Capability::Image1D, Capability::SampledBuffer,
682 Capability::ImageBuffer});
684 addAvailableCaps({Capability::ImageReadWrite});
688 addAvailableCaps({Capability::SubgroupDispatch, Capability::PipeStorage});
690 addAvailableCaps({Capability::DenormPreserve, Capability::DenormFlushToZero,
691 Capability::SignedZeroInfNanPreserve,
692 Capability::RoundingModeRTE,
693 Capability::RoundingModeRTZ});
695 addAvailableCaps({Capability::Float16, Capability::Float64});
700void RequirementHandler::initAvailableCapabilitiesForVulkan(
704 addAvailableCaps({Capability::Int64, Capability::Float16, Capability::Float64,
705 Capability::GroupNonUniform, Capability::Image1D,
706 Capability::SampledBuffer, Capability::ImageBuffer,
707 Capability::UniformBufferArrayDynamicIndexing,
708 Capability::SampledImageArrayDynamicIndexing,
709 Capability::StorageBufferArrayDynamicIndexing,
710 Capability::StorageImageArrayDynamicIndexing});
715 {Capability::ShaderNonUniformEXT, Capability::RuntimeDescriptorArrayEXT,
716 Capability::InputAttachmentArrayDynamicIndexingEXT,
717 Capability::UniformTexelBufferArrayDynamicIndexingEXT,
718 Capability::StorageTexelBufferArrayDynamicIndexingEXT,
719 Capability::UniformBufferArrayNonUniformIndexingEXT,
720 Capability::SampledImageArrayNonUniformIndexingEXT,
721 Capability::StorageBufferArrayNonUniformIndexingEXT,
722 Capability::StorageImageArrayNonUniformIndexingEXT,
723 Capability::InputAttachmentArrayNonUniformIndexingEXT,
724 Capability::UniformTexelBufferArrayNonUniformIndexingEXT,
725 Capability::StorageTexelBufferArrayNonUniformIndexingEXT});
730 addAvailableCaps({Capability::StorageImageWriteWithoutFormat,
731 Capability::StorageImageReadWithoutFormat});
742 int64_t DecOp =
MI.getOperand(DecIndex).getImm();
743 auto Dec =
static_cast<SPIRV::Decoration::Decoration
>(DecOp);
745 SPIRV::OperandCategory::DecorationOperand, Dec, ST, Reqs));
747 if (Dec == SPIRV::Decoration::BuiltIn) {
748 int64_t BuiltInOp =
MI.getOperand(DecIndex + 1).getImm();
749 auto BuiltIn =
static_cast<SPIRV::BuiltIn::BuiltIn
>(BuiltInOp);
751 SPIRV::OperandCategory::BuiltInOperand, BuiltIn, ST, Reqs));
752 }
else if (Dec == SPIRV::Decoration::LinkageAttributes) {
753 int64_t LinkageOp =
MI.getOperand(
MI.getNumOperands() - 1).getImm();
754 SPIRV::LinkageType::LinkageType LnkType =
755 static_cast<SPIRV::LinkageType::LinkageType
>(LinkageOp);
756 if (LnkType == SPIRV::LinkageType::LinkOnceODR)
757 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_linkonce_odr);
758 }
else if (Dec == SPIRV::Decoration::CacheControlLoadINTEL ||
759 Dec == SPIRV::Decoration::CacheControlStoreINTEL) {
760 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_cache_controls);
761 }
else if (Dec == SPIRV::Decoration::HostAccessINTEL) {
762 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_global_variable_host_access);
763 }
else if (Dec == SPIRV::Decoration::InitModeINTEL ||
764 Dec == SPIRV::Decoration::ImplementInRegisterMapINTEL) {
766 SPIRV::Extension::SPV_INTEL_global_variable_fpga_decorations);
767 }
else if (Dec == SPIRV::Decoration::NonUniformEXT) {
776 assert(
MI.getNumOperands() >= 8 &&
"Insufficient operands for OpTypeImage");
779 int64_t ImgFormatOp =
MI.getOperand(7).getImm();
780 auto ImgFormat =
static_cast<SPIRV::ImageFormat::ImageFormat
>(ImgFormatOp);
784 bool IsArrayed =
MI.getOperand(4).getImm() == 1;
785 bool IsMultisampled =
MI.getOperand(5).getImm() == 1;
786 bool NoSampler =
MI.getOperand(6).getImm() == 2;
789 switch (
MI.getOperand(2).getImm()) {
790 case SPIRV::Dim::DIM_1D:
792 : SPIRV::Capability::Sampled1D);
794 case SPIRV::Dim::DIM_2D:
795 if (IsMultisampled && NoSampler)
798 case SPIRV::Dim::DIM_Cube:
802 : SPIRV::Capability::SampledCubeArray);
804 case SPIRV::Dim::DIM_Rect:
806 : SPIRV::Capability::SampledRect);
808 case SPIRV::Dim::DIM_Buffer:
810 : SPIRV::Capability::SampledBuffer);
812 case SPIRV::Dim::DIM_SubpassData:
818 if (ST.isOpenCLEnv()) {
819 if (
MI.getNumOperands() > 8 &&
820 MI.getOperand(8).getImm() == SPIRV::AccessQualifier::ReadWrite)
828#define ATOM_FLT_REQ_EXT_MSG(ExtName) \
829 "The atomic float instruction requires the following SPIR-V " \
830 "extension: SPV_EXT_shader_atomic_float" ExtName
835 "Expect register operand in atomic float instruction");
837 SPIRVType *TypeDef =
MI.getMF()->getRegInfo().getVRegDef(TypeReg);
838 if (TypeDef->
getOpcode() != SPIRV::OpTypeFloat)
840 "floating-point type scalar");
843 unsigned Op =
MI.getOpcode();
844 if (
Op == SPIRV::OpAtomicFAddEXT) {
845 if (!ST.canUseExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float_add))
847 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float_add);
850 if (!ST.canUseExtension(
851 SPIRV::Extension::SPV_EXT_shader_atomic_float16_add))
853 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float16_add);
864 "Unexpected floating-point type width in atomic float instruction");
867 if (!ST.canUseExtension(
868 SPIRV::Extension::SPV_EXT_shader_atomic_float_min_max))
870 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float_min_max);
873 Reqs.
addCapability(SPIRV::Capability::AtomicFloat16MinMaxEXT);
876 Reqs.
addCapability(SPIRV::Capability::AtomicFloat32MinMaxEXT);
879 Reqs.
addCapability(SPIRV::Capability::AtomicFloat64MinMaxEXT);
883 "Unexpected floating-point type width in atomic float instruction");
889 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
893 return Dim == SPIRV::Dim::DIM_Buffer && Sampled == 1;
897 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
901 return Dim == SPIRV::Dim::DIM_Buffer && Sampled == 2;
905 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
909 return Dim != SPIRV::Dim::DIM_Buffer && Sampled == 1;
913 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
917 return Dim == SPIRV::Dim::DIM_SubpassData && Sampled == 2;
921 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
925 return Dim != SPIRV::Dim::DIM_Buffer && Sampled == 2;
929 if (SampledImageInst->
getOpcode() != SPIRV::OpTypeSampledImage)
934 auto *ImageInst =
MRI.getUniqueVRegDef(ImageReg);
939 for (
const auto &
MI :
MRI.reg_instructions(Reg)) {
940 if (
MI.getOpcode() != SPIRV::OpDecorate)
944 if (Dec == SPIRV::Decoration::NonUniformEXT)
957 Register ResTypeReg = Instr.getOperand(1).getReg();
962 if (
StorageClass != SPIRV::StorageClass::StorageClass::UniformConstant &&
963 StorageClass != SPIRV::StorageClass::StorageClass::Uniform &&
964 StorageClass != SPIRV::StorageClass::StorageClass::StorageBuffer) {
970 if (PointeeType->
getOpcode() != SPIRV::OpTypeImage &&
971 PointeeType->
getOpcode() != SPIRV::OpTypeSampledImage &&
972 PointeeType->
getOpcode() != SPIRV::OpTypeSampler) {
981 SPIRV::Capability::UniformTexelBufferArrayNonUniformIndexingEXT);
984 SPIRV::Capability::UniformTexelBufferArrayDynamicIndexingEXT);
988 SPIRV::Capability::InputAttachmentArrayNonUniformIndexingEXT);
991 SPIRV::Capability::InputAttachmentArrayDynamicIndexingEXT);
995 SPIRV::Capability::StorageTexelBufferArrayNonUniformIndexingEXT);
998 SPIRV::Capability::StorageTexelBufferArrayDynamicIndexingEXT);
1001 PointeeType->
getOpcode() == SPIRV::OpTypeSampler) {
1004 SPIRV::Capability::SampledImageArrayNonUniformIndexingEXT);
1007 SPIRV::Capability::SampledImageArrayDynamicIndexing);
1011 SPIRV::Capability::StorageImageArrayNonUniformIndexingEXT);
1014 SPIRV::Capability::StorageImageArrayDynamicIndexing);
1019 if (TypeInst->
getOpcode() != SPIRV::OpTypeImage)
1028 if (ST.canUseExtension(SPIRV::Extension::SPV_KHR_integer_dot_product))
1029 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_integer_dot_product);
1033 assert(
MI.getOperand(2).isReg() &&
"Unexpected operand in dot");
1041 if (TypeDef->
getOpcode() == SPIRV::OpTypeInt) {
1043 Reqs.
addCapability(SPIRV::Capability::DotProductInput4x8BitPacked);
1044 }
else if (TypeDef->
getOpcode() == SPIRV::OpTypeVector) {
1049 "Dot operand of 8-bit integer type requires 4 components");
1050 Reqs.
addCapability(SPIRV::Capability::DotProductInput4x8Bit);
1060 switch (
MI.getOpcode()) {
1061 case SPIRV::OpMemoryModel: {
1062 int64_t
Addr =
MI.getOperand(0).getImm();
1065 int64_t Mem =
MI.getOperand(1).getImm();
1070 case SPIRV::OpEntryPoint: {
1071 int64_t Exe =
MI.getOperand(0).getImm();
1076 case SPIRV::OpExecutionMode:
1077 case SPIRV::OpExecutionModeId: {
1078 int64_t Exe =
MI.getOperand(1).getImm();
1083 case SPIRV::OpTypeMatrix:
1086 case SPIRV::OpTypeInt: {
1087 unsigned BitWidth =
MI.getOperand(1).getImm();
1096 case SPIRV::OpTypeFloat: {
1097 unsigned BitWidth =
MI.getOperand(1).getImm();
1104 case SPIRV::OpTypeVector: {
1105 unsigned NumComponents =
MI.getOperand(2).getImm();
1106 if (NumComponents == 8 || NumComponents == 16)
1110 case SPIRV::OpTypePointer: {
1111 auto SC =
MI.getOperand(1).getImm();
1116 if (!ST.isOpenCLEnv())
1121 if (TypeDef->
getOpcode() == SPIRV::OpTypeFloat &&
1126 case SPIRV::OpExtInst: {
1127 if (
MI.getOperand(2).getImm() ==
1128 static_cast<int64_t
>(
1129 SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100)) {
1130 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_non_semantic_info);
1134 case SPIRV::OpBitReverse:
1135 case SPIRV::OpBitFieldInsert:
1136 case SPIRV::OpBitFieldSExtract:
1137 case SPIRV::OpBitFieldUExtract:
1138 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_bit_instructions)) {
1142 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_bit_instructions);
1145 case SPIRV::OpTypeRuntimeArray:
1148 case SPIRV::OpTypeOpaque:
1149 case SPIRV::OpTypeEvent:
1152 case SPIRV::OpTypePipe:
1153 case SPIRV::OpTypeReserveId:
1156 case SPIRV::OpTypeDeviceEvent:
1157 case SPIRV::OpTypeQueue:
1158 case SPIRV::OpBuildNDRange:
1161 case SPIRV::OpDecorate:
1162 case SPIRV::OpDecorateId:
1163 case SPIRV::OpDecorateString:
1166 case SPIRV::OpMemberDecorate:
1167 case SPIRV::OpMemberDecorateString:
1170 case SPIRV::OpInBoundsPtrAccessChain:
1173 case SPIRV::OpConstantSampler:
1176 case SPIRV::OpInBoundsAccessChain:
1177 case SPIRV::OpAccessChain:
1180 case SPIRV::OpTypeImage:
1183 case SPIRV::OpTypeSampler:
1184 if (!ST.isVulkanEnv()) {
1188 case SPIRV::OpTypeForwardPointer:
1192 case SPIRV::OpAtomicFlagTestAndSet:
1193 case SPIRV::OpAtomicLoad:
1194 case SPIRV::OpAtomicStore:
1195 case SPIRV::OpAtomicExchange:
1196 case SPIRV::OpAtomicCompareExchange:
1197 case SPIRV::OpAtomicIIncrement:
1198 case SPIRV::OpAtomicIDecrement:
1199 case SPIRV::OpAtomicIAdd:
1200 case SPIRV::OpAtomicISub:
1201 case SPIRV::OpAtomicUMin:
1202 case SPIRV::OpAtomicUMax:
1203 case SPIRV::OpAtomicSMin:
1204 case SPIRV::OpAtomicSMax:
1205 case SPIRV::OpAtomicAnd:
1206 case SPIRV::OpAtomicOr:
1207 case SPIRV::OpAtomicXor: {
1210 if (
MI.getOpcode() == SPIRV::OpAtomicStore) {
1212 InstrPtr =
MRI.getVRegDef(
MI.getOperand(3).getReg());
1213 assert(InstrPtr &&
"Unexpected type instruction for OpAtomicStore");
1218 if (TypeDef->
getOpcode() == SPIRV::OpTypeInt) {
1225 case SPIRV::OpGroupNonUniformIAdd:
1226 case SPIRV::OpGroupNonUniformFAdd:
1227 case SPIRV::OpGroupNonUniformIMul:
1228 case SPIRV::OpGroupNonUniformFMul:
1229 case SPIRV::OpGroupNonUniformSMin:
1230 case SPIRV::OpGroupNonUniformUMin:
1231 case SPIRV::OpGroupNonUniformFMin:
1232 case SPIRV::OpGroupNonUniformSMax:
1233 case SPIRV::OpGroupNonUniformUMax:
1234 case SPIRV::OpGroupNonUniformFMax:
1235 case SPIRV::OpGroupNonUniformBitwiseAnd:
1236 case SPIRV::OpGroupNonUniformBitwiseOr:
1237 case SPIRV::OpGroupNonUniformBitwiseXor:
1238 case SPIRV::OpGroupNonUniformLogicalAnd:
1239 case SPIRV::OpGroupNonUniformLogicalOr:
1240 case SPIRV::OpGroupNonUniformLogicalXor: {
1242 int64_t GroupOp =
MI.getOperand(3).getImm();
1244 case SPIRV::GroupOperation::Reduce:
1245 case SPIRV::GroupOperation::InclusiveScan:
1246 case SPIRV::GroupOperation::ExclusiveScan:
1248 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformArithmetic);
1249 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformBallot);
1251 case SPIRV::GroupOperation::ClusteredReduce:
1252 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformClustered);
1254 case SPIRV::GroupOperation::PartitionedReduceNV:
1255 case SPIRV::GroupOperation::PartitionedInclusiveScanNV:
1256 case SPIRV::GroupOperation::PartitionedExclusiveScanNV:
1257 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformPartitionedNV);
1262 case SPIRV::OpGroupNonUniformShuffle:
1263 case SPIRV::OpGroupNonUniformShuffleXor:
1264 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformShuffle);
1266 case SPIRV::OpGroupNonUniformShuffleUp:
1267 case SPIRV::OpGroupNonUniformShuffleDown:
1268 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformShuffleRelative);
1270 case SPIRV::OpGroupAll:
1271 case SPIRV::OpGroupAny:
1272 case SPIRV::OpGroupBroadcast:
1273 case SPIRV::OpGroupIAdd:
1274 case SPIRV::OpGroupFAdd:
1275 case SPIRV::OpGroupFMin:
1276 case SPIRV::OpGroupUMin:
1277 case SPIRV::OpGroupSMin:
1278 case SPIRV::OpGroupFMax:
1279 case SPIRV::OpGroupUMax:
1280 case SPIRV::OpGroupSMax:
1283 case SPIRV::OpGroupNonUniformElect:
1286 case SPIRV::OpGroupNonUniformAll:
1287 case SPIRV::OpGroupNonUniformAny:
1288 case SPIRV::OpGroupNonUniformAllEqual:
1291 case SPIRV::OpGroupNonUniformBroadcast:
1292 case SPIRV::OpGroupNonUniformBroadcastFirst:
1293 case SPIRV::OpGroupNonUniformBallot:
1294 case SPIRV::OpGroupNonUniformInverseBallot:
1295 case SPIRV::OpGroupNonUniformBallotBitExtract:
1296 case SPIRV::OpGroupNonUniformBallotBitCount:
1297 case SPIRV::OpGroupNonUniformBallotFindLSB:
1298 case SPIRV::OpGroupNonUniformBallotFindMSB:
1299 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformBallot);
1301 case SPIRV::OpSubgroupShuffleINTEL:
1302 case SPIRV::OpSubgroupShuffleDownINTEL:
1303 case SPIRV::OpSubgroupShuffleUpINTEL:
1304 case SPIRV::OpSubgroupShuffleXorINTEL:
1305 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {
1306 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_subgroups);
1307 Reqs.
addCapability(SPIRV::Capability::SubgroupShuffleINTEL);
1310 case SPIRV::OpSubgroupBlockReadINTEL:
1311 case SPIRV::OpSubgroupBlockWriteINTEL:
1312 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {
1313 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_subgroups);
1314 Reqs.
addCapability(SPIRV::Capability::SubgroupBufferBlockIOINTEL);
1317 case SPIRV::OpSubgroupImageBlockReadINTEL:
1318 case SPIRV::OpSubgroupImageBlockWriteINTEL:
1319 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {
1320 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_subgroups);
1321 Reqs.
addCapability(SPIRV::Capability::SubgroupImageBlockIOINTEL);
1324 case SPIRV::OpSubgroupImageMediaBlockReadINTEL:
1325 case SPIRV::OpSubgroupImageMediaBlockWriteINTEL:
1326 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_media_block_io)) {
1327 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_media_block_io);
1328 Reqs.
addCapability(SPIRV::Capability::SubgroupImageMediaBlockIOINTEL);
1331 case SPIRV::OpAssumeTrueKHR:
1332 case SPIRV::OpExpectKHR:
1333 if (ST.canUseExtension(SPIRV::Extension::SPV_KHR_expect_assume)) {
1334 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_expect_assume);
1338 case SPIRV::OpPtrCastToCrossWorkgroupINTEL:
1339 case SPIRV::OpCrossWorkgroupCastToPtrINTEL:
1340 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_usm_storage_classes)) {
1341 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_usm_storage_classes);
1342 Reqs.
addCapability(SPIRV::Capability::USMStorageClassesINTEL);
1345 case SPIRV::OpConstantFunctionPointerINTEL:
1346 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_function_pointers)) {
1347 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_function_pointers);
1348 Reqs.
addCapability(SPIRV::Capability::FunctionPointersINTEL);
1351 case SPIRV::OpGroupNonUniformRotateKHR:
1352 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_subgroup_rotate))
1354 "following SPIR-V extension: SPV_KHR_subgroup_rotate",
1356 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_subgroup_rotate);
1357 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformRotateKHR);
1360 case SPIRV::OpGroupIMulKHR:
1361 case SPIRV::OpGroupFMulKHR:
1362 case SPIRV::OpGroupBitwiseAndKHR:
1363 case SPIRV::OpGroupBitwiseOrKHR:
1364 case SPIRV::OpGroupBitwiseXorKHR:
1365 case SPIRV::OpGroupLogicalAndKHR:
1366 case SPIRV::OpGroupLogicalOrKHR:
1367 case SPIRV::OpGroupLogicalXorKHR:
1368 if (ST.canUseExtension(
1369 SPIRV::Extension::SPV_KHR_uniform_group_instructions)) {
1370 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_uniform_group_instructions);
1371 Reqs.
addCapability(SPIRV::Capability::GroupUniformArithmeticKHR);
1374 case SPIRV::OpReadClockKHR:
1375 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_shader_clock))
1377 "following SPIR-V extension: SPV_KHR_shader_clock",
1379 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_shader_clock);
1382 case SPIRV::OpFunctionPointerCallINTEL:
1383 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_function_pointers)) {
1384 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_function_pointers);
1385 Reqs.
addCapability(SPIRV::Capability::FunctionPointersINTEL);
1388 case SPIRV::OpAtomicFAddEXT:
1389 case SPIRV::OpAtomicFMinEXT:
1390 case SPIRV::OpAtomicFMaxEXT:
1393 case SPIRV::OpConvertBF16ToFINTEL:
1394 case SPIRV::OpConvertFToBF16INTEL:
1395 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bfloat16_conversion)) {
1396 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bfloat16_conversion);
1397 Reqs.
addCapability(SPIRV::Capability::BFloat16ConversionINTEL);
1400 case SPIRV::OpVariableLengthArrayINTEL:
1401 case SPIRV::OpSaveMemoryINTEL:
1402 case SPIRV::OpRestoreMemoryINTEL:
1403 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_variable_length_array)) {
1404 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_variable_length_array);
1405 Reqs.
addCapability(SPIRV::Capability::VariableLengthArrayINTEL);
1408 case SPIRV::OpAsmTargetINTEL:
1409 case SPIRV::OpAsmINTEL:
1410 case SPIRV::OpAsmCallINTEL:
1411 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_inline_assembly)) {
1412 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_inline_assembly);
1416 case SPIRV::OpTypeCooperativeMatrixKHR:
1417 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix))
1419 "OpTypeCooperativeMatrixKHR type requires the "
1420 "following SPIR-V extension: SPV_KHR_cooperative_matrix",
1422 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix);
1423 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixKHR);
1425 case SPIRV::OpArithmeticFenceEXT:
1426 if (!ST.canUseExtension(SPIRV::Extension::SPV_EXT_arithmetic_fence))
1428 "following SPIR-V extension: SPV_EXT_arithmetic_fence",
1430 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_arithmetic_fence);
1433 case SPIRV::OpControlBarrierArriveINTEL:
1434 case SPIRV::OpControlBarrierWaitINTEL:
1435 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_split_barrier)) {
1436 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_split_barrier);
1440 case SPIRV::OpCooperativeMatrixMulAddKHR: {
1441 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix))
1443 "following SPIR-V extension: "
1444 "SPV_KHR_cooperative_matrix",
1446 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix);
1447 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixKHR);
1448 constexpr unsigned MulAddMaxSize = 6;
1449 if (
MI.getNumOperands() != MulAddMaxSize)
1451 const int64_t CoopOperands =
MI.getOperand(MulAddMaxSize - 1).getImm();
1453 SPIRV::CooperativeMatrixOperands::MatrixAAndBTF32ComponentsINTEL) {
1454 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
1456 "require the following SPIR-V extension: "
1457 "SPV_INTEL_joint_matrix",
1459 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
1461 SPIRV::Capability::CooperativeMatrixTF32ComponentTypeINTEL);
1463 if (CoopOperands & SPIRV::CooperativeMatrixOperands::
1464 MatrixAAndBBFloat16ComponentsINTEL ||
1466 SPIRV::CooperativeMatrixOperands::MatrixCBFloat16ComponentsINTEL ||
1467 CoopOperands & SPIRV::CooperativeMatrixOperands::
1468 MatrixResultBFloat16ComponentsINTEL) {
1469 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
1471 "require the following SPIR-V extension: "
1472 "SPV_INTEL_joint_matrix",
1474 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
1476 SPIRV::Capability::CooperativeMatrixBFloat16ComponentTypeINTEL);
1480 case SPIRV::OpCooperativeMatrixLoadKHR:
1481 case SPIRV::OpCooperativeMatrixStoreKHR:
1482 case SPIRV::OpCooperativeMatrixLoadCheckedINTEL:
1483 case SPIRV::OpCooperativeMatrixStoreCheckedINTEL:
1484 case SPIRV::OpCooperativeMatrixPrefetchINTEL: {
1485 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix))
1487 "following SPIR-V extension: "
1488 "SPV_KHR_cooperative_matrix",
1490 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix);
1491 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixKHR);
1495 std::unordered_map<unsigned, unsigned> LayoutToInstMap = {
1496 {SPIRV::OpCooperativeMatrixLoadKHR, 3},
1497 {SPIRV::OpCooperativeMatrixStoreKHR, 2},
1498 {SPIRV::OpCooperativeMatrixLoadCheckedINTEL, 5},
1499 {SPIRV::OpCooperativeMatrixStoreCheckedINTEL, 4},
1500 {SPIRV::OpCooperativeMatrixPrefetchINTEL, 4}};
1502 const auto OpCode =
MI.getOpcode();
1503 const unsigned LayoutNum = LayoutToInstMap[OpCode];
1504 Register RegLayout =
MI.getOperand(LayoutNum).getReg();
1507 if (MILayout->
getOpcode() == SPIRV::OpConstantI) {
1510 static_cast<unsigned>(SPIRV::CooperativeMatrixLayout::PackedINTEL)) {
1511 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
1513 "extension: SPV_INTEL_joint_matrix",
1515 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
1516 Reqs.
addCapability(SPIRV::Capability::PackedCooperativeMatrixINTEL);
1521 if (OpCode == SPIRV::OpCooperativeMatrixLoadKHR ||
1522 OpCode == SPIRV::OpCooperativeMatrixStoreKHR)
1525 std::string InstName;
1527 case SPIRV::OpCooperativeMatrixPrefetchINTEL:
1528 InstName =
"OpCooperativeMatrixPrefetchINTEL";
1530 case SPIRV::OpCooperativeMatrixLoadCheckedINTEL:
1531 InstName =
"OpCooperativeMatrixLoadCheckedINTEL";
1533 case SPIRV::OpCooperativeMatrixStoreCheckedINTEL:
1534 InstName =
"OpCooperativeMatrixStoreCheckedINTEL";
1538 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix)) {
1539 const std::string ErrorMsg =
1540 InstName +
" instruction requires the "
1541 "following SPIR-V extension: SPV_INTEL_joint_matrix";
1544 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
1545 if (OpCode == SPIRV::OpCooperativeMatrixPrefetchINTEL) {
1546 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixPrefetchINTEL);
1550 SPIRV::Capability::CooperativeMatrixCheckedInstructionsINTEL);
1553 case SPIRV::OpCooperativeMatrixConstructCheckedINTEL:
1554 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
1556 "instructions require the following SPIR-V extension: "
1557 "SPV_INTEL_joint_matrix",
1559 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
1561 SPIRV::Capability::CooperativeMatrixCheckedInstructionsINTEL);
1563 case SPIRV::OpCooperativeMatrixGetElementCoordINTEL:
1564 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
1566 "following SPIR-V extension: SPV_INTEL_joint_matrix",
1568 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
1570 SPIRV::Capability::CooperativeMatrixInvocationInstructionsINTEL);
1572 case SPIRV::OpKill: {
1575 case SPIRV::OpDemoteToHelperInvocation:
1576 Reqs.
addCapability(SPIRV::Capability::DemoteToHelperInvocation);
1578 if (ST.canUseExtension(
1579 SPIRV::Extension::SPV_EXT_demote_to_helper_invocation)) {
1582 SPIRV::Extension::SPV_EXT_demote_to_helper_invocation);
1589 case SPIRV::OpImageRead: {
1590 Register ImageReg =
MI.getOperand(2).getReg();
1591 SPIRVType *TypeDef = ST.getSPIRVGlobalRegistry()->getResultType(ImageReg);
1593 Reqs.
addCapability(SPIRV::Capability::StorageImageReadWithoutFormat);
1596 case SPIRV::OpImageWrite: {
1597 Register ImageReg =
MI.getOperand(0).getReg();
1598 SPIRVType *TypeDef = ST.getSPIRVGlobalRegistry()->getResultType(ImageReg);
1600 Reqs.
addCapability(SPIRV::Capability::StorageImageWriteWithoutFormat);
1612 SPIRV::Capability::Shader);
1618 for (
auto F = M.begin(), E = M.end();
F != E; ++
F) {
1627 auto Node = M.getNamedMetadata(
"spirv.ExecutionMode");
1629 bool RequireFloatControls =
false, RequireFloatControls2 =
false,
1630 VerLower14 = !ST.isAtLeastSPIRVVer(
VersionTuple(1, 4));
1631 bool HasFloatControls2 =
1632 ST.canUseExtension(SPIRV::Extension::SPV_INTEL_float_controls2);
1633 for (
unsigned i = 0; i <
Node->getNumOperands(); i++) {
1634 MDNode *MDN = cast<MDNode>(
Node->getOperand(i));
1636 if (
auto *CMeta = dyn_cast<ConstantAsMetadata>(MDOp)) {
1639 auto EM = Const->getZExtValue();
1643 case SPIRV::ExecutionMode::DenormPreserve:
1644 case SPIRV::ExecutionMode::DenormFlushToZero:
1645 case SPIRV::ExecutionMode::SignedZeroInfNanPreserve:
1646 case SPIRV::ExecutionMode::RoundingModeRTE:
1647 case SPIRV::ExecutionMode::RoundingModeRTZ:
1648 RequireFloatControls = VerLower14;
1650 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
1652 case SPIRV::ExecutionMode::RoundingModeRTPINTEL:
1653 case SPIRV::ExecutionMode::RoundingModeRTNINTEL:
1654 case SPIRV::ExecutionMode::FloatingPointModeALTINTEL:
1655 case SPIRV::ExecutionMode::FloatingPointModeIEEEINTEL:
1656 if (HasFloatControls2) {
1657 RequireFloatControls2 =
true;
1659 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
1664 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
1669 if (RequireFloatControls &&
1670 ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls))
1672 if (RequireFloatControls2)
1675 for (
auto FI = M.begin(), E = M.end(); FI != E; ++FI) {
1677 if (
F.isDeclaration())
1679 if (
F.getMetadata(
"reqd_work_group_size"))
1681 SPIRV::OperandCategory::ExecutionModeOperand,
1682 SPIRV::ExecutionMode::LocalSize, ST);
1683 if (
F.getFnAttribute(
"hlsl.numthreads").isValid()) {
1685 SPIRV::OperandCategory::ExecutionModeOperand,
1686 SPIRV::ExecutionMode::LocalSize, ST);
1688 if (
F.getMetadata(
"work_group_size_hint"))
1690 SPIRV::OperandCategory::ExecutionModeOperand,
1691 SPIRV::ExecutionMode::LocalSizeHint, ST);
1692 if (
F.getMetadata(
"intel_reqd_sub_group_size"))
1694 SPIRV::OperandCategory::ExecutionModeOperand,
1695 SPIRV::ExecutionMode::SubgroupSize, ST);
1696 if (
F.getMetadata(
"vec_type_hint"))
1698 SPIRV::OperandCategory::ExecutionModeOperand,
1699 SPIRV::ExecutionMode::VecTypeHint, ST);
1701 if (
F.hasOptNone()) {
1702 if (ST.canUseExtension(SPIRV::Extension::SPV_EXT_optnone)) {
1705 }
else if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_optnone)) {
1714 unsigned Flags = SPIRV::FPFastMathMode::None;
1716 Flags |= SPIRV::FPFastMathMode::NotNaN;
1718 Flags |= SPIRV::FPFastMathMode::NotInf;
1720 Flags |= SPIRV::FPFastMathMode::NSZ;
1722 Flags |= SPIRV::FPFastMathMode::AllowRecip;
1724 Flags |= SPIRV::FPFastMathMode::Fast;
1732 getSymbolicOperandRequirements(SPIRV::OperandCategory::DecorationOperand,
1733 SPIRV::Decoration::NoSignedWrap, ST, Reqs)
1736 SPIRV::Decoration::NoSignedWrap, {});
1739 getSymbolicOperandRequirements(SPIRV::OperandCategory::DecorationOperand,
1740 SPIRV::Decoration::NoUnsignedWrap, ST,
1744 SPIRV::Decoration::NoUnsignedWrap, {});
1746 if (!
TII.canUseFastMathFlags(
I))
1749 if (FMFlags == SPIRV::FPFastMathMode::None)
1751 Register DstReg =
I.getOperand(0).getReg();
1759 for (
auto F = M.begin(), E = M.end();
F != E; ++
F) {
1763 for (
auto &
MBB : *MF)
1764 for (
auto &
MI :
MBB)
1772 for (
auto F = M.begin(), E = M.end();
F != E; ++
F) {
1777 for (
auto &
MBB : *MF) {
1782 MRI.setRegClass(Reg, &SPIRV::IDRegClass);
1793 for (
auto F = M.begin(), E = M.end();
F != E; ++
F) {
1797 for (
auto &
MBB : *MF) {
1799 if (
MI.getOpcode() != TargetOpcode::PHI)
1801 MI.setDesc(
TII.get(SPIRV::OpPhi));
1804 MI.insert(
MI.operands_begin() + 1,
1805 {MachineOperand::CreateReg(ResTypeReg, false)});
1821 ST = TM.getSubtargetImpl();
1822 GR = ST->getSPIRVGlobalRegistry();
1823 TII = ST->getInstrInfo();
1825 MMI = &getAnalysis<MachineModuleInfoWrapperPass>().getMMI();
1838 processDefInstrs(M);
1841 numberRegistersGlobally(M);
1844 if (GR->hasConstFunPtr())
1848 processOtherInstrs(M);
1855 GR->setBound(MAI.
MaxID);
unsigned const MachineRegisterInfo * MRI
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)
bool isStorageImage(MachineInstr *ImageInst)
static void addDecorations(const Module &M, const SPIRVInstrInfo &TII, MachineModuleInfo *MMI, const SPIRVSubtarget &ST, SPIRV::ModuleAnalysisInfo &MAI)
bool isInputAttachment(MachineInstr *ImageInst)
static cl::opt< bool > SPVDumpDeps("spv-dump-deps", cl::desc("Dump MIR with SPIR-V dependencies info"), cl::Optional, cl::init(false))
bool isSampledImage(MachineInstr *ImageInst)
static void patchPhis(const Module &M, SPIRVGlobalRegistry *GR, const SPIRVInstrInfo &TII, MachineModuleInfo *MMI)
static void collectOtherInstr(MachineInstr &MI, SPIRV::ModuleAnalysisInfo &MAI, SPIRV::ModuleSectionType MSType, InstrTraces &IS, bool Append=true)
static void addOpTypeImageReqs(const MachineInstr &MI, SPIRV::RequirementHandler &Reqs, const SPIRVSubtarget &ST)
bool isUniformTexelBuffer(MachineInstr *ImageInst)
bool isStorageTexelBuffer(MachineInstr *ImageInst)
static void AddAtomicFloatRequirements(const MachineInstr &MI, SPIRV::RequirementHandler &Reqs, const SPIRVSubtarget &ST)
bool isCombinedImageSampler(MachineInstr *SampledImageInst)
static InstrSignature instrToSignature(MachineInstr &MI, SPIRV::ModuleAnalysisInfo &MAI)
bool hasNonUniformDecoration(Register Reg, const MachineRegisterInfo &MRI)
unsigned unsigned DefaultVal
static void addOpDecorateReqs(const MachineInstr &MI, unsigned DecIndex, SPIRV::RequirementHandler &Reqs, const SPIRVSubtarget &ST)
static bool isImageTypeWithUnknownFormat(SPIRVType *TypeInst)
static void handleMIFlagDecoration(MachineInstr &I, const SPIRVSubtarget &ST, const SPIRVInstrInfo &TII, SPIRV::RequirementHandler &Reqs)
static void collectReqs(const Module &M, SPIRV::ModuleAnalysisInfo &MAI, MachineModuleInfo *MMI, const SPIRVSubtarget &ST)
static void AddDotProductRequirements(const MachineInstr &MI, SPIRV::RequirementHandler &Reqs, const SPIRVSubtarget &ST)
void addInstrRequirements(const MachineInstr &MI, SPIRV::RequirementHandler &Reqs, const SPIRVSubtarget &ST)
void addOpAccessChainReqs(const MachineInstr &Instr, SPIRV::RequirementHandler &Handler, const SPIRVSubtarget &Subtarget)
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")))
static void addMBBNames(const Module &M, const SPIRVInstrInfo &TII, MachineModuleInfo *MMI, const SPIRVSubtarget &ST, SPIRV::ModuleAnalysisInfo &MAI)
static unsigned getFastMathFlags(const MachineInstr &I)
std::set< InstrSignature > InstrTraces
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.
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.
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.
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,...
MachineInstr * getUniqueVRegDef(Register Reg) const
getUniqueVRegDef - Return the unique machine instr that defines the specified virtual register or nul...
A Module instance is used to store all the information related to an LLVM module.
PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...
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 MachineOperand * getFunctionDefinitionByUse(const MachineOperand *Use)
Register getSPIRVTypeID(const SPIRVType *SpirvType) const
void buildDepsGraph(std::vector< SPIRV::DTSortableEntry * > &Graph, const SPIRVInstrInfo *TII, MachineModuleInfo *MMI=nullptr)
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.
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).
std::pair< iterator, bool > insert(const ValueT &V)
@ 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)
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.
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
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< MachineInstr *, 4 > GlobalVarList
DenseMap< const Function *, Register > FuncMap
void setRegisterAlias(const MachineFunction *MF, Register Reg, Register AliasReg)
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
void setSkipEmission(MachineInstr *MI)
SourceLanguage::SourceLanguage SrcLang
DenseSet< MachineInstr * > InstrsToDelete
DenseMap< unsigned, Register > ExtInstSetMap
void checkSatisfiable(const SPIRVSubtarget &ST) const
void getAndAddRequirements(SPIRV::OperandCategory::OperandCategory Category, uint32_t i, const SPIRVSubtarget &ST)
void addRequirements(const Requirements &Req)
bool isCapabilityAvailable(Capability::Capability Cap) const
void removeCapabilityIf(const Capability::Capability ToRemove, const Capability::Capability IfPresent)
void addAvailableCaps(const CapabilityList &ToAdd)
void addExtension(Extension::Extension ToAdd)
void initAvailableCapabilities(const SPIRVSubtarget &ST)
void addCapability(Capability::Capability ToAdd)
void addCapabilities(const CapabilityList &ToAdd)
const std::optional< Capability::Capability > Cap
const VersionTuple MinVer
const VersionTuple MaxVer