34#define DEBUG_TYPE "spirv-module-analysis"
38 cl::desc(
"Dump MIR with SPIR-V dependencies info"),
43 cl::desc(
"SPIR-V capabilities to avoid if there are "
44 "other options enabling a feature"),
47 "SPIR-V Shader capability")));
61 unsigned DefaultVal = 0) {
63 const auto &
Op = MdNode->getOperand(
OpIndex);
70getSymbolicOperandRequirements(SPIRV::OperandCategory::OperandCategory Category,
76 AvoidCaps.
S.
insert(SPIRV::Capability::Shader);
78 AvoidCaps.
S.
insert(SPIRV::Capability::Kernel);
83 bool MinVerOK = SPIRVVersion.
empty() || SPIRVVersion >= ReqMinVer;
85 ReqMaxVer.
empty() || SPIRVVersion.
empty() || SPIRVVersion <= ReqMaxVer;
88 if (ReqCaps.
empty()) {
89 if (ReqExts.
empty()) {
90 if (MinVerOK && MaxVerOK)
91 return {
true, {}, {}, ReqMinVer, ReqMaxVer};
94 }
else if (MinVerOK && MaxVerOK) {
95 if (ReqCaps.
size() == 1) {
96 auto Cap = ReqCaps[0];
99 SPIRV::OperandCategory::CapabilityOperand, Cap));
100 return {
true, {Cap}, std::move(ReqExts), ReqMinVer, ReqMaxVer};
110 for (
auto Cap : ReqCaps)
113 for (
size_t i = 0, Sz = UseCaps.
size(); i < Sz; ++i) {
114 auto Cap = UseCaps[i];
115 if (i == Sz - 1 || !AvoidCaps.
S.
contains(Cap)) {
117 SPIRV::OperandCategory::CapabilityOperand, Cap));
118 return {
true, {Cap}, std::move(ReqExts), ReqMinVer, ReqMaxVer};
126 if (
llvm::all_of(ReqExts, [&ST](
const SPIRV::Extension::Extension &Ext) {
127 return ST.canUseExtension(Ext);
138void SPIRVModuleAnalysis::setBaseInfo(
const Module &M) {
142 MAI.RegisterAliasTable.clear();
143 MAI.InstrsToDelete.clear();
144 MAI.GlobalObjMap.clear();
145 MAI.GlobalVarList.clear();
146 MAI.ExtInstSetMap.clear();
148 MAI.Reqs.initAvailableCapabilities(*ST);
151 if (
auto MemModel =
M.getNamedMetadata(
"spirv.MemoryModel")) {
152 auto MemMD = MemModel->getOperand(0);
153 MAI.Addr =
static_cast<SPIRV::AddressingModel::AddressingModel
>(
154 getMetadataUInt(MemMD, 0));
156 static_cast<SPIRV::MemoryModel::MemoryModel
>(getMetadataUInt(MemMD, 1));
159 MAI.Mem = ST->isShader() ? SPIRV::MemoryModel::GLSL450
160 : SPIRV::MemoryModel::OpenCL;
161 if (
MAI.Mem == SPIRV::MemoryModel::OpenCL) {
162 unsigned PtrSize = ST->getPointerSize();
163 MAI.Addr = PtrSize == 32 ? SPIRV::AddressingModel::Physical32
164 : PtrSize == 64 ? SPIRV::AddressingModel::Physical64
165 : SPIRV::AddressingModel::Logical;
168 MAI.Addr = SPIRV::AddressingModel::Logical;
173 if (
auto VerNode =
M.getNamedMetadata(
"opencl.ocl.version")) {
174 MAI.SrcLang = SPIRV::SourceLanguage::OpenCL_C;
177 assert(VerNode->getNumOperands() > 0 &&
"Invalid SPIR");
178 auto VersionMD = VerNode->getOperand(0);
179 unsigned MajorNum = getMetadataUInt(VersionMD, 0, 2);
180 unsigned MinorNum = getMetadataUInt(VersionMD, 1);
181 unsigned RevNum = getMetadataUInt(VersionMD, 2);
184 (std::max(1U, MajorNum) * 100 + MinorNum) * 1000 + RevNum;
187 if (
auto *CxxVerNode =
M.getNamedMetadata(
"opencl.cxx.version")) {
188 assert(CxxVerNode->getNumOperands() > 0 &&
"Invalid SPIR");
189 auto *CxxMD = CxxVerNode->getOperand(0);
191 (getMetadataUInt(CxxMD, 0) * 100 + getMetadataUInt(CxxMD, 1)) * 1000 +
192 getMetadataUInt(CxxMD, 2);
193 if ((
MAI.SrcLangVersion == 200000 && CxxVer == 100000) ||
194 (
MAI.SrcLangVersion == 300000 && CxxVer == 202100000)) {
195 MAI.SrcLang = SPIRV::SourceLanguage::CPP_for_OpenCL;
196 MAI.SrcLangVersion = CxxVer;
199 "opencl cxx version is not compatible with opencl c version!");
207 if (!ST->isShader()) {
208 MAI.SrcLang = SPIRV::SourceLanguage::OpenCL_CPP;
209 MAI.SrcLangVersion = 100000;
211 MAI.SrcLang = SPIRV::SourceLanguage::Unknown;
212 MAI.SrcLangVersion = 0;
216 if (
auto ExtNode =
M.getNamedMetadata(
"opencl.used.extensions")) {
217 for (
unsigned I = 0,
E = ExtNode->getNumOperands();
I !=
E; ++
I) {
218 MDNode *MD = ExtNode->getOperand(
I);
228 MAI.Reqs.getAndAddRequirements(SPIRV::OperandCategory::MemoryModelOperand,
230 MAI.Reqs.getAndAddRequirements(SPIRV::OperandCategory::SourceLanguageOperand,
232 MAI.Reqs.getAndAddRequirements(SPIRV::OperandCategory::AddressingModelOperand,
235 if (
MAI.Mem == SPIRV::MemoryModel::VulkanKHR)
236 MAI.Reqs.addExtension(SPIRV::Extension::SPV_KHR_vulkan_memory_model);
238 if (!ST->isShader()) {
240 MAI.ExtInstSetMap[
static_cast<unsigned>(
241 SPIRV::InstructionSet::OpenCL_std)] =
MAI.getNextIDRegister();
252 if (
UseMI.getOpcode() != SPIRV::OpDecorate &&
253 UseMI.getOpcode() != SPIRV::OpMemberDecorate)
256 for (
unsigned I = 0;
I <
UseMI.getNumOperands(); ++
I) {
274 for (
unsigned i = 0; i <
MI.getNumOperands(); ++i) {
283 unsigned Opcode =
MI.getOpcode();
284 if ((Opcode == SPIRV::OpDecorate) && i >= 2) {
285 unsigned DecorationID =
MI.getOperand(1).getImm();
286 if (DecorationID != SPIRV::Decoration::FuncParamAttr &&
287 DecorationID != SPIRV::Decoration::UserSemantic &&
288 DecorationID != SPIRV::Decoration::CacheControlLoadINTEL &&
289 DecorationID != SPIRV::Decoration::CacheControlStoreINTEL)
295 if (!UseDefReg && MO.
isDef()) {
303 dbgs() <<
"Unexpectedly, no global id found for the operand ";
305 dbgs() <<
"\nInstruction: ";
324 appendDecorationsForReg(
MI.getMF()->getRegInfo(), DefReg, Signature);
331 unsigned Opcode =
MI.getOpcode();
333 case SPIRV::OpTypeForwardPointer:
336 case SPIRV::OpVariable:
337 return static_cast<SPIRV::StorageClass::StorageClass
>(
338 MI.getOperand(2).
getImm()) != SPIRV::StorageClass::Function;
339 case SPIRV::OpFunction:
340 case SPIRV::OpFunctionParameter:
343 if (GR->hasConstFunPtr() && Opcode == SPIRV::OpUndef) {
351 if (GR->getFunctionDefinitionByUse(&
MI.getOperand(0))) {
353 unsigned UseOp =
UseMI.getOpcode();
354 if (UseOp == SPIRV::OpConstantFunctionPointerINTEL ||
355 UseOp == SPIRV::OpEnqueueKernel) {
356 MAI.setSkipEmission(&
MI);
362 if (
UseMI.getOpcode() != SPIRV::OpConstantFunctionPointerINTEL)
368 MAI.setSkipEmission(&
MI);
372 return TII->isTypeDeclInstr(
MI) || TII->isConstantInstr(
MI) ||
373 TII->isInlineAsmDefInstr(
MI);
382void SPIRVModuleAnalysis::visitFunPtrUse(
385 std::map<const Value *, unsigned> &GlobalToGReg,
387 const MachineOperand *OpFunDef = GR->getFunctionDefinitionByUse(FunPtrOp);
390 const MachineInstr *OpDefMI = OpFunDef->
getParent();
393 const MachineRegisterInfo &FunDefMRI = FunDefMF->
getRegInfo();
395 visitDecl(FunDefMRI, SignatureToGReg, GlobalToGReg, FunDefMF, *OpDefMI);
397 }
while (OpDefMI && (OpDefMI->
getOpcode() == SPIRV::OpFunction ||
398 OpDefMI->
getOpcode() == SPIRV::OpFunctionParameter));
400 MCRegister GlobalFunDefReg =
401 MAI.getRegisterAlias(FunDefMF, OpFunDef->
getReg());
403 "Function definition must refer to a global register");
404 MAI.setRegisterAlias(MF, OpReg, GlobalFunDefReg);
409void SPIRVModuleAnalysis::visitDecl(
411 std::map<const Value *, unsigned> &GlobalToGReg,
const MachineFunction *MF,
413 unsigned Opcode =
MI.getOpcode();
416 for (
const MachineOperand &MO :
MI.operands()) {
421 if (Opcode == SPIRV::OpConstantFunctionPointerINTEL &&
423 visitFunPtrUse(OpReg, &
MI.getOperand(2), SignatureToGReg, GlobalToGReg,
428 if (
MAI.hasRegisterAlias(MF, MO.
getReg()))
432 if (isDeclSection(MRI, *OpDefMI))
433 visitDecl(MRI, SignatureToGReg, GlobalToGReg, MF, *OpDefMI);
439 dbgs() <<
"Unexpectedly, no unique definition for the operand ";
441 dbgs() <<
"\nInstruction: ";
446 "No unique definition is found for the virtual register");
450 bool IsFunDef =
false;
451 if (TII->isSpecConstantInstr(
MI)) {
452 GReg =
MAI.getNextIDRegister();
454 }
else if (Opcode == SPIRV::OpFunction ||
455 Opcode == SPIRV::OpFunctionParameter) {
456 GReg = handleFunctionOrParameter(MF,
MI, GlobalToGReg, IsFunDef);
457 }
else if (Opcode == SPIRV::OpTypeStruct ||
458 Opcode == SPIRV::OpConstantComposite) {
459 GReg = handleTypeDeclOrConstant(
MI, SignatureToGReg);
460 const MachineInstr *NextInstr =
MI.getNextNode();
462 ((Opcode == SPIRV::OpTypeStruct &&
463 NextInstr->
getOpcode() == SPIRV::OpTypeStructContinuedINTEL) ||
464 (Opcode == SPIRV::OpConstantComposite &&
466 SPIRV::OpConstantCompositeContinuedINTEL))) {
467 MCRegister Tmp = handleTypeDeclOrConstant(*NextInstr, SignatureToGReg);
469 MAI.setSkipEmission(NextInstr);
472 }
else if (TII->isTypeDeclInstr(
MI) || TII->isConstantInstr(
MI) ||
473 TII->isInlineAsmDefInstr(
MI)) {
474 GReg = handleTypeDeclOrConstant(
MI, SignatureToGReg);
475 }
else if (Opcode == SPIRV::OpVariable) {
476 GReg = handleVariable(MF,
MI, GlobalToGReg);
479 dbgs() <<
"\nInstruction: ";
485 MAI.setRegisterAlias(MF,
MI.getOperand(0).getReg(), GReg);
487 MAI.setSkipEmission(&
MI);
490MCRegister SPIRVModuleAnalysis::handleFunctionOrParameter(
492 std::map<const Value *, unsigned> &GlobalToGReg,
bool &IsFunDef) {
493 const Value *GObj = GR->getGlobalObject(MF,
MI.getOperand(0).getReg());
494 assert(GObj &&
"Unregistered global definition");
498 assert(
F &&
"Expected a reference to a function or an argument");
499 IsFunDef = !
F->isDeclaration();
500 auto [It,
Inserted] = GlobalToGReg.try_emplace(GObj);
503 MCRegister GReg =
MAI.getNextIDRegister();
511SPIRVModuleAnalysis::handleTypeDeclOrConstant(
const MachineInstr &
MI,
514 auto [It,
Inserted] = SignatureToGReg.try_emplace(MISign);
517 MCRegister GReg =
MAI.getNextIDRegister();
523MCRegister SPIRVModuleAnalysis::handleVariable(
525 std::map<const Value *, unsigned> &GlobalToGReg) {
526 MAI.GlobalVarList.push_back(&
MI);
527 const Value *GObj = GR->getGlobalObject(MF,
MI.getOperand(0).getReg());
528 assert(GObj &&
"Unregistered global definition");
529 auto [It,
Inserted] = GlobalToGReg.try_emplace(GObj);
532 MCRegister GReg =
MAI.getNextIDRegister();
536 MAI.GlobalObjMap[GV] = GReg;
540void SPIRVModuleAnalysis::collectDeclarations(
const Module &M) {
542 std::map<const Value *, unsigned> GlobalToGReg;
543 for (
const Function &
F : M) {
544 MachineFunction *MF = MMI->getMachineFunction(
F);
547 const MachineRegisterInfo &MRI = MF->
getRegInfo();
548 unsigned PastHeader = 0;
549 for (MachineBasicBlock &
MBB : *MF) {
550 for (MachineInstr &
MI :
MBB) {
551 if (
MI.getNumOperands() == 0)
553 unsigned Opcode =
MI.getOpcode();
554 if (Opcode == SPIRV::OpFunction) {
555 if (PastHeader == 0) {
559 }
else if (Opcode == SPIRV::OpFunctionParameter) {
562 }
else if (PastHeader > 0) {
566 const MachineOperand &DefMO =
MI.getOperand(0);
568 case SPIRV::OpExtension:
569 MAI.Reqs.addExtension(SPIRV::Extension::Extension(DefMO.
getImm()));
570 MAI.setSkipEmission(&
MI);
572 case SPIRV::OpCapability:
573 MAI.Reqs.addCapability(SPIRV::Capability::Capability(DefMO.
getImm()));
574 MAI.setSkipEmission(&
MI);
579 if (DefMO.
isReg() && isDeclSection(MRI,
MI) &&
580 !
MAI.hasRegisterAlias(MF, DefMO.
getReg()))
581 visitDecl(MRI, SignatureToGReg, GlobalToGReg, MF,
MI);
585 if (Opcode == SPIRV::OpEnqueueKernel &&
MI.getNumOperands() > 8) {
586 const MachineOperand &InvokeMO =
MI.getOperand(8);
587 if (InvokeMO.
isReg()) {
589 if (!
MAI.hasRegisterAlias(MF, InvokeReg)) {
590 if (
const MachineInstr *
DefMI =
594 if (GR->getFunctionDefinitionByUse(FunPtrOp))
595 visitFunPtrUse(InvokeReg, FunPtrOp, SignatureToGReg,
614 if (
MI.getOpcode() == SPIRV::OpDecorate) {
616 auto Dec =
MI.getOperand(1).getImm();
617 if (Dec == SPIRV::Decoration::LinkageAttributes) {
618 auto Lnk =
MI.getOperand(
MI.getNumOperands() - 1).getImm();
619 if (Lnk == SPIRV::LinkageType::Import) {
624 MAI.GlobalObjMap[ImportedFunc] =
625 MAI.getRegisterAlias(
MI.getMF(), Target);
628 }
else if (
MI.getOpcode() == SPIRV::OpFunction) {
631 MCRegister GlobalReg =
MAI.getRegisterAlias(
MI.getMF(),
Reg);
633 MAI.GlobalObjMap[
F] = GlobalReg;
645 auto FoundMI = IS.insert(std::move(MISign));
646 if (!FoundMI.second) {
647 if (
MI.getOpcode() == SPIRV::OpDecorate) {
649 "Decoration instructions must have at least 2 operands");
651 "Only OpDecorate instructions can be duplicates");
656 if (
MI.getOperand(1).getImm() != SPIRV::Decoration::FPFastMathMode)
661 if (instrToSignature(*OrigMI, MAI,
true) == MISign) {
662 assert(OrigMI->getNumOperands() ==
MI.getNumOperands() &&
663 "Original instruction must have the same number of operands");
665 OrigMI->getNumOperands() == 3 &&
666 "FPFastMathMode decoration must have 3 operands for OpDecorate");
667 unsigned OrigFlags = OrigMI->getOperand(2).getImm();
668 unsigned NewFlags =
MI.getOperand(2).getImm();
669 if (OrigFlags == NewFlags)
673 unsigned FinalFlags = OrigFlags | NewFlags;
675 <<
"Warning: Conflicting FPFastMathMode decoration flags "
677 << *OrigMI <<
"Original flags: " << OrigFlags
678 <<
", new flags: " << NewFlags
679 <<
". They will be merged on a best effort basis, but not "
680 "validated. Final flags: "
681 << FinalFlags <<
"\n";
688 assert(
false &&
"No original instruction found for the duplicate "
689 "OpDecorate, but we found one in IS.");
702void SPIRVModuleAnalysis::processOtherInstrs(
const Module &M) {
704 for (
const Function &
F : M) {
705 if (
F.isDeclaration())
707 MachineFunction *MF = MMI->getMachineFunction(
F);
710 for (MachineBasicBlock &
MBB : *MF)
711 for (MachineInstr &
MI :
MBB) {
712 if (
MAI.getSkipEmission(&
MI))
714 const unsigned OpCode =
MI.getOpcode();
715 if (OpCode == SPIRV::OpString) {
717 }
else if (OpCode == SPIRV::OpExtInst &&
MI.getOperand(2).isImm() &&
718 MI.getOperand(2).getImm() ==
719 SPIRV::InstructionSet::
720 NonSemantic_Shader_DebugInfo_100) {
727 MachineOperand Ins =
MI.getOperand(3);
728 namespace NS = SPIRV::NonSemanticExtInst;
729 static constexpr int64_t GlobalNonSemanticDITy[] = {
730 NS::DebugSource, NS::DebugCompilationUnit, NS::DebugInfoNone,
731 NS::DebugTypeBasic, NS::DebugTypePointer};
732 bool IsGlobalDI =
false;
733 for (
unsigned Idx = 0; Idx < std::size(GlobalNonSemanticDITy); ++Idx)
734 IsGlobalDI |= Ins.
getImm() == GlobalNonSemanticDITy[Idx];
737 }
else if (OpCode == SPIRV::OpName || OpCode == SPIRV::OpMemberName) {
739 }
else if (OpCode == SPIRV::OpEntryPoint) {
741 }
else if (TII->isAliasingInstr(
MI)) {
743 }
else if (TII->isDecorationInstr(
MI)) {
745 collectFuncNames(
MI, &
F);
746 }
else if (TII->isConstantInstr(
MI)) {
750 }
else if (OpCode == SPIRV::OpFunction) {
751 collectFuncNames(
MI, &
F);
752 }
else if (OpCode == SPIRV::OpTypeForwardPointer) {
760 auto AliasingTier = [](
const MachineInstr *
MI) {
761 switch (
MI->getOpcode()) {
762 case SPIRV::OpAliasDomainDeclINTEL:
764 case SPIRV::OpAliasScopeDeclINTEL:
766 case SPIRV::OpAliasScopeListDeclINTEL:
773 [&](
const MachineInstr *
LHS,
const MachineInstr *
RHS) {
774 return AliasingTier(LHS) < AliasingTier(RHS);
781void SPIRVModuleAnalysis::numberRegistersGlobally(
const Module &M) {
782 for (
const Function &
F : M) {
783 if (
F.isDeclaration())
785 MachineFunction *MF = MMI->getMachineFunction(
F);
787 for (MachineBasicBlock &
MBB : *MF) {
788 for (MachineInstr &
MI :
MBB) {
789 for (MachineOperand &
Op :
MI.operands()) {
793 if (
MAI.hasRegisterAlias(MF,
Reg))
795 MCRegister NewReg =
MAI.getNextIDRegister();
796 MAI.setRegisterAlias(MF,
Reg, NewReg);
798 if (
MI.getOpcode() != SPIRV::OpExtInst)
800 auto Set =
MI.getOperand(2).getImm();
801 auto [It,
Inserted] =
MAI.ExtInstSetMap.try_emplace(Set);
803 It->second =
MAI.getNextIDRegister();
811 SPIRV::OperandCategory::OperandCategory Category, uint32_t i,
813 addRequirements(getSymbolicOperandRequirements(Category, i, ST, *
this));
816void SPIRV::RequirementHandler::recursiveAddCapabilities(
818 for (
const auto &Cap : ToPrune) {
822 recursiveAddCapabilities(ImplicitDecls);
827 for (
const auto &Cap : ToAdd) {
828 bool IsNewlyInserted = AllCaps.insert(Cap).second;
829 if (!IsNewlyInserted)
833 recursiveAddCapabilities(ImplicitDecls);
834 MinimalCaps.push_back(Cap);
839 const SPIRV::Requirements &Req) {
843 if (Req.
Cap.has_value())
844 addCapabilities({Req.
Cap.value()});
846 addExtensions(Req.
Exts);
849 if (!MaxVersion.empty() && Req.
MinVer > MaxVersion) {
851 <<
" and <= " << MaxVersion <<
"\n");
855 if (MinVersion.empty() || Req.
MinVer > MinVersion)
860 if (!MinVersion.empty() && Req.
MaxVer < MinVersion) {
862 <<
" and >= " << MinVersion <<
"\n");
866 if (MaxVersion.empty() || Req.
MaxVer < MaxVersion)
872 const SPIRVSubtarget &ST)
const {
874 bool IsSatisfiable =
true;
875 auto TargetVer =
ST.getSPIRVVersion();
877 if (!MaxVersion.empty() && !TargetVer.empty() && MaxVersion < TargetVer) {
879 dbgs() <<
"Target SPIR-V version too high for required features\n"
880 <<
"Required max version: " << MaxVersion <<
" target version "
881 << TargetVer <<
"\n");
882 IsSatisfiable =
false;
885 if (!MinVersion.empty() && !TargetVer.empty() && MinVersion > TargetVer) {
886 LLVM_DEBUG(
dbgs() <<
"Target SPIR-V version too low for required features\n"
887 <<
"Required min version: " << MinVersion
888 <<
" target version " << TargetVer <<
"\n");
889 IsSatisfiable =
false;
892 if (!MinVersion.empty() && !MaxVersion.empty() && MinVersion > MaxVersion) {
895 <<
"Version is too low for some features and too high for others.\n"
896 <<
"Required SPIR-V min version: " << MinVersion
897 <<
" required SPIR-V max version " << MaxVersion <<
"\n");
898 IsSatisfiable =
false;
901 AvoidCapabilitiesSet AvoidCaps;
903 AvoidCaps.
S.
insert(SPIRV::Capability::Shader);
905 AvoidCaps.
S.
insert(SPIRV::Capability::Kernel);
907 for (
auto Cap : MinimalCaps) {
908 if (AvailableCaps.contains(Cap) && !AvoidCaps.
S.
contains(Cap))
912 OperandCategory::CapabilityOperand, Cap)
914 IsSatisfiable =
false;
917 for (
auto Ext : AllExtensions) {
918 if (
ST.canUseExtension(Ext))
922 OperandCategory::ExtensionOperand, Ext)
924 IsSatisfiable =
false;
933 for (
const auto Cap : ToAdd)
934 if (AvailableCaps.insert(Cap).second)
936 SPIRV::OperandCategory::CapabilityOperand, Cap));
940 const Capability::Capability
ToRemove,
941 const Capability::Capability IfPresent) {
942 if (AllCaps.contains(IfPresent)) {
952 addAvailableCaps({Capability::Shader, Capability::Linkage, Capability::Int8,
955 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 3)))
957 Capability::GroupNonUniformVote,
958 Capability::GroupNonUniformArithmetic,
959 Capability::GroupNonUniformBallot,
960 Capability::GroupNonUniformClustered,
961 Capability::GroupNonUniformShuffle,
962 Capability::GroupNonUniformShuffleRelative,
963 Capability::GroupNonUniformQuad});
965 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 6)))
967 Capability::DotProductInput4x8Bit,
968 Capability::DotProductInput4x8BitPacked,
969 Capability::DemoteToHelperInvocation});
972 for (
auto Extension :
ST.getAllAvailableExtensions()) {
978 if (!
ST.isShader()) {
979 initAvailableCapabilitiesForOpenCL(ST);
984 initAvailableCapabilitiesForVulkan(ST);
991void RequirementHandler::initAvailableCapabilitiesForOpenCL(
992 const SPIRVSubtarget &ST) {
995 Capability::Kernel, Capability::Vector16,
996 Capability::Groups, Capability::GenericPointer,
997 Capability::StorageImageWriteWithoutFormat,
998 Capability::StorageImageReadWithoutFormat});
999 if (
ST.hasOpenCLFullProfile())
1001 if (
ST.hasOpenCLImageSupport()) {
1003 Capability::Image1D, Capability::SampledBuffer,
1004 Capability::ImageBuffer});
1005 if (
ST.isAtLeastOpenCLVer(VersionTuple(2, 0)))
1008 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 1)) &&
1009 ST.isAtLeastOpenCLVer(VersionTuple(2, 2)))
1011 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 4)))
1012 addAvailableCaps({Capability::DenormPreserve, Capability::DenormFlushToZero,
1013 Capability::SignedZeroInfNanPreserve,
1014 Capability::RoundingModeRTE,
1015 Capability::RoundingModeRTZ});
1022void RequirementHandler::initAvailableCapabilitiesForVulkan(
1023 const SPIRVSubtarget &ST) {
1027 Capability::Float16,
1028 Capability::Float64,
1029 Capability::GroupNonUniform,
1030 Capability::Image1D,
1031 Capability::SampledBuffer,
1032 Capability::ImageBuffer,
1033 Capability::UniformBufferArrayDynamicIndexing,
1034 Capability::SampledImageArrayDynamicIndexing,
1035 Capability::StorageBufferArrayDynamicIndexing,
1036 Capability::StorageImageArrayDynamicIndexing,
1037 Capability::DerivativeControl,
1039 Capability::ImageQuery,
1040 Capability::ImageGatherExtended,
1041 Capability::Addresses,
1042 Capability::VulkanMemoryModelKHR,
1043 Capability::StorageImageExtendedFormats,
1044 Capability::StorageImageMultisample,
1045 Capability::ImageMSArray});
1048 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 5))) {
1050 {Capability::Int64Atomics, Capability::ShaderNonUniformEXT,
1051 Capability::RuntimeDescriptorArrayEXT,
1052 Capability::InputAttachmentArrayDynamicIndexingEXT,
1053 Capability::UniformTexelBufferArrayDynamicIndexingEXT,
1054 Capability::StorageTexelBufferArrayDynamicIndexingEXT,
1055 Capability::UniformBufferArrayNonUniformIndexingEXT,
1056 Capability::SampledImageArrayNonUniformIndexingEXT,
1057 Capability::StorageBufferArrayNonUniformIndexingEXT,
1058 Capability::StorageImageArrayNonUniformIndexingEXT,
1059 Capability::InputAttachmentArrayNonUniformIndexingEXT,
1060 Capability::UniformTexelBufferArrayNonUniformIndexingEXT,
1061 Capability::StorageTexelBufferArrayNonUniformIndexingEXT});
1065 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 6)))
1067 Capability::StorageImageReadWithoutFormat});
1075static void addOpDecorateReqs(
const MachineInstr &
MI,
unsigned DecIndex,
1078 int64_t DecOp =
MI.getOperand(DecIndex).getImm();
1079 auto Dec =
static_cast<SPIRV::Decoration::Decoration
>(DecOp);
1081 SPIRV::OperandCategory::DecorationOperand, Dec, ST, Reqs));
1083 if (Dec == SPIRV::Decoration::BuiltIn) {
1084 int64_t BuiltInOp =
MI.getOperand(DecIndex + 1).getImm();
1085 auto BuiltIn =
static_cast<SPIRV::BuiltIn::BuiltIn
>(BuiltInOp);
1087 SPIRV::OperandCategory::BuiltInOperand, BuiltIn, ST, Reqs));
1088 }
else if (Dec == SPIRV::Decoration::LinkageAttributes) {
1089 int64_t LinkageOp =
MI.getOperand(
MI.getNumOperands() - 1).getImm();
1090 SPIRV::LinkageType::LinkageType LnkType =
1091 static_cast<SPIRV::LinkageType::LinkageType
>(LinkageOp);
1092 if (LnkType == SPIRV::LinkageType::LinkOnceODR)
1093 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_linkonce_odr);
1094 else if (LnkType == SPIRV::LinkageType::WeakAMD) {
1095 Reqs.
addExtension(SPIRV::Extension::SPV_AMD_weak_linkage);
1098 }
else if (Dec == SPIRV::Decoration::CacheControlLoadINTEL ||
1099 Dec == SPIRV::Decoration::CacheControlStoreINTEL) {
1100 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_cache_controls);
1101 }
else if (Dec == SPIRV::Decoration::HostAccessINTEL) {
1102 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_global_variable_host_access);
1103 }
else if (Dec == SPIRV::Decoration::InitModeINTEL ||
1104 Dec == SPIRV::Decoration::ImplementInRegisterMapINTEL) {
1106 SPIRV::Extension::SPV_INTEL_global_variable_fpga_decorations);
1107 }
else if (Dec == SPIRV::Decoration::NonUniformEXT) {
1109 }
else if (Dec == SPIRV::Decoration::FPMaxErrorDecorationINTEL) {
1111 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_fp_max_error);
1112 }
else if (Dec == SPIRV::Decoration::FPFastMathMode) {
1113 if (
ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2)) {
1115 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_float_controls2);
1124 assert(
MI.getNumOperands() >= 8 &&
"Insufficient operands for OpTypeImage");
1127 int64_t ImgFormatOp =
MI.getOperand(7).getImm();
1128 auto ImgFormat =
static_cast<SPIRV::ImageFormat::ImageFormat
>(ImgFormatOp);
1132 bool IsArrayed =
MI.getOperand(4).getImm() == 1;
1133 bool IsMultisampled =
MI.getOperand(5).getImm() == 1;
1134 bool NoSampler =
MI.getOperand(6).getImm() == 2;
1137 switch (
MI.getOperand(2).getImm()) {
1138 case SPIRV::Dim::DIM_1D:
1140 : SPIRV::Capability::Sampled1D);
1142 case SPIRV::Dim::DIM_2D:
1143 if (IsMultisampled && NoSampler)
1145 if (IsMultisampled && IsArrayed)
1148 case SPIRV::Dim::DIM_3D:
1150 case SPIRV::Dim::DIM_Cube:
1154 : SPIRV::Capability::SampledCubeArray);
1156 case SPIRV::Dim::DIM_Rect:
1158 : SPIRV::Capability::SampledRect);
1160 case SPIRV::Dim::DIM_Buffer:
1162 : SPIRV::Capability::SampledBuffer);
1164 case SPIRV::Dim::DIM_SubpassData:
1176 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_shader_image_int64);
1180 if (!
ST.isShader()) {
1181 if (
MI.getNumOperands() > 8 &&
1182 MI.getOperand(8).getImm() == SPIRV::AccessQualifier::ReadWrite)
1191 TypeDef->
getOpcode() == SPIRV::OpTypeFloat &&
1197#define ATOM_FLT_REQ_EXT_MSG(ExtName) \
1198 "The atomic float instruction requires the following SPIR-V " \
1199 "extension: SPV_EXT_shader_atomic_float" ExtName
1200static void AddAtomicVectorFloatRequirements(
const MachineInstr &
MI,
1204 MI.getMF()->getRegInfo().getVRegDef(
MI.getOperand(1).getReg());
1207 if (Rank != 2 && Rank != 4)
1209 "must be a 2-component or 4 component vector");
1214 if (EltTypeDef->
getOpcode() != SPIRV::OpTypeFloat ||
1217 "The element type for the result type of an atomic vector float "
1218 "instruction must be a 16-bit floating-point scalar");
1222 if (isBFloat16Type(EltTypeDef) &&
1225 "The element type for the result type of an atomic vector float "
1226 "instruction cannot be a bfloat16 scalar");
1227 if (!
ST.canUseExtension(SPIRV::Extension::SPV_NV_shader_atomic_fp16_vector))
1229 "The atomic float16 vector instruction requires the following SPIR-V "
1230 "extension: SPV_NV_shader_atomic_fp16_vector");
1232 Reqs.
addExtension(SPIRV::Extension::SPV_NV_shader_atomic_fp16_vector);
1233 Reqs.
addCapability(SPIRV::Capability::AtomicFloat16VectorNV);
1240 "Expect register operand in atomic float instruction");
1241 Register TypeReg =
MI.getOperand(1).getReg();
1244 if (TypeDef->
getOpcode() == SPIRV::OpTypeVector)
1245 return AddAtomicVectorFloatRequirements(
MI, Reqs, ST);
1247 if (TypeDef->
getOpcode() != SPIRV::OpTypeFloat)
1249 "floating-point type scalar");
1252 unsigned Op =
MI.getOpcode();
1253 if (
Op == SPIRV::OpAtomicFAddEXT) {
1254 if (!
ST.canUseExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float_add))
1256 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float_add);
1259 if (isBFloat16Type(TypeDef)) {
1260 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics))
1262 "The atomic bfloat16 instruction requires the following SPIR-V "
1263 "extension: SPV_INTEL_16bit_atomics",
1265 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics);
1266 Reqs.
addCapability(SPIRV::Capability::AtomicBFloat16AddINTEL);
1268 if (!
ST.canUseExtension(
1269 SPIRV::Extension::SPV_EXT_shader_atomic_float16_add))
1271 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float16_add);
1283 "Unexpected floating-point type width in atomic float instruction");
1286 if (!
ST.canUseExtension(
1287 SPIRV::Extension::SPV_EXT_shader_atomic_float_min_max))
1289 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float_min_max);
1292 if (isBFloat16Type(TypeDef)) {
1293 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics))
1295 "The atomic bfloat16 instruction requires the following SPIR-V "
1296 "extension: SPV_INTEL_16bit_atomics",
1298 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics);
1299 Reqs.
addCapability(SPIRV::Capability::AtomicBFloat16MinMaxINTEL);
1301 Reqs.
addCapability(SPIRV::Capability::AtomicFloat16MinMaxEXT);
1305 Reqs.
addCapability(SPIRV::Capability::AtomicFloat32MinMaxEXT);
1308 Reqs.
addCapability(SPIRV::Capability::AtomicFloat64MinMaxEXT);
1312 "Unexpected floating-point type width in atomic float instruction");
1318 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1322 return Dim == SPIRV::Dim::DIM_Buffer && Sampled == 1;
1326 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1330 return Dim == SPIRV::Dim::DIM_Buffer && Sampled == 2;
1334 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1338 return Dim != SPIRV::Dim::DIM_Buffer && Sampled == 1;
1342 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1346 return Dim == SPIRV::Dim::DIM_SubpassData && Sampled == 2;
1350 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1354 return Dim != SPIRV::Dim::DIM_Buffer && Sampled == 2;
1357bool isCombinedImageSampler(
MachineInstr *SampledImageInst) {
1358 if (SampledImageInst->
getOpcode() != SPIRV::OpTypeSampledImage)
1364 return isSampledImage(ImageInst);
1369 if (
MI.getOpcode() != SPIRV::OpDecorate)
1373 if (Dec == SPIRV::Decoration::NonUniformEXT)
1391 if (
StorageClass != SPIRV::StorageClass::StorageClass::UniformConstant &&
1392 StorageClass != SPIRV::StorageClass::StorageClass::Uniform &&
1393 StorageClass != SPIRV::StorageClass::StorageClass::StorageBuffer) {
1398 hasNonUniformDecoration(
Instr.getOperand(0).getReg(), MRI);
1400 auto FirstIndexReg =
Instr.getOperand(3).getReg();
1401 bool FirstIndexIsConstant =
1404 if (
StorageClass == SPIRV::StorageClass::StorageClass::StorageBuffer) {
1407 SPIRV::Capability::StorageBufferArrayNonUniformIndexingEXT);
1408 else if (!FirstIndexIsConstant)
1410 SPIRV::Capability::StorageBufferArrayDynamicIndexing);
1416 if (PointeeType->
getOpcode() != SPIRV::OpTypeImage &&
1417 PointeeType->
getOpcode() != SPIRV::OpTypeSampledImage &&
1418 PointeeType->
getOpcode() != SPIRV::OpTypeSampler) {
1422 if (isUniformTexelBuffer(PointeeType)) {
1425 SPIRV::Capability::UniformTexelBufferArrayNonUniformIndexingEXT);
1426 else if (!FirstIndexIsConstant)
1428 SPIRV::Capability::UniformTexelBufferArrayDynamicIndexingEXT);
1429 }
else if (isInputAttachment(PointeeType)) {
1432 SPIRV::Capability::InputAttachmentArrayNonUniformIndexingEXT);
1433 else if (!FirstIndexIsConstant)
1435 SPIRV::Capability::InputAttachmentArrayDynamicIndexingEXT);
1436 }
else if (isStorageTexelBuffer(PointeeType)) {
1439 SPIRV::Capability::StorageTexelBufferArrayNonUniformIndexingEXT);
1440 else if (!FirstIndexIsConstant)
1442 SPIRV::Capability::StorageTexelBufferArrayDynamicIndexingEXT);
1443 }
else if (isSampledImage(PointeeType) ||
1444 isCombinedImageSampler(PointeeType) ||
1445 PointeeType->
getOpcode() == SPIRV::OpTypeSampler) {
1448 SPIRV::Capability::SampledImageArrayNonUniformIndexingEXT);
1449 else if (!FirstIndexIsConstant)
1451 SPIRV::Capability::SampledImageArrayDynamicIndexing);
1452 }
else if (isStorageImage(PointeeType)) {
1455 SPIRV::Capability::StorageImageArrayNonUniformIndexingEXT);
1456 else if (!FirstIndexIsConstant)
1458 SPIRV::Capability::StorageImageArrayDynamicIndexing);
1462static bool isImageTypeWithUnknownFormat(
SPIRVTypeInst TypeInst) {
1463 if (TypeInst->
getOpcode() != SPIRV::OpTypeImage)
1472 if (
ST.canUseExtension(SPIRV::Extension::SPV_KHR_integer_dot_product))
1473 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_integer_dot_product);
1477 assert(
MI.getOperand(2).isReg() &&
"Unexpected operand in dot");
1481 assert(
Input->getOperand(1).isReg() &&
"Unexpected operand in dot input");
1485 if (TypeDef->
getOpcode() == SPIRV::OpTypeInt) {
1487 Reqs.
addCapability(SPIRV::Capability::DotProductInput4x8BitPacked);
1488 }
else if (TypeDef->
getOpcode() == SPIRV::OpTypeVector) {
1494 "Dot operand of 8-bit integer type requires 4 components");
1495 Reqs.
addCapability(SPIRV::Capability::DotProductInput4x8Bit);
1511 unsigned AddrSpace = ASOp.
getImm();
1512 if (AddrSpace != SPIRV::StorageClass::UniformConstant) {
1513 if (!
ST.canUseExtension(
1515 SPV_EXT_relaxed_printf_string_address_space)) {
1517 "required because printf uses a format string not "
1518 "in constant address space.",
1522 SPIRV::Extension::SPV_EXT_relaxed_printf_string_address_space);
1531 if (
MI.getNumOperands() <=
OpIdx)
1535 if (Mask & (1U <<
I))
1544 unsigned Op =
MI.getOpcode();
1546 case SPIRV::OpMemoryModel: {
1547 int64_t Addr =
MI.getOperand(0).getImm();
1550 int64_t Mem =
MI.getOperand(1).getImm();
1555 case SPIRV::OpEntryPoint: {
1556 int64_t
Exe =
MI.getOperand(0).getImm();
1561 case SPIRV::OpExecutionMode:
1562 case SPIRV::OpExecutionModeId: {
1563 int64_t
Exe =
MI.getOperand(1).getImm();
1568 case SPIRV::OpTypeMatrix:
1571 case SPIRV::OpTypeInt: {
1572 unsigned BitWidth =
MI.getOperand(1).getImm();
1580 ST.canUseExtension(SPIRV::Extension::SPV_INTEL_int4)) {
1584 if (!
ST.canUseExtension(
1585 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_integers))
1587 "OpTypeInt type with a width other than 8, 16, 32 or 64 bits "
1588 "requires the following SPIR-V extension: "
1589 "SPV_ALTERA_arbitrary_precision_integers");
1591 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_integers);
1592 Reqs.
addCapability(SPIRV::Capability::ArbitraryPrecisionIntegersALTERA);
1596 case SPIRV::OpDot: {
1599 if (isBFloat16Type(TypeDef))
1600 Reqs.
addCapability(SPIRV::Capability::BFloat16DotProductKHR);
1603 case SPIRV::OpTypeFloat: {
1604 unsigned BitWidth =
MI.getOperand(1).getImm();
1608 if (isBFloat16Type(&
MI)) {
1609 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_bfloat16))
1611 "following SPIR-V extension: SPV_KHR_bfloat16",
1621 case SPIRV::OpTypeVector: {
1622 unsigned NumComponents =
MI.getOperand(2).getImm();
1623 if (NumComponents == 8 || NumComponents == 16)
1629 if (ElemTypeDef->
getOpcode() == SPIRV::OpTypePointer &&
1630 ST.canUseExtension(SPIRV::Extension::SPV_INTEL_masked_gather_scatter)) {
1631 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_masked_gather_scatter);
1632 Reqs.
addCapability(SPIRV::Capability::MaskedGatherScatterINTEL);
1636 case SPIRV::OpTypePointer: {
1637 auto SC =
MI.getOperand(1).getImm();
1648 (TypeDef->
getOpcode() == SPIRV::OpTypeFloat) &&
1653 case SPIRV::OpExtInst: {
1654 if (
MI.getOperand(2).getImm() ==
1655 static_cast<int64_t
>(
1656 SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100)) {
1657 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_non_semantic_info);
1660 if (
MI.getOperand(3).getImm() ==
1661 static_cast<int64_t
>(SPIRV::OpenCLExtInst::printf)) {
1662 addPrintfRequirements(
MI, Reqs, ST);
1669 case SPIRV::OpAliasDomainDeclINTEL:
1670 case SPIRV::OpAliasScopeDeclINTEL:
1671 case SPIRV::OpAliasScopeListDeclINTEL: {
1672 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_memory_access_aliasing);
1673 Reqs.
addCapability(SPIRV::Capability::MemoryAccessAliasingINTEL);
1676 case SPIRV::OpBitReverse:
1677 case SPIRV::OpBitFieldInsert:
1678 case SPIRV::OpBitFieldSExtract:
1679 case SPIRV::OpBitFieldUExtract:
1680 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_bit_instructions)) {
1684 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_bit_instructions);
1687 case SPIRV::OpTypeRuntimeArray:
1690 case SPIRV::OpTypeOpaque:
1691 case SPIRV::OpTypeEvent:
1694 case SPIRV::OpTypePipe:
1695 case SPIRV::OpTypeReserveId:
1698 case SPIRV::OpTypeDeviceEvent:
1699 case SPIRV::OpTypeQueue:
1700 case SPIRV::OpBuildNDRange:
1701 case SPIRV::OpEnqueueKernel:
1704 case SPIRV::OpDecorate:
1705 case SPIRV::OpDecorateId:
1706 case SPIRV::OpDecorateString:
1707 addOpDecorateReqs(
MI, 1, Reqs, ST);
1709 case SPIRV::OpMemberDecorate:
1710 case SPIRV::OpMemberDecorateString:
1711 addOpDecorateReqs(
MI, 2, Reqs, ST);
1713 case SPIRV::OpInBoundsPtrAccessChain:
1716 case SPIRV::OpConstantSampler:
1719 case SPIRV::OpInBoundsAccessChain:
1720 case SPIRV::OpAccessChain:
1721 addOpAccessChainReqs(
MI, Reqs, ST);
1723 case SPIRV::OpTypeImage:
1724 addOpTypeImageReqs(
MI, Reqs, ST);
1726 case SPIRV::OpTypeSampler:
1727 if (!
ST.isShader()) {
1731 case SPIRV::OpTypeForwardPointer:
1735 case SPIRV::OpAtomicFlagTestAndSet:
1736 case SPIRV::OpAtomicLoad:
1737 case SPIRV::OpAtomicStore:
1738 case SPIRV::OpAtomicExchange:
1739 case SPIRV::OpAtomicCompareExchange:
1740 case SPIRV::OpAtomicIIncrement:
1741 case SPIRV::OpAtomicIDecrement:
1742 case SPIRV::OpAtomicIAdd:
1743 case SPIRV::OpAtomicISub:
1744 case SPIRV::OpAtomicUMin:
1745 case SPIRV::OpAtomicUMax:
1746 case SPIRV::OpAtomicSMin:
1747 case SPIRV::OpAtomicSMax:
1748 case SPIRV::OpAtomicAnd:
1749 case SPIRV::OpAtomicOr:
1750 case SPIRV::OpAtomicXor: {
1753 if (
Op == SPIRV::OpAtomicStore) {
1756 assert(InstrPtr &&
"Unexpected type instruction for OpAtomicStore");
1762 if (TypeDef->
getOpcode() == SPIRV::OpTypeInt) {
1767 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics))
1769 "16-bit integer atomic operations require the following SPIR-V "
1770 "extension: SPV_INTEL_16bit_atomics",
1772 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics);
1774 case SPIRV::OpAtomicLoad:
1775 case SPIRV::OpAtomicStore:
1776 case SPIRV::OpAtomicExchange:
1777 case SPIRV::OpAtomicCompareExchange:
1778 case SPIRV::OpAtomicCompareExchangeWeak:
1780 SPIRV::Capability::AtomicInt16CompareExchangeINTEL);
1787 }
else if (isBFloat16Type(TypeDef)) {
1788 if (
is_contained({SPIRV::OpAtomicLoad, SPIRV::OpAtomicStore,
1789 SPIRV::OpAtomicExchange},
1791 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics))
1793 "The atomic bfloat16 instruction requires the following SPIR-V "
1794 "extension: SPV_INTEL_16bit_atomics",
1796 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics);
1797 Reqs.
addCapability(SPIRV::Capability::AtomicBFloat16LoadStoreINTEL);
1802 case SPIRV::OpGroupNonUniformIAdd:
1803 case SPIRV::OpGroupNonUniformFAdd:
1804 case SPIRV::OpGroupNonUniformIMul:
1805 case SPIRV::OpGroupNonUniformFMul:
1806 case SPIRV::OpGroupNonUniformSMin:
1807 case SPIRV::OpGroupNonUniformUMin:
1808 case SPIRV::OpGroupNonUniformFMin:
1809 case SPIRV::OpGroupNonUniformSMax:
1810 case SPIRV::OpGroupNonUniformUMax:
1811 case SPIRV::OpGroupNonUniformFMax:
1812 case SPIRV::OpGroupNonUniformBitwiseAnd:
1813 case SPIRV::OpGroupNonUniformBitwiseOr:
1814 case SPIRV::OpGroupNonUniformBitwiseXor:
1815 case SPIRV::OpGroupNonUniformLogicalAnd:
1816 case SPIRV::OpGroupNonUniformLogicalOr:
1817 case SPIRV::OpGroupNonUniformLogicalXor: {
1819 int64_t GroupOp =
MI.getOperand(3).getImm();
1821 case SPIRV::GroupOperation::Reduce:
1822 case SPIRV::GroupOperation::InclusiveScan:
1823 case SPIRV::GroupOperation::ExclusiveScan:
1824 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformArithmetic);
1826 case SPIRV::GroupOperation::ClusteredReduce:
1827 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformClustered);
1829 case SPIRV::GroupOperation::PartitionedReduceNV:
1830 case SPIRV::GroupOperation::PartitionedInclusiveScanNV:
1831 case SPIRV::GroupOperation::PartitionedExclusiveScanNV:
1832 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformPartitionedNV);
1837 case SPIRV::OpGroupNonUniformQuadSwap:
1840 case SPIRV::OpImageQueryLod:
1843 case SPIRV::OpImageQuerySize:
1844 case SPIRV::OpImageQuerySizeLod:
1845 case SPIRV::OpImageQueryLevels:
1846 case SPIRV::OpImageQuerySamples:
1850 case SPIRV::OpImageQueryFormat: {
1851 Register ResultReg =
MI.getOperand(0).getReg();
1853 static const unsigned CompareOps[] = {
1854 SPIRV::OpIEqual, SPIRV::OpINotEqual,
1855 SPIRV::OpUGreaterThan, SPIRV::OpUGreaterThanEqual,
1856 SPIRV::OpULessThan, SPIRV::OpULessThanEqual,
1857 SPIRV::OpSGreaterThan, SPIRV::OpSGreaterThanEqual,
1858 SPIRV::OpSLessThan, SPIRV::OpSLessThanEqual};
1860 auto CheckAndAddExtension = [&](int64_t ImmVal) {
1861 if (ImmVal == 4323 || ImmVal == 4324) {
1862 if (
ST.canUseExtension(SPIRV::Extension::SPV_EXT_image_raw10_raw12))
1863 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_image_raw10_raw12);
1866 "SPV_EXT_image_raw10_raw12 extension");
1871 unsigned Opc = UseInst.getOpcode();
1873 if (
Opc == SPIRV::OpSwitch) {
1876 CheckAndAddExtension(
Op.getImm());
1878 for (
unsigned i = 1; i < UseInst.getNumOperands(); ++i) {
1881 if (ConstInst && ConstInst->
getOpcode() == SPIRV::OpConstantI) {
1884 CheckAndAddExtension(ImmVal);
1892 case SPIRV::OpGroupNonUniformShuffle:
1893 case SPIRV::OpGroupNonUniformShuffleXor:
1894 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformShuffle);
1896 case SPIRV::OpGroupNonUniformShuffleUp:
1897 case SPIRV::OpGroupNonUniformShuffleDown:
1898 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformShuffleRelative);
1900 case SPIRV::OpGroupAll:
1901 case SPIRV::OpGroupAny:
1902 case SPIRV::OpGroupBroadcast:
1903 case SPIRV::OpGroupIAdd:
1904 case SPIRV::OpGroupFAdd:
1905 case SPIRV::OpGroupFMin:
1906 case SPIRV::OpGroupUMin:
1907 case SPIRV::OpGroupSMin:
1908 case SPIRV::OpGroupFMax:
1909 case SPIRV::OpGroupUMax:
1910 case SPIRV::OpGroupSMax:
1913 case SPIRV::OpGroupNonUniformElect:
1916 case SPIRV::OpGroupNonUniformAll:
1917 case SPIRV::OpGroupNonUniformAny:
1918 case SPIRV::OpGroupNonUniformAllEqual:
1921 case SPIRV::OpGroupNonUniformBroadcast:
1922 case SPIRV::OpGroupNonUniformBroadcastFirst:
1923 case SPIRV::OpGroupNonUniformBallot:
1924 case SPIRV::OpGroupNonUniformInverseBallot:
1925 case SPIRV::OpGroupNonUniformBallotBitExtract:
1926 case SPIRV::OpGroupNonUniformBallotBitCount:
1927 case SPIRV::OpGroupNonUniformBallotFindLSB:
1928 case SPIRV::OpGroupNonUniformBallotFindMSB:
1929 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformBallot);
1931 case SPIRV::OpSubgroupShuffleINTEL:
1932 case SPIRV::OpSubgroupShuffleDownINTEL:
1933 case SPIRV::OpSubgroupShuffleUpINTEL:
1934 case SPIRV::OpSubgroupShuffleXorINTEL:
1935 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {
1936 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_subgroups);
1937 Reqs.
addCapability(SPIRV::Capability::SubgroupShuffleINTEL);
1940 case SPIRV::OpSubgroupBlockReadINTEL:
1941 case SPIRV::OpSubgroupBlockWriteINTEL:
1942 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {
1943 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_subgroups);
1944 Reqs.
addCapability(SPIRV::Capability::SubgroupBufferBlockIOINTEL);
1947 case SPIRV::OpSubgroupImageBlockReadINTEL:
1948 case SPIRV::OpSubgroupImageBlockWriteINTEL:
1949 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {
1950 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_subgroups);
1951 Reqs.
addCapability(SPIRV::Capability::SubgroupImageBlockIOINTEL);
1954 case SPIRV::OpSubgroupImageMediaBlockReadINTEL:
1955 case SPIRV::OpSubgroupImageMediaBlockWriteINTEL:
1956 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_media_block_io)) {
1957 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_media_block_io);
1958 Reqs.
addCapability(SPIRV::Capability::SubgroupImageMediaBlockIOINTEL);
1961 case SPIRV::OpAssumeTrueKHR:
1962 case SPIRV::OpExpectKHR:
1963 if (
ST.canUseExtension(SPIRV::Extension::SPV_KHR_expect_assume)) {
1964 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_expect_assume);
1968 case SPIRV::OpFmaKHR:
1969 if (
ST.canUseExtension(SPIRV::Extension::SPV_KHR_fma)) {
1974 case SPIRV::OpPtrCastToCrossWorkgroupINTEL:
1975 case SPIRV::OpCrossWorkgroupCastToPtrINTEL:
1976 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_usm_storage_classes)) {
1977 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_usm_storage_classes);
1978 Reqs.
addCapability(SPIRV::Capability::USMStorageClassesINTEL);
1981 case SPIRV::OpConstantFunctionPointerINTEL:
1982 case SPIRV::OpFunctionPointerCallINTEL:
1983 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_function_pointers)) {
1984 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_function_pointers);
1985 Reqs.
addCapability(SPIRV::Capability::FunctionPointersINTEL);
1988 case SPIRV::OpGroupNonUniformRotateKHR:
1989 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_subgroup_rotate))
1991 "following SPIR-V extension: SPV_KHR_subgroup_rotate",
1993 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_subgroup_rotate);
1994 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformRotateKHR);
1997 case SPIRV::OpFixedCosALTERA:
1998 case SPIRV::OpFixedSinALTERA:
1999 case SPIRV::OpFixedCosPiALTERA:
2000 case SPIRV::OpFixedSinPiALTERA:
2001 case SPIRV::OpFixedExpALTERA:
2002 case SPIRV::OpFixedLogALTERA:
2003 case SPIRV::OpFixedRecipALTERA:
2004 case SPIRV::OpFixedSqrtALTERA:
2005 case SPIRV::OpFixedSinCosALTERA:
2006 case SPIRV::OpFixedSinCosPiALTERA:
2007 case SPIRV::OpFixedRsqrtALTERA:
2008 if (!
ST.canUseExtension(
2009 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_fixed_point))
2011 "following SPIR-V extension: "
2012 "SPV_ALTERA_arbitrary_precision_fixed_point",
2015 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_fixed_point);
2016 Reqs.
addCapability(SPIRV::Capability::ArbitraryPrecisionFixedPointALTERA);
2018 case SPIRV::OpGroupIMulKHR:
2019 case SPIRV::OpGroupFMulKHR:
2020 case SPIRV::OpGroupBitwiseAndKHR:
2021 case SPIRV::OpGroupBitwiseOrKHR:
2022 case SPIRV::OpGroupBitwiseXorKHR:
2023 case SPIRV::OpGroupLogicalAndKHR:
2024 case SPIRV::OpGroupLogicalOrKHR:
2025 case SPIRV::OpGroupLogicalXorKHR:
2026 if (
ST.canUseExtension(
2027 SPIRV::Extension::SPV_KHR_uniform_group_instructions)) {
2028 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_uniform_group_instructions);
2029 Reqs.
addCapability(SPIRV::Capability::GroupUniformArithmeticKHR);
2032 case SPIRV::OpReadClockKHR:
2033 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_shader_clock))
2035 "following SPIR-V extension: SPV_KHR_shader_clock",
2037 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_shader_clock);
2040 case SPIRV::OpAbortKHR:
2041 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_abort))
2043 "following SPIR-V extension: SPV_KHR_abort",
2048 case SPIRV::OpPoisonKHR:
2049 case SPIRV::OpFreezeKHR:
2050 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_poison_freeze))
2052 "following SPIR-V extension: SPV_KHR_poison_freeze",
2054 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_poison_freeze);
2057 case SPIRV::OpAtomicFAddEXT:
2058 case SPIRV::OpAtomicFMinEXT:
2059 case SPIRV::OpAtomicFMaxEXT:
2060 AddAtomicFloatRequirements(
MI, Reqs, ST);
2062 case SPIRV::OpConvertBF16ToFINTEL:
2063 case SPIRV::OpConvertFToBF16INTEL:
2064 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bfloat16_conversion)) {
2065 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bfloat16_conversion);
2066 Reqs.
addCapability(SPIRV::Capability::BFloat16ConversionINTEL);
2069 case SPIRV::OpRoundFToTF32INTEL:
2070 if (
ST.canUseExtension(
2071 SPIRV::Extension::SPV_INTEL_tensor_float32_conversion)) {
2072 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_tensor_float32_conversion);
2073 Reqs.
addCapability(SPIRV::Capability::TensorFloat32RoundingINTEL);
2076 case SPIRV::OpVariableLengthArrayINTEL:
2077 case SPIRV::OpSaveMemoryINTEL:
2078 case SPIRV::OpRestoreMemoryINTEL:
2079 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_variable_length_array)) {
2080 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_variable_length_array);
2081 Reqs.
addCapability(SPIRV::Capability::VariableLengthArrayINTEL);
2084 case SPIRV::OpAsmTargetINTEL:
2085 case SPIRV::OpAsmINTEL:
2086 case SPIRV::OpAsmCallINTEL:
2087 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_inline_assembly)) {
2088 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_inline_assembly);
2092 case SPIRV::OpTypeCooperativeMatrixKHR: {
2093 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix))
2095 "OpTypeCooperativeMatrixKHR type requires the "
2096 "following SPIR-V extension: SPV_KHR_cooperative_matrix",
2098 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix);
2099 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixKHR);
2102 if (isBFloat16Type(TypeDef))
2103 Reqs.
addCapability(SPIRV::Capability::BFloat16CooperativeMatrixKHR);
2106 case SPIRV::OpArithmeticFenceEXT:
2107 if (!
ST.canUseExtension(SPIRV::Extension::SPV_EXT_arithmetic_fence))
2109 "following SPIR-V extension: SPV_EXT_arithmetic_fence",
2111 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_arithmetic_fence);
2114 case SPIRV::OpControlBarrierArriveINTEL:
2115 case SPIRV::OpControlBarrierWaitINTEL:
2116 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_split_barrier)) {
2117 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_split_barrier);
2121 case SPIRV::OpCooperativeMatrixMulAddKHR: {
2122 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix))
2124 "following SPIR-V extension: "
2125 "SPV_KHR_cooperative_matrix",
2127 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix);
2128 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixKHR);
2129 constexpr unsigned MulAddMaxSize = 6;
2130 if (
MI.getNumOperands() != MulAddMaxSize)
2132 const int64_t CoopOperands =
MI.getOperand(MulAddMaxSize - 1).getImm();
2134 SPIRV::CooperativeMatrixOperands::MatrixAAndBTF32ComponentsINTEL) {
2135 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
2137 "require the following SPIR-V extension: "
2138 "SPV_INTEL_joint_matrix",
2140 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2142 SPIRV::Capability::CooperativeMatrixTF32ComponentTypeINTEL);
2145 MatrixAAndBBFloat16ComponentsINTEL ||
2147 SPIRV::CooperativeMatrixOperands::MatrixCBFloat16ComponentsINTEL ||
2149 MatrixResultBFloat16ComponentsINTEL) {
2150 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
2152 "require the following SPIR-V extension: "
2153 "SPV_INTEL_joint_matrix",
2155 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2157 SPIRV::Capability::CooperativeMatrixBFloat16ComponentTypeINTEL);
2161 case SPIRV::OpCooperativeMatrixLoadKHR:
2162 case SPIRV::OpCooperativeMatrixStoreKHR:
2163 case SPIRV::OpCooperativeMatrixLoadCheckedINTEL:
2164 case SPIRV::OpCooperativeMatrixStoreCheckedINTEL:
2165 case SPIRV::OpCooperativeMatrixPrefetchINTEL: {
2166 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix))
2168 "following SPIR-V extension: "
2169 "SPV_KHR_cooperative_matrix",
2171 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix);
2172 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixKHR);
2178 case SPIRV::OpCooperativeMatrixLoadKHR:
2181 case SPIRV::OpCooperativeMatrixStoreKHR:
2184 case SPIRV::OpCooperativeMatrixLoadCheckedINTEL:
2187 case SPIRV::OpCooperativeMatrixStoreCheckedINTEL:
2188 case SPIRV::OpCooperativeMatrixPrefetchINTEL:
2194 Register RegLayout =
MI.getOperand(LayoutNum).getReg();
2197 if (MILayout->
getOpcode() == SPIRV::OpConstantI) {
2200 static_cast<unsigned>(SPIRV::CooperativeMatrixLayout::PackedINTEL)) {
2201 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
2203 "extension: SPV_INTEL_joint_matrix",
2205 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2206 Reqs.
addCapability(SPIRV::Capability::PackedCooperativeMatrixINTEL);
2211 if (
Op == SPIRV::OpCooperativeMatrixLoadKHR ||
2212 Op == SPIRV::OpCooperativeMatrixStoreKHR)
2215 std::string InstName;
2217 case SPIRV::OpCooperativeMatrixPrefetchINTEL:
2218 InstName =
"OpCooperativeMatrixPrefetchINTEL";
2220 case SPIRV::OpCooperativeMatrixLoadCheckedINTEL:
2221 InstName =
"OpCooperativeMatrixLoadCheckedINTEL";
2223 case SPIRV::OpCooperativeMatrixStoreCheckedINTEL:
2224 InstName =
"OpCooperativeMatrixStoreCheckedINTEL";
2228 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix)) {
2229 const std::string ErrorMsg =
2230 InstName +
" instruction requires the "
2231 "following SPIR-V extension: SPV_INTEL_joint_matrix";
2234 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2235 if (
Op == SPIRV::OpCooperativeMatrixPrefetchINTEL) {
2236 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixPrefetchINTEL);
2240 SPIRV::Capability::CooperativeMatrixCheckedInstructionsINTEL);
2243 case SPIRV::OpCooperativeMatrixConstructCheckedINTEL:
2244 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
2246 "instructions require the following SPIR-V extension: "
2247 "SPV_INTEL_joint_matrix",
2249 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2251 SPIRV::Capability::CooperativeMatrixCheckedInstructionsINTEL);
2253 case SPIRV::OpReadPipeBlockingALTERA:
2254 case SPIRV::OpWritePipeBlockingALTERA:
2255 if (
ST.canUseExtension(SPIRV::Extension::SPV_ALTERA_blocking_pipes)) {
2256 Reqs.
addExtension(SPIRV::Extension::SPV_ALTERA_blocking_pipes);
2260 case SPIRV::OpCooperativeMatrixGetElementCoordINTEL:
2261 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
2263 "following SPIR-V extension: SPV_INTEL_joint_matrix",
2265 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2267 SPIRV::Capability::CooperativeMatrixInvocationInstructionsINTEL);
2269 case SPIRV::OpConvertHandleToImageINTEL:
2270 case SPIRV::OpConvertHandleToSamplerINTEL:
2271 case SPIRV::OpConvertHandleToSampledImageINTEL: {
2272 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bindless_images))
2274 "instructions require the following SPIR-V extension: "
2275 "SPV_INTEL_bindless_images",
2278 SPIRV::AddressingModel::AddressingModel AddrModel = MAI.
Addr;
2280 if (
Op == SPIRV::OpConvertHandleToImageINTEL &&
2281 TyDef->
getOpcode() != SPIRV::OpTypeImage) {
2283 "OpConvertHandleToImageINTEL",
2285 }
else if (
Op == SPIRV::OpConvertHandleToSamplerINTEL &&
2286 TyDef->
getOpcode() != SPIRV::OpTypeSampler) {
2288 "OpConvertHandleToSamplerINTEL",
2290 }
else if (
Op == SPIRV::OpConvertHandleToSampledImageINTEL &&
2291 TyDef->
getOpcode() != SPIRV::OpTypeSampledImage) {
2293 "OpConvertHandleToSampledImageINTEL",
2298 if (!(Bitwidth == 32 && AddrModel == SPIRV::AddressingModel::Physical32) &&
2299 !(Bitwidth == 64 && AddrModel == SPIRV::AddressingModel::Physical64)) {
2301 "Parameter value must be a 32-bit scalar in case of "
2302 "Physical32 addressing model or a 64-bit scalar in case of "
2303 "Physical64 addressing model",
2306 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bindless_images);
2310 case SPIRV::OpSubgroup2DBlockLoadINTEL:
2311 case SPIRV::OpSubgroup2DBlockLoadTransposeINTEL:
2312 case SPIRV::OpSubgroup2DBlockLoadTransformINTEL:
2313 case SPIRV::OpSubgroup2DBlockPrefetchINTEL:
2314 case SPIRV::OpSubgroup2DBlockStoreINTEL: {
2315 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_2d_block_io))
2317 "Prefetch/Store]INTEL instructions require the "
2318 "following SPIR-V extension: SPV_INTEL_2d_block_io",
2320 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_2d_block_io);
2321 Reqs.
addCapability(SPIRV::Capability::Subgroup2DBlockIOINTEL);
2323 if (
Op == SPIRV::OpSubgroup2DBlockLoadTransposeINTEL) {
2324 Reqs.
addCapability(SPIRV::Capability::Subgroup2DBlockTransposeINTEL);
2327 if (
Op == SPIRV::OpSubgroup2DBlockLoadTransformINTEL) {
2328 Reqs.
addCapability(SPIRV::Capability::Subgroup2DBlockTransformINTEL);
2333 case SPIRV::OpKill: {
2336 case SPIRV::OpDemoteToHelperInvocation:
2337 Reqs.
addCapability(SPIRV::Capability::DemoteToHelperInvocation);
2339 if (
ST.canUseExtension(
2340 SPIRV::Extension::SPV_EXT_demote_to_helper_invocation)) {
2343 SPIRV::Extension::SPV_EXT_demote_to_helper_invocation);
2348 case SPIRV::OpSUDot:
2349 case SPIRV::OpSDotAccSat:
2350 case SPIRV::OpUDotAccSat:
2351 case SPIRV::OpSUDotAccSat:
2352 AddDotProductRequirements(
MI, Reqs, ST);
2354 case SPIRV::OpImageSampleImplicitLod:
2355 case SPIRV::OpImageFetch:
2357 addImageOperandReqs(
MI, Reqs, ST, 4);
2359 case SPIRV::OpImageSampleExplicitLod:
2360 addImageOperandReqs(
MI, Reqs, ST, 4);
2362 case SPIRV::OpImageSampleDrefImplicitLod:
2363 case SPIRV::OpImageSampleDrefExplicitLod:
2364 case SPIRV::OpImageDrefGather:
2365 case SPIRV::OpImageGather:
2367 addImageOperandReqs(
MI, Reqs, ST, 5);
2369 case SPIRV::OpImageRead: {
2370 Register ImageReg =
MI.getOperand(2).getReg();
2379 if (isImageTypeWithUnknownFormat(TypeDef) &&
ST.isShader())
2380 Reqs.
addCapability(SPIRV::Capability::StorageImageReadWithoutFormat);
2383 case SPIRV::OpImageWrite: {
2384 Register ImageReg =
MI.getOperand(0).getReg();
2393 if (isImageTypeWithUnknownFormat(TypeDef) &&
ST.isShader())
2394 Reqs.
addCapability(SPIRV::Capability::StorageImageWriteWithoutFormat);
2397 case SPIRV::OpTypeStructContinuedINTEL:
2398 case SPIRV::OpConstantCompositeContinuedINTEL:
2399 case SPIRV::OpSpecConstantCompositeContinuedINTEL:
2400 case SPIRV::OpCompositeConstructContinuedINTEL: {
2401 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_long_composites))
2403 "Continued instructions require the "
2404 "following SPIR-V extension: SPV_INTEL_long_composites",
2406 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_long_composites);
2410 case SPIRV::OpArbitraryFloatEQALTERA:
2411 case SPIRV::OpArbitraryFloatGEALTERA:
2412 case SPIRV::OpArbitraryFloatGTALTERA:
2413 case SPIRV::OpArbitraryFloatLEALTERA:
2414 case SPIRV::OpArbitraryFloatLTALTERA:
2415 case SPIRV::OpArbitraryFloatCbrtALTERA:
2416 case SPIRV::OpArbitraryFloatCosALTERA:
2417 case SPIRV::OpArbitraryFloatCosPiALTERA:
2418 case SPIRV::OpArbitraryFloatExp10ALTERA:
2419 case SPIRV::OpArbitraryFloatExp2ALTERA:
2420 case SPIRV::OpArbitraryFloatExpALTERA:
2421 case SPIRV::OpArbitraryFloatExpm1ALTERA:
2422 case SPIRV::OpArbitraryFloatHypotALTERA:
2423 case SPIRV::OpArbitraryFloatLog10ALTERA:
2424 case SPIRV::OpArbitraryFloatLog1pALTERA:
2425 case SPIRV::OpArbitraryFloatLog2ALTERA:
2426 case SPIRV::OpArbitraryFloatLogALTERA:
2427 case SPIRV::OpArbitraryFloatRecipALTERA:
2428 case SPIRV::OpArbitraryFloatSinCosALTERA:
2429 case SPIRV::OpArbitraryFloatSinCosPiALTERA:
2430 case SPIRV::OpArbitraryFloatSinALTERA:
2431 case SPIRV::OpArbitraryFloatSinPiALTERA:
2432 case SPIRV::OpArbitraryFloatSqrtALTERA:
2433 case SPIRV::OpArbitraryFloatACosALTERA:
2434 case SPIRV::OpArbitraryFloatACosPiALTERA:
2435 case SPIRV::OpArbitraryFloatAddALTERA:
2436 case SPIRV::OpArbitraryFloatASinALTERA:
2437 case SPIRV::OpArbitraryFloatASinPiALTERA:
2438 case SPIRV::OpArbitraryFloatATan2ALTERA:
2439 case SPIRV::OpArbitraryFloatATanALTERA:
2440 case SPIRV::OpArbitraryFloatATanPiALTERA:
2441 case SPIRV::OpArbitraryFloatCastFromIntALTERA:
2442 case SPIRV::OpArbitraryFloatCastALTERA:
2443 case SPIRV::OpArbitraryFloatCastToIntALTERA:
2444 case SPIRV::OpArbitraryFloatDivALTERA:
2445 case SPIRV::OpArbitraryFloatMulALTERA:
2446 case SPIRV::OpArbitraryFloatPowALTERA:
2447 case SPIRV::OpArbitraryFloatPowNALTERA:
2448 case SPIRV::OpArbitraryFloatPowRALTERA:
2449 case SPIRV::OpArbitraryFloatRSqrtALTERA:
2450 case SPIRV::OpArbitraryFloatSubALTERA: {
2451 if (!
ST.canUseExtension(
2452 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_floating_point))
2454 "Floating point instructions can't be translated correctly without "
2455 "enabled SPV_ALTERA_arbitrary_precision_floating_point extension!",
2458 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_floating_point);
2460 SPIRV::Capability::ArbitraryPrecisionFloatingPointALTERA);
2463 case SPIRV::OpSubgroupMatrixMultiplyAccumulateINTEL: {
2464 if (!
ST.canUseExtension(
2465 SPIRV::Extension::SPV_INTEL_subgroup_matrix_multiply_accumulate))
2467 "OpSubgroupMatrixMultiplyAccumulateINTEL instruction requires the "
2469 "extension: SPV_INTEL_subgroup_matrix_multiply_accumulate",
2472 SPIRV::Extension::SPV_INTEL_subgroup_matrix_multiply_accumulate);
2474 SPIRV::Capability::SubgroupMatrixMultiplyAccumulateINTEL);
2477 case SPIRV::OpBitwiseFunctionINTEL: {
2478 if (!
ST.canUseExtension(
2479 SPIRV::Extension::SPV_INTEL_ternary_bitwise_function))
2481 "OpBitwiseFunctionINTEL instruction requires the following SPIR-V "
2482 "extension: SPV_INTEL_ternary_bitwise_function",
2484 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_ternary_bitwise_function);
2485 Reqs.
addCapability(SPIRV::Capability::TernaryBitwiseFunctionINTEL);
2488 case SPIRV::OpCopyMemorySized: {
2493 case SPIRV::OpPredicatedLoadINTEL:
2494 case SPIRV::OpPredicatedStoreINTEL: {
2495 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_predicated_io))
2497 "OpPredicated[Load/Store]INTEL instructions require "
2498 "the following SPIR-V extension: SPV_INTEL_predicated_io",
2500 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_predicated_io);
2504 case SPIRV::OpFAddS:
2505 case SPIRV::OpFSubS:
2506 case SPIRV::OpFMulS:
2507 case SPIRV::OpFDivS:
2508 case SPIRV::OpFRemS:
2510 case SPIRV::OpFNegate:
2511 case SPIRV::OpFAddV:
2512 case SPIRV::OpFSubV:
2513 case SPIRV::OpFMulV:
2514 case SPIRV::OpFDivV:
2515 case SPIRV::OpFRemV:
2516 case SPIRV::OpFNegateV: {
2519 if (TypeDef->
getOpcode() == SPIRV::OpTypeVector)
2521 if (isBFloat16Type(TypeDef)) {
2522 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic))
2524 "Arithmetic instructions with bfloat16 arguments require the "
2525 "following SPIR-V extension: SPV_INTEL_bfloat16_arithmetic",
2527 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic);
2528 Reqs.
addCapability(SPIRV::Capability::BFloat16ArithmeticINTEL);
2532 case SPIRV::OpOrdered:
2533 case SPIRV::OpUnordered:
2534 case SPIRV::OpFOrdEqual:
2535 case SPIRV::OpFOrdNotEqual:
2536 case SPIRV::OpFOrdLessThan:
2537 case SPIRV::OpFOrdLessThanEqual:
2538 case SPIRV::OpFOrdGreaterThan:
2539 case SPIRV::OpFOrdGreaterThanEqual:
2540 case SPIRV::OpFUnordEqual:
2541 case SPIRV::OpFUnordNotEqual:
2542 case SPIRV::OpFUnordLessThan:
2543 case SPIRV::OpFUnordLessThanEqual:
2544 case SPIRV::OpFUnordGreaterThan:
2545 case SPIRV::OpFUnordGreaterThanEqual: {
2549 if (TypeDef->
getOpcode() == SPIRV::OpTypeVector)
2551 if (isBFloat16Type(TypeDef)) {
2552 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic))
2554 "Relational instructions with bfloat16 arguments require the "
2555 "following SPIR-V extension: SPV_INTEL_bfloat16_arithmetic",
2557 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic);
2558 Reqs.
addCapability(SPIRV::Capability::BFloat16ArithmeticINTEL);
2562 case SPIRV::OpDPdxCoarse:
2563 case SPIRV::OpDPdyCoarse:
2564 case SPIRV::OpDPdxFine:
2565 case SPIRV::OpDPdyFine: {
2569 case SPIRV::OpLoopControlINTEL: {
2570 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_unstructured_loop_controls);
2571 Reqs.
addCapability(SPIRV::Capability::UnstructuredLoopControlsINTEL);
2583 SPIRV::Capability::Shader);
2595 addInstrRequirements(
MI, MAI, ST);
2598 auto Node = M.getNamedMetadata(
"spirv.ExecutionMode");
2600 bool RequireFloatControls =
false, RequireIntelFloatControls2 =
false,
2601 RequireKHRFloatControls2 =
false,
2603 bool HasIntelFloatControls2 =
2604 ST.canUseExtension(SPIRV::Extension::SPV_INTEL_float_controls2);
2605 bool HasKHRFloatControls2 =
2606 ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2);
2607 for (
unsigned i = 0; i <
Node->getNumOperands(); i++) {
2613 auto EM =
Const->getZExtValue();
2617 case SPIRV::ExecutionMode::DenormPreserve:
2618 case SPIRV::ExecutionMode::DenormFlushToZero:
2619 case SPIRV::ExecutionMode::RoundingModeRTE:
2620 case SPIRV::ExecutionMode::RoundingModeRTZ:
2621 RequireFloatControls = VerLower14;
2623 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2625 case SPIRV::ExecutionMode::RoundingModeRTPINTEL:
2626 case SPIRV::ExecutionMode::RoundingModeRTNINTEL:
2627 case SPIRV::ExecutionMode::FloatingPointModeALTINTEL:
2628 case SPIRV::ExecutionMode::FloatingPointModeIEEEINTEL:
2629 if (HasIntelFloatControls2) {
2630 RequireIntelFloatControls2 =
true;
2632 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2635 case SPIRV::ExecutionMode::FPFastMathDefault: {
2636 if (HasKHRFloatControls2) {
2637 RequireKHRFloatControls2 =
true;
2639 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2643 case SPIRV::ExecutionMode::ContractionOff:
2644 case SPIRV::ExecutionMode::SignedZeroInfNanPreserve:
2645 if (HasKHRFloatControls2) {
2646 RequireKHRFloatControls2 =
true;
2648 SPIRV::OperandCategory::ExecutionModeOperand,
2649 SPIRV::ExecutionMode::FPFastMathDefault, ST);
2652 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2657 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2662 if (RequireFloatControls &&
2663 ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls))
2665 if (RequireIntelFloatControls2)
2667 if (RequireKHRFloatControls2)
2671 if (
F.isDeclaration())
2673 if (
F.getMetadata(
"reqd_work_group_size"))
2675 SPIRV::OperandCategory::ExecutionModeOperand,
2676 SPIRV::ExecutionMode::LocalSize, ST);
2677 if (
F.getFnAttribute(
"hlsl.numthreads").isValid()) {
2679 SPIRV::OperandCategory::ExecutionModeOperand,
2680 SPIRV::ExecutionMode::LocalSize, ST);
2682 if (
F.getFnAttribute(
"enable-maximal-reconvergence").getValueAsBool()) {
2685 if (
F.getMetadata(
"work_group_size_hint"))
2687 SPIRV::OperandCategory::ExecutionModeOperand,
2688 SPIRV::ExecutionMode::LocalSizeHint, ST);
2689 if (
F.getMetadata(
"intel_reqd_sub_group_size") ||
2690 F.getMetadata(
"reqd_sub_group_size"))
2692 SPIRV::OperandCategory::ExecutionModeOperand,
2693 SPIRV::ExecutionMode::SubgroupSize, ST);
2694 if (
F.getMetadata(
"max_work_group_size"))
2696 SPIRV::OperandCategory::ExecutionModeOperand,
2697 SPIRV::ExecutionMode::MaxWorkgroupSizeINTEL, ST);
2698 if (
F.getMetadata(
"vec_type_hint"))
2700 SPIRV::OperandCategory::ExecutionModeOperand,
2701 SPIRV::ExecutionMode::VecTypeHint, ST);
2703 if (
F.hasOptNone()) {
2704 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_optnone)) {
2707 }
else if (
ST.canUseExtension(SPIRV::Extension::SPV_EXT_optnone)) {
2717 unsigned Flags = SPIRV::FPFastMathMode::None;
2718 bool CanUseKHRFloatControls2 =
2719 ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2);
2721 Flags |= SPIRV::FPFastMathMode::NotNaN;
2723 Flags |= SPIRV::FPFastMathMode::NotInf;
2725 Flags |= SPIRV::FPFastMathMode::NSZ;
2727 Flags |= SPIRV::FPFastMathMode::AllowRecip;
2729 Flags |= SPIRV::FPFastMathMode::AllowContract;
2731 if (CanUseKHRFloatControls2)
2739 Flags |= SPIRV::FPFastMathMode::NotNaN | SPIRV::FPFastMathMode::NotInf |
2740 SPIRV::FPFastMathMode::NSZ | SPIRV::FPFastMathMode::AllowRecip |
2741 SPIRV::FPFastMathMode::AllowTransform |
2742 SPIRV::FPFastMathMode::AllowReassoc |
2743 SPIRV::FPFastMathMode::AllowContract;
2745 Flags |= SPIRV::FPFastMathMode::Fast;
2748 if (CanUseKHRFloatControls2) {
2750 assert(!(Flags & SPIRV::FPFastMathMode::Fast) &&
2751 "SPIRV::FPFastMathMode::Fast is deprecated and should not be used "
2756 assert((!(Flags & SPIRV::FPFastMathMode::AllowTransform) ||
2757 ((Flags & SPIRV::FPFastMathMode::AllowReassoc &&
2758 Flags & SPIRV::FPFastMathMode::AllowContract))) &&
2759 "SPIRV::FPFastMathMode::AllowTransform requires AllowReassoc and "
2760 "AllowContract flags to be enabled as well.");
2771 return ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2);
2774static void handleMIFlagDecoration(
2778 if (
TII.canUseIntegerWrapDecoration(
I)) {
2780 getSymbolicOperandRequirements(
2781 SPIRV::OperandCategory::DecorationOperand,
2782 SPIRV::Decoration::NoSignedWrap, ST, Reqs)
2785 SPIRV::Decoration::NoSignedWrap, {});
2787 getSymbolicOperandRequirements(
2788 SPIRV::OperandCategory::DecorationOperand,
2789 SPIRV::Decoration::NoUnsignedWrap, ST, Reqs)
2792 SPIRV::Decoration::NoUnsignedWrap, {});
2797 TII.canUseFastMathFlags(
2798 I,
ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2)) ||
2799 (
ST.isKernel() &&
I.getOpcode() == SPIRV::OpExtInst);
2803 unsigned FMFlags = getFastMathFlags(
I, ST);
2804 if (FMFlags == SPIRV::FPFastMathMode::None) {
2807 if (FPFastMathDefaultInfoVec.
empty())
2823 assert(
I.getNumOperands() >= 3 &&
"Expected at least 3 operands");
2824 Register ResReg =
I.getOpcode() == SPIRV::OpExtInst
2825 ?
I.getOperand(1).getReg()
2826 :
I.getOperand(2).getReg();
2834 if (Ty == Elem.Ty) {
2835 FMFlags = Elem.FastMathFlags;
2836 Emit = Elem.ContractionOff || Elem.SignedZeroInfNanPreserve ||
2837 Elem.FPFastMathDefault;
2842 if (FMFlags == SPIRV::FPFastMathMode::None && !Emit)
2845 if (isFastMathModeAvailable(ST)) {
2846 Register DstReg =
I.getOperand(0).getReg();
2862 for (
auto &
MBB : *MF)
2863 for (
auto &
MI :
MBB)
2864 handleMIFlagDecoration(
MI, ST,
TII, MAI.
Reqs, GR,
2881 for (
auto &
MBB : *MF) {
2882 if (!
MBB.hasName() ||
MBB.empty())
2901 for (
auto &
MBB : *MF) {
2903 MI.setDesc(
TII.get(SPIRV::OpPhi));
2906 MI.insert(
MI.operands_begin() + 1,
2907 {MachineOperand::CreateReg(ResTypeReg, false)});
2926 SPIRV::FPFastMathMode::None);
2928 SPIRV::FPFastMathMode::None);
2930 SPIRV::FPFastMathMode::None);
2937 size_t BitWidth = Ty->getScalarSizeInBits();
2941 assert(Index >= 0 && Index < 3 &&
2942 "Expected FPFastMathDefaultInfo for half, float, or double");
2943 assert(FPFastMathDefaultInfoVec.
size() == 3 &&
2944 "Expected FPFastMathDefaultInfoVec to have exactly 3 elements");
2945 return FPFastMathDefaultInfoVec[Index];
2948static void collectFPFastMathDefaults(
const Module &M,
2951 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2))
2960 auto Node = M.getNamedMetadata(
"spirv.ExecutionMode");
2964 for (
unsigned i = 0; i <
Node->getNumOperands(); i++) {
2973 if (EM == SPIRV::ExecutionMode::FPFastMathDefault) {
2975 "Expected 4 operands for FPFastMathDefault");
2986 Info.FastMathFlags = Flags;
2987 Info.FPFastMathDefault =
true;
2988 }
else if (EM == SPIRV::ExecutionMode::ContractionOff) {
2990 "Expected no operands for ContractionOff");
2997 Info.ContractionOff =
true;
2999 }
else if (EM == SPIRV::ExecutionMode::SignedZeroInfNanPreserve) {
3001 "Expected 1 operand for SignedZeroInfNanPreserve");
3002 unsigned TargetWidth =
3011 assert(Index >= 0 && Index < 3 &&
3012 "Expected FPFastMathDefaultInfo for half, float, or double");
3013 assert(FPFastMathDefaultInfoVec.
size() == 3 &&
3014 "Expected FPFastMathDefaultInfoVec to have exactly 3 elements");
3015 FPFastMathDefaultInfoVec[Index].SignedZeroInfNanPreserve =
true;
3026 SPIRVTargetMachine &TM =
3030 TII = ST->getInstrInfo();
3036 patchPhis(M, GR, *TII, MMI);
3038 addMBBNames(M, *TII, MMI, *ST,
MAI);
3039 collectFPFastMathDefaults(M,
MAI, *ST);
3040 addDecorations(M, *TII, MMI, *ST,
MAI, GR);
3042 collectReqs(M,
MAI, MMI, *ST);
3046 collectDeclarations(M);
3049 numberRegistersGlobally(M);
3052 processOtherInstrs(M);
3056 MAI.Reqs.addCapability(SPIRV::Capability::Linkage);
3059 GR->setBound(
MAI.MaxID);
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
ReachingDefInfo InstSet & ToRemove
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
MachineInstr unsigned OpIdx
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
static SPIRV::FPFastMathDefaultInfoVector & getOrCreateFPFastMathDefaultInfoVec(const Module &M, DenseMap< Function *, SPIRV::FPFastMathDefaultInfoVector > &FPFastMathDefaultInfoMap, Function *F)
static SPIRV::FPFastMathDefaultInfo & getFPFastMathDefaultInfo(SPIRV::FPFastMathDefaultInfoVector &FPFastMathDefaultInfoVec, const Type *Ty)
#define ATOM_FLT_REQ_EXT_MSG(ExtName)
static cl::opt< bool > SPVDumpDeps("spv-dump-deps", cl::desc("Dump MIR with SPIR-V dependencies info"), cl::Optional, cl::init(false))
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")))
#define SPIRV_BACKEND_SERVICE_FUN_NAME
Target-Independent Code Generator Pass Configuration Options pass.
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.
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
This class contains meta information specific to a module.
LLVM_ABI MachineFunction * getMachineFunction(const Function &F) const
Returns the MachineFunction associated to IR function F if there is one, otherwise nullptr.
MachineOperand class - Representation of each machine instruction operand.
unsigned getSubReg() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
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 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 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.
virtual void print(raw_ostream &OS, const Module *M) const
print - Print out the internal state of the pass.
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
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
const SPIRVInstrInfo * getInstrInfo() const override
SPIRVGlobalRegistry * getSPIRVGlobalRegistry() const
const SPIRVSubtarget * getSubtargetImpl() const
bool isTypeIntN(unsigned N=0) 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)
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.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
@ C
The default llvm calling convention, compatible with C.
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.
NodeAddr< InstrNode * > Instr
This is an optimization pass for GlobalISel generic memory operations.
void buildOpName(Register Target, const StringRef &Name, MachineIRBuilder &MIRBuilder)
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
void buildOpDecorate(Register Reg, MachineIRBuilder &MIRBuilder, SPIRV::Decoration::Decoration Dec, ArrayRef< uint32_t > DecArgs, StringRef StrImm)
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
VersionTuple getSymbolicOperandMaxVersion(SPIRV::OperandCategory::OperandCategory Category, uint32_t Value)
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
hash_code hash_combine(const Ts &...args)
Combine values into a single hash_code.
std::map< SmallVector< size_t >, unsigned > InstrGRegsMap
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
SmallSet< SPIRV::Capability::Capability, 4 > S
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 addCapabilities(const CapabilityList &ToAdd)
bool isCapabilityAvailable(Capability::Capability Cap) const
void checkSatisfiable(const SPIRVSubtarget &ST) const
void getAndAddRequirements(SPIRV::OperandCategory::OperandCategory Category, uint32_t i, const SPIRVSubtarget &ST)
void addExtension(Extension::Extension ToAdd)
void initAvailableCapabilities(const SPIRVSubtarget &ST)
void removeCapabilityIf(const Capability::Capability ToRemove, const Capability::Capability IfPresent)
void addCapability(Capability::Capability ToAdd)
void addAvailableCaps(const CapabilityList &ToAdd)
void addRequirements(const Requirements &Req)
const std::optional< Capability::Capability > Cap
const VersionTuple MinVer
const VersionTuple MaxVer