Skip to content

Commit 0aba833

Browse files
authored
[SPIR-V] Handle struct member loading from ptrcast (#130089)
Adds support for loading the first element of an aggregate from a GEP instruction & load to the member type.
1 parent 29925b7 commit 0aba833

File tree

2 files changed

+77
-10
lines changed

2 files changed

+77
-10
lines changed

llvm/lib/Target/SPIRV/SPIRVLegalizePointerCast.cpp

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -103,12 +103,8 @@ class SPIRVLegalizePointerCast : public FunctionPass {
103103
auto *GEP = B.CreateIntrinsic(Intrinsic::spv_gep, {Types}, {Args});
104104
GR->buildAssignPtr(B, ElementType, GEP);
105105

106-
const auto *TLI = TM->getSubtargetImpl()->getTargetLowering();
107-
MachineMemOperand::Flags Flags = TLI->getLoadMemOperandFlags(
108-
*BadLoad, BadLoad->getFunction()->getDataLayout());
109-
Instruction *LI = B.CreateIntrinsic(
110-
Intrinsic::spv_load, {BadLoad->getOperand(0)->getType()},
111-
{GEP, B.getInt16(Flags), B.getInt8(BadLoad->getAlign().value())});
106+
LoadInst *LI = B.CreateLoad(ElementType, GEP);
107+
LI->setAlignment(BadLoad->getAlign());
112108
buildAssignType(B, ElementType, LI);
113109
return LI;
114110
}
@@ -123,6 +119,7 @@ class SPIRVLegalizePointerCast : public FunctionPass {
123119

124120
auto *SAT = dyn_cast<ArrayType>(FromTy);
125121
auto *SVT = dyn_cast<FixedVectorType>(FromTy);
122+
auto *SST = dyn_cast<StructType>(FromTy);
126123
auto *DVT = dyn_cast<FixedVectorType>(ToTy);
127124

128125
B.SetInsertPoint(LI);
@@ -144,6 +141,11 @@ class SPIRVLegalizePointerCast : public FunctionPass {
144141
// - float3 v3 = vector4;
145142
else if (SVT && DVT)
146143
Output = loadVectorFromVector(B, SVT, DVT, OriginalOperand);
144+
// Destination is the scalar type stored at the start of an aggregate.
145+
// - struct S { float m };
146+
// - float v = s.m;
147+
else if (SST && SST->getTypeAtIndex(0u) == ToTy)
148+
Output = loadFirstValueFromAggregate(B, ToTy, OriginalOperand, LI);
147149
else
148150
llvm_unreachable("Unimplemented implicit down-cast from load.");
149151

@@ -166,10 +168,11 @@ class SPIRVLegalizePointerCast : public FunctionPass {
166168
continue;
167169
}
168170

169-
IntrinsicInst *Intrin = dyn_cast<IntrinsicInst>(User);
170-
if (Intrin->getIntrinsicID() == Intrinsic::spv_assign_ptr_type) {
171-
DeadInstructions.push_back(Intrin);
172-
continue;
171+
if (IntrinsicInst *Intrin = dyn_cast<IntrinsicInst>(User)) {
172+
if (Intrin->getIntrinsicID() == Intrinsic::spv_assign_ptr_type) {
173+
DeadInstructions.push_back(Intrin);
174+
continue;
175+
}
173176
}
174177

175178
llvm_unreachable("Unsupported ptrcast user. Please fix.");
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-vulkan-compute %s -o - | FileCheck %s
2+
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-vulkan %s -o - -filetype=obj | spirv-val %}
3+
4+
; CHECK-DAG: %[[#uint:]] = OpTypeInt 32 0
5+
; CHECK-DAG: %[[#float:]] = OpTypeFloat 32
6+
; CHECK-DAG: %[[#float_fp:]] = OpTypePointer Function %[[#float]]
7+
; CHECK-DAG: %[[#float_pp:]] = OpTypePointer Private %[[#float]]
8+
; CHECK-DAG: %[[#uint_fp:]] = OpTypePointer Function %[[#uint]]
9+
; CHECK-DAG: %[[#uint_0:]] = OpConstant %[[#uint]] 0
10+
; CHECK-DAG: %[[#sf:]] = OpTypeStruct %[[#float]]
11+
; CHECK-DAG: %[[#su:]] = OpTypeStruct %[[#uint]]
12+
; CHECK-DAG: %[[#sfuf:]] = OpTypeStruct %[[#float]] %[[#uint]] %[[#float]]
13+
; CHECK-DAG: %[[#sf_fp:]] = OpTypePointer Function %[[#sf]]
14+
; CHECK-DAG: %[[#su_fp:]] = OpTypePointer Function %[[#su]]
15+
; CHECK-DAG: %[[#sfuf_fp:]] = OpTypePointer Function %[[#sfuf]]
16+
; CHECK-DAG: %[[#sfuf_pp:]] = OpTypePointer Private %[[#sfuf]]
17+
18+
%struct.SF = type { float }
19+
%struct.SU = type { i32 }
20+
%struct.SFUF = type { float, i32, float }
21+
22+
@gsfuf = external addrspace(10) global %struct.SFUF
23+
; CHECK: %[[#gsfuf:]] = OpVariable %[[#sfuf_pp]] Private
24+
25+
define internal spir_func float @foo() {
26+
%1 = alloca %struct.SF, align 4
27+
; CHECK: %[[#var:]] = OpVariable %[[#sf_fp]] Function
28+
29+
%2 = load float, ptr %1, align 4
30+
; CHECK: %[[#tmp:]] = OpAccessChain %[[#float_fp]] %[[#var]] %[[#uint_0]]
31+
; CHECK: %[[#val:]] = OpLoad %[[#float]] %[[#tmp]] Aligned 4
32+
33+
ret float %2
34+
}
35+
36+
define internal spir_func i32 @bar() {
37+
%1 = alloca %struct.SU, align 4
38+
; CHECK: %[[#var:]] = OpVariable %[[#su_fp]] Function
39+
40+
%2 = load i32, ptr %1, align 4
41+
; CHECK: %[[#tmp:]] = OpAccessChain %[[#uint_fp]] %[[#var]] %[[#uint_0]]
42+
; CHECK: %[[#val:]] = OpLoad %[[#uint]] %[[#tmp]] Aligned 4
43+
44+
ret i32 %2
45+
}
46+
47+
define internal spir_func float @baz() {
48+
%1 = alloca %struct.SFUF, align 4
49+
; CHECK: %[[#var:]] = OpVariable %[[#sfuf_fp]] Function
50+
51+
%2 = load float, ptr %1, align 4
52+
; CHECK: %[[#tmp:]] = OpAccessChain %[[#float_fp]] %[[#var]] %[[#uint_0]]
53+
; CHECK: %[[#val:]] = OpLoad %[[#float]] %[[#tmp]] Aligned 4
54+
55+
ret float %2
56+
}
57+
58+
define internal spir_func float @biz() {
59+
%2 = load float, ptr addrspace(10) @gsfuf, align 4
60+
; CHECK: %[[#tmp:]] = OpAccessChain %[[#float_pp]] %[[#gsfuf]] %[[#uint_0]]
61+
; CHECK: %[[#val:]] = OpLoad %[[#float]] %[[#tmp]] Aligned 4
62+
63+
ret float %2
64+
}

0 commit comments

Comments
 (0)