-
Notifications
You must be signed in to change notification settings - Fork 13.6k
[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
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. |
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. |
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.
Thanks! I believe that this approach is good enough. Later some extra heuristics can be added, but first it seems like we need to modify clang to update triple for OpenCL.
@Keenuts can you confirm this is good from Vulkan side of things? |
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.
LGTM. Just some trivial nits to flip conditions.
@svenvh @AlexVlx @michalpaszkowski @bader just pinging to see if you have any comments about this PR. Otherwise, as this already has 3 approvals, I'll ask gatekeepers to merge in a couple of days. |
@@ -532,7 +532,7 @@ void SPIRVAsmPrinter::outputExecutionMode(const Module &M) { | |||
Inst.addOperand(MCOperand::createImm(TypeCode)); | |||
outputMCInst(Inst); | |||
} | |||
if (ST->isOpenCLEnv() && !M.getNamedMetadata("spirv.ExecutionMode") && | |||
if (ST->isKernelEnv() && !M.getNamedMetadata("spirv.ExecutionMode") && |
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.
Change how to detect OpenCL/Vulkan Env and update tests accordingly
Let me clarify the terminology.
SPIR-V specification defines OpenCL/Vulkan as environments and Kernel/Shader as capabilities.
What exactly are we detecting here: environments or capabilities?
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.
To be honest, I don't see in the SPIR-V spec anything about environments being OpenCL/Vulkan. Anyway, I think what we are detecting here is capabilities because most uses of isKernelEnv()/isShaderEnv()
are used to check if a particular feature is allowed --e.g. Constant
decoration is only allowed if Kernel
capability is enabled. Fundamentally, we want to know if we're dealing with graphical shaders or compute kernels.
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.
Anyway, I think what we are detecting here is capabilities because most uses of
isKernelEnv()/isShaderEnv()
are used to check if a particular feature is allowed --e.g.Constant
decoration is only allowed ifKernel
capability is enabled. Fundamentally, we want to know if we're dealing with graphical shaders or compute kernels.
Please, make the method name clearer. E.g.
if (ST->isKernelEnv() && !M.getNamedMetadata("spirv.ExecutionMode") && | |
if (ST->isKernel() && !M.getNamedMetadata("spirv.ExecutionMode") && |
or requiresKernelCapability()
.
To be honest, I don't see in the SPIR-V spec anything about environments being OpenCL/Vulkan.
Right, SPIR-V spec only says that there are separate specifications:
1.2. Execution Environment and Client API
SPIR-V is adaptable to multiple execution environments: A SPIR-V module is consumed by an execution environment, as specified by a client API. The full set of rules needed to consume SPIR-V in a particular environment comes from the combination of SPIR-V and that environment’s client API specification. The client API specifies its SPIR-V execution environment as well as extra rules, limitations, capabilities, etc. required by the form of SPIR-V it can validly consume.
OpenCL provides The OpenCL™ SPIR-V Environment Specification and Vulkan provides Vulkan Environment for SPIR-V. There are other execution environments supporting SPIR-V formats (e.g. Level Zero)
My understanding is that compiler performs additional checks for restrictions in the environment specification, which is specified as OS component of the target triple.
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.
Would isCompute()/isShader()
work for you?
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 prefer using terminology from the spec to avoid ambiguity.
For instance, Vulkan uses "compute shader" term for shaders doing GPGPU computations (i.e. what we call just "Shader" in clang project) - https://vulkan-tutorial.com/Compute_Shader.
Is it okay to use isKernel
/isShader
?
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.
It works for me. Let's see if any of the people that already approved disagrees: @Keenuts @VyacheslavLevytskyy @MrSidims. If no comments in the next 24 hours, I'll assume they agree and I'll go ahead and change them to isKernel/isShader
.
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 with isKernel/isShader
(I'd be against isCompute
for OpenCL as this could be confusing)
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.
Updated in 42df23d.
@VyacheslavLevytskyy @michalpaszkowski can we get this merged? |
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.