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) {
259 unsigned Opcode =
MI.getOpcode();
260 if ((Opcode == SPIRV::OpDecorate) && i >= 2) {
261 unsigned DecorationID =
MI.getOperand(1).getImm();
262 if (DecorationID != SPIRV::Decoration::FuncParamAttr &&
263 DecorationID != SPIRV::Decoration::UserSemantic &&
264 DecorationID != SPIRV::Decoration::CacheControlLoadINTEL &&
265 DecorationID != SPIRV::Decoration::CacheControlStoreINTEL)
271 if (!UseDefReg && MO.
isDef()) {
279 dbgs() <<
"Unexpectedly, no global id found for the operand ";
281 dbgs() <<
"\nInstruction: ";
300 appendDecorationsForReg(
MI.getMF()->getRegInfo(), DefReg, Signature);
307 unsigned Opcode =
MI.getOpcode();
309 case SPIRV::OpTypeForwardPointer:
312 case SPIRV::OpVariable:
313 return static_cast<SPIRV::StorageClass::StorageClass
>(
314 MI.getOperand(2).
getImm()) != SPIRV::StorageClass::Function;
315 case SPIRV::OpFunction:
316 case SPIRV::OpFunctionParameter:
319 if (GR->hasConstFunPtr() && Opcode == SPIRV::OpUndef) {
321 for (MachineInstr &
UseMI :
MRI.use_instructions(DefReg)) {
322 if (
UseMI.getOpcode() != SPIRV::OpConstantFunctionPointerINTEL)
328 MAI.setSkipEmission(&
MI);
332 return TII->isTypeDeclInstr(
MI) || TII->isConstantInstr(
MI) ||
333 TII->isInlineAsmDefInstr(
MI);
339void SPIRVModuleAnalysis::visitFunPtrUse(
341 std::map<const Value *, unsigned> &GlobalToGReg,
const MachineFunction *MF,
343 const MachineOperand *OpFunDef =
344 GR->getFunctionDefinitionByUse(&
MI.getOperand(2));
347 const MachineInstr *OpDefMI = OpFunDef->
getParent();
350 const MachineRegisterInfo &FunDefMRI = FunDefMF->
getRegInfo();
352 visitDecl(FunDefMRI, SignatureToGReg, GlobalToGReg, FunDefMF, *OpDefMI);
354 }
while (OpDefMI && (OpDefMI->
getOpcode() == SPIRV::OpFunction ||
355 OpDefMI->
getOpcode() == SPIRV::OpFunctionParameter));
357 MCRegister GlobalFunDefReg =
358 MAI.getRegisterAlias(FunDefMF, OpFunDef->
getReg());
360 "Function definition must refer to a global register");
361 MAI.setRegisterAlias(MF, OpReg, GlobalFunDefReg);
366void SPIRVModuleAnalysis::visitDecl(
368 std::map<const Value *, unsigned> &GlobalToGReg,
const MachineFunction *MF,
370 unsigned Opcode =
MI.getOpcode();
373 for (
const MachineOperand &MO :
MI.operands()) {
378 if (Opcode == SPIRV::OpConstantFunctionPointerINTEL &&
379 MRI.getRegClass(OpReg) == &SPIRV::pIDRegClass) {
380 visitFunPtrUse(OpReg, SignatureToGReg, GlobalToGReg, MF,
MI);
384 if (
MAI.hasRegisterAlias(MF, MO.
getReg()))
387 if (
const MachineInstr *OpDefMI =
MRI.getUniqueVRegDef(OpReg)) {
388 if (isDeclSection(
MRI, *OpDefMI))
389 visitDecl(
MRI, SignatureToGReg, GlobalToGReg, MF, *OpDefMI);
395 dbgs() <<
"Unexpectedly, no unique definition for the operand ";
397 dbgs() <<
"\nInstruction: ";
402 "No unique definition is found for the virtual register");
406 bool IsFunDef =
false;
407 if (TII->isSpecConstantInstr(
MI)) {
408 GReg =
MAI.getNextIDRegister();
410 }
else if (Opcode == SPIRV::OpFunction ||
411 Opcode == SPIRV::OpFunctionParameter) {
412 GReg = handleFunctionOrParameter(MF,
MI, GlobalToGReg, IsFunDef);
413 }
else if (Opcode == SPIRV::OpTypeStruct ||
414 Opcode == SPIRV::OpConstantComposite) {
415 GReg = handleTypeDeclOrConstant(
MI, SignatureToGReg);
416 const MachineInstr *NextInstr =
MI.getNextNode();
418 ((Opcode == SPIRV::OpTypeStruct &&
419 NextInstr->
getOpcode() == SPIRV::OpTypeStructContinuedINTEL) ||
420 (Opcode == SPIRV::OpConstantComposite &&
422 SPIRV::OpConstantCompositeContinuedINTEL))) {
423 MCRegister Tmp = handleTypeDeclOrConstant(*NextInstr, SignatureToGReg);
425 MAI.setSkipEmission(NextInstr);
428 }
else if (TII->isTypeDeclInstr(
MI) || TII->isConstantInstr(
MI) ||
429 TII->isInlineAsmDefInstr(
MI)) {
430 GReg = handleTypeDeclOrConstant(
MI, SignatureToGReg);
431 }
else if (Opcode == SPIRV::OpVariable) {
432 GReg = handleVariable(MF,
MI, GlobalToGReg);
435 dbgs() <<
"\nInstruction: ";
441 MAI.setRegisterAlias(MF,
MI.getOperand(0).getReg(), GReg);
443 MAI.setSkipEmission(&
MI);
446MCRegister SPIRVModuleAnalysis::handleFunctionOrParameter(
448 std::map<const Value *, unsigned> &GlobalToGReg,
bool &IsFunDef) {
449 const Value *GObj = GR->getGlobalObject(MF,
MI.getOperand(0).getReg());
450 assert(GObj &&
"Unregistered global definition");
454 assert(
F &&
"Expected a reference to a function or an argument");
455 IsFunDef = !
F->isDeclaration();
456 auto [It,
Inserted] = GlobalToGReg.try_emplace(GObj);
459 MCRegister GReg =
MAI.getNextIDRegister();
467SPIRVModuleAnalysis::handleTypeDeclOrConstant(
const MachineInstr &
MI,
470 auto [It,
Inserted] = SignatureToGReg.try_emplace(MISign);
473 MCRegister GReg =
MAI.getNextIDRegister();
479MCRegister SPIRVModuleAnalysis::handleVariable(
481 std::map<const Value *, unsigned> &GlobalToGReg) {
482 MAI.GlobalVarList.push_back(&
MI);
483 const Value *GObj = GR->getGlobalObject(MF,
MI.getOperand(0).getReg());
484 assert(GObj &&
"Unregistered global definition");
485 auto [It,
Inserted] = GlobalToGReg.try_emplace(GObj);
488 MCRegister GReg =
MAI.getNextIDRegister();
494void SPIRVModuleAnalysis::collectDeclarations(
const Module &M) {
496 std::map<const Value *, unsigned> GlobalToGReg;
497 for (
auto F =
M.begin(),
E =
M.end();
F !=
E; ++
F) {
498 MachineFunction *MF = MMI->getMachineFunction(*
F);
502 unsigned PastHeader = 0;
503 for (MachineBasicBlock &
MBB : *MF) {
504 for (MachineInstr &
MI :
MBB) {
505 if (
MI.getNumOperands() == 0)
507 unsigned Opcode =
MI.getOpcode();
508 if (Opcode == SPIRV::OpFunction) {
509 if (PastHeader == 0) {
513 }
else if (Opcode == SPIRV::OpFunctionParameter) {
516 }
else if (PastHeader > 0) {
520 const MachineOperand &DefMO =
MI.getOperand(0);
522 case SPIRV::OpExtension:
523 MAI.Reqs.addExtension(SPIRV::Extension::Extension(DefMO.
getImm()));
524 MAI.setSkipEmission(&
MI);
526 case SPIRV::OpCapability:
527 MAI.Reqs.addCapability(SPIRV::Capability::Capability(DefMO.
getImm()));
528 MAI.setSkipEmission(&
MI);
533 if (DefMO.
isReg() && isDeclSection(
MRI,
MI) &&
534 !
MAI.hasRegisterAlias(MF, DefMO.
getReg()))
535 visitDecl(
MRI, SignatureToGReg, GlobalToGReg, MF,
MI);
548 if (
MI.getOpcode() == SPIRV::OpDecorate) {
550 auto Dec =
MI.getOperand(1).getImm();
551 if (Dec == SPIRV::Decoration::LinkageAttributes) {
552 auto Lnk =
MI.getOperand(
MI.getNumOperands() - 1).getImm();
553 if (Lnk == SPIRV::LinkageType::Import) {
558 MAI.FuncMap[ImportedFunc] =
MAI.getRegisterAlias(
MI.getMF(), Target);
561 }
else if (
MI.getOpcode() == SPIRV::OpFunction) {
564 MCRegister GlobalReg =
MAI.getRegisterAlias(
MI.getMF(),
Reg);
566 MAI.FuncMap[
F] = GlobalReg;
575 bool Append =
true) {
578 auto FoundMI = IS.insert(std::move(MISign));
579 if (!FoundMI.second) {
580 if (
MI.getOpcode() == SPIRV::OpDecorate) {
582 "Decoration instructions must have at least 2 operands");
584 "Only OpDecorate instructions can be duplicates");
589 if (
MI.getOperand(1).getImm() != SPIRV::Decoration::FPFastMathMode)
594 if (instrToSignature(*OrigMI, MAI,
true) == MISign) {
595 assert(OrigMI->getNumOperands() ==
MI.getNumOperands() &&
596 "Original instruction must have the same number of operands");
598 OrigMI->getNumOperands() == 3 &&
599 "FPFastMathMode decoration must have 3 operands for OpDecorate");
600 unsigned OrigFlags = OrigMI->getOperand(2).getImm();
601 unsigned NewFlags =
MI.getOperand(2).getImm();
602 if (OrigFlags == NewFlags)
606 unsigned FinalFlags = OrigFlags | NewFlags;
608 <<
"Warning: Conflicting FPFastMathMode decoration flags "
610 << *OrigMI <<
"Original flags: " << OrigFlags
611 <<
", new flags: " << NewFlags
612 <<
". They will be merged on a best effort basis, but not "
613 "validated. Final flags: "
614 << FinalFlags <<
"\n";
621 assert(
false &&
"No original instruction found for the duplicate "
622 "OpDecorate, but we found one in IS.");
635void SPIRVModuleAnalysis::processOtherInstrs(
const Module &M) {
637 for (
auto F =
M.begin(),
E =
M.end();
F !=
E; ++
F) {
638 if (
F->isDeclaration())
640 MachineFunction *MF = MMI->getMachineFunction(*
F);
643 for (MachineBasicBlock &
MBB : *MF)
644 for (MachineInstr &
MI :
MBB) {
645 if (
MAI.getSkipEmission(&
MI))
647 const unsigned OpCode =
MI.getOpcode();
648 if (OpCode == SPIRV::OpString) {
650 }
else if (OpCode == SPIRV::OpExtInst &&
MI.getOperand(2).isImm() &&
651 MI.getOperand(2).getImm() ==
652 SPIRV::InstructionSet::
653 NonSemantic_Shader_DebugInfo_100) {
654 MachineOperand
Ins =
MI.getOperand(3);
655 namespace NS = SPIRV::NonSemanticExtInst;
656 static constexpr int64_t GlobalNonSemanticDITy[] = {
657 NS::DebugSource, NS::DebugCompilationUnit, NS::DebugInfoNone,
658 NS::DebugTypeBasic, NS::DebugTypePointer};
659 bool IsGlobalDI =
false;
660 for (
unsigned Idx = 0; Idx < std::size(GlobalNonSemanticDITy); ++Idx)
661 IsGlobalDI |=
Ins.getImm() == GlobalNonSemanticDITy[Idx];
664 }
else if (OpCode == SPIRV::OpName || OpCode == SPIRV::OpMemberName) {
666 }
else if (OpCode == SPIRV::OpEntryPoint) {
668 }
else if (TII->isAliasingInstr(
MI)) {
670 }
else if (TII->isDecorationInstr(
MI)) {
672 collectFuncNames(
MI, &*
F);
673 }
else if (TII->isConstantInstr(
MI)) {
677 }
else if (OpCode == SPIRV::OpFunction) {
678 collectFuncNames(
MI, &*
F);
679 }
else if (OpCode == SPIRV::OpTypeForwardPointer) {
689void SPIRVModuleAnalysis::numberRegistersGlobally(
const Module &M) {
690 for (
auto F =
M.begin(),
E =
M.end();
F !=
E; ++
F) {
691 if ((*F).isDeclaration())
693 MachineFunction *MF = MMI->getMachineFunction(*
F);
695 for (MachineBasicBlock &
MBB : *MF) {
696 for (MachineInstr &
MI :
MBB) {
697 for (MachineOperand &
Op :
MI.operands()) {
701 if (
MAI.hasRegisterAlias(MF,
Reg))
703 MCRegister NewReg =
MAI.getNextIDRegister();
704 MAI.setRegisterAlias(MF,
Reg, NewReg);
706 if (
MI.getOpcode() != SPIRV::OpExtInst)
708 auto Set =
MI.getOperand(2).getImm();
709 auto [It,
Inserted] =
MAI.ExtInstSetMap.try_emplace(Set);
711 It->second =
MAI.getNextIDRegister();
719 SPIRV::OperandCategory::OperandCategory Category, uint32_t i,
721 addRequirements(getSymbolicOperandRequirements(Category, i, ST, *
this));
724void SPIRV::RequirementHandler::recursiveAddCapabilities(
726 for (
const auto &Cap : ToPrune) {
730 recursiveAddCapabilities(ImplicitDecls);
735 for (
const auto &Cap : ToAdd) {
736 bool IsNewlyInserted = AllCaps.insert(Cap).second;
737 if (!IsNewlyInserted)
741 recursiveAddCapabilities(ImplicitDecls);
742 MinimalCaps.push_back(Cap);
747 const SPIRV::Requirements &Req) {
751 if (Req.
Cap.has_value())
752 addCapabilities({Req.
Cap.value()});
754 addExtensions(Req.
Exts);
757 if (!MaxVersion.empty() && Req.
MinVer > MaxVersion) {
759 <<
" and <= " << MaxVersion <<
"\n");
763 if (MinVersion.empty() || Req.
MinVer > MinVersion)
768 if (!MinVersion.empty() && Req.
MaxVer < MinVersion) {
770 <<
" and >= " << MinVersion <<
"\n");
774 if (MaxVersion.empty() || Req.
MaxVer < MaxVersion)
780 const SPIRVSubtarget &ST)
const {
782 bool IsSatisfiable =
true;
783 auto TargetVer =
ST.getSPIRVVersion();
785 if (!MaxVersion.empty() && !TargetVer.empty() && MaxVersion < TargetVer) {
787 dbgs() <<
"Target SPIR-V version too high for required features\n"
788 <<
"Required max version: " << MaxVersion <<
" target version "
789 << TargetVer <<
"\n");
790 IsSatisfiable =
false;
793 if (!MinVersion.empty() && !TargetVer.empty() && MinVersion > TargetVer) {
794 LLVM_DEBUG(
dbgs() <<
"Target SPIR-V version too low for required features\n"
795 <<
"Required min version: " << MinVersion
796 <<
" target version " << TargetVer <<
"\n");
797 IsSatisfiable =
false;
800 if (!MinVersion.empty() && !MaxVersion.empty() && MinVersion > MaxVersion) {
803 <<
"Version is too low for some features and too high for others.\n"
804 <<
"Required SPIR-V min version: " << MinVersion
805 <<
" required SPIR-V max version " << MaxVersion <<
"\n");
806 IsSatisfiable =
false;
809 AvoidCapabilitiesSet AvoidCaps;
811 AvoidCaps.
S.
insert(SPIRV::Capability::Shader);
813 AvoidCaps.
S.
insert(SPIRV::Capability::Kernel);
815 for (
auto Cap : MinimalCaps) {
816 if (AvailableCaps.contains(Cap) && !AvoidCaps.
S.
contains(Cap))
820 OperandCategory::CapabilityOperand, Cap)
822 IsSatisfiable =
false;
825 for (
auto Ext : AllExtensions) {
826 if (
ST.canUseExtension(Ext))
830 OperandCategory::ExtensionOperand, Ext)
832 IsSatisfiable =
false;
841 for (
const auto Cap : ToAdd)
842 if (AvailableCaps.insert(Cap).second)
844 SPIRV::OperandCategory::CapabilityOperand, Cap));
848 const Capability::Capability
ToRemove,
849 const Capability::Capability IfPresent) {
850 if (AllCaps.contains(IfPresent))
858 addAvailableCaps({Capability::Shader, Capability::Linkage, Capability::Int8,
861 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 3)))
863 Capability::GroupNonUniformVote,
864 Capability::GroupNonUniformArithmetic,
865 Capability::GroupNonUniformBallot,
866 Capability::GroupNonUniformClustered,
867 Capability::GroupNonUniformShuffle,
868 Capability::GroupNonUniformShuffleRelative});
870 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 6)))
872 Capability::DotProductInput4x8Bit,
873 Capability::DotProductInput4x8BitPacked,
874 Capability::DemoteToHelperInvocation});
877 for (
auto Extension :
ST.getAllAvailableExtensions()) {
883 if (!
ST.isShader()) {
884 initAvailableCapabilitiesForOpenCL(ST);
889 initAvailableCapabilitiesForVulkan(ST);
896void RequirementHandler::initAvailableCapabilitiesForOpenCL(
897 const SPIRVSubtarget &ST) {
900 Capability::Kernel, Capability::Vector16,
901 Capability::Groups, Capability::GenericPointer,
902 Capability::StorageImageWriteWithoutFormat,
903 Capability::StorageImageReadWithoutFormat});
904 if (
ST.hasOpenCLFullProfile())
906 if (
ST.hasOpenCLImageSupport()) {
908 Capability::Image1D, Capability::SampledBuffer,
909 Capability::ImageBuffer});
910 if (
ST.isAtLeastOpenCLVer(VersionTuple(2, 0)))
913 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 1)) &&
914 ST.isAtLeastOpenCLVer(VersionTuple(2, 2)))
916 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 4)))
917 addAvailableCaps({Capability::DenormPreserve, Capability::DenormFlushToZero,
918 Capability::SignedZeroInfNanPreserve,
919 Capability::RoundingModeRTE,
920 Capability::RoundingModeRTZ});
927void RequirementHandler::initAvailableCapabilitiesForVulkan(
928 const SPIRVSubtarget &ST) {
931 addAvailableCaps({Capability::Int64, Capability::Float16, Capability::Float64,
932 Capability::GroupNonUniform, Capability::Image1D,
933 Capability::SampledBuffer, Capability::ImageBuffer,
934 Capability::UniformBufferArrayDynamicIndexing,
935 Capability::SampledImageArrayDynamicIndexing,
936 Capability::StorageBufferArrayDynamicIndexing,
937 Capability::StorageImageArrayDynamicIndexing,
938 Capability::DerivativeControl});
941 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 5))) {
943 {Capability::ShaderNonUniformEXT, Capability::RuntimeDescriptorArrayEXT,
944 Capability::InputAttachmentArrayDynamicIndexingEXT,
945 Capability::UniformTexelBufferArrayDynamicIndexingEXT,
946 Capability::StorageTexelBufferArrayDynamicIndexingEXT,
947 Capability::UniformBufferArrayNonUniformIndexingEXT,
948 Capability::SampledImageArrayNonUniformIndexingEXT,
949 Capability::StorageBufferArrayNonUniformIndexingEXT,
950 Capability::StorageImageArrayNonUniformIndexingEXT,
951 Capability::InputAttachmentArrayNonUniformIndexingEXT,
952 Capability::UniformTexelBufferArrayNonUniformIndexingEXT,
953 Capability::StorageTexelBufferArrayNonUniformIndexingEXT});
957 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 6)))
959 Capability::StorageImageReadWithoutFormat});
967static void addOpDecorateReqs(
const MachineInstr &
MI,
unsigned DecIndex,
970 int64_t DecOp =
MI.getOperand(DecIndex).getImm();
971 auto Dec =
static_cast<SPIRV::Decoration::Decoration
>(DecOp);
973 SPIRV::OperandCategory::DecorationOperand, Dec, ST, Reqs));
975 if (Dec == SPIRV::Decoration::BuiltIn) {
976 int64_t BuiltInOp =
MI.getOperand(DecIndex + 1).getImm();
977 auto BuiltIn =
static_cast<SPIRV::BuiltIn::BuiltIn
>(BuiltInOp);
979 SPIRV::OperandCategory::BuiltInOperand, BuiltIn, ST, Reqs));
980 }
else if (Dec == SPIRV::Decoration::LinkageAttributes) {
981 int64_t LinkageOp =
MI.getOperand(
MI.getNumOperands() - 1).getImm();
982 SPIRV::LinkageType::LinkageType LnkType =
983 static_cast<SPIRV::LinkageType::LinkageType
>(LinkageOp);
984 if (LnkType == SPIRV::LinkageType::LinkOnceODR)
985 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_linkonce_odr);
986 }
else if (Dec == SPIRV::Decoration::CacheControlLoadINTEL ||
987 Dec == SPIRV::Decoration::CacheControlStoreINTEL) {
988 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_cache_controls);
989 }
else if (Dec == SPIRV::Decoration::HostAccessINTEL) {
990 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_global_variable_host_access);
991 }
else if (Dec == SPIRV::Decoration::InitModeINTEL ||
992 Dec == SPIRV::Decoration::ImplementInRegisterMapINTEL) {
994 SPIRV::Extension::SPV_INTEL_global_variable_fpga_decorations);
995 }
else if (Dec == SPIRV::Decoration::NonUniformEXT) {
997 }
else if (Dec == SPIRV::Decoration::FPMaxErrorDecorationINTEL) {
999 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_fp_max_error);
1000 }
else if (Dec == SPIRV::Decoration::FPFastMathMode) {
1001 if (
ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2)) {
1003 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_float_controls2);
1012 assert(
MI.getNumOperands() >= 8 &&
"Insufficient operands for OpTypeImage");
1015 int64_t ImgFormatOp =
MI.getOperand(7).getImm();
1016 auto ImgFormat =
static_cast<SPIRV::ImageFormat::ImageFormat
>(ImgFormatOp);
1020 bool IsArrayed =
MI.getOperand(4).getImm() == 1;
1021 bool IsMultisampled =
MI.getOperand(5).getImm() == 1;
1022 bool NoSampler =
MI.getOperand(6).getImm() == 2;
1025 switch (
MI.getOperand(2).getImm()) {
1026 case SPIRV::Dim::DIM_1D:
1028 : SPIRV::Capability::Sampled1D);
1030 case SPIRV::Dim::DIM_2D:
1031 if (IsMultisampled && NoSampler)
1034 case SPIRV::Dim::DIM_Cube:
1038 : SPIRV::Capability::SampledCubeArray);
1040 case SPIRV::Dim::DIM_Rect:
1042 : SPIRV::Capability::SampledRect);
1044 case SPIRV::Dim::DIM_Buffer:
1046 : SPIRV::Capability::SampledBuffer);
1048 case SPIRV::Dim::DIM_SubpassData:
1054 if (!
ST.isShader()) {
1055 if (
MI.getNumOperands() > 8 &&
1056 MI.getOperand(8).getImm() == SPIRV::AccessQualifier::ReadWrite)
1063static bool isBFloat16Type(
const SPIRVType *TypeDef) {
1065 TypeDef->
getOpcode() == SPIRV::OpTypeFloat &&
1071#define ATOM_FLT_REQ_EXT_MSG(ExtName) \
1072 "The atomic float instruction requires the following SPIR-V " \
1073 "extension: SPV_EXT_shader_atomic_float" ExtName
1078 "Expect register operand in atomic float instruction");
1079 Register TypeReg =
MI.getOperand(1).getReg();
1080 SPIRVType *TypeDef =
MI.getMF()->getRegInfo().getVRegDef(TypeReg);
1081 if (TypeDef->
getOpcode() != SPIRV::OpTypeFloat)
1083 "floating-point type scalar");
1086 unsigned Op =
MI.getOpcode();
1087 if (
Op == SPIRV::OpAtomicFAddEXT) {
1088 if (!
ST.canUseExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float_add))
1090 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float_add);
1093 if (isBFloat16Type(TypeDef)) {
1094 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics))
1096 "The atomic bfloat16 instruction requires the following SPIR-V "
1097 "extension: SPV_INTEL_16bit_atomics",
1099 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics);
1100 Reqs.
addCapability(SPIRV::Capability::AtomicBFloat16AddINTEL);
1102 if (!
ST.canUseExtension(
1103 SPIRV::Extension::SPV_EXT_shader_atomic_float16_add))
1105 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float16_add);
1117 "Unexpected floating-point type width in atomic float instruction");
1120 if (!
ST.canUseExtension(
1121 SPIRV::Extension::SPV_EXT_shader_atomic_float_min_max))
1123 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float_min_max);
1126 if (isBFloat16Type(TypeDef)) {
1127 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics))
1129 "The atomic bfloat16 instruction requires the following SPIR-V "
1130 "extension: SPV_INTEL_16bit_atomics",
1132 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics);
1133 Reqs.
addCapability(SPIRV::Capability::AtomicBFloat16MinMaxINTEL);
1135 Reqs.
addCapability(SPIRV::Capability::AtomicFloat16MinMaxEXT);
1139 Reqs.
addCapability(SPIRV::Capability::AtomicFloat32MinMaxEXT);
1142 Reqs.
addCapability(SPIRV::Capability::AtomicFloat64MinMaxEXT);
1146 "Unexpected floating-point type width in atomic float instruction");
1152 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1156 return Dim == SPIRV::Dim::DIM_Buffer && Sampled == 1;
1160 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1164 return Dim == SPIRV::Dim::DIM_Buffer && Sampled == 2;
1168 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1172 return Dim != SPIRV::Dim::DIM_Buffer && Sampled == 1;
1176 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1180 return Dim == SPIRV::Dim::DIM_SubpassData && Sampled == 2;
1184 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1188 return Dim != SPIRV::Dim::DIM_Buffer && Sampled == 2;
1191bool isCombinedImageSampler(
MachineInstr *SampledImageInst) {
1192 if (SampledImageInst->
getOpcode() != SPIRV::OpTypeSampledImage)
1197 auto *ImageInst =
MRI.getUniqueVRegDef(ImageReg);
1198 return isSampledImage(ImageInst);
1202 for (
const auto &
MI :
MRI.reg_instructions(
Reg)) {
1203 if (
MI.getOpcode() != SPIRV::OpDecorate)
1207 if (Dec == SPIRV::Decoration::NonUniformEXT)
1225 if (
StorageClass != SPIRV::StorageClass::StorageClass::UniformConstant &&
1226 StorageClass != SPIRV::StorageClass::StorageClass::Uniform &&
1227 StorageClass != SPIRV::StorageClass::StorageClass::StorageBuffer) {
1232 hasNonUniformDecoration(
Instr.getOperand(0).getReg(),
MRI);
1234 auto FirstIndexReg =
Instr.getOperand(3).getReg();
1235 bool FirstIndexIsConstant =
1238 if (
StorageClass == SPIRV::StorageClass::StorageClass::StorageBuffer) {
1241 SPIRV::Capability::StorageBufferArrayNonUniformIndexingEXT);
1242 else if (!FirstIndexIsConstant)
1244 SPIRV::Capability::StorageBufferArrayDynamicIndexing);
1250 if (PointeeType->
getOpcode() != SPIRV::OpTypeImage &&
1251 PointeeType->
getOpcode() != SPIRV::OpTypeSampledImage &&
1252 PointeeType->
getOpcode() != SPIRV::OpTypeSampler) {
1256 if (isUniformTexelBuffer(PointeeType)) {
1259 SPIRV::Capability::UniformTexelBufferArrayNonUniformIndexingEXT);
1260 else if (!FirstIndexIsConstant)
1262 SPIRV::Capability::UniformTexelBufferArrayDynamicIndexingEXT);
1263 }
else if (isInputAttachment(PointeeType)) {
1266 SPIRV::Capability::InputAttachmentArrayNonUniformIndexingEXT);
1267 else if (!FirstIndexIsConstant)
1269 SPIRV::Capability::InputAttachmentArrayDynamicIndexingEXT);
1270 }
else if (isStorageTexelBuffer(PointeeType)) {
1273 SPIRV::Capability::StorageTexelBufferArrayNonUniformIndexingEXT);
1274 else if (!FirstIndexIsConstant)
1276 SPIRV::Capability::StorageTexelBufferArrayDynamicIndexingEXT);
1277 }
else if (isSampledImage(PointeeType) ||
1278 isCombinedImageSampler(PointeeType) ||
1279 PointeeType->
getOpcode() == SPIRV::OpTypeSampler) {
1282 SPIRV::Capability::SampledImageArrayNonUniformIndexingEXT);
1283 else if (!FirstIndexIsConstant)
1285 SPIRV::Capability::SampledImageArrayDynamicIndexing);
1286 }
else if (isStorageImage(PointeeType)) {
1289 SPIRV::Capability::StorageImageArrayNonUniformIndexingEXT);
1290 else if (!FirstIndexIsConstant)
1292 SPIRV::Capability::StorageImageArrayDynamicIndexing);
1296static bool isImageTypeWithUnknownFormat(
SPIRVType *TypeInst) {
1297 if (TypeInst->
getOpcode() != SPIRV::OpTypeImage)
1306 if (
ST.canUseExtension(SPIRV::Extension::SPV_KHR_integer_dot_product))
1307 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_integer_dot_product);
1311 assert(
MI.getOperand(2).isReg() &&
"Unexpected operand in dot");
1315 assert(
Input->getOperand(1).isReg() &&
"Unexpected operand in dot input");
1319 if (TypeDef->
getOpcode() == SPIRV::OpTypeInt) {
1321 Reqs.
addCapability(SPIRV::Capability::DotProductInput4x8BitPacked);
1322 }
else if (TypeDef->
getOpcode() == SPIRV::OpTypeVector) {
1327 "Dot operand of 8-bit integer type requires 4 components");
1328 Reqs.
addCapability(SPIRV::Capability::DotProductInput4x8Bit);
1343 unsigned AddrSpace = ASOp.
getImm();
1344 if (AddrSpace != SPIRV::StorageClass::UniformConstant) {
1345 if (!
ST.canUseExtension(
1347 SPV_EXT_relaxed_printf_string_address_space)) {
1349 "required because printf uses a format string not "
1350 "in constant address space.",
1354 SPIRV::Extension::SPV_EXT_relaxed_printf_string_address_space);
1364 switch (
MI.getOpcode()) {
1365 case SPIRV::OpMemoryModel: {
1366 int64_t Addr =
MI.getOperand(0).getImm();
1369 int64_t Mem =
MI.getOperand(1).getImm();
1374 case SPIRV::OpEntryPoint: {
1375 int64_t
Exe =
MI.getOperand(0).getImm();
1380 case SPIRV::OpExecutionMode:
1381 case SPIRV::OpExecutionModeId: {
1382 int64_t
Exe =
MI.getOperand(1).getImm();
1387 case SPIRV::OpTypeMatrix:
1390 case SPIRV::OpTypeInt: {
1391 unsigned BitWidth =
MI.getOperand(1).getImm();
1400 case SPIRV::OpDot: {
1403 if (isBFloat16Type(TypeDef))
1404 Reqs.
addCapability(SPIRV::Capability::BFloat16DotProductKHR);
1407 case SPIRV::OpTypeFloat: {
1408 unsigned BitWidth =
MI.getOperand(1).getImm();
1412 if (isBFloat16Type(&
MI)) {
1413 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_bfloat16))
1415 "following SPIR-V extension: SPV_KHR_bfloat16",
1425 case SPIRV::OpTypeVector: {
1426 unsigned NumComponents =
MI.getOperand(2).getImm();
1427 if (NumComponents == 8 || NumComponents == 16)
1431 case SPIRV::OpTypePointer: {
1432 auto SC =
MI.getOperand(1).getImm();
1443 (TypeDef->
getOpcode() == SPIRV::OpTypeFloat) &&
1448 case SPIRV::OpExtInst: {
1449 if (
MI.getOperand(2).getImm() ==
1450 static_cast<int64_t
>(
1451 SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100)) {
1452 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_non_semantic_info);
1455 if (
MI.getOperand(3).getImm() ==
1456 static_cast<int64_t
>(SPIRV::OpenCLExtInst::printf)) {
1457 addPrintfRequirements(
MI, Reqs, ST);
1464 case SPIRV::OpAliasDomainDeclINTEL:
1465 case SPIRV::OpAliasScopeDeclINTEL:
1466 case SPIRV::OpAliasScopeListDeclINTEL: {
1467 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_memory_access_aliasing);
1468 Reqs.
addCapability(SPIRV::Capability::MemoryAccessAliasingINTEL);
1471 case SPIRV::OpBitReverse:
1472 case SPIRV::OpBitFieldInsert:
1473 case SPIRV::OpBitFieldSExtract:
1474 case SPIRV::OpBitFieldUExtract:
1475 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_bit_instructions)) {
1479 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_bit_instructions);
1482 case SPIRV::OpTypeRuntimeArray:
1485 case SPIRV::OpTypeOpaque:
1486 case SPIRV::OpTypeEvent:
1489 case SPIRV::OpTypePipe:
1490 case SPIRV::OpTypeReserveId:
1493 case SPIRV::OpTypeDeviceEvent:
1494 case SPIRV::OpTypeQueue:
1495 case SPIRV::OpBuildNDRange:
1498 case SPIRV::OpDecorate:
1499 case SPIRV::OpDecorateId:
1500 case SPIRV::OpDecorateString:
1501 addOpDecorateReqs(
MI, 1, Reqs, ST);
1503 case SPIRV::OpMemberDecorate:
1504 case SPIRV::OpMemberDecorateString:
1505 addOpDecorateReqs(
MI, 2, Reqs, ST);
1507 case SPIRV::OpInBoundsPtrAccessChain:
1510 case SPIRV::OpConstantSampler:
1513 case SPIRV::OpInBoundsAccessChain:
1514 case SPIRV::OpAccessChain:
1515 addOpAccessChainReqs(
MI, Reqs, ST);
1517 case SPIRV::OpTypeImage:
1518 addOpTypeImageReqs(
MI, Reqs, ST);
1520 case SPIRV::OpTypeSampler:
1521 if (!
ST.isShader()) {
1525 case SPIRV::OpTypeForwardPointer:
1529 case SPIRV::OpAtomicFlagTestAndSet:
1530 case SPIRV::OpAtomicLoad:
1531 case SPIRV::OpAtomicStore:
1532 case SPIRV::OpAtomicExchange:
1533 case SPIRV::OpAtomicCompareExchange:
1534 case SPIRV::OpAtomicIIncrement:
1535 case SPIRV::OpAtomicIDecrement:
1536 case SPIRV::OpAtomicIAdd:
1537 case SPIRV::OpAtomicISub:
1538 case SPIRV::OpAtomicUMin:
1539 case SPIRV::OpAtomicUMax:
1540 case SPIRV::OpAtomicSMin:
1541 case SPIRV::OpAtomicSMax:
1542 case SPIRV::OpAtomicAnd:
1543 case SPIRV::OpAtomicOr:
1544 case SPIRV::OpAtomicXor: {
1547 if (
MI.getOpcode() == SPIRV::OpAtomicStore) {
1549 InstrPtr =
MRI.getVRegDef(
MI.getOperand(3).getReg());
1550 assert(InstrPtr &&
"Unexpected type instruction for OpAtomicStore");
1555 if (TypeDef->
getOpcode() == SPIRV::OpTypeInt) {
1562 case SPIRV::OpGroupNonUniformIAdd:
1563 case SPIRV::OpGroupNonUniformFAdd:
1564 case SPIRV::OpGroupNonUniformIMul:
1565 case SPIRV::OpGroupNonUniformFMul:
1566 case SPIRV::OpGroupNonUniformSMin:
1567 case SPIRV::OpGroupNonUniformUMin:
1568 case SPIRV::OpGroupNonUniformFMin:
1569 case SPIRV::OpGroupNonUniformSMax:
1570 case SPIRV::OpGroupNonUniformUMax:
1571 case SPIRV::OpGroupNonUniformFMax:
1572 case SPIRV::OpGroupNonUniformBitwiseAnd:
1573 case SPIRV::OpGroupNonUniformBitwiseOr:
1574 case SPIRV::OpGroupNonUniformBitwiseXor:
1575 case SPIRV::OpGroupNonUniformLogicalAnd:
1576 case SPIRV::OpGroupNonUniformLogicalOr:
1577 case SPIRV::OpGroupNonUniformLogicalXor: {
1579 int64_t GroupOp =
MI.getOperand(3).getImm();
1581 case SPIRV::GroupOperation::Reduce:
1582 case SPIRV::GroupOperation::InclusiveScan:
1583 case SPIRV::GroupOperation::ExclusiveScan:
1584 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformArithmetic);
1586 case SPIRV::GroupOperation::ClusteredReduce:
1587 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformClustered);
1589 case SPIRV::GroupOperation::PartitionedReduceNV:
1590 case SPIRV::GroupOperation::PartitionedInclusiveScanNV:
1591 case SPIRV::GroupOperation::PartitionedExclusiveScanNV:
1592 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformPartitionedNV);
1597 case SPIRV::OpGroupNonUniformShuffle:
1598 case SPIRV::OpGroupNonUniformShuffleXor:
1599 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformShuffle);
1601 case SPIRV::OpGroupNonUniformShuffleUp:
1602 case SPIRV::OpGroupNonUniformShuffleDown:
1603 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformShuffleRelative);
1605 case SPIRV::OpGroupAll:
1606 case SPIRV::OpGroupAny:
1607 case SPIRV::OpGroupBroadcast:
1608 case SPIRV::OpGroupIAdd:
1609 case SPIRV::OpGroupFAdd:
1610 case SPIRV::OpGroupFMin:
1611 case SPIRV::OpGroupUMin:
1612 case SPIRV::OpGroupSMin:
1613 case SPIRV::OpGroupFMax:
1614 case SPIRV::OpGroupUMax:
1615 case SPIRV::OpGroupSMax:
1618 case SPIRV::OpGroupNonUniformElect:
1621 case SPIRV::OpGroupNonUniformAll:
1622 case SPIRV::OpGroupNonUniformAny:
1623 case SPIRV::OpGroupNonUniformAllEqual:
1626 case SPIRV::OpGroupNonUniformBroadcast:
1627 case SPIRV::OpGroupNonUniformBroadcastFirst:
1628 case SPIRV::OpGroupNonUniformBallot:
1629 case SPIRV::OpGroupNonUniformInverseBallot:
1630 case SPIRV::OpGroupNonUniformBallotBitExtract:
1631 case SPIRV::OpGroupNonUniformBallotBitCount:
1632 case SPIRV::OpGroupNonUniformBallotFindLSB:
1633 case SPIRV::OpGroupNonUniformBallotFindMSB:
1634 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformBallot);
1636 case SPIRV::OpSubgroupShuffleINTEL:
1637 case SPIRV::OpSubgroupShuffleDownINTEL:
1638 case SPIRV::OpSubgroupShuffleUpINTEL:
1639 case SPIRV::OpSubgroupShuffleXorINTEL:
1640 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {
1641 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_subgroups);
1642 Reqs.
addCapability(SPIRV::Capability::SubgroupShuffleINTEL);
1645 case SPIRV::OpSubgroupBlockReadINTEL:
1646 case SPIRV::OpSubgroupBlockWriteINTEL:
1647 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {
1648 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_subgroups);
1649 Reqs.
addCapability(SPIRV::Capability::SubgroupBufferBlockIOINTEL);
1652 case SPIRV::OpSubgroupImageBlockReadINTEL:
1653 case SPIRV::OpSubgroupImageBlockWriteINTEL:
1654 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {
1655 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_subgroups);
1656 Reqs.
addCapability(SPIRV::Capability::SubgroupImageBlockIOINTEL);
1659 case SPIRV::OpSubgroupImageMediaBlockReadINTEL:
1660 case SPIRV::OpSubgroupImageMediaBlockWriteINTEL:
1661 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_media_block_io)) {
1662 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_media_block_io);
1663 Reqs.
addCapability(SPIRV::Capability::SubgroupImageMediaBlockIOINTEL);
1666 case SPIRV::OpAssumeTrueKHR:
1667 case SPIRV::OpExpectKHR:
1668 if (
ST.canUseExtension(SPIRV::Extension::SPV_KHR_expect_assume)) {
1669 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_expect_assume);
1673 case SPIRV::OpPtrCastToCrossWorkgroupINTEL:
1674 case SPIRV::OpCrossWorkgroupCastToPtrINTEL:
1675 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_usm_storage_classes)) {
1676 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_usm_storage_classes);
1677 Reqs.
addCapability(SPIRV::Capability::USMStorageClassesINTEL);
1680 case SPIRV::OpConstantFunctionPointerINTEL:
1681 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_function_pointers)) {
1682 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_function_pointers);
1683 Reqs.
addCapability(SPIRV::Capability::FunctionPointersINTEL);
1686 case SPIRV::OpGroupNonUniformRotateKHR:
1687 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_subgroup_rotate))
1689 "following SPIR-V extension: SPV_KHR_subgroup_rotate",
1691 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_subgroup_rotate);
1692 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformRotateKHR);
1695 case SPIRV::OpGroupIMulKHR:
1696 case SPIRV::OpGroupFMulKHR:
1697 case SPIRV::OpGroupBitwiseAndKHR:
1698 case SPIRV::OpGroupBitwiseOrKHR:
1699 case SPIRV::OpGroupBitwiseXorKHR:
1700 case SPIRV::OpGroupLogicalAndKHR:
1701 case SPIRV::OpGroupLogicalOrKHR:
1702 case SPIRV::OpGroupLogicalXorKHR:
1703 if (
ST.canUseExtension(
1704 SPIRV::Extension::SPV_KHR_uniform_group_instructions)) {
1705 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_uniform_group_instructions);
1706 Reqs.
addCapability(SPIRV::Capability::GroupUniformArithmeticKHR);
1709 case SPIRV::OpReadClockKHR:
1710 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_shader_clock))
1712 "following SPIR-V extension: SPV_KHR_shader_clock",
1714 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_shader_clock);
1717 case SPIRV::OpFunctionPointerCallINTEL:
1718 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_function_pointers)) {
1719 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_function_pointers);
1720 Reqs.
addCapability(SPIRV::Capability::FunctionPointersINTEL);
1723 case SPIRV::OpAtomicFAddEXT:
1724 case SPIRV::OpAtomicFMinEXT:
1725 case SPIRV::OpAtomicFMaxEXT:
1726 AddAtomicFloatRequirements(
MI, Reqs, ST);
1728 case SPIRV::OpConvertBF16ToFINTEL:
1729 case SPIRV::OpConvertFToBF16INTEL:
1730 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bfloat16_conversion)) {
1731 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bfloat16_conversion);
1732 Reqs.
addCapability(SPIRV::Capability::BFloat16ConversionINTEL);
1735 case SPIRV::OpRoundFToTF32INTEL:
1736 if (
ST.canUseExtension(
1737 SPIRV::Extension::SPV_INTEL_tensor_float32_conversion)) {
1738 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_tensor_float32_conversion);
1739 Reqs.
addCapability(SPIRV::Capability::TensorFloat32RoundingINTEL);
1742 case SPIRV::OpVariableLengthArrayINTEL:
1743 case SPIRV::OpSaveMemoryINTEL:
1744 case SPIRV::OpRestoreMemoryINTEL:
1745 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_variable_length_array)) {
1746 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_variable_length_array);
1747 Reqs.
addCapability(SPIRV::Capability::VariableLengthArrayINTEL);
1750 case SPIRV::OpAsmTargetINTEL:
1751 case SPIRV::OpAsmINTEL:
1752 case SPIRV::OpAsmCallINTEL:
1753 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_inline_assembly)) {
1754 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_inline_assembly);
1758 case SPIRV::OpTypeCooperativeMatrixKHR: {
1759 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix))
1761 "OpTypeCooperativeMatrixKHR type requires the "
1762 "following SPIR-V extension: SPV_KHR_cooperative_matrix",
1764 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix);
1765 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixKHR);
1768 if (isBFloat16Type(TypeDef))
1769 Reqs.
addCapability(SPIRV::Capability::BFloat16CooperativeMatrixKHR);
1772 case SPIRV::OpArithmeticFenceEXT:
1773 if (!
ST.canUseExtension(SPIRV::Extension::SPV_EXT_arithmetic_fence))
1775 "following SPIR-V extension: SPV_EXT_arithmetic_fence",
1777 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_arithmetic_fence);
1780 case SPIRV::OpControlBarrierArriveINTEL:
1781 case SPIRV::OpControlBarrierWaitINTEL:
1782 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_split_barrier)) {
1783 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_split_barrier);
1787 case SPIRV::OpCooperativeMatrixMulAddKHR: {
1788 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix))
1790 "following SPIR-V extension: "
1791 "SPV_KHR_cooperative_matrix",
1793 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix);
1794 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixKHR);
1795 constexpr unsigned MulAddMaxSize = 6;
1796 if (
MI.getNumOperands() != MulAddMaxSize)
1798 const int64_t CoopOperands =
MI.getOperand(MulAddMaxSize - 1).getImm();
1800 SPIRV::CooperativeMatrixOperands::MatrixAAndBTF32ComponentsINTEL) {
1801 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
1803 "require the following SPIR-V extension: "
1804 "SPV_INTEL_joint_matrix",
1806 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
1808 SPIRV::Capability::CooperativeMatrixTF32ComponentTypeINTEL);
1811 MatrixAAndBBFloat16ComponentsINTEL ||
1813 SPIRV::CooperativeMatrixOperands::MatrixCBFloat16ComponentsINTEL ||
1815 MatrixResultBFloat16ComponentsINTEL) {
1816 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
1818 "require the following SPIR-V extension: "
1819 "SPV_INTEL_joint_matrix",
1821 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
1823 SPIRV::Capability::CooperativeMatrixBFloat16ComponentTypeINTEL);
1827 case SPIRV::OpCooperativeMatrixLoadKHR:
1828 case SPIRV::OpCooperativeMatrixStoreKHR:
1829 case SPIRV::OpCooperativeMatrixLoadCheckedINTEL:
1830 case SPIRV::OpCooperativeMatrixStoreCheckedINTEL:
1831 case SPIRV::OpCooperativeMatrixPrefetchINTEL: {
1832 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix))
1834 "following SPIR-V extension: "
1835 "SPV_KHR_cooperative_matrix",
1837 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix);
1838 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixKHR);
1842 std::unordered_map<unsigned, unsigned> LayoutToInstMap = {
1843 {SPIRV::OpCooperativeMatrixLoadKHR, 3},
1844 {SPIRV::OpCooperativeMatrixStoreKHR, 2},
1845 {SPIRV::OpCooperativeMatrixLoadCheckedINTEL, 5},
1846 {SPIRV::OpCooperativeMatrixStoreCheckedINTEL, 4},
1847 {SPIRV::OpCooperativeMatrixPrefetchINTEL, 4}};
1849 const auto OpCode =
MI.getOpcode();
1850 const unsigned LayoutNum = LayoutToInstMap[OpCode];
1851 Register RegLayout =
MI.getOperand(LayoutNum).getReg();
1854 if (MILayout->
getOpcode() == SPIRV::OpConstantI) {
1857 static_cast<unsigned>(SPIRV::CooperativeMatrixLayout::PackedINTEL)) {
1858 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
1860 "extension: SPV_INTEL_joint_matrix",
1862 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
1863 Reqs.
addCapability(SPIRV::Capability::PackedCooperativeMatrixINTEL);
1868 if (OpCode == SPIRV::OpCooperativeMatrixLoadKHR ||
1869 OpCode == SPIRV::OpCooperativeMatrixStoreKHR)
1872 std::string InstName;
1874 case SPIRV::OpCooperativeMatrixPrefetchINTEL:
1875 InstName =
"OpCooperativeMatrixPrefetchINTEL";
1877 case SPIRV::OpCooperativeMatrixLoadCheckedINTEL:
1878 InstName =
"OpCooperativeMatrixLoadCheckedINTEL";
1880 case SPIRV::OpCooperativeMatrixStoreCheckedINTEL:
1881 InstName =
"OpCooperativeMatrixStoreCheckedINTEL";
1885 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix)) {
1886 const std::string ErrorMsg =
1887 InstName +
" instruction requires the "
1888 "following SPIR-V extension: SPV_INTEL_joint_matrix";
1891 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
1892 if (OpCode == SPIRV::OpCooperativeMatrixPrefetchINTEL) {
1893 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixPrefetchINTEL);
1897 SPIRV::Capability::CooperativeMatrixCheckedInstructionsINTEL);
1900 case SPIRV::OpCooperativeMatrixConstructCheckedINTEL:
1901 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
1903 "instructions require the following SPIR-V extension: "
1904 "SPV_INTEL_joint_matrix",
1906 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
1908 SPIRV::Capability::CooperativeMatrixCheckedInstructionsINTEL);
1910 case SPIRV::OpReadPipeBlockingALTERA:
1911 case SPIRV::OpWritePipeBlockingALTERA:
1912 if (
ST.canUseExtension(SPIRV::Extension::SPV_ALTERA_blocking_pipes)) {
1913 Reqs.
addExtension(SPIRV::Extension::SPV_ALTERA_blocking_pipes);
1917 case SPIRV::OpCooperativeMatrixGetElementCoordINTEL:
1918 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
1920 "following SPIR-V extension: SPV_INTEL_joint_matrix",
1922 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
1924 SPIRV::Capability::CooperativeMatrixInvocationInstructionsINTEL);
1926 case SPIRV::OpConvertHandleToImageINTEL:
1927 case SPIRV::OpConvertHandleToSamplerINTEL:
1928 case SPIRV::OpConvertHandleToSampledImageINTEL: {
1929 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bindless_images))
1931 "instructions require the following SPIR-V extension: "
1932 "SPV_INTEL_bindless_images",
1935 SPIRV::AddressingModel::AddressingModel AddrModel = MAI.
Addr;
1937 if (
MI.getOpcode() == SPIRV::OpConvertHandleToImageINTEL &&
1938 TyDef->
getOpcode() != SPIRV::OpTypeImage) {
1940 "OpConvertHandleToImageINTEL",
1942 }
else if (
MI.getOpcode() == SPIRV::OpConvertHandleToSamplerINTEL &&
1943 TyDef->
getOpcode() != SPIRV::OpTypeSampler) {
1945 "OpConvertHandleToSamplerINTEL",
1947 }
else if (
MI.getOpcode() == SPIRV::OpConvertHandleToSampledImageINTEL &&
1948 TyDef->
getOpcode() != SPIRV::OpTypeSampledImage) {
1950 "OpConvertHandleToSampledImageINTEL",
1955 if (!(Bitwidth == 32 && AddrModel == SPIRV::AddressingModel::Physical32) &&
1956 !(Bitwidth == 64 && AddrModel == SPIRV::AddressingModel::Physical64)) {
1958 "Parameter value must be a 32-bit scalar in case of "
1959 "Physical32 addressing model or a 64-bit scalar in case of "
1960 "Physical64 addressing model",
1963 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bindless_images);
1967 case SPIRV::OpSubgroup2DBlockLoadINTEL:
1968 case SPIRV::OpSubgroup2DBlockLoadTransposeINTEL:
1969 case SPIRV::OpSubgroup2DBlockLoadTransformINTEL:
1970 case SPIRV::OpSubgroup2DBlockPrefetchINTEL:
1971 case SPIRV::OpSubgroup2DBlockStoreINTEL: {
1972 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_2d_block_io))
1974 "Prefetch/Store]INTEL instructions require the "
1975 "following SPIR-V extension: SPV_INTEL_2d_block_io",
1977 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_2d_block_io);
1978 Reqs.
addCapability(SPIRV::Capability::Subgroup2DBlockIOINTEL);
1980 const auto OpCode =
MI.getOpcode();
1981 if (OpCode == SPIRV::OpSubgroup2DBlockLoadTransposeINTEL) {
1982 Reqs.
addCapability(SPIRV::Capability::Subgroup2DBlockTransposeINTEL);
1985 if (OpCode == SPIRV::OpSubgroup2DBlockLoadTransformINTEL) {
1986 Reqs.
addCapability(SPIRV::Capability::Subgroup2DBlockTransformINTEL);
1991 case SPIRV::OpKill: {
1994 case SPIRV::OpDemoteToHelperInvocation:
1995 Reqs.
addCapability(SPIRV::Capability::DemoteToHelperInvocation);
1997 if (
ST.canUseExtension(
1998 SPIRV::Extension::SPV_EXT_demote_to_helper_invocation)) {
2001 SPIRV::Extension::SPV_EXT_demote_to_helper_invocation);
2006 case SPIRV::OpSUDot:
2007 case SPIRV::OpSDotAccSat:
2008 case SPIRV::OpUDotAccSat:
2009 case SPIRV::OpSUDotAccSat:
2010 AddDotProductRequirements(
MI, Reqs, ST);
2012 case SPIRV::OpImageRead: {
2013 Register ImageReg =
MI.getOperand(2).getReg();
2014 SPIRVType *TypeDef =
ST.getSPIRVGlobalRegistry()->getResultType(
2022 if (isImageTypeWithUnknownFormat(TypeDef) &&
ST.isShader())
2023 Reqs.
addCapability(SPIRV::Capability::StorageImageReadWithoutFormat);
2026 case SPIRV::OpImageWrite: {
2027 Register ImageReg =
MI.getOperand(0).getReg();
2028 SPIRVType *TypeDef =
ST.getSPIRVGlobalRegistry()->getResultType(
2036 if (isImageTypeWithUnknownFormat(TypeDef) &&
ST.isShader())
2037 Reqs.
addCapability(SPIRV::Capability::StorageImageWriteWithoutFormat);
2040 case SPIRV::OpTypeStructContinuedINTEL:
2041 case SPIRV::OpConstantCompositeContinuedINTEL:
2042 case SPIRV::OpSpecConstantCompositeContinuedINTEL:
2043 case SPIRV::OpCompositeConstructContinuedINTEL: {
2044 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_long_composites))
2046 "Continued instructions require the "
2047 "following SPIR-V extension: SPV_INTEL_long_composites",
2049 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_long_composites);
2053 case SPIRV::OpSubgroupMatrixMultiplyAccumulateINTEL: {
2054 if (!
ST.canUseExtension(
2055 SPIRV::Extension::SPV_INTEL_subgroup_matrix_multiply_accumulate))
2057 "OpSubgroupMatrixMultiplyAccumulateINTEL instruction requires the "
2059 "extension: SPV_INTEL_subgroup_matrix_multiply_accumulate",
2062 SPIRV::Extension::SPV_INTEL_subgroup_matrix_multiply_accumulate);
2064 SPIRV::Capability::SubgroupMatrixMultiplyAccumulateINTEL);
2067 case SPIRV::OpBitwiseFunctionINTEL: {
2068 if (!
ST.canUseExtension(
2069 SPIRV::Extension::SPV_INTEL_ternary_bitwise_function))
2071 "OpBitwiseFunctionINTEL instruction requires the following SPIR-V "
2072 "extension: SPV_INTEL_ternary_bitwise_function",
2074 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_ternary_bitwise_function);
2075 Reqs.
addCapability(SPIRV::Capability::TernaryBitwiseFunctionINTEL);
2078 case SPIRV::OpCopyMemorySized: {
2083 case SPIRV::OpPredicatedLoadINTEL:
2084 case SPIRV::OpPredicatedStoreINTEL: {
2085 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_predicated_io))
2087 "OpPredicated[Load/Store]INTEL instructions require "
2088 "the following SPIR-V extension: SPV_INTEL_predicated_io",
2090 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_predicated_io);
2094 case SPIRV::OpFAddS:
2095 case SPIRV::OpFSubS:
2096 case SPIRV::OpFMulS:
2097 case SPIRV::OpFDivS:
2098 case SPIRV::OpFRemS:
2100 case SPIRV::OpFNegate:
2101 case SPIRV::OpFAddV:
2102 case SPIRV::OpFSubV:
2103 case SPIRV::OpFMulV:
2104 case SPIRV::OpFDivV:
2105 case SPIRV::OpFRemV:
2106 case SPIRV::OpFNegateV: {
2109 if (TypeDef->
getOpcode() == SPIRV::OpTypeVector)
2111 if (isBFloat16Type(TypeDef)) {
2112 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic))
2114 "Arithmetic instructions with bfloat16 arguments require the "
2115 "following SPIR-V extension: SPV_INTEL_bfloat16_arithmetic",
2117 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic);
2118 Reqs.
addCapability(SPIRV::Capability::BFloat16ArithmeticINTEL);
2122 case SPIRV::OpOrdered:
2123 case SPIRV::OpUnordered:
2124 case SPIRV::OpFOrdEqual:
2125 case SPIRV::OpFOrdNotEqual:
2126 case SPIRV::OpFOrdLessThan:
2127 case SPIRV::OpFOrdLessThanEqual:
2128 case SPIRV::OpFOrdGreaterThan:
2129 case SPIRV::OpFOrdGreaterThanEqual:
2130 case SPIRV::OpFUnordEqual:
2131 case SPIRV::OpFUnordNotEqual:
2132 case SPIRV::OpFUnordLessThan:
2133 case SPIRV::OpFUnordLessThanEqual:
2134 case SPIRV::OpFUnordGreaterThan:
2135 case SPIRV::OpFUnordGreaterThanEqual: {
2139 if (TypeDef->
getOpcode() == SPIRV::OpTypeVector)
2141 if (isBFloat16Type(TypeDef)) {
2142 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic))
2144 "Relational instructions with bfloat16 arguments require the "
2145 "following SPIR-V extension: SPV_INTEL_bfloat16_arithmetic",
2147 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic);
2148 Reqs.
addCapability(SPIRV::Capability::BFloat16ArithmeticINTEL);
2152 case SPIRV::OpDPdxCoarse:
2153 case SPIRV::OpDPdyCoarse: {
2166 SPIRV::Capability::Shader);
2172 for (
auto F = M.begin(),
E = M.end();
F !=
E; ++
F) {
2178 addInstrRequirements(
MI, MAI, ST);
2181 auto Node = M.getNamedMetadata(
"spirv.ExecutionMode");
2183 bool RequireFloatControls =
false, RequireIntelFloatControls2 =
false,
2184 RequireKHRFloatControls2 =
false,
2186 bool HasIntelFloatControls2 =
2187 ST.canUseExtension(SPIRV::Extension::SPV_INTEL_float_controls2);
2188 bool HasKHRFloatControls2 =
2189 ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2);
2190 for (
unsigned i = 0; i <
Node->getNumOperands(); i++) {
2196 auto EM =
Const->getZExtValue();
2200 case SPIRV::ExecutionMode::DenormPreserve:
2201 case SPIRV::ExecutionMode::DenormFlushToZero:
2202 case SPIRV::ExecutionMode::RoundingModeRTE:
2203 case SPIRV::ExecutionMode::RoundingModeRTZ:
2204 RequireFloatControls = VerLower14;
2206 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2208 case SPIRV::ExecutionMode::RoundingModeRTPINTEL:
2209 case SPIRV::ExecutionMode::RoundingModeRTNINTEL:
2210 case SPIRV::ExecutionMode::FloatingPointModeALTINTEL:
2211 case SPIRV::ExecutionMode::FloatingPointModeIEEEINTEL:
2212 if (HasIntelFloatControls2) {
2213 RequireIntelFloatControls2 =
true;
2215 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2218 case SPIRV::ExecutionMode::FPFastMathDefault: {
2219 if (HasKHRFloatControls2) {
2220 RequireKHRFloatControls2 =
true;
2222 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2226 case SPIRV::ExecutionMode::ContractionOff:
2227 case SPIRV::ExecutionMode::SignedZeroInfNanPreserve:
2228 if (HasKHRFloatControls2) {
2229 RequireKHRFloatControls2 =
true;
2231 SPIRV::OperandCategory::ExecutionModeOperand,
2232 SPIRV::ExecutionMode::FPFastMathDefault, ST);
2235 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2240 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2245 if (RequireFloatControls &&
2246 ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls))
2248 if (RequireIntelFloatControls2)
2250 if (RequireKHRFloatControls2)
2253 for (
auto FI = M.begin(),
E = M.end(); FI !=
E; ++FI) {
2255 if (
F.isDeclaration())
2257 if (
F.getMetadata(
"reqd_work_group_size"))
2259 SPIRV::OperandCategory::ExecutionModeOperand,
2260 SPIRV::ExecutionMode::LocalSize, ST);
2261 if (
F.getFnAttribute(
"hlsl.numthreads").isValid()) {
2263 SPIRV::OperandCategory::ExecutionModeOperand,
2264 SPIRV::ExecutionMode::LocalSize, ST);
2266 if (
F.getFnAttribute(
"enable-maximal-reconvergence").getValueAsBool()) {
2269 if (
F.getMetadata(
"work_group_size_hint"))
2271 SPIRV::OperandCategory::ExecutionModeOperand,
2272 SPIRV::ExecutionMode::LocalSizeHint, ST);
2273 if (
F.getMetadata(
"intel_reqd_sub_group_size"))
2275 SPIRV::OperandCategory::ExecutionModeOperand,
2276 SPIRV::ExecutionMode::SubgroupSize, ST);
2277 if (
F.getMetadata(
"max_work_group_size"))
2279 SPIRV::OperandCategory::ExecutionModeOperand,
2280 SPIRV::ExecutionMode::MaxWorkgroupSizeINTEL, ST);
2281 if (
F.getMetadata(
"vec_type_hint"))
2283 SPIRV::OperandCategory::ExecutionModeOperand,
2284 SPIRV::ExecutionMode::VecTypeHint, ST);
2286 if (
F.hasOptNone()) {
2287 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_optnone)) {
2290 }
else if (
ST.canUseExtension(SPIRV::Extension::SPV_EXT_optnone)) {
2300 unsigned Flags = SPIRV::FPFastMathMode::None;
2301 bool CanUseKHRFloatControls2 =
2302 ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2);
2304 Flags |= SPIRV::FPFastMathMode::NotNaN;
2306 Flags |= SPIRV::FPFastMathMode::NotInf;
2308 Flags |= SPIRV::FPFastMathMode::NSZ;
2310 Flags |= SPIRV::FPFastMathMode::AllowRecip;
2312 Flags |= SPIRV::FPFastMathMode::AllowContract;
2314 if (CanUseKHRFloatControls2)
2322 Flags |= SPIRV::FPFastMathMode::NotNaN | SPIRV::FPFastMathMode::NotInf |
2323 SPIRV::FPFastMathMode::NSZ | SPIRV::FPFastMathMode::AllowRecip |
2324 SPIRV::FPFastMathMode::AllowTransform |
2325 SPIRV::FPFastMathMode::AllowReassoc |
2326 SPIRV::FPFastMathMode::AllowContract;
2328 Flags |= SPIRV::FPFastMathMode::Fast;
2331 if (CanUseKHRFloatControls2) {
2333 assert(!(Flags & SPIRV::FPFastMathMode::Fast) &&
2334 "SPIRV::FPFastMathMode::Fast is deprecated and should not be used "
2339 assert((!(Flags & SPIRV::FPFastMathMode::AllowTransform) ||
2340 ((Flags & SPIRV::FPFastMathMode::AllowReassoc &&
2341 Flags & SPIRV::FPFastMathMode::AllowContract))) &&
2342 "SPIRV::FPFastMathMode::AllowTransform requires AllowReassoc and "
2343 "AllowContract flags to be enabled as well.");
2354 return ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2);
2357static void handleMIFlagDecoration(
2362 getSymbolicOperandRequirements(SPIRV::OperandCategory::DecorationOperand,
2363 SPIRV::Decoration::NoSignedWrap, ST, Reqs)
2366 SPIRV::Decoration::NoSignedWrap, {});
2369 getSymbolicOperandRequirements(SPIRV::OperandCategory::DecorationOperand,
2370 SPIRV::Decoration::NoUnsignedWrap, ST,
2374 SPIRV::Decoration::NoUnsignedWrap, {});
2376 if (!
TII.canUseFastMathFlags(
2377 I,
ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2)))
2380 unsigned FMFlags = getFastMathFlags(
I, ST);
2381 if (FMFlags == SPIRV::FPFastMathMode::None) {
2384 if (FPFastMathDefaultInfoVec.
empty())
2400 assert(
I.getNumOperands() >= 3 &&
"Expected at least 3 operands");
2401 Register ResReg =
I.getOpcode() == SPIRV::OpExtInst
2402 ?
I.getOperand(1).getReg()
2403 :
I.getOperand(2).getReg();
2411 if (Ty == Elem.Ty) {
2412 FMFlags = Elem.FastMathFlags;
2413 Emit = Elem.ContractionOff || Elem.SignedZeroInfNanPreserve ||
2414 Elem.FPFastMathDefault;
2419 if (FMFlags == SPIRV::FPFastMathMode::None && !Emit)
2422 if (isFastMathModeAvailable(ST)) {
2423 Register DstReg =
I.getOperand(0).getReg();
2434 for (
auto F = M.begin(),
E = M.end();
F !=
E; ++
F) {
2439 for (
auto &
MBB : *MF)
2440 for (
auto &
MI :
MBB)
2441 handleMIFlagDecoration(
MI, ST,
TII, MAI.
Reqs, GR,
2449 for (
auto F = M.begin(),
E = M.end();
F !=
E; ++
F) {
2454 for (
auto &
MBB : *MF) {
2455 if (!
MBB.hasName() ||
MBB.empty())
2459 MRI.setRegClass(
Reg, &SPIRV::IDRegClass);
2470 for (
auto F = M.begin(),
E = M.end();
F !=
E; ++
F) {
2474 for (
auto &
MBB : *MF) {
2476 MI.setDesc(
TII.get(SPIRV::OpPhi));
2479 MI.insert(
MI.operands_begin() + 1,
2480 {MachineOperand::CreateReg(ResTypeReg, false)});
2499 SPIRV::FPFastMathMode::None);
2501 SPIRV::FPFastMathMode::None);
2503 SPIRV::FPFastMathMode::None);
2510 size_t BitWidth = Ty->getScalarSizeInBits();
2514 assert(Index >= 0 && Index < 3 &&
2515 "Expected FPFastMathDefaultInfo for half, float, or double");
2516 assert(FPFastMathDefaultInfoVec.
size() == 3 &&
2517 "Expected FPFastMathDefaultInfoVec to have exactly 3 elements");
2518 return FPFastMathDefaultInfoVec[Index];
2521static void collectFPFastMathDefaults(
const Module &M,
2524 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2))
2533 auto Node = M.getNamedMetadata(
"spirv.ExecutionMode");
2537 for (
unsigned i = 0; i <
Node->getNumOperands(); i++) {
2546 if (EM == SPIRV::ExecutionMode::FPFastMathDefault) {
2548 "Expected 4 operands for FPFastMathDefault");
2559 Info.FastMathFlags = Flags;
2560 Info.FPFastMathDefault =
true;
2561 }
else if (EM == SPIRV::ExecutionMode::ContractionOff) {
2563 "Expected no operands for ContractionOff");
2570 Info.ContractionOff =
true;
2572 }
else if (EM == SPIRV::ExecutionMode::SignedZeroInfNanPreserve) {
2574 "Expected 1 operand for SignedZeroInfNanPreserve");
2575 unsigned TargetWidth =
2584 assert(Index >= 0 && Index < 3 &&
2585 "Expected FPFastMathDefaultInfo for half, float, or double");
2586 assert(FPFastMathDefaultInfoVec.
size() == 3 &&
2587 "Expected FPFastMathDefaultInfoVec to have exactly 3 elements");
2588 FPFastMathDefaultInfoVec[Index].SignedZeroInfNanPreserve =
true;