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()) {
1034 if (!ST.isShader()) {
1035 initAvailableCapabilitiesForOpenCL(ST);
1039 if (ST.isShader()) {
1040 initAvailableCapabilitiesForVulkan(ST);
1047void RequirementHandler::initAvailableCapabilitiesForOpenCL(
1051 Capability::Kernel, Capability::Vector16,
1052 Capability::Groups, Capability::GenericPointer,
1053 Capability::StorageImageWriteWithoutFormat,
1054 Capability::StorageImageReadWithoutFormat});
1055 if (ST.hasOpenCLFullProfile())
1057 if (ST.hasOpenCLImageSupport()) {
1059 Capability::Image1D, Capability::SampledBuffer,
1060 Capability::ImageBuffer});
1061 if (
ST.isAtLeastOpenCLVer(VersionTuple(2, 0)))
1064 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 1)) &&
1065 ST.isAtLeastOpenCLVer(VersionTuple(2, 2)))
1067 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 4)))
1068 addAvailableCaps({Capability::DenormPreserve, Capability::DenormFlushToZero,
1069 Capability::SignedZeroInfNanPreserve,
1070 Capability::RoundingModeRTE,
1071 Capability::RoundingModeRTZ});
1078void RequirementHandler::initAvailableCapabilitiesForVulkan(
1079 const SPIRVSubtarget &ST) {
1083 Capability::Geometry,
1084 Capability::Float16,
1085 Capability::Float64,
1086 Capability::GroupNonUniform,
1087 Capability::Image1D,
1088 Capability::SampledBuffer,
1089 Capability::ImageBuffer,
1090 Capability::UniformBufferArrayDynamicIndexing,
1091 Capability::SampledImageArrayDynamicIndexing,
1092 Capability::StorageBufferArrayDynamicIndexing,
1093 Capability::StorageImageArrayDynamicIndexing,
1094 Capability::DerivativeControl,
1095 Capability::SampleRateShading,
1097 Capability::ImageQuery,
1098 Capability::ImageGatherExtended,
1099 Capability::Addresses,
1100 Capability::VulkanMemoryModelKHR,
1101 Capability::StorageImageExtendedFormats,
1102 Capability::StorageImageMultisample,
1103 Capability::ImageMSArray});
1105 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 3)) ||
1106 ST.canUseExtension(Extension::SPV_KHR_variable_pointers))
1108 Capability::VariablePointers});
1111 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 3)))
1115 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 5))) {
1117 {Capability::Int64Atomics, Capability::ShaderNonUniformEXT,
1118 Capability::RuntimeDescriptorArrayEXT,
1119 Capability::InputAttachmentArrayDynamicIndexingEXT,
1120 Capability::UniformTexelBufferArrayDynamicIndexingEXT,
1121 Capability::StorageTexelBufferArrayDynamicIndexingEXT,
1122 Capability::UniformBufferArrayNonUniformIndexingEXT,
1123 Capability::SampledImageArrayNonUniformIndexingEXT,
1124 Capability::StorageBufferArrayNonUniformIndexingEXT,
1125 Capability::StorageImageArrayNonUniformIndexingEXT,
1126 Capability::InputAttachmentArrayNonUniformIndexingEXT,
1127 Capability::UniformTexelBufferArrayNonUniformIndexingEXT,
1128 Capability::StorageTexelBufferArrayNonUniformIndexingEXT});
1132 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 6)))
1134 Capability::StorageImageReadWithoutFormat});
1144 SPIRV::Capability::Capability Cap,
1145 SPIRV::Extension::Extension Ext) {
1149 if (!ST.canUseExtension(Ext))
1151 Twine(
"capability ") +
1153 SPIRV::OperandCategory::CapabilityOperand, Cap) +
1154 " requires SPIR-V 1.3 or the following SPIR-V extension: " +
1166 int64_t DecOp =
MI.getOperand(DecIndex).getImm();
1167 auto Dec =
static_cast<SPIRV::Decoration::Decoration
>(DecOp);
1169 SPIRV::OperandCategory::DecorationOperand, Dec, ST, Reqs));
1171 if (Dec == SPIRV::Decoration::BuiltIn) {
1172 int64_t BuiltInOp =
MI.getOperand(DecIndex + 1).getImm();
1173 auto BuiltIn =
static_cast<SPIRV::BuiltIn::BuiltIn
>(BuiltInOp);
1174 if ((BuiltIn == SPIRV::BuiltIn::BaryCoordKHR ||
1175 BuiltIn == SPIRV::BuiltIn::BaryCoordNoPerspKHR) &&
1176 !ST.canUseExtension(
1177 SPIRV::Extension::SPV_KHR_fragment_shader_barycentric))
1179 "Barycentric built-ins require the following SPIR-V extension: "
1180 "SPV_KHR_fragment_shader_barycentric",
1183 case SPIRV::BuiltIn::BaseVertex:
1184 case SPIRV::BuiltIn::BaseInstance:
1186 Reqs, ST, SPIRV::Capability::DrawParameters,
1187 SPIRV::Extension::SPV_KHR_shader_draw_parameters);
1189 case SPIRV::BuiltIn::ViewIndex:
1191 SPIRV::Extension::SPV_KHR_multiview);
1195 SPIRV::OperandCategory::BuiltInOperand, BuiltIn, ST, Reqs));
1198 }
else if (Dec == SPIRV::Decoration::LinkageAttributes) {
1199 int64_t LinkageOp =
MI.getOperand(
MI.getNumOperands() - 1).getImm();
1200 SPIRV::LinkageType::LinkageType LnkType =
1201 static_cast<SPIRV::LinkageType::LinkageType
>(LinkageOp);
1202 if (LnkType == SPIRV::LinkageType::LinkOnceODR)
1203 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_linkonce_odr);
1204 else if (LnkType == SPIRV::LinkageType::WeakAMD) {
1205 Reqs.
addExtension(SPIRV::Extension::SPV_AMD_weak_linkage);
1208 }
else if (Dec == SPIRV::Decoration::CacheControlLoadINTEL ||
1209 Dec == SPIRV::Decoration::CacheControlStoreINTEL) {
1210 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_cache_controls);
1211 }
else if (Dec == SPIRV::Decoration::HostAccessINTEL) {
1212 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_global_variable_host_access);
1213 }
else if (Dec == SPIRV::Decoration::InitModeINTEL ||
1214 Dec == SPIRV::Decoration::ImplementInRegisterMapINTEL) {
1216 SPIRV::Extension::SPV_INTEL_global_variable_fpga_decorations);
1217 }
else if (Dec == SPIRV::Decoration::NonUniformEXT) {
1219 }
else if (Dec == SPIRV::Decoration::FPMaxErrorDecorationINTEL) {
1221 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_fp_max_error);
1222 }
else if (Dec == SPIRV::Decoration::FPFastMathMode) {
1223 if (ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2)) {
1225 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_float_controls2);
1234 assert(
MI.getNumOperands() >= 8 &&
"Insufficient operands for OpTypeImage");
1237 int64_t ImgFormatOp =
MI.getOperand(7).getImm();
1238 auto ImgFormat =
static_cast<SPIRV::ImageFormat::ImageFormat
>(ImgFormatOp);
1242 bool IsArrayed =
MI.getOperand(4).getImm() == 1;
1243 bool IsMultisampled =
MI.getOperand(5).getImm() == 1;
1244 bool NoSampler =
MI.getOperand(6).getImm() == 2;
1247 switch (
MI.getOperand(2).getImm()) {
1248 case SPIRV::Dim::DIM_1D:
1250 : SPIRV::Capability::Sampled1D);
1252 case SPIRV::Dim::DIM_2D:
1253 if (IsMultisampled && NoSampler)
1255 if (IsMultisampled && IsArrayed)
1258 case SPIRV::Dim::DIM_3D:
1260 case SPIRV::Dim::DIM_Cube:
1264 : SPIRV::Capability::SampledCubeArray);
1266 case SPIRV::Dim::DIM_Rect:
1268 : SPIRV::Capability::SampledRect);
1270 case SPIRV::Dim::DIM_Buffer:
1272 : SPIRV::Capability::SampledBuffer);
1274 case SPIRV::Dim::DIM_SubpassData:
1280 if (!ST.isShader()) {
1281 if (
MI.getNumOperands() > 8 &&
1282 MI.getOperand(8).getImm() == SPIRV::AccessQualifier::ReadWrite)
1291 TypeDef->
getOpcode() == SPIRV::OpTypeFloat &&
1303 return MRI.getVRegDef(
MRI.getVRegDef(
Reg)->getOperand(1).getReg());
1307#define ATOM_FLT_REQ_EXT_MSG(ExtName) \
1308 "The atomic float instruction requires the following SPIR-V " \
1309 "extension: SPV_EXT_shader_atomic_float" ExtName
1314 MI.getMF()->getRegInfo().getVRegDef(
MI.getOperand(1).getReg());
1317 if (Rank != 2 && Rank != 4)
1319 "must be a 2-component or 4 component vector");
1324 if (EltTypeDef->
getOpcode() != SPIRV::OpTypeFloat ||
1327 "The element type for the result type of an atomic vector float "
1328 "instruction must be a 16-bit floating-point scalar");
1335 "The element type for the result type of an atomic vector float "
1336 "instruction cannot be a bfloat16 scalar");
1337 if (!ST.canUseExtension(SPIRV::Extension::SPV_NV_shader_atomic_fp16_vector))
1339 "The atomic float16 vector instruction requires the following SPIR-V "
1340 "extension: SPV_NV_shader_atomic_fp16_vector");
1342 Reqs.
addExtension(SPIRV::Extension::SPV_NV_shader_atomic_fp16_vector);
1343 Reqs.
addCapability(SPIRV::Capability::AtomicFloat16VectorNV);
1350 "Expect register operand in atomic float instruction");
1351 Register TypeReg =
MI.getOperand(1).getReg();
1357 if (TypeDef->
getOpcode() != SPIRV::OpTypeFloat)
1359 "floating-point type scalar");
1362 unsigned Op =
MI.getOpcode();
1363 if (
Op == SPIRV::OpAtomicFAddEXT) {
1364 if (!ST.canUseExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float_add))
1366 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float_add);
1370 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics))
1372 "The atomic bfloat16 instruction requires the following SPIR-V "
1373 "extension: SPV_INTEL_16bit_atomics",
1375 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics);
1376 Reqs.
addCapability(SPIRV::Capability::AtomicBFloat16AddINTEL);
1378 if (!ST.canUseExtension(
1379 SPIRV::Extension::SPV_EXT_shader_atomic_float16_add))
1381 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float16_add);
1393 "Unexpected floating-point type width in atomic float instruction");
1396 if (!ST.canUseExtension(
1397 SPIRV::Extension::SPV_EXT_shader_atomic_float_min_max))
1399 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float_min_max);
1403 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics))
1405 "The atomic bfloat16 instruction requires the following SPIR-V "
1406 "extension: SPV_INTEL_16bit_atomics",
1408 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics);
1409 Reqs.
addCapability(SPIRV::Capability::AtomicBFloat16MinMaxINTEL);
1411 Reqs.
addCapability(SPIRV::Capability::AtomicFloat16MinMaxEXT);
1415 Reqs.
addCapability(SPIRV::Capability::AtomicFloat32MinMaxEXT);
1418 Reqs.
addCapability(SPIRV::Capability::AtomicFloat64MinMaxEXT);
1422 "Unexpected floating-point type width in atomic float instruction");
1428 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1432 return Dim == SPIRV::Dim::DIM_Buffer && Sampled == 1;
1436 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1440 return Dim == SPIRV::Dim::DIM_Buffer && Sampled == 2;
1444 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1448 return Dim != SPIRV::Dim::DIM_Buffer && Sampled == 1;
1452 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1456 return Dim == SPIRV::Dim::DIM_SubpassData && Sampled == 2;
1460 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1464 return Dim != SPIRV::Dim::DIM_Buffer && Sampled == 2;
1468 if (SampledImageInst->
getOpcode() != SPIRV::OpTypeSampledImage)
1473 auto *ImageInst =
MRI.getUniqueVRegDef(ImageReg);
1478 for (
const auto &
MI :
MRI.reg_instructions(
Reg)) {
1479 if (
MI.getOpcode() != SPIRV::OpDecorate)
1483 if (Dec == SPIRV::Decoration::NonUniformEXT)
1496 Register ResTypeReg = Instr.getOperand(1).getReg();
1501 if (
StorageClass != SPIRV::StorageClass::StorageClass::UniformConstant &&
1502 StorageClass != SPIRV::StorageClass::StorageClass::Uniform &&
1503 StorageClass != SPIRV::StorageClass::StorageClass::StorageBuffer) {
1510 auto FirstIndexReg = Instr.getOperand(3).getReg();
1511 bool FirstIndexIsConstant =
1514 if (
StorageClass == SPIRV::StorageClass::StorageClass::StorageBuffer) {
1517 SPIRV::Capability::StorageBufferArrayNonUniformIndexingEXT);
1518 else if (!FirstIndexIsConstant)
1520 SPIRV::Capability::StorageBufferArrayDynamicIndexing);
1526 if (PointeeType->
getOpcode() != SPIRV::OpTypeImage &&
1527 PointeeType->
getOpcode() != SPIRV::OpTypeSampledImage &&
1528 PointeeType->
getOpcode() != SPIRV::OpTypeSampler) {
1535 SPIRV::Capability::UniformTexelBufferArrayNonUniformIndexingEXT);
1536 else if (!FirstIndexIsConstant)
1538 SPIRV::Capability::UniformTexelBufferArrayDynamicIndexingEXT);
1542 SPIRV::Capability::InputAttachmentArrayNonUniformIndexingEXT);
1543 else if (!FirstIndexIsConstant)
1545 SPIRV::Capability::InputAttachmentArrayDynamicIndexingEXT);
1549 SPIRV::Capability::StorageTexelBufferArrayNonUniformIndexingEXT);
1550 else if (!FirstIndexIsConstant)
1552 SPIRV::Capability::StorageTexelBufferArrayDynamicIndexingEXT);
1555 PointeeType->
getOpcode() == SPIRV::OpTypeSampler) {
1558 SPIRV::Capability::SampledImageArrayNonUniformIndexingEXT);
1559 else if (!FirstIndexIsConstant)
1561 SPIRV::Capability::SampledImageArrayDynamicIndexing);
1565 SPIRV::Capability::StorageImageArrayNonUniformIndexingEXT);
1566 else if (!FirstIndexIsConstant)
1568 SPIRV::Capability::StorageImageArrayDynamicIndexing);
1573 if (TypeInst->
getOpcode() != SPIRV::OpTypeImage)
1582 if (ST.canUseExtension(SPIRV::Extension::SPV_KHR_integer_dot_product))
1583 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_integer_dot_product);
1587 assert(
MI.getOperand(2).isReg() &&
"Unexpected operand in dot");
1589 ST.getSPIRVGlobalRegistry());
1590 assert(TypeDef &&
"Unexpected type instruction for dot input");
1591 if (TypeDef->
getOpcode() == SPIRV::OpTypeInt) {
1593 Reqs.
addCapability(SPIRV::Capability::DotProductInput4x8BitPacked);
1600 "Dot operand of 8-bit integer type requires 4 components");
1601 Reqs.
addCapability(SPIRV::Capability::DotProductInput4x8Bit);
1617 unsigned AddrSpace = ASOp.
getImm();
1618 if (AddrSpace != SPIRV::StorageClass::UniformConstant) {
1619 if (!ST.canUseExtension(
1621 SPV_EXT_relaxed_printf_string_address_space)) {
1623 "required because printf uses a format string not "
1624 "in constant address space.",
1628 SPIRV::Extension::SPV_EXT_relaxed_printf_string_address_space);
1637 if (
MI.getNumOperands() <= OpIdx)
1639 uint32_t Mask =
MI.getOperand(OpIdx).getImm();
1641 if (Mask & (1U <<
I))
1652 if (ElemTypeDef->
getOpcode() == SPIRV::OpTypePointer &&
1653 ST.canUseExtension(SPIRV::Extension::SPV_INTEL_masked_gather_scatter)) {
1654 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_masked_gather_scatter);
1655 Reqs.
addCapability(SPIRV::Capability::MaskedGatherScatterINTEL);
1663 unsigned Op =
MI.getOpcode();
1665 case SPIRV::OpMemoryModel: {
1666 int64_t Addr =
MI.getOperand(0).getImm();
1669 int64_t Mem =
MI.getOperand(1).getImm();
1674 case SPIRV::OpEntryPoint: {
1675 int64_t Exe =
MI.getOperand(0).getImm();
1680 case SPIRV::OpExecutionMode:
1681 case SPIRV::OpExecutionModeId: {
1682 int64_t Exe =
MI.getOperand(1).getImm();
1687 case SPIRV::OpTypeMatrix:
1690 case SPIRV::OpTypeInt: {
1691 unsigned BitWidth =
MI.getOperand(1).getImm();
1699 ST.canUseExtension(SPIRV::Extension::SPV_INTEL_int4)) {
1703 if (!ST.canUseExtension(
1704 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_integers))
1706 "OpTypeInt type with a width other than 8, 16, 32 or 64 bits "
1707 "requires the following SPIR-V extension: "
1708 "SPV_ALTERA_arbitrary_precision_integers");
1710 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_integers);
1711 Reqs.
addCapability(SPIRV::Capability::ArbitraryPrecisionIntegersALTERA);
1715 case SPIRV::OpDot: {
1719 Reqs.
addCapability(SPIRV::Capability::BFloat16DotProductKHR);
1722 case SPIRV::OpTypeFloat: {
1723 unsigned BitWidth =
MI.getOperand(1).getImm();
1728 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_bfloat16))
1730 "following SPIR-V extension: SPV_KHR_bfloat16",
1740 case SPIRV::OpTypeVector: {
1741 unsigned NumComponents =
MI.getOperand(2).getImm();
1742 if (NumComponents == 8 || NumComponents == 16)
1747 "OpTypeVector with " +
Twine(NumComponents) +
1748 " components requires the following SPIR-V extension: "
1749 "SPV_EXT_long_vector");
1754 case SPIRV::OpTypeVectorIdEXT: {
1755 if (!ST.canUseExtension(SPIRV::Extension::SPV_EXT_long_vector))
1757 "extension: SPV_EXT_long_vector extension");
1758 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_long_vector);
1763 case SPIRV::OpTypePointer: {
1764 auto SC =
MI.getOperand(1).getImm();
1775 (TypeDef->
getOpcode() == SPIRV::OpTypeFloat) &&
1780 case SPIRV::OpExtInst: {
1781 if (
MI.getOperand(2).getImm() ==
1782 static_cast<int64_t
>(
1783 SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100)) {
1784 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_non_semantic_info);
1787 if (
MI.getOperand(3).getImm() ==
1788 static_cast<int64_t
>(SPIRV::OpenCLExtInst::printf)) {
1792 if (
MI.getOperand(2).getImm() ==
1793 static_cast<int64_t
>(SPIRV::InstructionSet::OpenCL_std)) {
1799 if (TypeDef && TypeDef->getOpcode() == SPIRV::OpTypeVector)
1800 TypeDef =
MRI.getVRegDef(TypeDef->getOperand(1).getReg());
1805 bool UsesBFloat16 = IsBFloat16(
MRI.getVRegDef(
MI.getOperand(1).getReg()));
1806 for (
unsigned I = 4,
E =
MI.getNumOperands();
I <
E && !UsesBFloat16;
1815 if (!ST.canUseExtension(
1816 SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic)) {
1818 MI,
"OpenCL Extended instructions with bfloat16 require the "
1819 "following SPIR-V extension: SPV_INTEL_bfloat16_arithmetic");
1822 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic);
1823 Reqs.
addCapability(SPIRV::Capability::BFloat16ArithmeticINTEL);
1828 case SPIRV::OpAliasDomainDeclINTEL:
1829 case SPIRV::OpAliasScopeDeclINTEL:
1830 case SPIRV::OpAliasScopeListDeclINTEL: {
1831 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_memory_access_aliasing);
1832 Reqs.
addCapability(SPIRV::Capability::MemoryAccessAliasingINTEL);
1835 case SPIRV::OpBitReverse:
1836 case SPIRV::OpBitFieldInsert:
1837 case SPIRV::OpBitFieldSExtract:
1838 case SPIRV::OpBitFieldUExtract:
1839 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_bit_instructions)) {
1843 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_bit_instructions);
1846 case SPIRV::OpTypeRuntimeArray:
1849 case SPIRV::OpTypeOpaque:
1850 case SPIRV::OpTypeEvent:
1853 case SPIRV::OpTypePipe:
1854 case SPIRV::OpTypeReserveId:
1857 case SPIRV::OpTypePipeStorage:
1860 case SPIRV::OpTypeDeviceEvent:
1861 case SPIRV::OpTypeQueue:
1862 case SPIRV::OpBuildNDRange:
1863 case SPIRV::OpEnqueueKernel:
1864 case SPIRV::OpGetKernelNDrangeSubGroupCount:
1865 case SPIRV::OpGetKernelNDrangeMaxSubGroupSize:
1866 case SPIRV::OpGetKernelWorkGroupSize:
1867 case SPIRV::OpGetKernelPreferredWorkGroupSizeMultiple:
1870 case SPIRV::OpDecorate:
1871 case SPIRV::OpDecorateId:
1872 case SPIRV::OpDecorateString:
1875 case SPIRV::OpMemberDecorate:
1876 case SPIRV::OpMemberDecorateString:
1879 case SPIRV::OpInBoundsPtrAccessChain:
1882 case SPIRV::OpConstantSampler:
1885 case SPIRV::OpInBoundsAccessChain:
1886 case SPIRV::OpAccessChain:
1889 case SPIRV::OpTypeImage:
1892 case SPIRV::OpTypeSampler:
1893 if (!ST.isShader()) {
1897 case SPIRV::OpTypeForwardPointer:
1901 case SPIRV::OpAtomicFlagTestAndSet:
1902 case SPIRV::OpAtomicLoad:
1903 case SPIRV::OpAtomicStore:
1904 case SPIRV::OpAtomicExchange:
1905 case SPIRV::OpAtomicCompareExchange:
1906 case SPIRV::OpAtomicCompareExchangeWeak:
1907 case SPIRV::OpAtomicIIncrement:
1908 case SPIRV::OpAtomicIDecrement:
1909 case SPIRV::OpAtomicIAdd:
1910 case SPIRV::OpAtomicISub:
1911 case SPIRV::OpAtomicUMin:
1912 case SPIRV::OpAtomicUMax:
1913 case SPIRV::OpAtomicSMin:
1914 case SPIRV::OpAtomicSMax:
1915 case SPIRV::OpAtomicAnd:
1916 case SPIRV::OpAtomicOr:
1917 case SPIRV::OpAtomicXor: {
1920 if (
Op == SPIRV::OpAtomicStore) {
1923 ST.getSPIRVGlobalRegistry());
1924 assert(TypeDef &&
"Unexpected type instruction for OpAtomicStore");
1926 assert(
MI.getOperand(1).isReg() &&
"Unexpected operand in atomic");
1927 TypeDef =
MRI.getVRegDef(
MI.getOperand(1).getReg());
1930 if (TypeDef->
getOpcode() == SPIRV::OpTypeInt) {
1935 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics))
1937 "16-bit integer atomic operations require the following SPIR-V "
1938 "extension: SPV_INTEL_16bit_atomics",
1940 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics);
1942 case SPIRV::OpAtomicLoad:
1943 case SPIRV::OpAtomicStore:
1944 case SPIRV::OpAtomicExchange:
1945 case SPIRV::OpAtomicCompareExchange:
1946 case SPIRV::OpAtomicCompareExchangeWeak:
1948 SPIRV::Capability::AtomicInt16CompareExchangeINTEL);
1956 if (
is_contained({SPIRV::OpAtomicLoad, SPIRV::OpAtomicStore,
1957 SPIRV::OpAtomicExchange},
1959 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics))
1961 "The atomic bfloat16 instruction requires the following SPIR-V "
1962 "extension: SPV_INTEL_16bit_atomics",
1964 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics);
1965 Reqs.
addCapability(SPIRV::Capability::AtomicBFloat16LoadStoreINTEL);
1970 case SPIRV::OpGroupNonUniformIAdd:
1971 case SPIRV::OpGroupNonUniformFAdd:
1972 case SPIRV::OpGroupNonUniformIMul:
1973 case SPIRV::OpGroupNonUniformFMul:
1974 case SPIRV::OpGroupNonUniformSMin:
1975 case SPIRV::OpGroupNonUniformUMin:
1976 case SPIRV::OpGroupNonUniformFMin:
1977 case SPIRV::OpGroupNonUniformSMax:
1978 case SPIRV::OpGroupNonUniformUMax:
1979 case SPIRV::OpGroupNonUniformFMax:
1980 case SPIRV::OpGroupNonUniformBitwiseAnd:
1981 case SPIRV::OpGroupNonUniformBitwiseOr:
1982 case SPIRV::OpGroupNonUniformBitwiseXor:
1983 case SPIRV::OpGroupNonUniformLogicalAnd:
1984 case SPIRV::OpGroupNonUniformLogicalOr:
1985 case SPIRV::OpGroupNonUniformLogicalXor: {
1987 int64_t GroupOp =
MI.getOperand(3).getImm();
1989 case SPIRV::GroupOperation::Reduce:
1990 case SPIRV::GroupOperation::InclusiveScan:
1991 case SPIRV::GroupOperation::ExclusiveScan:
1992 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformArithmetic);
1994 case SPIRV::GroupOperation::ClusteredReduce:
1995 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformClustered);
1997 case SPIRV::GroupOperation::PartitionedReduceNV:
1998 case SPIRV::GroupOperation::PartitionedInclusiveScanNV:
1999 case SPIRV::GroupOperation::PartitionedExclusiveScanNV:
2000 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformPartitionedNV);
2005 case SPIRV::OpGroupNonUniformQuadSwap:
2008 case SPIRV::OpImageQueryLod:
2011 case SPIRV::OpImageQuerySize:
2012 case SPIRV::OpImageQuerySizeLod:
2013 case SPIRV::OpImageQueryLevels:
2014 case SPIRV::OpImageQuerySamples:
2018 case SPIRV::OpImageQueryFormat: {
2019 Register ResultReg =
MI.getOperand(0).getReg();
2021 static const unsigned CompareOps[] = {
2022 SPIRV::OpIEqual, SPIRV::OpINotEqual,
2023 SPIRV::OpUGreaterThan, SPIRV::OpUGreaterThanEqual,
2024 SPIRV::OpULessThan, SPIRV::OpULessThanEqual,
2025 SPIRV::OpSGreaterThan, SPIRV::OpSGreaterThanEqual,
2026 SPIRV::OpSLessThan, SPIRV::OpSLessThanEqual};
2028 auto CheckAndAddExtension = [&](int64_t ImmVal) {
2029 if (ImmVal == 4323 || ImmVal == 4324) {
2030 if (ST.canUseExtension(SPIRV::Extension::SPV_EXT_image_raw10_raw12))
2031 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_image_raw10_raw12);
2034 "SPV_EXT_image_raw10_raw12 extension");
2039 unsigned Opc = UseInst.getOpcode();
2041 if (
Opc == SPIRV::OpSwitch) {
2044 CheckAndAddExtension(
Op.getImm());
2046 for (
unsigned i = 1; i < UseInst.getNumOperands(); ++i) {
2049 if (ConstInst && ConstInst->
getOpcode() == SPIRV::OpConstantI) {
2052 CheckAndAddExtension(ImmVal);
2060 case SPIRV::OpGroupNonUniformShuffle:
2061 case SPIRV::OpGroupNonUniformShuffleXor:
2062 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformShuffle);
2064 case SPIRV::OpGroupNonUniformShuffleUp:
2065 case SPIRV::OpGroupNonUniformShuffleDown:
2066 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformShuffleRelative);
2068 case SPIRV::OpGroupAll:
2069 case SPIRV::OpGroupAny:
2070 case SPIRV::OpGroupBroadcast:
2071 case SPIRV::OpGroupIAdd:
2072 case SPIRV::OpGroupFAdd:
2073 case SPIRV::OpGroupFMin:
2074 case SPIRV::OpGroupUMin:
2075 case SPIRV::OpGroupSMin:
2076 case SPIRV::OpGroupFMax:
2077 case SPIRV::OpGroupUMax:
2078 case SPIRV::OpGroupSMax:
2081 case SPIRV::OpGroupNonUniformElect:
2084 case SPIRV::OpGroupNonUniformAll:
2085 case SPIRV::OpGroupNonUniformAny:
2086 case SPIRV::OpGroupNonUniformAllEqual:
2089 case SPIRV::OpGroupNonUniformBroadcast:
2090 case SPIRV::OpGroupNonUniformBroadcastFirst:
2091 case SPIRV::OpGroupNonUniformBallot:
2092 case SPIRV::OpGroupNonUniformInverseBallot:
2093 case SPIRV::OpGroupNonUniformBallotBitExtract:
2094 case SPIRV::OpGroupNonUniformBallotBitCount:
2095 case SPIRV::OpGroupNonUniformBallotFindLSB:
2096 case SPIRV::OpGroupNonUniformBallotFindMSB:
2097 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformBallot);
2099 case SPIRV::OpSubgroupShuffleINTEL:
2100 case SPIRV::OpSubgroupShuffleDownINTEL:
2101 case SPIRV::OpSubgroupShuffleUpINTEL:
2102 case SPIRV::OpSubgroupShuffleXorINTEL:
2103 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {
2104 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_subgroups);
2105 Reqs.
addCapability(SPIRV::Capability::SubgroupShuffleINTEL);
2108 case SPIRV::OpSubgroupBlockReadINTEL:
2109 case SPIRV::OpSubgroupBlockWriteINTEL:
2110 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {
2111 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_subgroups);
2112 Reqs.
addCapability(SPIRV::Capability::SubgroupBufferBlockIOINTEL);
2115 case SPIRV::OpSubgroupImageBlockReadINTEL:
2116 case SPIRV::OpSubgroupImageBlockWriteINTEL:
2117 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {
2118 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_subgroups);
2119 Reqs.
addCapability(SPIRV::Capability::SubgroupImageBlockIOINTEL);
2122 case SPIRV::OpSubgroupImageMediaBlockReadINTEL:
2123 case SPIRV::OpSubgroupImageMediaBlockWriteINTEL:
2124 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_media_block_io)) {
2125 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_media_block_io);
2126 Reqs.
addCapability(SPIRV::Capability::SubgroupImageMediaBlockIOINTEL);
2129 case SPIRV::OpAssumeTrueKHR:
2130 case SPIRV::OpExpectKHR:
2131 if (ST.canUseExtension(SPIRV::Extension::SPV_KHR_expect_assume)) {
2132 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_expect_assume);
2136 case SPIRV::OpFmaKHR:
2137 if (ST.canUseExtension(SPIRV::Extension::SPV_KHR_fma)) {
2142 case SPIRV::OpPtrCastToCrossWorkgroupINTEL:
2143 case SPIRV::OpCrossWorkgroupCastToPtrINTEL:
2144 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_usm_storage_classes)) {
2145 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_usm_storage_classes);
2146 Reqs.
addCapability(SPIRV::Capability::USMStorageClassesINTEL);
2149 case SPIRV::OpConstantFunctionPointerINTEL:
2150 case SPIRV::OpFunctionPointerCallINTEL:
2151 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_function_pointers)) {
2152 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_function_pointers);
2153 Reqs.
addCapability(SPIRV::Capability::FunctionPointersINTEL);
2156 case SPIRV::OpGroupNonUniformRotateKHR:
2157 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_subgroup_rotate))
2159 "following SPIR-V extension: SPV_KHR_subgroup_rotate",
2161 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_subgroup_rotate);
2162 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformRotateKHR);
2165 case SPIRV::OpFixedCosALTERA:
2166 case SPIRV::OpFixedSinALTERA:
2167 case SPIRV::OpFixedCosPiALTERA:
2168 case SPIRV::OpFixedSinPiALTERA:
2169 case SPIRV::OpFixedExpALTERA:
2170 case SPIRV::OpFixedLogALTERA:
2171 case SPIRV::OpFixedRecipALTERA:
2172 case SPIRV::OpFixedSqrtALTERA:
2173 case SPIRV::OpFixedSinCosALTERA:
2174 case SPIRV::OpFixedSinCosPiALTERA:
2175 case SPIRV::OpFixedRsqrtALTERA:
2176 if (!ST.canUseExtension(
2177 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_fixed_point))
2179 "following SPIR-V extension: "
2180 "SPV_ALTERA_arbitrary_precision_fixed_point",
2183 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_fixed_point);
2184 Reqs.
addCapability(SPIRV::Capability::ArbitraryPrecisionFixedPointALTERA);
2186 case SPIRV::OpGroupIMulKHR:
2187 case SPIRV::OpGroupFMulKHR:
2188 case SPIRV::OpGroupBitwiseAndKHR:
2189 case SPIRV::OpGroupBitwiseOrKHR:
2190 case SPIRV::OpGroupBitwiseXorKHR:
2191 case SPIRV::OpGroupLogicalAndKHR:
2192 case SPIRV::OpGroupLogicalOrKHR:
2193 case SPIRV::OpGroupLogicalXorKHR:
2194 if (ST.canUseExtension(
2195 SPIRV::Extension::SPV_KHR_uniform_group_instructions)) {
2196 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_uniform_group_instructions);
2197 Reqs.
addCapability(SPIRV::Capability::GroupUniformArithmeticKHR);
2200 case SPIRV::OpReadClockKHR:
2201 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_shader_clock))
2203 "following SPIR-V extension: SPV_KHR_shader_clock",
2205 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_shader_clock);
2208 case SPIRV::OpAbortKHR:
2209 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_abort))
2211 "following SPIR-V extension: SPV_KHR_abort",
2216 case SPIRV::OpPoisonKHR:
2217 case SPIRV::OpFreezeKHR:
2218 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_poison_freeze))
2220 "following SPIR-V extension: SPV_KHR_poison_freeze",
2222 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_poison_freeze);
2225 case SPIRV::OpAtomicFAddEXT:
2226 case SPIRV::OpAtomicFMinEXT:
2227 case SPIRV::OpAtomicFMaxEXT:
2230 case SPIRV::OpConvertBF16ToFINTEL:
2231 case SPIRV::OpConvertFToBF16INTEL:
2232 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bfloat16_conversion)) {
2233 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bfloat16_conversion);
2234 Reqs.
addCapability(SPIRV::Capability::BFloat16ConversionINTEL);
2237 case SPIRV::OpRoundFToTF32INTEL:
2238 if (ST.canUseExtension(
2239 SPIRV::Extension::SPV_INTEL_tensor_float32_conversion)) {
2240 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_tensor_float32_conversion);
2241 Reqs.
addCapability(SPIRV::Capability::TensorFloat32RoundingINTEL);
2244 case SPIRV::OpVariableLengthArrayINTEL:
2245 case SPIRV::OpSaveMemoryINTEL:
2246 case SPIRV::OpRestoreMemoryINTEL:
2247 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_variable_length_array)) {
2248 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_variable_length_array);
2249 Reqs.
addCapability(SPIRV::Capability::VariableLengthArrayINTEL);
2252 case SPIRV::OpUntypedVariableLengthArrayINTEL:
2253 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_variable_length_array)) {
2254 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_variable_length_array);
2255 Reqs.
addCapability(SPIRV::Capability::UntypedVariableLengthArrayINTEL);
2258 case SPIRV::OpAsmTargetINTEL:
2259 case SPIRV::OpAsmINTEL:
2260 case SPIRV::OpAsmCallINTEL:
2261 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_inline_assembly)) {
2262 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_inline_assembly);
2266 case SPIRV::OpTypeCooperativeMatrixKHR: {
2267 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix))
2269 "OpTypeCooperativeMatrixKHR type requires the "
2270 "following SPIR-V extension: SPV_KHR_cooperative_matrix",
2272 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix);
2273 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixKHR);
2277 Reqs.
addCapability(SPIRV::Capability::BFloat16CooperativeMatrixKHR);
2280 case SPIRV::OpArithmeticFenceEXT:
2281 if (!ST.canUseExtension(SPIRV::Extension::SPV_EXT_arithmetic_fence))
2283 "following SPIR-V extension: SPV_EXT_arithmetic_fence",
2285 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_arithmetic_fence);
2288 case SPIRV::OpControlBarrierArriveINTEL:
2289 case SPIRV::OpControlBarrierWaitINTEL:
2290 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_split_barrier)) {
2291 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_split_barrier);
2295 case SPIRV::OpCooperativeMatrixMulAddKHR: {
2296 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix))
2298 "following SPIR-V extension: "
2299 "SPV_KHR_cooperative_matrix",
2301 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix);
2302 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixKHR);
2303 constexpr unsigned MulAddMaxSize = 6;
2304 if (
MI.getNumOperands() != MulAddMaxSize)
2306 const int64_t CoopOperands =
MI.getOperand(MulAddMaxSize - 1).getImm();
2308 SPIRV::CooperativeMatrixOperands::MatrixAAndBTF32ComponentsINTEL) {
2309 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
2311 "require the following SPIR-V extension: "
2312 "SPV_INTEL_joint_matrix",
2314 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2316 SPIRV::Capability::CooperativeMatrixTF32ComponentTypeINTEL);
2319 MatrixAAndBBFloat16ComponentsINTEL ||
2321 SPIRV::CooperativeMatrixOperands::MatrixCBFloat16ComponentsINTEL ||
2323 MatrixResultBFloat16ComponentsINTEL) {
2324 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
2326 "require the following SPIR-V extension: "
2327 "SPV_INTEL_joint_matrix",
2329 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2331 SPIRV::Capability::CooperativeMatrixBFloat16ComponentTypeINTEL);
2335 case SPIRV::OpCooperativeMatrixLoadKHR:
2336 case SPIRV::OpCooperativeMatrixStoreKHR:
2337 case SPIRV::OpCooperativeMatrixLoadCheckedINTEL:
2338 case SPIRV::OpCooperativeMatrixStoreCheckedINTEL:
2339 case SPIRV::OpCooperativeMatrixPrefetchINTEL: {
2340 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix))
2342 "following SPIR-V extension: "
2343 "SPV_KHR_cooperative_matrix",
2345 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix);
2346 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixKHR);
2352 case SPIRV::OpCooperativeMatrixLoadKHR:
2355 case SPIRV::OpCooperativeMatrixStoreKHR:
2358 case SPIRV::OpCooperativeMatrixLoadCheckedINTEL:
2361 case SPIRV::OpCooperativeMatrixStoreCheckedINTEL:
2362 case SPIRV::OpCooperativeMatrixPrefetchINTEL:
2368 Register RegLayout =
MI.getOperand(LayoutNum).getReg();
2371 if (MILayout->
getOpcode() == SPIRV::OpConstantI) {
2374 static_cast<unsigned>(SPIRV::CooperativeMatrixLayout::PackedINTEL)) {
2375 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
2377 "extension: SPV_INTEL_joint_matrix",
2379 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2380 Reqs.
addCapability(SPIRV::Capability::PackedCooperativeMatrixINTEL);
2385 if (
Op == SPIRV::OpCooperativeMatrixLoadKHR ||
2386 Op == SPIRV::OpCooperativeMatrixStoreKHR)
2389 std::string InstName;
2391 case SPIRV::OpCooperativeMatrixPrefetchINTEL:
2392 InstName =
"OpCooperativeMatrixPrefetchINTEL";
2394 case SPIRV::OpCooperativeMatrixLoadCheckedINTEL:
2395 InstName =
"OpCooperativeMatrixLoadCheckedINTEL";
2397 case SPIRV::OpCooperativeMatrixStoreCheckedINTEL:
2398 InstName =
"OpCooperativeMatrixStoreCheckedINTEL";
2402 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix)) {
2403 const std::string ErrorMsg =
2404 InstName +
" instruction requires the "
2405 "following SPIR-V extension: SPV_INTEL_joint_matrix";
2408 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2409 if (
Op == SPIRV::OpCooperativeMatrixPrefetchINTEL) {
2410 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixPrefetchINTEL);
2414 SPIRV::Capability::CooperativeMatrixCheckedInstructionsINTEL);
2417 case SPIRV::OpCooperativeMatrixConstructCheckedINTEL:
2418 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
2420 "instructions require the following SPIR-V extension: "
2421 "SPV_INTEL_joint_matrix",
2423 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2425 SPIRV::Capability::CooperativeMatrixCheckedInstructionsINTEL);
2427 case SPIRV::OpReadPipeBlockingALTERA:
2428 case SPIRV::OpWritePipeBlockingALTERA:
2429 if (ST.canUseExtension(SPIRV::Extension::SPV_ALTERA_blocking_pipes)) {
2430 Reqs.
addExtension(SPIRV::Extension::SPV_ALTERA_blocking_pipes);
2434 case SPIRV::OpCooperativeMatrixGetElementCoordINTEL:
2435 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
2437 "following SPIR-V extension: SPV_INTEL_joint_matrix",
2439 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2441 SPIRV::Capability::CooperativeMatrixInvocationInstructionsINTEL);
2443 case SPIRV::OpConvertHandleToImageINTEL:
2444 case SPIRV::OpConvertHandleToSamplerINTEL:
2445 case SPIRV::OpConvertHandleToSampledImageINTEL: {
2446 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bindless_images))
2448 "instructions require the following SPIR-V extension: "
2449 "SPV_INTEL_bindless_images",
2452 SPIRV::AddressingModel::AddressingModel AddrModel = MAI.
Addr;
2454 if (
Op == SPIRV::OpConvertHandleToImageINTEL &&
2455 TyDef->
getOpcode() != SPIRV::OpTypeImage) {
2457 "OpConvertHandleToImageINTEL",
2459 }
else if (
Op == SPIRV::OpConvertHandleToSamplerINTEL &&
2460 TyDef->
getOpcode() != SPIRV::OpTypeSampler) {
2462 "OpConvertHandleToSamplerINTEL",
2464 }
else if (
Op == SPIRV::OpConvertHandleToSampledImageINTEL &&
2465 TyDef->
getOpcode() != SPIRV::OpTypeSampledImage) {
2467 "OpConvertHandleToSampledImageINTEL",
2473 if (!(Bitwidth == 32 && AddrModel == SPIRV::AddressingModel::Physical32) &&
2474 !(Bitwidth == 64 && AddrModel == SPIRV::AddressingModel::Physical64)) {
2476 "Parameter value must be a 32-bit scalar in case of "
2477 "Physical32 addressing model or a 64-bit scalar in case of "
2478 "Physical64 addressing model",
2481 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bindless_images);
2485 case SPIRV::OpSubgroup2DBlockLoadINTEL:
2486 case SPIRV::OpSubgroup2DBlockLoadTransposeINTEL:
2487 case SPIRV::OpSubgroup2DBlockLoadTransformINTEL:
2488 case SPIRV::OpSubgroup2DBlockPrefetchINTEL:
2489 case SPIRV::OpSubgroup2DBlockStoreINTEL: {
2490 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_2d_block_io))
2492 "Prefetch/Store]INTEL instructions require the "
2493 "following SPIR-V extension: SPV_INTEL_2d_block_io",
2495 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_2d_block_io);
2496 Reqs.
addCapability(SPIRV::Capability::Subgroup2DBlockIOINTEL);
2498 if (
Op == SPIRV::OpSubgroup2DBlockLoadTransposeINTEL) {
2499 Reqs.
addCapability(SPIRV::Capability::Subgroup2DBlockTransposeINTEL);
2502 if (
Op == SPIRV::OpSubgroup2DBlockLoadTransformINTEL) {
2503 Reqs.
addCapability(SPIRV::Capability::Subgroup2DBlockTransformINTEL);
2508 case SPIRV::OpKill: {
2511 case SPIRV::OpDemoteToHelperInvocation:
2512 Reqs.
addCapability(SPIRV::Capability::DemoteToHelperInvocation);
2514 if (ST.canUseExtension(
2515 SPIRV::Extension::SPV_EXT_demote_to_helper_invocation)) {
2518 SPIRV::Extension::SPV_EXT_demote_to_helper_invocation);
2523 case SPIRV::OpSUDot:
2524 case SPIRV::OpSDotAccSat:
2525 case SPIRV::OpUDotAccSat:
2526 case SPIRV::OpSUDotAccSat:
2529 case SPIRV::OpImageSampleImplicitLod:
2530 case SPIRV::OpImageFetch:
2534 case SPIRV::OpImageSampleExplicitLod:
2537 case SPIRV::OpImageSampleDrefImplicitLod:
2538 case SPIRV::OpImageSampleDrefExplicitLod:
2539 case SPIRV::OpImageDrefGather:
2540 case SPIRV::OpImageGather:
2544 case SPIRV::OpImageRead: {
2545 Register ImageReg =
MI.getOperand(2).getReg();
2546 SPIRVTypeInst TypeDef = ST.getSPIRVGlobalRegistry()->getResultType(
2555 Reqs.
addCapability(SPIRV::Capability::StorageImageReadWithoutFormat);
2558 case SPIRV::OpImageWrite: {
2559 Register ImageReg =
MI.getOperand(0).getReg();
2560 SPIRVTypeInst TypeDef = ST.getSPIRVGlobalRegistry()->getResultType(
2569 Reqs.
addCapability(SPIRV::Capability::StorageImageWriteWithoutFormat);
2572 case SPIRV::OpTypeStructContinuedINTEL:
2573 case SPIRV::OpConstantCompositeContinuedINTEL:
2574 case SPIRV::OpSpecConstantCompositeContinuedINTEL:
2575 case SPIRV::OpCompositeConstructContinuedINTEL: {
2576 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_long_composites))
2578 "Continued instructions require the "
2579 "following SPIR-V extension: SPV_INTEL_long_composites",
2581 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_long_composites);
2585 case SPIRV::OpArbitraryFloatEQALTERA:
2586 case SPIRV::OpArbitraryFloatGEALTERA:
2587 case SPIRV::OpArbitraryFloatGTALTERA:
2588 case SPIRV::OpArbitraryFloatLEALTERA:
2589 case SPIRV::OpArbitraryFloatLTALTERA:
2590 case SPIRV::OpArbitraryFloatCbrtALTERA:
2591 case SPIRV::OpArbitraryFloatCosALTERA:
2592 case SPIRV::OpArbitraryFloatCosPiALTERA:
2593 case SPIRV::OpArbitraryFloatExp10ALTERA:
2594 case SPIRV::OpArbitraryFloatExp2ALTERA:
2595 case SPIRV::OpArbitraryFloatExpALTERA:
2596 case SPIRV::OpArbitraryFloatExpm1ALTERA:
2597 case SPIRV::OpArbitraryFloatHypotALTERA:
2598 case SPIRV::OpArbitraryFloatLog10ALTERA:
2599 case SPIRV::OpArbitraryFloatLog1pALTERA:
2600 case SPIRV::OpArbitraryFloatLog2ALTERA:
2601 case SPIRV::OpArbitraryFloatLogALTERA:
2602 case SPIRV::OpArbitraryFloatRecipALTERA:
2603 case SPIRV::OpArbitraryFloatSinCosALTERA:
2604 case SPIRV::OpArbitraryFloatSinCosPiALTERA:
2605 case SPIRV::OpArbitraryFloatSinALTERA:
2606 case SPIRV::OpArbitraryFloatSinPiALTERA:
2607 case SPIRV::OpArbitraryFloatSqrtALTERA:
2608 case SPIRV::OpArbitraryFloatACosALTERA:
2609 case SPIRV::OpArbitraryFloatACosPiALTERA:
2610 case SPIRV::OpArbitraryFloatAddALTERA:
2611 case SPIRV::OpArbitraryFloatASinALTERA:
2612 case SPIRV::OpArbitraryFloatASinPiALTERA:
2613 case SPIRV::OpArbitraryFloatATan2ALTERA:
2614 case SPIRV::OpArbitraryFloatATanALTERA:
2615 case SPIRV::OpArbitraryFloatATanPiALTERA:
2616 case SPIRV::OpArbitraryFloatCastFromIntALTERA:
2617 case SPIRV::OpArbitraryFloatCastALTERA:
2618 case SPIRV::OpArbitraryFloatCastToIntALTERA:
2619 case SPIRV::OpArbitraryFloatDivALTERA:
2620 case SPIRV::OpArbitraryFloatMulALTERA:
2621 case SPIRV::OpArbitraryFloatPowALTERA:
2622 case SPIRV::OpArbitraryFloatPowNALTERA:
2623 case SPIRV::OpArbitraryFloatPowRALTERA:
2624 case SPIRV::OpArbitraryFloatRSqrtALTERA:
2625 case SPIRV::OpArbitraryFloatSubALTERA: {
2626 if (!ST.canUseExtension(
2627 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_floating_point))
2629 "Floating point instructions can't be translated correctly without "
2630 "enabled SPV_ALTERA_arbitrary_precision_floating_point extension!",
2633 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_floating_point);
2635 SPIRV::Capability::ArbitraryPrecisionFloatingPointALTERA);
2638 case SPIRV::OpSubgroupMatrixMultiplyAccumulateINTEL: {
2639 if (!ST.canUseExtension(
2640 SPIRV::Extension::SPV_INTEL_subgroup_matrix_multiply_accumulate))
2642 "OpSubgroupMatrixMultiplyAccumulateINTEL instruction requires the "
2644 "extension: SPV_INTEL_subgroup_matrix_multiply_accumulate",
2647 SPIRV::Extension::SPV_INTEL_subgroup_matrix_multiply_accumulate);
2649 SPIRV::Capability::SubgroupMatrixMultiplyAccumulateINTEL);
2652 case SPIRV::OpBitwiseFunctionINTEL: {
2653 if (!ST.canUseExtension(
2654 SPIRV::Extension::SPV_INTEL_ternary_bitwise_function))
2656 "OpBitwiseFunctionINTEL instruction requires the following SPIR-V "
2657 "extension: SPV_INTEL_ternary_bitwise_function",
2659 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_ternary_bitwise_function);
2660 Reqs.
addCapability(SPIRV::Capability::TernaryBitwiseFunctionINTEL);
2663 case SPIRV::OpCopyMemorySized: {
2668 case SPIRV::OpTypeUntypedPointerKHR:
2670 MI.getOperand(1).getImm(), ST);
2672 case SPIRV::OpUntypedVariableKHR:
2673 case SPIRV::OpUntypedAccessChainKHR:
2674 case SPIRV::OpUntypedInBoundsAccessChainKHR:
2675 case SPIRV::OpUntypedPtrAccessChainKHR:
2676 case SPIRV::OpUntypedInBoundsPtrAccessChainKHR:
2677 case SPIRV::OpUntypedPrefetchKHR:
2678 case SPIRV::OpUntypedGroupAsyncCopyKHR: {
2679 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_untyped_pointers))
2681 "SPIR-V extension: SPV_KHR_untyped_pointers",
2683 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_untyped_pointers);
2687 case SPIRV::OpPredicatedLoadINTEL:
2688 case SPIRV::OpPredicatedStoreINTEL: {
2689 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_predicated_io))
2691 "OpPredicated[Load/Store]INTEL instructions require "
2692 "the following SPIR-V extension: SPV_INTEL_predicated_io",
2694 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_predicated_io);
2698 case SPIRV::OpFAddS:
2699 case SPIRV::OpFSubS:
2700 case SPIRV::OpFMulS:
2701 case SPIRV::OpFDivS:
2702 case SPIRV::OpFRemS:
2704 case SPIRV::OpFNegate:
2705 case SPIRV::OpFAddV:
2706 case SPIRV::OpFSubV:
2707 case SPIRV::OpFMulV:
2708 case SPIRV::OpFDivV:
2709 case SPIRV::OpFRemV:
2710 case SPIRV::OpFNegateV: {
2716 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic))
2718 "Arithmetic instructions with bfloat16 arguments require the "
2719 "following SPIR-V extension: SPV_INTEL_bfloat16_arithmetic",
2721 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic);
2722 Reqs.
addCapability(SPIRV::Capability::BFloat16ArithmeticINTEL);
2726 case SPIRV::OpOrdered:
2727 case SPIRV::OpUnordered:
2728 case SPIRV::OpFOrdEqual:
2729 case SPIRV::OpFOrdNotEqual:
2730 case SPIRV::OpFOrdLessThan:
2731 case SPIRV::OpFOrdLessThanEqual:
2732 case SPIRV::OpFOrdGreaterThan:
2733 case SPIRV::OpFOrdGreaterThanEqual:
2734 case SPIRV::OpFUnordEqual:
2735 case SPIRV::OpFUnordNotEqual:
2736 case SPIRV::OpFUnordLessThan:
2737 case SPIRV::OpFUnordLessThanEqual:
2738 case SPIRV::OpFUnordGreaterThan:
2739 case SPIRV::OpFUnordGreaterThanEqual: {
2742 ST.getSPIRVGlobalRegistry());
2743 assert(TypeDef &&
"Unexpected type instruction for comparison operand");
2747 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic))
2749 "Relational instructions with bfloat16 arguments require the "
2750 "following SPIR-V extension: SPV_INTEL_bfloat16_arithmetic",
2752 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic);
2753 Reqs.
addCapability(SPIRV::Capability::BFloat16ArithmeticINTEL);
2757 case SPIRV::OpDPdxCoarse:
2758 case SPIRV::OpDPdyCoarse:
2759 case SPIRV::OpDPdxFine:
2760 case SPIRV::OpDPdyFine: {
2764 case SPIRV::OpLoopControlINTEL: {
2765 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_unstructured_loop_controls);
2766 Reqs.
addCapability(SPIRV::Capability::UnstructuredLoopControlsINTEL);
2778 SPIRV::Capability::Shader);
2793 auto Node = M.getNamedMetadata(
"spirv.ExecutionMode");
2795 bool RequireFloatControls =
false, RequireIntelFloatControls2 =
false,
2796 RequireKHRFloatControls2 =
false,
2797 VerLower14 = !ST.isAtLeastSPIRVVer(
VersionTuple(1, 4));
2798 bool HasIntelFloatControls2 =
2799 ST.canUseExtension(SPIRV::Extension::SPV_INTEL_float_controls2);
2800 bool HasKHRFloatControls2 =
2801 ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2);
2802 for (
unsigned i = 0; i <
Node->getNumOperands(); i++) {
2808 auto EM = Const->getZExtValue();
2812 case SPIRV::ExecutionMode::DenormPreserve:
2813 case SPIRV::ExecutionMode::DenormFlushToZero:
2814 case SPIRV::ExecutionMode::RoundingModeRTE:
2815 case SPIRV::ExecutionMode::RoundingModeRTZ:
2816 RequireFloatControls = VerLower14;
2818 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2820 case SPIRV::ExecutionMode::RoundingModeRTPINTEL:
2821 case SPIRV::ExecutionMode::RoundingModeRTNINTEL:
2822 case SPIRV::ExecutionMode::FloatingPointModeALTINTEL:
2823 case SPIRV::ExecutionMode::FloatingPointModeIEEEINTEL:
2824 if (HasIntelFloatControls2) {
2825 RequireIntelFloatControls2 =
true;
2827 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2830 case SPIRV::ExecutionMode::FPFastMathDefault: {
2831 if (HasKHRFloatControls2) {
2832 RequireKHRFloatControls2 =
true;
2834 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2838 case SPIRV::ExecutionMode::ContractionOff:
2839 case SPIRV::ExecutionMode::SignedZeroInfNanPreserve:
2840 if (HasKHRFloatControls2) {
2841 RequireKHRFloatControls2 =
true;
2843 SPIRV::OperandCategory::ExecutionModeOperand,
2844 SPIRV::ExecutionMode::FPFastMathDefault, ST);
2847 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2852 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2857 if (RequireFloatControls &&
2858 ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls))
2860 if (RequireIntelFloatControls2)
2862 if (RequireKHRFloatControls2)
2866 if (
F.isDeclaration())
2868 if (
F.getMetadata(
"reqd_work_group_size"))
2870 SPIRV::OperandCategory::ExecutionModeOperand,
2871 SPIRV::ExecutionMode::LocalSize, ST);
2872 if (
F.getFnAttribute(
"hlsl.numthreads").isValid()) {
2874 SPIRV::OperandCategory::ExecutionModeOperand,
2875 SPIRV::ExecutionMode::LocalSize, ST);
2877 if (
F.getFnAttribute(
"enable-maximal-reconvergence").getValueAsBool()) {
2880 if (
F.getMetadata(
"work_group_size_hint"))
2882 SPIRV::OperandCategory::ExecutionModeOperand,
2883 SPIRV::ExecutionMode::LocalSizeHint, ST);
2884 if (
F.getMetadata(
"intel_reqd_sub_group_size") ||
2885 F.getMetadata(
"reqd_sub_group_size"))
2887 SPIRV::OperandCategory::ExecutionModeOperand,
2888 SPIRV::ExecutionMode::SubgroupSize, ST);
2889 if (
F.getMetadata(
"max_work_group_size"))
2891 SPIRV::OperandCategory::ExecutionModeOperand,
2892 SPIRV::ExecutionMode::MaxWorkgroupSizeINTEL, ST);
2893 if (
F.getMetadata(
"vec_type_hint"))
2895 SPIRV::OperandCategory::ExecutionModeOperand,
2896 SPIRV::ExecutionMode::VecTypeHint, ST);
2898 if (
F.hasOptNone()) {
2899 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_optnone)) {
2902 }
else if (ST.canUseExtension(SPIRV::Extension::SPV_EXT_optnone)) {
2912 unsigned Flags = SPIRV::FPFastMathMode::None;
2913 bool CanUseKHRFloatControls2 =
2914 ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2);
2916 Flags |= SPIRV::FPFastMathMode::NotNaN;
2918 Flags |= SPIRV::FPFastMathMode::NotInf;
2920 Flags |= SPIRV::FPFastMathMode::NSZ;
2922 Flags |= SPIRV::FPFastMathMode::AllowRecip;
2924 Flags |= SPIRV::FPFastMathMode::AllowContract;
2926 if (CanUseKHRFloatControls2)
2934 Flags |= SPIRV::FPFastMathMode::NotNaN | SPIRV::FPFastMathMode::NotInf |
2935 SPIRV::FPFastMathMode::NSZ | SPIRV::FPFastMathMode::AllowRecip |
2936 SPIRV::FPFastMathMode::AllowTransform |
2937 SPIRV::FPFastMathMode::AllowReassoc |
2938 SPIRV::FPFastMathMode::AllowContract;
2940 Flags |= SPIRV::FPFastMathMode::Fast;
2943 if (CanUseKHRFloatControls2) {
2945 assert(!(Flags & SPIRV::FPFastMathMode::Fast) &&
2946 "SPIRV::FPFastMathMode::Fast is deprecated and should not be used "
2951 assert((!(Flags & SPIRV::FPFastMathMode::AllowTransform) ||
2952 ((Flags & SPIRV::FPFastMathMode::AllowReassoc &&
2953 Flags & SPIRV::FPFastMathMode::AllowContract))) &&
2954 "SPIRV::FPFastMathMode::AllowTransform requires AllowReassoc and "
2955 "AllowContract flags to be enabled as well.");
2966 return ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2);
2976 auto Decorate = [&](SPIRV::Decoration::Decoration Dec,
2983 if (
TII.canUseIntegerWrapDecoration(
I)) {
2986 SPIRV::OperandCategory::DecorationOperand,
2987 SPIRV::Decoration::NoSignedWrap, ST, Reqs)
2989 Decorate(SPIRV::Decoration::NoSignedWrap, {});
2992 SPIRV::OperandCategory::DecorationOperand,
2993 SPIRV::Decoration::NoUnsignedWrap, ST, Reqs)
2995 Decorate(SPIRV::Decoration::NoUnsignedWrap, {});
3000 TII.canUseFastMathFlags(
3001 I, ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2)) ||
3002 (ST.isKernel() &&
I.getOpcode() == SPIRV::OpExtInst);
3007 if (FMFlags == SPIRV::FPFastMathMode::None) {
3010 if (FPFastMathDefaultInfoVec.
empty())
3016 I.getOpcode() == SPIRV::OpExtInst ||
3017 I.getOpcode() == SPIRV::OpFunctionCall
3018 ?
I.getMF()->getRegInfo().getVRegDef(
I.getOperand(1).getReg())
3019 :
getRegType(
I.getOperand(2).getReg(), *
I.getMF(), GR);
3026 if (Ty == Elem.Ty) {
3027 FMFlags = Elem.FastMathFlags;
3028 Emit = Elem.ContractionOff || Elem.SignedZeroInfNanPreserve ||
3029 Elem.FPFastMathDefault;
3034 if (FMFlags == SPIRV::FPFastMathMode::None && !Emit)
3038 Decorate(SPIRV::Decoration::FPFastMathMode, {FMFlags});
3052 for (
const auto &
MBB : *MF) {
3053 if (!
MBB.hasName() ||
MBB.empty())
3064 auto it = FPFastMathDefaultInfoMap.
find(
F);
3065 if (it != FPFastMathDefaultInfoMap.
end())
3073 SPIRV::FPFastMathMode::None);
3075 SPIRV::FPFastMathMode::None);
3077 SPIRV::FPFastMathMode::None);
3078 return FPFastMathDefaultInfoMap[
F] = std::move(FPFastMathDefaultInfoVec);
3084 size_t BitWidth = Ty->getScalarSizeInBits();
3088 assert(Index >= 0 && Index < 3 &&
3089 "Expected FPFastMathDefaultInfo for half, float, or double");
3090 assert(FPFastMathDefaultInfoVec.
size() == 3 &&
3091 "Expected FPFastMathDefaultInfoVec to have exactly 3 elements");
3092 return FPFastMathDefaultInfoVec[Index];
3099 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2))
3108 auto Node = M.getNamedMetadata(
"spirv.ExecutionMode");
3112 for (
unsigned i = 0; i <
Node->getNumOperands(); i++) {
3117 if (OnlyF &&
F != OnlyF)
3123 if (EM == SPIRV::ExecutionMode::FPFastMathDefault) {
3125 "Expected 4 operands for FPFastMathDefault");
3136 Info.FastMathFlags = Flags;
3137 Info.FPFastMathDefault =
true;
3138 }
else if (EM == SPIRV::ExecutionMode::ContractionOff) {
3140 "Expected no operands for ContractionOff");
3147 Info.ContractionOff =
true;
3149 }
else if (EM == SPIRV::ExecutionMode::SignedZeroInfNanPreserve) {
3151 "Expected 1 operand for SignedZeroInfNanPreserve");
3152 unsigned TargetWidth =
3161 assert(Index >= 0 && Index < 3 &&
3162 "Expected FPFastMathDefaultInfo for half, float, or double");
3163 assert(FPFastMathDefaultInfoVec.
size() == 3 &&
3164 "Expected FPFastMathDefaultInfoVec to have exactly 3 elements");
3165 FPFastMathDefaultInfoVec[Index].SignedZeroInfNanPreserve =
true;
3173 : ST(&ST), GR(ST.getSPIRVGlobalRegistry()), TII(ST.getInstrInfo()),
3174 MAI(MAI), GetMF(GetMF) {}
3186 collectDeclarations(M);
3189 numberRegistersGlobally(M);
3192 processOtherInstrs(M);
3196 MAI.Reqs.addCapability(SPIRV::Capability::Linkage);
3199 GR->setBound(MAI.MaxID);
3213 [&MMI](
const Function &
F) { return MMI.getMachineFunction(F); })
3229 MachineFunctionAnalysis::Result *MFA =
3230 FAM.getCachedResult<MachineFunctionAnalysis>(
3231 const_cast<Function &>(F));
3232 assert((MFA || F.isDeclaration()) &&
3233 "Missing MachineFunction for definition");
3234 return MFA ? &MFA->getMF() : nullptr;
3251 for (
auto &
MBB : MF)
3254 FPFastMathDefaultInfoMap[&
F]);
3262 SPIRVPrepareModuleAnalysisLegacy() : MachineFunctionPass(
ID) {}
3269char SPIRVPrepareModuleAnalysisLegacy::ID = 0;
3272 "spirv-prepare-module-analysis",
3273 "SPIRV prepare module analysis",
false,
false)
3276 return new SPIRVPrepareModuleAnalysisLegacy();
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
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.
iterator find(const_arg_type_t< KeyT > Val)
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...
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
bool isConstantInstr(const MachineInstr &MI) 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 SPIRVInstrInfo * getInstrInfo() const override
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.
DenseMap< 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
bool requiresLongVectorEXT(unsigned NumComponents)
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.
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