[llvm] [SPIR-V] Emit SPIR-V generator magic number and version (PR #87951)
via llvm-commits
llvm-commits at lists.llvm.org
Sun Apr 7 16:20:27 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-mc
Author: Michal Paszkowski (michalpaszkowski)
<details>
<summary>Changes</summary>
This patch:
- Adds SPIR-V backend's registered generator magic number to the emitted binary. The magic number consists of the generator ID (43) and LLVM major version.
- Adds SPIR-V version to the binary.
- Allows reading the expected (maximum supported) SPIR-V version from the target triple.
- Uses VersionTuple for representing versions throughout the backend's codebase.
- Registers v1.6 for spirv32 and spirv64 triple.
See more: https://github.com/KhronosGroup/SPIRV-Headers/commit/7d500c
---
Patch is 43.88 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/87951.diff
21 Files Affected:
- (modified) llvm/lib/MC/SPIRVObjectWriter.cpp (+3-3)
- (modified) llvm/lib/Target/SPIRV/SPIRV.td (-13)
- (modified) llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp (+11-9)
- (modified) llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp (+28-7)
- (modified) llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h (+6-1)
- (modified) llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp (+13-4)
- (modified) llvm/lib/Target/SPIRV/SPIRVISelLowering.h (+4)
- (modified) llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp (+26-22)
- (modified) llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.h (+9-11)
- (modified) llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp (+56-167)
- (modified) llvm/lib/Target/SPIRV/SPIRVSubtarget.cpp (+32-11)
- (modified) llvm/lib/Target/SPIRV/SPIRVSubtarget.h (+6-6)
- (modified) llvm/lib/TargetParser/Triple.cpp (+8-6)
- (modified) llvm/test/CodeGen/SPIRV/ComparePointers.ll (+2-2)
- (modified) llvm/test/CodeGen/SPIRV/branching/OpSwitchUnreachable.ll (+3-2)
- (added) llvm/test/CodeGen/SPIRV/branching/switch-range-check.ll (+73)
- (modified) llvm/test/CodeGen/SPIRV/empty-opencl32.ll (-2)
- (modified) llvm/test/CodeGen/SPIRV/exec_mode_float_control_khr.ll (+2-2)
- (added) llvm/test/CodeGen/SPIRV/physical-layout/generator-magic-number.ll (+4)
- (added) llvm/test/CodeGen/SPIRV/physical-layout/spirv-version.ll (+16)
- (modified) llvm/test/CodeGen/SPIRV/transcoding/AtomicCompareExchangeExplicit_cl20.ll (+2-2)
``````````diff
diff --git a/llvm/lib/MC/SPIRVObjectWriter.cpp b/llvm/lib/MC/SPIRVObjectWriter.cpp
index d72d6e07f2e6fd..5d85c5de4e4e10 100644
--- a/llvm/lib/MC/SPIRVObjectWriter.cpp
+++ b/llvm/lib/MC/SPIRVObjectWriter.cpp
@@ -43,10 +43,10 @@ class SPIRVObjectWriter : public MCObjectWriter {
void SPIRVObjectWriter::writeHeader(const MCAssembler &Asm) {
constexpr uint32_t MagicNumber = 0x07230203;
- constexpr uint32_t GeneratorMagicNumber = 0;
+ constexpr uint32_t GeneratorID = 43;
+ constexpr uint32_t GeneratorMagicNumber =
+ (GeneratorID << 16) | (LLVM_VERSION_MAJOR);
constexpr uint32_t Schema = 0;
-
- // Construct SPIR-V version and Bound
const MCAssembler::VersionInfoType &VIT = Asm.getVersionInfo();
uint32_t VersionNumber = 0 | (VIT.Major << 16) | (VIT.Minor << 8);
uint32_t Bound = VIT.Update;
diff --git a/llvm/lib/Target/SPIRV/SPIRV.td b/llvm/lib/Target/SPIRV/SPIRV.td
index beb55d05307ca9..108c7e6d3861f0 100644
--- a/llvm/lib/Target/SPIRV/SPIRV.td
+++ b/llvm/lib/Target/SPIRV/SPIRV.td
@@ -20,19 +20,6 @@ class Proc<string Name, list<SubtargetFeature> Features>
def : Proc<"generic", []>;
-def SPIRV10 : SubtargetFeature<"spirv1.0", "SPIRVVersion", "10",
- "Use SPIR-V version 1.0">;
-def SPIRV11 : SubtargetFeature<"spirv1.1", "SPIRVVersion", "11",
- "Use SPIR-V version 1.1">;
-def SPIRV12 : SubtargetFeature<"spirv1.2", "SPIRVVersion", "12",
- "Use SPIR-V version 1.2">;
-def SPIRV13 : SubtargetFeature<"spirv1.3", "SPIRVVersion", "13",
- "Use SPIR-V version 1.3">;
-def SPIRV14 : SubtargetFeature<"spirv1.4", "SPIRVVersion", "14",
- "Use SPIR-V version 1.4">;
-def SPIRV15 : SubtargetFeature<"spirv1.5", "SPIRVVersion", "15",
- "Use SPIR-V version 1.5">;
-
def SPIRVInstPrinter : AsmWriter {
string AsmWriterClassName = "InstPrinter";
bit isMCAsmWriter = 1;
diff --git a/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp b/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp
index 4eee8062f28248..2ebe5bdc47715b 100644
--- a/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp
@@ -43,6 +43,8 @@ using namespace llvm;
namespace {
class SPIRVAsmPrinter : public AsmPrinter {
+ unsigned NLabels = 0;
+
public:
explicit SPIRVAsmPrinter(TargetMachine &TM,
std::unique_ptr<MCStreamer> Streamer)
@@ -106,13 +108,12 @@ void SPIRVAsmPrinter::emitEndOfAsmFile(Module &M) {
}
ST = static_cast<const SPIRVTargetMachine &>(TM).getSubtargetImpl();
- uint32_t DecSPIRVVersion = ST->getSPIRVVersion();
- uint32_t Major = DecSPIRVVersion / 10;
- uint32_t Minor = DecSPIRVVersion - Major * 10;
- // TODO: calculate Bound more carefully from maximum used register number,
- // accounting for generated OpLabels and other related instructions if
- // needed.
- unsigned Bound = 2 * (ST->getBound() + 1);
+ VersionTuple SPIRVVersion = ST->getSPIRVVersion();
+ uint32_t Major = SPIRVVersion.getMajor();
+ uint32_t Minor = SPIRVVersion.getMinor().value_or(0);
+ // Bound is an approximation that accounts for the maximum used register
+ // number and number of generated OpLabels
+ unsigned Bound = 2 * (ST->getBound() + 1) + NLabels;
bool FlagToRestore = OutStreamer->getUseAssemblerInfoForParsing();
OutStreamer->setUseAssemblerInfoForParsing(true);
if (MCAssembler *Asm = OutStreamer->getAssemblerPtr())
@@ -158,6 +159,7 @@ void SPIRVAsmPrinter::emitOpLabel(const MachineBasicBlock &MBB) {
LabelInst.setOpcode(SPIRV::OpLabel);
LabelInst.addOperand(MCOperand::createReg(MAI->getOrCreateMBBRegister(MBB)));
outputMCInst(LabelInst);
+ ++NLabels;
}
void SPIRVAsmPrinter::emitBasicBlockStart(const MachineBasicBlock &MBB) {
@@ -319,8 +321,8 @@ void SPIRVAsmPrinter::outputEntryPoints() {
// the Input and Output storage classes. Starting with version 1.4,
// the interface's storage classes are all storage classes used in
// declaring all global variables referenced by the entry point call tree.
- if (ST->getSPIRVVersion() >= 14 || SC == SPIRV::StorageClass::Input ||
- SC == SPIRV::StorageClass::Output) {
+ if (ST->isAtLeastSPIRVVer(VersionTuple(1, 4)) ||
+ SC == SPIRV::StorageClass::Input || SC == SPIRV::StorageClass::Output) {
MachineFunction *MF = MI->getMF();
Register Reg = MAI->getRegisterAlias(MF, MI->getOperand(0).getReg());
InterfaceIDs.insert(Reg);
diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
index b341fcb41d0312..e8ce5a35b457d5 100644
--- a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
@@ -460,15 +460,36 @@ void SPIRVEmitIntrinsics::preprocessCompositeConstants(IRBuilder<> &B) {
}
Instruction *SPIRVEmitIntrinsics::visitSwitchInst(SwitchInst &I) {
- IRBuilder<> B(I.getParent());
+ BasicBlock *ParentBB = I.getParent();
+ IRBuilder<> B(ParentBB);
+ B.SetInsertPoint(&I);
SmallVector<Value *, 4> Args;
- for (auto &Op : I.operands())
- if (Op.get()->getType()->isSized())
+ SmallVector<BasicBlock *> BBCases;
+ for (auto &Op : I.operands()) {
+ if (Op.get()->getType()->isSized()) {
Args.push_back(Op);
- B.SetInsertPoint(&I);
- B.CreateIntrinsic(Intrinsic::spv_switch, {I.getOperand(0)->getType()},
- {Args});
- return &I;
+ } else if (BasicBlock *BB = dyn_cast<BasicBlock>(Op.get())) {
+ BBCases.push_back(BB);
+ Args.push_back(BlockAddress::get(BB->getParent(), BB));
+ } else {
+ report_fatal_error("Unexpected switch operand");
+ }
+ }
+ CallInst *NewI = B.CreateIntrinsic(Intrinsic::spv_switch,
+ {I.getOperand(0)->getType()}, {Args});
+ // remove switch to avoid its unneeded and undesirable unwrap into branches
+ // and conditions
+ I.replaceAllUsesWith(NewI);
+ I.eraseFromParent();
+ // insert artificial and temporary instruction to preserve valid CFG,
+ // it will be removed after IR translation pass
+ B.SetInsertPoint(ParentBB);
+ IndirectBrInst *BrI = B.CreateIndirectBr(
+ Constant::getNullValue(PointerType::getUnqual(ParentBB->getContext())),
+ BBCases.size());
+ for (BasicBlock *BBCase : BBCases)
+ BrI->addDestination(BBCase);
+ return BrI;
}
Instruction *SPIRVEmitIntrinsics::visitGetElementPtrInst(GetElementPtrInst &I) {
diff --git a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h
index ac799374adce8c..37f575e884ef48 100644
--- a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h
+++ b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h
@@ -284,7 +284,12 @@ class SPIRVGlobalRegistry {
// Return the VReg holding the result of the given OpTypeXXX instruction.
Register getSPIRVTypeID(const SPIRVType *SpirvType) const;
- void setCurrentFunc(MachineFunction &MF) { CurMF = &MF; }
+ // Return previous value of the current machine function
+ MachineFunction *setCurrentFunc(MachineFunction &MF) {
+ MachineFunction *Ret = CurMF;
+ CurMF = &MF;
+ return Ret;
+ }
// Whether the given VReg has an OpTypeXXX instruction mapped to it with the
// given opcode (e.g. OpTypeFloat).
diff --git a/llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp b/llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp
index d450078d793fb7..8db54c74f23690 100644
--- a/llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp
@@ -160,12 +160,15 @@ void validateFunCallMachineDef(const SPIRVSubtarget &STI,
: nullptr;
if (DefElemType) {
const Type *DefElemTy = GR.getTypeForSPIRVType(DefElemType);
- // Switch GR context to the call site instead of the (default) definition
- // side
- GR.setCurrentFunc(*FunCall.getParent()->getParent());
+ // validatePtrTypes() works in the context if the call site
+ // When we process historical records about forward calls
+ // we need to switch context to the (forward) call site and
+ // then restore it back to the current machine function.
+ MachineFunction *CurMF =
+ GR.setCurrentFunc(*FunCall.getParent()->getParent());
validatePtrTypes(STI, CallMRI, GR, FunCall, OpIdx, DefElemType,
DefElemTy);
- GR.setCurrentFunc(*FunDef->getParent()->getParent());
+ GR.setCurrentFunc(*CurMF);
}
}
}
@@ -215,6 +218,11 @@ void validateAccessChain(const SPIRVSubtarget &STI, MachineRegisterInfo *MRI,
// TODO: the logic of inserting additional bitcast's is to be moved
// to pre-IRTranslation passes eventually
void SPIRVTargetLowering::finalizeLowering(MachineFunction &MF) const {
+ // finalizeLowering() is called twice (see GlobalISel/InstructionSelect.cpp)
+ // We'd like to avoid the needless second processing pass.
+ if (ProcessedMF.find(&MF) != ProcessedMF.end())
+ return;
+
MachineRegisterInfo *MRI = &MF.getRegInfo();
SPIRVGlobalRegistry &GR = *STI.getSPIRVGlobalRegistry();
GR.setCurrentFunc(MF);
@@ -302,5 +310,6 @@ void SPIRVTargetLowering::finalizeLowering(MachineFunction &MF) const {
}
}
}
+ ProcessedMF.insert(&MF);
TargetLowering::finalizeLowering(MF);
}
diff --git a/llvm/lib/Target/SPIRV/SPIRVISelLowering.h b/llvm/lib/Target/SPIRV/SPIRVISelLowering.h
index b01571bfc1eeb5..8c1de7d97d1a3c 100644
--- a/llvm/lib/Target/SPIRV/SPIRVISelLowering.h
+++ b/llvm/lib/Target/SPIRV/SPIRVISelLowering.h
@@ -16,6 +16,7 @@
#include "SPIRVGlobalRegistry.h"
#include "llvm/CodeGen/TargetLowering.h"
+#include <set>
namespace llvm {
class SPIRVSubtarget;
@@ -23,6 +24,9 @@ class SPIRVSubtarget;
class SPIRVTargetLowering : public TargetLowering {
const SPIRVSubtarget &STI;
+ // Record of already processed machine functions
+ mutable std::set<const MachineFunction *> ProcessedMF;
+
public:
explicit SPIRVTargetLowering(const TargetMachine &TM,
const SPIRVSubtarget &ST)
diff --git a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
index 40c3e5f9c6bdab..d6c1b81b56048a 100644
--- a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
@@ -76,18 +76,21 @@ getSymbolicOperandRequirements(SPIRV::OperandCategory::OperandCategory Category,
SPIRV::RequirementHandler &Reqs) {
static AvoidCapabilitiesSet
AvoidCaps; // contains capabilities to avoid if there is another option
- unsigned ReqMinVer = getSymbolicOperandMinVersion(Category, i);
- unsigned ReqMaxVer = getSymbolicOperandMaxVersion(Category, i);
- unsigned TargetVer = ST.getSPIRVVersion();
- bool MinVerOK = !ReqMinVer || !TargetVer || TargetVer >= ReqMinVer;
- bool MaxVerOK = !ReqMaxVer || !TargetVer || TargetVer <= ReqMaxVer;
+
+ unsigned ReqMinVerDec = getSymbolicOperandMinVersion(Category, i);
+ VersionTuple ReqMinVer = VersionTuple(ReqMinVerDec / 10, ReqMinVerDec % 10);
+ unsigned ReqMaxVerDec = getSymbolicOperandMaxVersion(Category, i);
+ VersionTuple ReqMaxVer = VersionTuple(ReqMaxVerDec / 10, ReqMaxVerDec % 10);
+ VersionTuple SPIRVVersion = ST.getSPIRVVersion();
+ bool MinVerOK = ReqMinVer.empty() || SPIRVVersion.empty() || SPIRVVersion >= ReqMinVer;
+ bool MaxVerOK = ReqMaxVer.empty() || SPIRVVersion.empty() || SPIRVVersion <= ReqMaxVer;
CapabilityList ReqCaps = getSymbolicOperandCapabilities(Category, i);
ExtensionList ReqExts = getSymbolicOperandExtensions(Category, i);
if (ReqCaps.empty()) {
if (ReqExts.empty()) {
if (MinVerOK && MaxVerOK)
return {true, {}, {}, ReqMinVer, ReqMaxVer};
- return {false, {}, {}, 0, 0};
+ return {false, {}, {}, VersionTuple(), VersionTuple()};
}
} else if (MinVerOK && MaxVerOK) {
if (ReqCaps.size() == 1) {
@@ -118,9 +121,9 @@ getSymbolicOperandRequirements(SPIRV::OperandCategory::OperandCategory Category,
if (llvm::all_of(ReqExts, [&ST](const SPIRV::Extension::Extension &Ext) {
return ST.canUseExtension(Ext);
})) {
- return {true, {}, ReqExts, 0, 0}; // TODO: add versions to extensions.
+ return {true, {}, ReqExts, VersionTuple(), VersionTuple()}; // TODO: add versions to extensions.
}
- return {false, {}, {}, 0, 0};
+ return {false, {}, {}, VersionTuple(), VersionTuple()};
}
void SPIRVModuleAnalysis::setBaseInfo(const Module &M) {
@@ -499,25 +502,25 @@ void SPIRV::RequirementHandler::addRequirements(
addExtensions(Req.Exts);
- if (Req.MinVer) {
- if (MaxVersion && Req.MinVer > MaxVersion) {
+ if (!Req.MinVer.empty()) {
+ if (!MaxVersion.empty() && Req.MinVer > MaxVersion) {
LLVM_DEBUG(dbgs() << "Conflicting version requirements: >= " << Req.MinVer
<< " and <= " << MaxVersion << "\n");
report_fatal_error("Adding SPIR-V requirements that can't be satisfied.");
}
- if (MinVersion == 0 || Req.MinVer > MinVersion)
+ if (MinVersion.empty() || Req.MinVer > MinVersion)
MinVersion = Req.MinVer;
}
- if (Req.MaxVer) {
- if (MinVersion && Req.MaxVer < MinVersion) {
+ if (!Req.MaxVer.empty()) {
+ if (!MinVersion.empty() && Req.MaxVer < MinVersion) {
LLVM_DEBUG(dbgs() << "Conflicting version requirements: <= " << Req.MaxVer
<< " and >= " << MinVersion << "\n");
report_fatal_error("Adding SPIR-V requirements that can't be satisfied.");
}
- if (MaxVersion == 0 || Req.MaxVer < MaxVersion)
+ if (MaxVersion.empty() || Req.MaxVer < MaxVersion)
MaxVersion = Req.MaxVer;
}
}
@@ -528,7 +531,7 @@ void SPIRV::RequirementHandler::checkSatisfiable(
bool IsSatisfiable = true;
auto TargetVer = ST.getSPIRVVersion();
- if (MaxVersion && TargetVer && MaxVersion < TargetVer) {
+ if (!MaxVersion.empty() && !TargetVer.empty() && MaxVersion < TargetVer) {
LLVM_DEBUG(
dbgs() << "Target SPIR-V version too high for required features\n"
<< "Required max version: " << MaxVersion << " target version "
@@ -536,14 +539,14 @@ void SPIRV::RequirementHandler::checkSatisfiable(
IsSatisfiable = false;
}
- if (MinVersion && TargetVer && MinVersion > TargetVer) {
+ if (!MinVersion.empty() && !TargetVer.empty() && MinVersion > TargetVer) {
LLVM_DEBUG(dbgs() << "Target SPIR-V version too low for required features\n"
<< "Required min version: " << MinVersion
<< " target version " << TargetVer << "\n");
IsSatisfiable = false;
}
- if (MinVersion && MaxVersion && MinVersion > MaxVersion) {
+ if (!MinVersion.empty() && !MaxVersion.empty() && MinVersion > MaxVersion) {
LLVM_DEBUG(
dbgs()
<< "Version is too low for some features and too high for others.\n"
@@ -621,12 +624,12 @@ void RequirementHandler::initAvailableCapabilitiesForOpenCL(
addAvailableCaps({Capability::ImageBasic, Capability::LiteralSampler,
Capability::Image1D, Capability::SampledBuffer,
Capability::ImageBuffer});
- if (ST.isAtLeastOpenCLVer(20))
+ if (ST.isAtLeastOpenCLVer(VersionTuple(2, 0)))
addAvailableCaps({Capability::ImageReadWrite});
}
- if (ST.isAtLeastSPIRVVer(11) && ST.isAtLeastOpenCLVer(22))
+ if (ST.isAtLeastSPIRVVer(VersionTuple(1, 1)) && ST.isAtLeastOpenCLVer(VersionTuple(2, 2)))
addAvailableCaps({Capability::SubgroupDispatch, Capability::PipeStorage});
- if (ST.isAtLeastSPIRVVer(13))
+ if (ST.isAtLeastSPIRVVer(VersionTuple(1, 3)))
addAvailableCaps({Capability::GroupNonUniform,
Capability::GroupNonUniformVote,
Capability::GroupNonUniformArithmetic,
@@ -634,7 +637,7 @@ void RequirementHandler::initAvailableCapabilitiesForOpenCL(
Capability::GroupNonUniformClustered,
Capability::GroupNonUniformShuffle,
Capability::GroupNonUniformShuffleRelative});
- if (ST.isAtLeastSPIRVVer(14))
+ if (ST.isAtLeastSPIRVVer(VersionTuple(1, 4)))
addAvailableCaps({Capability::DenormPreserve, Capability::DenormFlushToZero,
Capability::SignedZeroInfNanPreserve,
Capability::RoundingModeRTE,
@@ -1151,7 +1154,8 @@ static void collectReqs(const Module &M, SPIRV::ModuleAnalysisInfo &MAI,
auto Node = M.getNamedMetadata("spirv.ExecutionMode");
if (Node) {
// SPV_KHR_float_controls is not available until v1.4
- bool RequireFloatControls = false, VerLower14 = !ST.isAtLeastSPIRVVer(14);
+ bool RequireFloatControls = false,
+ VerLower14 = !ST.isAtLeastSPIRVVer(VersionTuple(1, 4));
for (unsigned i = 0; i < Node->getNumOperands(); i++) {
MDNode *MDN = cast<MDNode>(Node->getOperand(i));
const MDOperand &MDOp = MDN->getOperand(1);
diff --git a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.h b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.h
index 6e86eed30c5dc1..79226d6d93efb2 100644
--- a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.h
+++ b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.h
@@ -45,13 +45,13 @@ struct Requirements {
const bool IsSatisfiable;
const std::optional<Capability::Capability> Cap;
const ExtensionList Exts;
- const unsigned MinVer; // 0 if no min version is required.
- const unsigned MaxVer; // 0 if no max version is required.
+ const VersionTuple MinVer; // 0 if no min version is required.
+ const VersionTuple MaxVer; // 0 if no max version is required.
Requirements(bool IsSatisfiable = false,
std::optional<Capability::Capability> Cap = {},
- ExtensionList Exts = {}, unsigned MinVer = 0,
- unsigned MaxVer = 0)
+ ExtensionList Exts = {}, VersionTuple MinVer = VersionTuple(),
+ VersionTuple MaxVer = VersionTuple())
: IsSatisfiable(IsSatisfiable), Cap(Cap), Exts(Exts), MinVer(MinVer),
MaxVer(MaxVer) {}
Requirements(Capability::Capability Cap) : Requirements(true, {Cap}) {}
@@ -69,8 +69,8 @@ struct RequirementHandler {
DenseSet<unsigned> AvailableCaps;
SmallSet<Extension::Extension, 4> AllExtensions;
- unsigned MinVersion; // 0 if no min version is defined.
- unsigned MaxVersion; // 0 if no max version is defined.
+ VersionTuple MinVersion; // 0 if no min version is defined.
+ VersionTuple MaxVersion; // 0 if no max version is defined.
// Add capabilities to AllCaps, recursing through their implicitly declared
// capabilities too.
void recursiveAddCapabilities(const CapabilityList &ToPrune);
@@ -79,17 +79,15 @@ struct RequirementHandler {
void initAvailableCapabilitiesForVulkan(const SPIRVSubtarget &ST);
public:
- RequirementHandler() : MinVersion(0), MaxVersion(0) {}
+ RequirementHandler() {}
void clear() {
MinimalCaps.clear();
AllCaps.clear();
AvailableCaps.clear();
AllExtensions.clear();
- MinVersion = 0;
- MaxVersion = 0;
+ MinVersion = VersionTuple();
+ MaxVersion = VersionTuple();
}
- unsigned getMinVersion() const { return MinVersion; }
- unsigned getMaxVersion() const { return MaxVersion; }
const CapabilityList &getMinimalCapabilities() const { return MinimalCaps; }
const SmallSet<Extension::Extension, 4> &getExtensions() const {
return AllExtensions;
diff --git a/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp b/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp
index b133f0ae85de20..7e155a36aadbc4 100644
--- a/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp
@@ -438,186 +438,75 @@ static void processInstrsWithTypeFolding(MachineFunction &MF,
}
}
+// Find basic blocks of the switch and replace registers in spv_switch() by its
+// MBB equivalent.
static void processSwitches(MachineFunction &MF, SPIRVGlobalRegistry *GR,
MachineIRBuilder MIB) {
- // Before IRTranslator pass, calls to spv_switch intrinsic are inserted before
- // each switch instruction. IRTranslator lowers switches to G_ICMP + G_BRCOND
- // + G_BR triples. A switch with two cases may be transformed to this MIR
- // sequence:
- //
- // intrinsic(@llvm.spv.switch), %CmpReg, %Const0, %Const1
- // %Dst0 = G_ICMP intpred(eq), %CmpReg, %Const0
- // G_BRCOND %Dst0, %bb.2
- // G_BR %bb.5
- // bb.5.entry:
- // %Dst1 = G_ICMP intpred(eq), %CmpReg, %Const1
- // G_BRCOND %Dst1, %bb.3
- // G_BR %bb.4
- // bb.2....
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/87951
More information about the llvm-commits
mailing list