36#define DEBUG_TYPE "spirv-module-analysis"
41 "SPIRV module analysis",
true,
true)
45 Func.getContext().diagnose(
51 unsigned DefaultVal = 0) {
52 if (MdNode && OpIndex < MdNode->getNumOperands()) {
61 SPIRV::Capability::Capability Cap) {
62 return Cap == (ST.isShader() ? SPIRV::Capability::Kernel
63 : SPIRV::Capability::Shader) ||
74 bool MinVerOK = SPIRVVersion.
empty() || SPIRVVersion >= ReqMinVer;
76 ReqMaxVer.
empty() || SPIRVVersion.
empty() || SPIRVVersion <= ReqMaxVer;
77 bool VerOK = MinVerOK && MaxVerOK;
81 if (VerOK && !ReqMinVer.
empty())
83 if (ReqCaps.
empty()) {
84 if (ReqExts.
empty()) {
86 return {
true, {}, {}, ReqMinVer, ReqMaxVer};
90 if (ReqCaps.
size() == 1) {
91 auto Cap = ReqCaps[0];
94 SPIRV::OperandCategory::CapabilityOperand, Cap));
95 return {
true, {Cap}, std::move(ReqExts), ReqMinVer, ReqMaxVer};
105 for (
auto Cap : ReqCaps)
108 for (
size_t i = 0, Sz = UseCaps.
size(); i < Sz; ++i) {
109 auto Cap = UseCaps[i];
112 SPIRV::OperandCategory::CapabilityOperand, Cap));
113 return {
true, {Cap}, std::move(ReqExts), ReqMinVer, ReqMaxVer};
122 if ((!ReqExts.
empty() || VerOK) &&
123 llvm::all_of(ReqExts, [&ST](
const SPIRV::Extension::Extension &Ext) {
124 return ST.canUseExtension(Ext);
127 return {
true, {}, std::move(ReqExts), ReqMinVer, ReqMaxVer};
133void SPIRVModuleAnalysisImpl::setBaseInfo(
const Module &M) {
137 MAI.RegisterAliasTable.clear();
138 MAI.InstrsToDelete.clear();
139 MAI.MBBNames.clear();
140 MAI.GlobalObjMap.clear();
141 MAI.GlobalVarList.clear();
142 MAI.ExtInstSetMap.clear();
143 MAI.InstrAuxDataRecords.clear();
144 MAI.DebugValueMIs.clear();
146 MAI.Reqs.initAvailableCapabilities(*ST);
149 if (
auto MemModel =
M.getNamedMetadata(
"spirv.MemoryModel")) {
150 auto MemMD = MemModel->getOperand(0);
151 MAI.Addr =
static_cast<SPIRV::AddressingModel::AddressingModel
>(
154 static_cast<SPIRV::MemoryModel::MemoryModel
>(
getMetadataUInt(MemMD, 1));
157 MAI.Mem = ST->isShader() ? SPIRV::MemoryModel::GLSL450
158 : SPIRV::MemoryModel::OpenCL;
159 if (MAI.Mem == SPIRV::MemoryModel::OpenCL) {
160 unsigned PtrSize = ST->getPointerSize();
161 MAI.Addr = PtrSize == 32 ? SPIRV::AddressingModel::Physical32
162 : PtrSize == 64 ? SPIRV::AddressingModel::Physical64
163 : SPIRV::AddressingModel::Logical;
166 MAI.Addr = SPIRV::AddressingModel::Logical;
171 if (
auto VerNode =
M.getNamedMetadata(
"opencl.ocl.version")) {
172 MAI.SrcLang = SPIRV::SourceLanguage::OpenCL_C;
175 assert(VerNode->getNumOperands() > 0 &&
"Invalid SPIR");
176 auto VersionMD = VerNode->getOperand(0);
182 (std::max(1U, MajorNum) * 100 + MinorNum) * 1000 + RevNum;
185 if (
auto *CxxVerNode =
M.getNamedMetadata(
"opencl.cxx.version")) {
186 assert(CxxVerNode->getNumOperands() > 0 &&
"Invalid SPIR");
187 auto *CxxMD = CxxVerNode->getOperand(0);
191 if ((MAI.SrcLangVersion == 200000 && CxxVer == 100000) ||
192 (MAI.SrcLangVersion == 300000 && CxxVer == 202100000)) {
193 MAI.SrcLang = SPIRV::SourceLanguage::CPP_for_OpenCL;
194 MAI.SrcLangVersion = CxxVer;
197 "opencl cxx version is not compatible with opencl c version!");
205 if (!ST->isShader()) {
206 MAI.SrcLang = SPIRV::SourceLanguage::OpenCL_CPP;
207 MAI.SrcLangVersion = 100000;
209 MAI.SrcLang = SPIRV::SourceLanguage::Unknown;
210 MAI.SrcLangVersion = 0;
214 if (
auto ExtNode =
M.getNamedMetadata(
"opencl.used.extensions")) {
215 for (
unsigned I = 0,
E = ExtNode->getNumOperands();
I !=
E; ++
I) {
216 MDNode *MD = ExtNode->getOperand(
I);
226 MAI.Reqs.getAndAddRequirements(SPIRV::OperandCategory::MemoryModelOperand,
228 MAI.Reqs.getAndAddRequirements(SPIRV::OperandCategory::SourceLanguageOperand,
230 MAI.Reqs.getAndAddRequirements(SPIRV::OperandCategory::AddressingModelOperand,
233 if (MAI.Mem == SPIRV::MemoryModel::VulkanKHR)
234 MAI.Reqs.addExtension(SPIRV::Extension::SPV_KHR_vulkan_memory_model);
236 if (!ST->isShader()) {
238 MAI.ExtInstSetMap[
static_cast<unsigned>(
239 SPIRV::InstructionSet::OpenCL_std)] = MAI.getNextIDRegister();
250 if (
UseMI.getOpcode() != SPIRV::OpDecorate &&
251 UseMI.getOpcode() != SPIRV::OpMemberDecorate)
254 for (
unsigned I = 0;
I <
UseMI.getNumOperands(); ++
I) {
272 for (
unsigned i = 0; i <
MI.getNumOperands(); ++i) {
281 unsigned Opcode =
MI.getOpcode();
282 if ((Opcode == SPIRV::OpDecorate) && i >= 2) {
283 unsigned DecorationID =
MI.getOperand(1).getImm();
284 if (DecorationID != SPIRV::Decoration::FuncParamAttr &&
285 DecorationID != SPIRV::Decoration::UserSemantic &&
286 DecorationID != SPIRV::Decoration::CacheControlLoadINTEL &&
287 DecorationID != SPIRV::Decoration::CacheControlStoreINTEL)
293 if (!UseDefReg && MO.
isDef()) {
301 dbgs() <<
"Unexpectedly, no global id found for the operand ";
303 dbgs() <<
"\nInstruction: ";
330 case SPIRV::OpEnqueueKernel:
332 case SPIRV::OpGetKernelNDrangeSubGroupCount:
333 case SPIRV::OpGetKernelNDrangeMaxSubGroupSize:
335 case SPIRV::OpGetKernelWorkGroupSize:
336 case SPIRV::OpGetKernelPreferredWorkGroupSizeMultiple:
345 unsigned Opcode =
MI.getOpcode();
347 case SPIRV::OpTypeForwardPointer:
350 case SPIRV::OpVariable:
351 case SPIRV::OpUntypedVariableKHR:
352 return static_cast<SPIRV::StorageClass::StorageClass
>(
353 MI.getOperand(2).
getImm()) != SPIRV::StorageClass::Function;
354 case SPIRV::OpFunction:
355 case SPIRV::OpFunctionParameter:
358 if (GR->hasConstFunPtr() && Opcode == SPIRV::OpUndef) {
366 if (GR->getFunctionDefinitionByUse(&
MI.getOperand(0))) {
368 unsigned UseOp =
UseMI.getOpcode();
369 if (UseOp == SPIRV::OpConstantFunctionPointerINTEL ||
371 MAI.setSkipEmission(&
MI);
377 if (
UseMI.getOpcode() != SPIRV::OpConstantFunctionPointerINTEL)
383 MAI.setSkipEmission(&
MI);
387 return TII->isTypeDeclInstr(
MI) || TII->isConstantInstr(
MI) ||
388 TII->isInlineAsmDefInstr(
MI);
397void SPIRVModuleAnalysisImpl::visitFunPtrUse(
400 std::map<const Value *, unsigned> &GlobalToGReg,
402 const MachineOperand *OpFunDef = GR->getFunctionDefinitionByUse(FunPtrOp);
405 const MachineInstr *OpDefMI = OpFunDef->
getParent();
408 const MachineRegisterInfo &FunDefMRI = FunDefMF->
getRegInfo();
410 visitDecl(FunDefMRI, SignatureToGReg, GlobalToGReg, FunDefMF, *OpDefMI);
412 }
while (OpDefMI && (OpDefMI->
getOpcode() == SPIRV::OpFunction ||
413 OpDefMI->
getOpcode() == SPIRV::OpFunctionParameter));
415 MCRegister GlobalFunDefReg =
416 MAI.getRegisterAlias(FunDefMF, OpFunDef->
getReg());
418 "Function definition must refer to a global register");
419 MAI.setRegisterAlias(MF, OpReg, GlobalFunDefReg);
424void SPIRVModuleAnalysisImpl::visitDecl(
426 std::map<const Value *, unsigned> &GlobalToGReg,
const MachineFunction *MF,
428 unsigned Opcode =
MI.getOpcode();
431 for (
const MachineOperand &MO :
MI.operands()) {
432 if (!MO.isReg() || MO.isDef())
436 if (Opcode == SPIRV::OpConstantFunctionPointerINTEL &&
438 visitFunPtrUse(OpReg, &
MI.getOperand(2), SignatureToGReg, GlobalToGReg,
443 if (MAI.hasRegisterAlias(MF, MO.getReg()))
447 if (isDeclSection(
MRI, *OpDefMI))
448 visitDecl(
MRI, SignatureToGReg, GlobalToGReg, MF, *OpDefMI);
454 dbgs() <<
"Unexpectedly, no unique definition for the operand ";
456 dbgs() <<
"\nInstruction: ";
461 "No unique definition is found for the virtual register");
465 bool IsFunDef =
false;
466 if (TII->isSpecConstantInstr(
MI)) {
467 GReg = MAI.getNextIDRegister();
469 }
else if (Opcode == SPIRV::OpFunction ||
470 Opcode == SPIRV::OpFunctionParameter) {
471 GReg = handleFunctionOrParameter(MF,
MI, GlobalToGReg, IsFunDef);
472 }
else if (Opcode == SPIRV::OpTypeStruct ||
473 Opcode == SPIRV::OpConstantComposite) {
474 GReg = handleTypeDeclOrConstant(
MI, SignatureToGReg);
475 const MachineInstr *NextInstr =
MI.getNextNode();
477 ((Opcode == SPIRV::OpTypeStruct &&
478 NextInstr->
getOpcode() == SPIRV::OpTypeStructContinuedINTEL) ||
479 (Opcode == SPIRV::OpConstantComposite &&
481 SPIRV::OpConstantCompositeContinuedINTEL))) {
482 MCRegister Tmp = handleTypeDeclOrConstant(*NextInstr, SignatureToGReg);
484 MAI.setSkipEmission(NextInstr);
487 }
else if (TII->isTypeDeclInstr(
MI) || TII->isConstantInstr(
MI) ||
488 TII->isInlineAsmDefInstr(
MI)) {
489 GReg = handleTypeDeclOrConstant(
MI, SignatureToGReg);
490 }
else if (Opcode == SPIRV::OpVariable ||
491 Opcode == SPIRV::OpUntypedVariableKHR) {
492 GReg = handleVariable(MF,
MI, GlobalToGReg);
495 dbgs() <<
"\nInstruction: ";
501 MAI.setRegisterAlias(MF,
MI.getOperand(0).getReg(), GReg);
503 MAI.setSkipEmission(&
MI);
506MCRegister SPIRVModuleAnalysisImpl::handleFunctionOrParameter(
508 std::map<const Value *, unsigned> &GlobalToGReg,
bool &IsFunDef) {
509 const Value *GObj = GR->getGlobalObject(MF,
MI.getOperand(0).getReg());
510 assert(GObj &&
"Unregistered global definition");
514 assert(
F &&
"Expected a reference to a function or an argument");
515 IsFunDef = !
F->isDeclaration();
516 auto [It,
Inserted] = GlobalToGReg.try_emplace(GObj);
519 MCRegister GReg = MAI.getNextIDRegister();
526MCRegister SPIRVModuleAnalysisImpl::handleTypeDeclOrConstant(
529 auto [It,
Inserted] = SignatureToGReg.try_emplace(MISign);
532 MCRegister GReg = MAI.getNextIDRegister();
538MCRegister SPIRVModuleAnalysisImpl::handleVariable(
540 std::map<const Value *, unsigned> &GlobalToGReg) {
541 MAI.GlobalVarList.push_back(&
MI);
542 const Value *GObj = GR->getGlobalObject(MF,
MI.getOperand(0).getReg());
543 assert(GObj &&
"Unregistered global definition");
544 auto [It,
Inserted] = GlobalToGReg.try_emplace(GObj);
547 MCRegister GReg = MAI.getNextIDRegister();
551 MAI.GlobalObjMap[GV] = GReg;
555void SPIRVModuleAnalysisImpl::collectDeclarations(
const Module &M) {
557 std::map<const Value *, unsigned> GlobalToGReg;
563 unsigned PastHeader = 0;
564 for (MachineBasicBlock &
MBB : *MF) {
565 for (MachineInstr &
MI :
MBB) {
566 if (
MI.getNumOperands() == 0)
568 unsigned Opcode =
MI.getOpcode();
569 if (Opcode == SPIRV::OpFunction) {
570 if (PastHeader == 0) {
574 }
else if (Opcode == SPIRV::OpFunctionParameter) {
577 }
else if (PastHeader > 0) {
581 const MachineOperand &DefMO =
MI.getOperand(0);
583 case SPIRV::OpExtension:
584 MAI.Reqs.addExtension(SPIRV::Extension::Extension(DefMO.
getImm()));
585 MAI.setSkipEmission(&
MI);
587 case SPIRV::OpCapability:
588 MAI.Reqs.addCapability(SPIRV::Capability::Capability(DefMO.
getImm()));
589 MAI.setSkipEmission(&
MI);
594 if (DefMO.
isReg() && isDeclSection(
MRI,
MI) &&
595 !MAI.hasRegisterAlias(MF, DefMO.
getReg()))
596 visitDecl(
MRI, SignatureToGReg, GlobalToGReg, MF,
MI);
601 const MachineOperand &InvokeMO =
MI.getOperand(InvokeIdx);
602 if (InvokeMO.
isReg()) {
604 if (!MAI.hasRegisterAlias(MF, InvokeReg)) {
605 if (
const MachineInstr *
DefMI =
609 if (GR->getFunctionDefinitionByUse(FunPtrOp))
610 visitFunPtrUse(InvokeReg, FunPtrOp, SignatureToGReg,
629 if (
MI.getOpcode() == SPIRV::OpDecorate) {
631 auto Dec =
MI.getOperand(1).getImm();
632 if (Dec == SPIRV::Decoration::LinkageAttributes) {
633 auto Lnk =
MI.getOperand(
MI.getNumOperands() - 1).getImm();
634 if (Lnk == SPIRV::LinkageType::Import) {
639 MAI.GlobalObjMap[ImportedFunc] =
640 MAI.getRegisterAlias(
MI.getMF(), Target);
643 }
else if (
MI.getOpcode() == SPIRV::OpFunction) {
646 MCRegister GlobalReg = MAI.getRegisterAlias(
MI.getMF(),
Reg);
648 MAI.GlobalObjMap[
F] = GlobalReg;
660 auto FoundMI = IS.insert(std::move(MISign));
661 if (!FoundMI.second) {
662 if (
MI.getOpcode() == SPIRV::OpDecorate) {
664 "Decoration instructions must have at least 2 operands");
666 "Only OpDecorate instructions can be duplicates");
671 if (
MI.getOperand(1).getImm() != SPIRV::Decoration::FPFastMathMode)
677 assert(OrigMI->getNumOperands() ==
MI.getNumOperands() &&
678 "Original instruction must have the same number of operands");
680 OrigMI->getNumOperands() == 3 &&
681 "FPFastMathMode decoration must have 3 operands for OpDecorate");
682 unsigned OrigFlags = OrigMI->getOperand(2).getImm();
683 unsigned NewFlags =
MI.getOperand(2).getImm();
684 if (OrigFlags == NewFlags)
688 unsigned FinalFlags = OrigFlags | NewFlags;
690 <<
"Warning: Conflicting FPFastMathMode decoration flags "
692 << *OrigMI <<
"Original flags: " << OrigFlags
693 <<
", new flags: " << NewFlags
694 <<
". They will be merged on a best effort basis, but not "
695 "validated. Final flags: "
696 << FinalFlags <<
"\n";
703 assert(
false &&
"No original instruction found for the duplicate "
704 "OpDecorate, but we found one in IS.");
717void SPIRVModuleAnalysisImpl::processOtherInstrs(
const Module &M) {
720 if (
F.isDeclaration())
725 for (MachineBasicBlock &
MBB : *MF)
726 for (MachineInstr &
MI :
MBB) {
727 if (
MI.isDebugValueLike()) {
728 MAI.DebugValueMIs.push_back(&
MI);
731 if (MAI.getSkipEmission(&
MI))
733 const unsigned OpCode =
MI.getOpcode();
734 if (OpCode == SPIRV::OpString) {
736 }
else if (OpCode == SPIRV::OpExtInst &&
MI.getOperand(2).isImm() &&
737 MI.getOperand(2).getImm() ==
738 SPIRV::InstructionSet::
739 NonSemantic_Shader_DebugInfo_100) {
746 MachineOperand Ins =
MI.getOperand(3);
747 namespace NS = SPIRV::NonSemanticExtInst;
748 static constexpr int64_t GlobalNonSemanticDITy[] = {
749 NS::DebugSource, NS::DebugCompilationUnit, NS::DebugInfoNone,
750 NS::DebugTypeBasic, NS::DebugTypePointer};
751 bool IsGlobalDI =
false;
752 for (
unsigned Idx = 0;
Idx < std::size(GlobalNonSemanticDITy); ++
Idx)
753 IsGlobalDI |= Ins.
getImm() == GlobalNonSemanticDITy[
Idx];
756 }
else if (OpCode == SPIRV::OpName || OpCode == SPIRV::OpMemberName) {
758 }
else if (OpCode == SPIRV::OpEntryPoint) {
760 }
else if (TII->isAliasingInstr(
MI)) {
762 }
else if (TII->isDecorationInstr(
MI)) {
763 if (
MI.getOpcode() == SPIRV::OpDecorate &&
764 MI.getOperand(1).getImm() ==
765 static_cast<unsigned>(
766 SPIRV::Decoration::AuxDataInstructionMetadata)) {
767 MAI.setSkipEmission(&
MI);
771 StringSwitch<std::optional<AMDMD>>(Str)
772 .Case(
"amdgpu.no.fine.grained.memory",
773 AMDMD::NoFineGrainedMemory)
774 .Case(
"amdgpu.no.remote.memory", AMDMD::NoRemoteMemory)
775 .Case(
"atomic.ignore.denormal.mode",
776 AMDMD::IgnoreDenormalMode)
777 .Default(std::nullopt);
779 MAI.InstrAuxDataRecords.push_back(
780 {MF,
MI.getOperand(0).getReg(), *MaybeKind});
784 collectFuncNames(
MI, &
F);
785 }
else if (TII->isConstantInstr(
MI)) {
789 }
else if (OpCode == SPIRV::OpFunction) {
790 collectFuncNames(
MI, &
F);
791 }
else if (OpCode == SPIRV::OpTypeForwardPointer) {
799 auto AliasingTier = [](
const MachineInstr *
MI) {
800 switch (
MI->getOpcode()) {
801 case SPIRV::OpAliasDomainDeclINTEL:
803 case SPIRV::OpAliasScopeDeclINTEL:
805 case SPIRV::OpAliasScopeListDeclINTEL:
812 [&](
const MachineInstr *
LHS,
const MachineInstr *
RHS) {
813 return AliasingTier(LHS) < AliasingTier(RHS);
820void SPIRVModuleAnalysisImpl::numberRegistersGlobally(
const Module &M) {
822 if (
F.isDeclaration())
826 for (MachineBasicBlock &
MBB : *MF) {
827 for (MachineInstr &
MI :
MBB) {
828 for (MachineOperand &
Op :
MI.operands()) {
832 if (MAI.hasRegisterAlias(MF,
Reg))
834 MCRegister NewReg = MAI.getNextIDRegister();
835 MAI.setRegisterAlias(MF,
Reg, NewReg);
837 if (
MI.getOpcode() != SPIRV::OpExtInst)
839 auto Set =
MI.getOperand(2).getImm();
840 auto [It,
Inserted] = MAI.ExtInstSetMap.try_emplace(Set);
842 It->second = MAI.getNextIDRegister();
853 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_quad_control))
855 "extension: SPV_KHR_quad_control",
857 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_maximal_reconvergence))
859 "extension: SPV_KHR_maximal_reconvergence",
861 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_quad_control);
862 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_maximal_reconvergence);
867 SPIRV::OperandCategory::OperandCategory Category,
uint32_t i,
869 if (Category == SPIRV::OperandCategory::ExecutionModeOperand &&
870 (i == SPIRV::ExecutionMode::QuadDerivativesKHR ||
871 i == SPIRV::ExecutionMode::RequireFullQuadsKHR))
874 if (Category == SPIRV::OperandCategory::ExecutionModeOperand &&
875 i == SPIRV::ExecutionMode::DerivativeGroupQuadsKHR &&
876 !ST.canUseExtension(SPIRV::Extension::SPV_KHR_compute_shader_derivatives))
878 "DerivativeGroupQuadsKHR requires the following SPIR-V extension: "
879 "SPV_KHR_compute_shader_derivatives",
884void SPIRV::RequirementHandler::recursiveAddCapabilities(
886 for (
const auto &Cap : ToPrune) {
890 recursiveAddCapabilities(ImplicitDecls);
895 for (
const auto &Cap : ToAdd) {
896 bool IsNewlyInserted = AllCaps.insert(Cap).second;
897 if (!IsNewlyInserted)
901 recursiveAddCapabilities(ImplicitDecls);
902 MinimalCaps.push_back(Cap);
911 if (Req.
Cap.has_value())
917 if (!MaxVersion.empty() && Req.
MinVer > MaxVersion) {
919 <<
" and <= " << MaxVersion <<
"\n");
923 if (MinVersion.empty() || Req.
MinVer > MinVersion)
928 if (!MinVersion.empty() && Req.
MaxVer < MinVersion) {
930 <<
" and >= " << MinVersion <<
"\n");
934 if (MaxVersion.empty() || Req.
MaxVer < MaxVersion)
942 bool IsSatisfiable =
true;
943 auto TargetVer = ST.getSPIRVVersion();
945 if (!MaxVersion.empty() && !TargetVer.empty() && MaxVersion < TargetVer) {
947 dbgs() <<
"Target SPIR-V version too high for required features\n"
948 <<
"Required max version: " << MaxVersion <<
" target version "
949 << TargetVer <<
"\n");
950 IsSatisfiable =
false;
953 if (!MinVersion.empty() && !TargetVer.empty() && MinVersion > TargetVer) {
954 LLVM_DEBUG(
dbgs() <<
"Target SPIR-V version too low for required features\n"
955 <<
"Required min version: " << MinVersion
956 <<
" target version " << TargetVer <<
"\n");
957 IsSatisfiable =
false;
960 if (!MinVersion.empty() && !MaxVersion.empty() && MinVersion > MaxVersion) {
963 <<
"Version is too low for some features and too high for others.\n"
964 <<
"Required SPIR-V min version: " << MinVersion
965 <<
" required SPIR-V max version " << MaxVersion <<
"\n");
966 IsSatisfiable =
false;
969 for (
auto Cap : MinimalCaps) {
974 OperandCategory::CapabilityOperand, Cap)
976 IsSatisfiable =
false;
979 for (
auto Ext : AllExtensions) {
980 if (ST.canUseExtension(Ext))
984 OperandCategory::ExtensionOperand, Ext)
986 IsSatisfiable =
false;
995 for (
const auto Cap : ToAdd)
996 if (AvailableCaps.insert(Cap).second)
998 SPIRV::OperandCategory::CapabilityOperand, Cap));
1002 const Capability::Capability
ToRemove,
1003 const Capability::Capability IfPresent) {
1004 if (AllCaps.contains(IfPresent)) {
1014 addAvailableCaps({Capability::Shader, Capability::Linkage, Capability::Int8,
1015 Capability::Int16});
1019 Capability::GroupNonUniformVote,
1020 Capability::GroupNonUniformArithmetic,
1021 Capability::GroupNonUniformBallot,
1022 Capability::GroupNonUniformClustered,
1023 Capability::GroupNonUniformShuffle,
1024 Capability::GroupNonUniformShuffleRelative,
1025 Capability::GroupNonUniformQuad});
1029 Capability::DotProductInput4x8Bit,
1030 Capability::DotProductInput4x8BitPacked,
1031 Capability::DemoteToHelperInvocation});
1034 for (
auto Extension : ST.getAllAvailableExtensions()) {
1041 if (ST.canUseExtension(Extension::SPV_EXT_shader_subgroup_partitioned))
1044 if (!ST.isShader()) {
1045 initAvailableCapabilitiesForOpenCL(ST);
1049 if (ST.isShader()) {
1050 initAvailableCapabilitiesForVulkan(ST);
1057void RequirementHandler::initAvailableCapabilitiesForOpenCL(
1061 Capability::Kernel, Capability::Vector16,
1062 Capability::Groups, Capability::GenericPointer,
1063 Capability::StorageImageWriteWithoutFormat,
1064 Capability::StorageImageReadWithoutFormat});
1065 if (ST.hasOpenCLFullProfile())
1067 if (ST.hasOpenCLImageSupport()) {
1069 Capability::Image1D, Capability::SampledBuffer,
1070 Capability::ImageBuffer});
1071 if (
ST.isAtLeastOpenCLVer(VersionTuple(2, 0)))
1074 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 1)) &&
1075 ST.isAtLeastOpenCLVer(VersionTuple(2, 2)))
1077 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 4)))
1078 addAvailableCaps({Capability::DenormPreserve, Capability::DenormFlushToZero,
1079 Capability::SignedZeroInfNanPreserve,
1080 Capability::RoundingModeRTE,
1081 Capability::RoundingModeRTZ});
1088void RequirementHandler::initAvailableCapabilitiesForVulkan(
1089 const SPIRVSubtarget &ST) {
1093 Capability::Geometry,
1094 Capability::Float16,
1095 Capability::Float64,
1096 Capability::GroupNonUniform,
1097 Capability::Image1D,
1098 Capability::SampledBuffer,
1099 Capability::ImageBuffer,
1100 Capability::UniformBufferArrayDynamicIndexing,
1101 Capability::SampledImageArrayDynamicIndexing,
1102 Capability::StorageBufferArrayDynamicIndexing,
1103 Capability::StorageImageArrayDynamicIndexing,
1104 Capability::DerivativeControl,
1105 Capability::SampleRateShading,
1107 Capability::ImageQuery,
1108 Capability::ImageGatherExtended,
1109 Capability::Addresses,
1110 Capability::VulkanMemoryModelKHR,
1111 Capability::StorageImageExtendedFormats,
1112 Capability::StorageImageMultisample,
1113 Capability::ImageMSArray});
1115 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 3)) ||
1116 ST.canUseExtension(Extension::SPV_KHR_variable_pointers))
1118 Capability::VariablePointers});
1121 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 3)))
1125 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 5))) {
1127 {Capability::Int64Atomics, Capability::ShaderNonUniformEXT,
1128 Capability::RuntimeDescriptorArrayEXT,
1129 Capability::InputAttachmentArrayDynamicIndexingEXT,
1130 Capability::UniformTexelBufferArrayDynamicIndexingEXT,
1131 Capability::StorageTexelBufferArrayDynamicIndexingEXT,
1132 Capability::UniformBufferArrayNonUniformIndexingEXT,
1133 Capability::SampledImageArrayNonUniformIndexingEXT,
1134 Capability::StorageBufferArrayNonUniformIndexingEXT,
1135 Capability::StorageImageArrayNonUniformIndexingEXT,
1136 Capability::InputAttachmentArrayNonUniformIndexingEXT,
1137 Capability::UniformTexelBufferArrayNonUniformIndexingEXT,
1138 Capability::StorageTexelBufferArrayNonUniformIndexingEXT});
1142 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 6)))
1144 Capability::StorageImageReadWithoutFormat});
1154 SPIRV::Capability::Capability Cap,
1155 SPIRV::Extension::Extension Ext) {
1159 if (!ST.canUseExtension(Ext))
1161 Twine(
"capability ") +
1163 SPIRV::OperandCategory::CapabilityOperand, Cap) +
1164 " requires SPIR-V 1.3 or the following SPIR-V extension: " +
1176 int64_t DecOp =
MI.getOperand(DecIndex).getImm();
1177 auto Dec =
static_cast<SPIRV::Decoration::Decoration
>(DecOp);
1179 SPIRV::OperandCategory::DecorationOperand, Dec, ST, Reqs));
1181 if (Dec == SPIRV::Decoration::BuiltIn) {
1182 int64_t BuiltInOp =
MI.getOperand(DecIndex + 1).getImm();
1183 auto BuiltIn =
static_cast<SPIRV::BuiltIn::BuiltIn
>(BuiltInOp);
1184 if ((BuiltIn == SPIRV::BuiltIn::BaryCoordKHR ||
1185 BuiltIn == SPIRV::BuiltIn::BaryCoordNoPerspKHR) &&
1186 !ST.canUseExtension(
1187 SPIRV::Extension::SPV_KHR_fragment_shader_barycentric))
1189 "Barycentric built-ins require the following SPIR-V extension: "
1190 "SPV_KHR_fragment_shader_barycentric",
1193 case SPIRV::BuiltIn::BaseVertex:
1194 case SPIRV::BuiltIn::BaseInstance:
1196 Reqs, ST, SPIRV::Capability::DrawParameters,
1197 SPIRV::Extension::SPV_KHR_shader_draw_parameters);
1199 case SPIRV::BuiltIn::ViewIndex:
1201 SPIRV::Extension::SPV_KHR_multiview);
1205 SPIRV::OperandCategory::BuiltInOperand, BuiltIn, ST, Reqs));
1208 }
else if (Dec == SPIRV::Decoration::LinkageAttributes) {
1209 int64_t LinkageOp =
MI.getOperand(
MI.getNumOperands() - 1).getImm();
1210 SPIRV::LinkageType::LinkageType LnkType =
1211 static_cast<SPIRV::LinkageType::LinkageType
>(LinkageOp);
1212 if (LnkType == SPIRV::LinkageType::LinkOnceODR)
1213 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_linkonce_odr);
1214 else if (LnkType == SPIRV::LinkageType::WeakAMD) {
1215 Reqs.
addExtension(SPIRV::Extension::SPV_AMD_weak_linkage);
1218 }
else if (Dec == SPIRV::Decoration::CacheControlLoadINTEL ||
1219 Dec == SPIRV::Decoration::CacheControlStoreINTEL) {
1220 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_cache_controls);
1221 }
else if (Dec == SPIRV::Decoration::HostAccessINTEL) {
1222 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_global_variable_host_access);
1223 }
else if (Dec == SPIRV::Decoration::InitModeINTEL ||
1224 Dec == SPIRV::Decoration::ImplementInRegisterMapINTEL) {
1226 SPIRV::Extension::SPV_INTEL_global_variable_fpga_decorations);
1227 }
else if (Dec == SPIRV::Decoration::NonUniformEXT) {
1229 }
else if (Dec == SPIRV::Decoration::FPMaxErrorDecorationINTEL) {
1231 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_fp_max_error);
1232 }
else if (Dec == SPIRV::Decoration::FPFastMathMode) {
1233 if (ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2)) {
1235 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_float_controls2);
1244 assert(
MI.getNumOperands() >= 8 &&
"Insufficient operands for OpTypeImage");
1247 int64_t ImgFormatOp =
MI.getOperand(7).getImm();
1248 auto ImgFormat =
static_cast<SPIRV::ImageFormat::ImageFormat
>(ImgFormatOp);
1252 bool IsArrayed =
MI.getOperand(4).getImm() == 1;
1253 bool IsMultisampled =
MI.getOperand(5).getImm() == 1;
1254 bool NoSampler =
MI.getOperand(6).getImm() == 2;
1257 switch (
MI.getOperand(2).getImm()) {
1258 case SPIRV::Dim::DIM_1D:
1260 : SPIRV::Capability::Sampled1D);
1262 case SPIRV::Dim::DIM_2D:
1263 if (IsMultisampled && NoSampler)
1265 if (IsMultisampled && IsArrayed)
1268 case SPIRV::Dim::DIM_3D:
1270 case SPIRV::Dim::DIM_Cube:
1274 : SPIRV::Capability::SampledCubeArray);
1276 case SPIRV::Dim::DIM_Rect:
1278 : SPIRV::Capability::SampledRect);
1280 case SPIRV::Dim::DIM_Buffer:
1282 : SPIRV::Capability::SampledBuffer);
1284 case SPIRV::Dim::DIM_SubpassData:
1290 if (!ST.isShader()) {
1291 if (
MI.getNumOperands() > 8 &&
1292 MI.getOperand(8).getImm() == SPIRV::AccessQualifier::ReadWrite)
1301 TypeDef->
getOpcode() == SPIRV::OpTypeFloat &&
1313 return MRI.getVRegDef(
MRI.getVRegDef(
Reg)->getOperand(1).getReg());
1317#define ATOM_FLT_REQ_EXT_MSG(ExtName) \
1318 "The atomic float instruction requires the following SPIR-V " \
1319 "extension: SPV_EXT_shader_atomic_float" ExtName
1324 MI.getMF()->getRegInfo().getVRegDef(
MI.getOperand(1).getReg());
1327 if (Rank != 2 && Rank != 4)
1329 "must be a 2-component or 4 component vector");
1334 if (EltTypeDef->
getOpcode() != SPIRV::OpTypeFloat ||
1337 "The element type for the result type of an atomic vector float "
1338 "instruction must be a 16-bit floating-point scalar");
1345 "The element type for the result type of an atomic vector float "
1346 "instruction cannot be a bfloat16 scalar");
1347 if (!ST.canUseExtension(SPIRV::Extension::SPV_NV_shader_atomic_fp16_vector))
1349 "The atomic float16 vector instruction requires the following SPIR-V "
1350 "extension: SPV_NV_shader_atomic_fp16_vector");
1352 Reqs.
addExtension(SPIRV::Extension::SPV_NV_shader_atomic_fp16_vector);
1353 Reqs.
addCapability(SPIRV::Capability::AtomicFloat16VectorNV);
1360 "Expect register operand in atomic float instruction");
1361 Register TypeReg =
MI.getOperand(1).getReg();
1367 if (TypeDef->
getOpcode() != SPIRV::OpTypeFloat)
1369 "floating-point type scalar");
1372 unsigned Op =
MI.getOpcode();
1373 if (
Op == SPIRV::OpAtomicFAddEXT) {
1374 if (!ST.canUseExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float_add))
1376 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float_add);
1380 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics))
1382 "The atomic bfloat16 instruction requires the following SPIR-V "
1383 "extension: SPV_INTEL_16bit_atomics",
1385 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics);
1386 Reqs.
addCapability(SPIRV::Capability::AtomicBFloat16AddINTEL);
1388 if (!ST.canUseExtension(
1389 SPIRV::Extension::SPV_EXT_shader_atomic_float16_add))
1391 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float16_add);
1403 "Unexpected floating-point type width in atomic float instruction");
1406 if (!ST.canUseExtension(
1407 SPIRV::Extension::SPV_EXT_shader_atomic_float_min_max))
1409 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float_min_max);
1413 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics))
1415 "The atomic bfloat16 instruction requires the following SPIR-V "
1416 "extension: SPV_INTEL_16bit_atomics",
1418 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics);
1419 Reqs.
addCapability(SPIRV::Capability::AtomicBFloat16MinMaxINTEL);
1421 Reqs.
addCapability(SPIRV::Capability::AtomicFloat16MinMaxEXT);
1425 Reqs.
addCapability(SPIRV::Capability::AtomicFloat32MinMaxEXT);
1428 Reqs.
addCapability(SPIRV::Capability::AtomicFloat64MinMaxEXT);
1432 "Unexpected floating-point type width in atomic float instruction");
1438 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1442 return Dim == SPIRV::Dim::DIM_Buffer && Sampled == 1;
1446 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1450 return Dim == SPIRV::Dim::DIM_Buffer && Sampled == 2;
1454 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1458 return Dim != SPIRV::Dim::DIM_Buffer && Sampled == 1;
1462 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1466 return Dim == SPIRV::Dim::DIM_SubpassData && Sampled == 2;
1470 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1474 return Dim != SPIRV::Dim::DIM_Buffer && Sampled == 2;
1478 if (SampledImageInst->
getOpcode() != SPIRV::OpTypeSampledImage)
1483 auto *ImageInst =
MRI.getUniqueVRegDef(ImageReg);
1488 for (
const auto &
MI :
MRI.reg_instructions(
Reg)) {
1489 if (
MI.getOpcode() != SPIRV::OpDecorate)
1493 if (Dec == SPIRV::Decoration::NonUniformEXT)
1506 Register ResTypeReg = Instr.getOperand(1).getReg();
1511 if (
StorageClass != SPIRV::StorageClass::StorageClass::UniformConstant &&
1512 StorageClass != SPIRV::StorageClass::StorageClass::Uniform &&
1513 StorageClass != SPIRV::StorageClass::StorageClass::StorageBuffer) {
1520 auto FirstIndexReg = Instr.getOperand(3).getReg();
1521 bool FirstIndexIsConstant =
1522 Subtarget.getInstrInfo()->isConstantInstr(*
MRI.getVRegDef(FirstIndexReg));
1524 if (
StorageClass == SPIRV::StorageClass::StorageClass::StorageBuffer) {
1527 SPIRV::Capability::StorageBufferArrayNonUniformIndexingEXT);
1528 else if (!FirstIndexIsConstant)
1530 SPIRV::Capability::StorageBufferArrayDynamicIndexing);
1536 if (PointeeType->
getOpcode() != SPIRV::OpTypeImage &&
1537 PointeeType->
getOpcode() != SPIRV::OpTypeSampledImage &&
1538 PointeeType->
getOpcode() != SPIRV::OpTypeSampler) {
1545 SPIRV::Capability::UniformTexelBufferArrayNonUniformIndexingEXT);
1546 else if (!FirstIndexIsConstant)
1548 SPIRV::Capability::UniformTexelBufferArrayDynamicIndexingEXT);
1552 SPIRV::Capability::InputAttachmentArrayNonUniformIndexingEXT);
1553 else if (!FirstIndexIsConstant)
1555 SPIRV::Capability::InputAttachmentArrayDynamicIndexingEXT);
1559 SPIRV::Capability::StorageTexelBufferArrayNonUniformIndexingEXT);
1560 else if (!FirstIndexIsConstant)
1562 SPIRV::Capability::StorageTexelBufferArrayDynamicIndexingEXT);
1565 PointeeType->
getOpcode() == SPIRV::OpTypeSampler) {
1568 SPIRV::Capability::SampledImageArrayNonUniformIndexingEXT);
1569 else if (!FirstIndexIsConstant)
1571 SPIRV::Capability::SampledImageArrayDynamicIndexing);
1575 SPIRV::Capability::StorageImageArrayNonUniformIndexingEXT);
1576 else if (!FirstIndexIsConstant)
1578 SPIRV::Capability::StorageImageArrayDynamicIndexing);
1583 if (TypeInst->
getOpcode() != SPIRV::OpTypeImage)
1592 if (ST.canUseExtension(SPIRV::Extension::SPV_KHR_integer_dot_product))
1593 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_integer_dot_product);
1597 assert(
MI.getOperand(2).isReg() &&
"Unexpected operand in dot");
1599 ST.getSPIRVGlobalRegistry());
1600 assert(TypeDef &&
"Unexpected type instruction for dot input");
1601 if (TypeDef->
getOpcode() == SPIRV::OpTypeInt) {
1603 Reqs.
addCapability(SPIRV::Capability::DotProductInput4x8BitPacked);
1610 "Dot operand of 8-bit integer type requires 4 components");
1611 Reqs.
addCapability(SPIRV::Capability::DotProductInput4x8Bit);
1627 unsigned AddrSpace = ASOp.
getImm();
1628 if (AddrSpace != SPIRV::StorageClass::UniformConstant) {
1629 if (!ST.canUseExtension(
1631 SPV_EXT_relaxed_printf_string_address_space)) {
1633 "required because printf uses a format string not "
1634 "in constant address space.",
1638 SPIRV::Extension::SPV_EXT_relaxed_printf_string_address_space);
1647 if (
MI.getNumOperands() <= OpIdx)
1649 uint32_t Mask =
MI.getOperand(OpIdx).getImm();
1651 if (Mask & (1U <<
I))
1662 if (ElemTypeDef->
getOpcode() == SPIRV::OpTypePointer &&
1663 ST.canUseExtension(SPIRV::Extension::SPV_INTEL_masked_gather_scatter)) {
1664 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_masked_gather_scatter);
1665 Reqs.
addCapability(SPIRV::Capability::MaskedGatherScatterINTEL);
1673 unsigned Op =
MI.getOpcode();
1675 case SPIRV::OpMemoryModel: {
1676 int64_t Addr =
MI.getOperand(0).getImm();
1679 int64_t Mem =
MI.getOperand(1).getImm();
1684 case SPIRV::OpEntryPoint: {
1685 int64_t Exe =
MI.getOperand(0).getImm();
1690 case SPIRV::OpExecutionMode:
1691 case SPIRV::OpExecutionModeId: {
1692 int64_t Exe =
MI.getOperand(1).getImm();
1697 case SPIRV::OpTypeMatrix:
1700 case SPIRV::OpTypeInt: {
1701 unsigned BitWidth =
MI.getOperand(1).getImm();
1709 ST.canUseExtension(SPIRV::Extension::SPV_INTEL_int4)) {
1713 if (!ST.canUseExtension(
1714 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_integers))
1716 "OpTypeInt type with a width other than 8, 16, 32 or 64 bits "
1717 "requires the following SPIR-V extension: "
1718 "SPV_ALTERA_arbitrary_precision_integers");
1720 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_integers);
1721 Reqs.
addCapability(SPIRV::Capability::ArbitraryPrecisionIntegersALTERA);
1725 case SPIRV::OpDot: {
1729 Reqs.
addCapability(SPIRV::Capability::BFloat16DotProductKHR);
1732 case SPIRV::OpTypeFloat: {
1733 unsigned BitWidth =
MI.getOperand(1).getImm();
1738 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_bfloat16))
1740 "following SPIR-V extension: SPV_KHR_bfloat16",
1750 case SPIRV::OpTypeVector: {
1751 unsigned NumComponents =
MI.getOperand(2).getImm();
1752 if (NumComponents == 8 || NumComponents == 16)
1757 "OpTypeVector with " +
Twine(NumComponents) +
1758 " components requires the following SPIR-V extension: "
1759 "SPV_EXT_long_vector");
1764 case SPIRV::OpTypeVectorIdEXT: {
1765 if (!ST.canUseExtension(SPIRV::Extension::SPV_EXT_long_vector))
1767 "extension: SPV_EXT_long_vector extension");
1768 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_long_vector);
1773 case SPIRV::OpTypePointer: {
1774 auto SC =
MI.getOperand(1).getImm();
1785 (TypeDef->
getOpcode() == SPIRV::OpTypeFloat) &&
1790 case SPIRV::OpExtInst: {
1791 if (
MI.getOperand(2).getImm() ==
1792 static_cast<int64_t
>(
1793 SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100)) {
1794 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_non_semantic_info);
1797 if (
MI.getOperand(2).getImm() ==
1798 static_cast<int64_t
>(SPIRV::InstructionSet::NonSemantic_DebugBreak)) {
1802 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_non_semantic_info);
1805 if (
MI.getOperand(3).getImm() ==
1806 static_cast<int64_t
>(SPIRV::OpenCLExtInst::printf)) {
1810 if (
MI.getOperand(2).getImm() ==
1811 static_cast<int64_t
>(SPIRV::InstructionSet::OpenCL_std)) {
1817 if (TypeDef && TypeDef->getOpcode() == SPIRV::OpTypeVector)
1818 TypeDef =
MRI.getVRegDef(TypeDef->getOperand(1).getReg());
1823 bool UsesBFloat16 = IsBFloat16(
MRI.getVRegDef(
MI.getOperand(1).getReg()));
1824 for (
unsigned I = 4,
E =
MI.getNumOperands();
I <
E && !UsesBFloat16;
1833 if (!ST.canUseExtension(
1834 SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic)) {
1836 MI,
"OpenCL Extended instructions with bfloat16 require the "
1837 "following SPIR-V extension: SPV_INTEL_bfloat16_arithmetic");
1840 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic);
1841 Reqs.
addCapability(SPIRV::Capability::BFloat16ArithmeticINTEL);
1846 case SPIRV::OpAliasDomainDeclINTEL:
1847 case SPIRV::OpAliasScopeDeclINTEL:
1848 case SPIRV::OpAliasScopeListDeclINTEL: {
1849 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_memory_access_aliasing);
1850 Reqs.
addCapability(SPIRV::Capability::MemoryAccessAliasingINTEL);
1853 case SPIRV::OpBitReverse:
1854 case SPIRV::OpBitFieldInsert:
1855 case SPIRV::OpBitFieldSExtract:
1856 case SPIRV::OpBitFieldUExtract:
1857 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_bit_instructions)) {
1861 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_bit_instructions);
1864 case SPIRV::OpTypeRuntimeArray:
1867 case SPIRV::OpTypeOpaque:
1868 case SPIRV::OpTypeEvent:
1871 case SPIRV::OpTypePipe:
1872 case SPIRV::OpTypeReserveId:
1875 case SPIRV::OpTypePipeStorage:
1878 case SPIRV::OpTypeDeviceEvent:
1879 case SPIRV::OpTypeQueue:
1880 case SPIRV::OpBuildNDRange:
1881 case SPIRV::OpEnqueueKernel:
1882 case SPIRV::OpGetKernelNDrangeSubGroupCount:
1883 case SPIRV::OpGetKernelNDrangeMaxSubGroupSize:
1884 case SPIRV::OpGetKernelWorkGroupSize:
1885 case SPIRV::OpGetKernelPreferredWorkGroupSizeMultiple:
1888 case SPIRV::OpDecorate:
1889 case SPIRV::OpDecorateId:
1890 case SPIRV::OpDecorateString:
1893 case SPIRV::OpMemberDecorate:
1894 case SPIRV::OpMemberDecorateString:
1897 case SPIRV::OpInBoundsPtrAccessChain:
1900 case SPIRV::OpConstantSampler:
1903 case SPIRV::OpInBoundsAccessChain:
1904 case SPIRV::OpAccessChain:
1907 case SPIRV::OpTypeImage:
1910 case SPIRV::OpTypeSampler:
1911 if (!ST.isShader()) {
1915 case SPIRV::OpTypeForwardPointer:
1919 case SPIRV::OpAtomicFlagTestAndSet:
1920 case SPIRV::OpAtomicLoad:
1921 case SPIRV::OpAtomicStore:
1922 case SPIRV::OpAtomicExchange:
1923 case SPIRV::OpAtomicCompareExchange:
1924 case SPIRV::OpAtomicCompareExchangeWeak:
1925 case SPIRV::OpAtomicIIncrement:
1926 case SPIRV::OpAtomicIDecrement:
1927 case SPIRV::OpAtomicIAdd:
1928 case SPIRV::OpAtomicISub:
1929 case SPIRV::OpAtomicUMin:
1930 case SPIRV::OpAtomicUMax:
1931 case SPIRV::OpAtomicSMin:
1932 case SPIRV::OpAtomicSMax:
1933 case SPIRV::OpAtomicAnd:
1934 case SPIRV::OpAtomicOr:
1935 case SPIRV::OpAtomicXor: {
1938 if (
Op == SPIRV::OpAtomicStore) {
1941 ST.getSPIRVGlobalRegistry());
1942 assert(TypeDef &&
"Unexpected type instruction for OpAtomicStore");
1944 assert(
MI.getOperand(1).isReg() &&
"Unexpected operand in atomic");
1945 TypeDef =
MRI.getVRegDef(
MI.getOperand(1).getReg());
1948 if (TypeDef->
getOpcode() == SPIRV::OpTypeInt) {
1953 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics))
1955 "16-bit integer atomic operations require the following SPIR-V "
1956 "extension: SPV_INTEL_16bit_atomics",
1958 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics);
1960 case SPIRV::OpAtomicLoad:
1961 case SPIRV::OpAtomicStore:
1962 case SPIRV::OpAtomicExchange:
1963 case SPIRV::OpAtomicCompareExchange:
1964 case SPIRV::OpAtomicCompareExchangeWeak:
1966 SPIRV::Capability::AtomicInt16CompareExchangeINTEL);
1974 if (
is_contained({SPIRV::OpAtomicLoad, SPIRV::OpAtomicStore,
1975 SPIRV::OpAtomicExchange},
1977 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics))
1979 "The atomic bfloat16 instruction requires the following SPIR-V "
1980 "extension: SPV_INTEL_16bit_atomics",
1982 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics);
1983 Reqs.
addCapability(SPIRV::Capability::AtomicBFloat16LoadStoreINTEL);
1988 case SPIRV::OpGroupNonUniformIAdd:
1989 case SPIRV::OpGroupNonUniformFAdd:
1990 case SPIRV::OpGroupNonUniformIMul:
1991 case SPIRV::OpGroupNonUniformFMul:
1992 case SPIRV::OpGroupNonUniformSMin:
1993 case SPIRV::OpGroupNonUniformUMin:
1994 case SPIRV::OpGroupNonUniformFMin:
1995 case SPIRV::OpGroupNonUniformSMax:
1996 case SPIRV::OpGroupNonUniformUMax:
1997 case SPIRV::OpGroupNonUniformFMax:
1998 case SPIRV::OpGroupNonUniformBitwiseAnd:
1999 case SPIRV::OpGroupNonUniformBitwiseOr:
2000 case SPIRV::OpGroupNonUniformBitwiseXor:
2001 case SPIRV::OpGroupNonUniformLogicalAnd:
2002 case SPIRV::OpGroupNonUniformLogicalOr:
2003 case SPIRV::OpGroupNonUniformLogicalXor: {
2005 int64_t GroupOp =
MI.getOperand(3).getImm();
2007 case SPIRV::GroupOperation::Reduce:
2008 case SPIRV::GroupOperation::InclusiveScan:
2009 case SPIRV::GroupOperation::ExclusiveScan:
2010 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformArithmetic);
2012 case SPIRV::GroupOperation::ClusteredReduce:
2013 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformClustered);
2015 case SPIRV::GroupOperation::PartitionedReduceNV:
2016 case SPIRV::GroupOperation::PartitionedInclusiveScanNV:
2017 case SPIRV::GroupOperation::PartitionedExclusiveScanNV:
2018 if (ST.canUseExtension(
2019 SPIRV::Extension::SPV_EXT_shader_subgroup_partitioned))
2021 SPIRV::Extension::SPV_EXT_shader_subgroup_partitioned);
2023 Reqs.
addExtension(SPIRV::Extension::SPV_NV_shader_subgroup_partitioned);
2024 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformPartitionedNV);
2029 case SPIRV::OpGroupNonUniformQuadSwap:
2032 case SPIRV::OpImageQueryLod:
2035 case SPIRV::OpImageQuerySize:
2036 case SPIRV::OpImageQuerySizeLod:
2037 case SPIRV::OpImageQueryLevels:
2038 case SPIRV::OpImageQuerySamples:
2042 case SPIRV::OpImageQueryFormat: {
2043 Register ResultReg =
MI.getOperand(0).getReg();
2045 static const unsigned CompareOps[] = {
2046 SPIRV::OpIEqual, SPIRV::OpINotEqual,
2047 SPIRV::OpUGreaterThan, SPIRV::OpUGreaterThanEqual,
2048 SPIRV::OpULessThan, SPIRV::OpULessThanEqual,
2049 SPIRV::OpSGreaterThan, SPIRV::OpSGreaterThanEqual,
2050 SPIRV::OpSLessThan, SPIRV::OpSLessThanEqual};
2052 auto CheckAndAddExtension = [&](int64_t ImmVal) {
2053 if (ImmVal == 4323 || ImmVal == 4324) {
2054 if (ST.canUseExtension(SPIRV::Extension::SPV_EXT_image_raw10_raw12))
2055 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_image_raw10_raw12);
2058 "SPV_EXT_image_raw10_raw12 extension");
2063 unsigned Opc = UseInst.getOpcode();
2065 if (
Opc == SPIRV::OpSwitch) {
2068 CheckAndAddExtension(
Op.getImm());
2070 for (
unsigned i = 1; i < UseInst.getNumOperands(); ++i) {
2073 if (ConstInst && ConstInst->
getOpcode() == SPIRV::OpConstantI) {
2076 CheckAndAddExtension(ImmVal);
2084 case SPIRV::OpGroupNonUniformShuffle:
2085 case SPIRV::OpGroupNonUniformShuffleXor:
2086 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformShuffle);
2088 case SPIRV::OpGroupNonUniformShuffleUp:
2089 case SPIRV::OpGroupNonUniformShuffleDown:
2090 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformShuffleRelative);
2092 case SPIRV::OpGroupAll:
2093 case SPIRV::OpGroupAny:
2094 case SPIRV::OpGroupBroadcast:
2095 case SPIRV::OpGroupIAdd:
2096 case SPIRV::OpGroupFAdd:
2097 case SPIRV::OpGroupFMin:
2098 case SPIRV::OpGroupUMin:
2099 case SPIRV::OpGroupSMin:
2100 case SPIRV::OpGroupFMax:
2101 case SPIRV::OpGroupUMax:
2102 case SPIRV::OpGroupSMax:
2105 case SPIRV::OpGroupNonUniformElect:
2108 case SPIRV::OpGroupNonUniformAll:
2109 case SPIRV::OpGroupNonUniformAny:
2110 case SPIRV::OpGroupNonUniformAllEqual:
2113 case SPIRV::OpGroupNonUniformBroadcast:
2114 case SPIRV::OpGroupNonUniformBroadcastFirst:
2115 case SPIRV::OpGroupNonUniformBallot:
2116 case SPIRV::OpGroupNonUniformInverseBallot:
2117 case SPIRV::OpGroupNonUniformBallotBitExtract:
2118 case SPIRV::OpGroupNonUniformBallotBitCount:
2119 case SPIRV::OpGroupNonUniformBallotFindLSB:
2120 case SPIRV::OpGroupNonUniformBallotFindMSB:
2121 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformBallot);
2123 case SPIRV::OpSubgroupShuffleINTEL:
2124 case SPIRV::OpSubgroupShuffleDownINTEL:
2125 case SPIRV::OpSubgroupShuffleUpINTEL:
2126 case SPIRV::OpSubgroupShuffleXorINTEL:
2127 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {
2128 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_subgroups);
2129 Reqs.
addCapability(SPIRV::Capability::SubgroupShuffleINTEL);
2132 case SPIRV::OpSubgroupBlockReadINTEL:
2133 case SPIRV::OpSubgroupBlockWriteINTEL:
2134 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {
2135 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_subgroups);
2136 Reqs.
addCapability(SPIRV::Capability::SubgroupBufferBlockIOINTEL);
2139 case SPIRV::OpSubgroupImageBlockReadINTEL:
2140 case SPIRV::OpSubgroupImageBlockWriteINTEL:
2141 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {
2142 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_subgroups);
2143 Reqs.
addCapability(SPIRV::Capability::SubgroupImageBlockIOINTEL);
2146 case SPIRV::OpSubgroupImageMediaBlockReadINTEL:
2147 case SPIRV::OpSubgroupImageMediaBlockWriteINTEL:
2148 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_media_block_io)) {
2149 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_media_block_io);
2150 Reqs.
addCapability(SPIRV::Capability::SubgroupImageMediaBlockIOINTEL);
2153 case SPIRV::OpAssumeTrueKHR:
2154 case SPIRV::OpExpectKHR:
2155 if (ST.canUseExtension(SPIRV::Extension::SPV_KHR_expect_assume)) {
2156 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_expect_assume);
2160 case SPIRV::OpFmaKHR:
2161 if (ST.canUseExtension(SPIRV::Extension::SPV_KHR_fma)) {
2166 case SPIRV::OpPtrCastToCrossWorkgroupINTEL:
2167 case SPIRV::OpCrossWorkgroupCastToPtrINTEL:
2168 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_usm_storage_classes)) {
2169 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_usm_storage_classes);
2170 Reqs.
addCapability(SPIRV::Capability::USMStorageClassesINTEL);
2173 case SPIRV::OpConstantFunctionPointerINTEL:
2174 case SPIRV::OpFunctionPointerCallINTEL:
2175 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_function_pointers)) {
2176 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_function_pointers);
2177 Reqs.
addCapability(SPIRV::Capability::FunctionPointersINTEL);
2180 case SPIRV::OpGroupNonUniformQuadAllKHR:
2184 case SPIRV::OpGroupNonUniformRotateKHR:
2185 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_subgroup_rotate))
2187 "following SPIR-V extension: SPV_KHR_subgroup_rotate",
2189 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_subgroup_rotate);
2190 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformRotateKHR);
2193 case SPIRV::OpFixedCosALTERA:
2194 case SPIRV::OpFixedSinALTERA:
2195 case SPIRV::OpFixedCosPiALTERA:
2196 case SPIRV::OpFixedSinPiALTERA:
2197 case SPIRV::OpFixedExpALTERA:
2198 case SPIRV::OpFixedLogALTERA:
2199 case SPIRV::OpFixedRecipALTERA:
2200 case SPIRV::OpFixedSqrtALTERA:
2201 case SPIRV::OpFixedSinCosALTERA:
2202 case SPIRV::OpFixedSinCosPiALTERA:
2203 case SPIRV::OpFixedRsqrtALTERA:
2204 if (!ST.canUseExtension(
2205 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_fixed_point))
2207 "following SPIR-V extension: "
2208 "SPV_ALTERA_arbitrary_precision_fixed_point",
2211 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_fixed_point);
2212 Reqs.
addCapability(SPIRV::Capability::ArbitraryPrecisionFixedPointALTERA);
2214 case SPIRV::OpGroupIMulKHR:
2215 case SPIRV::OpGroupFMulKHR:
2216 case SPIRV::OpGroupBitwiseAndKHR:
2217 case SPIRV::OpGroupBitwiseOrKHR:
2218 case SPIRV::OpGroupBitwiseXorKHR:
2219 case SPIRV::OpGroupLogicalAndKHR:
2220 case SPIRV::OpGroupLogicalOrKHR:
2221 case SPIRV::OpGroupLogicalXorKHR:
2222 if (ST.canUseExtension(
2223 SPIRV::Extension::SPV_KHR_uniform_group_instructions)) {
2224 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_uniform_group_instructions);
2225 Reqs.
addCapability(SPIRV::Capability::GroupUniformArithmeticKHR);
2228 case SPIRV::OpReadClockKHR:
2229 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_shader_clock))
2231 "following SPIR-V extension: SPV_KHR_shader_clock",
2233 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_shader_clock);
2236 case SPIRV::OpAbortKHR:
2237 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_abort))
2239 "following SPIR-V extension: SPV_KHR_abort",
2244 case SPIRV::OpPoisonKHR:
2245 case SPIRV::OpFreezeKHR:
2246 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_poison_freeze))
2248 "following SPIR-V extension: SPV_KHR_poison_freeze",
2250 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_poison_freeze);
2253 case SPIRV::OpAtomicFAddEXT:
2254 case SPIRV::OpAtomicFMinEXT:
2255 case SPIRV::OpAtomicFMaxEXT:
2258 case SPIRV::OpConvertBF16ToFINTEL:
2259 case SPIRV::OpConvertFToBF16INTEL:
2260 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bfloat16_conversion)) {
2261 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bfloat16_conversion);
2262 Reqs.
addCapability(SPIRV::Capability::BFloat16ConversionINTEL);
2265 case SPIRV::OpRoundFToTF32INTEL:
2266 if (ST.canUseExtension(
2267 SPIRV::Extension::SPV_INTEL_tensor_float32_conversion)) {
2268 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_tensor_float32_conversion);
2269 Reqs.
addCapability(SPIRV::Capability::TensorFloat32RoundingINTEL);
2272 case SPIRV::OpVariableLengthArrayINTEL:
2273 case SPIRV::OpSaveMemoryINTEL:
2274 case SPIRV::OpRestoreMemoryINTEL:
2275 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_variable_length_array)) {
2276 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_variable_length_array);
2277 Reqs.
addCapability(SPIRV::Capability::VariableLengthArrayINTEL);
2280 case SPIRV::OpUntypedVariableLengthArrayINTEL:
2281 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_variable_length_array)) {
2282 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_variable_length_array);
2283 Reqs.
addCapability(SPIRV::Capability::UntypedVariableLengthArrayINTEL);
2286 case SPIRV::OpAsmTargetINTEL:
2287 case SPIRV::OpAsmINTEL:
2288 case SPIRV::OpAsmCallINTEL:
2289 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_inline_assembly)) {
2290 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_inline_assembly);
2294 case SPIRV::OpTypeCooperativeMatrixKHR: {
2295 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix))
2297 "OpTypeCooperativeMatrixKHR type requires the "
2298 "following SPIR-V extension: SPV_KHR_cooperative_matrix",
2300 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix);
2301 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixKHR);
2305 Reqs.
addCapability(SPIRV::Capability::BFloat16CooperativeMatrixKHR);
2308 case SPIRV::OpArithmeticFenceEXT:
2309 if (!ST.canUseExtension(SPIRV::Extension::SPV_EXT_arithmetic_fence))
2311 "following SPIR-V extension: SPV_EXT_arithmetic_fence",
2313 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_arithmetic_fence);
2316 case SPIRV::OpControlBarrierArriveINTEL:
2317 case SPIRV::OpControlBarrierWaitINTEL:
2318 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_split_barrier)) {
2319 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_split_barrier);
2323 case SPIRV::OpCooperativeMatrixMulAddKHR: {
2324 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix))
2326 "following SPIR-V extension: "
2327 "SPV_KHR_cooperative_matrix",
2329 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix);
2330 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixKHR);
2331 constexpr unsigned MulAddMaxSize = 6;
2332 if (
MI.getNumOperands() != MulAddMaxSize)
2334 const int64_t CoopOperands =
MI.getOperand(MulAddMaxSize - 1).getImm();
2336 SPIRV::CooperativeMatrixOperands::MatrixAAndBTF32ComponentsINTEL) {
2337 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
2339 "require the following SPIR-V extension: "
2340 "SPV_INTEL_joint_matrix",
2342 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2344 SPIRV::Capability::CooperativeMatrixTF32ComponentTypeINTEL);
2347 MatrixAAndBBFloat16ComponentsINTEL ||
2349 SPIRV::CooperativeMatrixOperands::MatrixCBFloat16ComponentsINTEL ||
2351 MatrixResultBFloat16ComponentsINTEL) {
2352 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
2354 "require the following SPIR-V extension: "
2355 "SPV_INTEL_joint_matrix",
2357 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2359 SPIRV::Capability::CooperativeMatrixBFloat16ComponentTypeINTEL);
2363 case SPIRV::OpCooperativeMatrixLoadKHR:
2364 case SPIRV::OpCooperativeMatrixStoreKHR:
2365 case SPIRV::OpCooperativeMatrixLoadCheckedINTEL:
2366 case SPIRV::OpCooperativeMatrixStoreCheckedINTEL:
2367 case SPIRV::OpCooperativeMatrixPrefetchINTEL: {
2368 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix))
2370 "following SPIR-V extension: "
2371 "SPV_KHR_cooperative_matrix",
2373 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix);
2374 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixKHR);
2380 case SPIRV::OpCooperativeMatrixLoadKHR:
2383 case SPIRV::OpCooperativeMatrixStoreKHR:
2386 case SPIRV::OpCooperativeMatrixLoadCheckedINTEL:
2389 case SPIRV::OpCooperativeMatrixStoreCheckedINTEL:
2390 case SPIRV::OpCooperativeMatrixPrefetchINTEL:
2396 Register RegLayout =
MI.getOperand(LayoutNum).getReg();
2399 if (MILayout->
getOpcode() == SPIRV::OpConstantI) {
2402 static_cast<unsigned>(SPIRV::CooperativeMatrixLayout::PackedINTEL)) {
2403 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
2405 "extension: SPV_INTEL_joint_matrix",
2407 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2408 Reqs.
addCapability(SPIRV::Capability::PackedCooperativeMatrixINTEL);
2413 if (
Op == SPIRV::OpCooperativeMatrixLoadKHR ||
2414 Op == SPIRV::OpCooperativeMatrixStoreKHR)
2417 std::string InstName;
2419 case SPIRV::OpCooperativeMatrixPrefetchINTEL:
2420 InstName =
"OpCooperativeMatrixPrefetchINTEL";
2422 case SPIRV::OpCooperativeMatrixLoadCheckedINTEL:
2423 InstName =
"OpCooperativeMatrixLoadCheckedINTEL";
2425 case SPIRV::OpCooperativeMatrixStoreCheckedINTEL:
2426 InstName =
"OpCooperativeMatrixStoreCheckedINTEL";
2430 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix)) {
2431 const std::string ErrorMsg =
2432 InstName +
" instruction requires the "
2433 "following SPIR-V extension: SPV_INTEL_joint_matrix";
2436 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2437 if (
Op == SPIRV::OpCooperativeMatrixPrefetchINTEL) {
2438 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixPrefetchINTEL);
2442 SPIRV::Capability::CooperativeMatrixCheckedInstructionsINTEL);
2445 case SPIRV::OpCooperativeMatrixConstructCheckedINTEL:
2446 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
2448 "instructions require the following SPIR-V extension: "
2449 "SPV_INTEL_joint_matrix",
2451 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2453 SPIRV::Capability::CooperativeMatrixCheckedInstructionsINTEL);
2455 case SPIRV::OpReadPipeBlockingALTERA:
2456 case SPIRV::OpWritePipeBlockingALTERA:
2457 if (ST.canUseExtension(SPIRV::Extension::SPV_ALTERA_blocking_pipes)) {
2458 Reqs.
addExtension(SPIRV::Extension::SPV_ALTERA_blocking_pipes);
2462 case SPIRV::OpCooperativeMatrixGetElementCoordINTEL:
2463 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
2465 "following SPIR-V extension: SPV_INTEL_joint_matrix",
2467 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2469 SPIRV::Capability::CooperativeMatrixInvocationInstructionsINTEL);
2471 case SPIRV::OpConvertHandleToImageINTEL:
2472 case SPIRV::OpConvertHandleToSamplerINTEL:
2473 case SPIRV::OpConvertHandleToSampledImageINTEL: {
2474 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bindless_images))
2476 "instructions require the following SPIR-V extension: "
2477 "SPV_INTEL_bindless_images",
2480 SPIRV::AddressingModel::AddressingModel AddrModel = MAI.
Addr;
2482 if (
Op == SPIRV::OpConvertHandleToImageINTEL &&
2483 TyDef->
getOpcode() != SPIRV::OpTypeImage) {
2485 "OpConvertHandleToImageINTEL",
2487 }
else if (
Op == SPIRV::OpConvertHandleToSamplerINTEL &&
2488 TyDef->
getOpcode() != SPIRV::OpTypeSampler) {
2490 "OpConvertHandleToSamplerINTEL",
2492 }
else if (
Op == SPIRV::OpConvertHandleToSampledImageINTEL &&
2493 TyDef->
getOpcode() != SPIRV::OpTypeSampledImage) {
2495 "OpConvertHandleToSampledImageINTEL",
2501 if (!(Bitwidth == 32 && AddrModel == SPIRV::AddressingModel::Physical32) &&
2502 !(Bitwidth == 64 && AddrModel == SPIRV::AddressingModel::Physical64)) {
2504 "Parameter value must be a 32-bit scalar in case of "
2505 "Physical32 addressing model or a 64-bit scalar in case of "
2506 "Physical64 addressing model",
2509 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bindless_images);
2513 case SPIRV::OpSubgroup2DBlockLoadINTEL:
2514 case SPIRV::OpSubgroup2DBlockLoadTransposeINTEL:
2515 case SPIRV::OpSubgroup2DBlockLoadTransformINTEL:
2516 case SPIRV::OpSubgroup2DBlockPrefetchINTEL:
2517 case SPIRV::OpSubgroup2DBlockStoreINTEL: {
2518 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_2d_block_io))
2520 "Prefetch/Store]INTEL instructions require the "
2521 "following SPIR-V extension: SPV_INTEL_2d_block_io",
2523 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_2d_block_io);
2524 Reqs.
addCapability(SPIRV::Capability::Subgroup2DBlockIOINTEL);
2526 if (
Op == SPIRV::OpSubgroup2DBlockLoadTransposeINTEL) {
2527 Reqs.
addCapability(SPIRV::Capability::Subgroup2DBlockTransposeINTEL);
2530 if (
Op == SPIRV::OpSubgroup2DBlockLoadTransformINTEL) {
2531 Reqs.
addCapability(SPIRV::Capability::Subgroup2DBlockTransformINTEL);
2536 case SPIRV::OpKill: {
2539 case SPIRV::OpDemoteToHelperInvocation:
2540 Reqs.
addCapability(SPIRV::Capability::DemoteToHelperInvocation);
2542 if (ST.canUseExtension(
2543 SPIRV::Extension::SPV_EXT_demote_to_helper_invocation)) {
2546 SPIRV::Extension::SPV_EXT_demote_to_helper_invocation);
2551 case SPIRV::OpSUDot:
2552 case SPIRV::OpSDotAccSat:
2553 case SPIRV::OpUDotAccSat:
2554 case SPIRV::OpSUDotAccSat:
2557 case SPIRV::OpImageSampleImplicitLod:
2558 case SPIRV::OpImageFetch:
2562 case SPIRV::OpImageSampleExplicitLod:
2565 case SPIRV::OpImageSampleDrefImplicitLod:
2566 case SPIRV::OpImageSampleDrefExplicitLod:
2567 case SPIRV::OpImageDrefGather:
2568 case SPIRV::OpImageGather:
2572 case SPIRV::OpImageRead: {
2573 Register ImageReg =
MI.getOperand(2).getReg();
2574 SPIRVTypeInst TypeDef = ST.getSPIRVGlobalRegistry()->getResultType(
2583 Reqs.
addCapability(SPIRV::Capability::StorageImageReadWithoutFormat);
2586 case SPIRV::OpImageWrite: {
2587 Register ImageReg =
MI.getOperand(0).getReg();
2588 SPIRVTypeInst TypeDef = ST.getSPIRVGlobalRegistry()->getResultType(
2597 Reqs.
addCapability(SPIRV::Capability::StorageImageWriteWithoutFormat);
2600 case SPIRV::OpTypeStructContinuedINTEL:
2601 case SPIRV::OpConstantCompositeContinuedINTEL:
2602 case SPIRV::OpSpecConstantCompositeContinuedINTEL:
2603 case SPIRV::OpCompositeConstructContinuedINTEL: {
2604 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_long_composites))
2606 "Continued instructions require the "
2607 "following SPIR-V extension: SPV_INTEL_long_composites",
2609 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_long_composites);
2613 case SPIRV::OpArbitraryFloatEQALTERA:
2614 case SPIRV::OpArbitraryFloatGEALTERA:
2615 case SPIRV::OpArbitraryFloatGTALTERA:
2616 case SPIRV::OpArbitraryFloatLEALTERA:
2617 case SPIRV::OpArbitraryFloatLTALTERA:
2618 case SPIRV::OpArbitraryFloatCbrtALTERA:
2619 case SPIRV::OpArbitraryFloatCosALTERA:
2620 case SPIRV::OpArbitraryFloatCosPiALTERA:
2621 case SPIRV::OpArbitraryFloatExp10ALTERA:
2622 case SPIRV::OpArbitraryFloatExp2ALTERA:
2623 case SPIRV::OpArbitraryFloatExpALTERA:
2624 case SPIRV::OpArbitraryFloatExpm1ALTERA:
2625 case SPIRV::OpArbitraryFloatHypotALTERA:
2626 case SPIRV::OpArbitraryFloatLog10ALTERA:
2627 case SPIRV::OpArbitraryFloatLog1pALTERA:
2628 case SPIRV::OpArbitraryFloatLog2ALTERA:
2629 case SPIRV::OpArbitraryFloatLogALTERA:
2630 case SPIRV::OpArbitraryFloatRecipALTERA:
2631 case SPIRV::OpArbitraryFloatSinCosALTERA:
2632 case SPIRV::OpArbitraryFloatSinCosPiALTERA:
2633 case SPIRV::OpArbitraryFloatSinALTERA:
2634 case SPIRV::OpArbitraryFloatSinPiALTERA:
2635 case SPIRV::OpArbitraryFloatSqrtALTERA:
2636 case SPIRV::OpArbitraryFloatACosALTERA:
2637 case SPIRV::OpArbitraryFloatACosPiALTERA:
2638 case SPIRV::OpArbitraryFloatAddALTERA:
2639 case SPIRV::OpArbitraryFloatASinALTERA:
2640 case SPIRV::OpArbitraryFloatASinPiALTERA:
2641 case SPIRV::OpArbitraryFloatATan2ALTERA:
2642 case SPIRV::OpArbitraryFloatATanALTERA:
2643 case SPIRV::OpArbitraryFloatATanPiALTERA:
2644 case SPIRV::OpArbitraryFloatCastFromIntALTERA:
2645 case SPIRV::OpArbitraryFloatCastALTERA:
2646 case SPIRV::OpArbitraryFloatCastToIntALTERA:
2647 case SPIRV::OpArbitraryFloatDivALTERA:
2648 case SPIRV::OpArbitraryFloatMulALTERA:
2649 case SPIRV::OpArbitraryFloatPowALTERA:
2650 case SPIRV::OpArbitraryFloatPowNALTERA:
2651 case SPIRV::OpArbitraryFloatPowRALTERA:
2652 case SPIRV::OpArbitraryFloatRSqrtALTERA:
2653 case SPIRV::OpArbitraryFloatSubALTERA: {
2654 if (!ST.canUseExtension(
2655 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_floating_point))
2657 "Floating point instructions can't be translated correctly without "
2658 "enabled SPV_ALTERA_arbitrary_precision_floating_point extension!",
2661 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_floating_point);
2663 SPIRV::Capability::ArbitraryPrecisionFloatingPointALTERA);
2666 case SPIRV::OpSubgroupMatrixMultiplyAccumulateINTEL: {
2667 if (!ST.canUseExtension(
2668 SPIRV::Extension::SPV_INTEL_subgroup_matrix_multiply_accumulate))
2670 "OpSubgroupMatrixMultiplyAccumulateINTEL instruction requires the "
2672 "extension: SPV_INTEL_subgroup_matrix_multiply_accumulate",
2675 SPIRV::Extension::SPV_INTEL_subgroup_matrix_multiply_accumulate);
2677 SPIRV::Capability::SubgroupMatrixMultiplyAccumulateINTEL);
2680 case SPIRV::OpBitwiseFunctionINTEL: {
2681 if (!ST.canUseExtension(
2682 SPIRV::Extension::SPV_INTEL_ternary_bitwise_function))
2684 "OpBitwiseFunctionINTEL instruction requires the following SPIR-V "
2685 "extension: SPV_INTEL_ternary_bitwise_function",
2687 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_ternary_bitwise_function);
2688 Reqs.
addCapability(SPIRV::Capability::TernaryBitwiseFunctionINTEL);
2691 case SPIRV::OpCopyMemorySized: {
2696 case SPIRV::OpTypeUntypedPointerKHR:
2698 MI.getOperand(1).getImm(), ST);
2700 case SPIRV::OpUntypedVariableKHR:
2701 case SPIRV::OpUntypedAccessChainKHR:
2702 case SPIRV::OpUntypedInBoundsAccessChainKHR:
2703 case SPIRV::OpUntypedPtrAccessChainKHR:
2704 case SPIRV::OpUntypedInBoundsPtrAccessChainKHR:
2705 case SPIRV::OpUntypedPrefetchKHR:
2706 case SPIRV::OpUntypedGroupAsyncCopyKHR: {
2707 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_untyped_pointers))
2709 "SPIR-V extension: SPV_KHR_untyped_pointers",
2711 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_untyped_pointers);
2715 case SPIRV::OpPredicatedLoadINTEL:
2716 case SPIRV::OpPredicatedStoreINTEL: {
2717 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_predicated_io))
2719 "OpPredicated[Load/Store]INTEL instructions require "
2720 "the following SPIR-V extension: SPV_INTEL_predicated_io",
2722 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_predicated_io);
2726 case SPIRV::OpFAddS:
2727 case SPIRV::OpFSubS:
2728 case SPIRV::OpFMulS:
2729 case SPIRV::OpFDivS:
2730 case SPIRV::OpFRemS:
2732 case SPIRV::OpFNegate:
2733 case SPIRV::OpFAddV:
2734 case SPIRV::OpFSubV:
2735 case SPIRV::OpFMulV:
2736 case SPIRV::OpFDivV:
2737 case SPIRV::OpFRemV:
2738 case SPIRV::OpFNegateV: {
2744 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic))
2746 "Arithmetic instructions with bfloat16 arguments require the "
2747 "following SPIR-V extension: SPV_INTEL_bfloat16_arithmetic",
2749 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic);
2750 Reqs.
addCapability(SPIRV::Capability::BFloat16ArithmeticINTEL);
2754 case SPIRV::OpOrdered:
2755 case SPIRV::OpUnordered:
2756 case SPIRV::OpFOrdEqual:
2757 case SPIRV::OpFOrdNotEqual:
2758 case SPIRV::OpFOrdLessThan:
2759 case SPIRV::OpFOrdLessThanEqual:
2760 case SPIRV::OpFOrdGreaterThan:
2761 case SPIRV::OpFOrdGreaterThanEqual:
2762 case SPIRV::OpFUnordEqual:
2763 case SPIRV::OpFUnordNotEqual:
2764 case SPIRV::OpFUnordLessThan:
2765 case SPIRV::OpFUnordLessThanEqual:
2766 case SPIRV::OpFUnordGreaterThan:
2767 case SPIRV::OpFUnordGreaterThanEqual: {
2770 ST.getSPIRVGlobalRegistry());
2771 assert(TypeDef &&
"Unexpected type instruction for comparison operand");
2775 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic))
2777 "Relational instructions with bfloat16 arguments require the "
2778 "following SPIR-V extension: SPV_INTEL_bfloat16_arithmetic",
2780 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic);
2781 Reqs.
addCapability(SPIRV::Capability::BFloat16ArithmeticINTEL);
2785 case SPIRV::OpDPdxCoarse:
2786 case SPIRV::OpDPdyCoarse:
2787 case SPIRV::OpDPdxFine:
2788 case SPIRV::OpDPdyFine: {
2792 case SPIRV::OpLoopControlINTEL: {
2793 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_unstructured_loop_controls);
2794 Reqs.
addCapability(SPIRV::Capability::UnstructuredLoopControlsINTEL);
2806 SPIRV::Capability::Shader);
2821 auto Node = M.getNamedMetadata(
"spirv.ExecutionMode");
2823 bool RequireFloatControls =
false, RequireIntelFloatControls2 =
false,
2824 RequireKHRFloatControls2 =
false,
2825 VerLower14 = !ST.isAtLeastSPIRVVer(
VersionTuple(1, 4));
2826 bool HasIntelFloatControls2 =
2827 ST.canUseExtension(SPIRV::Extension::SPV_INTEL_float_controls2);
2828 bool HasKHRFloatControls2 =
2829 ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2);
2830 for (
unsigned i = 0; i <
Node->getNumOperands(); i++) {
2836 auto EM = Const->getZExtValue();
2840 case SPIRV::ExecutionMode::DenormPreserve:
2841 case SPIRV::ExecutionMode::DenormFlushToZero:
2842 case SPIRV::ExecutionMode::RoundingModeRTE:
2843 case SPIRV::ExecutionMode::RoundingModeRTZ:
2844 RequireFloatControls = VerLower14;
2846 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2848 case SPIRV::ExecutionMode::RoundingModeRTPINTEL:
2849 case SPIRV::ExecutionMode::RoundingModeRTNINTEL:
2850 case SPIRV::ExecutionMode::FloatingPointModeALTINTEL:
2851 case SPIRV::ExecutionMode::FloatingPointModeIEEEINTEL:
2852 if (HasIntelFloatControls2) {
2853 RequireIntelFloatControls2 =
true;
2855 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2858 case SPIRV::ExecutionMode::FPFastMathDefault: {
2859 if (HasKHRFloatControls2) {
2860 RequireKHRFloatControls2 =
true;
2862 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2866 case SPIRV::ExecutionMode::ContractionOff:
2867 case SPIRV::ExecutionMode::SignedZeroInfNanPreserve:
2868 if (HasKHRFloatControls2) {
2869 RequireKHRFloatControls2 =
true;
2871 SPIRV::OperandCategory::ExecutionModeOperand,
2872 SPIRV::ExecutionMode::FPFastMathDefault, ST);
2875 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2880 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2885 if (RequireFloatControls &&
2886 ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls))
2888 if (RequireIntelFloatControls2)
2890 if (RequireKHRFloatControls2)
2894 if (
F.isDeclaration())
2896 if (
F.getMetadata(
"reqd_work_group_size"))
2898 SPIRV::OperandCategory::ExecutionModeOperand,
2899 SPIRV::ExecutionMode::LocalSize, ST);
2900 if (
F.getFnAttribute(
"hlsl.numthreads").isValid()) {
2902 SPIRV::OperandCategory::ExecutionModeOperand,
2903 SPIRV::ExecutionMode::LocalSize, ST);
2905 if (
F.getFnAttribute(
"enable-maximal-reconvergence").getValueAsBool()) {
2908 if (
F.getMetadata(
"work_group_size_hint"))
2910 SPIRV::OperandCategory::ExecutionModeOperand,
2911 SPIRV::ExecutionMode::LocalSizeHint, ST);
2912 if (
F.getMetadata(
"intel_reqd_sub_group_size") ||
2913 F.getMetadata(
"reqd_sub_group_size"))
2915 SPIRV::OperandCategory::ExecutionModeOperand,
2916 SPIRV::ExecutionMode::SubgroupSize, ST);
2917 if (
F.getMetadata(
"max_work_group_size"))
2919 SPIRV::OperandCategory::ExecutionModeOperand,
2920 SPIRV::ExecutionMode::MaxWorkgroupSizeINTEL, ST);
2921 if (
F.getMetadata(
"vec_type_hint"))
2923 SPIRV::OperandCategory::ExecutionModeOperand,
2924 SPIRV::ExecutionMode::VecTypeHint, ST);
2926 if (
F.hasOptNone()) {
2927 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_optnone)) {
2930 }
else if (ST.canUseExtension(SPIRV::Extension::SPV_EXT_optnone)) {
2940 unsigned Flags = SPIRV::FPFastMathMode::None;
2941 bool CanUseKHRFloatControls2 =
2942 ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2);
2944 Flags |= SPIRV::FPFastMathMode::NotNaN;
2946 Flags |= SPIRV::FPFastMathMode::NotInf;
2948 Flags |= SPIRV::FPFastMathMode::NSZ;
2950 Flags |= SPIRV::FPFastMathMode::AllowRecip;
2952 Flags |= SPIRV::FPFastMathMode::AllowContract;
2954 if (CanUseKHRFloatControls2)
2962 Flags |= SPIRV::FPFastMathMode::NotNaN | SPIRV::FPFastMathMode::NotInf |
2963 SPIRV::FPFastMathMode::NSZ | SPIRV::FPFastMathMode::AllowRecip |
2964 SPIRV::FPFastMathMode::AllowTransform |
2965 SPIRV::FPFastMathMode::AllowReassoc |
2966 SPIRV::FPFastMathMode::AllowContract;
2968 Flags |= SPIRV::FPFastMathMode::Fast;
2971 if (CanUseKHRFloatControls2) {
2973 assert(!(Flags & SPIRV::FPFastMathMode::Fast) &&
2974 "SPIRV::FPFastMathMode::Fast is deprecated and should not be used "
2979 assert((!(Flags & SPIRV::FPFastMathMode::AllowTransform) ||
2980 ((Flags & SPIRV::FPFastMathMode::AllowReassoc &&
2981 Flags & SPIRV::FPFastMathMode::AllowContract))) &&
2982 "SPIRV::FPFastMathMode::AllowTransform requires AllowReassoc and "
2983 "AllowContract flags to be enabled as well.");
2994 return ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2);
3004 auto Decorate = [&](SPIRV::Decoration::Decoration Dec,
3011 if (
TII.canUseIntegerWrapDecoration(
I)) {
3014 SPIRV::OperandCategory::DecorationOperand,
3015 SPIRV::Decoration::NoSignedWrap, ST, Reqs)
3017 Decorate(SPIRV::Decoration::NoSignedWrap, {});
3020 SPIRV::OperandCategory::DecorationOperand,
3021 SPIRV::Decoration::NoUnsignedWrap, ST, Reqs)
3023 Decorate(SPIRV::Decoration::NoUnsignedWrap, {});
3028 TII.canUseFastMathFlags(
3029 I, ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2)) ||
3030 (ST.isKernel() &&
I.getOpcode() == SPIRV::OpExtInst);
3035 if (FMFlags == SPIRV::FPFastMathMode::None) {
3038 if (FPFastMathDefaultInfoVec.
empty())
3044 I.getOpcode() == SPIRV::OpExtInst ||
3045 I.getOpcode() == SPIRV::OpFunctionCall
3046 ?
I.getMF()->getRegInfo().getVRegDef(
I.getOperand(1).getReg())
3047 :
getRegType(
I.getOperand(2).getReg(), *
I.getMF(), GR);
3054 if (Ty == Elem.Ty) {
3055 FMFlags = Elem.FastMathFlags;
3056 Emit = Elem.ContractionOff || Elem.SignedZeroInfNanPreserve ||
3057 Elem.FPFastMathDefault;
3062 if (FMFlags == SPIRV::FPFastMathMode::None && !Emit)
3066 Decorate(SPIRV::Decoration::FPFastMathMode, {FMFlags});
3080 for (
const auto &
MBB : *MF) {
3081 if (!
MBB.hasName() ||
MBB.empty())
3092 auto it = FPFastMathDefaultInfoMap.
find(
F);
3093 if (it != FPFastMathDefaultInfoMap.
end())
3101 SPIRV::FPFastMathMode::None);
3103 SPIRV::FPFastMathMode::None);
3105 SPIRV::FPFastMathMode::None);
3106 return FPFastMathDefaultInfoMap[
F] = std::move(FPFastMathDefaultInfoVec);
3112 size_t BitWidth = Ty->getScalarSizeInBits();
3116 assert(Index >= 0 && Index < 3 &&
3117 "Expected FPFastMathDefaultInfo for half, float, or double");
3118 assert(FPFastMathDefaultInfoVec.
size() == 3 &&
3119 "Expected FPFastMathDefaultInfoVec to have exactly 3 elements");
3120 return FPFastMathDefaultInfoVec[Index];
3127 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2))
3136 auto Node = M.getNamedMetadata(
"spirv.ExecutionMode");
3140 for (
unsigned i = 0; i <
Node->getNumOperands(); i++) {
3145 if (OnlyF &&
F != OnlyF)
3151 if (EM == SPIRV::ExecutionMode::FPFastMathDefault) {
3153 "Expected 4 operands for FPFastMathDefault");
3164 Info.FastMathFlags = Flags;
3165 Info.FPFastMathDefault =
true;
3166 }
else if (EM == SPIRV::ExecutionMode::ContractionOff) {
3168 "Expected no operands for ContractionOff");
3175 Info.ContractionOff =
true;
3177 }
else if (EM == SPIRV::ExecutionMode::SignedZeroInfNanPreserve) {
3179 "Expected 1 operand for SignedZeroInfNanPreserve");
3180 unsigned TargetWidth =
3189 assert(Index >= 0 && Index < 3 &&
3190 "Expected FPFastMathDefaultInfo for half, float, or double");
3191 assert(FPFastMathDefaultInfoVec.
size() == 3 &&
3192 "Expected FPFastMathDefaultInfoVec to have exactly 3 elements");
3193 FPFastMathDefaultInfoVec[Index].SignedZeroInfNanPreserve =
true;
3201 : ST(&ST), GR(ST.getSPIRVGlobalRegistry()), TII(ST.getInstrInfo()),
3202 MAI(MAI), GetMF(GetMF) {}
3214 collectDeclarations(M);
3217 numberRegistersGlobally(M);
3220 processOtherInstrs(M);
3224 MAI.Reqs.addCapability(SPIRV::Capability::Linkage);
3227 GR->setBound(MAI.MaxID);
3241 [&MMI](
const Function &
F) { return MMI.getMachineFunction(F); })
3257 MachineFunctionAnalysis::Result *MFA =
3258 FAM.getCachedResult<MachineFunctionAnalysis>(
3259 const_cast<Function &>(F));
3260 assert((MFA || F.isDeclaration()) &&
3261 "Missing MachineFunction for definition");
3262 return MFA ? &MFA->getMF() : nullptr;
3279 for (
auto &
MBB : MF)
3282 FPFastMathDefaultInfoMap[&
F]);
3290 SPIRVPrepareModuleAnalysisLegacy() : MachineFunctionPass(
ID) {}
3297char SPIRVPrepareModuleAnalysisLegacy::ID = 0;
3300 "spirv-prepare-module-analysis",
3301 "SPIRV prepare module analysis",
false,
false)
3304 return new SPIRVPrepareModuleAnalysisLegacy();
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
const AArch64Subtarget & Subtarget
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
ReachingDefInfo InstSet & ToRemove
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static Register UseReg(const MachineOperand &MO)
const HexagonInstrInfo * TII
Promote Memory to Register
FunctionAnalysisManager FAM
ModuleAnalysisManager MAM
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
MachineRegisterInfo & MRI
#define ATOM_FLT_REQ_EXT_MSG(ExtName)
static bool isFastMathModeAvailable(const SPIRVSubtarget &ST)
static void addMBBNames(const Module &M, MachineFunctionGetter GetMF, SPIRV::ModuleAnalysisInfo &MAI)
static void maybeAddScatterGatherReq(const MachineInstr &MI, SPIRV::RequirementHandler &Reqs, const SPIRVSubtarget &ST)
static void addImageOperandReqs(const MachineInstr &MI, SPIRV::RequirementHandler &Reqs, const SPIRVSubtarget &ST, unsigned OpIdx)
bool isStorageImage(MachineInstr *ImageInst)
bool isInputAttachment(MachineInstr *ImageInst)
static bool isBFloat16Type(SPIRVTypeInst TypeDef)
static bool handleMIFlagDecoration(MachineInstr &I, const SPIRVSubtarget &ST, const SPIRVInstrInfo &TII, SPIRV::RequirementHandler &Reqs, const SPIRVGlobalRegistry *GR, SPIRV::FPFastMathDefaultInfoVector &FPFastMathDefaultInfoVec)
bool isSampledImage(MachineInstr *ImageInst)
static unsigned getInvokeOperandIdx(unsigned Opcode)
static SPIRV::FPFastMathDefaultInfo & getFPFastMathDefaultInfo(SPIRV::FPFastMathDefaultInfoVector &FPFastMathDefaultInfoVec, const Type *Ty)
static void collectFPFastMathDefaults(const Module &M, SPIRV::FPFastMathDefaultInfoMapTy &FPFastMathDefaultInfoMap, const SPIRVSubtarget &ST, const Function *OnlyF=nullptr)
static void collectOtherInstr(MachineInstr &MI, SPIRV::ModuleAnalysisInfo &MAI, SPIRV::ModuleSectionType MSType, InstrTraces &IS, bool Append=true)
void addPrintfRequirements(const MachineInstr &MI, SPIRV::RequirementHandler &Reqs, const SPIRVSubtarget &ST)
static void addOpTypeImageReqs(const MachineInstr &MI, SPIRV::RequirementHandler &Reqs, const SPIRVSubtarget &ST)
static void addQuadControlRequirements(SPIRV::RequirementHandler &Reqs, const SPIRVSubtarget &ST, StringRef Feature)
static bool isImageTypeWithUnknownFormat(SPIRVTypeInst TypeInst)
bool isUniformTexelBuffer(MachineInstr *ImageInst)
bool isStorageTexelBuffer(MachineInstr *ImageInst)
static void AddAtomicFloatRequirements(const MachineInstr &MI, SPIRV::RequirementHandler &Reqs, const SPIRVSubtarget &ST)
bool isCombinedImageSampler(MachineInstr *SampledImageInst)
bool hasNonUniformDecoration(Register Reg, const MachineRegisterInfo &MRI)
void addInstrRequirements(const MachineInstr &MI, SPIRV::ModuleAnalysisInfo &MAI, const SPIRVSubtarget &ST)
static void collectReqs(const Module &M, SPIRV::ModuleAnalysisInfo &MAI, MachineFunctionGetter GetMF, const SPIRVSubtarget &ST)
static void addOpDecorateReqs(const MachineInstr &MI, unsigned DecIndex, SPIRV::RequirementHandler &Reqs, const SPIRVSubtarget &ST)
static InstrSignature instrToSignature(const MachineInstr &MI, SPIRV::ModuleAnalysisInfo &MAI, bool UseDefReg)
static void AddDotProductRequirements(const MachineInstr &MI, SPIRV::RequirementHandler &Reqs, const SPIRVSubtarget &ST)
static SPIRV::Requirements getSymbolicOperandRequirements(SPIRV::OperandCategory::OperandCategory Category, unsigned i, const SPIRVSubtarget &ST, SPIRV::RequirementHandler &Reqs)
static SPIRVTypeInst getRegType(Register Reg, const MachineFunction &MF, const SPIRVGlobalRegistry *GR)
static unsigned getMetadataUInt(MDNode *MdNode, unsigned OpIndex, unsigned DefaultVal=0)
static void addCoreInSPIRV13Capability(SPIRV::RequirementHandler &Reqs, const SPIRVSubtarget &ST, SPIRV::Capability::Capability Cap, SPIRV::Extension::Extension Ext)
void addOpAccessChainReqs(const MachineInstr &Instr, SPIRV::RequirementHandler &Handler, const SPIRVSubtarget &Subtarget)
static bool prepareModuleAnalysis(MachineFunction &MF)
static void appendDecorationsForReg(const MachineRegisterInfo &MRI, Register R, InstrSignature &Signature)
static SPIRV::FPFastMathDefaultInfoVector & getOrCreateFPFastMathDefaultInfoVec(const Module &M, SPIRV::FPFastMathDefaultInfoMapTy &FPFastMathDefaultInfoMap, const Function *F)
static bool shouldAvoidCapability(const SPIRVSubtarget &ST, SPIRV::Capability::Capability Cap)
static void AddAtomicVectorFloatRequirements(const MachineInstr &MI, SPIRV::RequirementHandler &Reqs, const SPIRVSubtarget &ST)
static unsigned getFastMathFlags(const MachineInstr &I, const SPIRVSubtarget &ST)
#define SPIRV_BACKEND_SERVICE_FUN_NAME
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
Target-Independent Code Generator Pass Configuration Options pass.
static Function * getFunction(FunctionType *Ty, const Twine &Name, Module *M)
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
Represent a constant reference to an array (0 or more elements consecutively in memory),...
bool isValid() const
Return true if the attribute is any kind of attribute.
This is the shared class of boolean and integer constants.
This is an important base class in LLVM.
Diagnostic information for unsupported feature in backend.
FunctionPass class - This class is used to implement most global optimizations.
Attribute getFnAttribute(Attribute::AttrKind Kind) const
Return the attribute for the given attribute kind.
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.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
MachineInstrBundleIterator< MachineInstr > iterator
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
Helper class to build MachineInstr.
void setDebugLoc(const DebugLoc &DL)
Set the debug location to DL for all the next build instructions.
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
unsigned getNumOperands() const
Retuns the total number of operands.
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
An analysis that produces MachineModuleInfo for a module.
This class contains meta information specific to a module.
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.
static MachineOperand CreateImm(int64_t Val)
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,...
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
iterator_range< use_instr_iterator > use_instructions(Register Reg) const
LLVM_ABI LLVM_READONLY MachineInstr * getUniqueVRegDef(Register Reg) const
getUniqueVRegDef - Return the unique machine instr that defines the specified virtual register or nul...
iterator find(const KeyT &Key)
A Module instance is used to store all the information related to an LLVM module.
AnalysisType & getAnalysis() const
getAnalysis<AnalysisType>() - This function is used by subclasses to get to the analysis information ...
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Wrapper class representing virtual and physical registers.
constexpr bool isValid() const
unsigned getScalarOrVectorBitWidth(SPIRVTypeInst Type) const
SPIRVTypeInst getResultType(Register VReg, MachineFunction *MF=nullptr)
const Type * getTypeForSPIRVType(SPIRVTypeInst Ty) const
SPIRVTypeInst getSPIRVTypeForVReg(Register VReg, const MachineFunction *MF=nullptr) const
void run(const Module &M)
SPIRVModuleAnalysisImpl(const SPIRVSubtarget &ST, SPIRV::ModuleAnalysisInfo &MAI, MachineFunctionGetter GetMF)
SPIRV::ModuleAnalysisInfo Result
Result run(Module &M, ModuleAnalysisManager &MAM)
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
const SPIRVSubtarget * getSubtargetImpl() const
reference emplace_back(ArgTypes &&... Args)
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)
Represent a constant reference to a string, i.e.
Target-Independent Code Generator Pass Configuration Options.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
bool isVectorTy() const
True if this is an instance of VectorType.
static LLVM_ABI Type * getDoubleTy(LLVMContext &C)
static LLVM_ABI Type * getFloatTy(LLVMContext &C)
static LLVM_ABI Type * getHalfTy(LLVMContext &C)
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.
MapVector< const Function *, FPFastMathDefaultInfoVector > FPFastMathDefaultInfoMapTy
SmallVector< const MachineInstr * > InstrList
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > extract(Y &&MD)
Extract a Value from Metadata.
This is an optimization pass for GlobalISel generic memory operations.
void stable_sort(R &&Range)
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)
SmallVector< SPIRV::Extension::Extension, 8 > ExtensionList
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
SmallVector< size_t > InstrSignature
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
InnerAnalysisManagerProxy< FunctionAnalysisManager, Module > FunctionAnalysisManagerModuleProxy
Provide the FunctionAnalysisManager to Module proxy.
static void reportUnsupported(MachineIRBuilder &MIRBuilder, const Twine &Msg)
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
void buildOpDecorate(Register Reg, MachineIRBuilder &MIRBuilder, SPIRV::Decoration::Decoration Dec, ArrayRef< uint32_t > DecArgs, StringRef StrImm)
bool isVectorType(SPIRVTypeInst SPVTy)
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
VersionTuple getSymbolicOperandMaxVersion(SPIRV::OperandCategory::OperandCategory Category, uint32_t Value)
function_ref< MachineFunction *(const Function &)> MachineFunctionGetter
void erase(Container &C, ValueType V)
Wrapper function to remove a value from a container:
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.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
FunctionPass * createSPIRVPrepareModuleAnalysisLegacyPass()
std::string getSymbolicOperandMnemonic(SPIRV::OperandCategory::OperandCategory Category, int32_t Value)
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
bool requiresLongVectorEXT(unsigned NumComponents, bool CanUseVector16=true)
DWARFExpression::Operation Op
VersionTuple getSymbolicOperandMinVersion(SPIRV::OperandCategory::OperandCategory Category, uint32_t Value)
constexpr unsigned BitWidth
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
SmallVector< SPIRV::Capability::Capability, 8 > CapabilityList
std::set< InstrSignature > InstrTraces
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
hash_code hash_combine(const Ts &...args)
Combine values into a single hash_code.
std::map< SmallVector< size_t >, unsigned > InstrGRegsMap
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
A special type used by analysis passes to provide an address that identifies that particular analysis...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
SPIRV::ModuleAnalysisInfo MAI
bool runOnModule(Module &M) override
runOnModule - Virtual method overriden by subclasses to process the module being operated on.
static size_t computeFPFastMathDefaultInfoVecIndex(size_t BitWidth)
void setSkipEmission(const MachineInstr *MI)
MCRegister getRegisterAlias(const MachineFunction *MF, Register Reg)
MCRegister getOrCreateMBBRegister(const MachineBasicBlock &MBB)
InstrList MS[NUM_MODULE_SECTIONS]
AddressingModel::AddressingModel Addr
SmallVector< std::pair< MCRegister, StringRef > > MBBNames
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 addExtensions(const ExtensionList &ToAdd)
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