63 const auto &
Op = MdNode->getOperand(
OpIndex);
70getSymbolicOperandRequirements(SPIRV::OperandCategory::OperandCategory Category,
76 AvoidCaps.
S.
insert(SPIRV::Capability::Shader);
78 AvoidCaps.
S.
insert(SPIRV::Capability::Kernel);
83 bool MinVerOK = SPIRVVersion.
empty() || SPIRVVersion >= ReqMinVer;
85 ReqMaxVer.
empty() || SPIRVVersion.
empty() || SPIRVVersion <= ReqMaxVer;
88 if (ReqCaps.
empty()) {
89 if (ReqExts.
empty()) {
90 if (MinVerOK && MaxVerOK)
91 return {
true, {}, {}, ReqMinVer, ReqMaxVer};
94 }
else if (MinVerOK && MaxVerOK) {
95 if (ReqCaps.
size() == 1) {
96 auto Cap = ReqCaps[0];
99 SPIRV::OperandCategory::CapabilityOperand, Cap));
100 return {
true, {Cap}, std::move(ReqExts), ReqMinVer, ReqMaxVer};
110 for (
auto Cap : ReqCaps)
113 for (
size_t i = 0, Sz = UseCaps.
size(); i < Sz; ++i) {
114 auto Cap = UseCaps[i];
115 if (i == Sz - 1 || !AvoidCaps.
S.
contains(Cap)) {
117 SPIRV::OperandCategory::CapabilityOperand, Cap));
118 return {
true, {Cap}, std::move(ReqExts), ReqMinVer, ReqMaxVer};
126 if (
llvm::all_of(ReqExts, [&ST](
const SPIRV::Extension::Extension &Ext) {
127 return ST.canUseExtension(Ext);
138void SPIRVModuleAnalysis::setBaseInfo(
const Module &M) {
142 MAI.RegisterAliasTable.clear();
143 MAI.InstrsToDelete.clear();
145 MAI.GlobalVarList.clear();
146 MAI.ExtInstSetMap.clear();
148 MAI.Reqs.initAvailableCapabilities(*ST);
151 if (
auto MemModel =
M.getNamedMetadata(
"spirv.MemoryModel")) {
152 auto MemMD = MemModel->getOperand(0);
153 MAI.Addr =
static_cast<SPIRV::AddressingModel::AddressingModel
>(
154 getMetadataUInt(MemMD, 0));
156 static_cast<SPIRV::MemoryModel::MemoryModel
>(getMetadataUInt(MemMD, 1));
159 MAI.Mem = ST->isShader() ? SPIRV::MemoryModel::GLSL450
160 : SPIRV::MemoryModel::OpenCL;
161 if (
MAI.Mem == SPIRV::MemoryModel::OpenCL) {
162 unsigned PtrSize = ST->getPointerSize();
163 MAI.Addr = PtrSize == 32 ? SPIRV::AddressingModel::Physical32
164 : PtrSize == 64 ? SPIRV::AddressingModel::Physical64
165 : SPIRV::AddressingModel::Logical;
168 MAI.Addr = SPIRV::AddressingModel::Logical;
173 if (
auto VerNode =
M.getNamedMetadata(
"opencl.ocl.version")) {
174 MAI.SrcLang = SPIRV::SourceLanguage::OpenCL_C;
177 assert(VerNode->getNumOperands() > 0 &&
"Invalid SPIR");
178 auto VersionMD = VerNode->getOperand(0);
179 unsigned MajorNum = getMetadataUInt(VersionMD, 0, 2);
180 unsigned MinorNum = getMetadataUInt(VersionMD, 1);
181 unsigned RevNum = getMetadataUInt(VersionMD, 2);
184 (std::max(1U, MajorNum) * 100 + MinorNum) * 1000 + RevNum;
190 if (!ST->isShader()) {
191 MAI.SrcLang = SPIRV::SourceLanguage::OpenCL_CPP;
192 MAI.SrcLangVersion = 100000;
194 MAI.SrcLang = SPIRV::SourceLanguage::Unknown;
195 MAI.SrcLangVersion = 0;
199 if (
auto ExtNode =
M.getNamedMetadata(
"opencl.used.extensions")) {
200 for (
unsigned I = 0,
E = ExtNode->getNumOperands();
I !=
E; ++
I) {
201 MDNode *MD = ExtNode->getOperand(
I);
211 MAI.Reqs.getAndAddRequirements(SPIRV::OperandCategory::MemoryModelOperand,
213 MAI.Reqs.getAndAddRequirements(SPIRV::OperandCategory::SourceLanguageOperand,
215 MAI.Reqs.getAndAddRequirements(SPIRV::OperandCategory::AddressingModelOperand,
218 if (!ST->isShader()) {
220 MAI.ExtInstSetMap[
static_cast<unsigned>(
221 SPIRV::InstructionSet::OpenCL_std)] =
MAI.getNextIDRegister();
232 if (
UseMI.getOpcode() != SPIRV::OpDecorate &&
233 UseMI.getOpcode() != SPIRV::OpMemberDecorate)
236 for (
unsigned I = 0;
I <
UseMI.getNumOperands(); ++
I) {
254 for (
unsigned i = 0; i <
MI.getNumOperands(); ++i) {
263 unsigned Opcode =
MI.getOpcode();
264 if ((Opcode == SPIRV::OpDecorate) && i >= 2) {
265 unsigned DecorationID =
MI.getOperand(1).getImm();
266 if (DecorationID != SPIRV::Decoration::FuncParamAttr &&
267 DecorationID != SPIRV::Decoration::UserSemantic &&
268 DecorationID != SPIRV::Decoration::CacheControlLoadINTEL &&
269 DecorationID != SPIRV::Decoration::CacheControlStoreINTEL)
275 if (!UseDefReg && MO.
isDef()) {
283 dbgs() <<
"Unexpectedly, no global id found for the operand ";
285 dbgs() <<
"\nInstruction: ";
304 appendDecorationsForReg(
MI.getMF()->getRegInfo(), DefReg, Signature);
311 unsigned Opcode =
MI.getOpcode();
313 case SPIRV::OpTypeForwardPointer:
316 case SPIRV::OpVariable:
317 return static_cast<SPIRV::StorageClass::StorageClass
>(
318 MI.getOperand(2).
getImm()) != SPIRV::StorageClass::Function;
319 case SPIRV::OpFunction:
320 case SPIRV::OpFunctionParameter:
323 if (GR->hasConstFunPtr() && Opcode == SPIRV::OpUndef) {
325 for (MachineInstr &
UseMI :
MRI.use_instructions(DefReg)) {
326 if (
UseMI.getOpcode() != SPIRV::OpConstantFunctionPointerINTEL)
332 MAI.setSkipEmission(&
MI);
336 return TII->isTypeDeclInstr(
MI) || TII->isConstantInstr(
MI) ||
337 TII->isInlineAsmDefInstr(
MI);
343void SPIRVModuleAnalysis::visitFunPtrUse(
345 std::map<const Value *, unsigned> &GlobalToGReg,
const MachineFunction *MF,
347 const MachineOperand *OpFunDef =
348 GR->getFunctionDefinitionByUse(&
MI.getOperand(2));
351 const MachineInstr *OpDefMI = OpFunDef->
getParent();
354 const MachineRegisterInfo &FunDefMRI = FunDefMF->
getRegInfo();
356 visitDecl(FunDefMRI, SignatureToGReg, GlobalToGReg, FunDefMF, *OpDefMI);
358 }
while (OpDefMI && (OpDefMI->
getOpcode() == SPIRV::OpFunction ||
359 OpDefMI->
getOpcode() == SPIRV::OpFunctionParameter));
361 MCRegister GlobalFunDefReg =
362 MAI.getRegisterAlias(FunDefMF, OpFunDef->
getReg());
364 "Function definition must refer to a global register");
365 MAI.setRegisterAlias(MF, OpReg, GlobalFunDefReg);
370void SPIRVModuleAnalysis::visitDecl(
372 std::map<const Value *, unsigned> &GlobalToGReg,
const MachineFunction *MF,
374 unsigned Opcode =
MI.getOpcode();
377 for (
const MachineOperand &MO :
MI.operands()) {
382 if (Opcode == SPIRV::OpConstantFunctionPointerINTEL &&
383 MRI.getRegClass(OpReg) == &SPIRV::pIDRegClass) {
384 visitFunPtrUse(OpReg, SignatureToGReg, GlobalToGReg, MF,
MI);
388 if (
MAI.hasRegisterAlias(MF, MO.
getReg()))
391 if (
const MachineInstr *OpDefMI =
MRI.getUniqueVRegDef(OpReg)) {
392 if (isDeclSection(
MRI, *OpDefMI))
393 visitDecl(
MRI, SignatureToGReg, GlobalToGReg, MF, *OpDefMI);
399 dbgs() <<
"Unexpectedly, no unique definition for the operand ";
401 dbgs() <<
"\nInstruction: ";
406 "No unique definition is found for the virtual register");
410 bool IsFunDef =
false;
411 if (TII->isSpecConstantInstr(
MI)) {
412 GReg =
MAI.getNextIDRegister();
414 }
else if (Opcode == SPIRV::OpFunction ||
415 Opcode == SPIRV::OpFunctionParameter) {
416 GReg = handleFunctionOrParameter(MF,
MI, GlobalToGReg, IsFunDef);
417 }
else if (Opcode == SPIRV::OpTypeStruct ||
418 Opcode == SPIRV::OpConstantComposite) {
419 GReg = handleTypeDeclOrConstant(
MI, SignatureToGReg);
420 const MachineInstr *NextInstr =
MI.getNextNode();
422 ((Opcode == SPIRV::OpTypeStruct &&
423 NextInstr->
getOpcode() == SPIRV::OpTypeStructContinuedINTEL) ||
424 (Opcode == SPIRV::OpConstantComposite &&
426 SPIRV::OpConstantCompositeContinuedINTEL))) {
427 MCRegister Tmp = handleTypeDeclOrConstant(*NextInstr, SignatureToGReg);
429 MAI.setSkipEmission(NextInstr);
432 }
else if (TII->isTypeDeclInstr(
MI) || TII->isConstantInstr(
MI) ||
433 TII->isInlineAsmDefInstr(
MI)) {
434 GReg = handleTypeDeclOrConstant(
MI, SignatureToGReg);
435 }
else if (Opcode == SPIRV::OpVariable) {
436 GReg = handleVariable(MF,
MI, GlobalToGReg);
439 dbgs() <<
"\nInstruction: ";
445 MAI.setRegisterAlias(MF,
MI.getOperand(0).getReg(), GReg);
447 MAI.setSkipEmission(&
MI);
450MCRegister SPIRVModuleAnalysis::handleFunctionOrParameter(
452 std::map<const Value *, unsigned> &GlobalToGReg,
bool &IsFunDef) {
453 const Value *GObj = GR->getGlobalObject(MF,
MI.getOperand(0).getReg());
454 assert(GObj &&
"Unregistered global definition");
458 assert(
F &&
"Expected a reference to a function or an argument");
459 IsFunDef = !
F->isDeclaration();
460 auto [It,
Inserted] = GlobalToGReg.try_emplace(GObj);
463 MCRegister GReg =
MAI.getNextIDRegister();
471SPIRVModuleAnalysis::handleTypeDeclOrConstant(
const MachineInstr &
MI,
474 auto [It,
Inserted] = SignatureToGReg.try_emplace(MISign);
477 MCRegister GReg =
MAI.getNextIDRegister();
483MCRegister SPIRVModuleAnalysis::handleVariable(
485 std::map<const Value *, unsigned> &GlobalToGReg) {
486 MAI.GlobalVarList.push_back(&
MI);
487 const Value *GObj = GR->getGlobalObject(MF,
MI.getOperand(0).getReg());
488 assert(GObj &&
"Unregistered global definition");
489 auto [It,
Inserted] = GlobalToGReg.try_emplace(GObj);
492 MCRegister GReg =
MAI.getNextIDRegister();
498void SPIRVModuleAnalysis::collectDeclarations(
const Module &M) {
500 std::map<const Value *, unsigned> GlobalToGReg;
501 for (
const Function &
F : M) {
502 MachineFunction *MF = MMI->getMachineFunction(
F);
506 unsigned PastHeader = 0;
507 for (MachineBasicBlock &
MBB : *MF) {
508 for (MachineInstr &
MI :
MBB) {
509 if (
MI.getNumOperands() == 0)
511 unsigned Opcode =
MI.getOpcode();
512 if (Opcode == SPIRV::OpFunction) {
513 if (PastHeader == 0) {
517 }
else if (Opcode == SPIRV::OpFunctionParameter) {
520 }
else if (PastHeader > 0) {
524 const MachineOperand &DefMO =
MI.getOperand(0);
526 case SPIRV::OpExtension:
527 MAI.Reqs.addExtension(SPIRV::Extension::Extension(DefMO.
getImm()));
528 MAI.setSkipEmission(&
MI);
530 case SPIRV::OpCapability:
531 MAI.Reqs.addCapability(SPIRV::Capability::Capability(DefMO.
getImm()));
532 MAI.setSkipEmission(&
MI);
537 if (DefMO.
isReg() && isDeclSection(
MRI,
MI) &&
538 !
MAI.hasRegisterAlias(MF, DefMO.
getReg()))
539 visitDecl(
MRI, SignatureToGReg, GlobalToGReg, MF,
MI);
552 if (
MI.getOpcode() == SPIRV::OpDecorate) {
554 auto Dec =
MI.getOperand(1).getImm();
555 if (Dec == SPIRV::Decoration::LinkageAttributes) {
556 auto Lnk =
MI.getOperand(
MI.getNumOperands() - 1).getImm();
557 if (Lnk == SPIRV::LinkageType::Import) {
562 MAI.FuncMap[ImportedFunc] =
MAI.getRegisterAlias(
MI.getMF(), Target);
565 }
else if (
MI.getOpcode() == SPIRV::OpFunction) {
568 MCRegister GlobalReg =
MAI.getRegisterAlias(
MI.getMF(),
Reg);
570 MAI.FuncMap[
F] = GlobalReg;
579 bool Append =
true) {
582 auto FoundMI = IS.insert(std::move(MISign));
583 if (!FoundMI.second) {
584 if (
MI.getOpcode() == SPIRV::OpDecorate) {
586 "Decoration instructions must have at least 2 operands");
588 "Only OpDecorate instructions can be duplicates");
593 if (
MI.getOperand(1).getImm() != SPIRV::Decoration::FPFastMathMode)
598 if (instrToSignature(*OrigMI, MAI,
true) == MISign) {
599 assert(OrigMI->getNumOperands() ==
MI.getNumOperands() &&
600 "Original instruction must have the same number of operands");
602 OrigMI->getNumOperands() == 3 &&
603 "FPFastMathMode decoration must have 3 operands for OpDecorate");
604 unsigned OrigFlags = OrigMI->getOperand(2).getImm();
605 unsigned NewFlags =
MI.getOperand(2).getImm();
606 if (OrigFlags == NewFlags)
610 unsigned FinalFlags = OrigFlags | NewFlags;
612 <<
"Warning: Conflicting FPFastMathMode decoration flags "
614 << *OrigMI <<
"Original flags: " << OrigFlags
615 <<
", new flags: " << NewFlags
616 <<
". They will be merged on a best effort basis, but not "
617 "validated. Final flags: "
618 << FinalFlags <<
"\n";
625 assert(
false &&
"No original instruction found for the duplicate "
626 "OpDecorate, but we found one in IS.");
639void SPIRVModuleAnalysis::processOtherInstrs(
const Module &M) {
641 for (
const Function &
F : M) {
642 if (
F.isDeclaration())
644 MachineFunction *MF = MMI->getMachineFunction(
F);
647 for (MachineBasicBlock &
MBB : *MF)
648 for (MachineInstr &
MI :
MBB) {
649 if (
MAI.getSkipEmission(&
MI))
651 const unsigned OpCode =
MI.getOpcode();
652 if (OpCode == SPIRV::OpString) {
654 }
else if (OpCode == SPIRV::OpExtInst &&
MI.getOperand(2).isImm() &&
655 MI.getOperand(2).getImm() ==
656 SPIRV::InstructionSet::
657 NonSemantic_Shader_DebugInfo_100) {
658 MachineOperand Ins =
MI.getOperand(3);
659 namespace NS = SPIRV::NonSemanticExtInst;
660 static constexpr int64_t GlobalNonSemanticDITy[] = {
661 NS::DebugSource, NS::DebugCompilationUnit, NS::DebugInfoNone,
662 NS::DebugTypeBasic, NS::DebugTypePointer};
663 bool IsGlobalDI =
false;
664 for (
unsigned Idx = 0; Idx < std::size(GlobalNonSemanticDITy); ++Idx)
665 IsGlobalDI |= Ins.
getImm() == GlobalNonSemanticDITy[Idx];
668 }
else if (OpCode == SPIRV::OpName || OpCode == SPIRV::OpMemberName) {
670 }
else if (OpCode == SPIRV::OpEntryPoint) {
672 }
else if (TII->isAliasingInstr(
MI)) {
674 }
else if (TII->isDecorationInstr(
MI)) {
676 collectFuncNames(
MI, &
F);
677 }
else if (TII->isConstantInstr(
MI)) {
681 }
else if (OpCode == SPIRV::OpFunction) {
682 collectFuncNames(
MI, &
F);
683 }
else if (OpCode == SPIRV::OpTypeForwardPointer) {
693void SPIRVModuleAnalysis::numberRegistersGlobally(
const Module &M) {
694 for (
const Function &
F : M) {
695 if (
F.isDeclaration())
697 MachineFunction *MF = MMI->getMachineFunction(
F);
699 for (MachineBasicBlock &
MBB : *MF) {
700 for (MachineInstr &
MI :
MBB) {
701 for (MachineOperand &
Op :
MI.operands()) {
705 if (
MAI.hasRegisterAlias(MF,
Reg))
707 MCRegister NewReg =
MAI.getNextIDRegister();
708 MAI.setRegisterAlias(MF,
Reg, NewReg);
710 if (
MI.getOpcode() != SPIRV::OpExtInst)
712 auto Set =
MI.getOperand(2).getImm();
713 auto [It,
Inserted] =
MAI.ExtInstSetMap.try_emplace(Set);
715 It->second =
MAI.getNextIDRegister();
723 SPIRV::OperandCategory::OperandCategory Category, uint32_t i,
725 addRequirements(getSymbolicOperandRequirements(Category, i, ST, *
this));
728void SPIRV::RequirementHandler::recursiveAddCapabilities(
730 for (
const auto &Cap : ToPrune) {
734 recursiveAddCapabilities(ImplicitDecls);
739 for (
const auto &Cap : ToAdd) {
740 bool IsNewlyInserted = AllCaps.insert(Cap).second;
741 if (!IsNewlyInserted)
745 recursiveAddCapabilities(ImplicitDecls);
746 MinimalCaps.push_back(Cap);
751 const SPIRV::Requirements &Req) {
755 if (Req.
Cap.has_value())
756 addCapabilities({Req.
Cap.value()});
758 addExtensions(Req.
Exts);
761 if (!MaxVersion.empty() && Req.
MinVer > MaxVersion) {
763 <<
" and <= " << MaxVersion <<
"\n");
767 if (MinVersion.empty() || Req.
MinVer > MinVersion)
772 if (!MinVersion.empty() && Req.
MaxVer < MinVersion) {
774 <<
" and >= " << MinVersion <<
"\n");
778 if (MaxVersion.empty() || Req.
MaxVer < MaxVersion)
784 const SPIRVSubtarget &ST)
const {
786 bool IsSatisfiable =
true;
787 auto TargetVer =
ST.getSPIRVVersion();
789 if (!MaxVersion.empty() && !TargetVer.empty() && MaxVersion < TargetVer) {
791 dbgs() <<
"Target SPIR-V version too high for required features\n"
792 <<
"Required max version: " << MaxVersion <<
" target version "
793 << TargetVer <<
"\n");
794 IsSatisfiable =
false;
797 if (!MinVersion.empty() && !TargetVer.empty() && MinVersion > TargetVer) {
798 LLVM_DEBUG(
dbgs() <<
"Target SPIR-V version too low for required features\n"
799 <<
"Required min version: " << MinVersion
800 <<
" target version " << TargetVer <<
"\n");
801 IsSatisfiable =
false;
804 if (!MinVersion.empty() && !MaxVersion.empty() && MinVersion > MaxVersion) {
807 <<
"Version is too low for some features and too high for others.\n"
808 <<
"Required SPIR-V min version: " << MinVersion
809 <<
" required SPIR-V max version " << MaxVersion <<
"\n");
810 IsSatisfiable =
false;
813 AvoidCapabilitiesSet AvoidCaps;
815 AvoidCaps.
S.
insert(SPIRV::Capability::Shader);
817 AvoidCaps.
S.
insert(SPIRV::Capability::Kernel);
819 for (
auto Cap : MinimalCaps) {
820 if (AvailableCaps.contains(Cap) && !AvoidCaps.
S.
contains(Cap))
824 OperandCategory::CapabilityOperand, Cap)
826 IsSatisfiable =
false;
829 for (
auto Ext : AllExtensions) {
830 if (
ST.canUseExtension(Ext))
834 OperandCategory::ExtensionOperand, Ext)
836 IsSatisfiable =
false;
845 for (
const auto Cap : ToAdd)
846 if (AvailableCaps.insert(Cap).second)
848 SPIRV::OperandCategory::CapabilityOperand, Cap));
852 const Capability::Capability
ToRemove,
853 const Capability::Capability IfPresent) {
854 if (AllCaps.contains(IfPresent))
862 addAvailableCaps({Capability::Shader, Capability::Linkage, Capability::Int8,
865 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 3)))
867 Capability::GroupNonUniformVote,
868 Capability::GroupNonUniformArithmetic,
869 Capability::GroupNonUniformBallot,
870 Capability::GroupNonUniformClustered,
871 Capability::GroupNonUniformShuffle,
872 Capability::GroupNonUniformShuffleRelative});
874 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 6)))
876 Capability::DotProductInput4x8Bit,
877 Capability::DotProductInput4x8BitPacked,
878 Capability::DemoteToHelperInvocation});
881 for (
auto Extension :
ST.getAllAvailableExtensions()) {
887 if (!
ST.isShader()) {
888 initAvailableCapabilitiesForOpenCL(ST);
893 initAvailableCapabilitiesForVulkan(ST);
900void RequirementHandler::initAvailableCapabilitiesForOpenCL(
901 const SPIRVSubtarget &ST) {
904 Capability::Kernel, Capability::Vector16,
905 Capability::Groups, Capability::GenericPointer,
906 Capability::StorageImageWriteWithoutFormat,
907 Capability::StorageImageReadWithoutFormat});
908 if (
ST.hasOpenCLFullProfile())
910 if (
ST.hasOpenCLImageSupport()) {
912 Capability::Image1D, Capability::SampledBuffer,
913 Capability::ImageBuffer});
914 if (
ST.isAtLeastOpenCLVer(VersionTuple(2, 0)))
917 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 1)) &&
918 ST.isAtLeastOpenCLVer(VersionTuple(2, 2)))
920 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 4)))
921 addAvailableCaps({Capability::DenormPreserve, Capability::DenormFlushToZero,
922 Capability::SignedZeroInfNanPreserve,
923 Capability::RoundingModeRTE,
924 Capability::RoundingModeRTZ});
931void RequirementHandler::initAvailableCapabilitiesForVulkan(
932 const SPIRVSubtarget &ST) {
935 addAvailableCaps({Capability::Int64, Capability::Float16, Capability::Float64,
936 Capability::GroupNonUniform, Capability::Image1D,
937 Capability::SampledBuffer, Capability::ImageBuffer,
938 Capability::UniformBufferArrayDynamicIndexing,
939 Capability::SampledImageArrayDynamicIndexing,
940 Capability::StorageBufferArrayDynamicIndexing,
941 Capability::StorageImageArrayDynamicIndexing,
942 Capability::DerivativeControl, Capability::MinLod,
943 Capability::ImageGatherExtended});
946 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 5))) {
948 {Capability::ShaderNonUniformEXT, Capability::RuntimeDescriptorArrayEXT,
949 Capability::InputAttachmentArrayDynamicIndexingEXT,
950 Capability::UniformTexelBufferArrayDynamicIndexingEXT,
951 Capability::StorageTexelBufferArrayDynamicIndexingEXT,
952 Capability::UniformBufferArrayNonUniformIndexingEXT,
953 Capability::SampledImageArrayNonUniformIndexingEXT,
954 Capability::StorageBufferArrayNonUniformIndexingEXT,
955 Capability::StorageImageArrayNonUniformIndexingEXT,
956 Capability::InputAttachmentArrayNonUniformIndexingEXT,
957 Capability::UniformTexelBufferArrayNonUniformIndexingEXT,
958 Capability::StorageTexelBufferArrayNonUniformIndexingEXT});
962 if (
ST.isAtLeastSPIRVVer(VersionTuple(1, 6)))
964 Capability::StorageImageReadWithoutFormat});
972static void addOpDecorateReqs(
const MachineInstr &
MI,
unsigned DecIndex,
975 int64_t DecOp =
MI.getOperand(DecIndex).getImm();
976 auto Dec =
static_cast<SPIRV::Decoration::Decoration
>(DecOp);
978 SPIRV::OperandCategory::DecorationOperand, Dec, ST, Reqs));
980 if (Dec == SPIRV::Decoration::BuiltIn) {
981 int64_t BuiltInOp =
MI.getOperand(DecIndex + 1).getImm();
982 auto BuiltIn =
static_cast<SPIRV::BuiltIn::BuiltIn
>(BuiltInOp);
984 SPIRV::OperandCategory::BuiltInOperand, BuiltIn, ST, Reqs));
985 }
else if (Dec == SPIRV::Decoration::LinkageAttributes) {
986 int64_t LinkageOp =
MI.getOperand(
MI.getNumOperands() - 1).getImm();
987 SPIRV::LinkageType::LinkageType LnkType =
988 static_cast<SPIRV::LinkageType::LinkageType
>(LinkageOp);
989 if (LnkType == SPIRV::LinkageType::LinkOnceODR)
990 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_linkonce_odr);
991 }
else if (Dec == SPIRV::Decoration::CacheControlLoadINTEL ||
992 Dec == SPIRV::Decoration::CacheControlStoreINTEL) {
993 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_cache_controls);
994 }
else if (Dec == SPIRV::Decoration::HostAccessINTEL) {
995 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_global_variable_host_access);
996 }
else if (Dec == SPIRV::Decoration::InitModeINTEL ||
997 Dec == SPIRV::Decoration::ImplementInRegisterMapINTEL) {
999 SPIRV::Extension::SPV_INTEL_global_variable_fpga_decorations);
1000 }
else if (Dec == SPIRV::Decoration::NonUniformEXT) {
1002 }
else if (Dec == SPIRV::Decoration::FPMaxErrorDecorationINTEL) {
1004 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_fp_max_error);
1005 }
else if (Dec == SPIRV::Decoration::FPFastMathMode) {
1006 if (
ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2)) {
1008 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_float_controls2);
1017 assert(
MI.getNumOperands() >= 8 &&
"Insufficient operands for OpTypeImage");
1020 int64_t ImgFormatOp =
MI.getOperand(7).getImm();
1021 auto ImgFormat =
static_cast<SPIRV::ImageFormat::ImageFormat
>(ImgFormatOp);
1025 bool IsArrayed =
MI.getOperand(4).getImm() == 1;
1026 bool IsMultisampled =
MI.getOperand(5).getImm() == 1;
1027 bool NoSampler =
MI.getOperand(6).getImm() == 2;
1030 switch (
MI.getOperand(2).getImm()) {
1031 case SPIRV::Dim::DIM_1D:
1033 : SPIRV::Capability::Sampled1D);
1035 case SPIRV::Dim::DIM_2D:
1036 if (IsMultisampled && NoSampler)
1039 case SPIRV::Dim::DIM_Cube:
1043 : SPIRV::Capability::SampledCubeArray);
1045 case SPIRV::Dim::DIM_Rect:
1047 : SPIRV::Capability::SampledRect);
1049 case SPIRV::Dim::DIM_Buffer:
1051 : SPIRV::Capability::SampledBuffer);
1053 case SPIRV::Dim::DIM_SubpassData:
1059 if (!
ST.isShader()) {
1060 if (
MI.getNumOperands() > 8 &&
1061 MI.getOperand(8).getImm() == SPIRV::AccessQualifier::ReadWrite)
1070 TypeDef->
getOpcode() == SPIRV::OpTypeFloat &&
1076#define ATOM_FLT_REQ_EXT_MSG(ExtName) \
1077 "The atomic float instruction requires the following SPIR-V " \
1078 "extension: SPV_EXT_shader_atomic_float" ExtName
1079static void AddAtomicVectorFloatRequirements(
const MachineInstr &
MI,
1083 MI.getMF()->getRegInfo().getVRegDef(
MI.getOperand(1).getReg());
1086 if (Rank != 2 && Rank != 4)
1088 "must be a 2-component or 4 component vector");
1093 if (EltTypeDef->
getOpcode() != SPIRV::OpTypeFloat ||
1096 "The element type for the result type of an atomic vector float "
1097 "instruction must be a 16-bit floating-point scalar");
1099 if (isBFloat16Type(EltTypeDef))
1101 "The element type for the result type of an atomic vector float "
1102 "instruction cannot be a bfloat16 scalar");
1103 if (!
ST.canUseExtension(SPIRV::Extension::SPV_NV_shader_atomic_fp16_vector))
1105 "The atomic float16 vector instruction requires the following SPIR-V "
1106 "extension: SPV_NV_shader_atomic_fp16_vector");
1108 Reqs.
addExtension(SPIRV::Extension::SPV_NV_shader_atomic_fp16_vector);
1109 Reqs.
addCapability(SPIRV::Capability::AtomicFloat16VectorNV);
1116 "Expect register operand in atomic float instruction");
1117 Register TypeReg =
MI.getOperand(1).getReg();
1120 if (TypeDef->
getOpcode() == SPIRV::OpTypeVector)
1121 return AddAtomicVectorFloatRequirements(
MI, Reqs, ST);
1123 if (TypeDef->
getOpcode() != SPIRV::OpTypeFloat)
1125 "floating-point type scalar");
1128 unsigned Op =
MI.getOpcode();
1129 if (
Op == SPIRV::OpAtomicFAddEXT) {
1130 if (!
ST.canUseExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float_add))
1132 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float_add);
1135 if (isBFloat16Type(TypeDef)) {
1136 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics))
1138 "The atomic bfloat16 instruction requires the following SPIR-V "
1139 "extension: SPV_INTEL_16bit_atomics",
1141 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics);
1142 Reqs.
addCapability(SPIRV::Capability::AtomicBFloat16AddINTEL);
1144 if (!
ST.canUseExtension(
1145 SPIRV::Extension::SPV_EXT_shader_atomic_float16_add))
1147 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float16_add);
1159 "Unexpected floating-point type width in atomic float instruction");
1162 if (!
ST.canUseExtension(
1163 SPIRV::Extension::SPV_EXT_shader_atomic_float_min_max))
1165 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_shader_atomic_float_min_max);
1168 if (isBFloat16Type(TypeDef)) {
1169 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics))
1171 "The atomic bfloat16 instruction requires the following SPIR-V "
1172 "extension: SPV_INTEL_16bit_atomics",
1174 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_16bit_atomics);
1175 Reqs.
addCapability(SPIRV::Capability::AtomicBFloat16MinMaxINTEL);
1177 Reqs.
addCapability(SPIRV::Capability::AtomicFloat16MinMaxEXT);
1181 Reqs.
addCapability(SPIRV::Capability::AtomicFloat32MinMaxEXT);
1184 Reqs.
addCapability(SPIRV::Capability::AtomicFloat64MinMaxEXT);
1188 "Unexpected floating-point type width in atomic float instruction");
1194 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1198 return Dim == SPIRV::Dim::DIM_Buffer && Sampled == 1;
1202 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1206 return Dim == SPIRV::Dim::DIM_Buffer && Sampled == 2;
1210 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1214 return Dim != SPIRV::Dim::DIM_Buffer && Sampled == 1;
1218 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1222 return Dim == SPIRV::Dim::DIM_SubpassData && Sampled == 2;
1226 if (ImageInst->
getOpcode() != SPIRV::OpTypeImage)
1230 return Dim != SPIRV::Dim::DIM_Buffer && Sampled == 2;
1233bool isCombinedImageSampler(
MachineInstr *SampledImageInst) {
1234 if (SampledImageInst->
getOpcode() != SPIRV::OpTypeSampledImage)
1239 auto *ImageInst =
MRI.getUniqueVRegDef(ImageReg);
1240 return isSampledImage(ImageInst);
1244 for (
const auto &
MI :
MRI.reg_instructions(
Reg)) {
1245 if (
MI.getOpcode() != SPIRV::OpDecorate)
1249 if (Dec == SPIRV::Decoration::NonUniformEXT)
1267 if (
StorageClass != SPIRV::StorageClass::StorageClass::UniformConstant &&
1268 StorageClass != SPIRV::StorageClass::StorageClass::Uniform &&
1269 StorageClass != SPIRV::StorageClass::StorageClass::StorageBuffer) {
1274 hasNonUniformDecoration(
Instr.getOperand(0).getReg(),
MRI);
1276 auto FirstIndexReg =
Instr.getOperand(3).getReg();
1277 bool FirstIndexIsConstant =
1280 if (
StorageClass == SPIRV::StorageClass::StorageClass::StorageBuffer) {
1283 SPIRV::Capability::StorageBufferArrayNonUniformIndexingEXT);
1284 else if (!FirstIndexIsConstant)
1286 SPIRV::Capability::StorageBufferArrayDynamicIndexing);
1292 if (PointeeType->
getOpcode() != SPIRV::OpTypeImage &&
1293 PointeeType->
getOpcode() != SPIRV::OpTypeSampledImage &&
1294 PointeeType->
getOpcode() != SPIRV::OpTypeSampler) {
1298 if (isUniformTexelBuffer(PointeeType)) {
1301 SPIRV::Capability::UniformTexelBufferArrayNonUniformIndexingEXT);
1302 else if (!FirstIndexIsConstant)
1304 SPIRV::Capability::UniformTexelBufferArrayDynamicIndexingEXT);
1305 }
else if (isInputAttachment(PointeeType)) {
1308 SPIRV::Capability::InputAttachmentArrayNonUniformIndexingEXT);
1309 else if (!FirstIndexIsConstant)
1311 SPIRV::Capability::InputAttachmentArrayDynamicIndexingEXT);
1312 }
else if (isStorageTexelBuffer(PointeeType)) {
1315 SPIRV::Capability::StorageTexelBufferArrayNonUniformIndexingEXT);
1316 else if (!FirstIndexIsConstant)
1318 SPIRV::Capability::StorageTexelBufferArrayDynamicIndexingEXT);
1319 }
else if (isSampledImage(PointeeType) ||
1320 isCombinedImageSampler(PointeeType) ||
1321 PointeeType->
getOpcode() == SPIRV::OpTypeSampler) {
1324 SPIRV::Capability::SampledImageArrayNonUniformIndexingEXT);
1325 else if (!FirstIndexIsConstant)
1327 SPIRV::Capability::SampledImageArrayDynamicIndexing);
1328 }
else if (isStorageImage(PointeeType)) {
1331 SPIRV::Capability::StorageImageArrayNonUniformIndexingEXT);
1332 else if (!FirstIndexIsConstant)
1334 SPIRV::Capability::StorageImageArrayDynamicIndexing);
1338static bool isImageTypeWithUnknownFormat(
SPIRVTypeInst TypeInst) {
1339 if (TypeInst->
getOpcode() != SPIRV::OpTypeImage)
1348 if (
ST.canUseExtension(SPIRV::Extension::SPV_KHR_integer_dot_product))
1349 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_integer_dot_product);
1353 assert(
MI.getOperand(2).isReg() &&
"Unexpected operand in dot");
1357 assert(
Input->getOperand(1).isReg() &&
"Unexpected operand in dot input");
1361 if (TypeDef->
getOpcode() == SPIRV::OpTypeInt) {
1363 Reqs.
addCapability(SPIRV::Capability::DotProductInput4x8BitPacked);
1364 }
else if (TypeDef->
getOpcode() == SPIRV::OpTypeVector) {
1370 "Dot operand of 8-bit integer type requires 4 components");
1371 Reqs.
addCapability(SPIRV::Capability::DotProductInput4x8Bit);
1386 unsigned AddrSpace = ASOp.
getImm();
1387 if (AddrSpace != SPIRV::StorageClass::UniformConstant) {
1388 if (!
ST.canUseExtension(
1390 SPV_EXT_relaxed_printf_string_address_space)) {
1392 "required because printf uses a format string not "
1393 "in constant address space.",
1397 SPIRV::Extension::SPV_EXT_relaxed_printf_string_address_space);
1406 if (
MI.getNumOperands() <=
OpIdx)
1410 if (Mask & (1U <<
I))
1419 switch (
MI.getOpcode()) {
1420 case SPIRV::OpMemoryModel: {
1421 int64_t Addr =
MI.getOperand(0).getImm();
1424 int64_t Mem =
MI.getOperand(1).getImm();
1429 case SPIRV::OpEntryPoint: {
1430 int64_t
Exe =
MI.getOperand(0).getImm();
1435 case SPIRV::OpExecutionMode:
1436 case SPIRV::OpExecutionModeId: {
1437 int64_t
Exe =
MI.getOperand(1).getImm();
1442 case SPIRV::OpTypeMatrix:
1445 case SPIRV::OpTypeInt: {
1446 unsigned BitWidth =
MI.getOperand(1).getImm();
1454 ST.canUseExtension(SPIRV::Extension::SPV_INTEL_int4)) {
1458 if (!
ST.canUseExtension(
1459 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_integers))
1461 "OpTypeInt type with a width other than 8, 16, 32 or 64 bits "
1462 "requires the following SPIR-V extension: "
1463 "SPV_ALTERA_arbitrary_precision_integers");
1465 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_integers);
1466 Reqs.
addCapability(SPIRV::Capability::ArbitraryPrecisionIntegersALTERA);
1470 case SPIRV::OpDot: {
1473 if (isBFloat16Type(TypeDef))
1474 Reqs.
addCapability(SPIRV::Capability::BFloat16DotProductKHR);
1477 case SPIRV::OpTypeFloat: {
1478 unsigned BitWidth =
MI.getOperand(1).getImm();
1482 if (isBFloat16Type(&
MI)) {
1483 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_bfloat16))
1485 "following SPIR-V extension: SPV_KHR_bfloat16",
1495 case SPIRV::OpTypeVector: {
1496 unsigned NumComponents =
MI.getOperand(2).getImm();
1497 if (NumComponents == 8 || NumComponents == 16)
1501 case SPIRV::OpTypePointer: {
1502 auto SC =
MI.getOperand(1).getImm();
1513 (TypeDef->
getOpcode() == SPIRV::OpTypeFloat) &&
1518 case SPIRV::OpExtInst: {
1519 if (
MI.getOperand(2).getImm() ==
1520 static_cast<int64_t
>(
1521 SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100)) {
1522 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_non_semantic_info);
1525 if (
MI.getOperand(3).getImm() ==
1526 static_cast<int64_t
>(SPIRV::OpenCLExtInst::printf)) {
1527 addPrintfRequirements(
MI, Reqs, ST);
1534 case SPIRV::OpAliasDomainDeclINTEL:
1535 case SPIRV::OpAliasScopeDeclINTEL:
1536 case SPIRV::OpAliasScopeListDeclINTEL: {
1537 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_memory_access_aliasing);
1538 Reqs.
addCapability(SPIRV::Capability::MemoryAccessAliasingINTEL);
1541 case SPIRV::OpBitReverse:
1542 case SPIRV::OpBitFieldInsert:
1543 case SPIRV::OpBitFieldSExtract:
1544 case SPIRV::OpBitFieldUExtract:
1545 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_bit_instructions)) {
1549 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_bit_instructions);
1552 case SPIRV::OpTypeRuntimeArray:
1555 case SPIRV::OpTypeOpaque:
1556 case SPIRV::OpTypeEvent:
1559 case SPIRV::OpTypePipe:
1560 case SPIRV::OpTypeReserveId:
1563 case SPIRV::OpTypeDeviceEvent:
1564 case SPIRV::OpTypeQueue:
1565 case SPIRV::OpBuildNDRange:
1568 case SPIRV::OpDecorate:
1569 case SPIRV::OpDecorateId:
1570 case SPIRV::OpDecorateString:
1571 addOpDecorateReqs(
MI, 1, Reqs, ST);
1573 case SPIRV::OpMemberDecorate:
1574 case SPIRV::OpMemberDecorateString:
1575 addOpDecorateReqs(
MI, 2, Reqs, ST);
1577 case SPIRV::OpInBoundsPtrAccessChain:
1580 case SPIRV::OpConstantSampler:
1583 case SPIRV::OpInBoundsAccessChain:
1584 case SPIRV::OpAccessChain:
1585 addOpAccessChainReqs(
MI, Reqs, ST);
1587 case SPIRV::OpTypeImage:
1588 addOpTypeImageReqs(
MI, Reqs, ST);
1590 case SPIRV::OpTypeSampler:
1591 if (!
ST.isShader()) {
1595 case SPIRV::OpTypeForwardPointer:
1599 case SPIRV::OpAtomicFlagTestAndSet:
1600 case SPIRV::OpAtomicLoad:
1601 case SPIRV::OpAtomicStore:
1602 case SPIRV::OpAtomicExchange:
1603 case SPIRV::OpAtomicCompareExchange:
1604 case SPIRV::OpAtomicIIncrement:
1605 case SPIRV::OpAtomicIDecrement:
1606 case SPIRV::OpAtomicIAdd:
1607 case SPIRV::OpAtomicISub:
1608 case SPIRV::OpAtomicUMin:
1609 case SPIRV::OpAtomicUMax:
1610 case SPIRV::OpAtomicSMin:
1611 case SPIRV::OpAtomicSMax:
1612 case SPIRV::OpAtomicAnd:
1613 case SPIRV::OpAtomicOr:
1614 case SPIRV::OpAtomicXor: {
1617 if (
MI.getOpcode() == SPIRV::OpAtomicStore) {
1619 InstrPtr =
MRI.getVRegDef(
MI.getOperand(3).getReg());
1620 assert(InstrPtr &&
"Unexpected type instruction for OpAtomicStore");
1625 if (TypeDef->
getOpcode() == SPIRV::OpTypeInt) {
1632 case SPIRV::OpGroupNonUniformIAdd:
1633 case SPIRV::OpGroupNonUniformFAdd:
1634 case SPIRV::OpGroupNonUniformIMul:
1635 case SPIRV::OpGroupNonUniformFMul:
1636 case SPIRV::OpGroupNonUniformSMin:
1637 case SPIRV::OpGroupNonUniformUMin:
1638 case SPIRV::OpGroupNonUniformFMin:
1639 case SPIRV::OpGroupNonUniformSMax:
1640 case SPIRV::OpGroupNonUniformUMax:
1641 case SPIRV::OpGroupNonUniformFMax:
1642 case SPIRV::OpGroupNonUniformBitwiseAnd:
1643 case SPIRV::OpGroupNonUniformBitwiseOr:
1644 case SPIRV::OpGroupNonUniformBitwiseXor:
1645 case SPIRV::OpGroupNonUniformLogicalAnd:
1646 case SPIRV::OpGroupNonUniformLogicalOr:
1647 case SPIRV::OpGroupNonUniformLogicalXor: {
1649 int64_t GroupOp =
MI.getOperand(3).getImm();
1651 case SPIRV::GroupOperation::Reduce:
1652 case SPIRV::GroupOperation::InclusiveScan:
1653 case SPIRV::GroupOperation::ExclusiveScan:
1654 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformArithmetic);
1656 case SPIRV::GroupOperation::ClusteredReduce:
1657 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformClustered);
1659 case SPIRV::GroupOperation::PartitionedReduceNV:
1660 case SPIRV::GroupOperation::PartitionedInclusiveScanNV:
1661 case SPIRV::GroupOperation::PartitionedExclusiveScanNV:
1662 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformPartitionedNV);
1667 case SPIRV::OpImageQueryFormat: {
1668 Register ResultReg =
MI.getOperand(0).getReg();
1670 static const unsigned CompareOps[] = {
1671 SPIRV::OpIEqual, SPIRV::OpINotEqual,
1672 SPIRV::OpUGreaterThan, SPIRV::OpUGreaterThanEqual,
1673 SPIRV::OpULessThan, SPIRV::OpULessThanEqual,
1674 SPIRV::OpSGreaterThan, SPIRV::OpSGreaterThanEqual,
1675 SPIRV::OpSLessThan, SPIRV::OpSLessThanEqual};
1677 auto CheckAndAddExtension = [&](int64_t ImmVal) {
1678 if (ImmVal == 4323 || ImmVal == 4324) {
1679 if (
ST.canUseExtension(SPIRV::Extension::SPV_EXT_image_raw10_raw12))
1680 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_image_raw10_raw12);
1683 "SPV_EXT_image_raw10_raw12 extension");
1688 unsigned Opc = UseInst.getOpcode();
1690 if (
Opc == SPIRV::OpSwitch) {
1693 CheckAndAddExtension(
Op.getImm());
1695 for (
unsigned i = 1; i < UseInst.getNumOperands(); ++i) {
1698 if (ConstInst && ConstInst->
getOpcode() == SPIRV::OpConstantI) {
1701 CheckAndAddExtension(ImmVal);
1709 case SPIRV::OpGroupNonUniformShuffle:
1710 case SPIRV::OpGroupNonUniformShuffleXor:
1711 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformShuffle);
1713 case SPIRV::OpGroupNonUniformShuffleUp:
1714 case SPIRV::OpGroupNonUniformShuffleDown:
1715 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformShuffleRelative);
1717 case SPIRV::OpGroupAll:
1718 case SPIRV::OpGroupAny:
1719 case SPIRV::OpGroupBroadcast:
1720 case SPIRV::OpGroupIAdd:
1721 case SPIRV::OpGroupFAdd:
1722 case SPIRV::OpGroupFMin:
1723 case SPIRV::OpGroupUMin:
1724 case SPIRV::OpGroupSMin:
1725 case SPIRV::OpGroupFMax:
1726 case SPIRV::OpGroupUMax:
1727 case SPIRV::OpGroupSMax:
1730 case SPIRV::OpGroupNonUniformElect:
1733 case SPIRV::OpGroupNonUniformAll:
1734 case SPIRV::OpGroupNonUniformAny:
1735 case SPIRV::OpGroupNonUniformAllEqual:
1738 case SPIRV::OpGroupNonUniformBroadcast:
1739 case SPIRV::OpGroupNonUniformBroadcastFirst:
1740 case SPIRV::OpGroupNonUniformBallot:
1741 case SPIRV::OpGroupNonUniformInverseBallot:
1742 case SPIRV::OpGroupNonUniformBallotBitExtract:
1743 case SPIRV::OpGroupNonUniformBallotBitCount:
1744 case SPIRV::OpGroupNonUniformBallotFindLSB:
1745 case SPIRV::OpGroupNonUniformBallotFindMSB:
1746 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformBallot);
1748 case SPIRV::OpSubgroupShuffleINTEL:
1749 case SPIRV::OpSubgroupShuffleDownINTEL:
1750 case SPIRV::OpSubgroupShuffleUpINTEL:
1751 case SPIRV::OpSubgroupShuffleXorINTEL:
1752 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {
1753 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_subgroups);
1754 Reqs.
addCapability(SPIRV::Capability::SubgroupShuffleINTEL);
1757 case SPIRV::OpSubgroupBlockReadINTEL:
1758 case SPIRV::OpSubgroupBlockWriteINTEL:
1759 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {
1760 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_subgroups);
1761 Reqs.
addCapability(SPIRV::Capability::SubgroupBufferBlockIOINTEL);
1764 case SPIRV::OpSubgroupImageBlockReadINTEL:
1765 case SPIRV::OpSubgroupImageBlockWriteINTEL:
1766 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {
1767 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_subgroups);
1768 Reqs.
addCapability(SPIRV::Capability::SubgroupImageBlockIOINTEL);
1771 case SPIRV::OpSubgroupImageMediaBlockReadINTEL:
1772 case SPIRV::OpSubgroupImageMediaBlockWriteINTEL:
1773 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_media_block_io)) {
1774 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_media_block_io);
1775 Reqs.
addCapability(SPIRV::Capability::SubgroupImageMediaBlockIOINTEL);
1778 case SPIRV::OpAssumeTrueKHR:
1779 case SPIRV::OpExpectKHR:
1780 if (
ST.canUseExtension(SPIRV::Extension::SPV_KHR_expect_assume)) {
1781 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_expect_assume);
1785 case SPIRV::OpFmaKHR:
1786 if (
ST.canUseExtension(SPIRV::Extension::SPV_KHR_fma)) {
1791 case SPIRV::OpPtrCastToCrossWorkgroupINTEL:
1792 case SPIRV::OpCrossWorkgroupCastToPtrINTEL:
1793 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_usm_storage_classes)) {
1794 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_usm_storage_classes);
1795 Reqs.
addCapability(SPIRV::Capability::USMStorageClassesINTEL);
1798 case SPIRV::OpConstantFunctionPointerINTEL:
1799 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_function_pointers)) {
1800 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_function_pointers);
1801 Reqs.
addCapability(SPIRV::Capability::FunctionPointersINTEL);
1804 case SPIRV::OpGroupNonUniformRotateKHR:
1805 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_subgroup_rotate))
1807 "following SPIR-V extension: SPV_KHR_subgroup_rotate",
1809 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_subgroup_rotate);
1810 Reqs.
addCapability(SPIRV::Capability::GroupNonUniformRotateKHR);
1813 case SPIRV::OpFixedCosALTERA:
1814 case SPIRV::OpFixedSinALTERA:
1815 case SPIRV::OpFixedCosPiALTERA:
1816 case SPIRV::OpFixedSinPiALTERA:
1817 case SPIRV::OpFixedExpALTERA:
1818 case SPIRV::OpFixedLogALTERA:
1819 case SPIRV::OpFixedRecipALTERA:
1820 case SPIRV::OpFixedSqrtALTERA:
1821 case SPIRV::OpFixedSinCosALTERA:
1822 case SPIRV::OpFixedSinCosPiALTERA:
1823 case SPIRV::OpFixedRsqrtALTERA:
1824 if (!
ST.canUseExtension(
1825 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_fixed_point))
1827 "following SPIR-V extension: "
1828 "SPV_ALTERA_arbitrary_precision_fixed_point",
1831 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_fixed_point);
1832 Reqs.
addCapability(SPIRV::Capability::ArbitraryPrecisionFixedPointALTERA);
1834 case SPIRV::OpGroupIMulKHR:
1835 case SPIRV::OpGroupFMulKHR:
1836 case SPIRV::OpGroupBitwiseAndKHR:
1837 case SPIRV::OpGroupBitwiseOrKHR:
1838 case SPIRV::OpGroupBitwiseXorKHR:
1839 case SPIRV::OpGroupLogicalAndKHR:
1840 case SPIRV::OpGroupLogicalOrKHR:
1841 case SPIRV::OpGroupLogicalXorKHR:
1842 if (
ST.canUseExtension(
1843 SPIRV::Extension::SPV_KHR_uniform_group_instructions)) {
1844 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_uniform_group_instructions);
1845 Reqs.
addCapability(SPIRV::Capability::GroupUniformArithmeticKHR);
1848 case SPIRV::OpReadClockKHR:
1849 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_shader_clock))
1851 "following SPIR-V extension: SPV_KHR_shader_clock",
1853 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_shader_clock);
1856 case SPIRV::OpFunctionPointerCallINTEL:
1857 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_function_pointers)) {
1858 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_function_pointers);
1859 Reqs.
addCapability(SPIRV::Capability::FunctionPointersINTEL);
1862 case SPIRV::OpAtomicFAddEXT:
1863 case SPIRV::OpAtomicFMinEXT:
1864 case SPIRV::OpAtomicFMaxEXT:
1865 AddAtomicFloatRequirements(
MI, Reqs, ST);
1867 case SPIRV::OpConvertBF16ToFINTEL:
1868 case SPIRV::OpConvertFToBF16INTEL:
1869 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bfloat16_conversion)) {
1870 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bfloat16_conversion);
1871 Reqs.
addCapability(SPIRV::Capability::BFloat16ConversionINTEL);
1874 case SPIRV::OpRoundFToTF32INTEL:
1875 if (
ST.canUseExtension(
1876 SPIRV::Extension::SPV_INTEL_tensor_float32_conversion)) {
1877 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_tensor_float32_conversion);
1878 Reqs.
addCapability(SPIRV::Capability::TensorFloat32RoundingINTEL);
1881 case SPIRV::OpVariableLengthArrayINTEL:
1882 case SPIRV::OpSaveMemoryINTEL:
1883 case SPIRV::OpRestoreMemoryINTEL:
1884 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_variable_length_array)) {
1885 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_variable_length_array);
1886 Reqs.
addCapability(SPIRV::Capability::VariableLengthArrayINTEL);
1889 case SPIRV::OpAsmTargetINTEL:
1890 case SPIRV::OpAsmINTEL:
1891 case SPIRV::OpAsmCallINTEL:
1892 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_inline_assembly)) {
1893 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_inline_assembly);
1897 case SPIRV::OpTypeCooperativeMatrixKHR: {
1898 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix))
1900 "OpTypeCooperativeMatrixKHR type requires the "
1901 "following SPIR-V extension: SPV_KHR_cooperative_matrix",
1903 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix);
1904 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixKHR);
1907 if (isBFloat16Type(TypeDef))
1908 Reqs.
addCapability(SPIRV::Capability::BFloat16CooperativeMatrixKHR);
1911 case SPIRV::OpArithmeticFenceEXT:
1912 if (!
ST.canUseExtension(SPIRV::Extension::SPV_EXT_arithmetic_fence))
1914 "following SPIR-V extension: SPV_EXT_arithmetic_fence",
1916 Reqs.
addExtension(SPIRV::Extension::SPV_EXT_arithmetic_fence);
1919 case SPIRV::OpControlBarrierArriveINTEL:
1920 case SPIRV::OpControlBarrierWaitINTEL:
1921 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_split_barrier)) {
1922 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_split_barrier);
1926 case SPIRV::OpCooperativeMatrixMulAddKHR: {
1927 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix))
1929 "following SPIR-V extension: "
1930 "SPV_KHR_cooperative_matrix",
1932 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix);
1933 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixKHR);
1934 constexpr unsigned MulAddMaxSize = 6;
1935 if (
MI.getNumOperands() != MulAddMaxSize)
1937 const int64_t CoopOperands =
MI.getOperand(MulAddMaxSize - 1).getImm();
1939 SPIRV::CooperativeMatrixOperands::MatrixAAndBTF32ComponentsINTEL) {
1940 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
1942 "require the following SPIR-V extension: "
1943 "SPV_INTEL_joint_matrix",
1945 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
1947 SPIRV::Capability::CooperativeMatrixTF32ComponentTypeINTEL);
1950 MatrixAAndBBFloat16ComponentsINTEL ||
1952 SPIRV::CooperativeMatrixOperands::MatrixCBFloat16ComponentsINTEL ||
1954 MatrixResultBFloat16ComponentsINTEL) {
1955 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
1957 "require the following SPIR-V extension: "
1958 "SPV_INTEL_joint_matrix",
1960 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
1962 SPIRV::Capability::CooperativeMatrixBFloat16ComponentTypeINTEL);
1966 case SPIRV::OpCooperativeMatrixLoadKHR:
1967 case SPIRV::OpCooperativeMatrixStoreKHR:
1968 case SPIRV::OpCooperativeMatrixLoadCheckedINTEL:
1969 case SPIRV::OpCooperativeMatrixStoreCheckedINTEL:
1970 case SPIRV::OpCooperativeMatrixPrefetchINTEL: {
1971 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix))
1973 "following SPIR-V extension: "
1974 "SPV_KHR_cooperative_matrix",
1976 Reqs.
addExtension(SPIRV::Extension::SPV_KHR_cooperative_matrix);
1977 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixKHR);
1981 std::unordered_map<unsigned, unsigned> LayoutToInstMap = {
1982 {SPIRV::OpCooperativeMatrixLoadKHR, 3},
1983 {SPIRV::OpCooperativeMatrixStoreKHR, 2},
1984 {SPIRV::OpCooperativeMatrixLoadCheckedINTEL, 5},
1985 {SPIRV::OpCooperativeMatrixStoreCheckedINTEL, 4},
1986 {SPIRV::OpCooperativeMatrixPrefetchINTEL, 4}};
1988 const auto OpCode =
MI.getOpcode();
1989 const unsigned LayoutNum = LayoutToInstMap[OpCode];
1990 Register RegLayout =
MI.getOperand(LayoutNum).getReg();
1993 if (MILayout->
getOpcode() == SPIRV::OpConstantI) {
1996 static_cast<unsigned>(SPIRV::CooperativeMatrixLayout::PackedINTEL)) {
1997 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
1999 "extension: SPV_INTEL_joint_matrix",
2001 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2002 Reqs.
addCapability(SPIRV::Capability::PackedCooperativeMatrixINTEL);
2007 if (OpCode == SPIRV::OpCooperativeMatrixLoadKHR ||
2008 OpCode == SPIRV::OpCooperativeMatrixStoreKHR)
2011 std::string InstName;
2013 case SPIRV::OpCooperativeMatrixPrefetchINTEL:
2014 InstName =
"OpCooperativeMatrixPrefetchINTEL";
2016 case SPIRV::OpCooperativeMatrixLoadCheckedINTEL:
2017 InstName =
"OpCooperativeMatrixLoadCheckedINTEL";
2019 case SPIRV::OpCooperativeMatrixStoreCheckedINTEL:
2020 InstName =
"OpCooperativeMatrixStoreCheckedINTEL";
2024 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix)) {
2025 const std::string ErrorMsg =
2026 InstName +
" instruction requires the "
2027 "following SPIR-V extension: SPV_INTEL_joint_matrix";
2030 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2031 if (OpCode == SPIRV::OpCooperativeMatrixPrefetchINTEL) {
2032 Reqs.
addCapability(SPIRV::Capability::CooperativeMatrixPrefetchINTEL);
2036 SPIRV::Capability::CooperativeMatrixCheckedInstructionsINTEL);
2039 case SPIRV::OpCooperativeMatrixConstructCheckedINTEL:
2040 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
2042 "instructions require the following SPIR-V extension: "
2043 "SPV_INTEL_joint_matrix",
2045 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2047 SPIRV::Capability::CooperativeMatrixCheckedInstructionsINTEL);
2049 case SPIRV::OpReadPipeBlockingALTERA:
2050 case SPIRV::OpWritePipeBlockingALTERA:
2051 if (
ST.canUseExtension(SPIRV::Extension::SPV_ALTERA_blocking_pipes)) {
2052 Reqs.
addExtension(SPIRV::Extension::SPV_ALTERA_blocking_pipes);
2056 case SPIRV::OpCooperativeMatrixGetElementCoordINTEL:
2057 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_joint_matrix))
2059 "following SPIR-V extension: SPV_INTEL_joint_matrix",
2061 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_joint_matrix);
2063 SPIRV::Capability::CooperativeMatrixInvocationInstructionsINTEL);
2065 case SPIRV::OpConvertHandleToImageINTEL:
2066 case SPIRV::OpConvertHandleToSamplerINTEL:
2067 case SPIRV::OpConvertHandleToSampledImageINTEL: {
2068 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bindless_images))
2070 "instructions require the following SPIR-V extension: "
2071 "SPV_INTEL_bindless_images",
2074 SPIRV::AddressingModel::AddressingModel AddrModel = MAI.
Addr;
2076 if (
MI.getOpcode() == SPIRV::OpConvertHandleToImageINTEL &&
2077 TyDef->
getOpcode() != SPIRV::OpTypeImage) {
2079 "OpConvertHandleToImageINTEL",
2081 }
else if (
MI.getOpcode() == SPIRV::OpConvertHandleToSamplerINTEL &&
2082 TyDef->
getOpcode() != SPIRV::OpTypeSampler) {
2084 "OpConvertHandleToSamplerINTEL",
2086 }
else if (
MI.getOpcode() == SPIRV::OpConvertHandleToSampledImageINTEL &&
2087 TyDef->
getOpcode() != SPIRV::OpTypeSampledImage) {
2089 "OpConvertHandleToSampledImageINTEL",
2094 if (!(Bitwidth == 32 && AddrModel == SPIRV::AddressingModel::Physical32) &&
2095 !(Bitwidth == 64 && AddrModel == SPIRV::AddressingModel::Physical64)) {
2097 "Parameter value must be a 32-bit scalar in case of "
2098 "Physical32 addressing model or a 64-bit scalar in case of "
2099 "Physical64 addressing model",
2102 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bindless_images);
2106 case SPIRV::OpSubgroup2DBlockLoadINTEL:
2107 case SPIRV::OpSubgroup2DBlockLoadTransposeINTEL:
2108 case SPIRV::OpSubgroup2DBlockLoadTransformINTEL:
2109 case SPIRV::OpSubgroup2DBlockPrefetchINTEL:
2110 case SPIRV::OpSubgroup2DBlockStoreINTEL: {
2111 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_2d_block_io))
2113 "Prefetch/Store]INTEL instructions require the "
2114 "following SPIR-V extension: SPV_INTEL_2d_block_io",
2116 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_2d_block_io);
2117 Reqs.
addCapability(SPIRV::Capability::Subgroup2DBlockIOINTEL);
2119 const auto OpCode =
MI.getOpcode();
2120 if (OpCode == SPIRV::OpSubgroup2DBlockLoadTransposeINTEL) {
2121 Reqs.
addCapability(SPIRV::Capability::Subgroup2DBlockTransposeINTEL);
2124 if (OpCode == SPIRV::OpSubgroup2DBlockLoadTransformINTEL) {
2125 Reqs.
addCapability(SPIRV::Capability::Subgroup2DBlockTransformINTEL);
2130 case SPIRV::OpKill: {
2133 case SPIRV::OpDemoteToHelperInvocation:
2134 Reqs.
addCapability(SPIRV::Capability::DemoteToHelperInvocation);
2136 if (
ST.canUseExtension(
2137 SPIRV::Extension::SPV_EXT_demote_to_helper_invocation)) {
2140 SPIRV::Extension::SPV_EXT_demote_to_helper_invocation);
2145 case SPIRV::OpSUDot:
2146 case SPIRV::OpSDotAccSat:
2147 case SPIRV::OpUDotAccSat:
2148 case SPIRV::OpSUDotAccSat:
2149 AddDotProductRequirements(
MI, Reqs, ST);
2151 case SPIRV::OpImageSampleImplicitLod:
2153 addImageOperandReqs(
MI, Reqs, ST, 4);
2155 case SPIRV::OpImageSampleExplicitLod:
2156 addImageOperandReqs(
MI, Reqs, ST, 4);
2158 case SPIRV::OpImageSampleDrefImplicitLod:
2160 addImageOperandReqs(
MI, Reqs, ST, 5);
2162 case SPIRV::OpImageSampleDrefExplicitLod:
2164 addImageOperandReqs(
MI, Reqs, ST, 5);
2166 case SPIRV::OpImageDrefGather:
2167 case SPIRV::OpImageGather:
2169 addImageOperandReqs(
MI, Reqs, ST, 5);
2171 case SPIRV::OpImageRead: {
2172 Register ImageReg =
MI.getOperand(2).getReg();
2181 if (isImageTypeWithUnknownFormat(TypeDef) &&
ST.isShader())
2182 Reqs.
addCapability(SPIRV::Capability::StorageImageReadWithoutFormat);
2185 case SPIRV::OpImageWrite: {
2186 Register ImageReg =
MI.getOperand(0).getReg();
2195 if (isImageTypeWithUnknownFormat(TypeDef) &&
ST.isShader())
2196 Reqs.
addCapability(SPIRV::Capability::StorageImageWriteWithoutFormat);
2199 case SPIRV::OpTypeStructContinuedINTEL:
2200 case SPIRV::OpConstantCompositeContinuedINTEL:
2201 case SPIRV::OpSpecConstantCompositeContinuedINTEL:
2202 case SPIRV::OpCompositeConstructContinuedINTEL: {
2203 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_long_composites))
2205 "Continued instructions require the "
2206 "following SPIR-V extension: SPV_INTEL_long_composites",
2208 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_long_composites);
2212 case SPIRV::OpArbitraryFloatEQALTERA:
2213 case SPIRV::OpArbitraryFloatGEALTERA:
2214 case SPIRV::OpArbitraryFloatGTALTERA:
2215 case SPIRV::OpArbitraryFloatLEALTERA:
2216 case SPIRV::OpArbitraryFloatLTALTERA:
2217 case SPIRV::OpArbitraryFloatCbrtALTERA:
2218 case SPIRV::OpArbitraryFloatCosALTERA:
2219 case SPIRV::OpArbitraryFloatCosPiALTERA:
2220 case SPIRV::OpArbitraryFloatExp10ALTERA:
2221 case SPIRV::OpArbitraryFloatExp2ALTERA:
2222 case SPIRV::OpArbitraryFloatExpALTERA:
2223 case SPIRV::OpArbitraryFloatExpm1ALTERA:
2224 case SPIRV::OpArbitraryFloatHypotALTERA:
2225 case SPIRV::OpArbitraryFloatLog10ALTERA:
2226 case SPIRV::OpArbitraryFloatLog1pALTERA:
2227 case SPIRV::OpArbitraryFloatLog2ALTERA:
2228 case SPIRV::OpArbitraryFloatLogALTERA:
2229 case SPIRV::OpArbitraryFloatRecipALTERA:
2230 case SPIRV::OpArbitraryFloatSinCosALTERA:
2231 case SPIRV::OpArbitraryFloatSinCosPiALTERA:
2232 case SPIRV::OpArbitraryFloatSinALTERA:
2233 case SPIRV::OpArbitraryFloatSinPiALTERA:
2234 case SPIRV::OpArbitraryFloatSqrtALTERA:
2235 case SPIRV::OpArbitraryFloatACosALTERA:
2236 case SPIRV::OpArbitraryFloatACosPiALTERA:
2237 case SPIRV::OpArbitraryFloatAddALTERA:
2238 case SPIRV::OpArbitraryFloatASinALTERA:
2239 case SPIRV::OpArbitraryFloatASinPiALTERA:
2240 case SPIRV::OpArbitraryFloatATan2ALTERA:
2241 case SPIRV::OpArbitraryFloatATanALTERA:
2242 case SPIRV::OpArbitraryFloatATanPiALTERA:
2243 case SPIRV::OpArbitraryFloatCastFromIntALTERA:
2244 case SPIRV::OpArbitraryFloatCastALTERA:
2245 case SPIRV::OpArbitraryFloatCastToIntALTERA:
2246 case SPIRV::OpArbitraryFloatDivALTERA:
2247 case SPIRV::OpArbitraryFloatMulALTERA:
2248 case SPIRV::OpArbitraryFloatPowALTERA:
2249 case SPIRV::OpArbitraryFloatPowNALTERA:
2250 case SPIRV::OpArbitraryFloatPowRALTERA:
2251 case SPIRV::OpArbitraryFloatRSqrtALTERA:
2252 case SPIRV::OpArbitraryFloatSubALTERA: {
2253 if (!
ST.canUseExtension(
2254 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_floating_point))
2256 "Floating point instructions can't be translated correctly without "
2257 "enabled SPV_ALTERA_arbitrary_precision_floating_point extension!",
2260 SPIRV::Extension::SPV_ALTERA_arbitrary_precision_floating_point);
2262 SPIRV::Capability::ArbitraryPrecisionFloatingPointALTERA);
2265 case SPIRV::OpSubgroupMatrixMultiplyAccumulateINTEL: {
2266 if (!
ST.canUseExtension(
2267 SPIRV::Extension::SPV_INTEL_subgroup_matrix_multiply_accumulate))
2269 "OpSubgroupMatrixMultiplyAccumulateINTEL instruction requires the "
2271 "extension: SPV_INTEL_subgroup_matrix_multiply_accumulate",
2274 SPIRV::Extension::SPV_INTEL_subgroup_matrix_multiply_accumulate);
2276 SPIRV::Capability::SubgroupMatrixMultiplyAccumulateINTEL);
2279 case SPIRV::OpBitwiseFunctionINTEL: {
2280 if (!
ST.canUseExtension(
2281 SPIRV::Extension::SPV_INTEL_ternary_bitwise_function))
2283 "OpBitwiseFunctionINTEL instruction requires the following SPIR-V "
2284 "extension: SPV_INTEL_ternary_bitwise_function",
2286 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_ternary_bitwise_function);
2287 Reqs.
addCapability(SPIRV::Capability::TernaryBitwiseFunctionINTEL);
2290 case SPIRV::OpCopyMemorySized: {
2295 case SPIRV::OpPredicatedLoadINTEL:
2296 case SPIRV::OpPredicatedStoreINTEL: {
2297 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_predicated_io))
2299 "OpPredicated[Load/Store]INTEL instructions require "
2300 "the following SPIR-V extension: SPV_INTEL_predicated_io",
2302 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_predicated_io);
2306 case SPIRV::OpFAddS:
2307 case SPIRV::OpFSubS:
2308 case SPIRV::OpFMulS:
2309 case SPIRV::OpFDivS:
2310 case SPIRV::OpFRemS:
2312 case SPIRV::OpFNegate:
2313 case SPIRV::OpFAddV:
2314 case SPIRV::OpFSubV:
2315 case SPIRV::OpFMulV:
2316 case SPIRV::OpFDivV:
2317 case SPIRV::OpFRemV:
2318 case SPIRV::OpFNegateV: {
2321 if (TypeDef->
getOpcode() == SPIRV::OpTypeVector)
2323 if (isBFloat16Type(TypeDef)) {
2324 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic))
2326 "Arithmetic instructions with bfloat16 arguments require the "
2327 "following SPIR-V extension: SPV_INTEL_bfloat16_arithmetic",
2329 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic);
2330 Reqs.
addCapability(SPIRV::Capability::BFloat16ArithmeticINTEL);
2334 case SPIRV::OpOrdered:
2335 case SPIRV::OpUnordered:
2336 case SPIRV::OpFOrdEqual:
2337 case SPIRV::OpFOrdNotEqual:
2338 case SPIRV::OpFOrdLessThan:
2339 case SPIRV::OpFOrdLessThanEqual:
2340 case SPIRV::OpFOrdGreaterThan:
2341 case SPIRV::OpFOrdGreaterThanEqual:
2342 case SPIRV::OpFUnordEqual:
2343 case SPIRV::OpFUnordNotEqual:
2344 case SPIRV::OpFUnordLessThan:
2345 case SPIRV::OpFUnordLessThanEqual:
2346 case SPIRV::OpFUnordGreaterThan:
2347 case SPIRV::OpFUnordGreaterThanEqual: {
2351 if (TypeDef->
getOpcode() == SPIRV::OpTypeVector)
2353 if (isBFloat16Type(TypeDef)) {
2354 if (!
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic))
2356 "Relational instructions with bfloat16 arguments require the "
2357 "following SPIR-V extension: SPV_INTEL_bfloat16_arithmetic",
2359 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_bfloat16_arithmetic);
2360 Reqs.
addCapability(SPIRV::Capability::BFloat16ArithmeticINTEL);
2364 case SPIRV::OpDPdxCoarse:
2365 case SPIRV::OpDPdyCoarse:
2366 case SPIRV::OpDPdxFine:
2367 case SPIRV::OpDPdyFine: {
2371 case SPIRV::OpLoopControlINTEL: {
2372 Reqs.
addExtension(SPIRV::Extension::SPV_INTEL_unstructured_loop_controls);
2373 Reqs.
addCapability(SPIRV::Capability::UnstructuredLoopControlsINTEL);
2385 SPIRV::Capability::Shader);
2397 addInstrRequirements(
MI, MAI, ST);
2400 auto Node = M.getNamedMetadata(
"spirv.ExecutionMode");
2402 bool RequireFloatControls =
false, RequireIntelFloatControls2 =
false,
2403 RequireKHRFloatControls2 =
false,
2405 bool HasIntelFloatControls2 =
2406 ST.canUseExtension(SPIRV::Extension::SPV_INTEL_float_controls2);
2407 bool HasKHRFloatControls2 =
2408 ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2);
2409 for (
unsigned i = 0; i <
Node->getNumOperands(); i++) {
2415 auto EM =
Const->getZExtValue();
2419 case SPIRV::ExecutionMode::DenormPreserve:
2420 case SPIRV::ExecutionMode::DenormFlushToZero:
2421 case SPIRV::ExecutionMode::RoundingModeRTE:
2422 case SPIRV::ExecutionMode::RoundingModeRTZ:
2423 RequireFloatControls = VerLower14;
2425 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2427 case SPIRV::ExecutionMode::RoundingModeRTPINTEL:
2428 case SPIRV::ExecutionMode::RoundingModeRTNINTEL:
2429 case SPIRV::ExecutionMode::FloatingPointModeALTINTEL:
2430 case SPIRV::ExecutionMode::FloatingPointModeIEEEINTEL:
2431 if (HasIntelFloatControls2) {
2432 RequireIntelFloatControls2 =
true;
2434 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2437 case SPIRV::ExecutionMode::FPFastMathDefault: {
2438 if (HasKHRFloatControls2) {
2439 RequireKHRFloatControls2 =
true;
2441 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2445 case SPIRV::ExecutionMode::ContractionOff:
2446 case SPIRV::ExecutionMode::SignedZeroInfNanPreserve:
2447 if (HasKHRFloatControls2) {
2448 RequireKHRFloatControls2 =
true;
2450 SPIRV::OperandCategory::ExecutionModeOperand,
2451 SPIRV::ExecutionMode::FPFastMathDefault, ST);
2454 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2459 SPIRV::OperandCategory::ExecutionModeOperand, EM, ST);
2464 if (RequireFloatControls &&
2465 ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls))
2467 if (RequireIntelFloatControls2)
2469 if (RequireKHRFloatControls2)
2473 if (
F.isDeclaration())
2475 if (
F.getMetadata(
"reqd_work_group_size"))
2477 SPIRV::OperandCategory::ExecutionModeOperand,
2478 SPIRV::ExecutionMode::LocalSize, ST);
2479 if (
F.getFnAttribute(
"hlsl.numthreads").isValid()) {
2481 SPIRV::OperandCategory::ExecutionModeOperand,
2482 SPIRV::ExecutionMode::LocalSize, ST);
2484 if (
F.getFnAttribute(
"enable-maximal-reconvergence").getValueAsBool()) {
2487 if (
F.getMetadata(
"work_group_size_hint"))
2489 SPIRV::OperandCategory::ExecutionModeOperand,
2490 SPIRV::ExecutionMode::LocalSizeHint, ST);
2491 if (
F.getMetadata(
"intel_reqd_sub_group_size"))
2493 SPIRV::OperandCategory::ExecutionModeOperand,
2494 SPIRV::ExecutionMode::SubgroupSize, ST);
2495 if (
F.getMetadata(
"max_work_group_size"))
2497 SPIRV::OperandCategory::ExecutionModeOperand,
2498 SPIRV::ExecutionMode::MaxWorkgroupSizeINTEL, ST);
2499 if (
F.getMetadata(
"vec_type_hint"))
2501 SPIRV::OperandCategory::ExecutionModeOperand,
2502 SPIRV::ExecutionMode::VecTypeHint, ST);
2504 if (
F.hasOptNone()) {
2505 if (
ST.canUseExtension(SPIRV::Extension::SPV_INTEL_optnone)) {
2508 }
else if (
ST.canUseExtension(SPIRV::Extension::SPV_EXT_optnone)) {
2518 unsigned Flags = SPIRV::FPFastMathMode::None;
2519 bool CanUseKHRFloatControls2 =
2520 ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2);
2522 Flags |= SPIRV::FPFastMathMode::NotNaN;
2524 Flags |= SPIRV::FPFastMathMode::NotInf;
2526 Flags |= SPIRV::FPFastMathMode::NSZ;
2528 Flags |= SPIRV::FPFastMathMode::AllowRecip;
2530 Flags |= SPIRV::FPFastMathMode::AllowContract;
2532 if (CanUseKHRFloatControls2)
2540 Flags |= SPIRV::FPFastMathMode::NotNaN | SPIRV::FPFastMathMode::NotInf |
2541 SPIRV::FPFastMathMode::NSZ | SPIRV::FPFastMathMode::AllowRecip |
2542 SPIRV::FPFastMathMode::AllowTransform |
2543 SPIRV::FPFastMathMode::AllowReassoc |
2544 SPIRV::FPFastMathMode::AllowContract;
2546 Flags |= SPIRV::FPFastMathMode::Fast;
2549 if (CanUseKHRFloatControls2) {
2551 assert(!(Flags & SPIRV::FPFastMathMode::Fast) &&
2552 "SPIRV::FPFastMathMode::Fast is deprecated and should not be used "
2557 assert((!(Flags & SPIRV::FPFastMathMode::AllowTransform) ||
2558 ((Flags & SPIRV::FPFastMathMode::AllowReassoc &&
2559 Flags & SPIRV::FPFastMathMode::AllowContract))) &&
2560 "SPIRV::FPFastMathMode::AllowTransform requires AllowReassoc and "
2561 "AllowContract flags to be enabled as well.");
2572 return ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2);
2575static void handleMIFlagDecoration(
2580 getSymbolicOperandRequirements(SPIRV::OperandCategory::DecorationOperand,
2581 SPIRV::Decoration::NoSignedWrap, ST, Reqs)
2584 SPIRV::Decoration::NoSignedWrap, {});
2587 getSymbolicOperandRequirements(SPIRV::OperandCategory::DecorationOperand,
2588 SPIRV::Decoration::NoUnsignedWrap, ST,
2592 SPIRV::Decoration::NoUnsignedWrap, {});
2594 if (!
TII.canUseFastMathFlags(
2595 I,
ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2)))
2598 unsigned FMFlags = getFastMathFlags(
I, ST);
2599 if (FMFlags == SPIRV::FPFastMathMode::None) {
2602 if (FPFastMathDefaultInfoVec.
empty())
2618 assert(
I.getNumOperands() >= 3 &&
"Expected at least 3 operands");
2619 Register ResReg =
I.getOpcode() == SPIRV::OpExtInst
2620 ?
I.getOperand(1).getReg()
2621 :
I.getOperand(2).getReg();
2629 if (Ty == Elem.Ty) {
2630 FMFlags = Elem.FastMathFlags;
2631 Emit = Elem.ContractionOff || Elem.SignedZeroInfNanPreserve ||
2632 Elem.FPFastMathDefault;
2637 if (FMFlags == SPIRV::FPFastMathMode::None && !Emit)
2640 if (isFastMathModeAvailable(ST)) {
2641 Register DstReg =
I.getOperand(0).getReg();
2657 for (
auto &
MBB : *MF)
2658 for (
auto &
MI :
MBB)
2659 handleMIFlagDecoration(
MI, ST,
TII, MAI.
Reqs, GR,
2672 for (
auto &
MBB : *MF) {
2673 if (!
MBB.hasName() ||
MBB.empty())
2677 MRI.setRegClass(
Reg, &SPIRV::IDRegClass);
2692 for (
auto &
MBB : *MF) {
2694 MI.setDesc(
TII.get(SPIRV::OpPhi));
2697 MI.insert(
MI.operands_begin() + 1,
2698 {MachineOperand::CreateReg(ResTypeReg, false)});
2717 SPIRV::FPFastMathMode::None);
2719 SPIRV::FPFastMathMode::None);
2721 SPIRV::FPFastMathMode::None);
2728 size_t BitWidth = Ty->getScalarSizeInBits();
2732 assert(Index >= 0 && Index < 3 &&
2733 "Expected FPFastMathDefaultInfo for half, float, or double");
2734 assert(FPFastMathDefaultInfoVec.
size() == 3 &&
2735 "Expected FPFastMathDefaultInfoVec to have exactly 3 elements");
2736 return FPFastMathDefaultInfoVec[Index];
2739static void collectFPFastMathDefaults(
const Module &M,
2742 if (!
ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2))
2751 auto Node = M.getNamedMetadata(
"spirv.ExecutionMode");
2755 for (
unsigned i = 0; i <
Node->getNumOperands(); i++) {
2764 if (EM == SPIRV::ExecutionMode::FPFastMathDefault) {
2766 "Expected 4 operands for FPFastMathDefault");
2777 Info.FastMathFlags = Flags;
2778 Info.FPFastMathDefault =
true;
2779 }
else if (EM == SPIRV::ExecutionMode::ContractionOff) {
2781 "Expected no operands for ContractionOff");
2788 Info.ContractionOff =
true;
2790 }
else if (EM == SPIRV::ExecutionMode::SignedZeroInfNanPreserve) {
2792 "Expected 1 operand for SignedZeroInfNanPreserve");
2793 unsigned TargetWidth =
2802 assert(Index >= 0 && Index < 3 &&
2803 "Expected FPFastMathDefaultInfo for half, float, or double");
2804 assert(FPFastMathDefaultInfoVec.
size() == 3 &&
2805 "Expected FPFastMathDefaultInfoVec to have exactly 3 elements");
2806 FPFastMathDefaultInfoVec[Index].SignedZeroInfNanPreserve =
true;