36#define DEBUG_TYPE "spirv-module-analysis"
40 cl::desc(
"Dump MIR with SPIR-V dependencies info"),
45 cl::desc(
"SPIR-V capabilities to avoid if there are "
46 "other options enabling a feature"),
49 "SPIR-V Shader capability")));
59 "SPIRV module analysis",
true,
true)
63 Func.getContext().diagnose(
69 unsigned DefaultVal = 0) {
70 if (MdNode && OpIndex < MdNode->getNumOperands()) {
84 AvoidCaps.
S.
insert(SPIRV::Capability::Shader);
86 AvoidCaps.
S.
insert(SPIRV::Capability::Kernel);
91 bool MinVerOK = SPIRVVersion.
empty() || SPIRVVersion >= ReqMinVer;
93 ReqMaxVer.
empty() || SPIRVVersion.
empty() || SPIRVVersion <= ReqMaxVer;
94 bool VerOK = MinVerOK && MaxVerOK;
98 if (VerOK && !ReqMinVer.
empty())
100 if (ReqCaps.
empty()) {
101 if (ReqExts.
empty()) {
103 return {
true, {}, {}, ReqMinVer, ReqMaxVer};
107 if (ReqCaps.
size() == 1) {
108 auto Cap = ReqCaps[0];
111 SPIRV::OperandCategory::CapabilityOperand, Cap));
112 return {
true, {Cap}, std::move(ReqExts), ReqMinVer, ReqMaxVer};
122 for (
auto Cap : ReqCaps)
125 for (
size_t i = 0, Sz = UseCaps.
size(); i < Sz; ++i) {
126 auto Cap = UseCaps[i];
127 if (i == Sz - 1 || !AvoidCaps.
S.
contains(Cap)) {
129 SPIRV::OperandCategory::CapabilityOperand, Cap));
130 return {
true, {Cap}, std::move(ReqExts), ReqMinVer, ReqMaxVer};
139 if ((!ReqExts.
empty() || VerOK) &&
140 llvm::all_of(ReqExts, [&ST](
const SPIRV::Extension::Extension &Ext) {
141 return ST.canUseExtension(Ext);
144 return {
true, {}, std::move(ReqExts), ReqMinVer, ReqMaxVer};
150void SPIRVModuleAnalysisImpl::setBaseInfo(
const Module &M) {
154 MAI.RegisterAliasTable.clear();
155 MAI.InstrsToDelete.clear();
156 MAI.MBBNames.clear();
157 MAI.GlobalObjMap.clear();
158 MAI.GlobalVarList.clear();
159 MAI.ExtInstSetMap.clear();
160 MAI.InstrAuxDataRecords.clear();
162 MAI.Reqs.initAvailableCapabilities(*ST);
165 if (
auto MemModel =
M.getNamedMetadata(
"spirv.MemoryModel")) {
166 auto MemMD = MemModel->getOperand(0);
167 MAI.Addr =
static_cast<SPIRV::AddressingModel::AddressingModel
>(
170 static_cast<SPIRV::MemoryModel::MemoryModel
>(
getMetadataUInt(MemMD, 1));
173 MAI.Mem = ST->isShader() ? SPIRV::MemoryModel::GLSL450
174 : SPIRV::MemoryModel::OpenCL;
175 if (MAI.Mem == SPIRV::MemoryModel::OpenCL) {
176 unsigned PtrSize = ST->getPointerSize();
177 MAI.Addr = PtrSize == 32 ? SPIRV::AddressingModel::Physical32
178 : PtrSize == 64 ? SPIRV::AddressingModel::Physical64
179 : SPIRV::AddressingModel::Logical;
182 MAI.Addr = SPIRV::AddressingModel::Logical;
187 if (
auto VerNode =
M.getNamedMetadata(
"opencl.ocl.version")) {
188 MAI.SrcLang = SPIRV::SourceLanguage::OpenCL_C;
191 assert(VerNode->getNumOperands() > 0 &&
"Invalid SPIR");
192 auto VersionMD = VerNode->getOperand(0);
198 (std::max(1U, MajorNum) * 100 + MinorNum) * 1000 + RevNum;
201 if (
auto *CxxVerNode =
M.getNamedMetadata(
"opencl.cxx.version")) {
202 assert(CxxVerNode->getNumOperands() > 0 &&
"Invalid SPIR");
203 auto *CxxMD = CxxVerNode->getOperand(0);
207 if ((MAI.SrcLangVersion == 200000 && CxxVer == 100000) ||
208 (MAI.SrcLangVersion == 300000 && CxxVer == 202100000)) {
209 MAI.SrcLang = SPIRV::SourceLanguage::CPP_for_OpenCL;
210 MAI.SrcLangVersion = CxxVer;
213 "opencl cxx version is not compatible with opencl c version!");
221 if (!ST->isShader()) {
222 MAI.SrcLang = SPIRV::SourceLanguage::OpenCL_CPP;
223 MAI.SrcLangVersion = 100000;
225 MAI.SrcLang = SPIRV::SourceLanguage::Unknown;
226 MAI.SrcLangVersion = 0;
230 if (
auto ExtNode =
M.getNamedMetadata(
"opencl.used.extensions")) {
231 for (
unsigned I = 0,
E = ExtNode->getNumOperands();
I !=
E; ++
I) {
232 MDNode *MD = ExtNode->getOperand(
I);
242 MAI.Reqs.getAndAddRequirements(SPIRV::OperandCategory::MemoryModelOperand,
244 MAI.Reqs.getAndAddRequirements(SPIRV::OperandCategory::SourceLanguageOperand,
246 MAI.Reqs.getAndAddRequirements(SPIRV::OperandCategory::AddressingModelOperand,
249 if (MAI.Mem == SPIRV::MemoryModel::VulkanKHR)
250 MAI.Reqs.addExtension(SPIRV::Extension::SPV_KHR_vulkan_memory_model);
252 if (!ST->isShader()) {
254 MAI.ExtInstSetMap[
static_cast<unsigned>(
255 SPIRV::InstructionSet::OpenCL_std)] = MAI.getNextIDRegister();
266 if (
UseMI.getOpcode() != SPIRV::OpDecorate &&
267 UseMI.getOpcode() != SPIRV::OpMemberDecorate)
270 for (
unsigned I = 0;
I <
UseMI.getNumOperands(); ++
I) {
288 for (
unsigned i = 0; i <
MI.getNumOperands(); ++i) {
297 unsigned Opcode =
MI.getOpcode();
298 if ((Opcode == SPIRV::OpDecorate) && i >= 2) {
299 unsigned DecorationID =
MI.getOperand(1).getImm();
300 if (DecorationID != SPIRV::Decoration::FuncParamAttr &&
301 DecorationID != SPIRV::Decoration::UserSemantic &&
302 DecorationID != SPIRV::Decoration::CacheControlLoadINTEL &&
303 DecorationID != SPIRV::Decoration::CacheControlStoreINTEL)
309 if (!UseDefReg && MO.
isDef()) {
317 dbgs() <<
"Unexpectedly, no global id found for the operand ";
319 dbgs() <<
"\nInstruction: ";
346 case SPIRV::OpEnqueueKernel:
348 case SPIRV::OpGetKernelNDrangeSubGroupCount:
349 case SPIRV::OpGetKernelNDrangeMaxSubGroupSize:
351 case SPIRV::OpGetKernelWorkGroupSize:
352 case SPIRV::OpGetKernelPreferredWorkGroupSizeMultiple:
361 unsigned Opcode =
MI.getOpcode();
363 case SPIRV::OpTypeForwardPointer:
366 case SPIRV::OpVariable:
367 case SPIRV::OpUntypedVariableKHR:
368 return static_cast<SPIRV::StorageClass::StorageClass
>(
369 MI.getOperand(2).
getImm()) != SPIRV::StorageClass::Function;
370 case SPIRV::OpFunction:
371 case SPIRV::OpFunctionParameter:
374 if (GR->hasConstFunPtr() && Opcode == SPIRV::OpUndef) {
382 if (GR->getFunctionDefinitionByUse(&
MI.getOperand(0))) {
384 unsigned UseOp =
UseMI.getOpcode();
385 if (UseOp == SPIRV::OpConstantFunctionPointerINTEL ||
387 MAI.setSkipEmission(&
MI);
393 if (
UseMI.getOpcode() != SPIRV::OpConstantFunctionPointerINTEL)
399 MAI.setSkipEmission(&
MI);
403 return TII->isTypeDeclInstr(
MI) || TII->isConstantInstr(
MI) ||
404 TII->isInlineAsmDefInstr(
MI);
413void SPIRVModuleAnalysisImpl::visitFunPtrUse(
416 std::map<const Value *, unsigned> &GlobalToGReg,
418 const MachineOperand *OpFunDef = GR->getFunctionDefinitionByUse(FunPtrOp);
421 const MachineInstr *OpDefMI = OpFunDef->
getParent();
424 const MachineRegisterInfo &FunDefMRI = FunDefMF->
getRegInfo();
426 visitDecl(FunDefMRI, SignatureToGReg, GlobalToGReg, FunDefMF, *OpDefMI);
428 }
while (OpDefMI && (OpDefMI->
getOpcode() == SPIRV::OpFunction ||
429 OpDefMI->
getOpcode() == SPIRV::OpFunctionParameter));
431 MCRegister GlobalFunDefReg =
432 MAI.getRegisterAlias(FunDefMF, OpFunDef->
getReg());
434 "Function definition must refer to a global register");
435 MAI.setRegisterAlias(MF, OpReg, GlobalFunDefReg);
440void SPIRVModuleAnalysisImpl::visitDecl(
442 std::map<const Value *, unsigned> &GlobalToGReg,
const MachineFunction *MF,
444 unsigned Opcode =
MI.getOpcode();
447 for (
const MachineOperand &MO :
MI.operands()) {
448 if (!MO.isReg() || MO.isDef())
452 if (Opcode == SPIRV::OpConstantFunctionPointerINTEL &&
454 visitFunPtrUse(OpReg, &
MI.getOperand(2), SignatureToGReg, GlobalToGReg,
459 if (MAI.hasRegisterAlias(MF, MO.getReg()))
463 if (isDeclSection(
MRI, *OpDefMI))
464 visitDecl(
MRI, SignatureToGReg, GlobalToGReg, MF, *OpDefMI);
470 dbgs() <<
"Unexpectedly, no unique definition for the operand ";
472 dbgs() <<
"\nInstruction: ";
477 "No unique definition is found for the virtual register");
481 bool IsFunDef =
false;
482 if (TII->isSpecConstantInstr(
MI)) {
483 GReg = MAI.getNextIDRegister();
485 }
else if (Opcode == SPIRV::OpFunction ||
486 Opcode == SPIRV::OpFunctionParameter) {
487 GReg = handleFunctionOrParameter(MF,
MI, GlobalToGReg, IsFunDef);
488 }
else if (Opcode == SPIRV::OpTypeStruct ||
489 Opcode == SPIRV::OpConstantComposite) {
490 GReg = handleTypeDeclOrConstant(
MI, SignatureToGReg);
491 const MachineInstr *NextInstr =
MI.getNextNode();
493 ((Opcode == SPIRV::OpTypeStruct &&
494 NextInstr->
getOpcode() == SPIRV::OpTypeStructContinuedINTEL) ||
495 (Opcode == SPIRV::OpConstantComposite &&
497 SPIRV::OpConstantCompositeContinuedINTEL))) {
498 MCRegister Tmp = handleTypeDeclOrConstant(*NextInstr, SignatureToGReg);
500 MAI.setSkipEmission(NextInstr);
503 }
else if (TII->isTypeDeclInstr(
MI) || TII->isConstantInstr(
MI) ||
504 TII->isInlineAsmDefInstr(
MI)) {
505 GReg = handleTypeDeclOrConstant(
MI, SignatureToGReg);
506 }
else if (Opcode == SPIRV::OpVariable ||
507 Opcode == SPIRV::OpUntypedVariableKHR) {
508 GReg = handleVariable(MF,
MI, GlobalToGReg);
511 dbgs() <<
"\nInstruction: ";
517 MAI.setRegisterAlias(MF,
MI.getOperand(0).getReg(), GReg);
519 MAI.setSkipEmission(&
MI);
522MCRegister SPIRVModuleAnalysisImpl::handleFunctionOrParameter(
524 std::map<const Value *, unsigned> &GlobalToGReg,
bool &IsFunDef) {
525 const Value *GObj = GR->getGlobalObject(MF,
MI.getOperand(0).getReg());
526 assert(GObj &&
"Unregistered global definition");
530 assert(
F &&
"Expected a reference to a function or an argument");
531 IsFunDef = !
F->isDeclaration();
532 auto [It,
Inserted] = GlobalToGReg.try_emplace(GObj);
535 MCRegister GReg = MAI.getNextIDRegister();
542MCRegister SPIRVModuleAnalysisImpl::handleTypeDeclOrConstant(
545 auto [It,
Inserted] = SignatureToGReg.try_emplace(MISign);
548 MCRegister GReg = MAI.getNextIDRegister();
554MCRegister SPIRVModuleAnalysisImpl::handleVariable(
556 std::map<const Value *, unsigned> &GlobalToGReg) {
557 MAI.GlobalVarList.push_back(&
MI);
558 const Value *GObj = GR->getGlobalObject(MF,
MI.getOperand(0).getReg());
559 assert(GObj &&
"Unregistered global definition");
560 auto [It,
Inserted] = GlobalToGReg.try_emplace(GObj);
563 MCRegister GReg = MAI.getNextIDRegister();
567 MAI.GlobalObjMap[GV] = GReg;
571void SPIRVModuleAnalysisImpl::collectDeclarations(
const Module &M) {
573 std::map<const Value *, unsigned> GlobalToGReg;
579 unsigned PastHeader = 0;
580 for (MachineBasicBlock &
MBB : *MF) {
581 for (MachineInstr &
MI :
MBB) {
582 if (
MI.getNumOperands() == 0)
584 unsigned Opcode =
MI.getOpcode();
585 if (Opcode == SPIRV::OpFunction) {
586 if (PastHeader == 0) {
590 }
else if (Opcode == SPIRV::OpFunctionParameter) {
593 }
else if (PastHeader > 0) {
597 const MachineOperand &DefMO =
MI.getOperand(0);
599 case SPIRV::OpExtension:
600 MAI.Reqs.addExtension(SPIRV::Extension::Extension(DefMO.
getImm()));
601 MAI.setSkipEmission(&
MI);
603 case SPIRV::OpCapability:
604 MAI.Reqs.addCapability(SPIRV::Capability::Capability(DefMO.
getImm()));
605 MAI.setSkipEmission(&
MI);
610 if (DefMO.
isReg() && isDeclSection(
MRI,
MI) &&
611 !MAI.hasRegisterAlias(MF, DefMO.
getReg()))
612 visitDecl(
MRI, SignatureToGReg, GlobalToGReg, MF,
MI);
617 const MachineOperand &InvokeMO =
MI.getOperand(InvokeIdx);
618 if (InvokeMO.
isReg()) {
620 if (!MAI.hasRegisterAlias(MF, InvokeReg)) {
621 if (
const MachineInstr *
DefMI =
625 if (GR->getFunctionDefinitionByUse(FunPtrOp))
626 visitFunPtrUse(InvokeReg, FunPtrOp, SignatureToGReg,
645 if (
MI.getOpcode() == SPIRV::OpDecorate) {
647 auto Dec =
MI.getOperand(1).getImm();
648 if (Dec == SPIRV::Decoration::LinkageAttributes) {
649 auto Lnk =
MI.getOperand(
MI.getNumOperands() - 1).getImm();
650 if (Lnk == SPIRV::LinkageType::Import) {
655 MAI.GlobalObjMap[ImportedFunc] =
656 MAI.getRegisterAlias(
MI.getMF(), Target);
659 }
else if (
MI.getOpcode() == SPIRV::OpFunction) {
662 MCRegister GlobalReg = MAI.getRegisterAlias(
MI.getMF(),
Reg);
664 MAI.GlobalObjMap[
F] = GlobalReg;
676 auto FoundMI = IS.insert(std::move(MISign));
677 if (!FoundMI.second) {
678 if (
MI.getOpcode() == SPIRV::OpDecorate) {
680 "Decoration instructions must have at least 2 operands");
682 "Only OpDecorate instructions can be duplicates");
687 if (
MI.getOperand(1).getImm() != SPIRV::Decoration::FPFastMathMode)
693 assert(OrigMI->getNumOperands() ==
MI.getNumOperands() &&
694 "Original instruction must have the same number of operands");
696 OrigMI->getNumOperands() == 3 &&
697 "FPFastMathMode decoration must have 3 operands for OpDecorate");
698 unsigned OrigFlags = OrigMI->getOperand(2).getImm();
699 unsigned NewFlags =
MI.getOperand(2).getImm();
700 if (OrigFlags == NewFlags)
704 unsigned FinalFlags = OrigFlags | NewFlags;
706 <<
"Warning: Conflicting FPFastMathMode decoration flags "
708 << *OrigMI <<
"Original flags: " << OrigFlags
709 <<
", new flags: " << NewFlags
710 <<
". They will be merged on a best effort basis, but not "
711 "validated. Final flags: "
712 << FinalFlags <<
"\n";
719 assert(
false &&
"No original instruction found for the duplicate "
720 "OpDecorate, but we found one in IS.");
733void SPIRVModuleAnalysisImpl::processOtherInstrs(
const Module &M) {
736 if (
F.isDeclaration())
741 for (MachineBasicBlock &
MBB : *MF)
742 for (MachineInstr &
MI :
MBB) {
743 if (MAI.getSkipEmission(&
MI))
745 const unsigned OpCode =
MI.getOpcode();
746 if (OpCode == SPIRV::OpString) {
748 }
else if (OpCode == SPIRV::OpExtInst &&
MI.getOperand(2).isImm() &&
749 MI.getOperand(2).getImm() ==
750 SPIRV::InstructionSet::
751 NonSemantic_Shader_DebugInfo_100) {
758 MachineOperand Ins =
MI.getOperand(3);
759 namespace NS = SPIRV::NonSemanticExtInst;
760 static constexpr int64_t GlobalNonSemanticDITy[] = {
761 NS::DebugSource, NS::DebugCompilationUnit, NS::DebugInfoNone,
762 NS::DebugTypeBasic, NS::DebugTypePointer};
763 bool IsGlobalDI =
false;
764 for (
unsigned Idx = 0;
Idx < std::size(GlobalNonSemanticDITy); ++
Idx)
765 IsGlobalDI |= Ins.
getImm() == GlobalNonSemanticDITy[
Idx];
768 }
else if (OpCode == SPIRV::OpName || OpCode == SPIRV::OpMemberName) {
770 }
else if (OpCode == SPIRV::OpEntryPoint) {
772 }
else if (TII->isAliasingInstr(
MI)) {
774 }
else if (TII->isDecorationInstr(
MI)) {
775 if (
MI.getOpcode() == SPIRV::OpDecorate &&
776 MI.getOperand(1).getImm() ==
777 static_cast<unsigned>(
778 SPIRV::Decoration::AuxDataInstructionMetadata)) {
779 MAI.setSkipEmission(&
MI);
783 StringSwitch<std::optional<AMDMD>>(Str)
784 .Case(
"amdgpu.no.fine.grained.memory",
785 AMDMD::NoFineGrainedMemory)
786 .Case(
"amdgpu.no.remote.memory", AMDMD::NoRemoteMemory)
787 .Case(
"atomic.ignore.denormal.mode",
788 AMDMD::IgnoreDenormalMode)
789 .Default(std::nullopt);
791 MAI.InstrAuxDataRecords.push_back(
792 {MF,
MI.getOperand(0).getReg(), *MaybeKind});
796 collectFuncNames(
MI, &
F);
797 }
else if (TII->isConstantInstr(
MI)) {
801 }
else if (OpCode == SPIRV::OpFunction) {
802 collectFuncNames(
MI, &
F);
803 }
else if (OpCode == SPIRV::OpTypeForwardPointer) {
811 auto AliasingTier = [](
const MachineInstr *
MI) {
812 switch (
MI->getOpcode()) {
813 case SPIRV::OpAliasDomainDeclINTEL:
815 case SPIRV::OpAliasScopeDeclINTEL:
817 case SPIRV::OpAliasScopeListDeclINTEL:
824 [&](
const MachineInstr *
LHS,
const MachineInstr *
RHS) {
825 return AliasingTier(LHS) < AliasingTier(RHS);
832void SPIRVModuleAnalysisImpl::numberRegistersGlobally(
const Module &M) {
834 if (
F.isDeclaration())
838 for (MachineBasicBlock &
MBB : *MF) {
839 for (MachineInstr &
MI :
MBB) {
840 for (MachineOperand &
Op :
MI.operands()) {
844 if (MAI.hasRegisterAlias(MF,
Reg))
846 MCRegister NewReg = MAI.getNextIDRegister();
847 MAI.setRegisterAlias(MF,
Reg, NewReg);
849 if (
MI.getOpcode() != SPIRV::OpExtInst)
851 auto Set =
MI.getOperand(2).getImm();
852 auto [It,
Inserted] = MAI.ExtInstSetMap.try_emplace(Set);
854 It->second = MAI.getNextIDRegister();
862 SPIRV::OperandCategory::OperandCategory Category,
uint32_t i,
867void SPIRV::RequirementHandler::recursiveAddCapabilities(
869 for (
const auto &Cap : ToPrune) {
873 recursiveAddCapabilities(ImplicitDecls);
878 for (
const auto &Cap : ToAdd) {
879 bool IsNewlyInserted = AllCaps.insert(Cap).second;
880 if (!IsNewlyInserted)
884 recursiveAddCapabilities(ImplicitDecls);
885 MinimalCaps.push_back(Cap);
894 if (Req.
Cap.has_value())
900 if (!MaxVersion.empty() && Req.
MinVer > MaxVersion) {
902 <<
" and <= " << MaxVersion <<
"\n");
906 if (MinVersion.empty() || Req.
MinVer > MinVersion)
911 if (!MinVersion.empty() && Req.
MaxVer < MinVersion) {
913 <<
" and >= " << MinVersion <<
"\n");
917 if (MaxVersion.empty() || Req.
MaxVer < MaxVersion)
925 bool IsSatisfiable =
true;
926 auto TargetVer = ST.getSPIRVVersion();
928 if (!MaxVersion.empty() && !TargetVer.empty() && MaxVersion < TargetVer) {
930 dbgs() <<
"Target SPIR-V version too high for required features\n"
931 <<
"Required max version: " << MaxVersion <<
" target version "
932 << TargetVer <<
"\n");
933 IsSatisfiable =
false;
936 if (!MinVersion.empty() && !TargetVer.empty() && MinVersion > TargetVer) {
937 LLVM_DEBUG(
dbgs() <<
"Target SPIR-V version too low for required features\n"
938 <<
"Required min version: " << MinVersion
939 <<
" target version " << TargetVer <<
"\n");
940 IsSatisfiable =
false;
943 if (!MinVersion.empty() && !MaxVersion.empty() && MinVersion > MaxVersion) {
946 <<
"Version is too low for some features and too high for others.\n"
947 <<
"Required SPIR-V min version: " << MinVersion
948 <<
" required SPIR-V max version " << MaxVersion <<
"\n");
949 IsSatisfiable =
false;
954 AvoidCaps.
S.
insert(SPIRV::Capability::Shader);
956 AvoidCaps.
S.
insert(SPIRV::Capability::Kernel);
958 for (
auto Cap : MinimalCaps) {
959 if (AvailableCaps.contains(Cap) && !AvoidCaps.
S.
contains(Cap))
963 OperandCategory::CapabilityOperand, Cap)
965 IsSatisfiable =
false;
968 for (
auto Ext : AllExtensions) {
969 if (ST.canUseExtension(Ext))
973 OperandCategory::ExtensionOperand, Ext)
975 IsSatisfiable =
false;
984 for (
const auto Cap : ToAdd)
985 if (AvailableCaps.insert(Cap).second)
987 SPIRV::OperandCategory::CapabilityOperand, Cap));
991 const Capability::Capability
ToRemove,
992 const Capability::Capability IfPresent) {
993 if (AllCaps.contains(IfPresent)) {
1003 addAvailableCaps({Capability::Shader, Capability::Linkage, Capability::Int8,
1004 Capability::Int16});
1008 Capability::GroupNonUniformVote,
1009 Capability::GroupNonUniformArithmetic,
1010 Capability::GroupNonUniformBallot,
1011 Capability::GroupNonUniformClustered,
1012 Capability::GroupNonUniformShuffle,
1013 Capability::GroupNonUniformShuffleRelative,
1014 Capability::GroupNonUniformQuad});
1018 Capability::DotProductInput4x8Bit,
1019 Capability::DotProductInput4x8BitPacked,
1020 Capability::DemoteToHelperInvocation});
1023 for (
auto Extension : ST.getAllAvailableExtensions()) {
1029 if (!ST.isShader()) {
1030 initAvailableCapabilitiesForOpenCL(ST);
1034 if (ST.isShader()) {
1035 initAvailableCapabilitiesForVulkan(ST);
1042void RequirementHandler::initAvailableCapabilitiesForOpenCL(
1046 Capability::Kernel, Capability::Vector16,
1047 Capability::Groups, Capability::GenericPointer,
1048 Capability::StorageImageWriteWithoutFormat,
1049 Capability::StorageImageReadWithoutFormat});
1050 if (ST.hasOpenCLFullProfile())
1052 if (ST.hasOpenCLImageSupport()) {
1054 Capability::Image1D, Capability::SampledBuffer,
1055 Capability::ImageBuffer});
1056 if (
ST.isAtLeastOpenCLVer(VersionTuple(2, 0)))
1059 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 1)) &&
1060 ST.isAtLeastOpenCLVer(VersionTuple(2, 2)))
1062 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 4)))
1063 addAvailableCaps({Capability::DenormPreserve, Capability::DenormFlushToZero,
1064 Capability::SignedZeroInfNanPreserve,
1065 Capability::RoundingModeRTE,
1066 Capability::RoundingModeRTZ});
1073void RequirementHandler::initAvailableCapabilitiesForVulkan(
1074 const SPIRVSubtarget &ST) {
1078 Capability::Geometry,
1079 Capability::Float16,
1080 Capability::Float64,
1081 Capability::GroupNonUniform,
1082 Capability::Image1D,
1083 Capability::SampledBuffer,
1084 Capability::ImageBuffer,
1085 Capability::UniformBufferArrayDynamicIndexing,
1086 Capability::SampledImageArrayDynamicIndexing,
1087 Capability::StorageBufferArrayDynamicIndexing,
1088 Capability::StorageImageArrayDynamicIndexing,
1089 Capability::DerivativeControl,
1090 Capability::SampleRateShading,
1092 Capability::ImageQuery,
1093 Capability::ImageGatherExtended,
1094 Capability::Addresses,
1095 Capability::VulkanMemoryModelKHR,
1096 Capability::StorageImageExtendedFormats,
1097 Capability::StorageImageMultisample,
1098 Capability::ImageMSArray});
1100 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 3)) ||
1101 ST.canUseExtension(Extension::SPV_KHR_variable_pointers))
1103 Capability::VariablePointers});
1106 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 3)))
1110 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 5))) {
1112 {Capability::Int64Atomics, Capability::ShaderNonUniformEXT,
1113 Capability::RuntimeDescriptorArrayEXT,
1114 Capability::InputAttachmentArrayDynamicIndexingEXT,
1115 Capability::UniformTexelBufferArrayDynamicIndexingEXT,
1116 Capability::StorageTexelBufferArrayDynamicIndexingEXT,
1117 Capability::UniformBufferArrayNonUniformIndexingEXT,
1118 Capability::SampledImageArrayNonUniformIndexingEXT,
1119 Capability::StorageBufferArrayNonUniformIndexingEXT,
1120 Capability::StorageImageArrayNonUniformIndexingEXT,
1121 Capability::InputAttachmentArrayNonUniformIndexingEXT,
1122 Capability::UniformTexelBufferArrayNonUniformIndexingEXT,
1123 Capability::StorageTexelBufferArrayNonUniformIndexingEXT});
1127 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 6)))
1129 Capability::StorageImageReadWithoutFormat});
1139 SPIRV::Capability::Capability Cap,
1140 SPIRV::Extension::Extension Ext) {
1144 if (!ST.canUseExtension(Ext))
1146 Twine(
"capability ") +
1148 SPIRV::OperandCategory::CapabilityOperand, Cap) +
1149 " requires SPIR-V 1.3 or the following SPIR-V extension: " +
1161 int64_t DecOp =
MI.getOperand(DecIndex).getImm();
1162 auto Dec =
static_cast<SPIRV::Decoration::Decoration
>(DecOp);
1164 SPIRV::OperandCategory::DecorationOperand, Dec, ST, Reqs));
1166 if (Dec == SPIRV::Decoration::BuiltIn) {
1167 int64_t BuiltInOp =
MI.getOperand(DecIndex + 1).getImm();
1168 auto BuiltIn =
static_cast<SPIRV::BuiltIn::BuiltIn
>(BuiltInOp);
1169 if ((BuiltIn == SPIRV::BuiltIn::BaryCoordKHR ||
1170 BuiltIn == SPIRV::BuiltIn::BaryCoordNoPerspKHR) &&
1171 !ST.canUseExtension(
1172 SPIRV::Extension::SPV_KHR_fragment_shader_barycentric))
1174 "Barycentric built-ins require the following SPIR-V extension: "
1175 "SPV_KHR_fragment_shader_barycentric",
1178 case SPIRV::BuiltIn::BaseVertex:
1179 case SPIRV::BuiltIn::BaseInstance:
1181 Reqs, ST, SPIRV::Capability::DrawParameters,
1182 SPIRV::Extension::SPV_KHR_shader_draw_parameters);
1184 case SPIRV::BuiltIn::ViewIndex:
1186 SPIRV::Extension::SPV_KHR_multiview);
1190 SPIRV::OperandCategory::BuiltInOperand, BuiltIn, ST, Reqs));
1193 }
else if (Dec == SPIRV::Decoration::LinkageAttributes) {
1194 int64_t LinkageOp =
MI.getOperand(
MI.getNumOperands() - 1).getImm();
1195 SPIRV::LinkageType::LinkageType LnkType =
1196 static_cast<SPIRV::LinkageType::LinkageType
>(LinkageOp);
1197 if (LnkType == SPIRV::LinkageType::LinkOnceODR)
1198 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_linkonce_odr);
1199 else if (LnkType == SPIRV::LinkageType::WeakAMD) {
1200 Reqs.
addExtension(SPIRV::Extension::SPV_AMD_weak_linkage);
1203 }
else if (Dec == SPIRV::Decoration::CacheControlLoadINTEL ||
1204 Dec == SPIRV::Decoration::CacheControlStoreINTEL) {
1205 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_cache_controls);
1206 }
else if (Dec == SPIRV::Decoration::HostAccessINTEL) {
1207 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_global_variable_host_access);
1208 }
else if (Dec == SPIRV::Decoration::InitModeINTEL ||
1209 Dec == SPIRV::Decoration::ImplementInRegisterMapINTEL) {
1211 SPIRV::Extension::SPV_INTEL_global_variable_fpga_decorations);
1212 }
else if (Dec == SPIRV::Decoration::NonUniformEXT) {
1214 }
else if (Dec == SPIRV::Decoration::FPMaxErrorDecorationINTEL) {
1216 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_fp_max_error);
1217 }
else if (Dec == SPIRV::Decoration::FPFastMathMode) {
1218 if (ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2)) {
1220 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_float_controls2);
1229 assert(
MI.getNumOperands() >= 8 &&
"Insufficient operands for OpTypeImage");
1232 int64_t ImgFormatOp =
MI.getOperand(7).getImm();
1233 auto ImgFormat =
static_cast<SPIRV::ImageFormat::ImageFormat
>(ImgFormatOp);
1237 bool IsArrayed =
MI.getOperand(4).getImm() == 1;
1238 bool IsMultisampled =
MI.getOperand(5).getImm() == 1;
1239 bool NoSampler =
MI.getOperand(6).getImm() == 2;
1242 switch (
MI.getOperand(2).getImm()) {
1243 case SPIRV::Dim::DIM_1D:
1245 : SPIRV::Capability::Sampled1D);
1247 case SPIRV::Dim::DIM_2D:
1248 if (IsMultisampled && NoSampler)
1250 if (IsMultisampled && IsArrayed)
1253 case SPIRV::Dim::DIM_3D:
1255 case SPIRV::Dim::DIM_Cube:
1259 : SPIRV::Capability::SampledCubeArray);
1261 case SPIRV::Dim::DIM_Rect:
1263 : SPIRV::Capability::SampledRect);
1265 case SPIRV::Dim::DIM_Buffer:
1267 : SPIRV::Capability::SampledBuffer);
1269 case SPIRV::Dim::DIM_SubpassData:
1275 if (!ST.isShader()) {
1276 if (
MI.getNumOperands() > 8 &&
1277 MI.getOperand(8).getImm() == SPIRV::AccessQualifier::ReadWrite)
1286 TypeDef->
getOpcode() == SPIRV::OpTypeFloat &&
1298 return MRI.getVRegDef(
MRI.getVRegDef(
Reg)->getOperand(1).getReg());
1302#define ATOM_FLT_REQ_EXT_MSG(ExtName) \
1303 "The atomic float instruction requires the following SPIR-V " \
1304 "extension: SPV_EXT_shader_atomic_float" ExtName
1309 MI.getMF()->getRegInfo().getVRegDef(
MI.getOperand(1).getReg());
1312 if (Rank != 2 && Rank != 4)
1314 "must be a 2-component or 4 component vector");
1319 if (EltTypeDef->
getOpcode() != SPIRV::OpTypeFloat ||
1322 "The element type for the result type of an atomic vector float "
1323 "instruction must be a 16-bit floating-point scalar");
1330 "The element type for the result type of an atomic vector float "
1331 "instruction cannot be a bfloat16 scalar");
1332 if (!ST.canUseExtension(SPIRV::Extension::SPV_NV_shader_atomic_fp16_vector))
1334 "The atomic float16 vector instruction requires the following SPIR-V "
1335 "extension: SPV_NV_shader_atomic_fp16_vector");
1337 Reqs.
addExtension(SPIRV::Extension::SPV_NV_shader_atomic_fp16_vector);
1338 Reqs.
addCapability(SPIRV::Capability::AtomicFloat16VectorNV);
1345 "Expect register operand in atomic float instruction");
1346 Register TypeReg =
MI.getOperand(1).getReg();
1352 if (TypeDef->
getOpcode() != SPIRV::OpTypeFloat)
1354 "floating-point type scalar");
1357 unsigned Op =
MI.getOpcode();
1358 if (
Op == SPIRV::OpAtomicFAddEXT) {
1359 if (!ST.canUseExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float_add))
1361 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float_add);
1365 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics))
1367 "The atomic bfloat16 instruction requires the following SPIR-V "
1368 "extension: SPV_INTEL_16bit_atomics",
1370 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics);
1371 Reqs.
addCapability(SPIRV::Capability::AtomicBFloat16AddINTEL);
1373 if (!ST.canUseExtension(
1374 SPIRV::Extension::SPV_EXT_shader_atomic_float16_add))
1376 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float16_add);
1388 "Unexpected floating-point type width in atomic float instruction");
1391 if (!ST.canUseExtension(
1392 SPIRV::Extension::SPV_EXT_shader_atomic_float_min_max))
1394 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float_min_max);
1398 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics))
1400 "The atomic bfloat16 instruction requires the following SPIR-V "
1401 "extension: SPV_INTEL_16bit_atomics",
1403 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics);
1404 Reqs.
addCapability(SPIRV::Capability::AtomicBFloat16MinMaxINTEL);
1406 Reqs.
addCapability(SPIRV::Capability::AtomicFloat16MinMaxEXT);
1410 Reqs.
addCapability(SPIRV::Capability::AtomicFloat32MinMaxEXT);
1413 Reqs.
addCapability(SPIRV::Capability::AtomicFloat64MinMaxEXT);
1417 "Unexpected floating-point type width in atomic float instruction");
1423 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1427 return Dim == SPIRV::Dim::DIM_Buffer && Sampled == 1;
1431 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1435 return Dim == SPIRV::Dim::DIM_Buffer && Sampled == 2;
1439 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1443 return Dim != SPIRV::Dim::DIM_Buffer && Sampled == 1;
1447 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1451 return Dim == SPIRV::Dim::DIM_SubpassData && Sampled == 2;
1455 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1459 return Dim != SPIRV::Dim::DIM_Buffer && Sampled == 2;
1463 if (SampledImageInst->
getOpcode() != SPIRV::OpTypeSampledImage)
1468 auto *ImageInst =
MRI.getUniqueVRegDef(ImageReg);
1473 for (
const auto &
MI :
MRI.reg_instructions(
Reg)) {
1474 if (
MI.getOpcode() != SPIRV::OpDecorate)
1478 if (Dec == SPIRV::Decoration::NonUniformEXT)
1491 Register ResTypeReg = Instr.getOperand(1).getReg();
1496 if (
StorageClass != SPIRV::StorageClass::StorageClass::UniformConstant &&
1497 StorageClass != SPIRV::StorageClass::StorageClass::Uniform &&
1498 StorageClass != SPIRV::StorageClass::StorageClass::StorageBuffer) {
1505 auto FirstIndexReg = Instr.getOperand(3).getReg();
1506 bool FirstIndexIsConstant =
1509 if (
StorageClass == SPIRV::StorageClass::StorageClass::StorageBuffer) {
1512 SPIRV::Capability::StorageBufferArrayNonUniformIndexingEXT);
1513 else if (!FirstIndexIsConstant)
1515 SPIRV::Capability::StorageBufferArrayDynamicIndexing);
1521 if (PointeeType->
getOpcode() != SPIRV::OpTypeImage &&
1522 PointeeType->
getOpcode() != SPIRV::OpTypeSampledImage &&
1523 PointeeType->
getOpcode() != SPIRV::OpTypeSampler) {
1530 SPIRV::Capability::UniformTexelBufferArrayNonUniformIndexingEXT);
1531 else if (!FirstIndexIsConstant)
1533 SPIRV::Capability::UniformTexelBufferArrayDynamicIndexingEXT);
1537 SPIRV::Capability::InputAttachmentArrayNonUniformIndexingEXT);
1538 else if (!FirstIndexIsConstant)
1540 SPIRV::Capability::InputAttachmentArrayDynamicIndexingEXT);
1544 SPIRV::Capability::StorageTexelBufferArrayNonUniformIndexingEXT);
1545 else if (!FirstIndexIsConstant)
1547 SPIRV::Capability::StorageTexelBufferArrayDynamicIndexingEXT);
1550 PointeeType->
getOpcode() == SPIRV::OpTypeSampler) {
1553 SPIRV::Capability::SampledImageArrayNonUniformIndexingEXT);
1554 else if (!FirstIndexIsConstant)
1556 SPIRV::Capability::SampledImageArrayDynamicIndexing);
1560 SPIRV::Capability::StorageImageArrayNonUniformIndexingEXT);
1561 else if (!FirstIndexIsConstant)
1563 SPIRV::Capability::StorageImageArrayDynamicIndexing);
1568 if (TypeInst->
getOpcode() != SPIRV::OpTypeImage)
1577 if (ST.canUseExtension(SPIRV::Extension::SPV_KHR_integer_dot_product))
1578 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_integer_dot_product);
1582 assert(
MI.getOperand(2).isReg() &&
"Unexpected operand in dot");
1584 ST.getSPIRVGlobalRegistry());
1585 assert(TypeDef &&
"Unexpected type instruction for dot input");
1586 if (TypeDef->
getOpcode() == SPIRV::OpTypeInt) {
1588 Reqs.
addCapability(SPIRV::Capability::DotProductInput4x8BitPacked);
1595 "Dot operand of 8-bit integer type requires 4 components");
1596 Reqs.
addCapability(SPIRV::Capability::DotProductInput4x8Bit);
1612 unsigned AddrSpace = ASOp.
getImm();
1613 if (AddrSpace != SPIRV::StorageClass::UniformConstant) {
1614 if (!ST.canUseExtension(
1616 SPV_EXT_relaxed_printf_string_address_space)) {
1618 "required because printf uses a format string not "
1619 "in constant address space.",
1623 SPIRV::Extension::SPV_EXT_relaxed_printf_string_address_space);
1632 if (
MI.getNumOperands() <= OpIdx)
1634 uint32_t Mask =
MI.getOperand(OpIdx).getImm();
1636 if (Mask & (1U <<
I))
1647 if (ElemTypeDef->
getOpcode() == SPIRV::OpTypePointer &&
1648 ST.canUseExtension(SPIRV::Extension::SPV_INTEL_masked_gather_scatter)) {
1649 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_masked_gather_scatter);
1650 Reqs.
addCapability(SPIRV::Capability::MaskedGatherScatterINTEL);
1658 unsigned Op =
MI.getOpcode();
1660 case SPIRV::OpMemoryModel: {
1661 int64_t Addr =
MI.getOperand(0).getImm();
1664 int64_t Mem =
MI.getOperand(1).getImm();
1669 case SPIRV::OpEntryPoint: {
1670 int64_t Exe =
MI.getOperand(0).getImm();
1675 case SPIRV::OpExecutionMode:
1676 case SPIRV::OpExecutionModeId: {
1677 int64_t Exe =
MI.getOperand(1).getImm();
1682 case SPIRV::OpTypeMatrix:
1685 case SPIRV::OpTypeInt: {
1686 unsigned BitWidth =
MI.getOperand(1).getImm();
1694 ST.canUseExtension(SPIRV::Extension::SPV_INTEL_int4)) {
1698 if (!ST.canUseExtension(
1699 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_integers))
1701 "OpTypeInt type with a width other than 8, 16, 32 or 64 bits "
1702 "requires the following SPIR-V extension: "
1703 "SPV_ALTERA_arbitrary_precision_integers");
1705 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_integers);
1706 Reqs.
addCapability(SPIRV::Capability::ArbitraryPrecisionIntegersALTERA);
1710 case SPIRV::OpDot: {
1714 Reqs.
addCapability(SPIRV::Capability::BFloat16DotProductKHR);
1717 case SPIRV::OpTypeFloat: {
1718 unsigned BitWidth =
MI.getOperand(1).getImm();
1723 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_bfloat16))
1725 "following SPIR-V extension: SPV_KHR_bfloat16",
1735 case SPIRV::OpTypeVector: {
1736 unsigned NumComponents =
MI.getOperand(2).getImm();
1737 if (NumComponents == 8 || NumComponents == 16)
1742 "OpTypeVector with " +
Twine(NumComponents) +
1743 " components requires the following SPIR-V extension: "
1744 "SPV_EXT_long_vector");
1749 case SPIRV::OpTypeVectorIdEXT: {
1750 if (!ST.canUseExtension(SPIRV::Extension::SPV_EXT_long_vector))
1752 "extension: SPV_EXT_long_vector extension");
1753 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_long_vector);
1758 case SPIRV::OpTypePointer: {
1759 auto SC =
MI.getOperand(1).getImm();
1770 (TypeDef->
getOpcode() == SPIRV::OpTypeFloat) &&
1775 case SPIRV::OpExtInst: {
1776 if (
MI.getOperand(2).getImm() ==
1777 static_cast<int64_t
>(
1778 SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100)) {
1779 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_non_semantic_info);
1782 if (
MI.getOperand(3).getImm() ==
1783 static_cast<int64_t
>(SPIRV::OpenCLExtInst::printf)) {
1787 if (
MI.getOperand(2).getImm() ==
1788 static_cast<int64_t
>(SPIRV::InstructionSet::OpenCL_std)) {
1794 if (TypeDef && TypeDef->getOpcode() == SPIRV::OpTypeVector)
1795 TypeDef =
MRI.getVRegDef(TypeDef->getOperand(1).getReg());
1800 bool UsesBFloat16 = IsBFloat16(
MRI.getVRegDef(
MI.getOperand(1).getReg()));
1801 for (
unsigned I = 4,
E =
MI.getNumOperands();
I <
E && !UsesBFloat16;
1810 if (!ST.canUseExtension(
1811 SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic)) {
1813 MI,
"OpenCL Extended instructions with bfloat16 require the "
1814 "following SPIR-V extension: SPV_INTEL_bfloat16_arithmetic");
1817 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic);
1818 Reqs.
addCapability(SPIRV::Capability::BFloat16ArithmeticINTEL);
1823 case SPIRV::OpAliasDomainDeclINTEL:
1824 case SPIRV::OpAliasScopeDeclINTEL:
1825 case SPIRV::OpAliasScopeListDeclINTEL: {
1826 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_memory_access_aliasing);
1827 Reqs.
addCapability(SPIRV::Capability::MemoryAccessAliasingINTEL);
1830 case SPIRV::OpBitReverse:
1831 case SPIRV::OpBitFieldInsert:
1832 case SPIRV::OpBitFieldSExtract:
1833 case SPIRV::OpBitFieldUExtract:
1834 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_bit_instructions)) {
1838 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_bit_instructions);
1841 case SPIRV::OpTypeRuntimeArray:
1844 case SPIRV::OpTypeOpaque:
1845 case SPIRV::OpTypeEvent:
1848 case SPIRV::OpTypePipe:
1849 case SPIRV::OpTypeReserveId:
1852 case SPIRV::OpTypeDeviceEvent:
1853 case SPIRV::OpTypeQueue:
1854 case SPIRV::OpBuildNDRange:
1855 case SPIRV::OpEnqueueKernel:
1856 case SPIRV::OpGetKernelNDrangeSubGroupCount:
1857 case SPIRV::OpGetKernelNDrangeMaxSubGroupSize:
1858 case SPIRV::OpGetKernelWorkGroupSize:
1859 case SPIRV::OpGetKernelPreferredWorkGroupSizeMultiple:
1862 case SPIRV::OpDecorate:
1863 case SPIRV::OpDecorateId:
1864 case SPIRV::OpDecorateString:
1867 case SPIRV::OpMemberDecorate:
1868 case SPIRV::OpMemberDecorateString:
1871 case SPIRV::OpInBoundsPtrAccessChain:
1874 case SPIRV::OpConstantSampler:
1877 case SPIRV::OpInBoundsAccessChain:
1878 case SPIRV::OpAccessChain:
1881 case SPIRV::OpTypeImage:
1884 case SPIRV::OpTypeSampler:
1885 if (!ST.isShader()) {
1889 case SPIRV::OpTypeForwardPointer:
1893 case SPIRV::OpAtomicFlagTestAndSet:
1894 case SPIRV::OpAtomicLoad:
1895 case SPIRV::OpAtomicStore:
1896 case SPIRV::OpAtomicExchange:
1897 case SPIRV::OpAtomicCompareExchange:
1898 case SPIRV::OpAtomicCompareExchangeWeak:
1899 case SPIRV::OpAtomicIIncrement:
1900 case SPIRV::OpAtomicIDecrement:
1901 case SPIRV::OpAtomicIAdd:
1902 case SPIRV::OpAtomicISub:
1903 case SPIRV::OpAtomicUMin:
1904 case SPIRV::OpAtomicUMax:
1905 case SPIRV::OpAtomicSMin:
1906 case SPIRV::OpAtomicSMax:
1907 case SPIRV::OpAtomicAnd:
1908 case SPIRV::OpAtomicOr:
1909 case SPIRV::OpAtomicXor: {
1912 if (
Op == SPIRV::OpAtomicStore) {
1915 ST.getSPIRVGlobalRegistry());
1916 assert(TypeDef &&
"Unexpected type instruction for OpAtomicStore");
1918 assert(
MI.getOperand(1).isReg() &&
"Unexpected operand in atomic");
1919 TypeDef =
MRI.getVRegDef(
MI.getOperand(1).getReg());
1922 if (TypeDef->
getOpcode() == SPIRV::OpTypeInt) {
1927 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics))
1929 "16-bit integer atomic operations require the following SPIR-V "
1930 "extension: SPV_INTEL_16bit_atomics",
1932 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics);
1934 case SPIRV::OpAtomicLoad:
1935 case SPIRV::OpAtomicStore:
1936 case SPIRV::OpAtomicExchange:
1937 case SPIRV::OpAtomicCompareExchange:
1938 case SPIRV::OpAtomicCompareExchangeWeak:
1940 SPIRV::Capability::AtomicInt16CompareExchangeINTEL);
1948 if (
is_contained({SPIRV::OpAtomicLoad, SPIRV::OpAtomicStore,
1949 SPIRV::OpAtomicExchange},
1951 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics))
1953 "The atomic bfloat16 instruction requires the following SPIR-V "
1954 "extension: SPV_INTEL_16bit_atomics",
1956 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics);
1957 Reqs.
addCapability(SPIRV::Capability::AtomicBFloat16LoadStoreINTEL);
1962 case SPIRV::OpGroupNonUniformIAdd:
1963 case SPIRV::OpGroupNonUniformFAdd:
1964 case SPIRV::OpGroupNonUniformIMul:
1965 case SPIRV::OpGroupNonUniformFMul:
1966 case SPIRV::OpGroupNonUniformSMin:
1967 case SPIRV::OpGroupNonUniformUMin:
1968 case SPIRV::OpGroupNonUniformFMin:
1969 case SPIRV::OpGroupNonUniformSMax:
1970 case SPIRV::OpGroupNonUniformUMax:
1971 case SPIRV::OpGroupNonUniformFMax:
1972 case SPIRV::OpGroupNonUniformBitwiseAnd:
1973 case SPIRV::OpGroupNonUniformBitwiseOr:
1974 case SPIRV::OpGroupNonUniformBitwiseXor:
1975 case SPIRV::OpGroupNonUniformLogicalAnd:
1976 case SPIRV::OpGroupNonUniformLogicalOr:
1977 case SPIRV::OpGroupNonUniformLogicalXor: {
1979 int64_t GroupOp =
MI.getOperand(3).getImm();
1981 case SPIRV::GroupOperation::Reduce:
1982 case SPIRV::GroupOperation::InclusiveScan:
1983 case SPIRV::GroupOperation::ExclusiveScan:
1984 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformArithmetic);
1986 case SPIRV::GroupOperation::ClusteredReduce:
1987 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformClustered);
1989 case SPIRV::GroupOperation::PartitionedReduceNV:
1990 case SPIRV::GroupOperation::PartitionedInclusiveScanNV:
1991 case SPIRV::GroupOperation::PartitionedExclusiveScanNV:
1992 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformPartitionedNV);
1997 case SPIRV::OpGroupNonUniformQuadSwap:
2000 case SPIRV::OpImageQueryLod:
2003 case SPIRV::OpImageQuerySize:
2004 case SPIRV::OpImageQuerySizeLod:
2005 case SPIRV::OpImageQueryLevels:
2006 case SPIRV::OpImageQuerySamples:
2010 case SPIRV::OpImageQueryFormat: {
2011 Register ResultReg =
MI.getOperand(0).getReg();
2013 static const unsigned CompareOps[] = {
2014 SPIRV::OpIEqual, SPIRV::OpINotEqual,
2015 SPIRV::OpUGreaterThan, SPIRV::OpUGreaterThanEqual,
2016 SPIRV::OpULessThan, SPIRV::OpULessThanEqual,
2017 SPIRV::OpSGreaterThan, SPIRV::OpSGreaterThanEqual,
2018 SPIRV::OpSLessThan, SPIRV::OpSLessThanEqual};
2020 auto CheckAndAddExtension = [&](int64_t ImmVal) {
2021 if (ImmVal == 4323 || ImmVal == 4324) {
2022 if (ST.canUseExtension(SPIRV::Extension::SPV_EXT_image_raw10_raw12))
2023 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_image_raw10_raw12);
2026 "SPV_EXT_image_raw10_raw12 extension");
2031 unsigned Opc = UseInst.getOpcode();
2033 if (
Opc == SPIRV::OpSwitch) {
2036 CheckAndAddExtension(
Op.getImm());
2038 for (
unsigned i = 1; i < UseInst.getNumOperands(); ++i) {
2041 if (ConstInst && ConstInst->
getOpcode() == SPIRV::OpConstantI) {
2044 CheckAndAddExtension(ImmVal);
2052 case SPIRV::OpGroupNonUniformShuffle:
2053 case SPIRV::OpGroupNonUniformShuffleXor:
2054 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformShuffle);
2056 case SPIRV::OpGroupNonUniformShuffleUp:
2057 case SPIRV::OpGroupNonUniformShuffleDown:
2058 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformShuffleRelative);
2060 case SPIRV::OpGroupAll:
2061 case SPIRV::OpGroupAny:
2062 case SPIRV::OpGroupBroadcast:
2063 case SPIRV::OpGroupIAdd:
2064 case SPIRV::OpGroupFAdd:
2065 case SPIRV::OpGroupFMin:
2066 case SPIRV::OpGroupUMin:
2067 case SPIRV::OpGroupSMin:
2068 case SPIRV::OpGroupFMax:
2069 case SPIRV::OpGroupUMax:
2070 case SPIRV::OpGroupSMax:
2073 case SPIRV::OpGroupNonUniformElect:
2076 case SPIRV::OpGroupNonUniformAll:
2077 case SPIRV::OpGroupNonUniformAny:
2078 case SPIRV::OpGroupNonUniformAllEqual:
2081 case SPIRV::OpGroupNonUniformBroadcast:
2082 case SPIRV::OpGroupNonUniformBroadcastFirst:
2083 case SPIRV::OpGroupNonUniformBallot:
2084 case SPIRV::OpGroupNonUniformInverseBallot:
2085 case SPIRV::OpGroupNonUniformBallotBitExtract:
2086 case SPIRV::OpGroupNonUniformBallotBitCount:
2087 case SPIRV::OpGroupNonUniformBallotFindLSB:
2088 case SPIRV::OpGroupNonUniformBallotFindMSB:
2089 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformBallot);
2091 case SPIRV::OpSubgroupShuffleINTEL:
2092 case SPIRV::OpSubgroupShuffleDownINTEL:
2093 case SPIRV::OpSubgroupShuffleUpINTEL:
2094 case SPIRV::OpSubgroupShuffleXorINTEL:
2095 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {
2096 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_subgroups);
2097 Reqs.
addCapability(SPIRV::Capability::SubgroupShuffleINTEL);
2100 case SPIRV::OpSubgroupBlockReadINTEL:
2101 case SPIRV::OpSubgroupBlockWriteINTEL:
2102 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {
2103 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_subgroups);
2104 Reqs.
addCapability(SPIRV::Capability::SubgroupBufferBlockIOINTEL);
2107 case SPIRV::OpSubgroupImageBlockReadINTEL:
2108 case SPIRV::OpSubgroupImageBlockWriteINTEL:
2109 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {
2110 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_subgroups);
2111 Reqs.
addCapability(SPIRV::Capability::SubgroupImageBlockIOINTEL);
2114 case SPIRV::OpSubgroupImageMediaBlockReadINTEL:
2115 case SPIRV::OpSubgroupImageMediaBlockWriteINTEL:
2116 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_media_block_io)) {
2117 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_media_block_io);
2118 Reqs.
addCapability(SPIRV::Capability::SubgroupImageMediaBlockIOINTEL);
2121 case SPIRV::OpAssumeTrueKHR:
2122 case SPIRV::OpExpectKHR:
2123 if (ST.canUseExtension(SPIRV::Extension::SPV_KHR_expect_assume)) {
2124 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_expect_assume);
2128 case SPIRV::OpFmaKHR:
2129 if (ST.canUseExtension(SPIRV::Extension::SPV_KHR_fma)) {
2134 case SPIRV::OpPtrCastToCrossWorkgroupINTEL:
2135 case SPIRV::OpCrossWorkgroupCastToPtrINTEL:
2136 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_usm_storage_classes)) {
2137 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_usm_storage_classes);
2138 Reqs.
addCapability(SPIRV::Capability::USMStorageClassesINTEL);
2141 case SPIRV::OpConstantFunctionPointerINTEL:
2142 case SPIRV::OpFunctionPointerCallINTEL:
2143 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_function_pointers)) {
2144 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_function_pointers);
2145 Reqs.
addCapability(SPIRV::Capability::FunctionPointersINTEL);
2148 case SPIRV::OpGroupNonUniformRotateKHR:
2149 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_subgroup_rotate))
2151 "following SPIR-V extension: SPV_KHR_subgroup_rotate",
2153 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_subgroup_rotate);
2154 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformRotateKHR);
2157 case SPIRV::OpFixedCosALTERA:
2158 case SPIRV::OpFixedSinALTERA:
2159 case SPIRV::OpFixedCosPiALTERA:
2160 case SPIRV::OpFixedSinPiALTERA:
2161 case SPIRV::OpFixedExpALTERA:
2162 case SPIRV::OpFixedLogALTERA:
2163 case SPIRV::OpFixedRecipALTERA:
2164 case SPIRV::OpFixedSqrtALTERA:
2165 case SPIRV::OpFixedSinCosALTERA:
2166 case SPIRV::OpFixedSinCosPiALTERA:
2167 case SPIRV::OpFixedRsqrtALTERA:
2168 if (!ST.canUseExtension(
2169 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_fixed_point))
2171 "following SPIR-V extension: "
2172 "SPV_ALTERA_arbitrary_precision_fixed_point",
2175 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_fixed_point);
2176 Reqs.
addCapability(SPIRV::Capability::ArbitraryPrecisionFixedPointALTERA);
2178 case SPIRV::OpGroupIMulKHR:
2179 case SPIRV::OpGroupFMulKHR:
2180 case SPIRV::OpGroupBitwiseAndKHR:
2181 case SPIRV::OpGroupBitwiseOrKHR:
2182 case SPIRV::OpGroupBitwiseXorKHR:
2183 case SPIRV::OpGroupLogicalAndKHR:
2184 case SPIRV::OpGroupLogicalOrKHR:
2185 case SPIRV::OpGroupLogicalXorKHR:
2186 if (ST.canUseExtension(
2187 SPIRV::Extension::SPV_KHR_uniform_group_instructions)) {
2188 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_uniform_group_instructions);
2189 Reqs.
addCapability(SPIRV::Capability::GroupUniformArithmeticKHR);
2192 case SPIRV::OpReadClockKHR:
2193 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_shader_clock))
2195 "following SPIR-V extension: SPV_KHR_shader_clock",
2197 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_shader_clock);
2200 case SPIRV::OpAbortKHR:
2201 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_abort))
2203 "following SPIR-V extension: SPV_KHR_abort",
2208 case SPIRV::OpPoisonKHR:
2209 case SPIRV::OpFreezeKHR:
2210 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_poison_freeze))
2212 "following SPIR-V extension: SPV_KHR_poison_freeze",
2214 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_poison_freeze);
2217 case SPIRV::OpAtomicFAddEXT:
2218 case SPIRV::OpAtomicFMinEXT:
2219 case SPIRV::OpAtomicFMaxEXT:
2222 case SPIRV::OpConvertBF16ToFINTEL:
2223 case SPIRV::OpConvertFToBF16INTEL:
2224 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bfloat16_conversion)) {
2225 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bfloat16_conversion);
2226 Reqs.
addCapability(SPIRV::Capability::BFloat16ConversionINTEL);
2229 case SPIRV::OpRoundFToTF32INTEL:
2230 if (ST.canUseExtension(
2231 SPIRV::Extension::SPV_INTEL_tensor_float32_conversion)) {
2232 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_tensor_float32_conversion);
2233 Reqs.
addCapability(SPIRV::Capability::TensorFloat32RoundingINTEL);
2236 case SPIRV::OpVariableLengthArrayINTEL:
2237 case SPIRV::OpSaveMemoryINTEL:
2238 case SPIRV::OpRestoreMemoryINTEL:
2239 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_variable_length_array)) {
2240 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_variable_length_array);
2241 Reqs.
addCapability(SPIRV::Capability::VariableLengthArrayINTEL);
2244 case SPIRV::OpUntypedVariableLengthArrayINTEL:
2245 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_variable_length_array)) {
2246 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_variable_length_array);
2247 Reqs.
addCapability(SPIRV::Capability::UntypedVariableLengthArrayINTEL);
2250 case SPIRV::OpAsmTargetINTEL:
2251 case SPIRV::OpAsmINTEL:
2252 case SPIRV::OpAsmCallINTEL:
2253 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_inline_assembly)) {
2254 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_inline_assembly);
2258 case SPIRV::OpTypeCooperativeMatrixKHR: {
2259 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix))
2261 "OpTypeCooperativeMatrixKHR type requires the "
2262 "following SPIR-V extension: SPV_KHR_cooperative_matrix",
2264 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix);
2265 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixKHR);
2269 Reqs.
addCapability(SPIRV::Capability::BFloat16CooperativeMatrixKHR);
2272 case SPIRV::OpArithmeticFenceEXT:
2273 if (!ST.canUseExtension(SPIRV::Extension::SPV_EXT_arithmetic_fence))
2275 "following SPIR-V extension: SPV_EXT_arithmetic_fence",
2277 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_arithmetic_fence);
2280 case SPIRV::OpControlBarrierArriveINTEL:
2281 case SPIRV::OpControlBarrierWaitINTEL:
2282 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_split_barrier)) {
2283 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_split_barrier);
2287 case SPIRV::OpCooperativeMatrixMulAddKHR: {
2288 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix))
2290 "following SPIR-V extension: "
2291 "SPV_KHR_cooperative_matrix",
2293 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix);
2294 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixKHR);
2295 constexpr unsigned MulAddMaxSize = 6;
2296 if (
MI.getNumOperands() != MulAddMaxSize)
2298 const int64_t CoopOperands =
MI.getOperand(MulAddMaxSize - 1).getImm();
2300 SPIRV::CooperativeMatrixOperands::MatrixAAndBTF32ComponentsINTEL) {
2301 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
2303 "require the following SPIR-V extension: "
2304 "SPV_INTEL_joint_matrix",
2306 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2308 SPIRV::Capability::CooperativeMatrixTF32ComponentTypeINTEL);
2311 MatrixAAndBBFloat16ComponentsINTEL ||
2313 SPIRV::CooperativeMatrixOperands::MatrixCBFloat16ComponentsINTEL ||
2315 MatrixResultBFloat16ComponentsINTEL) {
2316 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
2318 "require the following SPIR-V extension: "
2319 "SPV_INTEL_joint_matrix",
2321 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2323 SPIRV::Capability::CooperativeMatrixBFloat16ComponentTypeINTEL);
2327 case SPIRV::OpCooperativeMatrixLoadKHR:
2328 case SPIRV::OpCooperativeMatrixStoreKHR:
2329 case SPIRV::OpCooperativeMatrixLoadCheckedINTEL:
2330 case SPIRV::OpCooperativeMatrixStoreCheckedINTEL:
2331 case SPIRV::OpCooperativeMatrixPrefetchINTEL: {
2332 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix))
2334 "following SPIR-V extension: "
2335 "SPV_KHR_cooperative_matrix",
2337 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix);
2338 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixKHR);
2344 case SPIRV::OpCooperativeMatrixLoadKHR:
2347 case SPIRV::OpCooperativeMatrixStoreKHR:
2350 case SPIRV::OpCooperativeMatrixLoadCheckedINTEL:
2353 case SPIRV::OpCooperativeMatrixStoreCheckedINTEL:
2354 case SPIRV::OpCooperativeMatrixPrefetchINTEL:
2360 Register RegLayout =
MI.getOperand(LayoutNum).getReg();
2363 if (MILayout->
getOpcode() == SPIRV::OpConstantI) {
2366 static_cast<unsigned>(SPIRV::CooperativeMatrixLayout::PackedINTEL)) {
2367 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
2369 "extension: SPV_INTEL_joint_matrix",
2371 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2372 Reqs.
addCapability(SPIRV::Capability::PackedCooperativeMatrixINTEL);
2377 if (
Op == SPIRV::OpCooperativeMatrixLoadKHR ||
2378 Op == SPIRV::OpCooperativeMatrixStoreKHR)
2381 std::string InstName;
2383 case SPIRV::OpCooperativeMatrixPrefetchINTEL:
2384 InstName =
"OpCooperativeMatrixPrefetchINTEL";
2386 case SPIRV::OpCooperativeMatrixLoadCheckedINTEL:
2387 InstName =
"OpCooperativeMatrixLoadCheckedINTEL";
2389 case SPIRV::OpCooperativeMatrixStoreCheckedINTEL:
2390 InstName =
"OpCooperativeMatrixStoreCheckedINTEL";
2394 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix)) {
2395 const std::string ErrorMsg =
2396 InstName +
" instruction requires the "
2397 "following SPIR-V extension: SPV_INTEL_joint_matrix";
2400 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2401 if (
Op == SPIRV::OpCooperativeMatrixPrefetchINTEL) {
2402 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixPrefetchINTEL);
2406 SPIRV::Capability::CooperativeMatrixCheckedInstructionsINTEL);
2409 case SPIRV::OpCooperativeMatrixConstructCheckedINTEL:
2410 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
2412 "instructions require the following SPIR-V extension: "
2413 "SPV_INTEL_joint_matrix",
2415 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2417 SPIRV::Capability::CooperativeMatrixCheckedInstructionsINTEL);
2419 case SPIRV::OpReadPipeBlockingALTERA:
2420 case SPIRV::OpWritePipeBlockingALTERA:
2421 if (ST.canUseExtension(SPIRV::Extension::SPV_ALTERA_blocking_pipes)) {
2422 Reqs.
addExtension(SPIRV::Extension::SPV_ALTERA_blocking_pipes);
2426 case SPIRV::OpCooperativeMatrixGetElementCoordINTEL:
2427 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
2429 "following SPIR-V extension: SPV_INTEL_joint_matrix",
2431 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2433 SPIRV::Capability::CooperativeMatrixInvocationInstructionsINTEL);
2435 case SPIRV::OpConvertHandleToImageINTEL:
2436 case SPIRV::OpConvertHandleToSamplerINTEL:
2437 case SPIRV::OpConvertHandleToSampledImageINTEL: {
2438 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bindless_images))
2440 "instructions require the following SPIR-V extension: "
2441 "SPV_INTEL_bindless_images",
2444 SPIRV::AddressingModel::AddressingModel AddrModel = MAI.
Addr;
2446 if (
Op == SPIRV::OpConvertHandleToImageINTEL &&
2447 TyDef->
getOpcode() != SPIRV::OpTypeImage) {
2449 "OpConvertHandleToImageINTEL",
2451 }
else if (
Op == SPIRV::OpConvertHandleToSamplerINTEL &&
2452 TyDef->
getOpcode() != SPIRV::OpTypeSampler) {
2454 "OpConvertHandleToSamplerINTEL",
2456 }
else if (
Op == SPIRV::OpConvertHandleToSampledImageINTEL &&
2457 TyDef->
getOpcode() != SPIRV::OpTypeSampledImage) {
2459 "OpConvertHandleToSampledImageINTEL",
2465 if (!(Bitwidth == 32 && AddrModel == SPIRV::AddressingModel::Physical32) &&
2466 !(Bitwidth == 64 && AddrModel == SPIRV::AddressingModel::Physical64)) {
2468 "Parameter value must be a 32-bit scalar in case of "
2469 "Physical32 addressing model or a 64-bit scalar in case of "
2470 "Physical64 addressing model",
2473 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bindless_images);
2477 case SPIRV::OpSubgroup2DBlockLoadINTEL:
2478 case SPIRV::OpSubgroup2DBlockLoadTransposeINTEL:
2479 case SPIRV::OpSubgroup2DBlockLoadTransformINTEL:
2480 case SPIRV::OpSubgroup2DBlockPrefetchINTEL:
2481 case SPIRV::OpSubgroup2DBlockStoreINTEL: {
2482 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_2d_block_io))
2484 "Prefetch/Store]INTEL instructions require the "
2485 "following SPIR-V extension: SPV_INTEL_2d_block_io",
2487 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_2d_block_io);
2488 Reqs.
addCapability(SPIRV::Capability::Subgroup2DBlockIOINTEL);
2490 if (
Op == SPIRV::OpSubgroup2DBlockLoadTransposeINTEL) {
2491 Reqs.
addCapability(SPIRV::Capability::Subgroup2DBlockTransposeINTEL);
2494 if (
Op == SPIRV::OpSubgroup2DBlockLoadTransformINTEL) {
2495 Reqs.
addCapability(SPIRV::Capability::Subgroup2DBlockTransformINTEL);
2500 case SPIRV::OpKill: {
2503 case SPIRV::OpDemoteToHelperInvocation:
2504 Reqs.
addCapability(SPIRV::Capability::DemoteToHelperInvocation);
2506 if (ST.canUseExtension(
2507 SPIRV::Extension::SPV_EXT_demote_to_helper_invocation)) {
2510 SPIRV::Extension::SPV_EXT_demote_to_helper_invocation);
2515 case SPIRV::OpSUDot:
2516 case SPIRV::OpSDotAccSat:
2517 case SPIRV::OpUDotAccSat:
2518 case SPIRV::OpSUDotAccSat:
2521 case SPIRV::OpImageSampleImplicitLod:
2522 case SPIRV::OpImageFetch:
2526 case SPIRV::OpImageSampleExplicitLod:
2529 case SPIRV::OpImageSampleDrefImplicitLod:
2530 case SPIRV::OpImageSampleDrefExplicitLod:
2531 case SPIRV::OpImageDrefGather:
2532 case SPIRV::OpImageGather:
2536 case SPIRV::OpImageRead: {
2537 Register ImageReg =
MI.getOperand(2).getReg();
2538 SPIRVTypeInst TypeDef = ST.getSPIRVGlobalRegistry()->getResultType(
2547 Reqs.
addCapability(SPIRV::Capability::StorageImageReadWithoutFormat);
2550 case SPIRV::OpImageWrite: {
2551 Register ImageReg =
MI.getOperand(0).getReg();
2552 SPIRVTypeInst TypeDef = ST.getSPIRVGlobalRegistry()->getResultType(
2561 Reqs.
addCapability(SPIRV::Capability::StorageImageWriteWithoutFormat);
2564 case SPIRV::OpTypeStructContinuedINTEL:
2565 case SPIRV::OpConstantCompositeContinuedINTEL:
2566 case SPIRV::OpSpecConstantCompositeContinuedINTEL:
2567 case SPIRV::OpCompositeConstructContinuedINTEL: {
2568 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_long_composites))
2570 "Continued instructions require the "
2571 "following SPIR-V extension: SPV_INTEL_long_composites",
2573 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_long_composites);
2577 case SPIRV::OpArbitraryFloatEQALTERA:
2578 case SPIRV::OpArbitraryFloatGEALTERA:
2579 case SPIRV::OpArbitraryFloatGTALTERA:
2580 case SPIRV::OpArbitraryFloatLEALTERA:
2581 case SPIRV::OpArbitraryFloatLTALTERA:
2582 case SPIRV::OpArbitraryFloatCbrtALTERA:
2583 case SPIRV::OpArbitraryFloatCosALTERA:
2584 case SPIRV::OpArbitraryFloatCosPiALTERA:
2585 case SPIRV::OpArbitraryFloatExp10ALTERA:
2586 case SPIRV::OpArbitraryFloatExp2ALTERA:
2587 case SPIRV::OpArbitraryFloatExpALTERA:
2588 case SPIRV::OpArbitraryFloatExpm1ALTERA:
2589 case SPIRV::OpArbitraryFloatHypotALTERA:
2590 case SPIRV::OpArbitraryFloatLog10ALTERA:
2591 case SPIRV::OpArbitraryFloatLog1pALTERA:
2592 case SPIRV::OpArbitraryFloatLog2ALTERA:
2593 case SPIRV::OpArbitraryFloatLogALTERA:
2594 case SPIRV::OpArbitraryFloatRecipALTERA:
2595 case SPIRV::OpArbitraryFloatSinCosALTERA:
2596 case SPIRV::OpArbitraryFloatSinCosPiALTERA:
2597 case SPIRV::OpArbitraryFloatSinALTERA:
2598 case SPIRV::OpArbitraryFloatSinPiALTERA:
2599 case SPIRV::OpArbitraryFloatSqrtALTERA:
2600 case SPIRV::OpArbitraryFloatACosALTERA:
2601 case SPIRV::OpArbitraryFloatACosPiALTERA:
2602 case SPIRV::OpArbitraryFloatAddALTERA:
2603 case SPIRV::OpArbitraryFloatASinALTERA:
2604 case SPIRV::OpArbitraryFloatASinPiALTERA:
2605 case SPIRV::OpArbitraryFloatATan2ALTERA:
2606 case SPIRV::OpArbitraryFloatATanALTERA:
2607 case SPIRV::OpArbitraryFloatATanPiALTERA:
2608 case SPIRV::OpArbitraryFloatCastFromIntALTERA:
2609 case SPIRV::OpArbitraryFloatCastALTERA:
2610 case SPIRV::OpArbitraryFloatCastToIntALTERA:
2611 case SPIRV::OpArbitraryFloatDivALTERA:
2612 case SPIRV::OpArbitraryFloatMulALTERA:
2613 case SPIRV::OpArbitraryFloatPowALTERA:
2614 case SPIRV::OpArbitraryFloatPowNALTERA:
2615 case SPIRV::OpArbitraryFloatPowRALTERA:
2616 case SPIRV::OpArbitraryFloatRSqrtALTERA:
2617 case SPIRV::OpArbitraryFloatSubALTERA: {
2618 if (!ST.canUseExtension(
2619 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_floating_point))
2621 "Floating point instructions can't be translated correctly without "
2622 "enabled SPV_ALTERA_arbitrary_precision_floating_point extension!",
2625 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_floating_point);
2627 SPIRV::Capability::ArbitraryPrecisionFloatingPointALTERA);
2630 case SPIRV::OpSubgroupMatrixMultiplyAccumulateINTEL: {
2631 if (!ST.canUseExtension(
2632 SPIRV::Extension::SPV_INTEL_subgroup_matrix_multiply_accumulate))
2634 "OpSubgroupMatrixMultiplyAccumulateINTEL instruction requires the "
2636 "extension: SPV_INTEL_subgroup_matrix_multiply_accumulate",
2639 SPIRV::Extension::SPV_INTEL_subgroup_matrix_multiply_accumulate);
2641 SPIRV::Capability::SubgroupMatrixMultiplyAccumulateINTEL);
2644 case SPIRV::OpBitwiseFunctionINTEL: {
2645 if (!ST.canUseExtension(
2646 SPIRV::Extension::SPV_INTEL_ternary_bitwise_function))
2648 "OpBitwiseFunctionINTEL instruction requires the following SPIR-V "
2649 "extension: SPV_INTEL_ternary_bitwise_function",
2651 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_ternary_bitwise_function);
2652 Reqs.
addCapability(SPIRV::Capability::TernaryBitwiseFunctionINTEL);
2655 case SPIRV::OpCopyMemorySized: {
2660 case SPIRV::OpTypeUntypedPointerKHR:
2662 MI.getOperand(1).getImm(), ST);
2664 case SPIRV::OpUntypedVariableKHR:
2665 case SPIRV::OpUntypedAccessChainKHR:
2666 case SPIRV::OpUntypedInBoundsAccessChainKHR:
2667 case SPIRV::OpUntypedPtrAccessChainKHR:
2668 case SPIRV::OpUntypedInBoundsPtrAccessChainKHR:
2669 case SPIRV::OpUntypedPrefetchKHR:
2670 case SPIRV::OpUntypedGroupAsyncCopyKHR: {
2671 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_untyped_pointers))
2673 "SPIR-V extension: SPV_KHR_untyped_pointers",
2675 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_untyped_pointers);
2679 case SPIRV::OpPredicatedLoadINTEL:
2680 case SPIRV::OpPredicatedStoreINTEL: {
2681 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_predicated_io))
2683 "OpPredicated[Load/Store]INTEL instructions require "
2684 "the following SPIR-V extension: SPV_INTEL_predicated_io",
2686 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_predicated_io);
2690 case SPIRV::OpFAddS:
2691 case SPIRV::OpFSubS:
2692 case SPIRV::OpFMulS:
2693 case SPIRV::OpFDivS:
2694 case SPIRV::OpFRemS:
2696 case SPIRV::OpFNegate:
2697 case SPIRV::OpFAddV:
2698 case SPIRV::OpFSubV:
2699 case SPIRV::OpFMulV:
2700 case SPIRV::OpFDivV:
2701 case SPIRV::OpFRemV:
2702 case SPIRV::OpFNegateV: {
2708 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic))
2710 "Arithmetic instructions with bfloat16 arguments require the "
2711 "following SPIR-V extension: SPV_INTEL_bfloat16_arithmetic",
2713 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic);
2714 Reqs.
addCapability(SPIRV::Capability::BFloat16ArithmeticINTEL);
2718 case SPIRV::OpOrdered:
2719 case SPIRV::OpUnordered:
2720 case SPIRV::OpFOrdEqual:
2721 case SPIRV::OpFOrdNotEqual:
2722 case SPIRV::OpFOrdLessThan:
2723 case SPIRV::OpFOrdLessThanEqual:
2724 case SPIRV::OpFOrdGreaterThan:
2725 case SPIRV::OpFOrdGreaterThanEqual:
2726 case SPIRV::OpFUnordEqual:
2727 case SPIRV::OpFUnordNotEqual:
2728 case SPIRV::OpFUnordLessThan:
2729 case SPIRV::OpFUnordLessThanEqual:
2730 case SPIRV::OpFUnordGreaterThan:
2731 case SPIRV::OpFUnordGreaterThanEqual: {
2734 ST.getSPIRVGlobalRegistry());
2735 assert(TypeDef &&
"Unexpected type instruction for comparison operand");
2739 if (!ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic))
2741 "Relational instructions with bfloat16 arguments require the "
2742 "following SPIR-V extension: SPV_INTEL_bfloat16_arithmetic",
2744 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic);
2745 Reqs.
addCapability(SPIRV::Capability::BFloat16ArithmeticINTEL);
2749 case SPIRV::OpDPdxCoarse:
2750 case SPIRV::OpDPdyCoarse:
2751 case SPIRV::OpDPdxFine:
2752 case SPIRV::OpDPdyFine: {
2756 case SPIRV::OpLoopControlINTEL: {
2757 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_unstructured_loop_controls);
2758 Reqs.
addCapability(SPIRV::Capability::UnstructuredLoopControlsINTEL);
2770 SPIRV::Capability::Shader);
2785 auto Node = M.getNamedMetadata(
"spirv.ExecutionMode");
2787 bool RequireFloatControls =
false, RequireIntelFloatControls2 =
false,
2788 RequireKHRFloatControls2 =
false,
2789 VerLower14 = !ST.isAtLeastSPIRVVer(
VersionTuple(1, 4));
2790 bool HasIntelFloatControls2 =
2791 ST.canUseExtension(SPIRV::Extension::SPV_INTEL_float_controls2);
2792 bool HasKHRFloatControls2 =
2793 ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2);
2794 for (
unsigned i = 0; i <
Node->getNumOperands(); i++) {
2800 auto EM = Const->getZExtValue();
2804 case SPIRV::ExecutionMode::DenormPreserve:
2805 case SPIRV::ExecutionMode::DenormFlushToZero:
2806 case SPIRV::ExecutionMode::RoundingModeRTE:
2807 case SPIRV::ExecutionMode::RoundingModeRTZ:
2808 RequireFloatControls = VerLower14;
2810 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2812 case SPIRV::ExecutionMode::RoundingModeRTPINTEL:
2813 case SPIRV::ExecutionMode::RoundingModeRTNINTEL:
2814 case SPIRV::ExecutionMode::FloatingPointModeALTINTEL:
2815 case SPIRV::ExecutionMode::FloatingPointModeIEEEINTEL:
2816 if (HasIntelFloatControls2) {
2817 RequireIntelFloatControls2 =
true;
2819 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2822 case SPIRV::ExecutionMode::FPFastMathDefault: {
2823 if (HasKHRFloatControls2) {
2824 RequireKHRFloatControls2 =
true;
2826 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2830 case SPIRV::ExecutionMode::ContractionOff:
2831 case SPIRV::ExecutionMode::SignedZeroInfNanPreserve:
2832 if (HasKHRFloatControls2) {
2833 RequireKHRFloatControls2 =
true;
2835 SPIRV::OperandCategory::ExecutionModeOperand,
2836 SPIRV::ExecutionMode::FPFastMathDefault, ST);
2839 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2844 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2849 if (RequireFloatControls &&
2850 ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls))
2852 if (RequireIntelFloatControls2)
2854 if (RequireKHRFloatControls2)
2858 if (
F.isDeclaration())
2860 if (
F.getMetadata(
"reqd_work_group_size"))
2862 SPIRV::OperandCategory::ExecutionModeOperand,
2863 SPIRV::ExecutionMode::LocalSize, ST);
2864 if (
F.getFnAttribute(
"hlsl.numthreads").isValid()) {
2866 SPIRV::OperandCategory::ExecutionModeOperand,
2867 SPIRV::ExecutionMode::LocalSize, ST);
2869 if (
F.getFnAttribute(
"enable-maximal-reconvergence").getValueAsBool()) {
2872 if (
F.getMetadata(
"work_group_size_hint"))
2874 SPIRV::OperandCategory::ExecutionModeOperand,
2875 SPIRV::ExecutionMode::LocalSizeHint, ST);
2876 if (
F.getMetadata(
"intel_reqd_sub_group_size") ||
2877 F.getMetadata(
"reqd_sub_group_size"))
2879 SPIRV::OperandCategory::ExecutionModeOperand,
2880 SPIRV::ExecutionMode::SubgroupSize, ST);
2881 if (
F.getMetadata(
"max_work_group_size"))
2883 SPIRV::OperandCategory::ExecutionModeOperand,
2884 SPIRV::ExecutionMode::MaxWorkgroupSizeINTEL, ST);
2885 if (
F.getMetadata(
"vec_type_hint"))
2887 SPIRV::OperandCategory::ExecutionModeOperand,
2888 SPIRV::ExecutionMode::VecTypeHint, ST);
2890 if (
F.hasOptNone()) {
2891 if (ST.canUseExtension(SPIRV::Extension::SPV_INTEL_optnone)) {
2894 }
else if (ST.canUseExtension(SPIRV::Extension::SPV_EXT_optnone)) {
2904 unsigned Flags = SPIRV::FPFastMathMode::None;
2905 bool CanUseKHRFloatControls2 =
2906 ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2);
2908 Flags |= SPIRV::FPFastMathMode::NotNaN;
2910 Flags |= SPIRV::FPFastMathMode::NotInf;
2912 Flags |= SPIRV::FPFastMathMode::NSZ;
2914 Flags |= SPIRV::FPFastMathMode::AllowRecip;
2916 Flags |= SPIRV::FPFastMathMode::AllowContract;
2918 if (CanUseKHRFloatControls2)
2926 Flags |= SPIRV::FPFastMathMode::NotNaN | SPIRV::FPFastMathMode::NotInf |
2927 SPIRV::FPFastMathMode::NSZ | SPIRV::FPFastMathMode::AllowRecip |
2928 SPIRV::FPFastMathMode::AllowTransform |
2929 SPIRV::FPFastMathMode::AllowReassoc |
2930 SPIRV::FPFastMathMode::AllowContract;
2932 Flags |= SPIRV::FPFastMathMode::Fast;
2935 if (CanUseKHRFloatControls2) {
2937 assert(!(Flags & SPIRV::FPFastMathMode::Fast) &&
2938 "SPIRV::FPFastMathMode::Fast is deprecated and should not be used "
2943 assert((!(Flags & SPIRV::FPFastMathMode::AllowTransform) ||
2944 ((Flags & SPIRV::FPFastMathMode::AllowReassoc &&
2945 Flags & SPIRV::FPFastMathMode::AllowContract))) &&
2946 "SPIRV::FPFastMathMode::AllowTransform requires AllowReassoc and "
2947 "AllowContract flags to be enabled as well.");
2958 return ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2);
2968 auto Decorate = [&](SPIRV::Decoration::Decoration Dec,
2975 if (
TII.canUseIntegerWrapDecoration(
I)) {
2978 SPIRV::OperandCategory::DecorationOperand,
2979 SPIRV::Decoration::NoSignedWrap, ST, Reqs)
2981 Decorate(SPIRV::Decoration::NoSignedWrap, {});
2984 SPIRV::OperandCategory::DecorationOperand,
2985 SPIRV::Decoration::NoUnsignedWrap, ST, Reqs)
2987 Decorate(SPIRV::Decoration::NoUnsignedWrap, {});
2992 TII.canUseFastMathFlags(
2993 I, ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2)) ||
2994 (ST.isKernel() &&
I.getOpcode() == SPIRV::OpExtInst);
2999 if (FMFlags == SPIRV::FPFastMathMode::None) {
3002 if (FPFastMathDefaultInfoVec.
empty())
3008 I.getOpcode() == SPIRV::OpExtInst ||
3009 I.getOpcode() == SPIRV::OpFunctionCall
3010 ?
I.getMF()->getRegInfo().getVRegDef(
I.getOperand(1).getReg())
3011 :
getRegType(
I.getOperand(2).getReg(), *
I.getMF(), GR);
3018 if (Ty == Elem.Ty) {
3019 FMFlags = Elem.FastMathFlags;
3020 Emit = Elem.ContractionOff || Elem.SignedZeroInfNanPreserve ||
3021 Elem.FPFastMathDefault;
3026 if (FMFlags == SPIRV::FPFastMathMode::None && !Emit)
3030 Decorate(SPIRV::Decoration::FPFastMathMode, {FMFlags});
3044 for (
const auto &
MBB : *MF) {
3045 if (!
MBB.hasName() ||
MBB.empty())
3056 auto it = FPFastMathDefaultInfoMap.
find(
F);
3057 if (it != FPFastMathDefaultInfoMap.
end())
3065 SPIRV::FPFastMathMode::None);
3067 SPIRV::FPFastMathMode::None);
3069 SPIRV::FPFastMathMode::None);
3070 return FPFastMathDefaultInfoMap[
F] = std::move(FPFastMathDefaultInfoVec);
3076 size_t BitWidth = Ty->getScalarSizeInBits();
3080 assert(Index >= 0 && Index < 3 &&
3081 "Expected FPFastMathDefaultInfo for half, float, or double");
3082 assert(FPFastMathDefaultInfoVec.
size() == 3 &&
3083 "Expected FPFastMathDefaultInfoVec to have exactly 3 elements");
3084 return FPFastMathDefaultInfoVec[Index];
3091 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2))
3100 auto Node = M.getNamedMetadata(
"spirv.ExecutionMode");
3104 for (
unsigned i = 0; i <
Node->getNumOperands(); i++) {
3109 if (OnlyF &&
F != OnlyF)
3115 if (EM == SPIRV::ExecutionMode::FPFastMathDefault) {
3117 "Expected 4 operands for FPFastMathDefault");
3128 Info.FastMathFlags = Flags;
3129 Info.FPFastMathDefault =
true;
3130 }
else if (EM == SPIRV::ExecutionMode::ContractionOff) {
3132 "Expected no operands for ContractionOff");
3139 Info.ContractionOff =
true;
3141 }
else if (EM == SPIRV::ExecutionMode::SignedZeroInfNanPreserve) {
3143 "Expected 1 operand for SignedZeroInfNanPreserve");
3144 unsigned TargetWidth =
3153 assert(Index >= 0 && Index < 3 &&
3154 "Expected FPFastMathDefaultInfo for half, float, or double");
3155 assert(FPFastMathDefaultInfoVec.
size() == 3 &&
3156 "Expected FPFastMathDefaultInfoVec to have exactly 3 elements");
3157 FPFastMathDefaultInfoVec[Index].SignedZeroInfNanPreserve =
true;
3165 : ST(&ST), GR(ST.getSPIRVGlobalRegistry()), TII(ST.getInstrInfo()),
3166 MAI(MAI), GetMF(GetMF) {}
3178 collectDeclarations(M);
3181 numberRegistersGlobally(M);
3184 processOtherInstrs(M);
3188 MAI.Reqs.addCapability(SPIRV::Capability::Linkage);
3191 GR->setBound(MAI.MaxID);
3205 [&MMI](
const Function &
F) { return MMI.getMachineFunction(F); })
3221 MachineFunctionAnalysis::Result *MFA =
3222 FAM.getCachedResult<MachineFunctionAnalysis>(
3223 const_cast<Function &>(F));
3224 assert((MFA || F.isDeclaration()) &&
3225 "Missing MachineFunction for definition");
3226 return MFA ? &MFA->getMF() : nullptr;
3243 for (
auto &
MBB : MF)
3246 FPFastMathDefaultInfoMap[&
F]);
3254 SPIRVPrepareModuleAnalysisLegacy() : MachineFunctionPass(
ID) {}
3261char SPIRVPrepareModuleAnalysisLegacy::ID = 0;
3264 "spirv-prepare-module-analysis",
3265 "SPIRV prepare module analysis",
false,
false)
3268 return new SPIRVPrepareModuleAnalysisLegacy();
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
ReachingDefInfo InstSet & ToRemove
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define clEnumValN(ENUMVAL, FLAGNAME, DESC)
static Register UseReg(const MachineOperand &MO)
const HexagonInstrInfo * TII
Promote Memory to Register
FunctionAnalysisManager FAM
ModuleAnalysisManager MAM
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
MachineRegisterInfo & MRI
#define ATOM_FLT_REQ_EXT_MSG(ExtName)
static bool isFastMathModeAvailable(const SPIRVSubtarget &ST)
static void addMBBNames(const Module &M, MachineFunctionGetter GetMF, SPIRV::ModuleAnalysisInfo &MAI)
static void maybeAddScatterGatherReq(const MachineInstr &MI, SPIRV::RequirementHandler &Reqs, const SPIRVSubtarget &ST)
static void addImageOperandReqs(const MachineInstr &MI, SPIRV::RequirementHandler &Reqs, const SPIRVSubtarget &ST, unsigned OpIdx)
bool isStorageImage(MachineInstr *ImageInst)
bool isInputAttachment(MachineInstr *ImageInst)
static bool isBFloat16Type(SPIRVTypeInst TypeDef)
static bool handleMIFlagDecoration(MachineInstr &I, const SPIRVSubtarget &ST, const SPIRVInstrInfo &TII, SPIRV::RequirementHandler &Reqs, const SPIRVGlobalRegistry *GR, SPIRV::FPFastMathDefaultInfoVector &FPFastMathDefaultInfoVec)
bool isSampledImage(MachineInstr *ImageInst)
static cl::list< SPIRV::Capability::Capability > AvoidCapabilities("avoid-spirv-capabilities", cl::desc("SPIR-V capabilities to avoid if there are " "other options enabling a feature"), cl::Hidden, cl::values(clEnumValN(SPIRV::Capability::Shader, "Shader", "SPIR-V Shader capability")))
static unsigned getInvokeOperandIdx(unsigned Opcode)
static SPIRV::FPFastMathDefaultInfo & getFPFastMathDefaultInfo(SPIRV::FPFastMathDefaultInfoVector &FPFastMathDefaultInfoVec, const Type *Ty)
static cl::opt< bool > SPVDumpDeps("spv-dump-deps", cl::desc("Dump MIR with SPIR-V dependencies info"), cl::init(false))
static void collectFPFastMathDefaults(const Module &M, SPIRV::FPFastMathDefaultInfoMapTy &FPFastMathDefaultInfoMap, const SPIRVSubtarget &ST, const Function *OnlyF=nullptr)
static void collectOtherInstr(MachineInstr &MI, SPIRV::ModuleAnalysisInfo &MAI, SPIRV::ModuleSectionType MSType, InstrTraces &IS, bool Append=true)
void addPrintfRequirements(const MachineInstr &MI, SPIRV::RequirementHandler &Reqs, const SPIRVSubtarget &ST)
static void addOpTypeImageReqs(const MachineInstr &MI, SPIRV::RequirementHandler &Reqs, const SPIRVSubtarget &ST)
static bool isImageTypeWithUnknownFormat(SPIRVTypeInst TypeInst)
bool isUniformTexelBuffer(MachineInstr *ImageInst)
bool isStorageTexelBuffer(MachineInstr *ImageInst)
static void AddAtomicFloatRequirements(const MachineInstr &MI, SPIRV::RequirementHandler &Reqs, const SPIRVSubtarget &ST)
bool isCombinedImageSampler(MachineInstr *SampledImageInst)
bool hasNonUniformDecoration(Register Reg, const MachineRegisterInfo &MRI)
void addInstrRequirements(const MachineInstr &MI, SPIRV::ModuleAnalysisInfo &MAI, const SPIRVSubtarget &ST)
static void collectReqs(const Module &M, SPIRV::ModuleAnalysisInfo &MAI, MachineFunctionGetter GetMF, const SPIRVSubtarget &ST)
static void addOpDecorateReqs(const MachineInstr &MI, unsigned DecIndex, SPIRV::RequirementHandler &Reqs, const SPIRVSubtarget &ST)
static InstrSignature instrToSignature(const MachineInstr &MI, SPIRV::ModuleAnalysisInfo &MAI, bool UseDefReg)
static void AddDotProductRequirements(const MachineInstr &MI, SPIRV::RequirementHandler &Reqs, const SPIRVSubtarget &ST)
static SPIRV::Requirements getSymbolicOperandRequirements(SPIRV::OperandCategory::OperandCategory Category, unsigned i, const SPIRVSubtarget &ST, SPIRV::RequirementHandler &Reqs)
static SPIRVTypeInst getRegType(Register Reg, const MachineFunction &MF, const SPIRVGlobalRegistry *GR)
static unsigned getMetadataUInt(MDNode *MdNode, unsigned OpIndex, unsigned DefaultVal=0)
static void addCoreInSPIRV13Capability(SPIRV::RequirementHandler &Reqs, const SPIRVSubtarget &ST, SPIRV::Capability::Capability Cap, SPIRV::Extension::Extension Ext)
void addOpAccessChainReqs(const MachineInstr &Instr, SPIRV::RequirementHandler &Handler, const SPIRVSubtarget &Subtarget)
static bool prepareModuleAnalysis(MachineFunction &MF)
static void appendDecorationsForReg(const MachineRegisterInfo &MRI, Register R, InstrSignature &Signature)
static SPIRV::FPFastMathDefaultInfoVector & getOrCreateFPFastMathDefaultInfoVec(const Module &M, SPIRV::FPFastMathDefaultInfoMapTy &FPFastMathDefaultInfoMap, const Function *F)
static void AddAtomicVectorFloatRequirements(const MachineInstr &MI, SPIRV::RequirementHandler &Reqs, const SPIRVSubtarget &ST)
static unsigned getFastMathFlags(const MachineInstr &I, const SPIRVSubtarget &ST)
#define SPIRV_BACKEND_SERVICE_FUN_NAME
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
Target-Independent Code Generator Pass Configuration Options pass.
static Function * getFunction(FunctionType *Ty, const Twine &Name, Module *M)
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
Represent a constant reference to an array (0 or more elements consecutively in memory),...
bool isValid() const
Return true if the attribute is any kind of attribute.
This is the shared class of boolean and integer constants.
This is an important base class in LLVM.
iterator find(const_arg_type_t< KeyT > Val)
Diagnostic information for unsupported feature in backend.
FunctionPass class - This class is used to implement most global optimizations.
Attribute getFnAttribute(Attribute::AttrKind Kind) const
Return the attribute for the given attribute kind.
Wrapper class representing physical registers. Should be passed by value.
constexpr bool isValid() const
const MDOperand & getOperand(unsigned I) const
unsigned getNumOperands() const
Return number of MDNode operands.
Tracking metadata reference owned by Metadata.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
MachineInstrBundleIterator< MachineInstr > iterator
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
Helper class to build MachineInstr.
void setDebugLoc(const DebugLoc &DL)
Set the debug location to DL for all the next build instructions.
Register getReg(unsigned Idx) const
Get the register for the operand index.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineBasicBlock * getParent() const
unsigned getNumOperands() const
Retuns the total number of operands.
LLVM_ABI const MachineFunction * getMF() const
Return the function that contains the basic block that this instruction belongs to.
const MachineOperand & getOperand(unsigned i) const
An analysis that produces MachineModuleInfo for a module.
This class contains meta information specific to a module.
MachineOperand class - Representation of each machine instruction operand.
unsigned getSubReg() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
LLVM_ABI void print(raw_ostream &os, const TargetRegisterInfo *TRI=nullptr) const
Print the MachineOperand to os.
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
static MachineOperand CreateImm(int64_t Val)
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
iterator_range< use_instr_iterator > use_instructions(Register Reg) const
LLVM_ABI LLVM_READONLY MachineInstr * getUniqueVRegDef(Register Reg) const
getUniqueVRegDef - Return the unique machine instr that defines the specified virtual register or nul...
A Module instance is used to store all the information related to an LLVM module.
AnalysisType & getAnalysis() const
getAnalysis<AnalysisType>() - This function is used by subclasses to get to the analysis information ...
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Wrapper class representing virtual and physical registers.
constexpr bool isValid() const
unsigned getScalarOrVectorBitWidth(SPIRVTypeInst Type) const
SPIRVTypeInst getResultType(Register VReg, MachineFunction *MF=nullptr)
const Type * getTypeForSPIRVType(SPIRVTypeInst Ty) const
SPIRVTypeInst getSPIRVTypeForVReg(Register VReg, const MachineFunction *MF=nullptr) const
bool isConstantInstr(const MachineInstr &MI) const
void run(const Module &M)
SPIRVModuleAnalysisImpl(const SPIRVSubtarget &ST, SPIRV::ModuleAnalysisInfo &MAI, MachineFunctionGetter GetMF)
SPIRV::ModuleAnalysisInfo Result
Result run(Module &M, ModuleAnalysisManager &MAM)
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
const SPIRVInstrInfo * getInstrInfo() const override
const SPIRVSubtarget * getSubtargetImpl() const
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
bool contains(const T &V) const
Check if the SmallSet contains the given element.
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
reference emplace_back(ArgTypes &&... Args)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
iterator insert(iterator I, T &&Elt)
void push_back(const T &Elt)
Target-Independent Code Generator Pass Configuration Options.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
bool isVectorTy() const
True if this is an instance of VectorType.
static LLVM_ABI Type * getDoubleTy(LLVMContext &C)
static LLVM_ABI Type * getFloatTy(LLVMContext &C)
static LLVM_ABI Type * getHalfTy(LLVMContext &C)
Represents a version number in the form major[.minor[.subminor[.build]]].
bool empty() const
Determine whether this version information is empty (e.g., all version components are zero).
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
DenseMap< const Function *, FPFastMathDefaultInfoVector > FPFastMathDefaultInfoMapTy
SmallVector< const MachineInstr * > InstrList
ValuesClass values(OptsTy... Options)
Helper to build a ValuesClass by forwarding a variable number of arguments as an initializer list to ...
initializer< Ty > init(const Ty &Val)
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > extract(Y &&MD)
Extract a Value from Metadata.
This is an optimization pass for GlobalISel generic memory operations.
void stable_sort(R &&Range)
std::string getStringImm(const MachineInstr &MI, unsigned StartIndex)
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
hash_code hash_value(const FixedPointSemantics &Val)
ExtensionList getSymbolicOperandExtensions(SPIRV::OperandCategory::OperandCategory Category, uint32_t Value)
CapabilityList getSymbolicOperandCapabilities(SPIRV::OperandCategory::OperandCategory Category, uint32_t Value)
SmallVector< SPIRV::Extension::Extension, 8 > ExtensionList
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
SmallVector< size_t > InstrSignature
bool requiresLongVectorEXT(unsigned NumComponents)
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
InnerAnalysisManagerProxy< FunctionAnalysisManager, Module > FunctionAnalysisManagerModuleProxy
Provide the FunctionAnalysisManager to Module proxy.
static void reportUnsupported(MachineIRBuilder &MIRBuilder, const Twine &Msg)
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
void buildOpDecorate(Register Reg, MachineIRBuilder &MIRBuilder, SPIRV::Decoration::Decoration Dec, ArrayRef< uint32_t > DecArgs, StringRef StrImm)
bool isVectorType(SPIRVTypeInst SPVTy)
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
VersionTuple getSymbolicOperandMaxVersion(SPIRV::OperandCategory::OperandCategory Category, uint32_t Value)
function_ref< MachineFunction *(const Function &)> MachineFunctionGetter
void erase(Container &C, ValueType V)
Wrapper function to remove a value from a container:
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
CapabilityList getCapabilitiesEnabledByExtension(SPIRV::Extension::Extension Extension)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
FunctionPass * createSPIRVPrepareModuleAnalysisLegacyPass()
std::string getSymbolicOperandMnemonic(SPIRV::OperandCategory::OperandCategory Category, int32_t Value)
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
DWARFExpression::Operation Op
VersionTuple getSymbolicOperandMinVersion(SPIRV::OperandCategory::OperandCategory Category, uint32_t Value)
constexpr unsigned BitWidth
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
SmallVector< SPIRV::Capability::Capability, 8 > CapabilityList
std::set< InstrSignature > InstrTraces
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
hash_code hash_combine(const Ts &...args)
Combine values into a single hash_code.
std::map< SmallVector< size_t >, unsigned > InstrGRegsMap
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
SmallSet< SPIRV::Capability::Capability, 4 > S
A special type used by analysis passes to provide an address that identifies that particular analysis...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
SPIRV::ModuleAnalysisInfo MAI
bool runOnModule(Module &M) override
runOnModule - Virtual method overriden by subclasses to process the module being operated on.
static size_t computeFPFastMathDefaultInfoVecIndex(size_t BitWidth)
void setSkipEmission(const MachineInstr *MI)
MCRegister getRegisterAlias(const MachineFunction *MF, Register Reg)
MCRegister getOrCreateMBBRegister(const MachineBasicBlock &MBB)
InstrList MS[NUM_MODULE_SECTIONS]
AddressingModel::AddressingModel Addr
SmallVector< std::pair< MCRegister, StringRef > > MBBNames
void checkSatisfiable(const SPIRVSubtarget &ST) const
void getAndAddRequirements(SPIRV::OperandCategory::OperandCategory Category, uint32_t i, const SPIRVSubtarget &ST)
void addRequirements(const Requirements &Req)
bool isCapabilityAvailable(Capability::Capability Cap) const
void removeCapabilityIf(const Capability::Capability ToRemove, const Capability::Capability IfPresent)
void addExtensions(const ExtensionList &ToAdd)
void addAvailableCaps(const CapabilityList &ToAdd)
void addExtension(Extension::Extension ToAdd)
void initAvailableCapabilities(const SPIRVSubtarget &ST)
void addCapability(Capability::Capability ToAdd)
void addCapabilities(const CapabilityList &ToAdd)
const std::optional< Capability::Capability > Cap
const VersionTuple MinVer
const VersionTuple MaxVer