-
Notifications
You must be signed in to change notification settings - Fork 13.4k
[SPIRV] Change how to detect OpenCL/Vulkan Env and update tests accordingly. #129689
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
[SPIRV] Change how to detect OpenCL/Vulkan Env and update tests accordingly. #129689
Conversation
@llvm/pr-subscribers-backend-spir-v Author: Marcos Maronas (maarquitos14) ChangesThe test is intended to specifically test spirv-friendly builtins, so change the function name to spirv-friendly format. Full diff: https://github.com/llvm/llvm-project/pull/129689.diff 1 Files Affected:
diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_bit_instructions/spirv-friendly_extended_bit_ops.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_bit_instructions/spirv-friendly_extended_bit_ops.ll
index e49a55956aff0..c93a4ad1bf1c9 100644
--- a/llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_bit_instructions/spirv-friendly_extended_bit_ops.ll
+++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_bit_instructions/spirv-friendly_extended_bit_ops.ll
@@ -76,12 +76,12 @@ declare spir_func <8 x i8> @_Z24__spirv_BitFieldUExtractDv8_hjj(<8 x i8>, i32, i
; }
define spir_kernel void @testBitReverse_SPIRVFriendly(<4 x i64> %b, ptr addrspace(1) nocapture align 32 %res) #3 {
entry:
- %call = call <4 x i64> @llvm.bitreverse.v4i64(<4 x i64> %b)
+ %call = call <4 x i64> @_Z18__spirv_BitReverseDv4_l(<4 x i64> %b)
store <4 x i64> %call, ptr addrspace(1) %res, align 32
ret void
}
-declare <4 x i64> @llvm.bitreverse.v4i64(<4 x i64>) #4
+declare <4 x i64> @_Z18__spirv_BitReverseDv4_l(<4 x i64>) #4
|
b8daa27
to
11e5b6f
Compare
✅ With the latest revision this PR passed the C/C++ code formatter. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is OK for me, as I don't think there are any other target than OpenCL/Vulkan for now. This can be revisited when Microsoft adds their DX/SPIRV thing
"This entry point lacks mandatory hlsl.shader attribute."); | ||
"This entry point lacks mandatory hlsl.shader attribute.", false); | ||
} | ||
|
||
const auto value = attribute.getValueAsString(); | ||
if (value == "compute") | ||
return SPIRV::ExecutionModel::GLCompute; | ||
|
||
report_fatal_error("This HLSL entry point is not supported by this backend."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unrelated no?
I'm afraid, this looks fragile with regards to the triple. Triples of kinds, for instance, "spirv64-unknown-unknown" and "spirv64v1.6-unknown-unknown" are massively in use and nobody expects that the "-opencl" suffix change game rules. If a user needs now to apply "-opencl" everywhere to be recognized as the user of the compute flavor of SPIR-V, I expect that pretty much everything will start to fail after this change. Probably we need a way that doesn't require updating the whole compute's set of test cases, this is the only guarantee that SYCL, Intel's XPU backend for Triton, etc. will not notice the internal change in the SPIR-V backend. This is not to mention non-Intel applications of the compute flavor of SPIR-V. For the context it's important that isOpenCLEnv() is just a bad choice of the name for such a function, it should be renamed to something of a kind of isCompute() to reflect what it means. |
Let's add to the discussion more people: @michalpaszkowski @MrSidims @asudarsa |
I would expect that updating Clang to generate
I agree, and similarly, |
CC: @AlexVlx |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This patch is LGTM, but IMHO this is a case when a work shouldn't be split across components - I mean that either this PR should also include changes in clang, that are forcing OpenCL environment to be included in the triple information for OpenCL lang or the appropriate PR in clang should already exist and be linked here as we also need to have attention and feedback from the frontend folks.
fyi @svenvh
} | ||
bool isVulkanEnv() const { return TargetTriple.getArch() == Triple::spirv; } | ||
bool isVulkanEnv() const { return !isOpenCLEnv(); } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see that Vulkan is added to the triple as OSType:
Vulkan, // Vulkan SPIR-V |
SPIR target uses
Vulkan
OSType to detect Vulkan environment: llvm-project/clang/lib/Basic/Targets/SPIR.h
Lines 305 to 312 in 9fdac84
assert(Triple.getArch() == llvm::Triple::spirv && | |
"Invalid architecture for Logical SPIR-V."); | |
assert(Triple.getOS() == llvm::Triple::Vulkan && | |
Triple.getVulkanVersion() != llvm::VersionTuple(0) && | |
"Logical SPIR-V requires a valid Vulkan environment."); | |
assert(Triple.getEnvironment() >= llvm::Triple::Pixel && | |
Triple.getEnvironment() <= llvm::Triple::Amplification && | |
"Logical SPIR-V environment must be a valid shader stage."); |
OpenCL is a bit messy.
I see one* OpenCL OSType:
NVCL, // NVIDIA OpenCL |
Environment component also defines OpenCL:
OpenCL, |
I don't know the meaning of OpenCL in the environment component, but using OS triple component makes more sense to me. This topic probably forth a separate discussion, but I would add OpenCL component to OSType rather than to environment component. I guess we can alias NVCL
to the OpenCL
OSType value.
* - Maybe Mesa3D
can be also considered as OpenCL environment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know the meaning of OpenCL in the environment component
It was added in #78655 and seems to be just a side change. I've asked the author in the PR, what was the idea behind adding OpenCL to env, but not sure if I'll get a reply.
} | ||
bool isVulkanEnv() const { return TargetTriple.getArch() == Triple::spirv; } | ||
bool isVulkanEnv() const { return !isOpenCLEnv(); } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
bool isVulkanEnv() const { return !isOpenCLEnv(); }
This code says that any triple that doesn't match OpenCL environment is Vulkan environment.
I would prefer SPIR-V backend to keep existing behavior for existing triple i.e. spirv[32|64]-unknown-unknown -> OpenCL environment.
New triples:
spirv-<vendor>-vulkan
- SPIR-V for Vulkan environment.spirv[32|64]-<vendor>-opencl
- SPIR-V for OpenCL environment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One of the things that we would like to fix is the fact that Vulkan/Shader environment can also be for a physical target (spirv32, spirv64). In other words, although de facto every physical SPIRV is Compute, and every logical SPIRV is Shader, that is not a requirement from the spec, so we should be able to support logical SPIRV for Compute and physical SPIRV for Shader.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can it be done in less intrusive way e.g. by requiring vulkan OS in the target triple?
If OS target triple is not Vulkan, the environment is set to OpenCL.
This way, we won't break the existing interface for FEs using "unknown" OS type to target OpenCL environment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new approach I just added shouldn't break the existing interface for FEs using "unknown" OS type to target OpenCL environment.
11e5b6f
to
eef5045
Compare
@Keenuts the new approach I just added makes 58 tests fail. They can all pass if we explicitly pass |
@Keenuts friendly ping |
Sorry, missed your notification |
Yes, that's what I meant. I'll update those and ping again when the CI is green to make sure we are on the same page. |
eef5045
to
1a4e754
Compare
@Keenuts @bader @VyacheslavLevytskyy @MrSidims @michalpaszkowski this is ready for review now. Note that this changed significantly since the first time it was open. |
Don't know for others, but there is the |
// Can we rely on "hlsl.shader" attribute? Is it mandatory for Vulkan env? If | ||
// so, we can set Env to Vulkan whenever we find it, and to OpenCL otherwise. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, but we can rely on it? Can we assume that if we find such an attribute we're in Vulkan env?
// FIXME: At the moment, there's a possibility that both `isOpenCLEnv()` and | ||
// `isVulkanEnv()` return true. This is because the Triple is not always | ||
// precise enough. For now, we'll rely instead on `isLogicalSPIRV()`, but this | ||
// should be changed when `isOpenCLEnv()` and `isVulkanEnv()` cannot be true | ||
// at the same time. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You mean both return false if the env is Unknown
no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, they both return true. In order to not break current behavior, where some users of SPIRV BE rely on spirv-unknown-unknown
, we need to do it this way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SPIRVEnvType getEnv() const { return Env; }
bool isOpenCLEnv() const { return getEnv() == OpenCL; }
bool isVulkanEnv() const { return getEnv() == Vulkan; }
Env being an enum, not a bitmask, either both return false when getEnv()
is Unknown or they are exclusive, or am I misreading something?
SPIRVEnvType getEnv() const { return Env; } | ||
bool isOpenCLEnv() const { return getEnv() == OpenCL; } | ||
bool isVulkanEnv() const { return getEnv() == Vulkan; } | ||
// FIXME: This should check the triple arch instead, but a lot of places use | ||
// this method now instead of `is[OpenCL/Vulkan]Env()`, and this is a | ||
// shortcut to make sure `is[OpenCL/Vulkan]Env()` works as expected. When we | ||
// change back all uses of `isLogicalSPIRV()` to `is[OpenCL/Vulkan]Env()`, we | ||
// can implement this correctly again. | ||
bool isLogicalSPIRV() const { return isVulkanEnv(); } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm fine requiring an explicit -vulkan
when targeting vulkan.
Question: shall those 2 functions be:
bool isKernelEnv() { return Env==Unknown && (arch == spirv64 || arch == spirv32)
bool isShaderEnv() { return OS == vulkan }
bool isLogicalSPIRV() { return arch == spirv }
```
For now we gated many capabilities/things around `isOpenCL`/`isVulkan`, but we might to change that?
The `StorageImageReadWithoutFormat` check would is isShader(), but the Structurizer would rely on `isLogicalSPIRV()`
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can explore something along these lines, although one thing we wanted to do is decouple physical/logical SPIRV from Kernel/Shader env, so probably we don't want to do exactly bool isKernelEnv() { return Env==Unknown && (arch == spirv64 || arch == spirv32)
.
Thanks, I have done it now. Originally I couldn't even ask for reviewers myself (@VyacheslavLevytskyy did it for me), so I assumed I could not ask for re-review either, but turns out I can. |
@@ -36,6 +36,10 @@ class StringRef; | |||
class SPIRVTargetMachine; | |||
|
|||
class SPIRVSubtarget : public SPIRVGenSubtargetInfo { | |||
public: | |||
// Enum for the SPIR-V environment: OpenCL, Vulkan or Unkwnown. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// Enum for the SPIR-V environment: OpenCL, Vulkan or Unkwnown. | |
// Enum for the SPIR-V environment: OpenCL, Vulkan or Unknown. |
What is the semantic meaning of Unknown
? Does it mean it could be either OpenCL or Vulkan? Or does it mean "invalid" since it is not set?
A new test added for spirv-friendly builtins for SPV_KHR_bit_instructions unveiled that current mechanism to detect whether SPIRV Backend is in OpenCL environment or Vulkan environment was not good enough. This PR updates how to detect the environment and all the tests accordingly.
UPDATE: the new approach is having a new member in
SPIRVSubtarget
to represent the environment. It can be either OpenCL, Kernel or Unknown. If the triple is explicit, we can directly set it at the creation of theSPIRVSubtarget
, otherwise we just leave it unknown until we find other information that can help us set the environment. For now, the only other information we use to set the environment ishlsl.shader
attribute atSPIRV::ExecutionModel::ExecutionModel getExecutionModel(const SPIRVSubtarget &STI, const Function &F)
. Going forward we should consider also specific instructions that are Kernel-exclusive or Shader-exclusive.