35#define DEBUG_TYPE "spirv-module-analysis"
39 cl::desc(
"Dump MIR with SPIR-V dependencies info"),
44 cl::desc(
"SPIR-V capabilities to avoid if there are "
45 "other options enabling a feature"),
48 "SPIR-V Shader capability")));
58 "SPIRV module analysis",
true,
true)
62 Func.getContext().diagnose(
68 unsigned DefaultVal = 0) {
69 if (MdNode && OpIndex < MdNode->getNumOperands()) {
83 AvoidCaps.
S.
insert(SPIRV::Capability::Shader);
85 AvoidCaps.
S.
insert(SPIRV::Capability::Kernel);
90 bool MinVerOK = SPIRVVersion.
empty() || SPIRVVersion >= ReqMinVer;
92 ReqMaxVer.
empty() || SPIRVVersion.
empty() || SPIRVVersion <= ReqMaxVer;
95 if (ReqCaps.
empty()) {
96 if (ReqExts.
empty()) {
97 if (MinVerOK && MaxVerOK)
98 return {
true, {}, {}, ReqMinVer, ReqMaxVer};
101 }
else if (MinVerOK && MaxVerOK) {
102 if (ReqCaps.
size() == 1) {
103 auto Cap = ReqCaps[0];
106 SPIRV::OperandCategory::CapabilityOperand, Cap));
107 return {
true, {Cap}, std::move(ReqExts), ReqMinVer, ReqMaxVer};
117 for (
auto Cap : ReqCaps)
120 for (
size_t i = 0, Sz = UseCaps.
size(); i < Sz; ++i) {
121 auto Cap = UseCaps[i];
122 if (i == Sz - 1 || !AvoidCaps.
S.
contains(Cap)) {
124 SPIRV::OperandCategory::CapabilityOperand, Cap));
125 return {
true, {Cap}, std::move(ReqExts), ReqMinVer, ReqMaxVer};
133 if (
llvm::all_of(ReqExts, [&ST](
const SPIRV::Extension::Extension &Ext) {
134 return ST.canUseExtension(Ext);
145void SPIRVModuleAnalysisImpl::setBaseInfo(
const Module &M) {
149 MAI.RegisterAliasTable.clear();
150 MAI.InstrsToDelete.clear();
151 MAI.GlobalObjMap.clear();
152 MAI.GlobalVarList.clear();
153 MAI.ExtInstSetMap.clear();
155 MAI.Reqs.initAvailableCapabilities(*ST);
158 if (
auto MemModel =
M.getNamedMetadata(
"spirv.MemoryModel")) {
159 auto MemMD = MemModel->getOperand(0);
160 MAI.Addr =
static_cast<SPIRV::AddressingModel::AddressingModel
>(
163 static_cast<SPIRV::MemoryModel::MemoryModel
>(
getMetadataUInt(MemMD, 1));
166 MAI.Mem = ST->isShader() ? SPIRV::MemoryModel::GLSL450
167 : SPIRV::MemoryModel::OpenCL;
168 if (MAI.Mem == SPIRV::MemoryModel::OpenCL) {
169 unsigned PtrSize = ST->getPointerSize();
170 MAI.Addr = PtrSize == 32 ? SPIRV::AddressingModel::Physical32
171 : PtrSize == 64 ? SPIRV::AddressingModel::Physical64
172 : SPIRV::AddressingModel::Logical;
175 MAI.Addr = SPIRV::AddressingModel::Logical;
180 if (
auto VerNode =
M.getNamedMetadata(
"opencl.ocl.version")) {
181 MAI.SrcLang = SPIRV::SourceLanguage::OpenCL_C;
184 assert(VerNode->getNumOperands() > 0 &&
"Invalid SPIR");
185 auto VersionMD = VerNode->getOperand(0);
191 (std::max(1U, MajorNum) * 100 + MinorNum) * 1000 + RevNum;
194 if (
auto *CxxVerNode =
M.getNamedMetadata(
"opencl.cxx.version")) {
195 assert(CxxVerNode->getNumOperands() > 0 &&
"Invalid SPIR");
196 auto *CxxMD = CxxVerNode->getOperand(0);
200 if ((MAI.SrcLangVersion == 200000 && CxxVer == 100000) ||
201 (MAI.SrcLangVersion == 300000 && CxxVer == 202100000)) {
202 MAI.SrcLang = SPIRV::SourceLanguage::CPP_for_OpenCL;
203 MAI.SrcLangVersion = CxxVer;
206 "opencl cxx version is not compatible with opencl c version!");
214 if (!ST->isShader()) {
215 MAI.SrcLang = SPIRV::SourceLanguage::OpenCL_CPP;
216 MAI.SrcLangVersion = 100000;
218 MAI.SrcLang = SPIRV::SourceLanguage::Unknown;
219 MAI.SrcLangVersion = 0;
223 if (
auto ExtNode =
M.getNamedMetadata(
"opencl.used.extensions")) {
224 for (
unsigned I = 0,
E = ExtNode->getNumOperands();
I !=
E; ++
I) {
225 MDNode *MD = ExtNode->getOperand(
I);
235 MAI.Reqs.getAndAddRequirements(SPIRV::OperandCategory::MemoryModelOperand,
237 MAI.Reqs.getAndAddRequirements(SPIRV::OperandCategory::SourceLanguageOperand,
239 MAI.Reqs.getAndAddRequirements(SPIRV::OperandCategory::AddressingModelOperand,
242 if (MAI.Mem == SPIRV::MemoryModel::VulkanKHR)
243 MAI.Reqs.addExtension(SPIRV::Extension::SPV_KHR_vulkan_memory_model);
245 if (!ST->isShader()) {
247 MAI.ExtInstSetMap[
static_cast<unsigned>(
248 SPIRV::InstructionSet::OpenCL_std)] = MAI.getNextIDRegister();
259 if (
UseMI.getOpcode() != SPIRV::OpDecorate &&
260 UseMI.getOpcode() != SPIRV::OpMemberDecorate)
263 for (
unsigned I = 0;
I <
UseMI.getNumOperands(); ++
I) {
281 for (
unsigned i = 0; i <
MI.getNumOperands(); ++i) {
290 unsigned Opcode =
MI.getOpcode();
291 if ((Opcode == SPIRV::OpDecorate) && i >= 2) {
292 unsigned DecorationID =
MI.getOperand(1).getImm();
293 if (DecorationID != SPIRV::Decoration::FuncParamAttr &&
294 DecorationID != SPIRV::Decoration::UserSemantic &&
295 DecorationID != SPIRV::Decoration::CacheControlLoadINTEL &&
296 DecorationID != SPIRV::Decoration::CacheControlStoreINTEL)
302 if (!UseDefReg && MO.
isDef()) {
310 dbgs() <<
"Unexpectedly, no global id found for the operand ";
312 dbgs() <<
"\nInstruction: ";
339 case SPIRV::OpEnqueueKernel:
341 case SPIRV::OpGetKernelNDrangeSubGroupCount:
342 case SPIRV::OpGetKernelNDrangeMaxSubGroupSize:
344 case SPIRV::OpGetKernelWorkGroupSize:
345 case SPIRV::OpGetKernelPreferredWorkGroupSizeMultiple:
354 unsigned Opcode =
MI.getOpcode();
356 case SPIRV::OpTypeForwardPointer:
359 case SPIRV::OpVariable:
360 case SPIRV::OpUntypedVariableKHR:
361 return static_cast<SPIRV::StorageClass::StorageClass
>(
362 MI.getOperand(2).
getImm()) != SPIRV::StorageClass::Function;
363 case SPIRV::OpFunction:
364 case SPIRV::OpFunctionParameter:
367 if (GR->hasConstFunPtr() && Opcode == SPIRV::OpUndef) {
375 if (GR->getFunctionDefinitionByUse(&
MI.getOperand(0))) {
377 unsigned UseOp =
UseMI.getOpcode();
378 if (UseOp == SPIRV::OpConstantFunctionPointerINTEL ||
380 MAI.setSkipEmission(&
MI);
386 if (
UseMI.getOpcode() != SPIRV::OpConstantFunctionPointerINTEL)
392 MAI.setSkipEmission(&
MI);
396 return TII->isTypeDeclInstr(
MI) || TII->isConstantInstr(
MI) ||
397 TII->isInlineAsmDefInstr(
MI);
406void SPIRVModuleAnalysisImpl::visitFunPtrUse(
409 std::map<const Value *, unsigned> &GlobalToGReg,
411 const MachineOperand *OpFunDef = GR->getFunctionDefinitionByUse(FunPtrOp);
414 const MachineInstr *OpDefMI = OpFunDef->
getParent();
417 const MachineRegisterInfo &FunDefMRI = FunDefMF->
getRegInfo();
419 visitDecl(FunDefMRI, SignatureToGReg, GlobalToGReg, FunDefMF, *OpDefMI);
421 }
while (OpDefMI && (OpDefMI->
getOpcode() == SPIRV::OpFunction ||
422 OpDefMI->
getOpcode() == SPIRV::OpFunctionParameter));
424 MCRegister GlobalFunDefReg =
425 MAI.getRegisterAlias(FunDefMF, OpFunDef->
getReg());
427 "Function definition must refer to a global register");
428 MAI.setRegisterAlias(MF, OpReg, GlobalFunDefReg);
433void SPIRVModuleAnalysisImpl::visitDecl(
435 std::map<const Value *, unsigned> &GlobalToGReg,
const MachineFunction *MF,
437 unsigned Opcode =
MI.getOpcode();
440 for (
const MachineOperand &MO :
MI.operands()) {
441 if (!MO.isReg() || MO.isDef())
445 if (Opcode == SPIRV::OpConstantFunctionPointerINTEL &&
447 visitFunPtrUse(OpReg, &
MI.getOperand(2), SignatureToGReg, GlobalToGReg,
452 if (MAI.hasRegisterAlias(MF, MO.getReg()))
456 if (isDeclSection(MRI, *OpDefMI))
457 visitDecl(MRI, SignatureToGReg, GlobalToGReg, MF, *OpDefMI);
463 dbgs() <<
"Unexpectedly, no unique definition for the operand ";
465 dbgs() <<
"\nInstruction: ";
470 "No unique definition is found for the virtual register");
474 bool IsFunDef =
false;
475 if (TII->isSpecConstantInstr(
MI)) {
476 GReg = MAI.getNextIDRegister();
478 }
else if (Opcode == SPIRV::OpFunction ||
479 Opcode == SPIRV::OpFunctionParameter) {
480 GReg = handleFunctionOrParameter(MF,
MI, GlobalToGReg, IsFunDef);
481 }
else if (Opcode == SPIRV::OpTypeStruct ||
482 Opcode == SPIRV::OpConstantComposite) {
483 GReg = handleTypeDeclOrConstant(
MI, SignatureToGReg);
484 const MachineInstr *NextInstr =
MI.getNextNode();
486 ((Opcode == SPIRV::OpTypeStruct &&
487 NextInstr->
getOpcode() == SPIRV::OpTypeStructContinuedINTEL) ||
488 (Opcode == SPIRV::OpConstantComposite &&
490 SPIRV::OpConstantCompositeContinuedINTEL))) {
491 MCRegister Tmp = handleTypeDeclOrConstant(*NextInstr, SignatureToGReg);
493 MAI.setSkipEmission(NextInstr);
496 }
else if (TII->isTypeDeclInstr(
MI) || TII->isConstantInstr(
MI) ||
497 TII->isInlineAsmDefInstr(
MI)) {
498 GReg = handleTypeDeclOrConstant(
MI, SignatureToGReg);
499 }
else if (Opcode == SPIRV::OpVariable ||
500 Opcode == SPIRV::OpUntypedVariableKHR) {
501 GReg = handleVariable(MF,
MI, GlobalToGReg);
504 dbgs() <<
"\nInstruction: ";
510 MAI.setRegisterAlias(MF,
MI.getOperand(0).getReg(), GReg);
512 MAI.setSkipEmission(&
MI);
515MCRegister SPIRVModuleAnalysisImpl::handleFunctionOrParameter(
517 std::map<const Value *, unsigned> &GlobalToGReg,
bool &IsFunDef) {
518 const Value *GObj = GR->getGlobalObject(MF,
MI.getOperand(0).getReg());
519 assert(GObj &&
"Unregistered global definition");
523 assert(
F &&
"Expected a reference to a function or an argument");
524 IsFunDef = !
F->isDeclaration();
525 auto [It,
Inserted] = GlobalToGReg.try_emplace(GObj);
528 MCRegister GReg = MAI.getNextIDRegister();
535MCRegister SPIRVModuleAnalysisImpl::handleTypeDeclOrConstant(
538 auto [It,
Inserted] = SignatureToGReg.try_emplace(MISign);
541 MCRegister GReg = MAI.getNextIDRegister();
547MCRegister SPIRVModuleAnalysisImpl::handleVariable(
549 std::map<const Value *, unsigned> &GlobalToGReg) {
550 MAI.GlobalVarList.push_back(&
MI);
551 const Value *GObj = GR->getGlobalObject(MF,
MI.getOperand(0).getReg());
552 assert(GObj &&
"Unregistered global definition");
553 auto [It,
Inserted] = GlobalToGReg.try_emplace(GObj);
556 MCRegister GReg = MAI.getNextIDRegister();
560 MAI.GlobalObjMap[GV] = GReg;
564void SPIRVModuleAnalysisImpl::collectDeclarations(
const Module &M) {
566 std::map<const Value *, unsigned> GlobalToGReg;
571 const MachineRegisterInfo &MRI = MF->
getRegInfo();
572 unsigned PastHeader = 0;
573 for (MachineBasicBlock &
MBB : *MF) {
574 for (MachineInstr &
MI :
MBB) {
575 if (
MI.getNumOperands() == 0)
577 unsigned Opcode =
MI.getOpcode();
578 if (Opcode == SPIRV::OpFunction) {
579 if (PastHeader == 0) {
583 }
else if (Opcode == SPIRV::OpFunctionParameter) {
586 }
else if (PastHeader > 0) {
590 const MachineOperand &DefMO =
MI.getOperand(0);
592 case SPIRV::OpExtension:
593 MAI.Reqs.addExtension(SPIRV::Extension::Extension(DefMO.
getImm()));
594 MAI.setSkipEmission(&
MI);
596 case SPIRV::OpCapability:
597 MAI.Reqs.addCapability(SPIRV::Capability::Capability(DefMO.
getImm()));
598 MAI.setSkipEmission(&
MI);
603 if (DefMO.
isReg() && isDeclSection(MRI,
MI) &&
604 !MAI.hasRegisterAlias(MF, DefMO.
getReg()))
605 visitDecl(MRI, SignatureToGReg, GlobalToGReg, MF,
MI);
610 const MachineOperand &InvokeMO =
MI.getOperand(InvokeIdx);
611 if (InvokeMO.
isReg()) {
613 if (!MAI.hasRegisterAlias(MF, InvokeReg)) {
614 if (
const MachineInstr *
DefMI =
618 if (GR->getFunctionDefinitionByUse(FunPtrOp))
619 visitFunPtrUse(InvokeReg, FunPtrOp, SignatureToGReg,
638 if (
MI.getOpcode() == SPIRV::OpDecorate) {
640 auto Dec =
MI.getOperand(1).getImm();
641 if (Dec == SPIRV::Decoration::LinkageAttributes) {
642 auto Lnk =
MI.getOperand(
MI.getNumOperands() - 1).getImm();
643 if (Lnk == SPIRV::LinkageType::Import) {
648 MAI.GlobalObjMap[ImportedFunc] =
649 MAI.getRegisterAlias(
MI.getMF(), Target);
652 }
else if (
MI.getOpcode() == SPIRV::OpFunction) {
655 MCRegister GlobalReg = MAI.getRegisterAlias(
MI.getMF(),
Reg);
657 MAI.GlobalObjMap[
F] = GlobalReg;
669 auto FoundMI = IS.insert(std::move(MISign));
670 if (!FoundMI.second) {
671 if (
MI.getOpcode() == SPIRV::OpDecorate) {
673 "Decoration instructions must have at least 2 operands");
675 "Only OpDecorate instructions can be duplicates");
680 if (
MI.getOperand(1).getImm() != SPIRV::Decoration::FPFastMathMode)
686 assert(OrigMI->getNumOperands() ==
MI.getNumOperands() &&
687 "Original instruction must have the same number of operands");
689 OrigMI->getNumOperands() == 3 &&
690 "FPFastMathMode decoration must have 3 operands for OpDecorate");
691 unsigned OrigFlags = OrigMI->getOperand(2).getImm();
692 unsigned NewFlags =
MI.getOperand(2).getImm();
693 if (OrigFlags == NewFlags)
697 unsigned FinalFlags = OrigFlags | NewFlags;
699 <<
"Warning: Conflicting FPFastMathMode decoration flags "
701 << *OrigMI <<
"Original flags: " << OrigFlags
702 <<
", new flags: " << NewFlags
703 <<
". They will be merged on a best effort basis, but not "
704 "validated. Final flags: "
705 << FinalFlags <<
"\n";
712 assert(
false &&
"No original instruction found for the duplicate "
713 "OpDecorate, but we found one in IS.");
726void SPIRVModuleAnalysisImpl::processOtherInstrs(
const Module &M) {
729 if (
F.isDeclaration())
734 for (MachineBasicBlock &
MBB : *MF)
735 for (MachineInstr &
MI :
MBB) {
736 if (MAI.getSkipEmission(&
MI))
738 const unsigned OpCode =
MI.getOpcode();
739 if (OpCode == SPIRV::OpString) {
741 }
else if (OpCode == SPIRV::OpExtInst &&
MI.getOperand(2).isImm() &&
742 MI.getOperand(2).getImm() ==
743 SPIRV::InstructionSet::
744 NonSemantic_Shader_DebugInfo_100) {
751 MachineOperand Ins =
MI.getOperand(3);
752 namespace NS = SPIRV::NonSemanticExtInst;
753 static constexpr int64_t GlobalNonSemanticDITy[] = {
754 NS::DebugSource, NS::DebugCompilationUnit, NS::DebugInfoNone,
755 NS::DebugTypeBasic, NS::DebugTypePointer};
756 bool IsGlobalDI =
false;
757 for (
unsigned Idx = 0;
Idx < std::size(GlobalNonSemanticDITy); ++
Idx)
758 IsGlobalDI |= Ins.
getImm() == GlobalNonSemanticDITy[
Idx];
761 }
else if (OpCode == SPIRV::OpName || OpCode == SPIRV::OpMemberName) {
763 }
else if (OpCode == SPIRV::OpEntryPoint) {
765 }
else if (TII->isAliasingInstr(
MI)) {
767 }
else if (TII->isDecorationInstr(
MI)) {
769 collectFuncNames(
MI, &
F);
770 }
else if (TII->isConstantInstr(
MI)) {
774 }
else if (OpCode == SPIRV::OpFunction) {
775 collectFuncNames(
MI, &
F);
776 }
else if (OpCode == SPIRV::OpTypeForwardPointer) {
784 auto AliasingTier = [](
const MachineInstr *
MI) {
785 switch (
MI->getOpcode()) {
786 case SPIRV::OpAliasDomainDeclINTEL:
788 case SPIRV::OpAliasScopeDeclINTEL:
790 case SPIRV::OpAliasScopeListDeclINTEL:
797 [&](
const MachineInstr *
LHS,
const MachineInstr *
RHS) {
798 return AliasingTier(LHS) < AliasingTier(RHS);
805void SPIRVModuleAnalysisImpl::numberRegistersGlobally(
const Module &M) {
807 if (
F.isDeclaration())
811 for (MachineBasicBlock &
MBB : *MF) {
812 for (MachineInstr &
MI :
MBB) {
813 for (MachineOperand &
Op :
MI.operands()) {
817 if (MAI.hasRegisterAlias(MF,
Reg))
819 MCRegister NewReg = MAI.getNextIDRegister();
820 MAI.setRegisterAlias(MF,
Reg, NewReg);
822 if (
MI.getOpcode() != SPIRV::OpExtInst)
824 auto Set =
MI.getOperand(2).getImm();
825 auto [It,
Inserted] = MAI.ExtInstSetMap.try_emplace(Set);
827 It->second = MAI.getNextIDRegister();
835 SPIRV::OperandCategory::OperandCategory Category,
uint32_t i,
840void SPIRV::RequirementHandler::recursiveAddCapabilities(
842 for (
const auto &Cap : ToPrune) {
846 recursiveAddCapabilities(ImplicitDecls);
851 for (
const auto &Cap : ToAdd) {
852 bool IsNewlyInserted = AllCaps.insert(Cap).second;
853 if (!IsNewlyInserted)
857 recursiveAddCapabilities(ImplicitDecls);
858 MinimalCaps.push_back(Cap);
867 if (Req.
Cap.has_value())
873 if (!MaxVersion.empty() && Req.
MinVer > MaxVersion) {
875 <<
" and <= " << MaxVersion <<
"\n");
879 if (MinVersion.empty() || Req.
MinVer > MinVersion)
884 if (!MinVersion.empty() && Req.
MaxVer < MinVersion) {
886 <<
" and >= " << MinVersion <<
"\n");
890 if (MaxVersion.empty() || Req.
MaxVer < MaxVersion)
898 bool IsSatisfiable =
true;
899 auto TargetVer = ST.getSPIRVVersion();
901 if (!MaxVersion.empty() && !TargetVer.empty() && MaxVersion < TargetVer) {
903 dbgs() <<
"Target SPIR-V version too high for required features\n"
904 <<
"Required max version: " << MaxVersion <<
" target version "
905 << TargetVer <<
"\n");
906 IsSatisfiable =
false;
909 if (!MinVersion.empty() && !TargetVer.empty() && MinVersion > TargetVer) {
910 LLVM_DEBUG(
dbgs() <<
"Target SPIR-V version too low for required features\n"
911 <<
"Required min version: " << MinVersion
912 <<
" target version " << TargetVer <<
"\n");
913 IsSatisfiable =
false;
916 if (!MinVersion.empty() && !MaxVersion.empty() && MinVersion > MaxVersion) {
919 <<
"Version is too low for some features and too high for others.\n"
920 <<
"Required SPIR-V min version: " << MinVersion
921 <<
" required SPIR-V max version " << MaxVersion <<
"\n");
922 IsSatisfiable =
false;
927 AvoidCaps.
S.
insert(SPIRV::Capability::Shader);
929 AvoidCaps.
S.
insert(SPIRV::Capability::Kernel);
931 for (
auto Cap : MinimalCaps) {
932 if (AvailableCaps.contains(Cap) && !AvoidCaps.
S.
contains(Cap))
936 OperandCategory::CapabilityOperand, Cap)
938 IsSatisfiable =
false;
941 for (
auto Ext : AllExtensions) {
942 if (ST.canUseExtension(Ext))
946 OperandCategory::ExtensionOperand, Ext)
948 IsSatisfiable =
false;
957 for (
const auto Cap : ToAdd)
958 if (AvailableCaps.insert(Cap).second)
960 SPIRV::OperandCategory::CapabilityOperand, Cap));
964 const Capability::Capability
ToRemove,
965 const Capability::Capability IfPresent) {
966 if (AllCaps.contains(IfPresent)) {
976 addAvailableCaps({Capability::Shader, Capability::Linkage, Capability::Int8,
981 Capability::GroupNonUniformVote,
982 Capability::GroupNonUniformArithmetic,
983 Capability::GroupNonUniformBallot,
984 Capability::GroupNonUniformClustered,
985 Capability::GroupNonUniformShuffle,
986 Capability::GroupNonUniformShuffleRelative,
987 Capability::GroupNonUniformQuad});
991 Capability::DotProductInput4x8Bit,
992 Capability::DotProductInput4x8BitPacked,
993 Capability::DemoteToHelperInvocation});
996 for (
auto Extension : ST.getAllAvailableExtensions()) {
1002 if (!ST.isShader()) {
1003 initAvailableCapabilitiesForOpenCL(ST);
1007 if (ST.isShader()) {
1008 initAvailableCapabilitiesForVulkan(ST);
1015void RequirementHandler::initAvailableCapabilitiesForOpenCL(
1019 Capability::Kernel, Capability::Vector16,
1020 Capability::Groups, Capability::GenericPointer,
1021 Capability::StorageImageWriteWithoutFormat,
1022 Capability::StorageImageReadWithoutFormat});
1023 if (ST.hasOpenCLFullProfile())
1025 if (ST.hasOpenCLImageSupport()) {
1027 Capability::Image1D, Capability::SampledBuffer,
1028 Capability::ImageBuffer});
1029 if (
ST.isAtLeastOpenCLVer(VersionTuple(2, 0)))
1032 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 1)) &&
1033 ST.isAtLeastOpenCLVer(VersionTuple(2, 2)))
1035 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 4)))
1036 addAvailableCaps({Capability::DenormPreserve, Capability::DenormFlushToZero,
1037 Capability::SignedZeroInfNanPreserve,
1038 Capability::RoundingModeRTE,
1039 Capability::RoundingModeRTZ});
1046void RequirementHandler::initAvailableCapabilitiesForVulkan(
1047 const SPIRVSubtarget &ST) {
1051 Capability::Float16,
1052 Capability::Float64,
1053 Capability::GroupNonUniform,
1054 Capability::Image1D,
1055 Capability::SampledBuffer,
1056 Capability::ImageBuffer,
1057 Capability::UniformBufferArrayDynamicIndexing,
1058 Capability::SampledImageArrayDynamicIndexing,
1059 Capability::StorageBufferArrayDynamicIndexing,
1060 Capability::StorageImageArrayDynamicIndexing,
1061 Capability::DerivativeControl,
1063 Capability::ImageQuery,
1064 Capability::ImageGatherExtended,
1065 Capability::Addresses,
1066 Capability::VulkanMemoryModelKHR,
1067 Capability::StorageImageExtendedFormats,
1068 Capability::StorageImageMultisample,
1069 Capability::ImageMSArray});
1071 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 3)) ||
1072 ST.canUseExtension(Extension::SPV_KHR_variable_pointers))
1074 Capability::VariablePointers});
1077 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 5))) {
1079 {Capability::Int64Atomics, Capability::ShaderNonUniformEXT,
1080 Capability::RuntimeDescriptorArrayEXT,
1081 Capability::InputAttachmentArrayDynamicIndexingEXT,
1082 Capability::UniformTexelBufferArrayDynamicIndexingEXT,
1083 Capability::StorageTexelBufferArrayDynamicIndexingEXT,
1084 Capability::UniformBufferArrayNonUniformIndexingEXT,
1085 Capability::SampledImageArrayNonUniformIndexingEXT,
1086 Capability::StorageBufferArrayNonUniformIndexingEXT,
1087 Capability::StorageImageArrayNonUniformIndexingEXT,
1088 Capability::InputAttachmentArrayNonUniformIndexingEXT,
1089 Capability::UniformTexelBufferArrayNonUniformIndexingEXT,
1090 Capability::StorageTexelBufferArrayNonUniformIndexingEXT});
1094 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 6)))
1096 Capability::StorageImageReadWithoutFormat});
1107 int64_t DecOp =
MI.getOperand(DecIndex).getImm();
1108 auto Dec =
static_cast<SPIRV::Decoration::Decoration
>(DecOp);
1110 SPIRV::OperandCategory::DecorationOperand, Dec, ST, Reqs));
1112 if (Dec == SPIRV::Decoration::BuiltIn) {
1113 int64_t BuiltInOp =
MI.getOperand(DecIndex + 1).getImm();
1114 auto BuiltIn =
static_cast<SPIRV::BuiltIn::BuiltIn
>(BuiltInOp);
1116 SPIRV::OperandCategory::BuiltInOperand, BuiltIn, ST, Reqs));
1117 }
else if (Dec == SPIRV::Decoration::LinkageAttributes) {
1118 int64_t LinkageOp =
MI.getOperand(
MI.getNumOperands() - 1).getImm();
1119 SPIRV::LinkageType::LinkageType LnkType =
1120 static_cast<SPIRV::LinkageType::LinkageType
>(LinkageOp);
1121 if (LnkType == SPIRV::LinkageType::LinkOnceODR)
1122 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_linkonce_odr);
1123 else if (LnkType == SPIRV::LinkageType::WeakAMD) {
1124 Reqs.
addExtension(SPIRV::Extension::SPV_AMD_weak_linkage);
1127 }
else if (Dec == SPIRV::Decoration::CacheControlLoadINTEL ||
1128 Dec == SPIRV::Decoration::CacheControlStoreINTEL) {
1129 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_cache_controls);
1130 }
else if (Dec == SPIRV::Decoration::HostAccessINTEL) {
1131 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_global_variable_host_access);
1132 }
else if (Dec == SPIRV::Decoration::InitModeINTEL ||
1133 Dec == SPIRV::Decoration::ImplementInRegisterMapINTEL) {
1135 SPIRV::Extension::SPV_INTEL_global_variable_fpga_decorations);
1136 }
else if (Dec == SPIRV::Decoration::NonUniformEXT) {
1138 }
else if (Dec == SPIRV::Decoration::FPMaxErrorDecorationINTEL) {
1140 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_fp_max_error);
1141 }
else if (Dec == SPIRV::Decoration::FPFastMathMode) {
1142 if (ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2)) {
1144 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_float_controls2);
1153 assert(
MI.getNumOperands() >= 8 &&
"Insufficient operands for OpTypeImage");
1156 int64_t ImgFormatOp =
MI.getOperand(7).getImm();
1157 auto ImgFormat =
static_cast<SPIRV::ImageFormat::ImageFormat
>(ImgFormatOp);
1161 bool IsArrayed =
MI.getOperand(4).getImm() == 1;
1162 bool IsMultisampled =
MI.getOperand(5).getImm() == 1;
1163 bool NoSampler =
MI.getOperand(6).getImm() == 2;
1166 switch (
MI.getOperand(2).getImm()) {
1167 case SPIRV::Dim::DIM_1D:
1169 : SPIRV::Capability::Sampled1D);
1171 case SPIRV::Dim::DIM_2D:
1172 if (IsMultisampled && NoSampler)
1174 if (IsMultisampled && IsArrayed)
1177 case SPIRV::Dim::DIM_3D:
1179 case SPIRV::Dim::DIM_Cube:
1183 : SPIRV::Capability::SampledCubeArray);
1185 case SPIRV::Dim::DIM_Rect:
1187 : SPIRV::Capability::SampledRect);
1189 case SPIRV::Dim::DIM_Buffer:
1191 : SPIRV::Capability::SampledBuffer);
1193 case SPIRV::Dim::DIM_SubpassData:
1199 if (!ST.isShader()) {
1200 if (
MI.getNumOperands() > 8 &&
1201 MI.getOperand(8).getImm() == SPIRV::AccessQualifier::ReadWrite)
1210 TypeDef->
getOpcode() == SPIRV::OpTypeFloat &&
1216#define ATOM_FLT_REQ_EXT_MSG(ExtName) \
1217 "The atomic float instruction requires the following SPIR-V " \
1218 "extension: SPV_EXT_shader_atomic_float" ExtName
1223 MI.getMF()->getRegInfo().getVRegDef(
MI.getOperand(1).getReg());
1226 if (Rank != 2 && Rank != 4)
1228 "must be a 2-component or 4 component vector");
1233 if (EltTypeDef->
getOpcode() != SPIRV::OpTypeFloat ||
1236 "The element type for the result type of an atomic vector float "
1237 "instruction must be a 16-bit floating-point scalar");
1244 "The element type for the result type of an atomic vector float "
1245 "instruction cannot be a bfloat16 scalar");
1246 if (!ST.canUseExtension(SPIRV::Extension::SPV_NV_shader_atomic_fp16_vector))
1248 "The atomic float16 vector instruction requires the following SPIR-V "
1249 "extension: SPV_NV_shader_atomic_fp16_vector");
1251 Reqs.
addExtension(SPIRV::Extension::SPV_NV_shader_atomic_fp16_vector);
1252 Reqs.
addCapability(SPIRV::Capability::AtomicFloat16VectorNV);
1259 "Expect register operand in atomic float instruction");
1260 Register TypeReg =
MI.getOperand(1).getReg();
1266 if (TypeDef->
getOpcode() != SPIRV::OpTypeFloat)
1268 "floating-point type scalar");
1271 unsigned Op =
MI.getOpcode();
1272 if (
Op == SPIRV::OpAtomicFAddEXT) {
1273 if (!ST.canUseExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float_add))
1275 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float_add);
1279 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics))
1281 "The atomic bfloat16 instruction requires the following SPIR-V "
1282 "extension: SPV_INTEL_16bit_atomics",
1284 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics);
1285 Reqs.
addCapability(SPIRV::Capability::AtomicBFloat16AddINTEL);
1287 if (!ST.canUseExtension(
1288 SPIRV::Extension::SPV_EXT_shader_atomic_float16_add))
1290 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float16_add);
1302 "Unexpected floating-point type width in atomic float instruction");
1305 if (!ST.canUseExtension(
1306 SPIRV::Extension::SPV_EXT_shader_atomic_float_min_max))
1308 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float_min_max);
1312 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics))
1314 "The atomic bfloat16 instruction requires the following SPIR-V "
1315 "extension: SPV_INTEL_16bit_atomics",
1317 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics);
1318 Reqs.
addCapability(SPIRV::Capability::AtomicBFloat16MinMaxINTEL);
1320 Reqs.
addCapability(SPIRV::Capability::AtomicFloat16MinMaxEXT);
1324 Reqs.
addCapability(SPIRV::Capability::AtomicFloat32MinMaxEXT);
1327 Reqs.
addCapability(SPIRV::Capability::AtomicFloat64MinMaxEXT);
1331 "Unexpected floating-point type width in atomic float instruction");
1337 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1341 return Dim == SPIRV::Dim::DIM_Buffer && Sampled == 1;
1345 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1349 return Dim == SPIRV::Dim::DIM_Buffer && Sampled == 2;
1353 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1357 return Dim != SPIRV::Dim::DIM_Buffer && Sampled == 1;
1361 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1365 return Dim == SPIRV::Dim::DIM_SubpassData && Sampled == 2;
1369 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1373 return Dim != SPIRV::Dim::DIM_Buffer && Sampled == 2;
1377 if (SampledImageInst->
getOpcode() != SPIRV::OpTypeSampledImage)
1388 if (
MI.getOpcode() != SPIRV::OpDecorate)
1392 if (Dec == SPIRV::Decoration::NonUniformEXT)
1405 Register ResTypeReg = Instr.getOperand(1).getReg();
1410 if (
StorageClass != SPIRV::StorageClass::StorageClass::UniformConstant &&
1411 StorageClass != SPIRV::StorageClass::StorageClass::Uniform &&
1412 StorageClass != SPIRV::StorageClass::StorageClass::StorageBuffer) {
1419 auto FirstIndexReg = Instr.getOperand(3).getReg();
1420 bool FirstIndexIsConstant =
1423 if (
StorageClass == SPIRV::StorageClass::StorageClass::StorageBuffer) {
1426 SPIRV::Capability::StorageBufferArrayNonUniformIndexingEXT);
1427 else if (!FirstIndexIsConstant)
1429 SPIRV::Capability::StorageBufferArrayDynamicIndexing);
1435 if (PointeeType->
getOpcode() != SPIRV::OpTypeImage &&
1436 PointeeType->
getOpcode() != SPIRV::OpTypeSampledImage &&
1437 PointeeType->
getOpcode() != SPIRV::OpTypeSampler) {
1444 SPIRV::Capability::UniformTexelBufferArrayNonUniformIndexingEXT);
1445 else if (!FirstIndexIsConstant)
1447 SPIRV::Capability::UniformTexelBufferArrayDynamicIndexingEXT);
1451 SPIRV::Capability::InputAttachmentArrayNonUniformIndexingEXT);
1452 else if (!FirstIndexIsConstant)
1454 SPIRV::Capability::InputAttachmentArrayDynamicIndexingEXT);
1458 SPIRV::Capability::StorageTexelBufferArrayNonUniformIndexingEXT);
1459 else if (!FirstIndexIsConstant)
1461 SPIRV::Capability::StorageTexelBufferArrayDynamicIndexingEXT);
1464 PointeeType->
getOpcode() == SPIRV::OpTypeSampler) {
1467 SPIRV::Capability::SampledImageArrayNonUniformIndexingEXT);
1468 else if (!FirstIndexIsConstant)
1470 SPIRV::Capability::SampledImageArrayDynamicIndexing);
1474 SPIRV::Capability::StorageImageArrayNonUniformIndexingEXT);
1475 else if (!FirstIndexIsConstant)
1477 SPIRV::Capability::StorageImageArrayDynamicIndexing);
1482 if (TypeInst->
getOpcode() != SPIRV::OpTypeImage)
1491 if (ST.canUseExtension(SPIRV::Extension::SPV_KHR_integer_dot_product))
1492 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_integer_dot_product);
1496 assert(
MI.getOperand(2).isReg() &&
"Unexpected operand in dot");
1500 assert(
Input->getOperand(1).isReg() &&
"Unexpected operand in dot input");
1504 if (TypeDef->
getOpcode() == SPIRV::OpTypeInt) {
1506 Reqs.
addCapability(SPIRV::Capability::DotProductInput4x8BitPacked);
1513 "Dot operand of 8-bit integer type requires 4 components");
1514 Reqs.
addCapability(SPIRV::Capability::DotProductInput4x8Bit);
1530 unsigned AddrSpace = ASOp.
getImm();
1531 if (AddrSpace != SPIRV::StorageClass::UniformConstant) {
1532 if (!ST.canUseExtension(
1534 SPV_EXT_relaxed_printf_string_address_space)) {
1536 "required because printf uses a format string not "
1537 "in constant address space.",
1541 SPIRV::Extension::SPV_EXT_relaxed_printf_string_address_space);
1550 if (
MI.getNumOperands() <= OpIdx)
1552 uint32_t Mask =
MI.getOperand(OpIdx).getImm();
1554 if (Mask & (1U <<
I))
1565 if (ElemTypeDef->
getOpcode() == SPIRV::OpTypePointer &&
1566 ST.canUseExtension(SPIRV::Extension::SPV_INTEL_masked_gather_scatter)) {
1567 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_masked_gather_scatter);
1568 Reqs.
addCapability(SPIRV::Capability::MaskedGatherScatterINTEL);
1576 unsigned Op =
MI.getOpcode();
1578 case SPIRV::OpMemoryModel: {
1579 int64_t Addr =
MI.getOperand(0).getImm();
1582 int64_t Mem =
MI.getOperand(1).getImm();
1587 case SPIRV::OpEntryPoint: {
1588 int64_t Exe =
MI.getOperand(0).getImm();
1593 case SPIRV::OpExecutionMode:
1594 case SPIRV::OpExecutionModeId: {
1595 int64_t Exe =
MI.getOperand(1).getImm();
1600 case SPIRV::OpTypeMatrix:
1603 case SPIRV::OpTypeInt: {
1604 unsigned BitWidth =
MI.getOperand(1).getImm();
1612 ST.canUseExtension(SPIRV::Extension::SPV_INTEL_int4)) {
1616 if (!ST.canUseExtension(
1617 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_integers))
1619 "OpTypeInt type with a width other than 8, 16, 32 or 64 bits "
1620 "requires the following SPIR-V extension: "
1621 "SPV_ALTERA_arbitrary_precision_integers");
1623 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_integers);
1624 Reqs.
addCapability(SPIRV::Capability::ArbitraryPrecisionIntegersALTERA);
1628 case SPIRV::OpDot: {
1632 Reqs.
addCapability(SPIRV::Capability::BFloat16DotProductKHR);
1635 case SPIRV::OpTypeFloat: {
1636 unsigned BitWidth =
MI.getOperand(1).getImm();
1641 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_bfloat16))
1643 "following SPIR-V extension: SPV_KHR_bfloat16",
1653 case SPIRV::OpTypeVector: {
1654 unsigned NumComponents =
MI.getOperand(2).getImm();
1655 if (NumComponents == 8 || NumComponents == 16)
1660 "OpTypeVector with " +
Twine(NumComponents) +
1661 " components requires the following SPIR-V extension: "
1662 "SPV_EXT_long_vector");
1667 case SPIRV::OpTypeVectorIdEXT: {
1668 if (!ST.canUseExtension(SPIRV::Extension::SPV_EXT_long_vector))
1670 "extension: SPV_EXT_long_vector extension");
1671 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_long_vector);
1676 case SPIRV::OpTypePointer: {
1677 auto SC =
MI.getOperand(1).getImm();
1688 (TypeDef->
getOpcode() == SPIRV::OpTypeFloat) &&
1693 case SPIRV::OpExtInst: {
1694 if (
MI.getOperand(2).getImm() ==
1695 static_cast<int64_t
>(
1696 SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100)) {
1697 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_non_semantic_info);
1700 if (
MI.getOperand(3).getImm() ==
1701 static_cast<int64_t
>(SPIRV::OpenCLExtInst::printf)) {
1705 if (
MI.getOperand(2).getImm() ==
1706 static_cast<int64_t
>(SPIRV::InstructionSet::OpenCL_std)) {
1712 if (TypeDef && TypeDef->getOpcode() == SPIRV::OpTypeVector)
1713 TypeDef = MRI.
getVRegDef(TypeDef->getOperand(1).getReg());
1718 bool UsesBFloat16 = IsBFloat16(MRI.
getVRegDef(
MI.getOperand(1).getReg()));
1719 for (
unsigned I = 4,
E =
MI.getNumOperands();
I <
E && !UsesBFloat16;
1728 if (!ST.canUseExtension(
1729 SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic)) {
1731 MI,
"OpenCL Extended instructions with bfloat16 require the "
1732 "following SPIR-V extension: SPV_INTEL_bfloat16_arithmetic");
1735 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic);
1736 Reqs.
addCapability(SPIRV::Capability::BFloat16ArithmeticINTEL);
1741 case SPIRV::OpAliasDomainDeclINTEL:
1742 case SPIRV::OpAliasScopeDeclINTEL:
1743 case SPIRV::OpAliasScopeListDeclINTEL: {
1744 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_memory_access_aliasing);
1745 Reqs.
addCapability(SPIRV::Capability::MemoryAccessAliasingINTEL);
1748 case SPIRV::OpBitReverse:
1749 case SPIRV::OpBitFieldInsert:
1750 case SPIRV::OpBitFieldSExtract:
1751 case SPIRV::OpBitFieldUExtract:
1752 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_bit_instructions)) {
1756 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_bit_instructions);
1759 case SPIRV::OpTypeRuntimeArray:
1762 case SPIRV::OpTypeOpaque:
1763 case SPIRV::OpTypeEvent:
1766 case SPIRV::OpTypePipe:
1767 case SPIRV::OpTypeReserveId:
1770 case SPIRV::OpTypeDeviceEvent:
1771 case SPIRV::OpTypeQueue:
1772 case SPIRV::OpBuildNDRange:
1773 case SPIRV::OpEnqueueKernel:
1774 case SPIRV::OpGetKernelNDrangeSubGroupCount:
1775 case SPIRV::OpGetKernelNDrangeMaxSubGroupSize:
1776 case SPIRV::OpGetKernelWorkGroupSize:
1777 case SPIRV::OpGetKernelPreferredWorkGroupSizeMultiple:
1780 case SPIRV::OpDecorate:
1781 case SPIRV::OpDecorateId:
1782 case SPIRV::OpDecorateString:
1785 case SPIRV::OpMemberDecorate:
1786 case SPIRV::OpMemberDecorateString:
1789 case SPIRV::OpInBoundsPtrAccessChain:
1792 case SPIRV::OpConstantSampler:
1795 case SPIRV::OpInBoundsAccessChain:
1796 case SPIRV::OpAccessChain:
1799 case SPIRV::OpTypeImage:
1802 case SPIRV::OpTypeSampler:
1803 if (!ST.isShader()) {
1807 case SPIRV::OpTypeForwardPointer:
1811 case SPIRV::OpAtomicFlagTestAndSet:
1812 case SPIRV::OpAtomicLoad:
1813 case SPIRV::OpAtomicStore:
1814 case SPIRV::OpAtomicExchange:
1815 case SPIRV::OpAtomicCompareExchange:
1816 case SPIRV::OpAtomicCompareExchangeWeak:
1817 case SPIRV::OpAtomicIIncrement:
1818 case SPIRV::OpAtomicIDecrement:
1819 case SPIRV::OpAtomicIAdd:
1820 case SPIRV::OpAtomicISub:
1821 case SPIRV::OpAtomicUMin:
1822 case SPIRV::OpAtomicUMax:
1823 case SPIRV::OpAtomicSMin:
1824 case SPIRV::OpAtomicSMax:
1825 case SPIRV::OpAtomicAnd:
1826 case SPIRV::OpAtomicOr:
1827 case SPIRV::OpAtomicXor: {
1830 if (
Op == SPIRV::OpAtomicStore) {
1833 assert(InstrPtr &&
"Unexpected type instruction for OpAtomicStore");
1839 if (TypeDef->
getOpcode() == SPIRV::OpTypeInt) {
1844 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics))
1846 "16-bit integer atomic operations require the following SPIR-V "
1847 "extension: SPV_INTEL_16bit_atomics",
1849 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics);
1851 case SPIRV::OpAtomicLoad:
1852 case SPIRV::OpAtomicStore:
1853 case SPIRV::OpAtomicExchange:
1854 case SPIRV::OpAtomicCompareExchange:
1855 case SPIRV::OpAtomicCompareExchangeWeak:
1857 SPIRV::Capability::AtomicInt16CompareExchangeINTEL);
1865 if (
is_contained({SPIRV::OpAtomicLoad, SPIRV::OpAtomicStore,
1866 SPIRV::OpAtomicExchange},
1868 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics))
1870 "The atomic bfloat16 instruction requires the following SPIR-V "
1871 "extension: SPV_INTEL_16bit_atomics",
1873 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics);
1874 Reqs.
addCapability(SPIRV::Capability::AtomicBFloat16LoadStoreINTEL);
1879 case SPIRV::OpGroupNonUniformIAdd:
1880 case SPIRV::OpGroupNonUniformFAdd:
1881 case SPIRV::OpGroupNonUniformIMul:
1882 case SPIRV::OpGroupNonUniformFMul:
1883 case SPIRV::OpGroupNonUniformSMin:
1884 case SPIRV::OpGroupNonUniformUMin:
1885 case SPIRV::OpGroupNonUniformFMin:
1886 case SPIRV::OpGroupNonUniformSMax:
1887 case SPIRV::OpGroupNonUniformUMax:
1888 case SPIRV::OpGroupNonUniformFMax:
1889 case SPIRV::OpGroupNonUniformBitwiseAnd:
1890 case SPIRV::OpGroupNonUniformBitwiseOr:
1891 case SPIRV::OpGroupNonUniformBitwiseXor:
1892 case SPIRV::OpGroupNonUniformLogicalAnd:
1893 case SPIRV::OpGroupNonUniformLogicalOr:
1894 case SPIRV::OpGroupNonUniformLogicalXor: {
1896 int64_t GroupOp =
MI.getOperand(3).getImm();
1898 case SPIRV::GroupOperation::Reduce:
1899 case SPIRV::GroupOperation::InclusiveScan:
1900 case SPIRV::GroupOperation::ExclusiveScan:
1901 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformArithmetic);
1903 case SPIRV::GroupOperation::ClusteredReduce:
1904 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformClustered);
1906 case SPIRV::GroupOperation::PartitionedReduceNV:
1907 case SPIRV::GroupOperation::PartitionedInclusiveScanNV:
1908 case SPIRV::GroupOperation::PartitionedExclusiveScanNV:
1909 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformPartitionedNV);
1914 case SPIRV::OpGroupNonUniformQuadSwap:
1917 case SPIRV::OpImageQueryLod:
1920 case SPIRV::OpImageQuerySize:
1921 case SPIRV::OpImageQuerySizeLod:
1922 case SPIRV::OpImageQueryLevels:
1923 case SPIRV::OpImageQuerySamples:
1927 case SPIRV::OpImageQueryFormat: {
1928 Register ResultReg =
MI.getOperand(0).getReg();
1930 static const unsigned CompareOps[] = {
1931 SPIRV::OpIEqual, SPIRV::OpINotEqual,
1932 SPIRV::OpUGreaterThan, SPIRV::OpUGreaterThanEqual,
1933 SPIRV::OpULessThan, SPIRV::OpULessThanEqual,
1934 SPIRV::OpSGreaterThan, SPIRV::OpSGreaterThanEqual,
1935 SPIRV::OpSLessThan, SPIRV::OpSLessThanEqual};
1937 auto CheckAndAddExtension = [&](int64_t ImmVal) {
1938 if (ImmVal == 4323 || ImmVal == 4324) {
1939 if (ST.canUseExtension(SPIRV::Extension::SPV_EXT_image_raw10_raw12))
1940 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_image_raw10_raw12);
1943 "SPV_EXT_image_raw10_raw12 extension");
1948 unsigned Opc = UseInst.getOpcode();
1950 if (
Opc == SPIRV::OpSwitch) {
1953 CheckAndAddExtension(
Op.getImm());
1955 for (
unsigned i = 1; i < UseInst.getNumOperands(); ++i) {
1958 if (ConstInst && ConstInst->
getOpcode() == SPIRV::OpConstantI) {
1961 CheckAndAddExtension(ImmVal);
1969 case SPIRV::OpGroupNonUniformShuffle:
1970 case SPIRV::OpGroupNonUniformShuffleXor:
1971 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformShuffle);
1973 case SPIRV::OpGroupNonUniformShuffleUp:
1974 case SPIRV::OpGroupNonUniformShuffleDown:
1975 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformShuffleRelative);
1977 case SPIRV::OpGroupAll:
1978 case SPIRV::OpGroupAny:
1979 case SPIRV::OpGroupBroadcast:
1980 case SPIRV::OpGroupIAdd:
1981 case SPIRV::OpGroupFAdd:
1982 case SPIRV::OpGroupFMin:
1983 case SPIRV::OpGroupUMin:
1984 case SPIRV::OpGroupSMin:
1985 case SPIRV::OpGroupFMax:
1986 case SPIRV::OpGroupUMax:
1987 case SPIRV::OpGroupSMax:
1990 case SPIRV::OpGroupNonUniformElect:
1993 case SPIRV::OpGroupNonUniformAll:
1994 case SPIRV::OpGroupNonUniformAny:
1995 case SPIRV::OpGroupNonUniformAllEqual:
1998 case SPIRV::OpGroupNonUniformBroadcast:
1999 case SPIRV::OpGroupNonUniformBroadcastFirst:
2000 case SPIRV::OpGroupNonUniformBallot:
2001 case SPIRV::OpGroupNonUniformInverseBallot:
2002 case SPIRV::OpGroupNonUniformBallotBitExtract:
2003 case SPIRV::OpGroupNonUniformBallotBitCount:
2004 case SPIRV::OpGroupNonUniformBallotFindLSB:
2005 case SPIRV::OpGroupNonUniformBallotFindMSB:
2006 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformBallot);
2008 case SPIRV::OpSubgroupShuffleINTEL:
2009 case SPIRV::OpSubgroupShuffleDownINTEL:
2010 case SPIRV::OpSubgroupShuffleUpINTEL:
2011 case SPIRV::OpSubgroupShuffleXorINTEL:
2012 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {
2013 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_subgroups);
2014 Reqs.
addCapability(SPIRV::Capability::SubgroupShuffleINTEL);
2017 case SPIRV::OpSubgroupBlockReadINTEL:
2018 case SPIRV::OpSubgroupBlockWriteINTEL:
2019 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {
2020 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_subgroups);
2021 Reqs.
addCapability(SPIRV::Capability::SubgroupBufferBlockIOINTEL);
2024 case SPIRV::OpSubgroupImageBlockReadINTEL:
2025 case SPIRV::OpSubgroupImageBlockWriteINTEL:
2026 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {
2027 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_subgroups);
2028 Reqs.
addCapability(SPIRV::Capability::SubgroupImageBlockIOINTEL);
2031 case SPIRV::OpSubgroupImageMediaBlockReadINTEL:
2032 case SPIRV::OpSubgroupImageMediaBlockWriteINTEL:
2033 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_media_block_io)) {
2034 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_media_block_io);
2035 Reqs.
addCapability(SPIRV::Capability::SubgroupImageMediaBlockIOINTEL);
2038 case SPIRV::OpAssumeTrueKHR:
2039 case SPIRV::OpExpectKHR:
2040 if (ST.canUseExtension(SPIRV::Extension::SPV_KHR_expect_assume)) {
2041 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_expect_assume);
2045 case SPIRV::OpFmaKHR:
2046 if (ST.canUseExtension(SPIRV::Extension::SPV_KHR_fma)) {
2051 case SPIRV::OpPtrCastToCrossWorkgroupINTEL:
2052 case SPIRV::OpCrossWorkgroupCastToPtrINTEL:
2053 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_usm_storage_classes)) {
2054 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_usm_storage_classes);
2055 Reqs.
addCapability(SPIRV::Capability::USMStorageClassesINTEL);
2058 case SPIRV::OpConstantFunctionPointerINTEL:
2059 case SPIRV::OpFunctionPointerCallINTEL:
2060 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_function_pointers)) {
2061 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_function_pointers);
2062 Reqs.
addCapability(SPIRV::Capability::FunctionPointersINTEL);
2065 case SPIRV::OpGroupNonUniformRotateKHR:
2066 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_subgroup_rotate))
2068 "following SPIR-V extension: SPV_KHR_subgroup_rotate",
2070 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_subgroup_rotate);
2071 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformRotateKHR);
2074 case SPIRV::OpFixedCosALTERA:
2075 case SPIRV::OpFixedSinALTERA:
2076 case SPIRV::OpFixedCosPiALTERA:
2077 case SPIRV::OpFixedSinPiALTERA:
2078 case SPIRV::OpFixedExpALTERA:
2079 case SPIRV::OpFixedLogALTERA:
2080 case SPIRV::OpFixedRecipALTERA:
2081 case SPIRV::OpFixedSqrtALTERA:
2082 case SPIRV::OpFixedSinCosALTERA:
2083 case SPIRV::OpFixedSinCosPiALTERA:
2084 case SPIRV::OpFixedRsqrtALTERA:
2085 if (!ST.canUseExtension(
2086 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_fixed_point))
2088 "following SPIR-V extension: "
2089 "SPV_ALTERA_arbitrary_precision_fixed_point",
2092 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_fixed_point);
2093 Reqs.
addCapability(SPIRV::Capability::ArbitraryPrecisionFixedPointALTERA);
2095 case SPIRV::OpGroupIMulKHR:
2096 case SPIRV::OpGroupFMulKHR:
2097 case SPIRV::OpGroupBitwiseAndKHR:
2098 case SPIRV::OpGroupBitwiseOrKHR:
2099 case SPIRV::OpGroupBitwiseXorKHR:
2100 case SPIRV::OpGroupLogicalAndKHR:
2101 case SPIRV::OpGroupLogicalOrKHR:
2102 case SPIRV::OpGroupLogicalXorKHR:
2103 if (ST.canUseExtension(
2104 SPIRV::Extension::SPV_KHR_uniform_group_instructions)) {
2105 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_uniform_group_instructions);
2106 Reqs.
addCapability(SPIRV::Capability::GroupUniformArithmeticKHR);
2109 case SPIRV::OpReadClockKHR:
2110 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_shader_clock))
2112 "following SPIR-V extension: SPV_KHR_shader_clock",
2114 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_shader_clock);
2117 case SPIRV::OpAbortKHR:
2118 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_abort))
2120 "following SPIR-V extension: SPV_KHR_abort",
2125 case SPIRV::OpPoisonKHR:
2126 case SPIRV::OpFreezeKHR:
2127 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_poison_freeze))
2129 "following SPIR-V extension: SPV_KHR_poison_freeze",
2131 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_poison_freeze);
2134 case SPIRV::OpAtomicFAddEXT:
2135 case SPIRV::OpAtomicFMinEXT:
2136 case SPIRV::OpAtomicFMaxEXT:
2139 case SPIRV::OpConvertBF16ToFINTEL:
2140 case SPIRV::OpConvertFToBF16INTEL:
2141 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bfloat16_conversion)) {
2142 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bfloat16_conversion);
2143 Reqs.
addCapability(SPIRV::Capability::BFloat16ConversionINTEL);
2146 case SPIRV::OpRoundFToTF32INTEL:
2147 if (ST.canUseExtension(
2148 SPIRV::Extension::SPV_INTEL_tensor_float32_conversion)) {
2149 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_tensor_float32_conversion);
2150 Reqs.
addCapability(SPIRV::Capability::TensorFloat32RoundingINTEL);
2153 case SPIRV::OpVariableLengthArrayINTEL:
2154 case SPIRV::OpSaveMemoryINTEL:
2155 case SPIRV::OpRestoreMemoryINTEL:
2156 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_variable_length_array)) {
2157 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_variable_length_array);
2158 Reqs.
addCapability(SPIRV::Capability::VariableLengthArrayINTEL);
2161 case SPIRV::OpUntypedVariableLengthArrayINTEL:
2162 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_variable_length_array)) {
2163 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_variable_length_array);
2164 Reqs.
addCapability(SPIRV::Capability::UntypedVariableLengthArrayINTEL);
2167 case SPIRV::OpAsmTargetINTEL:
2168 case SPIRV::OpAsmINTEL:
2169 case SPIRV::OpAsmCallINTEL:
2170 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_inline_assembly)) {
2171 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_inline_assembly);
2175 case SPIRV::OpTypeCooperativeMatrixKHR: {
2176 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix))
2178 "OpTypeCooperativeMatrixKHR type requires the "
2179 "following SPIR-V extension: SPV_KHR_cooperative_matrix",
2181 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix);
2182 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixKHR);
2186 Reqs.
addCapability(SPIRV::Capability::BFloat16CooperativeMatrixKHR);
2189 case SPIRV::OpArithmeticFenceEXT:
2190 if (!ST.canUseExtension(SPIRV::Extension::SPV_EXT_arithmetic_fence))
2192 "following SPIR-V extension: SPV_EXT_arithmetic_fence",
2194 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_arithmetic_fence);
2197 case SPIRV::OpControlBarrierArriveINTEL:
2198 case SPIRV::OpControlBarrierWaitINTEL:
2199 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_split_barrier)) {
2200 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_split_barrier);
2204 case SPIRV::OpCooperativeMatrixMulAddKHR: {
2205 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix))
2207 "following SPIR-V extension: "
2208 "SPV_KHR_cooperative_matrix",
2210 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix);
2211 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixKHR);
2212 constexpr unsigned MulAddMaxSize = 6;
2213 if (
MI.getNumOperands() != MulAddMaxSize)
2215 const int64_t CoopOperands =
MI.getOperand(MulAddMaxSize - 1).getImm();
2217 SPIRV::CooperativeMatrixOperands::MatrixAAndBTF32ComponentsINTEL) {
2218 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
2220 "require the following SPIR-V extension: "
2221 "SPV_INTEL_joint_matrix",
2223 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2225 SPIRV::Capability::CooperativeMatrixTF32ComponentTypeINTEL);
2228 MatrixAAndBBFloat16ComponentsINTEL ||
2230 SPIRV::CooperativeMatrixOperands::MatrixCBFloat16ComponentsINTEL ||
2232 MatrixResultBFloat16ComponentsINTEL) {
2233 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
2235 "require the following SPIR-V extension: "
2236 "SPV_INTEL_joint_matrix",
2238 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2240 SPIRV::Capability::CooperativeMatrixBFloat16ComponentTypeINTEL);
2244 case SPIRV::OpCooperativeMatrixLoadKHR:
2245 case SPIRV::OpCooperativeMatrixStoreKHR:
2246 case SPIRV::OpCooperativeMatrixLoadCheckedINTEL:
2247 case SPIRV::OpCooperativeMatrixStoreCheckedINTEL:
2248 case SPIRV::OpCooperativeMatrixPrefetchINTEL: {
2249 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix))
2251 "following SPIR-V extension: "
2252 "SPV_KHR_cooperative_matrix",
2254 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix);
2255 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixKHR);
2261 case SPIRV::OpCooperativeMatrixLoadKHR:
2264 case SPIRV::OpCooperativeMatrixStoreKHR:
2267 case SPIRV::OpCooperativeMatrixLoadCheckedINTEL:
2270 case SPIRV::OpCooperativeMatrixStoreCheckedINTEL:
2271 case SPIRV::OpCooperativeMatrixPrefetchINTEL:
2277 Register RegLayout =
MI.getOperand(LayoutNum).getReg();
2280 if (MILayout->
getOpcode() == SPIRV::OpConstantI) {
2283 static_cast<unsigned>(SPIRV::CooperativeMatrixLayout::PackedINTEL)) {
2284 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
2286 "extension: SPV_INTEL_joint_matrix",
2288 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2289 Reqs.
addCapability(SPIRV::Capability::PackedCooperativeMatrixINTEL);
2294 if (
Op == SPIRV::OpCooperativeMatrixLoadKHR ||
2295 Op == SPIRV::OpCooperativeMatrixStoreKHR)
2298 std::string InstName;
2300 case SPIRV::OpCooperativeMatrixPrefetchINTEL:
2301 InstName =
"OpCooperativeMatrixPrefetchINTEL";
2303 case SPIRV::OpCooperativeMatrixLoadCheckedINTEL:
2304 InstName =
"OpCooperativeMatrixLoadCheckedINTEL";
2306 case SPIRV::OpCooperativeMatrixStoreCheckedINTEL:
2307 InstName =
"OpCooperativeMatrixStoreCheckedINTEL";
2311 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix)) {
2312 const std::string ErrorMsg =
2313 InstName +
" instruction requires the "
2314 "following SPIR-V extension: SPV_INTEL_joint_matrix";
2317 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2318 if (
Op == SPIRV::OpCooperativeMatrixPrefetchINTEL) {
2319 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixPrefetchINTEL);
2323 SPIRV::Capability::CooperativeMatrixCheckedInstructionsINTEL);
2326 case SPIRV::OpCooperativeMatrixConstructCheckedINTEL:
2327 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
2329 "instructions require the following SPIR-V extension: "
2330 "SPV_INTEL_joint_matrix",
2332 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2334 SPIRV::Capability::CooperativeMatrixCheckedInstructionsINTEL);
2336 case SPIRV::OpReadPipeBlockingALTERA:
2337 case SPIRV::OpWritePipeBlockingALTERA:
2338 if (ST.canUseExtension(SPIRV::Extension::SPV_ALTERA_blocking_pipes)) {
2339 Reqs.
addExtension(SPIRV::Extension::SPV_ALTERA_blocking_pipes);
2343 case SPIRV::OpCooperativeMatrixGetElementCoordINTEL:
2344 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
2346 "following SPIR-V extension: SPV_INTEL_joint_matrix",
2348 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2350 SPIRV::Capability::CooperativeMatrixInvocationInstructionsINTEL);
2352 case SPIRV::OpConvertHandleToImageINTEL:
2353 case SPIRV::OpConvertHandleToSamplerINTEL:
2354 case SPIRV::OpConvertHandleToSampledImageINTEL: {
2355 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bindless_images))
2357 "instructions require the following SPIR-V extension: "
2358 "SPV_INTEL_bindless_images",
2361 SPIRV::AddressingModel::AddressingModel AddrModel = MAI.
Addr;
2363 if (
Op == SPIRV::OpConvertHandleToImageINTEL &&
2364 TyDef->
getOpcode() != SPIRV::OpTypeImage) {
2366 "OpConvertHandleToImageINTEL",
2368 }
else if (
Op == SPIRV::OpConvertHandleToSamplerINTEL &&
2369 TyDef->
getOpcode() != SPIRV::OpTypeSampler) {
2371 "OpConvertHandleToSamplerINTEL",
2373 }
else if (
Op == SPIRV::OpConvertHandleToSampledImageINTEL &&
2374 TyDef->
getOpcode() != SPIRV::OpTypeSampledImage) {
2376 "OpConvertHandleToSampledImageINTEL",
2381 if (!(Bitwidth == 32 && AddrModel == SPIRV::AddressingModel::Physical32) &&
2382 !(Bitwidth == 64 && AddrModel == SPIRV::AddressingModel::Physical64)) {
2384 "Parameter value must be a 32-bit scalar in case of "
2385 "Physical32 addressing model or a 64-bit scalar in case of "
2386 "Physical64 addressing model",
2389 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bindless_images);
2393 case SPIRV::OpSubgroup2DBlockLoadINTEL:
2394 case SPIRV::OpSubgroup2DBlockLoadTransposeINTEL:
2395 case SPIRV::OpSubgroup2DBlockLoadTransformINTEL:
2396 case SPIRV::OpSubgroup2DBlockPrefetchINTEL:
2397 case SPIRV::OpSubgroup2DBlockStoreINTEL: {
2398 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_2d_block_io))
2400 "Prefetch/Store]INTEL instructions require the "
2401 "following SPIR-V extension: SPV_INTEL_2d_block_io",
2403 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_2d_block_io);
2404 Reqs.
addCapability(SPIRV::Capability::Subgroup2DBlockIOINTEL);
2406 if (
Op == SPIRV::OpSubgroup2DBlockLoadTransposeINTEL) {
2407 Reqs.
addCapability(SPIRV::Capability::Subgroup2DBlockTransposeINTEL);
2410 if (
Op == SPIRV::OpSubgroup2DBlockLoadTransformINTEL) {
2411 Reqs.
addCapability(SPIRV::Capability::Subgroup2DBlockTransformINTEL);
2416 case SPIRV::OpKill: {
2419 case SPIRV::OpDemoteToHelperInvocation:
2420 Reqs.
addCapability(SPIRV::Capability::DemoteToHelperInvocation);
2422 if (ST.canUseExtension(
2423 SPIRV::Extension::SPV_EXT_demote_to_helper_invocation)) {
2426 SPIRV::Extension::SPV_EXT_demote_to_helper_invocation);
2431 case SPIRV::OpSUDot:
2432 case SPIRV::OpSDotAccSat:
2433 case SPIRV::OpUDotAccSat:
2434 case SPIRV::OpSUDotAccSat:
2437 case SPIRV::OpImageSampleImplicitLod:
2438 case SPIRV::OpImageFetch:
2442 case SPIRV::OpImageSampleExplicitLod:
2445 case SPIRV::OpImageSampleDrefImplicitLod:
2446 case SPIRV::OpImageSampleDrefExplicitLod:
2447 case SPIRV::OpImageDrefGather:
2448 case SPIRV::OpImageGather:
2452 case SPIRV::OpImageRead: {
2453 Register ImageReg =
MI.getOperand(2).getReg();
2454 SPIRVTypeInst TypeDef = ST.getSPIRVGlobalRegistry()->getResultType(
2463 Reqs.
addCapability(SPIRV::Capability::StorageImageReadWithoutFormat);
2466 case SPIRV::OpImageWrite: {
2467 Register ImageReg =
MI.getOperand(0).getReg();
2468 SPIRVTypeInst TypeDef = ST.getSPIRVGlobalRegistry()->getResultType(
2477 Reqs.
addCapability(SPIRV::Capability::StorageImageWriteWithoutFormat);
2480 case SPIRV::OpTypeStructContinuedINTEL:
2481 case SPIRV::OpConstantCompositeContinuedINTEL:
2482 case SPIRV::OpSpecConstantCompositeContinuedINTEL:
2483 case SPIRV::OpCompositeConstructContinuedINTEL: {
2484 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_long_composites))
2486 "Continued instructions require the "
2487 "following SPIR-V extension: SPV_INTEL_long_composites",
2489 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_long_composites);
2493 case SPIRV::OpArbitraryFloatEQALTERA:
2494 case SPIRV::OpArbitraryFloatGEALTERA:
2495 case SPIRV::OpArbitraryFloatGTALTERA:
2496 case SPIRV::OpArbitraryFloatLEALTERA:
2497 case SPIRV::OpArbitraryFloatLTALTERA:
2498 case SPIRV::OpArbitraryFloatCbrtALTERA:
2499 case SPIRV::OpArbitraryFloatCosALTERA:
2500 case SPIRV::OpArbitraryFloatCosPiALTERA:
2501 case SPIRV::OpArbitraryFloatExp10ALTERA:
2502 case SPIRV::OpArbitraryFloatExp2ALTERA:
2503 case SPIRV::OpArbitraryFloatExpALTERA:
2504 case SPIRV::OpArbitraryFloatExpm1ALTERA:
2505 case SPIRV::OpArbitraryFloatHypotALTERA:
2506 case SPIRV::OpArbitraryFloatLog10ALTERA:
2507 case SPIRV::OpArbitraryFloatLog1pALTERA:
2508 case SPIRV::OpArbitraryFloatLog2ALTERA:
2509 case SPIRV::OpArbitraryFloatLogALTERA:
2510 case SPIRV::OpArbitraryFloatRecipALTERA:
2511 case SPIRV::OpArbitraryFloatSinCosALTERA:
2512 case SPIRV::OpArbitraryFloatSinCosPiALTERA:
2513 case SPIRV::OpArbitraryFloatSinALTERA:
2514 case SPIRV::OpArbitraryFloatSinPiALTERA:
2515 case SPIRV::OpArbitraryFloatSqrtALTERA:
2516 case SPIRV::OpArbitraryFloatACosALTERA:
2517 case SPIRV::OpArbitraryFloatACosPiALTERA:
2518 case SPIRV::OpArbitraryFloatAddALTERA:
2519 case SPIRV::OpArbitraryFloatASinALTERA:
2520 case SPIRV::OpArbitraryFloatASinPiALTERA:
2521 case SPIRV::OpArbitraryFloatATan2ALTERA:
2522 case SPIRV::OpArbitraryFloatATanALTERA:
2523 case SPIRV::OpArbitraryFloatATanPiALTERA:
2524 case SPIRV::OpArbitraryFloatCastFromIntALTERA:
2525 case SPIRV::OpArbitraryFloatCastALTERA:
2526 case SPIRV::OpArbitraryFloatCastToIntALTERA:
2527 case SPIRV::OpArbitraryFloatDivALTERA:
2528 case SPIRV::OpArbitraryFloatMulALTERA:
2529 case SPIRV::OpArbitraryFloatPowALTERA:
2530 case SPIRV::OpArbitraryFloatPowNALTERA:
2531 case SPIRV::OpArbitraryFloatPowRALTERA:
2532 case SPIRV::OpArbitraryFloatRSqrtALTERA:
2533 case SPIRV::OpArbitraryFloatSubALTERA: {
2534 if (!ST.canUseExtension(
2535 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_floating_point))
2537 "Floating point instructions can't be translated correctly without "
2538 "enabled SPV_ALTERA_arbitrary_precision_floating_point extension!",
2541 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_floating_point);
2543 SPIRV::Capability::ArbitraryPrecisionFloatingPointALTERA);
2546 case SPIRV::OpSubgroupMatrixMultiplyAccumulateINTEL: {
2547 if (!ST.canUseExtension(
2548 SPIRV::Extension::SPV_INTEL_subgroup_matrix_multiply_accumulate))
2550 "OpSubgroupMatrixMultiplyAccumulateINTEL instruction requires the "
2552 "extension: SPV_INTEL_subgroup_matrix_multiply_accumulate",
2555 SPIRV::Extension::SPV_INTEL_subgroup_matrix_multiply_accumulate);
2557 SPIRV::Capability::SubgroupMatrixMultiplyAccumulateINTEL);
2560 case SPIRV::OpBitwiseFunctionINTEL: {
2561 if (!ST.canUseExtension(
2562 SPIRV::Extension::SPV_INTEL_ternary_bitwise_function))
2564 "OpBitwiseFunctionINTEL instruction requires the following SPIR-V "
2565 "extension: SPV_INTEL_ternary_bitwise_function",
2567 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_ternary_bitwise_function);
2568 Reqs.
addCapability(SPIRV::Capability::TernaryBitwiseFunctionINTEL);
2571 case SPIRV::OpCopyMemorySized: {
2576 case SPIRV::OpTypeUntypedPointerKHR:
2578 MI.getOperand(1).getImm(), ST);
2580 case SPIRV::OpUntypedVariableKHR:
2581 case SPIRV::OpUntypedAccessChainKHR:
2582 case SPIRV::OpUntypedInBoundsAccessChainKHR:
2583 case SPIRV::OpUntypedPtrAccessChainKHR:
2584 case SPIRV::OpUntypedInBoundsPtrAccessChainKHR:
2585 case SPIRV::OpUntypedPrefetchKHR:
2586 case SPIRV::OpUntypedGroupAsyncCopyKHR: {
2587 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_untyped_pointers))
2589 "SPIR-V extension: SPV_KHR_untyped_pointers",
2591 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_untyped_pointers);
2595 case SPIRV::OpPredicatedLoadINTEL:
2596 case SPIRV::OpPredicatedStoreINTEL: {
2597 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_predicated_io))
2599 "OpPredicated[Load/Store]INTEL instructions require "
2600 "the following SPIR-V extension: SPV_INTEL_predicated_io",
2602 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_predicated_io);
2606 case SPIRV::OpFAddS:
2607 case SPIRV::OpFSubS:
2608 case SPIRV::OpFMulS:
2609 case SPIRV::OpFDivS:
2610 case SPIRV::OpFRemS:
2612 case SPIRV::OpFNegate:
2613 case SPIRV::OpFAddV:
2614 case SPIRV::OpFSubV:
2615 case SPIRV::OpFMulV:
2616 case SPIRV::OpFDivV:
2617 case SPIRV::OpFRemV:
2618 case SPIRV::OpFNegateV: {
2624 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic))
2626 "Arithmetic instructions with bfloat16 arguments require the "
2627 "following SPIR-V extension: SPV_INTEL_bfloat16_arithmetic",
2629 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic);
2630 Reqs.
addCapability(SPIRV::Capability::BFloat16ArithmeticINTEL);
2634 case SPIRV::OpOrdered:
2635 case SPIRV::OpUnordered:
2636 case SPIRV::OpFOrdEqual:
2637 case SPIRV::OpFOrdNotEqual:
2638 case SPIRV::OpFOrdLessThan:
2639 case SPIRV::OpFOrdLessThanEqual:
2640 case SPIRV::OpFOrdGreaterThan:
2641 case SPIRV::OpFOrdGreaterThanEqual:
2642 case SPIRV::OpFUnordEqual:
2643 case SPIRV::OpFUnordNotEqual:
2644 case SPIRV::OpFUnordLessThan:
2645 case SPIRV::OpFUnordLessThanEqual:
2646 case SPIRV::OpFUnordGreaterThan:
2647 case SPIRV::OpFUnordGreaterThanEqual: {
2654 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic))
2656 "Relational instructions with bfloat16 arguments require the "
2657 "following SPIR-V extension: SPV_INTEL_bfloat16_arithmetic",
2659 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic);
2660 Reqs.
addCapability(SPIRV::Capability::BFloat16ArithmeticINTEL);
2664 case SPIRV::OpDPdxCoarse:
2665 case SPIRV::OpDPdyCoarse:
2666 case SPIRV::OpDPdxFine:
2667 case SPIRV::OpDPdyFine: {
2671 case SPIRV::OpLoopControlINTEL: {
2672 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_unstructured_loop_controls);
2673 Reqs.
addCapability(SPIRV::Capability::UnstructuredLoopControlsINTEL);
2685 SPIRV::Capability::Shader);
2700 auto Node = M.getNamedMetadata(
"spirv.ExecutionMode");
2702 bool RequireFloatControls =
false, RequireIntelFloatControls2 =
false,
2703 RequireKHRFloatControls2 =
false,
2704 VerLower14 = !ST.isAtLeastSPIRVVer(
VersionTuple(1, 4));
2705 bool HasIntelFloatControls2 =
2706 ST.canUseExtension(SPIRV::Extension::SPV_INTEL_float_controls2);
2707 bool HasKHRFloatControls2 =
2708 ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2);
2709 for (
unsigned i = 0; i <
Node->getNumOperands(); i++) {
2715 auto EM = Const->getZExtValue();
2719 case SPIRV::ExecutionMode::DenormPreserve:
2720 case SPIRV::ExecutionMode::DenormFlushToZero:
2721 case SPIRV::ExecutionMode::RoundingModeRTE:
2722 case SPIRV::ExecutionMode::RoundingModeRTZ:
2723 RequireFloatControls = VerLower14;
2725 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2727 case SPIRV::ExecutionMode::RoundingModeRTPINTEL:
2728 case SPIRV::ExecutionMode::RoundingModeRTNINTEL:
2729 case SPIRV::ExecutionMode::FloatingPointModeALTINTEL:
2730 case SPIRV::ExecutionMode::FloatingPointModeIEEEINTEL:
2731 if (HasIntelFloatControls2) {
2732 RequireIntelFloatControls2 =
true;
2734 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2737 case SPIRV::ExecutionMode::FPFastMathDefault: {
2738 if (HasKHRFloatControls2) {
2739 RequireKHRFloatControls2 =
true;
2741 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2745 case SPIRV::ExecutionMode::ContractionOff:
2746 case SPIRV::ExecutionMode::SignedZeroInfNanPreserve:
2747 if (HasKHRFloatControls2) {
2748 RequireKHRFloatControls2 =
true;
2750 SPIRV::OperandCategory::ExecutionModeOperand,
2751 SPIRV::ExecutionMode::FPFastMathDefault, ST);
2754 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2759 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2764 if (RequireFloatControls &&
2765 ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls))
2767 if (RequireIntelFloatControls2)
2769 if (RequireKHRFloatControls2)
2773 if (
F.isDeclaration())
2775 if (
F.getMetadata(
"reqd_work_group_size"))
2777 SPIRV::OperandCategory::ExecutionModeOperand,
2778 SPIRV::ExecutionMode::LocalSize, ST);
2779 if (
F.getFnAttribute(
"hlsl.numthreads").isValid()) {
2781 SPIRV::OperandCategory::ExecutionModeOperand,
2782 SPIRV::ExecutionMode::LocalSize, ST);
2784 if (
F.getFnAttribute(
"enable-maximal-reconvergence").getValueAsBool()) {
2787 if (
F.getMetadata(
"work_group_size_hint"))
2789 SPIRV::OperandCategory::ExecutionModeOperand,
2790 SPIRV::ExecutionMode::LocalSizeHint, ST);
2791 if (
F.getMetadata(
"intel_reqd_sub_group_size") ||
2792 F.getMetadata(
"reqd_sub_group_size"))
2794 SPIRV::OperandCategory::ExecutionModeOperand,
2795 SPIRV::ExecutionMode::SubgroupSize, ST);
2796 if (
F.getMetadata(
"max_work_group_size"))
2798 SPIRV::OperandCategory::ExecutionModeOperand,
2799 SPIRV::ExecutionMode::MaxWorkgroupSizeINTEL, ST);
2800 if (
F.getMetadata(
"vec_type_hint"))
2802 SPIRV::OperandCategory::ExecutionModeOperand,
2803 SPIRV::ExecutionMode::VecTypeHint, ST);
2805 if (
F.hasOptNone()) {
2806 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_optnone)) {
2809 }
else if (ST.canUseExtension(SPIRV::Extension::SPV_EXT_optnone)) {
2819 unsigned Flags = SPIRV::FPFastMathMode::None;
2820 bool CanUseKHRFloatControls2 =
2821 ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2);
2823 Flags |= SPIRV::FPFastMathMode::NotNaN;
2825 Flags |= SPIRV::FPFastMathMode::NotInf;
2827 Flags |= SPIRV::FPFastMathMode::NSZ;
2829 Flags |= SPIRV::FPFastMathMode::AllowRecip;
2831 Flags |= SPIRV::FPFastMathMode::AllowContract;
2833 if (CanUseKHRFloatControls2)
2841 Flags |= SPIRV::FPFastMathMode::NotNaN | SPIRV::FPFastMathMode::NotInf |
2842 SPIRV::FPFastMathMode::NSZ | SPIRV::FPFastMathMode::AllowRecip |
2843 SPIRV::FPFastMathMode::AllowTransform |
2844 SPIRV::FPFastMathMode::AllowReassoc |
2845 SPIRV::FPFastMathMode::AllowContract;
2847 Flags |= SPIRV::FPFastMathMode::Fast;
2850 if (CanUseKHRFloatControls2) {
2852 assert(!(Flags & SPIRV::FPFastMathMode::Fast) &&
2853 "SPIRV::FPFastMathMode::Fast is deprecated and should not be used "
2858 assert((!(Flags & SPIRV::FPFastMathMode::AllowTransform) ||
2859 ((Flags & SPIRV::FPFastMathMode::AllowReassoc &&
2860 Flags & SPIRV::FPFastMathMode::AllowContract))) &&
2861 "SPIRV::FPFastMathMode::AllowTransform requires AllowReassoc and "
2862 "AllowContract flags to be enabled as well.");
2873 return ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2);
2880 if (
TII.canUseIntegerWrapDecoration(
I)) {
2883 SPIRV::OperandCategory::DecorationOperand,
2884 SPIRV::Decoration::NoSignedWrap, ST, Reqs)
2887 SPIRV::Decoration::NoSignedWrap, {});
2890 SPIRV::OperandCategory::DecorationOperand,
2891 SPIRV::Decoration::NoUnsignedWrap, ST, Reqs)
2894 SPIRV::Decoration::NoUnsignedWrap, {});
2899 TII.canUseFastMathFlags(
2900 I, ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2)) ||
2901 (ST.isKernel() &&
I.getOpcode() == SPIRV::OpExtInst);
2906 if (FMFlags == SPIRV::FPFastMathMode::None) {
2909 if (FPFastMathDefaultInfoVec.
empty())
2925 assert(
I.getNumOperands() >= 3 &&
"Expected at least 3 operands");
2926 Register ResReg =
I.getOpcode() == SPIRV::OpExtInst
2927 ?
I.getOperand(1).getReg()
2928 :
I.getOperand(2).getReg();
2936 if (Ty == Elem.Ty) {
2937 FMFlags = Elem.FastMathFlags;
2938 Emit = Elem.ContractionOff || Elem.SignedZeroInfNanPreserve ||
2939 Elem.FPFastMathDefault;
2944 if (FMFlags == SPIRV::FPFastMathMode::None && !Emit)
2948 Register DstReg =
I.getOperand(0).getReg();
2965 for (
auto &
MBB : *MF)
2966 for (
auto &
MI :
MBB)
2984 for (
auto &
MBB : *MF) {
2985 if (!
MBB.hasName() ||
MBB.empty())
3004 for (
auto &
MBB : *MF) {
3006 MI.setDesc(
TII.get(SPIRV::OpPhi));
3009 MI.insert(
MI.operands_begin() + 1,
3010 {MachineOperand::CreateReg(ResTypeReg, false)});
3029 SPIRV::FPFastMathMode::None);
3031 SPIRV::FPFastMathMode::None);
3033 SPIRV::FPFastMathMode::None);
3040 size_t BitWidth = Ty->getScalarSizeInBits();
3044 assert(Index >= 0 && Index < 3 &&
3045 "Expected FPFastMathDefaultInfo for half, float, or double");
3046 assert(FPFastMathDefaultInfoVec.
size() == 3 &&
3047 "Expected FPFastMathDefaultInfoVec to have exactly 3 elements");
3048 return FPFastMathDefaultInfoVec[Index];
3054 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2))
3063 auto Node = M.getNamedMetadata(
"spirv.ExecutionMode");
3067 for (
unsigned i = 0; i <
Node->getNumOperands(); i++) {
3076 if (EM == SPIRV::ExecutionMode::FPFastMathDefault) {
3078 "Expected 4 operands for FPFastMathDefault");
3089 Info.FastMathFlags = Flags;
3090 Info.FPFastMathDefault =
true;
3091 }
else if (EM == SPIRV::ExecutionMode::ContractionOff) {
3093 "Expected no operands for ContractionOff");
3100 Info.ContractionOff =
true;
3102 }
else if (EM == SPIRV::ExecutionMode::SignedZeroInfNanPreserve) {
3104 "Expected 1 operand for SignedZeroInfNanPreserve");
3105 unsigned TargetWidth =
3114 assert(Index >= 0 && Index < 3 &&
3115 "Expected FPFastMathDefaultInfo for half, float, or double");
3116 assert(FPFastMathDefaultInfoVec.
size() == 3 &&
3117 "Expected FPFastMathDefaultInfoVec to have exactly 3 elements");
3118 FPFastMathDefaultInfoVec[Index].SignedZeroInfNanPreserve =
true;
3126 : ST(&ST), GR(ST.getSPIRVGlobalRegistry()), TII(ST.getInstrInfo()),
3127 MAI(MAI), GetMF(GetMF) {}
3142 collectDeclarations(M);
3145 numberRegistersGlobally(M);
3148 processOtherInstrs(M);
3152 MAI.Reqs.addCapability(SPIRV::Capability::Linkage);
3155 GR->setBound(MAI.MaxID);
3169 [&MMI](
const Function &
F) { return MMI.getMachineFunction(F); })
3185 MachineFunctionAnalysis::Result *MFA =
3186 FAM.getCachedResult<MachineFunctionAnalysis>(
3187 const_cast<Function &>(F));
3188 assert((MFA || F.isDeclaration()) &&
3189 "Missing MachineFunction for definition");
3190 return MFA ? &MFA->getMF() : nullptr;
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)
#define ATOM_FLT_REQ_EXT_MSG(ExtName)
static bool isFastMathModeAvailable(const SPIRVSubtarget &ST)
static void patchPhis(const Module &M, SPIRVGlobalRegistry *GR, const SPIRVInstrInfo &TII, MachineFunctionGetter GetMF)
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)
static void addDecorations(const Module &M, const SPIRVInstrInfo &TII, MachineFunctionGetter GetMF, const SPIRVSubtarget &ST, SPIRV::ModuleAnalysisInfo &MAI, const SPIRVGlobalRegistry *GR)
bool isInputAttachment(MachineInstr *ImageInst)
static bool isBFloat16Type(SPIRVTypeInst TypeDef)
bool isSampledImage(MachineInstr *ImageInst)
static void handleMIFlagDecoration(MachineInstr &I, const SPIRVSubtarget &ST, const SPIRVInstrInfo &TII, SPIRV::RequirementHandler &Reqs, const SPIRVGlobalRegistry *GR, SPIRV::FPFastMathDefaultInfoVector &FPFastMathDefaultInfoVec)
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 collectOtherInstr(MachineInstr &MI, SPIRV::ModuleAnalysisInfo &MAI, SPIRV::ModuleSectionType MSType, InstrTraces &IS, bool Append=true)
void addPrintfRequirements(const MachineInstr &MI, SPIRV::RequirementHandler &Reqs, const SPIRVSubtarget &ST)
static void addOpTypeImageReqs(const MachineInstr &MI, SPIRV::RequirementHandler &Reqs, const SPIRVSubtarget &ST)
static void addMBBNames(const Module &M, const SPIRVInstrInfo &TII, MachineFunctionGetter GetMF, const SPIRVSubtarget &ST, SPIRV::ModuleAnalysisInfo &MAI)
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 void collectFPFastMathDefaults(const Module &M, SPIRV::ModuleAnalysisInfo &MAI, const SPIRVSubtarget &ST)
static SPIRV::Requirements getSymbolicOperandRequirements(SPIRV::OperandCategory::OperandCategory Category, unsigned i, const SPIRVSubtarget &ST, SPIRV::RequirementHandler &Reqs)
static unsigned getMetadataUInt(MDNode *MdNode, unsigned OpIndex, unsigned DefaultVal=0)
void addOpAccessChainReqs(const MachineInstr &Instr, SPIRV::RequirementHandler &Handler, const SPIRVSubtarget &Subtarget)
static void appendDecorationsForReg(const MachineRegisterInfo &MRI, Register R, InstrSignature &Signature)
static SPIRV::FPFastMathDefaultInfoVector & getOrCreateFPFastMathDefaultInfoVec(const Module &M, SPIRV::ModuleAnalysisInfo &MAI, 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
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()
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.
Attribute getFnAttribute(Attribute::AttrKind Kind) const
Return the attribute for the given attribute kind.
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
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.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
const MachineFunctionProperties & getProperties() const
Get the function properties.
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.
LLVM_ABI LLVM_READONLY MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
LLVM_ABI void setRegClass(Register Reg, const TargetRegisterClass *RC)
setRegClass - Set the register class of the specified virtual register.
LLVM_ABI Register createGenericVirtualRegister(LLT Ty, StringRef Name="")
Create and return a new generic virtual register with low-level type Ty.
iterator_range< reg_instr_iterator > reg_instructions(Register Reg) const
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 ...
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
Register getSPIRVTypeID(SPIRVTypeInst SpirvType) 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)
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.
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)
InnerAnalysisManagerProxy< FunctionAnalysisManager, Module > FunctionAnalysisManagerModuleProxy
Provide the FunctionAnalysisManager to Module proxy.
static void reportUnsupported(MachineIRBuilder &MIRBuilder, const Twine &Msg)
void buildOpDecorate(Register Reg, MachineIRBuilder &MIRBuilder, SPIRV::Decoration::Decoration Dec, ArrayRef< uint32_t > DecArgs, StringRef StrImm)
bool isVectorType(SPIRVTypeInst SPVTy)
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
VersionTuple getSymbolicOperandMaxVersion(SPIRV::OperandCategory::OperandCategory Category, uint32_t Value)
function_ref< MachineFunction *(const Function &)> MachineFunctionGetter
void buildOpName(Register Target, StringRef Name, MachineIRBuilder &MIRBuilder)
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)
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
void setRegisterAlias(const MachineFunction *MF, Register Reg, MCRegister AliasReg)
DenseMap< const Function *, SPIRV::FPFastMathDefaultInfoVector > FPFastMathDefaultInfoMap
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