59 const auto &
Op = MdNode->getOperand(
OpIndex);
66getSymbolicOperandRequirements(SPIRV::OperandCategory::OperandCategory Category,
72 AvoidCaps.
S.
insert(SPIRV::Capability::Shader);
74 AvoidCaps.
S.
insert(SPIRV::Capability::Kernel);
79 bool MinVerOK = SPIRVVersion.
empty() || SPIRVVersion >= ReqMinVer;
81 ReqMaxVer.
empty() || SPIRVVersion.
empty() || SPIRVVersion <= ReqMaxVer;
84 if (ReqCaps.
empty()) {
85 if (ReqExts.
empty()) {
86 if (MinVerOK && MaxVerOK)
87 return {
true, {}, {}, ReqMinVer, ReqMaxVer};
90 }
else if (MinVerOK && MaxVerOK) {
91 if (ReqCaps.
size() == 1) {
92 auto Cap = ReqCaps[0];
95 SPIRV::OperandCategory::CapabilityOperand, Cap));
96 return {
true, {Cap}, std::move(ReqExts), ReqMinVer, ReqMaxVer};
106 for (
auto Cap : ReqCaps)
109 for (
size_t i = 0, Sz = UseCaps.
size(); i < Sz; ++i) {
110 auto Cap = UseCaps[i];
111 if (i == Sz - 1 || !AvoidCaps.
S.
contains(Cap)) {
113 SPIRV::OperandCategory::CapabilityOperand, Cap));
114 return {
true, {Cap}, std::move(ReqExts), ReqMinVer, ReqMaxVer};
122 if (
llvm::all_of(ReqExts, [&ST](
const SPIRV::Extension::Extension &Ext) {
123 return ST.canUseExtension(Ext);
134void SPIRVModuleAnalysis::setBaseInfo(
const Module &M) {
138 MAI.RegisterAliasTable.clear();
139 MAI.InstrsToDelete.clear();
141 MAI.GlobalVarList.clear();
142 MAI.ExtInstSetMap.clear();
144 MAI.Reqs.initAvailableCapabilities(*ST);
147 if (
auto MemModel =
M.getNamedMetadata(
"spirv.MemoryModel")) {
148 auto MemMD = MemModel->getOperand(0);
149 MAI.Addr =
static_cast<SPIRV::AddressingModel::AddressingModel
>(
150 getMetadataUInt(MemMD, 0));
152 static_cast<SPIRV::MemoryModel::MemoryModel
>(getMetadataUInt(MemMD, 1));
155 MAI.Mem = ST->isShader() ? SPIRV::MemoryModel::GLSL450
156 : SPIRV::MemoryModel::OpenCL;
157 if (
MAI.Mem == SPIRV::MemoryModel::OpenCL) {
158 unsigned PtrSize = ST->getPointerSize();
159 MAI.Addr = PtrSize == 32 ? SPIRV::AddressingModel::Physical32
160 : PtrSize == 64 ? SPIRV::AddressingModel::Physical64
161 : SPIRV::AddressingModel::Logical;
164 MAI.Addr = SPIRV::AddressingModel::Logical;
169 if (
auto VerNode =
M.getNamedMetadata(
"opencl.ocl.version")) {
170 MAI.SrcLang = SPIRV::SourceLanguage::OpenCL_C;
173 assert(VerNode->getNumOperands() > 0 &&
"Invalid SPIR");
174 auto VersionMD = VerNode->getOperand(0);
175 unsigned MajorNum = getMetadataUInt(VersionMD, 0, 2);
176 unsigned MinorNum = getMetadataUInt(VersionMD, 1);
177 unsigned RevNum = getMetadataUInt(VersionMD, 2);
180 (std::max(1U, MajorNum) * 100 + MinorNum) * 1000 + RevNum;
186 if (!ST->isShader()) {
187 MAI.SrcLang = SPIRV::SourceLanguage::OpenCL_CPP;
188 MAI.SrcLangVersion = 100000;
190 MAI.SrcLang = SPIRV::SourceLanguage::Unknown;
191 MAI.SrcLangVersion = 0;
195 if (
auto ExtNode =
M.getNamedMetadata(
"opencl.used.extensions")) {
196 for (
unsigned I = 0,
E = ExtNode->getNumOperands();
I !=
E; ++
I) {
197 MDNode *MD = ExtNode->getOperand(
I);
207 MAI.Reqs.getAndAddRequirements(SPIRV::OperandCategory::MemoryModelOperand,
209 MAI.Reqs.getAndAddRequirements(SPIRV::OperandCategory::SourceLanguageOperand,
211 MAI.Reqs.getAndAddRequirements(SPIRV::OperandCategory::AddressingModelOperand,
214 if (!ST->isShader()) {
216 MAI.ExtInstSetMap[
static_cast<unsigned>(
217 SPIRV::InstructionSet::OpenCL_std)] =
MAI.getNextIDRegister();
228 if (
UseMI.getOpcode() != SPIRV::OpDecorate &&
229 UseMI.getOpcode() != SPIRV::OpMemberDecorate)
232 for (
unsigned I = 0;
I <
UseMI.getNumOperands(); ++
I) {
250 for (
unsigned i = 0; i <
MI.getNumOperands(); ++i) {
254 if (!UseDefReg && MO.
isDef()) {
262 dbgs() <<
"Unexpectedly, no global id found for the operand ";
264 dbgs() <<
"\nInstruction: ";
283 appendDecorationsForReg(
MI.getMF()->getRegInfo(), DefReg, Signature);
290 unsigned Opcode =
MI.getOpcode();
292 case SPIRV::OpTypeForwardPointer:
295 case SPIRV::OpVariable:
296 return static_cast<SPIRV::StorageClass::StorageClass
>(
297 MI.getOperand(2).
getImm()) != SPIRV::StorageClass::Function;
298 case SPIRV::OpFunction:
299 case SPIRV::OpFunctionParameter:
302 if (GR->hasConstFunPtr() && Opcode == SPIRV::OpUndef) {
304 for (MachineInstr &
UseMI :
MRI.use_instructions(DefReg)) {
305 if (
UseMI.getOpcode() != SPIRV::OpConstantFunctionPointerINTEL)
311 MAI.setSkipEmission(&
MI);
315 return TII->isTypeDeclInstr(
MI) || TII->isConstantInstr(
MI) ||
316 TII->isInlineAsmDefInstr(
MI);
322void SPIRVModuleAnalysis::visitFunPtrUse(
324 std::map<const Value *, unsigned> &GlobalToGReg,
const MachineFunction *MF,
326 const MachineOperand *OpFunDef =
327 GR->getFunctionDefinitionByUse(&
MI.getOperand(2));
330 const MachineInstr *OpDefMI = OpFunDef->
getParent();
333 const MachineRegisterInfo &FunDefMRI = FunDefMF->
getRegInfo();
335 visitDecl(FunDefMRI, SignatureToGReg, GlobalToGReg, FunDefMF, *OpDefMI);
337 }
while (OpDefMI && (OpDefMI->
getOpcode() == SPIRV::OpFunction ||
338 OpDefMI->
getOpcode() == SPIRV::OpFunctionParameter));
340 MCRegister GlobalFunDefReg =
341 MAI.getRegisterAlias(FunDefMF, OpFunDef->
getReg());
343 "Function definition must refer to a global register");
344 MAI.setRegisterAlias(MF, OpReg, GlobalFunDefReg);
349void SPIRVModuleAnalysis::visitDecl(
351 std::map<const Value *, unsigned> &GlobalToGReg,
const MachineFunction *MF,
353 unsigned Opcode =
MI.getOpcode();
356 for (
const MachineOperand &MO :
MI.operands()) {
361 if (Opcode == SPIRV::OpConstantFunctionPointerINTEL &&
362 MRI.getRegClass(OpReg) == &SPIRV::pIDRegClass) {
363 visitFunPtrUse(OpReg, SignatureToGReg, GlobalToGReg, MF,
MI);
367 if (
MAI.hasRegisterAlias(MF, MO.
getReg()))
370 if (
const MachineInstr *OpDefMI =
MRI.getUniqueVRegDef(OpReg)) {
371 if (isDeclSection(
MRI, *OpDefMI))
372 visitDecl(
MRI, SignatureToGReg, GlobalToGReg, MF, *OpDefMI);
378 dbgs() <<
"Unexpectedly, no unique definition for the operand ";
380 dbgs() <<
"\nInstruction: ";
385 "No unique definition is found for the virtual register");
389 bool IsFunDef =
false;
390 if (TII->isSpecConstantInstr(
MI)) {
391 GReg =
MAI.getNextIDRegister();
393 }
else if (Opcode == SPIRV::OpFunction ||
394 Opcode == SPIRV::OpFunctionParameter) {
395 GReg = handleFunctionOrParameter(MF,
MI, GlobalToGReg, IsFunDef);
396 }
else if (Opcode == SPIRV::OpTypeStruct ||
397 Opcode == SPIRV::OpConstantComposite) {
398 GReg = handleTypeDeclOrConstant(
MI, SignatureToGReg);
399 const MachineInstr *NextInstr =
MI.getNextNode();
401 ((Opcode == SPIRV::OpTypeStruct &&
402 NextInstr->
getOpcode() == SPIRV::OpTypeStructContinuedINTEL) ||
403 (Opcode == SPIRV::OpConstantComposite &&
405 SPIRV::OpConstantCompositeContinuedINTEL))) {
406 MCRegister Tmp = handleTypeDeclOrConstant(*NextInstr, SignatureToGReg);
408 MAI.setSkipEmission(NextInstr);
411 }
else if (TII->isTypeDeclInstr(
MI) || TII->isConstantInstr(
MI) ||
412 TII->isInlineAsmDefInstr(
MI)) {
413 GReg = handleTypeDeclOrConstant(
MI, SignatureToGReg);
414 }
else if (Opcode == SPIRV::OpVariable) {
415 GReg = handleVariable(MF,
MI, GlobalToGReg);
418 dbgs() <<
"\nInstruction: ";
424 MAI.setRegisterAlias(MF,
MI.getOperand(0).getReg(), GReg);
426 MAI.setSkipEmission(&
MI);
429MCRegister SPIRVModuleAnalysis::handleFunctionOrParameter(
431 std::map<const Value *, unsigned> &GlobalToGReg,
bool &IsFunDef) {
432 const Value *GObj = GR->getGlobalObject(MF,
MI.getOperand(0).getReg());
433 assert(GObj &&
"Unregistered global definition");
437 assert(
F &&
"Expected a reference to a function or an argument");
438 IsFunDef = !
F->isDeclaration();
439 auto [It,
Inserted] = GlobalToGReg.try_emplace(GObj);
442 MCRegister GReg =
MAI.getNextIDRegister();
450SPIRVModuleAnalysis::handleTypeDeclOrConstant(
const MachineInstr &
MI,
453 auto [It,
Inserted] = SignatureToGReg.try_emplace(MISign);
456 MCRegister GReg =
MAI.getNextIDRegister();
462MCRegister SPIRVModuleAnalysis::handleVariable(
464 std::map<const Value *, unsigned> &GlobalToGReg) {
465 MAI.GlobalVarList.push_back(&
MI);
466 const Value *GObj = GR->getGlobalObject(MF,
MI.getOperand(0).getReg());
467 assert(GObj &&
"Unregistered global definition");
468 auto [It,
Inserted] = GlobalToGReg.try_emplace(GObj);
471 MCRegister GReg =
MAI.getNextIDRegister();
477void SPIRVModuleAnalysis::collectDeclarations(
const Module &M) {
479 std::map<const Value *, unsigned> GlobalToGReg;
480 for (
auto F =
M.begin(),
E =
M.end();
F !=
E; ++
F) {
481 MachineFunction *MF = MMI->getMachineFunction(*
F);
485 unsigned PastHeader = 0;
486 for (MachineBasicBlock &
MBB : *MF) {
487 for (MachineInstr &
MI :
MBB) {
488 if (
MI.getNumOperands() == 0)
490 unsigned Opcode =
MI.getOpcode();
491 if (Opcode == SPIRV::OpFunction) {
492 if (PastHeader == 0) {
496 }
else if (Opcode == SPIRV::OpFunctionParameter) {
499 }
else if (PastHeader > 0) {
503 const MachineOperand &DefMO =
MI.getOperand(0);
505 case SPIRV::OpExtension:
506 MAI.Reqs.addExtension(SPIRV::Extension::Extension(DefMO.
getImm()));
507 MAI.setSkipEmission(&
MI);
509 case SPIRV::OpCapability:
510 MAI.Reqs.addCapability(SPIRV::Capability::Capability(DefMO.
getImm()));
511 MAI.setSkipEmission(&
MI);
516 if (DefMO.
isReg() && isDeclSection(
MRI,
MI) &&
517 !
MAI.hasRegisterAlias(MF, DefMO.
getReg()))
518 visitDecl(
MRI, SignatureToGReg, GlobalToGReg, MF,
MI);
531 if (
MI.getOpcode() == SPIRV::OpDecorate) {
533 auto Dec =
MI.getOperand(1).getImm();
534 if (Dec ==
static_cast<unsigned>(SPIRV::Decoration::LinkageAttributes)) {
535 auto Lnk =
MI.getOperand(
MI.getNumOperands() - 1).getImm();
536 if (Lnk ==
static_cast<unsigned>(SPIRV::LinkageType::Import)) {
541 MAI.FuncMap[ImportedFunc] =
MAI.getRegisterAlias(
MI.getMF(), Target);
544 }
else if (
MI.getOpcode() == SPIRV::OpFunction) {
547 MCRegister GlobalReg =
MAI.getRegisterAlias(
MI.getMF(),
Reg);
549 MAI.FuncMap[
F] = GlobalReg;
558 bool Append =
true) {
561 auto FoundMI = IS.insert(std::move(MISign));
573void SPIRVModuleAnalysis::processOtherInstrs(
const Module &M) {
575 for (
auto F =
M.begin(),
E =
M.end();
F !=
E; ++
F) {
576 if ((*F).isDeclaration())
578 MachineFunction *MF = MMI->getMachineFunction(*
F);
581 for (MachineBasicBlock &
MBB : *MF)
582 for (MachineInstr &
MI :
MBB) {
583 if (
MAI.getSkipEmission(&
MI))
585 const unsigned OpCode =
MI.getOpcode();
586 if (OpCode == SPIRV::OpString) {
588 }
else if (OpCode == SPIRV::OpExtInst &&
MI.getOperand(2).isImm() &&
589 MI.getOperand(2).getImm() ==
590 SPIRV::InstructionSet::
591 NonSemantic_Shader_DebugInfo_100) {
592 MachineOperand
Ins =
MI.getOperand(3);
593 namespace NS = SPIRV::NonSemanticExtInst;
594 static constexpr int64_t GlobalNonSemanticDITy[] = {
595 NS::DebugSource, NS::DebugCompilationUnit, NS::DebugInfoNone,
596 NS::DebugTypeBasic, NS::DebugTypePointer};
597 bool IsGlobalDI =
false;
598 for (
unsigned Idx = 0; Idx < std::size(GlobalNonSemanticDITy); ++Idx)
599 IsGlobalDI |=
Ins.getImm() == GlobalNonSemanticDITy[Idx];
602 }
else if (OpCode == SPIRV::OpName || OpCode == SPIRV::OpMemberName) {
604 }
else if (OpCode == SPIRV::OpEntryPoint) {
606 }
else if (TII->isAliasingInstr(
MI)) {
608 }
else if (TII->isDecorationInstr(
MI)) {
610 collectFuncNames(
MI, &*
F);
611 }
else if (TII->isConstantInstr(
MI)) {
615 }
else if (OpCode == SPIRV::OpFunction) {
616 collectFuncNames(
MI, &*
F);
617 }
else if (OpCode == SPIRV::OpTypeForwardPointer) {
627void SPIRVModuleAnalysis::numberRegistersGlobally(
const Module &M) {
628 for (
auto F =
M.begin(),
E =
M.end();
F !=
E; ++
F) {
629 if ((*F).isDeclaration())
631 MachineFunction *MF = MMI->getMachineFunction(*
F);
633 for (MachineBasicBlock &
MBB : *MF) {
634 for (MachineInstr &
MI :
MBB) {
635 for (MachineOperand &
Op :
MI.operands()) {
639 if (
MAI.hasRegisterAlias(MF,
Reg))
641 MCRegister NewReg =
MAI.getNextIDRegister();
642 MAI.setRegisterAlias(MF,
Reg, NewReg);
644 if (
MI.getOpcode() != SPIRV::OpExtInst)
646 auto Set =
MI.getOperand(2).getImm();
647 auto [It,
Inserted] =
MAI.ExtInstSetMap.try_emplace(Set);
649 It->second =
MAI.getNextIDRegister();
657 SPIRV::OperandCategory::OperandCategory Category, uint32_t i,
659 addRequirements(getSymbolicOperandRequirements(Category, i, ST, *
this));
662void SPIRV::RequirementHandler::recursiveAddCapabilities(
664 for (
const auto &Cap : ToPrune) {
668 recursiveAddCapabilities(ImplicitDecls);
673 for (
const auto &Cap : ToAdd) {
674 bool IsNewlyInserted = AllCaps.insert(Cap).second;
675 if (!IsNewlyInserted)
679 recursiveAddCapabilities(ImplicitDecls);
680 MinimalCaps.push_back(Cap);
685 const SPIRV::Requirements &Req) {
689 if (Req.
Cap.has_value())
690 addCapabilities({Req.
Cap.value()});
692 addExtensions(Req.
Exts);
695 if (!MaxVersion.empty() && Req.
MinVer > MaxVersion) {
697 <<
" and <= " << MaxVersion <<
"\n");
701 if (MinVersion.empty() || Req.
MinVer > MinVersion)
706 if (!MinVersion.empty() && Req.
MaxVer < MinVersion) {
708 <<
" and >= " << MinVersion <<
"\n");
712 if (MaxVersion.empty() || Req.
MaxVer < MaxVersion)
718 const SPIRVSubtarget &ST)
const {
720 bool IsSatisfiable =
true;
721 auto TargetVer =
ST.getSPIRVVersion();
723 if (!MaxVersion.empty() && !TargetVer.empty() && MaxVersion < TargetVer) {
725 dbgs() <<
"Target SPIR-V version too high for required features\n"
726 <<
"Required max version: " << MaxVersion <<
" target version "
727 << TargetVer <<
"\n");
728 IsSatisfiable =
false;
731 if (!MinVersion.empty() && !TargetVer.empty() && MinVersion > TargetVer) {
732 LLVM_DEBUG(
dbgs() <<
"Target SPIR-V version too low for required features\n"
733 <<
"Required min version: " << MinVersion
734 <<
" target version " << TargetVer <<
"\n");
735 IsSatisfiable =
false;
738 if (!MinVersion.empty() && !MaxVersion.empty() && MinVersion > MaxVersion) {
741 <<
"Version is too low for some features and too high for others.\n"
742 <<
"Required SPIR-V min version: " << MinVersion
743 <<
" required SPIR-V max version " << MaxVersion <<
"\n");
744 IsSatisfiable =
false;
747 AvoidCapabilitiesSet AvoidCaps;
749 AvoidCaps.
S.
insert(SPIRV::Capability::Shader);
751 AvoidCaps.
S.
insert(SPIRV::Capability::Kernel);
753 for (
auto Cap : MinimalCaps) {
754 if (AvailableCaps.contains(Cap) && !AvoidCaps.
S.
contains(Cap))
758 OperandCategory::CapabilityOperand, Cap)
760 IsSatisfiable =
false;
763 for (
auto Ext : AllExtensions) {
764 if (
ST.canUseExtension(Ext))
768 OperandCategory::ExtensionOperand, Ext)
770 IsSatisfiable =
false;
779 for (
const auto Cap : ToAdd)
780 if (AvailableCaps.insert(Cap).second)
782 SPIRV::OperandCategory::CapabilityOperand, Cap));
786 const Capability::Capability
ToRemove,
787 const Capability::Capability IfPresent) {
788 if (AllCaps.contains(IfPresent))
796 addAvailableCaps({Capability::Shader, Capability::Linkage, Capability::Int8,
799 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 3)))
801 Capability::GroupNonUniformVote,
802 Capability::GroupNonUniformArithmetic,
803 Capability::GroupNonUniformBallot,
804 Capability::GroupNonUniformClustered,
805 Capability::GroupNonUniformShuffle,
806 Capability::GroupNonUniformShuffleRelative});
808 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 6)))
810 Capability::DotProductInput4x8Bit,
811 Capability::DotProductInput4x8BitPacked,
812 Capability::DemoteToHelperInvocation});
815 for (
auto Extension :
ST.getAllAvailableExtensions()) {
821 if (!
ST.isShader()) {
822 initAvailableCapabilitiesForOpenCL(ST);
827 initAvailableCapabilitiesForVulkan(ST);
834void RequirementHandler::initAvailableCapabilitiesForOpenCL(
835 const SPIRVSubtarget &ST) {
838 Capability::Kernel, Capability::Vector16,
839 Capability::Groups, Capability::GenericPointer,
840 Capability::StorageImageWriteWithoutFormat,
841 Capability::StorageImageReadWithoutFormat});
842 if (
ST.hasOpenCLFullProfile())
844 if (
ST.hasOpenCLImageSupport()) {
846 Capability::Image1D, Capability::SampledBuffer,
847 Capability::ImageBuffer});
848 if (
ST.isAtLeastOpenCLVer(VersionTuple(2, 0)))
851 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 1)) &&
852 ST.isAtLeastOpenCLVer(VersionTuple(2, 2)))
854 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 4)))
855 addAvailableCaps({Capability::DenormPreserve, Capability::DenormFlushToZero,
856 Capability::SignedZeroInfNanPreserve,
857 Capability::RoundingModeRTE,
858 Capability::RoundingModeRTZ});
865void RequirementHandler::initAvailableCapabilitiesForVulkan(
866 const SPIRVSubtarget &ST) {
869 addAvailableCaps({Capability::Int64, Capability::Float16, Capability::Float64,
870 Capability::GroupNonUniform, Capability::Image1D,
871 Capability::SampledBuffer, Capability::ImageBuffer,
872 Capability::UniformBufferArrayDynamicIndexing,
873 Capability::SampledImageArrayDynamicIndexing,
874 Capability::StorageBufferArrayDynamicIndexing,
875 Capability::StorageImageArrayDynamicIndexing});
878 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 5))) {
880 {Capability::ShaderNonUniformEXT, Capability::RuntimeDescriptorArrayEXT,
881 Capability::InputAttachmentArrayDynamicIndexingEXT,
882 Capability::UniformTexelBufferArrayDynamicIndexingEXT,
883 Capability::StorageTexelBufferArrayDynamicIndexingEXT,
884 Capability::UniformBufferArrayNonUniformIndexingEXT,
885 Capability::SampledImageArrayNonUniformIndexingEXT,
886 Capability::StorageBufferArrayNonUniformIndexingEXT,
887 Capability::StorageImageArrayNonUniformIndexingEXT,
888 Capability::InputAttachmentArrayNonUniformIndexingEXT,
889 Capability::UniformTexelBufferArrayNonUniformIndexingEXT,
890 Capability::StorageTexelBufferArrayNonUniformIndexingEXT});
894 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 6)))
896 Capability::StorageImageReadWithoutFormat});
904static void addOpDecorateReqs(
const MachineInstr &
MI,
unsigned DecIndex,
907 int64_t DecOp =
MI.getOperand(DecIndex).getImm();
908 auto Dec =
static_cast<SPIRV::Decoration::Decoration
>(DecOp);
910 SPIRV::OperandCategory::DecorationOperand, Dec, ST, Reqs));
912 if (Dec == SPIRV::Decoration::BuiltIn) {
913 int64_t BuiltInOp =
MI.getOperand(DecIndex + 1).getImm();
914 auto BuiltIn =
static_cast<SPIRV::BuiltIn::BuiltIn
>(BuiltInOp);
916 SPIRV::OperandCategory::BuiltInOperand, BuiltIn, ST, Reqs));
917 }
else if (Dec == SPIRV::Decoration::LinkageAttributes) {
918 int64_t LinkageOp =
MI.getOperand(
MI.getNumOperands() - 1).getImm();
919 SPIRV::LinkageType::LinkageType LnkType =
920 static_cast<SPIRV::LinkageType::LinkageType
>(LinkageOp);
921 if (LnkType == SPIRV::LinkageType::LinkOnceODR)
922 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_linkonce_odr);
923 }
else if (Dec == SPIRV::Decoration::CacheControlLoadINTEL ||
924 Dec == SPIRV::Decoration::CacheControlStoreINTEL) {
925 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_cache_controls);
926 }
else if (Dec == SPIRV::Decoration::HostAccessINTEL) {
927 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_global_variable_host_access);
928 }
else if (Dec == SPIRV::Decoration::InitModeINTEL ||
929 Dec == SPIRV::Decoration::ImplementInRegisterMapINTEL) {
931 SPIRV::Extension::SPV_INTEL_global_variable_fpga_decorations);
932 }
else if (Dec == SPIRV::Decoration::NonUniformEXT) {
934 }
else if (Dec == SPIRV::Decoration::FPMaxErrorDecorationINTEL) {
936 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_fp_max_error);
944 assert(
MI.getNumOperands() >= 8 &&
"Insufficient operands for OpTypeImage");
947 int64_t ImgFormatOp =
MI.getOperand(7).getImm();
948 auto ImgFormat =
static_cast<SPIRV::ImageFormat::ImageFormat
>(ImgFormatOp);
952 bool IsArrayed =
MI.getOperand(4).getImm() == 1;
953 bool IsMultisampled =
MI.getOperand(5).getImm() == 1;
954 bool NoSampler =
MI.getOperand(6).getImm() == 2;
957 switch (
MI.getOperand(2).getImm()) {
958 case SPIRV::Dim::DIM_1D:
960 : SPIRV::Capability::Sampled1D);
962 case SPIRV::Dim::DIM_2D:
963 if (IsMultisampled && NoSampler)
966 case SPIRV::Dim::DIM_Cube:
970 : SPIRV::Capability::SampledCubeArray);
972 case SPIRV::Dim::DIM_Rect:
974 : SPIRV::Capability::SampledRect);
976 case SPIRV::Dim::DIM_Buffer:
978 : SPIRV::Capability::SampledBuffer);
980 case SPIRV::Dim::DIM_SubpassData:
986 if (!
ST.isShader()) {
987 if (
MI.getNumOperands() > 8 &&
988 MI.getOperand(8).getImm() == SPIRV::AccessQualifier::ReadWrite)
996#define ATOM_FLT_REQ_EXT_MSG(ExtName) \
997 "The atomic float instruction requires the following SPIR-V " \
998 "extension: SPV_EXT_shader_atomic_float" ExtName
1003 "Expect register operand in atomic float instruction");
1004 Register TypeReg =
MI.getOperand(1).getReg();
1005 SPIRVType *TypeDef =
MI.getMF()->getRegInfo().getVRegDef(TypeReg);
1006 if (TypeDef->
getOpcode() != SPIRV::OpTypeFloat)
1008 "floating-point type scalar");
1011 unsigned Op =
MI.getOpcode();
1012 if (
Op == SPIRV::OpAtomicFAddEXT) {
1013 if (!
ST.canUseExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float_add))
1015 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float_add);
1018 if (!
ST.canUseExtension(
1019 SPIRV::Extension::SPV_EXT_shader_atomic_float16_add))
1021 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float16_add);
1032 "Unexpected floating-point type width in atomic float instruction");
1035 if (!
ST.canUseExtension(
1036 SPIRV::Extension::SPV_EXT_shader_atomic_float_min_max))
1038 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float_min_max);
1041 Reqs.
addCapability(SPIRV::Capability::AtomicFloat16MinMaxEXT);
1044 Reqs.
addCapability(SPIRV::Capability::AtomicFloat32MinMaxEXT);
1047 Reqs.
addCapability(SPIRV::Capability::AtomicFloat64MinMaxEXT);
1051 "Unexpected floating-point type width in atomic float instruction");
1057 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1061 return Dim == SPIRV::Dim::DIM_Buffer && Sampled == 1;
1065 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1069 return Dim == SPIRV::Dim::DIM_Buffer && Sampled == 2;
1073 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1077 return Dim != SPIRV::Dim::DIM_Buffer && Sampled == 1;
1081 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1085 return Dim == SPIRV::Dim::DIM_SubpassData && Sampled == 2;
1089 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1093 return Dim != SPIRV::Dim::DIM_Buffer && Sampled == 2;
1096bool isCombinedImageSampler(
MachineInstr *SampledImageInst) {
1097 if (SampledImageInst->
getOpcode() != SPIRV::OpTypeSampledImage)
1102 auto *ImageInst =
MRI.getUniqueVRegDef(ImageReg);
1103 return isSampledImage(ImageInst);
1107 for (
const auto &
MI :
MRI.reg_instructions(
Reg)) {
1108 if (
MI.getOpcode() != SPIRV::OpDecorate)
1112 if (Dec == SPIRV::Decoration::NonUniformEXT)
1130 if (
StorageClass != SPIRV::StorageClass::StorageClass::UniformConstant &&
1131 StorageClass != SPIRV::StorageClass::StorageClass::Uniform &&
1132 StorageClass != SPIRV::StorageClass::StorageClass::StorageBuffer) {
1138 if (PointeeType->
getOpcode() != SPIRV::OpTypeImage &&
1139 PointeeType->
getOpcode() != SPIRV::OpTypeSampledImage &&
1140 PointeeType->
getOpcode() != SPIRV::OpTypeSampler) {
1145 hasNonUniformDecoration(
Instr.getOperand(0).getReg(),
MRI);
1146 if (isUniformTexelBuffer(PointeeType)) {
1149 SPIRV::Capability::UniformTexelBufferArrayNonUniformIndexingEXT);
1152 SPIRV::Capability::UniformTexelBufferArrayDynamicIndexingEXT);
1153 }
else if (isInputAttachment(PointeeType)) {
1156 SPIRV::Capability::InputAttachmentArrayNonUniformIndexingEXT);
1159 SPIRV::Capability::InputAttachmentArrayDynamicIndexingEXT);
1160 }
else if (isStorageTexelBuffer(PointeeType)) {
1163 SPIRV::Capability::StorageTexelBufferArrayNonUniformIndexingEXT);
1166 SPIRV::Capability::StorageTexelBufferArrayDynamicIndexingEXT);
1167 }
else if (isSampledImage(PointeeType) ||
1168 isCombinedImageSampler(PointeeType) ||
1169 PointeeType->
getOpcode() == SPIRV::OpTypeSampler) {
1172 SPIRV::Capability::SampledImageArrayNonUniformIndexingEXT);
1175 SPIRV::Capability::SampledImageArrayDynamicIndexing);
1176 }
else if (isStorageImage(PointeeType)) {
1179 SPIRV::Capability::StorageImageArrayNonUniformIndexingEXT);
1182 SPIRV::Capability::StorageImageArrayDynamicIndexing);
1186static bool isImageTypeWithUnknownFormat(
SPIRVType *TypeInst) {
1187 if (TypeInst->
getOpcode() != SPIRV::OpTypeImage)
1196 if (
ST.canUseExtension(SPIRV::Extension::SPV_KHR_integer_dot_product))
1197 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_integer_dot_product);
1201 assert(
MI.getOperand(2).isReg() &&
"Unexpected operand in dot");
1205 assert(
Input->getOperand(1).isReg() &&
"Unexpected operand in dot input");
1209 if (TypeDef->
getOpcode() == SPIRV::OpTypeInt) {
1211 Reqs.
addCapability(SPIRV::Capability::DotProductInput4x8BitPacked);
1212 }
else if (TypeDef->
getOpcode() == SPIRV::OpTypeVector) {
1217 "Dot operand of 8-bit integer type requires 4 components");
1218 Reqs.
addCapability(SPIRV::Capability::DotProductInput4x8Bit);
1225static bool isBFloat16Type(
const SPIRVType *TypeDef) {
1227 TypeDef->
getOpcode() == SPIRV::OpTypeFloat &&
1235 switch (
MI.getOpcode()) {
1236 case SPIRV::OpMemoryModel: {
1237 int64_t Addr =
MI.getOperand(0).getImm();
1240 int64_t Mem =
MI.getOperand(1).getImm();
1245 case SPIRV::OpEntryPoint: {
1246 int64_t
Exe =
MI.getOperand(0).getImm();
1251 case SPIRV::OpExecutionMode:
1252 case SPIRV::OpExecutionModeId: {
1253 int64_t
Exe =
MI.getOperand(1).getImm();
1258 case SPIRV::OpTypeMatrix:
1261 case SPIRV::OpTypeInt: {
1262 unsigned BitWidth =
MI.getOperand(1).getImm();
1271 case SPIRV::OpDot: {
1274 if (isBFloat16Type(TypeDef))
1275 Reqs.
addCapability(SPIRV::Capability::BFloat16DotProductKHR);
1278 case SPIRV::OpTypeFloat: {
1279 unsigned BitWidth =
MI.getOperand(1).getImm();
1283 if (isBFloat16Type(&
MI)) {
1284 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_bfloat16))
1286 "following SPIR-V extension: SPV_KHR_bfloat16",
1296 case SPIRV::OpTypeVector: {
1297 unsigned NumComponents =
MI.getOperand(2).getImm();
1298 if (NumComponents == 8 || NumComponents == 16)
1302 case SPIRV::OpTypePointer: {
1303 auto SC =
MI.getOperand(1).getImm();
1314 (TypeDef->
getOpcode() == SPIRV::OpTypeFloat) &&
1319 case SPIRV::OpExtInst: {
1320 if (
MI.getOperand(2).getImm() ==
1321 static_cast<int64_t
>(
1322 SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100)) {
1323 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_non_semantic_info);
1327 case SPIRV::OpAliasDomainDeclINTEL:
1328 case SPIRV::OpAliasScopeDeclINTEL:
1329 case SPIRV::OpAliasScopeListDeclINTEL: {
1330 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_memory_access_aliasing);
1331 Reqs.
addCapability(SPIRV::Capability::MemoryAccessAliasingINTEL);
1334 case SPIRV::OpBitReverse:
1335 case SPIRV::OpBitFieldInsert:
1336 case SPIRV::OpBitFieldSExtract:
1337 case SPIRV::OpBitFieldUExtract:
1338 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_bit_instructions)) {
1342 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_bit_instructions);
1345 case SPIRV::OpTypeRuntimeArray:
1348 case SPIRV::OpTypeOpaque:
1349 case SPIRV::OpTypeEvent:
1352 case SPIRV::OpTypePipe:
1353 case SPIRV::OpTypeReserveId:
1356 case SPIRV::OpTypeDeviceEvent:
1357 case SPIRV::OpTypeQueue:
1358 case SPIRV::OpBuildNDRange:
1361 case SPIRV::OpDecorate:
1362 case SPIRV::OpDecorateId:
1363 case SPIRV::OpDecorateString:
1364 addOpDecorateReqs(
MI, 1, Reqs, ST);
1366 case SPIRV::OpMemberDecorate:
1367 case SPIRV::OpMemberDecorateString:
1368 addOpDecorateReqs(
MI, 2, Reqs, ST);
1370 case SPIRV::OpInBoundsPtrAccessChain:
1373 case SPIRV::OpConstantSampler:
1376 case SPIRV::OpInBoundsAccessChain:
1377 case SPIRV::OpAccessChain:
1378 addOpAccessChainReqs(
MI, Reqs, ST);
1380 case SPIRV::OpTypeImage:
1381 addOpTypeImageReqs(
MI, Reqs, ST);
1383 case SPIRV::OpTypeSampler:
1384 if (!
ST.isShader()) {
1388 case SPIRV::OpTypeForwardPointer:
1392 case SPIRV::OpAtomicFlagTestAndSet:
1393 case SPIRV::OpAtomicLoad:
1394 case SPIRV::OpAtomicStore:
1395 case SPIRV::OpAtomicExchange:
1396 case SPIRV::OpAtomicCompareExchange:
1397 case SPIRV::OpAtomicIIncrement:
1398 case SPIRV::OpAtomicIDecrement:
1399 case SPIRV::OpAtomicIAdd:
1400 case SPIRV::OpAtomicISub:
1401 case SPIRV::OpAtomicUMin:
1402 case SPIRV::OpAtomicUMax:
1403 case SPIRV::OpAtomicSMin:
1404 case SPIRV::OpAtomicSMax:
1405 case SPIRV::OpAtomicAnd:
1406 case SPIRV::OpAtomicOr:
1407 case SPIRV::OpAtomicXor: {
1410 if (
MI.getOpcode() == SPIRV::OpAtomicStore) {
1412 InstrPtr =
MRI.getVRegDef(
MI.getOperand(3).getReg());
1413 assert(InstrPtr &&
"Unexpected type instruction for OpAtomicStore");
1418 if (TypeDef->
getOpcode() == SPIRV::OpTypeInt) {
1425 case SPIRV::OpGroupNonUniformIAdd:
1426 case SPIRV::OpGroupNonUniformFAdd:
1427 case SPIRV::OpGroupNonUniformIMul:
1428 case SPIRV::OpGroupNonUniformFMul:
1429 case SPIRV::OpGroupNonUniformSMin:
1430 case SPIRV::OpGroupNonUniformUMin:
1431 case SPIRV::OpGroupNonUniformFMin:
1432 case SPIRV::OpGroupNonUniformSMax:
1433 case SPIRV::OpGroupNonUniformUMax:
1434 case SPIRV::OpGroupNonUniformFMax:
1435 case SPIRV::OpGroupNonUniformBitwiseAnd:
1436 case SPIRV::OpGroupNonUniformBitwiseOr:
1437 case SPIRV::OpGroupNonUniformBitwiseXor:
1438 case SPIRV::OpGroupNonUniformLogicalAnd:
1439 case SPIRV::OpGroupNonUniformLogicalOr:
1440 case SPIRV::OpGroupNonUniformLogicalXor: {
1442 int64_t GroupOp =
MI.getOperand(3).getImm();
1444 case SPIRV::GroupOperation::Reduce:
1445 case SPIRV::GroupOperation::InclusiveScan:
1446 case SPIRV::GroupOperation::ExclusiveScan:
1447 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformArithmetic);
1449 case SPIRV::GroupOperation::ClusteredReduce:
1450 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformClustered);
1452 case SPIRV::GroupOperation::PartitionedReduceNV:
1453 case SPIRV::GroupOperation::PartitionedInclusiveScanNV:
1454 case SPIRV::GroupOperation::PartitionedExclusiveScanNV:
1455 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformPartitionedNV);
1460 case SPIRV::OpGroupNonUniformShuffle:
1461 case SPIRV::OpGroupNonUniformShuffleXor:
1462 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformShuffle);
1464 case SPIRV::OpGroupNonUniformShuffleUp:
1465 case SPIRV::OpGroupNonUniformShuffleDown:
1466 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformShuffleRelative);
1468 case SPIRV::OpGroupAll:
1469 case SPIRV::OpGroupAny:
1470 case SPIRV::OpGroupBroadcast:
1471 case SPIRV::OpGroupIAdd:
1472 case SPIRV::OpGroupFAdd:
1473 case SPIRV::OpGroupFMin:
1474 case SPIRV::OpGroupUMin:
1475 case SPIRV::OpGroupSMin:
1476 case SPIRV::OpGroupFMax:
1477 case SPIRV::OpGroupUMax:
1478 case SPIRV::OpGroupSMax:
1481 case SPIRV::OpGroupNonUniformElect:
1484 case SPIRV::OpGroupNonUniformAll:
1485 case SPIRV::OpGroupNonUniformAny:
1486 case SPIRV::OpGroupNonUniformAllEqual:
1489 case SPIRV::OpGroupNonUniformBroadcast:
1490 case SPIRV::OpGroupNonUniformBroadcastFirst:
1491 case SPIRV::OpGroupNonUniformBallot:
1492 case SPIRV::OpGroupNonUniformInverseBallot:
1493 case SPIRV::OpGroupNonUniformBallotBitExtract:
1494 case SPIRV::OpGroupNonUniformBallotBitCount:
1495 case SPIRV::OpGroupNonUniformBallotFindLSB:
1496 case SPIRV::OpGroupNonUniformBallotFindMSB:
1497 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformBallot);
1499 case SPIRV::OpSubgroupShuffleINTEL:
1500 case SPIRV::OpSubgroupShuffleDownINTEL:
1501 case SPIRV::OpSubgroupShuffleUpINTEL:
1502 case SPIRV::OpSubgroupShuffleXorINTEL:
1503 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {
1504 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_subgroups);
1505 Reqs.
addCapability(SPIRV::Capability::SubgroupShuffleINTEL);
1508 case SPIRV::OpSubgroupBlockReadINTEL:
1509 case SPIRV::OpSubgroupBlockWriteINTEL:
1510 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {
1511 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_subgroups);
1512 Reqs.
addCapability(SPIRV::Capability::SubgroupBufferBlockIOINTEL);
1515 case SPIRV::OpSubgroupImageBlockReadINTEL:
1516 case SPIRV::OpSubgroupImageBlockWriteINTEL:
1517 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {
1518 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_subgroups);
1519 Reqs.
addCapability(SPIRV::Capability::SubgroupImageBlockIOINTEL);
1522 case SPIRV::OpSubgroupImageMediaBlockReadINTEL:
1523 case SPIRV::OpSubgroupImageMediaBlockWriteINTEL:
1524 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_media_block_io)) {
1525 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_media_block_io);
1526 Reqs.
addCapability(SPIRV::Capability::SubgroupImageMediaBlockIOINTEL);
1529 case SPIRV::OpAssumeTrueKHR:
1530 case SPIRV::OpExpectKHR:
1531 if (
ST.canUseExtension(SPIRV::Extension::SPV_KHR_expect_assume)) {
1532 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_expect_assume);
1536 case SPIRV::OpPtrCastToCrossWorkgroupINTEL:
1537 case SPIRV::OpCrossWorkgroupCastToPtrINTEL:
1538 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_usm_storage_classes)) {
1539 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_usm_storage_classes);
1540 Reqs.
addCapability(SPIRV::Capability::USMStorageClassesINTEL);
1543 case SPIRV::OpConstantFunctionPointerINTEL:
1544 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_function_pointers)) {
1545 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_function_pointers);
1546 Reqs.
addCapability(SPIRV::Capability::FunctionPointersINTEL);
1549 case SPIRV::OpGroupNonUniformRotateKHR:
1550 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_subgroup_rotate))
1552 "following SPIR-V extension: SPV_KHR_subgroup_rotate",
1554 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_subgroup_rotate);
1555 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformRotateKHR);
1558 case SPIRV::OpGroupIMulKHR:
1559 case SPIRV::OpGroupFMulKHR:
1560 case SPIRV::OpGroupBitwiseAndKHR:
1561 case SPIRV::OpGroupBitwiseOrKHR:
1562 case SPIRV::OpGroupBitwiseXorKHR:
1563 case SPIRV::OpGroupLogicalAndKHR:
1564 case SPIRV::OpGroupLogicalOrKHR:
1565 case SPIRV::OpGroupLogicalXorKHR:
1566 if (
ST.canUseExtension(
1567 SPIRV::Extension::SPV_KHR_uniform_group_instructions)) {
1568 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_uniform_group_instructions);
1569 Reqs.
addCapability(SPIRV::Capability::GroupUniformArithmeticKHR);
1572 case SPIRV::OpReadClockKHR:
1573 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_shader_clock))
1575 "following SPIR-V extension: SPV_KHR_shader_clock",
1577 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_shader_clock);
1580 case SPIRV::OpFunctionPointerCallINTEL:
1581 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_function_pointers)) {
1582 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_function_pointers);
1583 Reqs.
addCapability(SPIRV::Capability::FunctionPointersINTEL);
1586 case SPIRV::OpAtomicFAddEXT:
1587 case SPIRV::OpAtomicFMinEXT:
1588 case SPIRV::OpAtomicFMaxEXT:
1589 AddAtomicFloatRequirements(
MI, Reqs, ST);
1591 case SPIRV::OpConvertBF16ToFINTEL:
1592 case SPIRV::OpConvertFToBF16INTEL:
1593 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bfloat16_conversion)) {
1594 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bfloat16_conversion);
1595 Reqs.
addCapability(SPIRV::Capability::BFloat16ConversionINTEL);
1598 case SPIRV::OpRoundFToTF32INTEL:
1599 if (
ST.canUseExtension(
1600 SPIRV::Extension::SPV_INTEL_tensor_float32_conversion)) {
1601 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_tensor_float32_conversion);
1602 Reqs.
addCapability(SPIRV::Capability::TensorFloat32RoundingINTEL);
1605 case SPIRV::OpVariableLengthArrayINTEL:
1606 case SPIRV::OpSaveMemoryINTEL:
1607 case SPIRV::OpRestoreMemoryINTEL:
1608 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_variable_length_array)) {
1609 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_variable_length_array);
1610 Reqs.
addCapability(SPIRV::Capability::VariableLengthArrayINTEL);
1613 case SPIRV::OpAsmTargetINTEL:
1614 case SPIRV::OpAsmINTEL:
1615 case SPIRV::OpAsmCallINTEL:
1616 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_inline_assembly)) {
1617 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_inline_assembly);
1621 case SPIRV::OpTypeCooperativeMatrixKHR: {
1622 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix))
1624 "OpTypeCooperativeMatrixKHR type requires the "
1625 "following SPIR-V extension: SPV_KHR_cooperative_matrix",
1627 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix);
1628 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixKHR);
1631 if (isBFloat16Type(TypeDef))
1632 Reqs.
addCapability(SPIRV::Capability::BFloat16CooperativeMatrixKHR);
1635 case SPIRV::OpArithmeticFenceEXT:
1636 if (!
ST.canUseExtension(SPIRV::Extension::SPV_EXT_arithmetic_fence))
1638 "following SPIR-V extension: SPV_EXT_arithmetic_fence",
1640 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_arithmetic_fence);
1643 case SPIRV::OpControlBarrierArriveINTEL:
1644 case SPIRV::OpControlBarrierWaitINTEL:
1645 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_split_barrier)) {
1646 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_split_barrier);
1650 case SPIRV::OpCooperativeMatrixMulAddKHR: {
1651 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix))
1653 "following SPIR-V extension: "
1654 "SPV_KHR_cooperative_matrix",
1656 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix);
1657 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixKHR);
1658 constexpr unsigned MulAddMaxSize = 6;
1659 if (
MI.getNumOperands() != MulAddMaxSize)
1661 const int64_t CoopOperands =
MI.getOperand(MulAddMaxSize - 1).getImm();
1663 SPIRV::CooperativeMatrixOperands::MatrixAAndBTF32ComponentsINTEL) {
1664 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
1666 "require the following SPIR-V extension: "
1667 "SPV_INTEL_joint_matrix",
1669 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
1671 SPIRV::Capability::CooperativeMatrixTF32ComponentTypeINTEL);
1674 MatrixAAndBBFloat16ComponentsINTEL ||
1676 SPIRV::CooperativeMatrixOperands::MatrixCBFloat16ComponentsINTEL ||
1678 MatrixResultBFloat16ComponentsINTEL) {
1679 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
1681 "require the following SPIR-V extension: "
1682 "SPV_INTEL_joint_matrix",
1684 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
1686 SPIRV::Capability::CooperativeMatrixBFloat16ComponentTypeINTEL);
1690 case SPIRV::OpCooperativeMatrixLoadKHR:
1691 case SPIRV::OpCooperativeMatrixStoreKHR:
1692 case SPIRV::OpCooperativeMatrixLoadCheckedINTEL:
1693 case SPIRV::OpCooperativeMatrixStoreCheckedINTEL:
1694 case SPIRV::OpCooperativeMatrixPrefetchINTEL: {
1695 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix))
1697 "following SPIR-V extension: "
1698 "SPV_KHR_cooperative_matrix",
1700 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix);
1701 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixKHR);
1705 std::unordered_map<unsigned, unsigned> LayoutToInstMap = {
1706 {SPIRV::OpCooperativeMatrixLoadKHR, 3},
1707 {SPIRV::OpCooperativeMatrixStoreKHR, 2},
1708 {SPIRV::OpCooperativeMatrixLoadCheckedINTEL, 5},
1709 {SPIRV::OpCooperativeMatrixStoreCheckedINTEL, 4},
1710 {SPIRV::OpCooperativeMatrixPrefetchINTEL, 4}};
1712 const auto OpCode =
MI.getOpcode();
1713 const unsigned LayoutNum = LayoutToInstMap[OpCode];
1714 Register RegLayout =
MI.getOperand(LayoutNum).getReg();
1717 if (MILayout->
getOpcode() == SPIRV::OpConstantI) {
1720 static_cast<unsigned>(SPIRV::CooperativeMatrixLayout::PackedINTEL)) {
1721 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
1723 "extension: SPV_INTEL_joint_matrix",
1725 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
1726 Reqs.
addCapability(SPIRV::Capability::PackedCooperativeMatrixINTEL);
1731 if (OpCode == SPIRV::OpCooperativeMatrixLoadKHR ||
1732 OpCode == SPIRV::OpCooperativeMatrixStoreKHR)
1735 std::string InstName;
1737 case SPIRV::OpCooperativeMatrixPrefetchINTEL:
1738 InstName =
"OpCooperativeMatrixPrefetchINTEL";
1740 case SPIRV::OpCooperativeMatrixLoadCheckedINTEL:
1741 InstName =
"OpCooperativeMatrixLoadCheckedINTEL";
1743 case SPIRV::OpCooperativeMatrixStoreCheckedINTEL:
1744 InstName =
"OpCooperativeMatrixStoreCheckedINTEL";
1748 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix)) {
1749 const std::string ErrorMsg =
1750 InstName +
" instruction requires the "
1751 "following SPIR-V extension: SPV_INTEL_joint_matrix";
1754 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
1755 if (OpCode == SPIRV::OpCooperativeMatrixPrefetchINTEL) {
1756 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixPrefetchINTEL);
1760 SPIRV::Capability::CooperativeMatrixCheckedInstructionsINTEL);
1763 case SPIRV::OpCooperativeMatrixConstructCheckedINTEL:
1764 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
1766 "instructions require the following SPIR-V extension: "
1767 "SPV_INTEL_joint_matrix",
1769 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
1771 SPIRV::Capability::CooperativeMatrixCheckedInstructionsINTEL);
1773 case SPIRV::OpCooperativeMatrixGetElementCoordINTEL:
1774 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
1776 "following SPIR-V extension: SPV_INTEL_joint_matrix",
1778 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
1780 SPIRV::Capability::CooperativeMatrixInvocationInstructionsINTEL);
1782 case SPIRV::OpConvertHandleToImageINTEL:
1783 case SPIRV::OpConvertHandleToSamplerINTEL:
1784 case SPIRV::OpConvertHandleToSampledImageINTEL:
1785 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bindless_images))
1787 "instructions require the following SPIR-V extension: "
1788 "SPV_INTEL_bindless_images",
1790 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bindless_images);
1793 case SPIRV::OpSubgroup2DBlockLoadINTEL:
1794 case SPIRV::OpSubgroup2DBlockLoadTransposeINTEL:
1795 case SPIRV::OpSubgroup2DBlockLoadTransformINTEL:
1796 case SPIRV::OpSubgroup2DBlockPrefetchINTEL:
1797 case SPIRV::OpSubgroup2DBlockStoreINTEL: {
1798 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_2d_block_io))
1800 "Prefetch/Store]INTEL instructions require the "
1801 "following SPIR-V extension: SPV_INTEL_2d_block_io",
1803 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_2d_block_io);
1804 Reqs.
addCapability(SPIRV::Capability::Subgroup2DBlockIOINTEL);
1806 const auto OpCode =
MI.getOpcode();
1807 if (OpCode == SPIRV::OpSubgroup2DBlockLoadTransposeINTEL) {
1808 Reqs.
addCapability(SPIRV::Capability::Subgroup2DBlockTransposeINTEL);
1811 if (OpCode == SPIRV::OpSubgroup2DBlockLoadTransformINTEL) {
1812 Reqs.
addCapability(SPIRV::Capability::Subgroup2DBlockTransformINTEL);
1817 case SPIRV::OpKill: {
1820 case SPIRV::OpDemoteToHelperInvocation:
1821 Reqs.
addCapability(SPIRV::Capability::DemoteToHelperInvocation);
1823 if (
ST.canUseExtension(
1824 SPIRV::Extension::SPV_EXT_demote_to_helper_invocation)) {
1827 SPIRV::Extension::SPV_EXT_demote_to_helper_invocation);
1832 case SPIRV::OpSUDot:
1833 case SPIRV::OpSDotAccSat:
1834 case SPIRV::OpUDotAccSat:
1835 case SPIRV::OpSUDotAccSat:
1836 AddDotProductRequirements(
MI, Reqs, ST);
1838 case SPIRV::OpImageRead: {
1839 Register ImageReg =
MI.getOperand(2).getReg();
1840 SPIRVType *TypeDef =
ST.getSPIRVGlobalRegistry()->getResultType(
1848 if (isImageTypeWithUnknownFormat(TypeDef) &&
ST.isShader())
1849 Reqs.
addCapability(SPIRV::Capability::StorageImageReadWithoutFormat);
1852 case SPIRV::OpImageWrite: {
1853 Register ImageReg =
MI.getOperand(0).getReg();
1854 SPIRVType *TypeDef =
ST.getSPIRVGlobalRegistry()->getResultType(
1862 if (isImageTypeWithUnknownFormat(TypeDef) &&
ST.isShader())
1863 Reqs.
addCapability(SPIRV::Capability::StorageImageWriteWithoutFormat);
1866 case SPIRV::OpTypeStructContinuedINTEL:
1867 case SPIRV::OpConstantCompositeContinuedINTEL:
1868 case SPIRV::OpSpecConstantCompositeContinuedINTEL:
1869 case SPIRV::OpCompositeConstructContinuedINTEL: {
1870 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_long_composites))
1872 "Continued instructions require the "
1873 "following SPIR-V extension: SPV_INTEL_long_composites",
1875 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_long_composites);
1879 case SPIRV::OpSubgroupMatrixMultiplyAccumulateINTEL: {
1880 if (!
ST.canUseExtension(
1881 SPIRV::Extension::SPV_INTEL_subgroup_matrix_multiply_accumulate))
1883 "OpSubgroupMatrixMultiplyAccumulateINTEL instruction requires the "
1885 "extension: SPV_INTEL_subgroup_matrix_multiply_accumulate",
1888 SPIRV::Extension::SPV_INTEL_subgroup_matrix_multiply_accumulate);
1890 SPIRV::Capability::SubgroupMatrixMultiplyAccumulateINTEL);
1893 case SPIRV::OpBitwiseFunctionINTEL: {
1894 if (!
ST.canUseExtension(
1895 SPIRV::Extension::SPV_INTEL_ternary_bitwise_function))
1897 "OpBitwiseFunctionINTEL instruction requires the following SPIR-V "
1898 "extension: SPV_INTEL_ternary_bitwise_function",
1900 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_ternary_bitwise_function);
1901 Reqs.
addCapability(SPIRV::Capability::TernaryBitwiseFunctionINTEL);
1904 case SPIRV::OpCopyMemorySized: {
1918 SPIRV::Capability::Shader);
1924 for (
auto F = M.begin(),
E = M.end();
F !=
E; ++
F) {
1930 addInstrRequirements(
MI, MAI.
Reqs, ST);
1933 auto Node = M.getNamedMetadata(
"spirv.ExecutionMode");
1935 bool RequireFloatControls =
false, RequireFloatControls2 =
false,
1937 bool HasFloatControls2 =
1938 ST.canUseExtension(SPIRV::Extension::SPV_INTEL_float_controls2);
1939 for (
unsigned i = 0; i <
Node->getNumOperands(); i++) {
1945 auto EM =
Const->getZExtValue();
1949 case SPIRV::ExecutionMode::DenormPreserve:
1950 case SPIRV::ExecutionMode::DenormFlushToZero:
1951 case SPIRV::ExecutionMode::SignedZeroInfNanPreserve:
1952 case SPIRV::ExecutionMode::RoundingModeRTE:
1953 case SPIRV::ExecutionMode::RoundingModeRTZ:
1954 RequireFloatControls = VerLower14;
1956 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
1958 case SPIRV::ExecutionMode::RoundingModeRTPINTEL:
1959 case SPIRV::ExecutionMode::RoundingModeRTNINTEL:
1960 case SPIRV::ExecutionMode::FloatingPointModeALTINTEL:
1961 case SPIRV::ExecutionMode::FloatingPointModeIEEEINTEL:
1962 if (HasFloatControls2) {
1963 RequireFloatControls2 =
true;
1965 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
1970 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
1975 if (RequireFloatControls &&
1976 ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls))
1978 if (RequireFloatControls2)
1981 for (
auto FI = M.begin(),
E = M.end(); FI !=
E; ++FI) {
1983 if (
F.isDeclaration())
1985 if (
F.getMetadata(
"reqd_work_group_size"))
1987 SPIRV::OperandCategory::ExecutionModeOperand,
1988 SPIRV::ExecutionMode::LocalSize, ST);
1989 if (
F.getFnAttribute(
"hlsl.numthreads").isValid()) {
1991 SPIRV::OperandCategory::ExecutionModeOperand,
1992 SPIRV::ExecutionMode::LocalSize, ST);
1994 if (
F.getMetadata(
"work_group_size_hint"))
1996 SPIRV::OperandCategory::ExecutionModeOperand,
1997 SPIRV::ExecutionMode::LocalSizeHint, ST);
1998 if (
F.getMetadata(
"intel_reqd_sub_group_size"))
2000 SPIRV::OperandCategory::ExecutionModeOperand,
2001 SPIRV::ExecutionMode::SubgroupSize, ST);
2002 if (
F.getMetadata(
"vec_type_hint"))
2004 SPIRV::OperandCategory::ExecutionModeOperand,
2005 SPIRV::ExecutionMode::VecTypeHint, ST);
2007 if (
F.hasOptNone()) {
2008 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_optnone)) {
2011 }
else if (
ST.canUseExtension(SPIRV::Extension::SPV_EXT_optnone)) {
2020 unsigned Flags = SPIRV::FPFastMathMode::None;
2022 Flags |= SPIRV::FPFastMathMode::NotNaN;
2024 Flags |= SPIRV::FPFastMathMode::NotInf;
2026 Flags |= SPIRV::FPFastMathMode::NSZ;
2028 Flags |= SPIRV::FPFastMathMode::AllowRecip;
2030 Flags |= SPIRV::FPFastMathMode::Fast;
2034static bool isFastMathMathModeAvailable(
const SPIRVSubtarget &ST) {
2039 return ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2);
2046 getSymbolicOperandRequirements(SPIRV::OperandCategory::DecorationOperand,
2047 SPIRV::Decoration::NoSignedWrap, ST, Reqs)
2050 SPIRV::Decoration::NoSignedWrap, {});
2053 getSymbolicOperandRequirements(SPIRV::OperandCategory::DecorationOperand,
2054 SPIRV::Decoration::NoUnsignedWrap, ST,
2058 SPIRV::Decoration::NoUnsignedWrap, {});
2060 if (!
TII.canUseFastMathFlags(
I))
2062 unsigned FMFlags = getFastMathFlags(
I);
2063 if (FMFlags == SPIRV::FPFastMathMode::None)
2066 if (isFastMathMathModeAvailable(ST)) {
2067 Register DstReg =
I.getOperand(0).getReg();
2077 for (
auto F = M.begin(),
E = M.end();
F !=
E; ++
F) {
2081 for (
auto &
MBB : *MF)
2082 for (
auto &
MI :
MBB)
2083 handleMIFlagDecoration(
MI, ST,
TII, MAI.
Reqs);
2090 for (
auto F = M.begin(),
E = M.end();
F !=
E; ++
F) {
2095 for (
auto &
MBB : *MF) {
2096 if (!
MBB.hasName() ||
MBB.empty())
2100 MRI.setRegClass(
Reg, &SPIRV::IDRegClass);
2111 for (
auto F = M.begin(),
E = M.end();
F !=
E; ++
F) {
2115 for (
auto &
MBB : *MF) {
2117 MI.setDesc(
TII.get(SPIRV::OpPhi));
2120 MI.insert(
MI.operands_begin() + 1,
2121 {MachineOperand::CreateReg(ResTypeReg, false)});