31#define DEBUG_TYPE "spirv-module-analysis"
35 cl::desc(
"Dump MIR with SPIR-V dependencies info"),
40 cl::desc(
"SPIR-V capabilities to avoid if there are "
41 "other options enabling a feature"),
44 "SPIR-V Shader capability")));
66 if (MdNode && OpIndex < MdNode->getNumOperands()) {
67 const auto &
Op = MdNode->getOperand(
OpIndex);
68 return mdconst::extract<ConstantInt>(
Op)->getZExtValue();
74getSymbolicOperandRequirements(SPIRV::OperandCategory::OperandCategory Category,
81 unsigned TargetVer =
ST.getSPIRVVersion();
82 bool MinVerOK = !ReqMinVer || !TargetVer || TargetVer >= ReqMinVer;
83 bool MaxVerOK = !ReqMaxVer || !TargetVer || TargetVer <= ReqMaxVer;
86 if (ReqCaps.
empty()) {
87 if (ReqExts.
empty()) {
88 if (MinVerOK && MaxVerOK)
89 return {
true, {}, {}, ReqMinVer, ReqMaxVer};
90 return {
false, {}, {}, 0, 0};
92 }
else if (MinVerOK && MaxVerOK) {
93 if (ReqCaps.
size() == 1) {
94 auto Cap = ReqCaps[0];
96 return {
true, {Cap}, {}, ReqMinVer, ReqMaxVer};
105 for (
auto Cap : ReqCaps)
108 for (
size_t i = 0, Sz = UseCaps.
size(); i < Sz; ++i) {
109 auto Cap = UseCaps[i];
110 if (i == Sz - 1 || !AvoidCaps.
S.
contains(Cap))
111 return {
true, {Cap}, {}, ReqMinVer, ReqMaxVer};
118 if (
llvm::all_of(ReqExts, [&ST](
const SPIRV::Extension::Extension &Ext) {
119 return ST.canUseExtension(Ext);
121 return {
true, {}, ReqExts, 0, 0};
123 return {
false, {}, {}, 0, 0};
126void SPIRVModuleAnalysis::setBaseInfo(
const Module &M) {
139 if (
auto MemModel =
M.getNamedMetadata(
"spirv.MemoryModel")) {
140 auto MemMD = MemModel->getOperand(0);
141 MAI.
Addr =
static_cast<SPIRV::AddressingModel::AddressingModel
>(
142 getMetadataUInt(MemMD, 0));
144 static_cast<SPIRV::MemoryModel::MemoryModel
>(getMetadataUInt(MemMD, 1));
147 MAI.
Mem =
ST->isOpenCLEnv() ? SPIRV::MemoryModel::OpenCL
148 : SPIRV::MemoryModel::GLSL450;
149 if (
MAI.
Mem == SPIRV::MemoryModel::OpenCL) {
150 unsigned PtrSize =
ST->getPointerSize();
151 MAI.
Addr = PtrSize == 32 ? SPIRV::AddressingModel::Physical32
152 : PtrSize == 64 ? SPIRV::AddressingModel::Physical64
153 : SPIRV::AddressingModel::Logical;
156 MAI.
Addr = SPIRV::AddressingModel::Logical;
161 if (
auto VerNode =
M.getNamedMetadata(
"opencl.ocl.version")) {
162 MAI.
SrcLang = SPIRV::SourceLanguage::OpenCL_C;
165 assert(VerNode->getNumOperands() > 0 &&
"Invalid SPIR");
166 auto VersionMD = VerNode->getOperand(0);
167 unsigned MajorNum = getMetadataUInt(VersionMD, 0, 2);
168 unsigned MinorNum = getMetadataUInt(VersionMD, 1);
169 unsigned RevNum = getMetadataUInt(VersionMD, 2);
176 if (
auto ExtNode =
M.getNamedMetadata(
"opencl.used.extensions")) {
177 for (
unsigned I = 0, E = ExtNode->getNumOperands();
I != E; ++
I) {
195 if (
ST->isOpenCLEnv()) {
198 SPIRV::InstructionSet::OpenCL_std)] =
207 bool DoInsert =
true) {
210 assert(
MI &&
"There should be an instruction that defines the register");
216void SPIRVModuleAnalysis::collectGlobalEntities(
217 const std::vector<SPIRV::DTSortableEntry *> &DepsGraph,
220 bool UsePreOrder =
false) {
222 for (
const auto *E : DepsGraph) {
226 RecHoistUtil = [MSType, UsePreOrder, &Visited, &Pred,
228 if (Visited.count(E) || !Pred(E))
237 for (
auto *S : E->getDeps())
248 collectDefInstr(Reg, MF, &
MAI, MSType, IsFirst);
255 for (
auto *S : E->getDeps())
266void SPIRVModuleAnalysis::processDefInstrs(
const Module &M) {
267 std::vector<SPIRV::DTSortableEntry *> DepsGraph;
271 collectGlobalEntities(
275 for (
auto F =
M.begin(), E =
M.end();
F != E; ++
F) {
282 if (
MI.getOpcode() == SPIRV::OpExtension) {
284 auto Ext = SPIRV::Extension::Extension(
MI.getOperand(0).getImm());
287 }
else if (
MI.getOpcode() == SPIRV::OpCapability) {
288 auto Cap = SPIRV::Capability::Capability(
MI.getOperand(0).getImm());
296 collectGlobalEntities(
307 if (
MI.getOpcode() == SPIRV::OpDecorate) {
309 auto Dec =
MI.getOperand(1).getImm();
310 if (Dec ==
static_cast<unsigned>(SPIRV::Decoration::LinkageAttributes)) {
311 auto Lnk =
MI.getOperand(
MI.getNumOperands() - 1).getImm();
312 if (Lnk ==
static_cast<unsigned>(SPIRV::LinkageType::Import)) {
320 }
else if (
MI.getOpcode() == SPIRV::OpFunction) {
333void SPIRVModuleAnalysis::collectFuncPtrs() {
335 if (
MI->getOpcode() == SPIRV::OpConstantFunctionPointerINTEL)
344 "Constant function pointer must refer to function definition");
345 Register FunDefReg = FunDef->getReg();
349 "Function definition must refer to a global register");
364 InstrSignature Signature;
365 for (
unsigned i = 0; i <
MI.getNumOperands(); ++i) {
376 Signature.push_back(h);
386 bool Append =
true) {
389 auto FoundMI = IS.insert(MISign);
401void SPIRVModuleAnalysis::processOtherInstrs(
const Module &M) {
403 for (
auto F =
M.begin(), E =
M.end();
F != E; ++
F) {
404 if ((*F).isDeclaration())
412 const unsigned OpCode =
MI.getOpcode();
413 if (OpCode == SPIRV::OpName || OpCode == SPIRV::OpMemberName) {
415 }
else if (OpCode == SPIRV::OpEntryPoint) {
419 collectFuncNames(
MI, &*
F);
424 }
else if (OpCode == SPIRV::OpFunction) {
425 collectFuncNames(
MI, &*
F);
426 }
else if (OpCode == SPIRV::OpTypeForwardPointer) {
436void SPIRVModuleAnalysis::numberRegistersGlobally(
const Module &M) {
437 for (
auto F =
M.begin(), E =
M.end();
F != E; ++
F) {
438 if ((*F).isDeclaration())
453 if (
MI.getOpcode() != SPIRV::OpExtInst)
455 auto Set =
MI.getOperand(2).getImm();
465 SPIRV::OperandCategory::OperandCategory Category,
uint32_t i,
467 addRequirements(getSymbolicOperandRequirements(Category, i, ST, *
this));
470void SPIRV::RequirementHandler::recursiveAddCapabilities(
472 for (
const auto &Cap : ToPrune) {
476 recursiveAddCapabilities(ImplicitDecls);
481 for (
const auto &Cap : ToAdd) {
482 bool IsNewlyInserted = AllCaps.insert(Cap).second;
483 if (!IsNewlyInserted)
487 recursiveAddCapabilities(ImplicitDecls);
488 MinimalCaps.push_back(Cap);
497 if (Req.
Cap.has_value())
498 addCapabilities({Req.
Cap.value()});
500 addExtensions(Req.
Exts);
503 if (MaxVersion && Req.
MinVer > MaxVersion) {
505 <<
" and <= " << MaxVersion <<
"\n");
509 if (MinVersion == 0 || Req.
MinVer > MinVersion)
514 if (MinVersion && Req.
MaxVer < MinVersion) {
516 <<
" and >= " << MinVersion <<
"\n");
520 if (MaxVersion == 0 || Req.
MaxVer < MaxVersion)
528 bool IsSatisfiable =
true;
529 auto TargetVer = ST.getSPIRVVersion();
531 if (MaxVersion && TargetVer && MaxVersion < TargetVer) {
533 dbgs() <<
"Target SPIR-V version too high for required features\n"
534 <<
"Required max version: " << MaxVersion <<
" target version "
535 << TargetVer <<
"\n");
536 IsSatisfiable =
false;
539 if (MinVersion && TargetVer && MinVersion > TargetVer) {
540 LLVM_DEBUG(
dbgs() <<
"Target SPIR-V version too low for required features\n"
541 <<
"Required min version: " << MinVersion
542 <<
" target version " << TargetVer <<
"\n");
543 IsSatisfiable =
false;
546 if (MinVersion && MaxVersion && MinVersion > MaxVersion) {
549 <<
"Version is too low for some features and too high for others.\n"
550 <<
"Required SPIR-V min version: " << MinVersion
551 <<
" required SPIR-V max version " << MaxVersion <<
"\n");
552 IsSatisfiable =
false;
555 for (
auto Cap : MinimalCaps) {
556 if (AvailableCaps.contains(Cap))
560 OperandCategory::CapabilityOperand, Cap)
562 IsSatisfiable =
false;
565 for (
auto Ext : AllExtensions) {
566 if (ST.canUseExtension(Ext))
570 OperandCategory::ExtensionOperand, Ext)
572 IsSatisfiable =
false;
581 for (
const auto Cap : ToAdd)
582 if (AvailableCaps.insert(Cap).second)
584 SPIRV::OperandCategory::CapabilityOperand, Cap));
588 const Capability::Capability
ToRemove,
589 const Capability::Capability IfPresent) {
590 if (AllCaps.contains(IfPresent))
597 if (ST.isOpenCLEnv()) {
598 initAvailableCapabilitiesForOpenCL(ST);
602 if (ST.isVulkanEnv()) {
603 initAvailableCapabilitiesForVulkan(ST);
610void RequirementHandler::initAvailableCapabilitiesForOpenCL(
613 addAvailableCaps({Capability::Addresses, Capability::Float16Buffer,
614 Capability::Int16, Capability::Int8, Capability::Kernel,
615 Capability::Linkage, Capability::Vector16,
616 Capability::Groups, Capability::GenericPointer,
617 Capability::Shader});
618 if (ST.hasOpenCLFullProfile())
619 addAvailableCaps({Capability::Int64, Capability::Int64Atomics});
620 if (ST.hasOpenCLImageSupport()) {
621 addAvailableCaps({Capability::ImageBasic, Capability::LiteralSampler,
622 Capability::Image1D, Capability::SampledBuffer,
623 Capability::ImageBuffer});
624 if (
ST.isAtLeastOpenCLVer(20))
625 addAvailableCaps({Capability::ImageReadWrite});
627 if (
ST.isAtLeastSPIRVVer(11) &&
ST.isAtLeastOpenCLVer(22))
628 addAvailableCaps({Capability::SubgroupDispatch, Capability::PipeStorage});
629 if (
ST.isAtLeastSPIRVVer(13))
630 addAvailableCaps({Capability::GroupNonUniform,
631 Capability::GroupNonUniformVote,
632 Capability::GroupNonUniformArithmetic,
633 Capability::GroupNonUniformBallot,
634 Capability::GroupNonUniformClustered,
635 Capability::GroupNonUniformShuffle,
636 Capability::GroupNonUniformShuffleRelative});
637 if (
ST.isAtLeastSPIRVVer(14))
638 addAvailableCaps({Capability::DenormPreserve, Capability::DenormFlushToZero,
639 Capability::SignedZeroInfNanPreserve,
640 Capability::RoundingModeRTE,
641 Capability::RoundingModeRTZ});
643 addAvailableCaps({Capability::Float16, Capability::Float64});
646 for (
auto Extension :
ST.getAllAvailableExtensions()) {
649 addAvailableCaps(EnabledCapabilities);
655void RequirementHandler::initAvailableCapabilitiesForVulkan(
657 addAvailableCaps({Capability::Shader, Capability::Linkage});
660 addAvailableCaps({Capability::Int16, Capability::Int64, Capability::Float16,
661 Capability::Float64, Capability::GroupNonUniform});
672 int64_t DecOp =
MI.getOperand(DecIndex).getImm();
673 auto Dec =
static_cast<SPIRV::Decoration::Decoration
>(DecOp);
675 SPIRV::OperandCategory::DecorationOperand, Dec, ST, Reqs));
677 if (Dec == SPIRV::Decoration::BuiltIn) {
678 int64_t BuiltInOp =
MI.getOperand(DecIndex + 1).getImm();
679 auto BuiltIn =
static_cast<SPIRV::BuiltIn::BuiltIn
>(BuiltInOp);
681 SPIRV::OperandCategory::BuiltInOperand, BuiltIn, ST, Reqs));
682 }
else if (Dec == SPIRV::Decoration::LinkageAttributes) {
683 int64_t LinkageOp =
MI.getOperand(
MI.getNumOperands() - 1).getImm();
684 SPIRV::LinkageType::LinkageType LnkType =
685 static_cast<SPIRV::LinkageType::LinkageType
>(LinkageOp);
686 if (LnkType == SPIRV::LinkageType::LinkOnceODR)
687 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_linkonce_odr);
695 assert(
MI.getNumOperands() >= 8 &&
"Insufficient operands for OpTypeImage");
698 int64_t ImgFormatOp =
MI.getOperand(7).getImm();
699 auto ImgFormat =
static_cast<SPIRV::ImageFormat::ImageFormat
>(ImgFormatOp);
703 bool IsArrayed =
MI.getOperand(4).getImm() == 1;
704 bool IsMultisampled =
MI.getOperand(5).getImm() == 1;
705 bool NoSampler =
MI.getOperand(6).getImm() == 2;
708 switch (
MI.getOperand(2).getImm()) {
709 case SPIRV::Dim::DIM_1D:
711 : SPIRV::Capability::Sampled1D);
713 case SPIRV::Dim::DIM_2D:
714 if (IsMultisampled && NoSampler)
717 case SPIRV::Dim::DIM_Cube:
721 : SPIRV::Capability::SampledCubeArray);
723 case SPIRV::Dim::DIM_Rect:
725 : SPIRV::Capability::SampledRect);
727 case SPIRV::Dim::DIM_Buffer:
729 : SPIRV::Capability::SampledBuffer);
731 case SPIRV::Dim::DIM_SubpassData:
738 if (
MI.getNumOperands() > 8 &&
739 MI.getOperand(8).getImm() == SPIRV::AccessQualifier::ReadWrite)
746#define ATOM_FLT_REQ_EXT_MSG(ExtName) \
747 "The atomic float instruction requires the following SPIR-V " \
748 "extension: SPV_EXT_shader_atomic_float" ExtName
753 "Expect register operand in atomic float instruction");
755 SPIRVType *TypeDef =
MI.getMF()->getRegInfo().getVRegDef(TypeReg);
756 if (TypeDef->
getOpcode() != SPIRV::OpTypeFloat)
758 "floating-point type scalar");
761 unsigned Op =
MI.getOpcode();
762 if (
Op == SPIRV::OpAtomicFAddEXT) {
763 if (!ST.canUseExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float_add))
765 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float_add);
768 if (!ST.canUseExtension(
769 SPIRV::Extension::SPV_EXT_shader_atomic_float16_add))
771 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float16_add);
782 "Unexpected floating-point type width in atomic float instruction");
785 if (!ST.canUseExtension(
786 SPIRV::Extension::SPV_EXT_shader_atomic_float_min_max))
788 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float_min_max);
791 Reqs.
addCapability(SPIRV::Capability::AtomicFloat16MinMaxEXT);
794 Reqs.
addCapability(SPIRV::Capability::AtomicFloat32MinMaxEXT);
797 Reqs.
addCapability(SPIRV::Capability::AtomicFloat64MinMaxEXT);
801 "Unexpected floating-point type width in atomic float instruction");
809 switch (
MI.getOpcode()) {
810 case SPIRV::OpMemoryModel: {
811 int64_t
Addr =
MI.getOperand(0).getImm();
814 int64_t Mem =
MI.getOperand(1).getImm();
819 case SPIRV::OpEntryPoint: {
820 int64_t Exe =
MI.getOperand(0).getImm();
825 case SPIRV::OpExecutionMode:
826 case SPIRV::OpExecutionModeId: {
827 int64_t Exe =
MI.getOperand(1).getImm();
832 case SPIRV::OpTypeMatrix:
835 case SPIRV::OpTypeInt: {
836 unsigned BitWidth =
MI.getOperand(1).getImm();
845 case SPIRV::OpTypeFloat: {
846 unsigned BitWidth =
MI.getOperand(1).getImm();
853 case SPIRV::OpTypeVector: {
854 unsigned NumComponents =
MI.getOperand(2).getImm();
855 if (NumComponents == 8 || NumComponents == 16)
859 case SPIRV::OpTypePointer: {
860 auto SC =
MI.getOperand(1).getImm();
865 if (!ST.isOpenCLEnv())
870 if (TypeDef->
getOpcode() == SPIRV::OpTypeFloat &&
875 case SPIRV::OpBitReverse:
876 case SPIRV::OpBitFieldInsert:
877 case SPIRV::OpBitFieldSExtract:
878 case SPIRV::OpBitFieldUExtract:
879 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_bit_instructions)) {
883 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_bit_instructions);
886 case SPIRV::OpTypeRuntimeArray:
889 case SPIRV::OpTypeOpaque:
890 case SPIRV::OpTypeEvent:
893 case SPIRV::OpTypePipe:
894 case SPIRV::OpTypeReserveId:
897 case SPIRV::OpTypeDeviceEvent:
898 case SPIRV::OpTypeQueue:
899 case SPIRV::OpBuildNDRange:
902 case SPIRV::OpDecorate:
903 case SPIRV::OpDecorateId:
904 case SPIRV::OpDecorateString:
907 case SPIRV::OpMemberDecorate:
908 case SPIRV::OpMemberDecorateString:
911 case SPIRV::OpInBoundsPtrAccessChain:
914 case SPIRV::OpConstantSampler:
917 case SPIRV::OpTypeImage:
920 case SPIRV::OpTypeSampler:
923 case SPIRV::OpTypeForwardPointer:
927 case SPIRV::OpAtomicFlagTestAndSet:
928 case SPIRV::OpAtomicLoad:
929 case SPIRV::OpAtomicStore:
930 case SPIRV::OpAtomicExchange:
931 case SPIRV::OpAtomicCompareExchange:
932 case SPIRV::OpAtomicIIncrement:
933 case SPIRV::OpAtomicIDecrement:
934 case SPIRV::OpAtomicIAdd:
935 case SPIRV::OpAtomicISub:
936 case SPIRV::OpAtomicUMin:
937 case SPIRV::OpAtomicUMax:
938 case SPIRV::OpAtomicSMin:
939 case SPIRV::OpAtomicSMax:
940 case SPIRV::OpAtomicAnd:
941 case SPIRV::OpAtomicOr:
942 case SPIRV::OpAtomicXor: {
945 if (
MI.getOpcode() == SPIRV::OpAtomicStore) {
947 InstrPtr =
MRI.getVRegDef(
MI.getOperand(3).getReg());
948 assert(InstrPtr &&
"Unexpected type instruction for OpAtomicStore");
953 if (TypeDef->
getOpcode() == SPIRV::OpTypeInt) {
960 case SPIRV::OpGroupNonUniformIAdd:
961 case SPIRV::OpGroupNonUniformFAdd:
962 case SPIRV::OpGroupNonUniformIMul:
963 case SPIRV::OpGroupNonUniformFMul:
964 case SPIRV::OpGroupNonUniformSMin:
965 case SPIRV::OpGroupNonUniformUMin:
966 case SPIRV::OpGroupNonUniformFMin:
967 case SPIRV::OpGroupNonUniformSMax:
968 case SPIRV::OpGroupNonUniformUMax:
969 case SPIRV::OpGroupNonUniformFMax:
970 case SPIRV::OpGroupNonUniformBitwiseAnd:
971 case SPIRV::OpGroupNonUniformBitwiseOr:
972 case SPIRV::OpGroupNonUniformBitwiseXor:
973 case SPIRV::OpGroupNonUniformLogicalAnd:
974 case SPIRV::OpGroupNonUniformLogicalOr:
975 case SPIRV::OpGroupNonUniformLogicalXor: {
977 int64_t GroupOp =
MI.getOperand(3).getImm();
979 case SPIRV::GroupOperation::Reduce:
980 case SPIRV::GroupOperation::InclusiveScan:
981 case SPIRV::GroupOperation::ExclusiveScan:
983 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformArithmetic);
984 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformBallot);
986 case SPIRV::GroupOperation::ClusteredReduce:
987 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformClustered);
989 case SPIRV::GroupOperation::PartitionedReduceNV:
990 case SPIRV::GroupOperation::PartitionedInclusiveScanNV:
991 case SPIRV::GroupOperation::PartitionedExclusiveScanNV:
992 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformPartitionedNV);
997 case SPIRV::OpGroupNonUniformShuffle:
998 case SPIRV::OpGroupNonUniformShuffleXor:
999 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformShuffle);
1001 case SPIRV::OpGroupNonUniformShuffleUp:
1002 case SPIRV::OpGroupNonUniformShuffleDown:
1003 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformShuffleRelative);
1005 case SPIRV::OpGroupAll:
1006 case SPIRV::OpGroupAny:
1007 case SPIRV::OpGroupBroadcast:
1008 case SPIRV::OpGroupIAdd:
1009 case SPIRV::OpGroupFAdd:
1010 case SPIRV::OpGroupFMin:
1011 case SPIRV::OpGroupUMin:
1012 case SPIRV::OpGroupSMin:
1013 case SPIRV::OpGroupFMax:
1014 case SPIRV::OpGroupUMax:
1015 case SPIRV::OpGroupSMax:
1018 case SPIRV::OpGroupNonUniformElect:
1021 case SPIRV::OpGroupNonUniformAll:
1022 case SPIRV::OpGroupNonUniformAny:
1023 case SPIRV::OpGroupNonUniformAllEqual:
1026 case SPIRV::OpGroupNonUniformBroadcast:
1027 case SPIRV::OpGroupNonUniformBroadcastFirst:
1028 case SPIRV::OpGroupNonUniformBallot:
1029 case SPIRV::OpGroupNonUniformInverseBallot:
1030 case SPIRV::OpGroupNonUniformBallotBitExtract:
1031 case SPIRV::OpGroupNonUniformBallotBitCount:
1032 case SPIRV::OpGroupNonUniformBallotFindLSB:
1033 case SPIRV::OpGroupNonUniformBallotFindMSB:
1034 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformBallot);
1036 case SPIRV::OpSubgroupShuffleINTEL:
1037 case SPIRV::OpSubgroupShuffleDownINTEL:
1038 case SPIRV::OpSubgroupShuffleUpINTEL:
1039 case SPIRV::OpSubgroupShuffleXorINTEL:
1040 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {
1041 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_subgroups);
1042 Reqs.
addCapability(SPIRV::Capability::SubgroupShuffleINTEL);
1045 case SPIRV::OpSubgroupBlockReadINTEL:
1046 case SPIRV::OpSubgroupBlockWriteINTEL:
1047 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {
1048 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_subgroups);
1049 Reqs.
addCapability(SPIRV::Capability::SubgroupBufferBlockIOINTEL);
1052 case SPIRV::OpSubgroupImageBlockReadINTEL:
1053 case SPIRV::OpSubgroupImageBlockWriteINTEL:
1054 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {
1055 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_subgroups);
1056 Reqs.
addCapability(SPIRV::Capability::SubgroupImageBlockIOINTEL);
1059 case SPIRV::OpAssumeTrueKHR:
1060 case SPIRV::OpExpectKHR:
1061 if (ST.canUseExtension(SPIRV::Extension::SPV_KHR_expect_assume)) {
1062 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_expect_assume);
1066 case SPIRV::OpPtrCastToCrossWorkgroupINTEL:
1067 case SPIRV::OpCrossWorkgroupCastToPtrINTEL:
1068 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_usm_storage_classes)) {
1069 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_usm_storage_classes);
1070 Reqs.
addCapability(SPIRV::Capability::USMStorageClassesINTEL);
1073 case SPIRV::OpConstantFunctionPointerINTEL:
1074 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_function_pointers)) {
1075 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_function_pointers);
1076 Reqs.
addCapability(SPIRV::Capability::FunctionPointersINTEL);
1079 case SPIRV::OpGroupNonUniformRotateKHR:
1080 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_subgroup_rotate))
1082 "following SPIR-V extension: SPV_KHR_subgroup_rotate",
1084 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_subgroup_rotate);
1085 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformRotateKHR);
1088 case SPIRV::OpGroupIMulKHR:
1089 case SPIRV::OpGroupFMulKHR:
1090 case SPIRV::OpGroupBitwiseAndKHR:
1091 case SPIRV::OpGroupBitwiseOrKHR:
1092 case SPIRV::OpGroupBitwiseXorKHR:
1093 case SPIRV::OpGroupLogicalAndKHR:
1094 case SPIRV::OpGroupLogicalOrKHR:
1095 case SPIRV::OpGroupLogicalXorKHR:
1096 if (ST.canUseExtension(
1097 SPIRV::Extension::SPV_KHR_uniform_group_instructions)) {
1098 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_uniform_group_instructions);
1099 Reqs.
addCapability(SPIRV::Capability::GroupUniformArithmeticKHR);
1102 case SPIRV::OpFunctionPointerCallINTEL:
1103 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_function_pointers)) {
1104 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_function_pointers);
1105 Reqs.
addCapability(SPIRV::Capability::FunctionPointersINTEL);
1108 case SPIRV::OpAtomicFAddEXT:
1109 case SPIRV::OpAtomicFMinEXT:
1110 case SPIRV::OpAtomicFMaxEXT:
1113 case SPIRV::OpConvertBF16ToFINTEL:
1114 case SPIRV::OpConvertFToBF16INTEL:
1115 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bfloat16_conversion)) {
1116 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bfloat16_conversion);
1117 Reqs.
addCapability(SPIRV::Capability::BFloat16ConversionINTEL);
1120 case SPIRV::OpVariableLengthArrayINTEL:
1121 case SPIRV::OpSaveMemoryINTEL:
1122 case SPIRV::OpRestoreMemoryINTEL:
1123 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_variable_length_array)) {
1124 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_variable_length_array);
1125 Reqs.
addCapability(SPIRV::Capability::VariableLengthArrayINTEL);
1136 SPIRV::Capability::Shader);
1142 for (
auto F = M.begin(), E = M.end();
F != E; ++
F) {
1151 auto Node = M.getNamedMetadata(
"spirv.ExecutionMode");
1154 bool RequireFloatControls =
false, VerLower14 = !ST.isAtLeastSPIRVVer(14);
1155 for (
unsigned i = 0; i <
Node->getNumOperands(); i++) {
1156 MDNode *MDN = cast<MDNode>(
Node->getOperand(i));
1158 if (
auto *CMeta = dyn_cast<ConstantAsMetadata>(MDOp)) {
1161 auto EM = Const->getZExtValue();
1163 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
1166 case SPIRV::ExecutionMode::DenormPreserve:
1167 case SPIRV::ExecutionMode::DenormFlushToZero:
1168 case SPIRV::ExecutionMode::SignedZeroInfNanPreserve:
1169 case SPIRV::ExecutionMode::RoundingModeRTE:
1170 case SPIRV::ExecutionMode::RoundingModeRTZ:
1171 RequireFloatControls = VerLower14;
1177 if (RequireFloatControls &&
1178 ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls))
1181 for (
auto FI = M.begin(), E = M.end(); FI != E; ++FI) {
1183 if (
F.isDeclaration())
1185 if (
F.getMetadata(
"reqd_work_group_size"))
1187 SPIRV::OperandCategory::ExecutionModeOperand,
1188 SPIRV::ExecutionMode::LocalSize, ST);
1189 if (
F.getFnAttribute(
"hlsl.numthreads").isValid()) {
1191 SPIRV::OperandCategory::ExecutionModeOperand,
1192 SPIRV::ExecutionMode::LocalSize, ST);
1194 if (
F.getMetadata(
"work_group_size_hint"))
1196 SPIRV::OperandCategory::ExecutionModeOperand,
1197 SPIRV::ExecutionMode::LocalSizeHint, ST);
1198 if (
F.getMetadata(
"intel_reqd_sub_group_size"))
1200 SPIRV::OperandCategory::ExecutionModeOperand,
1201 SPIRV::ExecutionMode::SubgroupSize, ST);
1202 if (
F.getMetadata(
"vec_type_hint"))
1204 SPIRV::OperandCategory::ExecutionModeOperand,
1205 SPIRV::ExecutionMode::VecTypeHint, ST);
1207 if (
F.hasOptNone() &&
1208 ST.canUseExtension(SPIRV::Extension::SPV_INTEL_optnone)) {
1217 unsigned Flags = SPIRV::FPFastMathMode::None;
1219 Flags |= SPIRV::FPFastMathMode::NotNaN;
1221 Flags |= SPIRV::FPFastMathMode::NotInf;
1223 Flags |= SPIRV::FPFastMathMode::NSZ;
1225 Flags |= SPIRV::FPFastMathMode::AllowRecip;
1227 Flags |= SPIRV::FPFastMathMode::Fast;
1235 getSymbolicOperandRequirements(SPIRV::OperandCategory::DecorationOperand,
1236 SPIRV::Decoration::NoSignedWrap, ST, Reqs)
1239 SPIRV::Decoration::NoSignedWrap, {});
1242 getSymbolicOperandRequirements(SPIRV::OperandCategory::DecorationOperand,
1243 SPIRV::Decoration::NoUnsignedWrap, ST,
1247 SPIRV::Decoration::NoUnsignedWrap, {});
1249 if (!
TII.canUseFastMathFlags(
I))
1252 if (FMFlags == SPIRV::FPFastMathMode::None)
1254 Register DstReg =
I.getOperand(0).getReg();
1262 for (
auto F = M.begin(), E = M.end();
F != E; ++
F) {
1266 for (
auto &
MBB : *MF)
1267 for (
auto &
MI :
MBB)
1282 ST =
TM.getSubtargetImpl();
1283 GR = ST->getSPIRVGlobalRegistry();
1284 TII = ST->getInstrInfo();
1286 MMI = &getAnalysis<MachineModuleInfoWrapperPass>().getMMI();
1296 processDefInstrs(M);
1299 numberRegistersGlobally(M);
1302 if (GR->hasConstFunPtr())
1306 processOtherInstrs(M);
1313 GR->setBound(MAI.
MaxID);
unsigned const MachineRegisterInfo * MRI
ReachingDefAnalysis InstSet & ToRemove
#define clEnumValN(ENUMVAL, FLAGNAME, DESC)
const HexagonInstrInfo * TII
const char LLVMTargetMachineRef TM
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
#define ATOM_FLT_REQ_EXT_MSG(ExtName)
static void addDecorations(const Module &M, const SPIRVInstrInfo &TII, MachineModuleInfo *MMI, const SPIRVSubtarget &ST, SPIRV::ModuleAnalysisInfo &MAI)
static cl::opt< bool > SPVDumpDeps("spv-dump-deps", cl::desc("Dump MIR with SPIR-V dependencies info"), cl::Optional, cl::init(false))
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)
static void AddAtomicFloatRequirements(const MachineInstr &MI, SPIRV::RequirementHandler &Reqs, const SPIRVSubtarget &ST)
static InstrSignature instrToSignature(MachineInstr &MI, SPIRV::ModuleAnalysisInfo &MAI)
unsigned unsigned DefaultVal
static void addOpDecorateReqs(const MachineInstr &MI, unsigned DecIndex, SPIRV::RequirementHandler &Reqs, const SPIRVSubtarget &ST)
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)
void addInstrRequirements(const MachineInstr &MI, SPIRV::RequirementHandler &Reqs, const SPIRVSubtarget &ST)
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 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.
const MDOperand & getOperand(unsigned I) const
unsigned getNumOperands() const
Return number of MDNode operands.
Tracking metadata reference owned by Metadata.
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.
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
const MachineOperand * getFunctionDefinitionByUse(const MachineOperand *Use)
void buildDepsGraph(std::vector< SPIRV::DTSortableEntry * > &Graph, MachineModuleInfo *MMI=nullptr)
bool isConstantInstr(const MachineInstr &MI) const
bool isDecorationInstr(const MachineInstr &MI) const
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
bool contains(const T &V) const
Check if the SmallSet contains the given element.
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
iterator insert(iterator I, T &&Elt)
void push_back(const T &Elt)
std::pair< typename Base::iterator, bool > insert(StringRef key)
Target-Independent Code Generator Pass Configuration Options.
Target - Wrapper for Target specific information.
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.
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)
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)
uint32_t getSymbolicOperandMinVersion(SPIRV::OperandCategory::OperandCategory Category, uint32_t Value)
constexpr unsigned BitWidth
uint32_t getSymbolicOperandMaxVersion(SPIRV::OperandCategory::OperandCategory Category, uint32_t Value)
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
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