Skip to content

Commit cfd8980

Browse files
authored
[SPIRV] Handle vector load/store for RWBuffer (#125581)
The type inference for `spv_resource_getpointer` must look at the uses of the intrinsic. The type of the handle will be a scalar type, but it can still be read or written as a vector of that type. Fixes #124551.
1 parent b51fc2a commit cfd8980

File tree

2 files changed

+89
-3
lines changed

2 files changed

+89
-3
lines changed

llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -748,7 +748,11 @@ Type *SPIRVEmitIntrinsics::deduceElementTypeHelper(
748748
if (II && II->getIntrinsicID() == Intrinsic::spv_resource_getpointer) {
749749
auto *ImageType = cast<TargetExtType>(II->getOperand(0)->getType());
750750
assert(ImageType->getTargetExtName() == "spirv.Image");
751-
Ty = ImageType->getTypeParameter(0);
751+
if (II->hasOneUse()) {
752+
auto *U = *II->users().begin();
753+
Ty = cast<Instruction>(U)->getAccessType();
754+
assert(Ty && "Unable to get type for resource pointer.");
755+
}
752756
} else if (Function *CalledF = CI->getCalledFunction()) {
753757
std::string DemangledName =
754758
getOclOrSpirvBuiltinDemangledName(CalledF->getName());

llvm/test/CodeGen/SPIRV/hlsl-resources/BufferLoadStore.ll

Lines changed: 84 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-vulkan-library %s -o - -filetype=obj | spirv-val %}
33

44
; CHECK-DAG: [[float:%[0-9]+]] = OpTypeFloat 32
5+
; CHECK-DAG: [[v2float:%[0-9]+]] = OpTypeVector [[float]] 2
56
; CHECK-DAG: [[v4float:%[0-9]+]] = OpTypeVector [[float]] 4
67
; CHECK-DAG: [[int:%[0-9]+]] = OpTypeInt 32 0
78
; CHECK-DAG: [[zero:%[0-9]+]] = OpConstant [[int]] 0
@@ -10,10 +11,11 @@
1011
; CHECK-DAG: [[twenty_three:%[0-9]+]] = OpConstant [[int]] 23
1112
; CHECK-DAG: [[ImageType:%[0-9]+]] = OpTypeImage [[float]] Buffer 2 0 0 2 Rgba32f
1213
; CHECK-DAG: [[ImagePtr:%[0-9]+]] = OpTypePointer UniformConstant [[ImageType]]
13-
; CHECK: [[Var:%[0-9]+]] = OpVariable [[ImagePtr]] UniformConstant
14+
; CHECK-DAG: [[Var:%[0-9]+]] = OpVariable [[ImagePtr]] UniformConstant
1415

1516
; Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(readwrite, inaccessiblemem: none)
16-
define void @main() local_unnamed_addr #0 {
17+
; CHECK: OpFunction
18+
define void @main_scalar() local_unnamed_addr #0 {
1719
entry:
1820
; CHECK: [[H:%[0-9]+]] = OpLoad [[ImageType]] [[Var]]
1921
%s_h.i = tail call target("spirv.Image", float, 5, 2, 0, 0, 2, 1) @llvm.spv.resource.handlefrombinding.tspirv.Image_f32_5_2_0_0_2_0t(i32 3, i32 5, i32 1, i32 0, i1 false)
@@ -50,6 +52,86 @@ bb_both:
5052
ret void
5153
}
5254

55+
; Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(readwrite, inaccessiblemem: none)
56+
; CHECK: OpFunction
57+
define void @main_vector2() local_unnamed_addr #0 {
58+
entry:
59+
; CHECK: [[H:%[0-9]+]] = OpLoad [[ImageType]] [[Var]]
60+
%s_h.i = tail call target("spirv.Image", float, 5, 2, 0, 0, 2, 1) @llvm.spv.resource.handlefrombinding.tspirv.Image_f32_5_2_0_0_2_0t(i32 3, i32 5, i32 1, i32 0, i1 false)
61+
62+
; CHECK: [[R:%[0-9]+]] = OpImageRead [[v4float]] [[H]] [[one]]
63+
; CHECK: [[E0:%[0-9]+]] = OpCompositeExtract [[float]] [[R]] 0
64+
; CHECK: [[E1:%[0-9]+]] = OpCompositeExtract [[float]] [[R]] 1
65+
; CHECK: [[V:%[0-9]+]] = OpCompositeConstruct [[v2float]] [[E0]] [[E1]]
66+
%0 = tail call noundef nonnull align 4 dereferenceable(4) ptr @llvm.spv.resource.getpointer.p0.tspirv.Image_f32_5_2_0_0_2_0t(target("spirv.Image", float, 5, 2, 0, 0, 2, 1) %s_h.i, i32 1)
67+
%1 = load <2 x float>, ptr %0, align 4
68+
; CHECK: OpBranch [[bb_store:%[0-9]+]]
69+
br label %bb_store
70+
71+
; CHECK: [[bb_store]] = OpLabel
72+
bb_store:
73+
74+
; CHECK: [[H:%[0-9]+]] = OpLoad [[ImageType]] [[Var]]
75+
; CHECK: OpImageWrite [[H]] [[zero]] [[V]]
76+
%2 = tail call noundef nonnull align 4 dereferenceable(4) ptr @llvm.spv.resource.getpointer.p0.tspirv.Image_f32_5_2_0_0_2_0t(target("spirv.Image", float, 5, 2, 0, 0, 2, 1) %s_h.i, i32 0)
77+
store <2 x float> %1, ptr %2, align 4
78+
; CHECK: OpBranch [[bb_both:%[0-9]+]]
79+
br label %bb_both
80+
81+
; CHECK: [[bb_both]] = OpLabel
82+
bb_both:
83+
; CHECK: [[H:%[0-9]+]] = OpLoad [[ImageType]] [[Var]]
84+
; CHECK: [[R:%[0-9]+]] = OpImageRead [[v4float]] [[H]] [[twenty_three]]
85+
; CHECK: [[E0:%[0-9]+]] = OpCompositeExtract [[float]] [[R]] 0
86+
; CHECK: [[E1:%[0-9]+]] = OpCompositeExtract [[float]] [[R]] 1
87+
; CHECK: [[V:%[0-9]+]] = OpCompositeConstruct [[v2float]] [[E0]] [[E1]]
88+
%3 = tail call noundef nonnull align 4 dereferenceable(4) ptr @llvm.spv.resource.getpointer.p0.tspirv.Image_f32_5_2_0_0_2_0t(target("spirv.Image", float, 5, 2, 0, 0, 2, 1) %s_h.i, i32 23)
89+
%4 = load <2 x float>, ptr %3, align 4
90+
91+
; CHECK: [[H:%[0-9]+]] = OpLoad [[ImageType]] [[Var]]
92+
; CHECK: OpImageWrite [[H]] [[twenty]] [[V]]
93+
%5 = tail call noundef nonnull align 4 dereferenceable(4) ptr @llvm.spv.resource.getpointer.p0.tspirv.Image_f32_5_2_0_0_2_0t(target("spirv.Image", float, 5, 2, 0, 0, 2, 1) %s_h.i, i32 20)
94+
store <2 x float> %4, ptr %5, align 4
95+
ret void
96+
}
97+
98+
; Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(readwrite, inaccessiblemem: none)
99+
; CHECK: OpFunction
100+
define void @main_vector4() local_unnamed_addr #0 {
101+
entry:
102+
; CHECK: [[H:%[0-9]+]] = OpLoad [[ImageType]] [[Var]]
103+
%s_h.i = tail call target("spirv.Image", float, 5, 2, 0, 0, 2, 1) @llvm.spv.resource.handlefrombinding.tspirv.Image_f32_5_2_0_0_2_0t(i32 3, i32 5, i32 1, i32 0, i1 false)
104+
105+
; CHECK: [[R:%[0-9]+]] = OpImageRead [[v4float]] [[H]] [[one]]
106+
%0 = tail call noundef nonnull align 4 dereferenceable(4) ptr @llvm.spv.resource.getpointer.p0.tspirv.Image_f32_5_2_0_0_2_0t(target("spirv.Image", float, 5, 2, 0, 0, 2, 1) %s_h.i, i32 1)
107+
%1 = load <4 x float>, ptr %0, align 4
108+
; CHECK: OpBranch [[bb_store:%[0-9]+]]
109+
br label %bb_store
110+
111+
; CHECK: [[bb_store]] = OpLabel
112+
bb_store:
113+
114+
; CHECK: [[H:%[0-9]+]] = OpLoad [[ImageType]] [[Var]]
115+
; CHECK: OpImageWrite [[H]] [[zero]] [[R]]
116+
%2 = tail call noundef nonnull align 4 dereferenceable(4) ptr @llvm.spv.resource.getpointer.p0.tspirv.Image_f32_5_2_0_0_2_0t(target("spirv.Image", float, 5, 2, 0, 0, 2, 1) %s_h.i, i32 0)
117+
store <4 x float> %1, ptr %2, align 4
118+
; CHECK: OpBranch [[bb_both:%[0-9]+]]
119+
br label %bb_both
120+
121+
; CHECK: [[bb_both]] = OpLabel
122+
bb_both:
123+
; CHECK: [[H:%[0-9]+]] = OpLoad [[ImageType]] [[Var]]
124+
; CHECK: [[R:%[0-9]+]] = OpImageRead [[v4float]] [[H]] [[twenty_three]]
125+
%3 = tail call noundef nonnull align 4 dereferenceable(4) ptr @llvm.spv.resource.getpointer.p0.tspirv.Image_f32_5_2_0_0_2_0t(target("spirv.Image", float, 5, 2, 0, 0, 2, 1) %s_h.i, i32 23)
126+
%4 = load <4 x float>, ptr %3, align 4
127+
128+
; CHECK: [[H:%[0-9]+]] = OpLoad [[ImageType]] [[Var]]
129+
; CHECK: OpImageWrite [[H]] [[twenty]] [[R]]
130+
%5 = tail call noundef nonnull align 4 dereferenceable(4) ptr @llvm.spv.resource.getpointer.p0.tspirv.Image_f32_5_2_0_0_2_0t(target("spirv.Image", float, 5, 2, 0, 0, 2, 1) %s_h.i, i32 20)
131+
store <4 x float> %4, ptr %5, align 4
132+
ret void
133+
}
134+
53135
; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(none)
54136
declare ptr @llvm.spv.resource.getpointer.p0.tspirv.Image_f32_5_2_0_0_2_0t(target("spirv.Image", float, 5, 2, 0, 0, 2, 1), i32) #1
55137

0 commit comments

Comments
 (0)