Skip to content

Commit eef5045

Browse files
committed
Use entry points to help determine the env.
1 parent f87ac68 commit eef5045

File tree

4 files changed

+69
-30
lines changed

4 files changed

+69
-30
lines changed

llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -272,14 +272,37 @@ getExecutionModel(const SPIRVSubtarget &STI, const Function &F) {
272272
// precise enough. For now, we'll rely instead on `isLogicalSPIRV()`, but this
273273
// should be changed when `isOpenCLEnv()` and `isVulkanEnv()` cannot be true
274274
// at the same time.
275-
if (!STI.isLogicalSPIRV())
275+
if (STI.isOpenCLEnv())
276276
return SPIRV::ExecutionModel::Kernel;
277277

278+
if (STI.isVulkanEnv()) {
279+
auto attribute = F.getFnAttribute("hlsl.shader");
280+
if (!attribute.isValid()) {
281+
report_fatal_error(
282+
"This entry point lacks mandatory hlsl.shader attribute.");
283+
}
284+
285+
const auto value = attribute.getValueAsString();
286+
if (value == "compute")
287+
return SPIRV::ExecutionModel::GLCompute;
288+
289+
report_fatal_error(
290+
"This HLSL entry point is not supported by this backend.");
291+
}
292+
293+
assert(STI.getEnv() == Unknown);
294+
// Can we rely on "hlsl.shader" attribute? Is it mandatory for Vulkan env? If
295+
// so, we can set Env to Vulkan whenever we find it, and to OpenCL otherwise.
296+
297+
// We will now change the Env based on the attribute, so we need to strip
298+
// `const` out of the ref to STI.
299+
SPIRVSubtarget *NonConstSTI = const_cast<SPIRVSubtarget *>(&STI);
278300
auto attribute = F.getFnAttribute("hlsl.shader");
279301
if (!attribute.isValid()) {
280-
report_fatal_error(
281-
"This entry point lacks mandatory hlsl.shader attribute.");
302+
NonConstSTI->setEnv(SPIRVSubtarget::OpenCL);
303+
return SPIRV::ExecutionModel::Kernel;
282304
}
305+
NonConstSTI->setEnv(SPIRVSubtarget::Vulkan);
283306

284307
const auto value = attribute.getValueAsString();
285308
if (value == "compute")
@@ -444,6 +467,11 @@ bool SPIRVCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
444467

445468
// Handle entry points and function linkage.
446469
if (isEntryPoint(F)) {
470+
// EntryPoints can help us to determine the environment we're working on.
471+
// Therefore, we need a non-const pointer to SPIRVSubtarget to update the
472+
// environment if we need to.
473+
const SPIRVSubtarget *ST =
474+
static_cast<const SPIRVSubtarget *>(&MIRBuilder.getMF().getSubtarget());
447475
auto MIB = MIRBuilder.buildInstr(SPIRV::OpEntryPoint)
448476
.addImm(static_cast<uint32_t>(getExecutionModel(*ST, F)))
449477
.addUse(FuncVReg);

llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -151,11 +151,11 @@ void SPIRVModuleAnalysis::setBaseInfo(const Module &M) {
151151
// TODO: Add support for VulkanMemoryModel.
152152
// FIXME: At the moment, there's a possibility that both `isOpenCLEnv()` and
153153
// `isVulkanEnv()` return true. This is because the Triple is not always
154-
// precise enough. For now, we'll rely instead on `isLogicalSPIRV()`, but this
155-
// should be changed when `isOpenCLEnv()` and `isVulkanEnv()` cannot be true
156-
// at the same time.
154+
// precise enough. For now, we'll rely instead on `isLogicalSPIRV()`, but
155+
// this should be changed when `isOpenCLEnv()` and `isVulkanEnv()` cannot be
156+
// true at the same time.
157157
MAI.Mem = !ST->isLogicalSPIRV() ? SPIRV::MemoryModel::OpenCL
158-
: SPIRV::MemoryModel::GLSL450;
158+
: SPIRV::MemoryModel::GLSL450;
159159
if (MAI.Mem == SPIRV::MemoryModel::OpenCL) {
160160
unsigned PtrSize = ST->getPointerSize();
161161
MAI.Addr = PtrSize == 32 ? SPIRV::AddressingModel::Physical32
@@ -1808,7 +1808,11 @@ void addInstrRequirements(const MachineInstr &MI,
18081808
// not allowed to produce
18091809
// StorageImageReadWithoutFormat/StorageImageWriteWithoutFormat, see
18101810
// https://github.com/KhronosGroup/SPIRV-Headers/issues/487
1811-
if (isImageTypeWithUnknownFormat(TypeDef) && !ST.isOpenCLEnv())
1811+
1812+
// FIXME: For now, `isOpenCLEnv()` is not precise enough. Instead, we're
1813+
// using `isLogicalSPIRV()`, but we should change this when `isOpenCLEnv()`
1814+
// is precise enough.
1815+
if (isImageTypeWithUnknownFormat(TypeDef) && ST.isLogicalSPIRV())
18121816
Reqs.addCapability(SPIRV::Capability::StorageImageReadWithoutFormat);
18131817
break;
18141818
}
@@ -1821,7 +1825,11 @@ void addInstrRequirements(const MachineInstr &MI,
18211825
// not allowed to produce
18221826
// StorageImageReadWithoutFormat/StorageImageWriteWithoutFormat, see
18231827
// https://github.com/KhronosGroup/SPIRV-Headers/issues/487
1824-
if (isImageTypeWithUnknownFormat(TypeDef) && !ST.isOpenCLEnv())
1828+
1829+
// FIXME: For now, `isOpenCLEnv()` is not precise enough. Instead, we're
1830+
// using `isLogicalSPIRV()`, but we should change this when `isOpenCLEnv()`
1831+
// is precise enough.
1832+
if (isImageTypeWithUnknownFormat(TypeDef) && ST.isLogicalSPIRV())
18251833
Reqs.addCapability(SPIRV::Capability::StorageImageWriteWithoutFormat);
18261834
break;
18271835
}

llvm/lib/Target/SPIRV/SPIRVSubtarget.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,14 @@ SPIRVSubtarget::SPIRVSubtarget(const Triple &TT, const std::string &CPU,
8383
}
8484
OpenCLVersion = VersionTuple(2, 2);
8585

86+
// Set the environment based on the target triple.
87+
if (TargetTriple.getOS() == Triple::Vulkan)
88+
Env = Vulkan;
89+
else if (TargetTriple.getEnvironment() == Triple::OpenCL)
90+
Env = OpenCL;
91+
else
92+
Env = Unknown;
93+
8694
// The order of initialization is important.
8795
initAvailableExtensions(Extensions);
8896
initAvailableExtInstSets();

llvm/lib/Target/SPIRV/SPIRVSubtarget.h

Lines changed: 16 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,10 @@ class StringRef;
3636
class SPIRVTargetMachine;
3737

3838
class SPIRVSubtarget : public SPIRVGenSubtargetInfo {
39+
public:
3940
// Enum for the SPIR-V environment: OpenCL, Vulkan or Unkwnown.
4041
enum SPIRVEnvType { OpenCL, Vulkan, Unknown };
42+
4143
private:
4244
const unsigned PointerSize;
4345
VersionTuple SPIRVVersion;
@@ -81,28 +83,21 @@ class SPIRVSubtarget : public SPIRVGenSubtargetInfo {
8183
unsigned getPointerSize() const { return PointerSize; }
8284
unsigned getBound() const { return GR->getBound(); }
8385
bool canDirectlyComparePointers() const;
84-
SPIRVEnvType getEnv() const {
85-
if (TargetTriple.getOS() == Triple::Vulkan)
86-
return Vulkan;
87-
if (TargetTriple.getEnvironment() == Triple::OpenCL)
88-
return OpenCL;
89-
return Unknown;
90-
}
91-
// FIXME: For now, we rely only on the triple to determine the environment.
92-
// However, a lot of frontends emit unknown OS or environment, which makes it
93-
// difficult to determine the environment. We should consider adding other
94-
// methods. For now, we will return true for both OpenCL and Unknown env.
95-
bool isOpenCLEnv() const {
96-
return getEnv() == OpenCL || getEnv() == Unknown;
97-
}
98-
// FIXME: For now, we rely only on the triple to determine the environment.
99-
// However, a lot of frontends emit unknown OS or environment, which makes it
100-
// difficult to determine the environment. We should consider adding other
101-
// methods. For now, we will return true for both Vulkan and Unknown env.
102-
bool isVulkanEnv() const {
103-
return getEnv() == Vulkan || getEnv() == Unknown;
86+
void setEnv(SPIRVEnvType E) {
87+
assert(E != Unknown && "Unknown environment is not allowed");
88+
assert(Env == Unknown && "Environment is already set");
89+
90+
Env = E;
10491
}
105-
bool isLogicalSPIRV() const { return TargetTriple.getArch() == Triple::spirv; }
92+
SPIRVEnvType getEnv() const { return Env; }
93+
bool isOpenCLEnv() const { return getEnv() == OpenCL; }
94+
bool isVulkanEnv() const { return getEnv() == Vulkan; }
95+
// FIXME: This should check the triple arch instead, but a lot of places use
96+
// this method now instead of `is[OpenCL/Vulkan]Env()`, and this is a
97+
// shortcut to make sure `is[OpenCL/Vulkan]Env()` works as expected. When we
98+
// change back all uses of `isLogicalSPIRV()` to `is[OpenCL/Vulkan]Env()`, we
99+
// can implement this correctly again.
100+
bool isLogicalSPIRV() const { return isVulkanEnv(); }
106101
const std::string &getTargetTripleAsStr() const { return TargetTriple.str(); }
107102
VersionTuple getSPIRVVersion() const { return SPIRVVersion; };
108103
bool isAtLeastSPIRVVer(VersionTuple VerToCompareTo) const;

0 commit comments

Comments
 (0)