36#define DEBUG_TYPE "spirv-module-analysis"
40 cl::desc(
"Dump MIR with SPIR-V dependencies info"),
45 cl::desc(
"SPIR-V capabilities to avoid if there are "
46 "other options enabling a feature"),
49 "SPIR-V Shader capability")));
59 "SPIRV module analysis",
true,
true)
63 Func.getContext().diagnose(
69 unsigned DefaultVal = 0) {
70 if (MdNode && OpIndex < MdNode->getNumOperands()) {
84 AvoidCaps.
S.
insert(SPIRV::Capability::Shader);
86 AvoidCaps.
S.
insert(SPIRV::Capability::Kernel);
91 bool MinVerOK = SPIRVVersion.
empty() || SPIRVVersion >= ReqMinVer;
93 ReqMaxVer.
empty() || SPIRVVersion.
empty() || SPIRVVersion <= ReqMaxVer;
94 bool VerOK = MinVerOK && MaxVerOK;
98 if (VerOK && !ReqMinVer.
empty())
100 if (ReqCaps.
empty()) {
101 if (ReqExts.
empty()) {
103 return {
true, {}, {}, ReqMinVer, ReqMaxVer};
107 if (ReqCaps.
size() == 1) {
108 auto Cap = ReqCaps[0];
111 SPIRV::OperandCategory::CapabilityOperand, Cap));
112 return {
true, {Cap}, std::move(ReqExts), ReqMinVer, ReqMaxVer};
122 for (
auto Cap : ReqCaps)
125 for (
size_t i = 0, Sz = UseCaps.
size(); i < Sz; ++i) {
126 auto Cap = UseCaps[i];
127 if (i == Sz - 1 || !AvoidCaps.
S.
contains(Cap)) {
129 SPIRV::OperandCategory::CapabilityOperand, Cap));
130 return {
true, {Cap}, std::move(ReqExts), ReqMinVer, ReqMaxVer};
139 if ((!ReqExts.
empty() || VerOK) &&
140 llvm::all_of(ReqExts, [&ST](
const SPIRV::Extension::Extension &Ext) {
141 return ST.canUseExtension(Ext);
144 return {
true, {}, std::move(ReqExts), ReqMinVer, ReqMaxVer};
150void SPIRVModuleAnalysisImpl::setBaseInfo(
const Module &M) {
154 MAI.RegisterAliasTable.clear();
155 MAI.InstrsToDelete.clear();
156 MAI.MBBNames.clear();
157 MAI.GlobalObjMap.clear();
158 MAI.GlobalVarList.clear();
159 MAI.ExtInstSetMap.clear();
160 MAI.InstrAuxDataRecords.clear();
161 MAI.DebugValueMIs.clear();
163 MAI.Reqs.initAvailableCapabilities(*ST);
166 if (
auto MemModel =
M.getNamedMetadata(
"spirv.MemoryModel")) {
167 auto MemMD = MemModel->getOperand(0);
168 MAI.Addr =
static_cast<SPIRV::AddressingModel::AddressingModel
>(
171 static_cast<SPIRV::MemoryModel::MemoryModel
>(
getMetadataUInt(MemMD, 1));
174 MAI.Mem = ST->isShader() ? SPIRV::MemoryModel::GLSL450
175 : SPIRV::MemoryModel::OpenCL;
176 if (MAI.Mem == SPIRV::MemoryModel::OpenCL) {
177 unsigned PtrSize = ST->getPointerSize();
178 MAI.Addr = PtrSize == 32 ? SPIRV::AddressingModel::Physical32
179 : PtrSize == 64 ? SPIRV::AddressingModel::Physical64
180 : SPIRV::AddressingModel::Logical;
183 MAI.Addr = SPIRV::AddressingModel::Logical;
188 if (
auto VerNode =
M.getNamedMetadata(
"opencl.ocl.version")) {
189 MAI.SrcLang = SPIRV::SourceLanguage::OpenCL_C;
192 assert(VerNode->getNumOperands() > 0 &&
"Invalid SPIR");
193 auto VersionMD = VerNode->getOperand(0);
199 (std::max(1U, MajorNum) * 100 + MinorNum) * 1000 + RevNum;
202 if (
auto *CxxVerNode =
M.getNamedMetadata(
"opencl.cxx.version")) {
203 assert(CxxVerNode->getNumOperands() > 0 &&
"Invalid SPIR");
204 auto *CxxMD = CxxVerNode->getOperand(0);
208 if ((MAI.SrcLangVersion == 200000 && CxxVer == 100000) ||
209 (MAI.SrcLangVersion == 300000 && CxxVer == 202100000)) {
210 MAI.SrcLang = SPIRV::SourceLanguage::CPP_for_OpenCL;
211 MAI.SrcLangVersion = CxxVer;
214 "opencl cxx version is not compatible with opencl c version!");
222 if (!ST->isShader()) {
223 MAI.SrcLang = SPIRV::SourceLanguage::OpenCL_CPP;
224 MAI.SrcLangVersion = 100000;
226 MAI.SrcLang = SPIRV::SourceLanguage::Unknown;
227 MAI.SrcLangVersion = 0;
231 if (
auto ExtNode =
M.getNamedMetadata(
"opencl.used.extensions")) {
232 for (
unsigned I = 0,
E = ExtNode->getNumOperands();
I !=
E; ++
I) {
233 MDNode *MD = ExtNode->getOperand(
I);
243 MAI.Reqs.getAndAddRequirements(SPIRV::OperandCategory::MemoryModelOperand,
245 MAI.Reqs.getAndAddRequirements(SPIRV::OperandCategory::SourceLanguageOperand,
247 MAI.Reqs.getAndAddRequirements(SPIRV::OperandCategory::AddressingModelOperand,
250 if (MAI.Mem == SPIRV::MemoryModel::VulkanKHR)
251 MAI.Reqs.addExtension(SPIRV::Extension::SPV_KHR_vulkan_memory_model);
253 if (!ST->isShader()) {
255 MAI.ExtInstSetMap[
static_cast<unsigned>(
256 SPIRV::InstructionSet::OpenCL_std)] = MAI.getNextIDRegister();
267 if (
UseMI.getOpcode() != SPIRV::OpDecorate &&
268 UseMI.getOpcode() != SPIRV::OpMemberDecorate)
271 for (
unsigned I = 0;
I <
UseMI.getNumOperands(); ++
I) {
289 for (
unsigned i = 0; i <
MI.getNumOperands(); ++i) {
298 unsigned Opcode =
MI.getOpcode();
299 if ((Opcode == SPIRV::OpDecorate) && i >= 2) {
300 unsigned DecorationID =
MI.getOperand(1).getImm();
301 if (DecorationID != SPIRV::Decoration::FuncParamAttr &&
302 DecorationID != SPIRV::Decoration::UserSemantic &&
303 DecorationID != SPIRV::Decoration::CacheControlLoadINTEL &&
304 DecorationID != SPIRV::Decoration::CacheControlStoreINTEL)
310 if (!UseDefReg && MO.
isDef()) {
318 dbgs() <<
"Unexpectedly, no global id found for the operand ";
320 dbgs() <<
"\nInstruction: ";
347 case SPIRV::OpEnqueueKernel:
349 case SPIRV::OpGetKernelNDrangeSubGroupCount:
350 case SPIRV::OpGetKernelNDrangeMaxSubGroupSize:
352 case SPIRV::OpGetKernelWorkGroupSize:
353 case SPIRV::OpGetKernelPreferredWorkGroupSizeMultiple:
362 unsigned Opcode =
MI.getOpcode();
364 case SPIRV::OpTypeForwardPointer:
367 case SPIRV::OpVariable:
368 case SPIRV::OpUntypedVariableKHR:
369 return static_cast<SPIRV::StorageClass::StorageClass
>(
370 MI.getOperand(2).
getImm()) != SPIRV::StorageClass::Function;
371 case SPIRV::OpFunction:
372 case SPIRV::OpFunctionParameter:
375 if (GR->hasConstFunPtr() && Opcode == SPIRV::OpUndef) {
383 if (GR->getFunctionDefinitionByUse(&
MI.getOperand(0))) {
385 unsigned UseOp =
UseMI.getOpcode();
386 if (UseOp == SPIRV::OpConstantFunctionPointerINTEL ||
388 MAI.setSkipEmission(&
MI);
394 if (
UseMI.getOpcode() != SPIRV::OpConstantFunctionPointerINTEL)
400 MAI.setSkipEmission(&
MI);
404 return TII->isTypeDeclInstr(
MI) || TII->isConstantInstr(
MI) ||
405 TII->isInlineAsmDefInstr(
MI);
414void SPIRVModuleAnalysisImpl::visitFunPtrUse(
417 std::map<const Value *, unsigned> &GlobalToGReg,
419 const MachineOperand *OpFunDef = GR->getFunctionDefinitionByUse(FunPtrOp);
422 const MachineInstr *OpDefMI = OpFunDef->
getParent();
425 const MachineRegisterInfo &FunDefMRI = FunDefMF->
getRegInfo();
427 visitDecl(FunDefMRI, SignatureToGReg, GlobalToGReg, FunDefMF, *OpDefMI);
429 }
while (OpDefMI && (OpDefMI->
getOpcode() == SPIRV::OpFunction ||
430 OpDefMI->
getOpcode() == SPIRV::OpFunctionParameter));
432 MCRegister GlobalFunDefReg =
433 MAI.getRegisterAlias(FunDefMF, OpFunDef->
getReg());
435 "Function definition must refer to a global register");
436 MAI.setRegisterAlias(MF, OpReg, GlobalFunDefReg);
441void SPIRVModuleAnalysisImpl::visitDecl(
443 std::map<const Value *, unsigned> &GlobalToGReg,
const MachineFunction *MF,
445 unsigned Opcode =
MI.getOpcode();
448 for (
const MachineOperand &MO :
MI.operands()) {
449 if (!MO.isReg() || MO.isDef())
453 if (Opcode == SPIRV::OpConstantFunctionPointerINTEL &&
455 visitFunPtrUse(OpReg, &
MI.getOperand(2), SignatureToGReg, GlobalToGReg,
460 if (MAI.hasRegisterAlias(MF, MO.getReg()))
464 if (isDeclSection(
MRI, *OpDefMI))
465 visitDecl(
MRI, SignatureToGReg, GlobalToGReg, MF, *OpDefMI);
471 dbgs() <<
"Unexpectedly, no unique definition for the operand ";
473 dbgs() <<
"\nInstruction: ";
478 "No unique definition is found for the virtual register");
482 bool IsFunDef =
false;
483 if (TII->isSpecConstantInstr(
MI)) {
484 GReg = MAI.getNextIDRegister();
486 }
else if (Opcode == SPIRV::OpFunction ||
487 Opcode == SPIRV::OpFunctionParameter) {
488 GReg = handleFunctionOrParameter(MF,
MI, GlobalToGReg, IsFunDef);
489 }
else if (Opcode == SPIRV::OpTypeStruct ||
490 Opcode == SPIRV::OpConstantComposite) {
491 GReg = handleTypeDeclOrConstant(
MI, SignatureToGReg);
492 const MachineInstr *NextInstr =
MI.getNextNode();
494 ((Opcode == SPIRV::OpTypeStruct &&
495 NextInstr->
getOpcode() == SPIRV::OpTypeStructContinuedINTEL) ||
496 (Opcode == SPIRV::OpConstantComposite &&
498 SPIRV::OpConstantCompositeContinuedINTEL))) {
499 MCRegister Tmp = handleTypeDeclOrConstant(*NextInstr, SignatureToGReg);
501 MAI.setSkipEmission(NextInstr);
504 }
else if (TII->isTypeDeclInstr(
MI) || TII->isConstantInstr(
MI) ||
505 TII->isInlineAsmDefInstr(
MI)) {
506 GReg = handleTypeDeclOrConstant(
MI, SignatureToGReg);
507 }
else if (Opcode == SPIRV::OpVariable ||
508 Opcode == SPIRV::OpUntypedVariableKHR) {
509 GReg = handleVariable(MF,
MI, GlobalToGReg);
512 dbgs() <<
"\nInstruction: ";
518 MAI.setRegisterAlias(MF,
MI.getOperand(0).getReg(), GReg);
520 MAI.setSkipEmission(&
MI);
523MCRegister SPIRVModuleAnalysisImpl::handleFunctionOrParameter(
525 std::map<const Value *, unsigned> &GlobalToGReg,
bool &IsFunDef) {
526 const Value *GObj = GR->getGlobalObject(MF,
MI.getOperand(0).getReg());
527 assert(GObj &&
"Unregistered global definition");
531 assert(
F &&
"Expected a reference to a function or an argument");
532 IsFunDef = !
F->isDeclaration();
533 auto [It,
Inserted] = GlobalToGReg.try_emplace(GObj);
536 MCRegister GReg = MAI.getNextIDRegister();
543MCRegister SPIRVModuleAnalysisImpl::handleTypeDeclOrConstant(
546 auto [It,
Inserted] = SignatureToGReg.try_emplace(MISign);
549 MCRegister GReg = MAI.getNextIDRegister();
555MCRegister SPIRVModuleAnalysisImpl::handleVariable(
557 std::map<const Value *, unsigned> &GlobalToGReg) {
558 MAI.GlobalVarList.push_back(&
MI);
559 const Value *GObj = GR->getGlobalObject(MF,
MI.getOperand(0).getReg());
560 assert(GObj &&
"Unregistered global definition");
561 auto [It,
Inserted] = GlobalToGReg.try_emplace(GObj);
564 MCRegister GReg = MAI.getNextIDRegister();
568 MAI.GlobalObjMap[GV] = GReg;
572void SPIRVModuleAnalysisImpl::collectDeclarations(
const Module &M) {
574 std::map<const Value *, unsigned> GlobalToGReg;
580 unsigned PastHeader = 0;
581 for (MachineBasicBlock &
MBB : *MF) {
582 for (MachineInstr &
MI :
MBB) {
583 if (
MI.getNumOperands() == 0)
585 unsigned Opcode =
MI.getOpcode();
586 if (Opcode == SPIRV::OpFunction) {
587 if (PastHeader == 0) {
591 }
else if (Opcode == SPIRV::OpFunctionParameter) {
594 }
else if (PastHeader > 0) {
598 const MachineOperand &DefMO =
MI.getOperand(0);
600 case SPIRV::OpExtension:
601 MAI.Reqs.addExtension(SPIRV::Extension::Extension(DefMO.
getImm()));
602 MAI.setSkipEmission(&
MI);
604 case SPIRV::OpCapability:
605 MAI.Reqs.addCapability(SPIRV::Capability::Capability(DefMO.
getImm()));
606 MAI.setSkipEmission(&
MI);
611 if (DefMO.
isReg() && isDeclSection(
MRI,
MI) &&
612 !MAI.hasRegisterAlias(MF, DefMO.
getReg()))
613 visitDecl(
MRI, SignatureToGReg, GlobalToGReg, MF,
MI);
618 const MachineOperand &InvokeMO =
MI.getOperand(InvokeIdx);
619 if (InvokeMO.
isReg()) {
621 if (!MAI.hasRegisterAlias(MF, InvokeReg)) {
622 if (
const MachineInstr *
DefMI =
626 if (GR->getFunctionDefinitionByUse(FunPtrOp))
627 visitFunPtrUse(InvokeReg, FunPtrOp, SignatureToGReg,
646 if (
MI.getOpcode() == SPIRV::OpDecorate) {
648 auto Dec =
MI.getOperand(1).getImm();
649 if (Dec == SPIRV::Decoration::LinkageAttributes) {
650 auto Lnk =
MI.getOperand(
MI.getNumOperands() - 1).getImm();
651 if (Lnk == SPIRV::LinkageType::Import) {
656 MAI.GlobalObjMap[ImportedFunc] =
657 MAI.getRegisterAlias(
MI.getMF(), Target);
660 }
else if (
MI.getOpcode() == SPIRV::OpFunction) {
663 MCRegister GlobalReg = MAI.getRegisterAlias(
MI.getMF(),
Reg);
665 MAI.GlobalObjMap[
F] = GlobalReg;
677 auto FoundMI = IS.insert(std::move(MISign));
678 if (!FoundMI.second) {
679 if (
MI.getOpcode() == SPIRV::OpDecorate) {
681 "Decoration instructions must have at least 2 operands");
683 "Only OpDecorate instructions can be duplicates");
688 if (
MI.getOperand(1).getImm() != SPIRV::Decoration::FPFastMathMode)
694 assert(OrigMI->getNumOperands() ==
MI.getNumOperands() &&
695 "Original instruction must have the same number of operands");
697 OrigMI->getNumOperands() == 3 &&
698 "FPFastMathMode decoration must have 3 operands for OpDecorate");
699 unsigned OrigFlags = OrigMI->getOperand(2).getImm();
700 unsigned NewFlags =
MI.getOperand(2).getImm();
701 if (OrigFlags == NewFlags)
705 unsigned FinalFlags = OrigFlags | NewFlags;
707 <<
"Warning: Conflicting FPFastMathMode decoration flags "
709 << *OrigMI <<
"Original flags: " << OrigFlags
710 <<
", new flags: " << NewFlags
711 <<
". They will be merged on a best effort basis, but not "
712 "validated. Final flags: "
713 << FinalFlags <<
"\n";
720 assert(
false &&
"No original instruction found for the duplicate "
721 "OpDecorate, but we found one in IS.");
734void SPIRVModuleAnalysisImpl::processOtherInstrs(
const Module &M) {
737 if (
F.isDeclaration())
742 for (MachineBasicBlock &
MBB : *MF)
743 for (MachineInstr &
MI :
MBB) {
744 if (
MI.isDebugValueLike()) {
745 MAI.DebugValueMIs.push_back(&
MI);
748 if (MAI.getSkipEmission(&
MI))
750 const unsigned OpCode =
MI.getOpcode();
751 if (OpCode == SPIRV::OpString) {
753 }
else if (OpCode == SPIRV::OpExtInst &&
MI.getOperand(2).isImm() &&
754 MI.getOperand(2).getImm() ==
755 SPIRV::InstructionSet::
756 NonSemantic_Shader_DebugInfo_100) {
763 MachineOperand Ins =
MI.getOperand(3);
764 namespace NS = SPIRV::NonSemanticExtInst;
765 static constexpr int64_t GlobalNonSemanticDITy[] = {
766 NS::DebugSource, NS::DebugCompilationUnit, NS::DebugInfoNone,
767 NS::DebugTypeBasic, NS::DebugTypePointer};
768 bool IsGlobalDI =
false;
769 for (
unsigned Idx = 0;
Idx < std::size(GlobalNonSemanticDITy); ++
Idx)
770 IsGlobalDI |= Ins.
getImm() == GlobalNonSemanticDITy[
Idx];
773 }
else if (OpCode == SPIRV::OpName || OpCode == SPIRV::OpMemberName) {
775 }
else if (OpCode == SPIRV::OpEntryPoint) {
777 }
else if (TII->isAliasingInstr(
MI)) {
779 }
else if (TII->isDecorationInstr(
MI)) {
780 if (
MI.getOpcode() == SPIRV::OpDecorate &&
781 MI.getOperand(1).getImm() ==
782 static_cast<unsigned>(
783 SPIRV::Decoration::AuxDataInstructionMetadata)) {
784 MAI.setSkipEmission(&
MI);
788 StringSwitch<std::optional<AMDMD>>(Str)
789 .Case(
"amdgpu.no.fine.grained.memory",
790 AMDMD::NoFineGrainedMemory)
791 .Case(
"amdgpu.no.remote.memory", AMDMD::NoRemoteMemory)
792 .Case(
"atomic.ignore.denormal.mode",
793 AMDMD::IgnoreDenormalMode)
794 .Default(std::nullopt);
796 MAI.InstrAuxDataRecords.push_back(
797 {MF,
MI.getOperand(0).getReg(), *MaybeKind});
801 collectFuncNames(
MI, &
F);
802 }
else if (TII->isConstantInstr(
MI)) {
806 }
else if (OpCode == SPIRV::OpFunction) {
807 collectFuncNames(
MI, &
F);
808 }
else if (OpCode == SPIRV::OpTypeForwardPointer) {
816 auto AliasingTier = [](
const MachineInstr *
MI) {
817 switch (
MI->getOpcode()) {
818 case SPIRV::OpAliasDomainDeclINTEL:
820 case SPIRV::OpAliasScopeDeclINTEL:
822 case SPIRV::OpAliasScopeListDeclINTEL:
829 [&](
const MachineInstr *
LHS,
const MachineInstr *
RHS) {
830 return AliasingTier(LHS) < AliasingTier(RHS);
837void SPIRVModuleAnalysisImpl::numberRegistersGlobally(
const Module &M) {
839 if (
F.isDeclaration())
843 for (MachineBasicBlock &
MBB : *MF) {
844 for (MachineInstr &
MI :
MBB) {
845 for (MachineOperand &
Op :
MI.operands()) {
849 if (MAI.hasRegisterAlias(MF,
Reg))
851 MCRegister NewReg = MAI.getNextIDRegister();
852 MAI.setRegisterAlias(MF,
Reg, NewReg);
854 if (
MI.getOpcode() != SPIRV::OpExtInst)
856 auto Set =
MI.getOperand(2).getImm();
857 auto [It,
Inserted] = MAI.ExtInstSetMap.try_emplace(Set);
859 It->second = MAI.getNextIDRegister();
867 SPIRV::OperandCategory::OperandCategory Category,
uint32_t i,
872void SPIRV::RequirementHandler::recursiveAddCapabilities(
874 for (
const auto &Cap : ToPrune) {
878 recursiveAddCapabilities(ImplicitDecls);
883 for (
const auto &Cap : ToAdd) {
884 bool IsNewlyInserted = AllCaps.insert(Cap).second;
885 if (!IsNewlyInserted)
889 recursiveAddCapabilities(ImplicitDecls);
890 MinimalCaps.push_back(Cap);
899 if (Req.
Cap.has_value())
905 if (!MaxVersion.empty() && Req.
MinVer > MaxVersion) {
907 <<
" and <= " << MaxVersion <<
"\n");
911 if (MinVersion.empty() || Req.
MinVer > MinVersion)
916 if (!MinVersion.empty() && Req.
MaxVer < MinVersion) {
918 <<
" and >= " << MinVersion <<
"\n");
922 if (MaxVersion.empty() || Req.
MaxVer < MaxVersion)
930 bool IsSatisfiable =
true;
931 auto TargetVer = ST.getSPIRVVersion();
933 if (!MaxVersion.empty() && !TargetVer.empty() && MaxVersion < TargetVer) {
935 dbgs() <<
"Target SPIR-V version too high for required features\n"
936 <<
"Required max version: " << MaxVersion <<
" target version "
937 << TargetVer <<
"\n");
938 IsSatisfiable =
false;
941 if (!MinVersion.empty() && !TargetVer.empty() && MinVersion > TargetVer) {
942 LLVM_DEBUG(
dbgs() <<
"Target SPIR-V version too low for required features\n"
943 <<
"Required min version: " << MinVersion
944 <<
" target version " << TargetVer <<
"\n");
945 IsSatisfiable =
false;
948 if (!MinVersion.empty() && !MaxVersion.empty() && MinVersion > MaxVersion) {
951 <<
"Version is too low for some features and too high for others.\n"
952 <<
"Required SPIR-V min version: " << MinVersion
953 <<
" required SPIR-V max version " << MaxVersion <<
"\n");
954 IsSatisfiable =
false;
959 AvoidCaps.
S.
insert(SPIRV::Capability::Shader);
961 AvoidCaps.
S.
insert(SPIRV::Capability::Kernel);
963 for (
auto Cap : MinimalCaps) {
964 if (AvailableCaps.contains(Cap) && !AvoidCaps.
S.
contains(Cap))
968 OperandCategory::CapabilityOperand, Cap)
970 IsSatisfiable =
false;
973 for (
auto Ext : AllExtensions) {
974 if (ST.canUseExtension(Ext))
978 OperandCategory::ExtensionOperand, Ext)
980 IsSatisfiable =
false;
989 for (
const auto Cap : ToAdd)
990 if (AvailableCaps.insert(Cap).second)
992 SPIRV::OperandCategory::CapabilityOperand, Cap));
996 const Capability::Capability
ToRemove,
997 const Capability::Capability IfPresent) {
998 if (AllCaps.contains(IfPresent)) {
1008 addAvailableCaps({Capability::Shader, Capability::Linkage, Capability::Int8,
1009 Capability::Int16});
1013 Capability::GroupNonUniformVote,
1014 Capability::GroupNonUniformArithmetic,
1015 Capability::GroupNonUniformBallot,
1016 Capability::GroupNonUniformClustered,
1017 Capability::GroupNonUniformShuffle,
1018 Capability::GroupNonUniformShuffleRelative,
1019 Capability::GroupNonUniformQuad});
1023 Capability::DotProductInput4x8Bit,
1024 Capability::DotProductInput4x8BitPacked,
1025 Capability::DemoteToHelperInvocation});
1028 for (
auto Extension : ST.getAllAvailableExtensions()) {
1035 if (ST.canUseExtension(Extension::SPV_EXT_shader_subgroup_partitioned))
1038 if (!ST.isShader()) {
1039 initAvailableCapabilitiesForOpenCL(ST);
1043 if (ST.isShader()) {
1044 initAvailableCapabilitiesForVulkan(ST);
1051void RequirementHandler::initAvailableCapabilitiesForOpenCL(
1055 Capability::Kernel, Capability::Vector16,
1056 Capability::Groups, Capability::GenericPointer,
1057 Capability::StorageImageWriteWithoutFormat,
1058 Capability::StorageImageReadWithoutFormat});
1059 if (ST.hasOpenCLFullProfile())
1061 if (ST.hasOpenCLImageSupport()) {
1063 Capability::Image1D, Capability::SampledBuffer,
1064 Capability::ImageBuffer});
1065 if (
ST.isAtLeastOpenCLVer(VersionTuple(2, 0)))
1068 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 1)) &&
1069 ST.isAtLeastOpenCLVer(VersionTuple(2, 2)))
1071 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 4)))
1072 addAvailableCaps({Capability::DenormPreserve, Capability::DenormFlushToZero,
1073 Capability::SignedZeroInfNanPreserve,
1074 Capability::RoundingModeRTE,
1075 Capability::RoundingModeRTZ});
1082void RequirementHandler::initAvailableCapabilitiesForVulkan(
1083 const SPIRVSubtarget &ST) {
1087 Capability::Geometry,
1088 Capability::Float16,
1089 Capability::Float64,
1090 Capability::GroupNonUniform,
1091 Capability::Image1D,
1092 Capability::SampledBuffer,
1093 Capability::ImageBuffer,
1094 Capability::UniformBufferArrayDynamicIndexing,
1095 Capability::SampledImageArrayDynamicIndexing,
1096 Capability::StorageBufferArrayDynamicIndexing,
1097 Capability::StorageImageArrayDynamicIndexing,
1098 Capability::DerivativeControl,
1099 Capability::SampleRateShading,
1101 Capability::ImageQuery,
1102 Capability::ImageGatherExtended,
1103 Capability::Addresses,
1104 Capability::VulkanMemoryModelKHR,
1105 Capability::StorageImageExtendedFormats,
1106 Capability::StorageImageMultisample,
1107 Capability::ImageMSArray});
1109 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 3)) ||
1110 ST.canUseExtension(Extension::SPV_KHR_variable_pointers))
1112 Capability::VariablePointers});
1115 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 3)))
1119 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 5))) {
1121 {Capability::Int64Atomics, Capability::ShaderNonUniformEXT,
1122 Capability::RuntimeDescriptorArrayEXT,
1123 Capability::InputAttachmentArrayDynamicIndexingEXT,
1124 Capability::UniformTexelBufferArrayDynamicIndexingEXT,
1125 Capability::StorageTexelBufferArrayDynamicIndexingEXT,
1126 Capability::UniformBufferArrayNonUniformIndexingEXT,
1127 Capability::SampledImageArrayNonUniformIndexingEXT,
1128 Capability::StorageBufferArrayNonUniformIndexingEXT,
1129 Capability::StorageImageArrayNonUniformIndexingEXT,
1130 Capability::InputAttachmentArrayNonUniformIndexingEXT,
1131 Capability::UniformTexelBufferArrayNonUniformIndexingEXT,
1132 Capability::StorageTexelBufferArrayNonUniformIndexingEXT});
1136 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 6)))
1138 Capability::StorageImageReadWithoutFormat});
1148 SPIRV::Capability::Capability Cap,
1149 SPIRV::Extension::Extension Ext) {
1153 if (!ST.canUseExtension(Ext))
1155 Twine(
"capability ") +
1157 SPIRV::OperandCategory::CapabilityOperand, Cap) +
1158 " requires SPIR-V 1.3 or the following SPIR-V extension: " +
1170 int64_t DecOp =
MI.getOperand(DecIndex).getImm();
1171 auto Dec =
static_cast<SPIRV::Decoration::Decoration
>(DecOp);
1173 SPIRV::OperandCategory::DecorationOperand, Dec, ST, Reqs));
1175 if (Dec == SPIRV::Decoration::BuiltIn) {
1176 int64_t BuiltInOp =
MI.getOperand(DecIndex + 1).getImm();
1177 auto BuiltIn =
static_cast<SPIRV::BuiltIn::BuiltIn
>(BuiltInOp);
1178 if ((BuiltIn == SPIRV::BuiltIn::BaryCoordKHR ||
1179 BuiltIn == SPIRV::BuiltIn::BaryCoordNoPerspKHR) &&
1180 !ST.canUseExtension(
1181 SPIRV::Extension::SPV_KHR_fragment_shader_barycentric))
1183 "Barycentric built-ins require the following SPIR-V extension: "
1184 "SPV_KHR_fragment_shader_barycentric",
1187 case SPIRV::BuiltIn::BaseVertex:
1188 case SPIRV::BuiltIn::BaseInstance:
1190 Reqs, ST, SPIRV::Capability::DrawParameters,
1191 SPIRV::Extension::SPV_KHR_shader_draw_parameters);
1193 case SPIRV::BuiltIn::ViewIndex:
1195 SPIRV::Extension::SPV_KHR_multiview);
1199 SPIRV::OperandCategory::BuiltInOperand, BuiltIn, ST, Reqs));
1202 }
else if (Dec == SPIRV::Decoration::LinkageAttributes) {
1203 int64_t LinkageOp =
MI.getOperand(
MI.getNumOperands() - 1).getImm();
1204 SPIRV::LinkageType::LinkageType LnkType =
1205 static_cast<SPIRV::LinkageType::LinkageType
>(LinkageOp);
1206 if (LnkType == SPIRV::LinkageType::LinkOnceODR)
1207 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_linkonce_odr);
1208 else if (LnkType == SPIRV::LinkageType::WeakAMD) {
1209 Reqs.
addExtension(SPIRV::Extension::SPV_AMD_weak_linkage);
1212 }
else if (Dec == SPIRV::Decoration::CacheControlLoadINTEL ||
1213 Dec == SPIRV::Decoration::CacheControlStoreINTEL) {
1214 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_cache_controls);
1215 }
else if (Dec == SPIRV::Decoration::HostAccessINTEL) {
1216 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_global_variable_host_access);
1217 }
else if (Dec == SPIRV::Decoration::InitModeINTEL ||
1218 Dec == SPIRV::Decoration::ImplementInRegisterMapINTEL) {
1220 SPIRV::Extension::SPV_INTEL_global_variable_fpga_decorations);
1221 }
else if (Dec == SPIRV::Decoration::NonUniformEXT) {
1223 }
else if (Dec == SPIRV::Decoration::FPMaxErrorDecorationINTEL) {
1225 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_fp_max_error);
1226 }
else if (Dec == SPIRV::Decoration::FPFastMathMode) {
1227 if (ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2)) {
1229 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_float_controls2);
1238 assert(
MI.getNumOperands() >= 8 &&
"Insufficient operands for OpTypeImage");
1241 int64_t ImgFormatOp =
MI.getOperand(7).getImm();
1242 auto ImgFormat =
static_cast<SPIRV::ImageFormat::ImageFormat
>(ImgFormatOp);
1246 bool IsArrayed =
MI.getOperand(4).getImm() == 1;
1247 bool IsMultisampled =
MI.getOperand(5).getImm() == 1;
1248 bool NoSampler =
MI.getOperand(6).getImm() == 2;
1251 switch (
MI.getOperand(2).getImm()) {
1252 case SPIRV::Dim::DIM_1D:
1254 : SPIRV::Capability::Sampled1D);
1256 case SPIRV::Dim::DIM_2D:
1257 if (IsMultisampled && NoSampler)
1259 if (IsMultisampled && IsArrayed)
1262 case SPIRV::Dim::DIM_3D:
1264 case SPIRV::Dim::DIM_Cube:
1268 : SPIRV::Capability::SampledCubeArray);
1270 case SPIRV::Dim::DIM_Rect:
1272 : SPIRV::Capability::SampledRect);
1274 case SPIRV::Dim::DIM_Buffer:
1276 : SPIRV::Capability::SampledBuffer);
1278 case SPIRV::Dim::DIM_SubpassData:
1284 if (!ST.isShader()) {
1285 if (
MI.getNumOperands() > 8 &&
1286 MI.getOperand(8).getImm() == SPIRV::AccessQualifier::ReadWrite)
1295 TypeDef->
getOpcode() == SPIRV::OpTypeFloat &&
1307 return MRI.getVRegDef(
MRI.getVRegDef(
Reg)->getOperand(1).getReg());
1311#define ATOM_FLT_REQ_EXT_MSG(ExtName) \
1312 "The atomic float instruction requires the following SPIR-V " \
1313 "extension: SPV_EXT_shader_atomic_float" ExtName
1318 MI.getMF()->getRegInfo().getVRegDef(
MI.getOperand(1).getReg());
1321 if (Rank != 2 && Rank != 4)
1323 "must be a 2-component or 4 component vector");
1328 if (EltTypeDef->
getOpcode() != SPIRV::OpTypeFloat ||
1331 "The element type for the result type of an atomic vector float "
1332 "instruction must be a 16-bit floating-point scalar");
1339 "The element type for the result type of an atomic vector float "
1340 "instruction cannot be a bfloat16 scalar");
1341 if (!ST.canUseExtension(SPIRV::Extension::SPV_NV_shader_atomic_fp16_vector))
1343 "The atomic float16 vector instruction requires the following SPIR-V "
1344 "extension: SPV_NV_shader_atomic_fp16_vector");
1346 Reqs.
addExtension(SPIRV::Extension::SPV_NV_shader_atomic_fp16_vector);
1347 Reqs.
addCapability(SPIRV::Capability::AtomicFloat16VectorNV);
1354 "Expect register operand in atomic float instruction");
1355 Register TypeReg =
MI.getOperand(1).getReg();
1361 if (TypeDef->
getOpcode() != SPIRV::OpTypeFloat)
1363 "floating-point type scalar");
1366 unsigned Op =
MI.getOpcode();
1367 if (
Op == SPIRV::OpAtomicFAddEXT) {
1368 if (!ST.canUseExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float_add))
1370 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float_add);
1374 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics))
1376 "The atomic bfloat16 instruction requires the following SPIR-V "
1377 "extension: SPV_INTEL_16bit_atomics",
1379 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics);
1380 Reqs.
addCapability(SPIRV::Capability::AtomicBFloat16AddINTEL);
1382 if (!ST.canUseExtension(
1383 SPIRV::Extension::SPV_EXT_shader_atomic_float16_add))
1385 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float16_add);
1397 "Unexpected floating-point type width in atomic float instruction");
1400 if (!ST.canUseExtension(
1401 SPIRV::Extension::SPV_EXT_shader_atomic_float_min_max))
1403 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float_min_max);
1407 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics))
1409 "The atomic bfloat16 instruction requires the following SPIR-V "
1410 "extension: SPV_INTEL_16bit_atomics",
1412 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics);
1413 Reqs.
addCapability(SPIRV::Capability::AtomicBFloat16MinMaxINTEL);
1415 Reqs.
addCapability(SPIRV::Capability::AtomicFloat16MinMaxEXT);
1419 Reqs.
addCapability(SPIRV::Capability::AtomicFloat32MinMaxEXT);
1422 Reqs.
addCapability(SPIRV::Capability::AtomicFloat64MinMaxEXT);
1426 "Unexpected floating-point type width in atomic float instruction");
1432 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1436 return Dim == SPIRV::Dim::DIM_Buffer && Sampled == 1;
1440 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1444 return Dim == SPIRV::Dim::DIM_Buffer && Sampled == 2;
1448 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1452 return Dim != SPIRV::Dim::DIM_Buffer && Sampled == 1;
1456 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1460 return Dim == SPIRV::Dim::DIM_SubpassData && Sampled == 2;
1464 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1468 return Dim != SPIRV::Dim::DIM_Buffer && Sampled == 2;
1472 if (SampledImageInst->
getOpcode() != SPIRV::OpTypeSampledImage)
1477 auto *ImageInst =
MRI.getUniqueVRegDef(ImageReg);
1482 for (
const auto &
MI :
MRI.reg_instructions(
Reg)) {
1483 if (
MI.getOpcode() != SPIRV::OpDecorate)
1487 if (Dec == SPIRV::Decoration::NonUniformEXT)
1500 Register ResTypeReg = Instr.getOperand(1).getReg();
1505 if (
StorageClass != SPIRV::StorageClass::StorageClass::UniformConstant &&
1506 StorageClass != SPIRV::StorageClass::StorageClass::Uniform &&
1507 StorageClass != SPIRV::StorageClass::StorageClass::StorageBuffer) {
1514 auto FirstIndexReg = Instr.getOperand(3).getReg();
1515 bool FirstIndexIsConstant =
1516 Subtarget.getInstrInfo()->isConstantInstr(*
MRI.getVRegDef(FirstIndexReg));
1518 if (
StorageClass == SPIRV::StorageClass::StorageClass::StorageBuffer) {
1521 SPIRV::Capability::StorageBufferArrayNonUniformIndexingEXT);
1522 else if (!FirstIndexIsConstant)
1524 SPIRV::Capability::StorageBufferArrayDynamicIndexing);
1530 if (PointeeType->
getOpcode() != SPIRV::OpTypeImage &&
1531 PointeeType->
getOpcode() != SPIRV::OpTypeSampledImage &&
1532 PointeeType->
getOpcode() != SPIRV::OpTypeSampler) {
1539 SPIRV::Capability::UniformTexelBufferArrayNonUniformIndexingEXT);
1540 else if (!FirstIndexIsConstant)
1542 SPIRV::Capability::UniformTexelBufferArrayDynamicIndexingEXT);
1546 SPIRV::Capability::InputAttachmentArrayNonUniformIndexingEXT);
1547 else if (!FirstIndexIsConstant)
1549 SPIRV::Capability::InputAttachmentArrayDynamicIndexingEXT);
1553 SPIRV::Capability::StorageTexelBufferArrayNonUniformIndexingEXT);
1554 else if (!FirstIndexIsConstant)
1556 SPIRV::Capability::StorageTexelBufferArrayDynamicIndexingEXT);
1559 PointeeType->
getOpcode() == SPIRV::OpTypeSampler) {
1562 SPIRV::Capability::SampledImageArrayNonUniformIndexingEXT);
1563 else if (!FirstIndexIsConstant)
1565 SPIRV::Capability::SampledImageArrayDynamicIndexing);
1569 SPIRV::Capability::StorageImageArrayNonUniformIndexingEXT);
1570 else if (!FirstIndexIsConstant)
1572 SPIRV::Capability::StorageImageArrayDynamicIndexing);
1577 if (TypeInst->
getOpcode() != SPIRV::OpTypeImage)
1586 if (ST.canUseExtension(SPIRV::Extension::SPV_KHR_integer_dot_product))
1587 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_integer_dot_product);
1591 assert(
MI.getOperand(2).isReg() &&
"Unexpected operand in dot");
1593 ST.getSPIRVGlobalRegistry());
1594 assert(TypeDef &&
"Unexpected type instruction for dot input");
1595 if (TypeDef->
getOpcode() == SPIRV::OpTypeInt) {
1597 Reqs.
addCapability(SPIRV::Capability::DotProductInput4x8BitPacked);
1604 "Dot operand of 8-bit integer type requires 4 components");
1605 Reqs.
addCapability(SPIRV::Capability::DotProductInput4x8Bit);
1621 unsigned AddrSpace = ASOp.
getImm();
1622 if (AddrSpace != SPIRV::StorageClass::UniformConstant) {
1623 if (!ST.canUseExtension(
1625 SPV_EXT_relaxed_printf_string_address_space)) {
1627 "required because printf uses a format string not "
1628 "in constant address space.",
1632 SPIRV::Extension::SPV_EXT_relaxed_printf_string_address_space);
1641 if (
MI.getNumOperands() <= OpIdx)
1643 uint32_t Mask =
MI.getOperand(OpIdx).getImm();
1645 if (Mask & (1U <<
I))
1656 if (ElemTypeDef->
getOpcode() == SPIRV::OpTypePointer &&
1657 ST.canUseExtension(SPIRV::Extension::SPV_INTEL_masked_gather_scatter)) {
1658 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_masked_gather_scatter);
1659 Reqs.
addCapability(SPIRV::Capability::MaskedGatherScatterINTEL);
1667 unsigned Op =
MI.getOpcode();
1669 case SPIRV::OpMemoryModel: {
1670 int64_t Addr =
MI.getOperand(0).getImm();
1673 int64_t Mem =
MI.getOperand(1).getImm();
1678 case SPIRV::OpEntryPoint: {
1679 int64_t Exe =
MI.getOperand(0).getImm();
1684 case SPIRV::OpExecutionMode:
1685 case SPIRV::OpExecutionModeId: {
1686 int64_t Exe =
MI.getOperand(1).getImm();
1691 case SPIRV::OpTypeMatrix:
1694 case SPIRV::OpTypeInt: {
1695 unsigned BitWidth =
MI.getOperand(1).getImm();
1703 ST.canUseExtension(SPIRV::Extension::SPV_INTEL_int4)) {
1707 if (!ST.canUseExtension(
1708 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_integers))
1710 "OpTypeInt type with a width other than 8, 16, 32 or 64 bits "
1711 "requires the following SPIR-V extension: "
1712 "SPV_ALTERA_arbitrary_precision_integers");
1714 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_integers);
1715 Reqs.
addCapability(SPIRV::Capability::ArbitraryPrecisionIntegersALTERA);
1719 case SPIRV::OpDot: {
1723 Reqs.
addCapability(SPIRV::Capability::BFloat16DotProductKHR);
1726 case SPIRV::OpTypeFloat: {
1727 unsigned BitWidth =
MI.getOperand(1).getImm();
1732 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_bfloat16))
1734 "following SPIR-V extension: SPV_KHR_bfloat16",
1744 case SPIRV::OpTypeVector: {
1745 unsigned NumComponents =
MI.getOperand(2).getImm();
1746 if (NumComponents == 8 || NumComponents == 16)
1751 "OpTypeVector with " +
Twine(NumComponents) +
1752 " components requires the following SPIR-V extension: "
1753 "SPV_EXT_long_vector");
1758 case SPIRV::OpTypeVectorIdEXT: {
1759 if (!ST.canUseExtension(SPIRV::Extension::SPV_EXT_long_vector))
1761 "extension: SPV_EXT_long_vector extension");
1762 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_long_vector);
1767 case SPIRV::OpTypePointer: {
1768 auto SC =
MI.getOperand(1).getImm();
1779 (TypeDef->
getOpcode() == SPIRV::OpTypeFloat) &&
1784 case SPIRV::OpExtInst: {
1785 if (
MI.getOperand(2).getImm() ==
1786 static_cast<int64_t
>(
1787 SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100)) {
1788 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_non_semantic_info);
1791 if (
MI.getOperand(3).getImm() ==
1792 static_cast<int64_t
>(SPIRV::OpenCLExtInst::printf)) {
1796 if (
MI.getOperand(2).getImm() ==
1797 static_cast<int64_t
>(SPIRV::InstructionSet::OpenCL_std)) {
1803 if (TypeDef && TypeDef->getOpcode() == SPIRV::OpTypeVector)
1804 TypeDef =
MRI.getVRegDef(TypeDef->getOperand(1).getReg());
1809 bool UsesBFloat16 = IsBFloat16(
MRI.getVRegDef(
MI.getOperand(1).getReg()));
1810 for (
unsigned I = 4,
E =
MI.getNumOperands();
I <
E && !UsesBFloat16;
1819 if (!ST.canUseExtension(
1820 SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic)) {
1822 MI,
"OpenCL Extended instructions with bfloat16 require the "
1823 "following SPIR-V extension: SPV_INTEL_bfloat16_arithmetic");
1826 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic);
1827 Reqs.
addCapability(SPIRV::Capability::BFloat16ArithmeticINTEL);
1832 case SPIRV::OpAliasDomainDeclINTEL:
1833 case SPIRV::OpAliasScopeDeclINTEL:
1834 case SPIRV::OpAliasScopeListDeclINTEL: {
1835 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_memory_access_aliasing);
1836 Reqs.
addCapability(SPIRV::Capability::MemoryAccessAliasingINTEL);
1839 case SPIRV::OpBitReverse:
1840 case SPIRV::OpBitFieldInsert:
1841 case SPIRV::OpBitFieldSExtract:
1842 case SPIRV::OpBitFieldUExtract:
1843 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_bit_instructions)) {
1847 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_bit_instructions);
1850 case SPIRV::OpTypeRuntimeArray:
1853 case SPIRV::OpTypeOpaque:
1854 case SPIRV::OpTypeEvent:
1857 case SPIRV::OpTypePipe:
1858 case SPIRV::OpTypeReserveId:
1861 case SPIRV::OpTypePipeStorage:
1864 case SPIRV::OpTypeDeviceEvent:
1865 case SPIRV::OpTypeQueue:
1866 case SPIRV::OpBuildNDRange:
1867 case SPIRV::OpEnqueueKernel:
1868 case SPIRV::OpGetKernelNDrangeSubGroupCount:
1869 case SPIRV::OpGetKernelNDrangeMaxSubGroupSize:
1870 case SPIRV::OpGetKernelWorkGroupSize:
1871 case SPIRV::OpGetKernelPreferredWorkGroupSizeMultiple:
1874 case SPIRV::OpDecorate:
1875 case SPIRV::OpDecorateId:
1876 case SPIRV::OpDecorateString:
1879 case SPIRV::OpMemberDecorate:
1880 case SPIRV::OpMemberDecorateString:
1883 case SPIRV::OpInBoundsPtrAccessChain:
1886 case SPIRV::OpConstantSampler:
1889 case SPIRV::OpInBoundsAccessChain:
1890 case SPIRV::OpAccessChain:
1893 case SPIRV::OpTypeImage:
1896 case SPIRV::OpTypeSampler:
1897 if (!ST.isShader()) {
1901 case SPIRV::OpTypeForwardPointer:
1905 case SPIRV::OpAtomicFlagTestAndSet:
1906 case SPIRV::OpAtomicLoad:
1907 case SPIRV::OpAtomicStore:
1908 case SPIRV::OpAtomicExchange:
1909 case SPIRV::OpAtomicCompareExchange:
1910 case SPIRV::OpAtomicCompareExchangeWeak:
1911 case SPIRV::OpAtomicIIncrement:
1912 case SPIRV::OpAtomicIDecrement:
1913 case SPIRV::OpAtomicIAdd:
1914 case SPIRV::OpAtomicISub:
1915 case SPIRV::OpAtomicUMin:
1916 case SPIRV::OpAtomicUMax:
1917 case SPIRV::OpAtomicSMin:
1918 case SPIRV::OpAtomicSMax:
1919 case SPIRV::OpAtomicAnd:
1920 case SPIRV::OpAtomicOr:
1921 case SPIRV::OpAtomicXor: {
1924 if (
Op == SPIRV::OpAtomicStore) {
1927 ST.getSPIRVGlobalRegistry());
1928 assert(TypeDef &&
"Unexpected type instruction for OpAtomicStore");
1930 assert(
MI.getOperand(1).isReg() &&
"Unexpected operand in atomic");
1931 TypeDef =
MRI.getVRegDef(
MI.getOperand(1).getReg());
1934 if (TypeDef->
getOpcode() == SPIRV::OpTypeInt) {
1939 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics))
1941 "16-bit integer atomic operations require the following SPIR-V "
1942 "extension: SPV_INTEL_16bit_atomics",
1944 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics);
1946 case SPIRV::OpAtomicLoad:
1947 case SPIRV::OpAtomicStore:
1948 case SPIRV::OpAtomicExchange:
1949 case SPIRV::OpAtomicCompareExchange:
1950 case SPIRV::OpAtomicCompareExchangeWeak:
1952 SPIRV::Capability::AtomicInt16CompareExchangeINTEL);
1960 if (
is_contained({SPIRV::OpAtomicLoad, SPIRV::OpAtomicStore,
1961 SPIRV::OpAtomicExchange},
1963 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics))
1965 "The atomic bfloat16 instruction requires the following SPIR-V "
1966 "extension: SPV_INTEL_16bit_atomics",
1968 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics);
1969 Reqs.
addCapability(SPIRV::Capability::AtomicBFloat16LoadStoreINTEL);
1974 case SPIRV::OpGroupNonUniformIAdd:
1975 case SPIRV::OpGroupNonUniformFAdd:
1976 case SPIRV::OpGroupNonUniformIMul:
1977 case SPIRV::OpGroupNonUniformFMul:
1978 case SPIRV::OpGroupNonUniformSMin:
1979 case SPIRV::OpGroupNonUniformUMin:
1980 case SPIRV::OpGroupNonUniformFMin:
1981 case SPIRV::OpGroupNonUniformSMax:
1982 case SPIRV::OpGroupNonUniformUMax:
1983 case SPIRV::OpGroupNonUniformFMax:
1984 case SPIRV::OpGroupNonUniformBitwiseAnd:
1985 case SPIRV::OpGroupNonUniformBitwiseOr:
1986 case SPIRV::OpGroupNonUniformBitwiseXor:
1987 case SPIRV::OpGroupNonUniformLogicalAnd:
1988 case SPIRV::OpGroupNonUniformLogicalOr:
1989 case SPIRV::OpGroupNonUniformLogicalXor: {
1991 int64_t GroupOp =
MI.getOperand(3).getImm();
1993 case SPIRV::GroupOperation::Reduce:
1994 case SPIRV::GroupOperation::InclusiveScan:
1995 case SPIRV::GroupOperation::ExclusiveScan:
1996 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformArithmetic);
1998 case SPIRV::GroupOperation::ClusteredReduce:
1999 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformClustered);
2001 case SPIRV::GroupOperation::PartitionedReduceNV:
2002 case SPIRV::GroupOperation::PartitionedInclusiveScanNV:
2003 case SPIRV::GroupOperation::PartitionedExclusiveScanNV:
2004 if (ST.canUseExtension(
2005 SPIRV::Extension::SPV_EXT_shader_subgroup_partitioned))
2007 SPIRV::Extension::SPV_EXT_shader_subgroup_partitioned);
2009 Reqs.
addExtension(SPIRV::Extension::SPV_NV_shader_subgroup_partitioned);
2010 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformPartitionedNV);
2015 case SPIRV::OpGroupNonUniformQuadSwap:
2018 case SPIRV::OpImageQueryLod:
2021 case SPIRV::OpImageQuerySize:
2022 case SPIRV::OpImageQuerySizeLod:
2023 case SPIRV::OpImageQueryLevels:
2024 case SPIRV::OpImageQuerySamples:
2028 case SPIRV::OpImageQueryFormat: {
2029 Register ResultReg =
MI.getOperand(0).getReg();
2031 static const unsigned CompareOps[] = {
2032 SPIRV::OpIEqual, SPIRV::OpINotEqual,
2033 SPIRV::OpUGreaterThan, SPIRV::OpUGreaterThanEqual,
2034 SPIRV::OpULessThan, SPIRV::OpULessThanEqual,
2035 SPIRV::OpSGreaterThan, SPIRV::OpSGreaterThanEqual,
2036 SPIRV::OpSLessThan, SPIRV::OpSLessThanEqual};
2038 auto CheckAndAddExtension = [&](int64_t ImmVal) {
2039 if (ImmVal == 4323 || ImmVal == 4324) {
2040 if (ST.canUseExtension(SPIRV::Extension::SPV_EXT_image_raw10_raw12))
2041 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_image_raw10_raw12);
2044 "SPV_EXT_image_raw10_raw12 extension");
2049 unsigned Opc = UseInst.getOpcode();
2051 if (
Opc == SPIRV::OpSwitch) {
2054 CheckAndAddExtension(
Op.getImm());
2056 for (
unsigned i = 1; i < UseInst.getNumOperands(); ++i) {
2059 if (ConstInst && ConstInst->
getOpcode() == SPIRV::OpConstantI) {
2062 CheckAndAddExtension(ImmVal);
2070 case SPIRV::OpGroupNonUniformShuffle:
2071 case SPIRV::OpGroupNonUniformShuffleXor:
2072 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformShuffle);
2074 case SPIRV::OpGroupNonUniformShuffleUp:
2075 case SPIRV::OpGroupNonUniformShuffleDown:
2076 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformShuffleRelative);
2078 case SPIRV::OpGroupAll:
2079 case SPIRV::OpGroupAny:
2080 case SPIRV::OpGroupBroadcast:
2081 case SPIRV::OpGroupIAdd:
2082 case SPIRV::OpGroupFAdd:
2083 case SPIRV::OpGroupFMin:
2084 case SPIRV::OpGroupUMin:
2085 case SPIRV::OpGroupSMin:
2086 case SPIRV::OpGroupFMax:
2087 case SPIRV::OpGroupUMax:
2088 case SPIRV::OpGroupSMax:
2091 case SPIRV::OpGroupNonUniformElect:
2094 case SPIRV::OpGroupNonUniformAll:
2095 case SPIRV::OpGroupNonUniformAny:
2096 case SPIRV::OpGroupNonUniformAllEqual:
2099 case SPIRV::OpGroupNonUniformBroadcast:
2100 case SPIRV::OpGroupNonUniformBroadcastFirst:
2101 case SPIRV::OpGroupNonUniformBallot:
2102 case SPIRV::OpGroupNonUniformInverseBallot:
2103 case SPIRV::OpGroupNonUniformBallotBitExtract:
2104 case SPIRV::OpGroupNonUniformBallotBitCount:
2105 case SPIRV::OpGroupNonUniformBallotFindLSB:
2106 case SPIRV::OpGroupNonUniformBallotFindMSB:
2107 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformBallot);
2109 case SPIRV::OpSubgroupShuffleINTEL:
2110 case SPIRV::OpSubgroupShuffleDownINTEL:
2111 case SPIRV::OpSubgroupShuffleUpINTEL:
2112 case SPIRV::OpSubgroupShuffleXorINTEL:
2113 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {
2114 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_subgroups);
2115 Reqs.
addCapability(SPIRV::Capability::SubgroupShuffleINTEL);
2118 case SPIRV::OpSubgroupBlockReadINTEL:
2119 case SPIRV::OpSubgroupBlockWriteINTEL:
2120 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {
2121 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_subgroups);
2122 Reqs.
addCapability(SPIRV::Capability::SubgroupBufferBlockIOINTEL);
2125 case SPIRV::OpSubgroupImageBlockReadINTEL:
2126 case SPIRV::OpSubgroupImageBlockWriteINTEL:
2127 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {
2128 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_subgroups);
2129 Reqs.
addCapability(SPIRV::Capability::SubgroupImageBlockIOINTEL);
2132 case SPIRV::OpSubgroupImageMediaBlockReadINTEL:
2133 case SPIRV::OpSubgroupImageMediaBlockWriteINTEL:
2134 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_media_block_io)) {
2135 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_media_block_io);
2136 Reqs.
addCapability(SPIRV::Capability::SubgroupImageMediaBlockIOINTEL);
2139 case SPIRV::OpAssumeTrueKHR:
2140 case SPIRV::OpExpectKHR:
2141 if (ST.canUseExtension(SPIRV::Extension::SPV_KHR_expect_assume)) {
2142 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_expect_assume);
2146 case SPIRV::OpFmaKHR:
2147 if (ST.canUseExtension(SPIRV::Extension::SPV_KHR_fma)) {
2152 case SPIRV::OpPtrCastToCrossWorkgroupINTEL:
2153 case SPIRV::OpCrossWorkgroupCastToPtrINTEL:
2154 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_usm_storage_classes)) {
2155 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_usm_storage_classes);
2156 Reqs.
addCapability(SPIRV::Capability::USMStorageClassesINTEL);
2159 case SPIRV::OpConstantFunctionPointerINTEL:
2160 case SPIRV::OpFunctionPointerCallINTEL:
2161 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_function_pointers)) {
2162 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_function_pointers);
2163 Reqs.
addCapability(SPIRV::Capability::FunctionPointersINTEL);
2166 case SPIRV::OpGroupNonUniformRotateKHR:
2167 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_subgroup_rotate))
2169 "following SPIR-V extension: SPV_KHR_subgroup_rotate",
2171 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_subgroup_rotate);
2172 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformRotateKHR);
2175 case SPIRV::OpFixedCosALTERA:
2176 case SPIRV::OpFixedSinALTERA:
2177 case SPIRV::OpFixedCosPiALTERA:
2178 case SPIRV::OpFixedSinPiALTERA:
2179 case SPIRV::OpFixedExpALTERA:
2180 case SPIRV::OpFixedLogALTERA:
2181 case SPIRV::OpFixedRecipALTERA:
2182 case SPIRV::OpFixedSqrtALTERA:
2183 case SPIRV::OpFixedSinCosALTERA:
2184 case SPIRV::OpFixedSinCosPiALTERA:
2185 case SPIRV::OpFixedRsqrtALTERA:
2186 if (!ST.canUseExtension(
2187 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_fixed_point))
2189 "following SPIR-V extension: "
2190 "SPV_ALTERA_arbitrary_precision_fixed_point",
2193 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_fixed_point);
2194 Reqs.
addCapability(SPIRV::Capability::ArbitraryPrecisionFixedPointALTERA);
2196 case SPIRV::OpGroupIMulKHR:
2197 case SPIRV::OpGroupFMulKHR:
2198 case SPIRV::OpGroupBitwiseAndKHR:
2199 case SPIRV::OpGroupBitwiseOrKHR:
2200 case SPIRV::OpGroupBitwiseXorKHR:
2201 case SPIRV::OpGroupLogicalAndKHR:
2202 case SPIRV::OpGroupLogicalOrKHR:
2203 case SPIRV::OpGroupLogicalXorKHR:
2204 if (ST.canUseExtension(
2205 SPIRV::Extension::SPV_KHR_uniform_group_instructions)) {
2206 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_uniform_group_instructions);
2207 Reqs.
addCapability(SPIRV::Capability::GroupUniformArithmeticKHR);
2210 case SPIRV::OpReadClockKHR:
2211 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_shader_clock))
2213 "following SPIR-V extension: SPV_KHR_shader_clock",
2215 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_shader_clock);
2218 case SPIRV::OpAbortKHR:
2219 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_abort))
2221 "following SPIR-V extension: SPV_KHR_abort",
2226 case SPIRV::OpPoisonKHR:
2227 case SPIRV::OpFreezeKHR:
2228 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_poison_freeze))
2230 "following SPIR-V extension: SPV_KHR_poison_freeze",
2232 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_poison_freeze);
2235 case SPIRV::OpAtomicFAddEXT:
2236 case SPIRV::OpAtomicFMinEXT:
2237 case SPIRV::OpAtomicFMaxEXT:
2240 case SPIRV::OpConvertBF16ToFINTEL:
2241 case SPIRV::OpConvertFToBF16INTEL:
2242 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bfloat16_conversion)) {
2243 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bfloat16_conversion);
2244 Reqs.
addCapability(SPIRV::Capability::BFloat16ConversionINTEL);
2247 case SPIRV::OpRoundFToTF32INTEL:
2248 if (ST.canUseExtension(
2249 SPIRV::Extension::SPV_INTEL_tensor_float32_conversion)) {
2250 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_tensor_float32_conversion);
2251 Reqs.
addCapability(SPIRV::Capability::TensorFloat32RoundingINTEL);
2254 case SPIRV::OpVariableLengthArrayINTEL:
2255 case SPIRV::OpSaveMemoryINTEL:
2256 case SPIRV::OpRestoreMemoryINTEL:
2257 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_variable_length_array)) {
2258 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_variable_length_array);
2259 Reqs.
addCapability(SPIRV::Capability::VariableLengthArrayINTEL);
2262 case SPIRV::OpUntypedVariableLengthArrayINTEL:
2263 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_variable_length_array)) {
2264 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_variable_length_array);
2265 Reqs.
addCapability(SPIRV::Capability::UntypedVariableLengthArrayINTEL);
2268 case SPIRV::OpAsmTargetINTEL:
2269 case SPIRV::OpAsmINTEL:
2270 case SPIRV::OpAsmCallINTEL:
2271 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_inline_assembly)) {
2272 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_inline_assembly);
2276 case SPIRV::OpTypeCooperativeMatrixKHR: {
2277 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix))
2279 "OpTypeCooperativeMatrixKHR type requires the "
2280 "following SPIR-V extension: SPV_KHR_cooperative_matrix",
2282 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix);
2283 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixKHR);
2287 Reqs.
addCapability(SPIRV::Capability::BFloat16CooperativeMatrixKHR);
2290 case SPIRV::OpArithmeticFenceEXT:
2291 if (!ST.canUseExtension(SPIRV::Extension::SPV_EXT_arithmetic_fence))
2293 "following SPIR-V extension: SPV_EXT_arithmetic_fence",
2295 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_arithmetic_fence);
2298 case SPIRV::OpControlBarrierArriveINTEL:
2299 case SPIRV::OpControlBarrierWaitINTEL:
2300 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_split_barrier)) {
2301 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_split_barrier);
2305 case SPIRV::OpCooperativeMatrixMulAddKHR: {
2306 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix))
2308 "following SPIR-V extension: "
2309 "SPV_KHR_cooperative_matrix",
2311 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix);
2312 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixKHR);
2313 constexpr unsigned MulAddMaxSize = 6;
2314 if (
MI.getNumOperands() != MulAddMaxSize)
2316 const int64_t CoopOperands =
MI.getOperand(MulAddMaxSize - 1).getImm();
2318 SPIRV::CooperativeMatrixOperands::MatrixAAndBTF32ComponentsINTEL) {
2319 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
2321 "require the following SPIR-V extension: "
2322 "SPV_INTEL_joint_matrix",
2324 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2326 SPIRV::Capability::CooperativeMatrixTF32ComponentTypeINTEL);
2329 MatrixAAndBBFloat16ComponentsINTEL ||
2331 SPIRV::CooperativeMatrixOperands::MatrixCBFloat16ComponentsINTEL ||
2333 MatrixResultBFloat16ComponentsINTEL) {
2334 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
2336 "require the following SPIR-V extension: "
2337 "SPV_INTEL_joint_matrix",
2339 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2341 SPIRV::Capability::CooperativeMatrixBFloat16ComponentTypeINTEL);
2345 case SPIRV::OpCooperativeMatrixLoadKHR:
2346 case SPIRV::OpCooperativeMatrixStoreKHR:
2347 case SPIRV::OpCooperativeMatrixLoadCheckedINTEL:
2348 case SPIRV::OpCooperativeMatrixStoreCheckedINTEL:
2349 case SPIRV::OpCooperativeMatrixPrefetchINTEL: {
2350 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix))
2352 "following SPIR-V extension: "
2353 "SPV_KHR_cooperative_matrix",
2355 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix);
2356 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixKHR);
2362 case SPIRV::OpCooperativeMatrixLoadKHR:
2365 case SPIRV::OpCooperativeMatrixStoreKHR:
2368 case SPIRV::OpCooperativeMatrixLoadCheckedINTEL:
2371 case SPIRV::OpCooperativeMatrixStoreCheckedINTEL:
2372 case SPIRV::OpCooperativeMatrixPrefetchINTEL:
2378 Register RegLayout =
MI.getOperand(LayoutNum).getReg();
2381 if (MILayout->
getOpcode() == SPIRV::OpConstantI) {
2384 static_cast<unsigned>(SPIRV::CooperativeMatrixLayout::PackedINTEL)) {
2385 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
2387 "extension: SPV_INTEL_joint_matrix",
2389 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2390 Reqs.
addCapability(SPIRV::Capability::PackedCooperativeMatrixINTEL);
2395 if (
Op == SPIRV::OpCooperativeMatrixLoadKHR ||
2396 Op == SPIRV::OpCooperativeMatrixStoreKHR)
2399 std::string InstName;
2401 case SPIRV::OpCooperativeMatrixPrefetchINTEL:
2402 InstName =
"OpCooperativeMatrixPrefetchINTEL";
2404 case SPIRV::OpCooperativeMatrixLoadCheckedINTEL:
2405 InstName =
"OpCooperativeMatrixLoadCheckedINTEL";
2407 case SPIRV::OpCooperativeMatrixStoreCheckedINTEL:
2408 InstName =
"OpCooperativeMatrixStoreCheckedINTEL";
2412 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix)) {
2413 const std::string ErrorMsg =
2414 InstName +
" instruction requires the "
2415 "following SPIR-V extension: SPV_INTEL_joint_matrix";
2418 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2419 if (
Op == SPIRV::OpCooperativeMatrixPrefetchINTEL) {
2420 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixPrefetchINTEL);
2424 SPIRV::Capability::CooperativeMatrixCheckedInstructionsINTEL);
2427 case SPIRV::OpCooperativeMatrixConstructCheckedINTEL:
2428 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
2430 "instructions require the following SPIR-V extension: "
2431 "SPV_INTEL_joint_matrix",
2433 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2435 SPIRV::Capability::CooperativeMatrixCheckedInstructionsINTEL);
2437 case SPIRV::OpReadPipeBlockingALTERA:
2438 case SPIRV::OpWritePipeBlockingALTERA:
2439 if (ST.canUseExtension(SPIRV::Extension::SPV_ALTERA_blocking_pipes)) {
2440 Reqs.
addExtension(SPIRV::Extension::SPV_ALTERA_blocking_pipes);
2444 case SPIRV::OpCooperativeMatrixGetElementCoordINTEL:
2445 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
2447 "following SPIR-V extension: SPV_INTEL_joint_matrix",
2449 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2451 SPIRV::Capability::CooperativeMatrixInvocationInstructionsINTEL);
2453 case SPIRV::OpConvertHandleToImageINTEL:
2454 case SPIRV::OpConvertHandleToSamplerINTEL:
2455 case SPIRV::OpConvertHandleToSampledImageINTEL: {
2456 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bindless_images))
2458 "instructions require the following SPIR-V extension: "
2459 "SPV_INTEL_bindless_images",
2462 SPIRV::AddressingModel::AddressingModel AddrModel = MAI.
Addr;
2464 if (
Op == SPIRV::OpConvertHandleToImageINTEL &&
2465 TyDef->
getOpcode() != SPIRV::OpTypeImage) {
2467 "OpConvertHandleToImageINTEL",
2469 }
else if (
Op == SPIRV::OpConvertHandleToSamplerINTEL &&
2470 TyDef->
getOpcode() != SPIRV::OpTypeSampler) {
2472 "OpConvertHandleToSamplerINTEL",
2474 }
else if (
Op == SPIRV::OpConvertHandleToSampledImageINTEL &&
2475 TyDef->
getOpcode() != SPIRV::OpTypeSampledImage) {
2477 "OpConvertHandleToSampledImageINTEL",
2483 if (!(Bitwidth == 32 && AddrModel == SPIRV::AddressingModel::Physical32) &&
2484 !(Bitwidth == 64 && AddrModel == SPIRV::AddressingModel::Physical64)) {
2486 "Parameter value must be a 32-bit scalar in case of "
2487 "Physical32 addressing model or a 64-bit scalar in case of "
2488 "Physical64 addressing model",
2491 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bindless_images);
2495 case SPIRV::OpSubgroup2DBlockLoadINTEL:
2496 case SPIRV::OpSubgroup2DBlockLoadTransposeINTEL:
2497 case SPIRV::OpSubgroup2DBlockLoadTransformINTEL:
2498 case SPIRV::OpSubgroup2DBlockPrefetchINTEL:
2499 case SPIRV::OpSubgroup2DBlockStoreINTEL: {
2500 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_2d_block_io))
2502 "Prefetch/Store]INTEL instructions require the "
2503 "following SPIR-V extension: SPV_INTEL_2d_block_io",
2505 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_2d_block_io);
2506 Reqs.
addCapability(SPIRV::Capability::Subgroup2DBlockIOINTEL);
2508 if (
Op == SPIRV::OpSubgroup2DBlockLoadTransposeINTEL) {
2509 Reqs.
addCapability(SPIRV::Capability::Subgroup2DBlockTransposeINTEL);
2512 if (
Op == SPIRV::OpSubgroup2DBlockLoadTransformINTEL) {
2513 Reqs.
addCapability(SPIRV::Capability::Subgroup2DBlockTransformINTEL);
2518 case SPIRV::OpKill: {
2521 case SPIRV::OpDemoteToHelperInvocation:
2522 Reqs.
addCapability(SPIRV::Capability::DemoteToHelperInvocation);
2524 if (ST.canUseExtension(
2525 SPIRV::Extension::SPV_EXT_demote_to_helper_invocation)) {
2528 SPIRV::Extension::SPV_EXT_demote_to_helper_invocation);
2533 case SPIRV::OpSUDot:
2534 case SPIRV::OpSDotAccSat:
2535 case SPIRV::OpUDotAccSat:
2536 case SPIRV::OpSUDotAccSat:
2539 case SPIRV::OpImageSampleImplicitLod:
2540 case SPIRV::OpImageFetch:
2544 case SPIRV::OpImageSampleExplicitLod:
2547 case SPIRV::OpImageSampleDrefImplicitLod:
2548 case SPIRV::OpImageSampleDrefExplicitLod:
2549 case SPIRV::OpImageDrefGather:
2550 case SPIRV::OpImageGather:
2554 case SPIRV::OpImageRead: {
2555 Register ImageReg =
MI.getOperand(2).getReg();
2556 SPIRVTypeInst TypeDef = ST.getSPIRVGlobalRegistry()->getResultType(
2565 Reqs.
addCapability(SPIRV::Capability::StorageImageReadWithoutFormat);
2568 case SPIRV::OpImageWrite: {
2569 Register ImageReg =
MI.getOperand(0).getReg();
2570 SPIRVTypeInst TypeDef = ST.getSPIRVGlobalRegistry()->getResultType(
2579 Reqs.
addCapability(SPIRV::Capability::StorageImageWriteWithoutFormat);
2582 case SPIRV::OpTypeStructContinuedINTEL:
2583 case SPIRV::OpConstantCompositeContinuedINTEL:
2584 case SPIRV::OpSpecConstantCompositeContinuedINTEL:
2585 case SPIRV::OpCompositeConstructContinuedINTEL: {
2586 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_long_composites))
2588 "Continued instructions require the "
2589 "following SPIR-V extension: SPV_INTEL_long_composites",
2591 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_long_composites);
2595 case SPIRV::OpArbitraryFloatEQALTERA:
2596 case SPIRV::OpArbitraryFloatGEALTERA:
2597 case SPIRV::OpArbitraryFloatGTALTERA:
2598 case SPIRV::OpArbitraryFloatLEALTERA:
2599 case SPIRV::OpArbitraryFloatLTALTERA:
2600 case SPIRV::OpArbitraryFloatCbrtALTERA:
2601 case SPIRV::OpArbitraryFloatCosALTERA:
2602 case SPIRV::OpArbitraryFloatCosPiALTERA:
2603 case SPIRV::OpArbitraryFloatExp10ALTERA:
2604 case SPIRV::OpArbitraryFloatExp2ALTERA:
2605 case SPIRV::OpArbitraryFloatExpALTERA:
2606 case SPIRV::OpArbitraryFloatExpm1ALTERA:
2607 case SPIRV::OpArbitraryFloatHypotALTERA:
2608 case SPIRV::OpArbitraryFloatLog10ALTERA:
2609 case SPIRV::OpArbitraryFloatLog1pALTERA:
2610 case SPIRV::OpArbitraryFloatLog2ALTERA:
2611 case SPIRV::OpArbitraryFloatLogALTERA:
2612 case SPIRV::OpArbitraryFloatRecipALTERA:
2613 case SPIRV::OpArbitraryFloatSinCosALTERA:
2614 case SPIRV::OpArbitraryFloatSinCosPiALTERA:
2615 case SPIRV::OpArbitraryFloatSinALTERA:
2616 case SPIRV::OpArbitraryFloatSinPiALTERA:
2617 case SPIRV::OpArbitraryFloatSqrtALTERA:
2618 case SPIRV::OpArbitraryFloatACosALTERA:
2619 case SPIRV::OpArbitraryFloatACosPiALTERA:
2620 case SPIRV::OpArbitraryFloatAddALTERA:
2621 case SPIRV::OpArbitraryFloatASinALTERA:
2622 case SPIRV::OpArbitraryFloatASinPiALTERA:
2623 case SPIRV::OpArbitraryFloatATan2ALTERA:
2624 case SPIRV::OpArbitraryFloatATanALTERA:
2625 case SPIRV::OpArbitraryFloatATanPiALTERA:
2626 case SPIRV::OpArbitraryFloatCastFromIntALTERA:
2627 case SPIRV::OpArbitraryFloatCastALTERA:
2628 case SPIRV::OpArbitraryFloatCastToIntALTERA:
2629 case SPIRV::OpArbitraryFloatDivALTERA:
2630 case SPIRV::OpArbitraryFloatMulALTERA:
2631 case SPIRV::OpArbitraryFloatPowALTERA:
2632 case SPIRV::OpArbitraryFloatPowNALTERA:
2633 case SPIRV::OpArbitraryFloatPowRALTERA:
2634 case SPIRV::OpArbitraryFloatRSqrtALTERA:
2635 case SPIRV::OpArbitraryFloatSubALTERA: {
2636 if (!ST.canUseExtension(
2637 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_floating_point))
2639 "Floating point instructions can't be translated correctly without "
2640 "enabled SPV_ALTERA_arbitrary_precision_floating_point extension!",
2643 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_floating_point);
2645 SPIRV::Capability::ArbitraryPrecisionFloatingPointALTERA);
2648 case SPIRV::OpSubgroupMatrixMultiplyAccumulateINTEL: {
2649 if (!ST.canUseExtension(
2650 SPIRV::Extension::SPV_INTEL_subgroup_matrix_multiply_accumulate))
2652 "OpSubgroupMatrixMultiplyAccumulateINTEL instruction requires the "
2654 "extension: SPV_INTEL_subgroup_matrix_multiply_accumulate",
2657 SPIRV::Extension::SPV_INTEL_subgroup_matrix_multiply_accumulate);
2659 SPIRV::Capability::SubgroupMatrixMultiplyAccumulateINTEL);
2662 case SPIRV::OpBitwiseFunctionINTEL: {
2663 if (!ST.canUseExtension(
2664 SPIRV::Extension::SPV_INTEL_ternary_bitwise_function))
2666 "OpBitwiseFunctionINTEL instruction requires the following SPIR-V "
2667 "extension: SPV_INTEL_ternary_bitwise_function",
2669 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_ternary_bitwise_function);
2670 Reqs.
addCapability(SPIRV::Capability::TernaryBitwiseFunctionINTEL);
2673 case SPIRV::OpCopyMemorySized: {
2678 case SPIRV::OpTypeUntypedPointerKHR:
2680 MI.getOperand(1).getImm(), ST);
2682 case SPIRV::OpUntypedVariableKHR:
2683 case SPIRV::OpUntypedAccessChainKHR:
2684 case SPIRV::OpUntypedInBoundsAccessChainKHR:
2685 case SPIRV::OpUntypedPtrAccessChainKHR:
2686 case SPIRV::OpUntypedInBoundsPtrAccessChainKHR:
2687 case SPIRV::OpUntypedPrefetchKHR:
2688 case SPIRV::OpUntypedGroupAsyncCopyKHR: {
2689 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_untyped_pointers))
2691 "SPIR-V extension: SPV_KHR_untyped_pointers",
2693 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_untyped_pointers);
2697 case SPIRV::OpPredicatedLoadINTEL:
2698 case SPIRV::OpPredicatedStoreINTEL: {
2699 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_predicated_io))
2701 "OpPredicated[Load/Store]INTEL instructions require "
2702 "the following SPIR-V extension: SPV_INTEL_predicated_io",
2704 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_predicated_io);
2708 case SPIRV::OpFAddS:
2709 case SPIRV::OpFSubS:
2710 case SPIRV::OpFMulS:
2711 case SPIRV::OpFDivS:
2712 case SPIRV::OpFRemS:
2714 case SPIRV::OpFNegate:
2715 case SPIRV::OpFAddV:
2716 case SPIRV::OpFSubV:
2717 case SPIRV::OpFMulV:
2718 case SPIRV::OpFDivV:
2719 case SPIRV::OpFRemV:
2720 case SPIRV::OpFNegateV: {
2726 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic))
2728 "Arithmetic instructions with bfloat16 arguments require the "
2729 "following SPIR-V extension: SPV_INTEL_bfloat16_arithmetic",
2731 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic);
2732 Reqs.
addCapability(SPIRV::Capability::BFloat16ArithmeticINTEL);
2736 case SPIRV::OpOrdered:
2737 case SPIRV::OpUnordered:
2738 case SPIRV::OpFOrdEqual:
2739 case SPIRV::OpFOrdNotEqual:
2740 case SPIRV::OpFOrdLessThan:
2741 case SPIRV::OpFOrdLessThanEqual:
2742 case SPIRV::OpFOrdGreaterThan:
2743 case SPIRV::OpFOrdGreaterThanEqual:
2744 case SPIRV::OpFUnordEqual:
2745 case SPIRV::OpFUnordNotEqual:
2746 case SPIRV::OpFUnordLessThan:
2747 case SPIRV::OpFUnordLessThanEqual:
2748 case SPIRV::OpFUnordGreaterThan:
2749 case SPIRV::OpFUnordGreaterThanEqual: {
2752 ST.getSPIRVGlobalRegistry());
2753 assert(TypeDef &&
"Unexpected type instruction for comparison operand");
2757 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic))
2759 "Relational instructions with bfloat16 arguments require the "
2760 "following SPIR-V extension: SPV_INTEL_bfloat16_arithmetic",
2762 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic);
2763 Reqs.
addCapability(SPIRV::Capability::BFloat16ArithmeticINTEL);
2767 case SPIRV::OpDPdxCoarse:
2768 case SPIRV::OpDPdyCoarse:
2769 case SPIRV::OpDPdxFine:
2770 case SPIRV::OpDPdyFine: {
2774 case SPIRV::OpLoopControlINTEL: {
2775 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_unstructured_loop_controls);
2776 Reqs.
addCapability(SPIRV::Capability::UnstructuredLoopControlsINTEL);
2788 SPIRV::Capability::Shader);
2803 auto Node = M.getNamedMetadata(
"spirv.ExecutionMode");
2805 bool RequireFloatControls =
false, RequireIntelFloatControls2 =
false,
2806 RequireKHRFloatControls2 =
false,
2807 VerLower14 = !ST.isAtLeastSPIRVVer(
VersionTuple(1, 4));
2808 bool HasIntelFloatControls2 =
2809 ST.canUseExtension(SPIRV::Extension::SPV_INTEL_float_controls2);
2810 bool HasKHRFloatControls2 =
2811 ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2);
2812 for (
unsigned i = 0; i <
Node->getNumOperands(); i++) {
2818 auto EM = Const->getZExtValue();
2822 case SPIRV::ExecutionMode::DenormPreserve:
2823 case SPIRV::ExecutionMode::DenormFlushToZero:
2824 case SPIRV::ExecutionMode::RoundingModeRTE:
2825 case SPIRV::ExecutionMode::RoundingModeRTZ:
2826 RequireFloatControls = VerLower14;
2828 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2830 case SPIRV::ExecutionMode::RoundingModeRTPINTEL:
2831 case SPIRV::ExecutionMode::RoundingModeRTNINTEL:
2832 case SPIRV::ExecutionMode::FloatingPointModeALTINTEL:
2833 case SPIRV::ExecutionMode::FloatingPointModeIEEEINTEL:
2834 if (HasIntelFloatControls2) {
2835 RequireIntelFloatControls2 =
true;
2837 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2840 case SPIRV::ExecutionMode::FPFastMathDefault: {
2841 if (HasKHRFloatControls2) {
2842 RequireKHRFloatControls2 =
true;
2844 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2848 case SPIRV::ExecutionMode::ContractionOff:
2849 case SPIRV::ExecutionMode::SignedZeroInfNanPreserve:
2850 if (HasKHRFloatControls2) {
2851 RequireKHRFloatControls2 =
true;
2853 SPIRV::OperandCategory::ExecutionModeOperand,
2854 SPIRV::ExecutionMode::FPFastMathDefault, ST);
2857 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2862 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2867 if (RequireFloatControls &&
2868 ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls))
2870 if (RequireIntelFloatControls2)
2872 if (RequireKHRFloatControls2)
2876 if (
F.isDeclaration())
2878 if (
F.getMetadata(
"reqd_work_group_size"))
2880 SPIRV::OperandCategory::ExecutionModeOperand,
2881 SPIRV::ExecutionMode::LocalSize, ST);
2882 if (
F.getFnAttribute(
"hlsl.numthreads").isValid()) {
2884 SPIRV::OperandCategory::ExecutionModeOperand,
2885 SPIRV::ExecutionMode::LocalSize, ST);
2887 if (
F.getFnAttribute(
"enable-maximal-reconvergence").getValueAsBool()) {
2890 if (
F.getMetadata(
"work_group_size_hint"))
2892 SPIRV::OperandCategory::ExecutionModeOperand,
2893 SPIRV::ExecutionMode::LocalSizeHint, ST);
2894 if (
F.getMetadata(
"intel_reqd_sub_group_size") ||
2895 F.getMetadata(
"reqd_sub_group_size"))
2897 SPIRV::OperandCategory::ExecutionModeOperand,
2898 SPIRV::ExecutionMode::SubgroupSize, ST);
2899 if (
F.getMetadata(
"max_work_group_size"))
2901 SPIRV::OperandCategory::ExecutionModeOperand,
2902 SPIRV::ExecutionMode::MaxWorkgroupSizeINTEL, ST);
2903 if (
F.getMetadata(
"vec_type_hint"))
2905 SPIRV::OperandCategory::ExecutionModeOperand,
2906 SPIRV::ExecutionMode::VecTypeHint, ST);
2908 if (
F.hasOptNone()) {
2909 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_optnone)) {
2912 }
else if (ST.canUseExtension(SPIRV::Extension::SPV_EXT_optnone)) {
2922 unsigned Flags = SPIRV::FPFastMathMode::None;
2923 bool CanUseKHRFloatControls2 =
2924 ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2);
2926 Flags |= SPIRV::FPFastMathMode::NotNaN;
2928 Flags |= SPIRV::FPFastMathMode::NotInf;
2930 Flags |= SPIRV::FPFastMathMode::NSZ;
2932 Flags |= SPIRV::FPFastMathMode::AllowRecip;
2934 Flags |= SPIRV::FPFastMathMode::AllowContract;
2936 if (CanUseKHRFloatControls2)
2944 Flags |= SPIRV::FPFastMathMode::NotNaN | SPIRV::FPFastMathMode::NotInf |
2945 SPIRV::FPFastMathMode::NSZ | SPIRV::FPFastMathMode::AllowRecip |
2946 SPIRV::FPFastMathMode::AllowTransform |
2947 SPIRV::FPFastMathMode::AllowReassoc |
2948 SPIRV::FPFastMathMode::AllowContract;
2950 Flags |= SPIRV::FPFastMathMode::Fast;
2953 if (CanUseKHRFloatControls2) {
2955 assert(!(Flags & SPIRV::FPFastMathMode::Fast) &&
2956 "SPIRV::FPFastMathMode::Fast is deprecated and should not be used "
2961 assert((!(Flags & SPIRV::FPFastMathMode::AllowTransform) ||
2962 ((Flags & SPIRV::FPFastMathMode::AllowReassoc &&
2963 Flags & SPIRV::FPFastMathMode::AllowContract))) &&
2964 "SPIRV::FPFastMathMode::AllowTransform requires AllowReassoc and "
2965 "AllowContract flags to be enabled as well.");
2976 return ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2);
2986 auto Decorate = [&](SPIRV::Decoration::Decoration Dec,
2993 if (
TII.canUseIntegerWrapDecoration(
I)) {
2996 SPIRV::OperandCategory::DecorationOperand,
2997 SPIRV::Decoration::NoSignedWrap, ST, Reqs)
2999 Decorate(SPIRV::Decoration::NoSignedWrap, {});
3002 SPIRV::OperandCategory::DecorationOperand,
3003 SPIRV::Decoration::NoUnsignedWrap, ST, Reqs)
3005 Decorate(SPIRV::Decoration::NoUnsignedWrap, {});
3010 TII.canUseFastMathFlags(
3011 I, ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2)) ||
3012 (ST.isKernel() &&
I.getOpcode() == SPIRV::OpExtInst);
3017 if (FMFlags == SPIRV::FPFastMathMode::None) {
3020 if (FPFastMathDefaultInfoVec.
empty())
3026 I.getOpcode() == SPIRV::OpExtInst ||
3027 I.getOpcode() == SPIRV::OpFunctionCall
3028 ?
I.getMF()->getRegInfo().getVRegDef(
I.getOperand(1).getReg())
3029 :
getRegType(
I.getOperand(2).getReg(), *
I.getMF(), GR);
3036 if (Ty == Elem.Ty) {
3037 FMFlags = Elem.FastMathFlags;
3038 Emit = Elem.ContractionOff || Elem.SignedZeroInfNanPreserve ||
3039 Elem.FPFastMathDefault;
3044 if (FMFlags == SPIRV::FPFastMathMode::None && !Emit)
3048 Decorate(SPIRV::Decoration::FPFastMathMode, {FMFlags});
3062 for (
const auto &
MBB : *MF) {
3063 if (!
MBB.hasName() ||
MBB.empty())
3074 auto it = FPFastMathDefaultInfoMap.
find(
F);
3075 if (it != FPFastMathDefaultInfoMap.
end())
3083 SPIRV::FPFastMathMode::None);
3085 SPIRV::FPFastMathMode::None);
3087 SPIRV::FPFastMathMode::None);
3088 return FPFastMathDefaultInfoMap[
F] = std::move(FPFastMathDefaultInfoVec);
3094 size_t BitWidth = Ty->getScalarSizeInBits();
3098 assert(Index >= 0 && Index < 3 &&
3099 "Expected FPFastMathDefaultInfo for half, float, or double");
3100 assert(FPFastMathDefaultInfoVec.
size() == 3 &&
3101 "Expected FPFastMathDefaultInfoVec to have exactly 3 elements");
3102 return FPFastMathDefaultInfoVec[Index];
3109 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2))
3118 auto Node = M.getNamedMetadata(
"spirv.ExecutionMode");
3122 for (
unsigned i = 0; i <
Node->getNumOperands(); i++) {
3127 if (OnlyF &&
F != OnlyF)
3133 if (EM == SPIRV::ExecutionMode::FPFastMathDefault) {
3135 "Expected 4 operands for FPFastMathDefault");
3146 Info.FastMathFlags = Flags;
3147 Info.FPFastMathDefault =
true;
3148 }
else if (EM == SPIRV::ExecutionMode::ContractionOff) {
3150 "Expected no operands for ContractionOff");
3157 Info.ContractionOff =
true;
3159 }
else if (EM == SPIRV::ExecutionMode::SignedZeroInfNanPreserve) {
3161 "Expected 1 operand for SignedZeroInfNanPreserve");
3162 unsigned TargetWidth =
3171 assert(Index >= 0 && Index < 3 &&
3172 "Expected FPFastMathDefaultInfo for half, float, or double");
3173 assert(FPFastMathDefaultInfoVec.
size() == 3 &&
3174 "Expected FPFastMathDefaultInfoVec to have exactly 3 elements");
3175 FPFastMathDefaultInfoVec[Index].SignedZeroInfNanPreserve =
true;
3183 : ST(&ST), GR(ST.getSPIRVGlobalRegistry()), TII(ST.getInstrInfo()),
3184 MAI(MAI), GetMF(GetMF) {}
3196 collectDeclarations(M);
3199 numberRegistersGlobally(M);
3202 processOtherInstrs(M);
3206 MAI.Reqs.addCapability(SPIRV::Capability::Linkage);
3209 GR->setBound(MAI.MaxID);
3223 [&MMI](
const Function &
F) { return MMI.getMachineFunction(F); })
3239 MachineFunctionAnalysis::Result *MFA =
3240 FAM.getCachedResult<MachineFunctionAnalysis>(
3241 const_cast<Function &>(F));
3242 assert((MFA || F.isDeclaration()) &&
3243 "Missing MachineFunction for definition");
3244 return MFA ? &MFA->getMF() : nullptr;
3261 for (
auto &
MBB : MF)
3264 FPFastMathDefaultInfoMap[&
F]);
3272 SPIRVPrepareModuleAnalysisLegacy() : MachineFunctionPass(
ID) {}
3279char SPIRVPrepareModuleAnalysisLegacy::ID = 0;
3282 "spirv-prepare-module-analysis",
3283 "SPIRV prepare module analysis",
false,
false)
3286 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")
#define clEnumValN(ENUMVAL, FLAGNAME, DESC)
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 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::Hidden, cl::values(clEnumValN(SPIRV::Capability::Shader, "Shader", "SPIR-V Shader capability")))
static unsigned getInvokeOperandIdx(unsigned Opcode)
static SPIRV::FPFastMathDefaultInfo & getFPFastMathDefaultInfo(SPIRV::FPFastMathDefaultInfoVector &FPFastMathDefaultInfoVec, const Type *Ty)
static cl::opt< bool > SPVDumpDeps("spv-dump-deps", cl::desc("Dump MIR with SPIR-V dependencies info"), cl::init(false))
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 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 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
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.
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)
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
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)
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.
SmallSet< SPIRV::Capability::Capability, 4 > S
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