-
Notifications
You must be signed in to change notification settings - Fork 14.7k
[SPIRV] Preserve implicit bitcast #151041
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
Conversation
@llvm/pr-subscribers-backend-spir-v Author: Farzon Lotfi (farzonl) Changesfixes #146942 IssueThe cause of the bug is in InstCombine which is converting hour load of float vec4 and bitcast to i32 vec4 into one load of i32 vec4. It seems like we will have to do a legalization in the spirv backent to convert - %3 = load <4 x i32>, ptr addrspace(11) %2, align 16
+ %3 = load <4 x float>, ptr addrspace(11) %2, align 16
+ %4 = bitcast <4 x float> %3 to <4 x i32> <img width="2566" height="548" alt="Image" src="https://github.com/user-attachments/assets/0bf8813c-70f8-47df-8207-ab7da54f5382" /> https://godbolt.org/z/K4GeM4fKT The FixJust removing the assert isn't enough to fix this bug. If we do so we get an assert later If we just remove the assert the Full diff: https://github.com/llvm/llvm-project/pull/151041.diff 2 Files Affected:
diff --git a/llvm/lib/Target/SPIRV/SPIRVLegalizePointerCast.cpp b/llvm/lib/Target/SPIRV/SPIRVLegalizePointerCast.cpp
index 5cda6a07352d5..7e9c9c62cd889 100644
--- a/llvm/lib/Target/SPIRV/SPIRVLegalizePointerCast.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVLegalizePointerCast.cpp
@@ -74,17 +74,17 @@ class SPIRVLegalizePointerCast : public FunctionPass {
// Returns the loaded value.
Value *loadVectorFromVector(IRBuilder<> &B, FixedVectorType *SourceType,
FixedVectorType *TargetType, Value *Source) {
- // We expect the codegen to avoid doing implicit bitcast from a load.
- assert(TargetType->getElementType() == SourceType->getElementType());
- assert(TargetType->getNumElements() < SourceType->getNumElements());
-
+ assert(TargetType->getNumElements() <= SourceType->getNumElements());
LoadInst *NewLoad = B.CreateLoad(SourceType, Source);
- buildAssignType(B, SourceType, NewLoad);
+ Value *AssignType = NewLoad;
+ if (TargetType->getElementType() != SourceType->getElementType())
+ AssignType = B.CreateBitCast(NewLoad, TargetType);
+ buildAssignType(B, SourceType, AssignType);
SmallVector<int> Mask(/* Size= */ TargetType->getNumElements());
for (unsigned I = 0; I < TargetType->getNumElements(); ++I)
Mask[I] = I;
- Value *Output = B.CreateShuffleVector(NewLoad, NewLoad, Mask);
+ Value *Output = B.CreateShuffleVector(AssignType, AssignType, Mask);
buildAssignType(B, TargetType, Output);
return Output;
}
diff --git a/llvm/test/CodeGen/SPIRV/hlsl-resources/issue-146942-ptr-cast.ll b/llvm/test/CodeGen/SPIRV/hlsl-resources/issue-146942-ptr-cast.ll
new file mode 100644
index 0000000000000..859b6eca8c084
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/hlsl-resources/issue-146942-ptr-cast.ll
@@ -0,0 +1,24 @@
+; RUN: llc -O0 -verify-machineinstrs -mtriple=spirv-unknown-vulkan %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-vulkan %s -o - -filetype=obj | spirv-val %}
+
+@.str = private unnamed_addr constant [4 x i8] c"In3\00", align 1
+@.str.2 = private unnamed_addr constant [5 x i8] c"Out3\00", align 1
+
+; Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(readwrite, inaccessiblemem: none)
+define void @main() local_unnamed_addr #0 {
+ ; CHECK: %[[#INT32:]] = OpTypeInt 32 0
+ ; CHECK: %[[#INT4:]] = OpTypeVector %[[#INT32]] 4
+ ; CHECK: %[[#FLOAT:]] = OpTypeFloat 32
+ ; CHECK: %[[#FLOAT4:]] = OpTypeVector %[[#FLOAT]] 4
+ ; CHECK: %[[#BUFFER_LOAD:]] = OpLoad %[[#FLOAT4]] %{{[0-9]+}} Aligned 16
+ ; CHECK: %[[#VEC_SHUFFLE:]] = OpVectorShuffle %[[#INT4]] %[[#BUFFER_LOAD]] %[[#BUFFER_LOAD]] 0 1 2 3
+ %1 = tail call target("spirv.VulkanBuffer", [0 x <4 x float>], 12, 0) @llvm.spv.resource.handlefrombinding.tspirv.VulkanBuffer_a0v4f32_12_0t(i32 0, i32 2, i32 1, i32 0, i1 false, ptr nonnull @.str)
+ %2 = tail call target("spirv.VulkanBuffer", [0 x <4 x i32>], 12, 1) @llvm.spv.resource.handlefrombinding.tspirv.VulkanBuffer_a0v4i32_12_1t(i32 0, i32 5, i32 1, i32 0, i1 false, ptr nonnull @.str.2)
+ %3 = tail call noundef align 16 dereferenceable(16) ptr addrspace(11) @llvm.spv.resource.getpointer.p11.tspirv.VulkanBuffer_a0v4f32_12_0t(target("spirv.VulkanBuffer", [0 x <4 x float>], 12, 0) %1, i32 0)
+ %4 = load <4 x i32>, ptr addrspace(11) %3, align 16
+ %5 = tail call noundef align 16 dereferenceable(16) ptr addrspace(11) @llvm.spv.resource.getpointer.p11.tspirv.VulkanBuffer_a0v4i32_12_1t(target("spirv.VulkanBuffer", [0 x <4 x i32>], 12, 1) %2, i32 0)
+ store <4 x i32> %4, ptr addrspace(11) %5, align 16
+ ret void
+}
+
+attributes #0 = { mustprogress nofree noinline norecurse nosync nounwind willreturn memory(readwrite, inaccessiblemem: none) "approx-func-fp-math"="true" "frame-pointer"="all" "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" "no-infs-fp-math"="true" "no-nans-fp-math"="true" "no-signed-zeros-fp-math"="true" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
\ No newline at end of file
|
10e7c8b
to
22bac98
Compare
Need to investigate spirv-val issue tomorrow. |
…translated into MIR. Instead we will do what `SPIRVEmitIntrinsics::visitBitCastInst` does and emit `spv_bitcast` instead of `BitCastInst`.
22bac98
to
52cc44e
Compare
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 for the fix. LGTM, just an additional test to verify the interaction between both
98d43f2
to
d06d08c
Compare
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 small comment formatting nit.
Co-authored-by: Chris B <[email protected]>
fixes #146942
Issue
The cause of the bug is in InstCombine which is converting our load of float vec4 and bitcast to i32 vec4 into one load of i32 vec4. That means wr have to do a legalization in the spirv backend to convert back
https://godbolt.org/z/K4GeM4fKT
The Fix
Just removing the assert isn't enough to fix this bug. If we do so we get an assert later
Assertion failed: (!storageClassRequiresExplictLayout(SC)), function getOrCreateSPIRVPointerType, file SPIRVGlobalRegistry.cpp, line 1806.
If we just remove the assert the
CreateShuffleVector
uses the source type via theNewLoad
when theOutput
type needs to be theTargetType
.We also can't use
CreateBitCast
That will feed the right types for theShuffleVector
but it doesn't emit OpBitcast. the llvmIR isn't translated over to MIR.The fix then is to emit
spv_bitcast
just like whatSPIRVEmitIntrinsics::visitBitCastInst
does.