Skip to content

Commit 3a94986

Browse files
committed
[SPIRV] Lower spirv.Layout type
Add this type in accordance with the [design doc](llvm/wg-hlsl#171). Fixes #138276
1 parent 6ee30e8 commit 3a94986

File tree

8 files changed

+130
-20
lines changed

8 files changed

+130
-20
lines changed

llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3163,6 +3163,12 @@ static SPIRVType *getVulkanBufferType(const TargetExtType *ExtensionType,
31633163
return GR->getOrCreateVulkanBufferType(MIRBuilder, T, SC, IsWritable);
31643164
}
31653165

3166+
static SPIRVType *getLayoutType(const TargetExtType *ExtensionType,
3167+
MachineIRBuilder &MIRBuilder,
3168+
SPIRVGlobalRegistry *GR) {
3169+
return GR->getOrCreateLayoutType(MIRBuilder, ExtensionType);
3170+
}
3171+
31663172
namespace SPIRV {
31673173
TargetExtType *parseBuiltinTypeNameToTargetExtType(std::string TypeName,
31683174
LLVMContext &Context) {
@@ -3240,6 +3246,8 @@ SPIRVType *lowerBuiltinType(const Type *OpaqueType,
32403246
TargetType = getInlineSpirvType(BuiltinType, MIRBuilder, GR);
32413247
} else if (Name == "spirv.VulkanBuffer") {
32423248
TargetType = getVulkanBufferType(BuiltinType, MIRBuilder, GR);
3249+
} else if (Name == "spirv.Layout") {
3250+
TargetType = getLayoutType(BuiltinType, MIRBuilder, GR);
32433251
} else {
32443252
// Lookup the demangled builtin type in the TableGen records.
32453253
const SPIRV::BuiltinType *TypeRecord = SPIRV::lookupBuiltinType(Name);

llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -673,10 +673,16 @@ Type *SPIRVEmitIntrinsics::deduceElementTypeHelper(
673673
} else if (HandleType->getTargetExtName() == "spirv.VulkanBuffer") {
674674
// This call is supposed to index into an array
675675
Ty = HandleType->getTypeParameter(0);
676-
assert(Ty->isArrayTy() &&
677-
"spv_resource_getpointer indexes into an array, so the type of "
678-
"the buffer should be an array.");
679-
Ty = Ty->getArrayElementType();
676+
if (Ty->isArrayTy())
677+
Ty = Ty->getArrayElementType();
678+
else {
679+
TargetExtType *BufferTy = cast<TargetExtType>(Ty);
680+
assert(BufferTy->getTargetExtName() == "spirv.Layout");
681+
Ty = BufferTy->getTypeParameter(0);
682+
assert(Ty && Ty->isStructTy());
683+
uint32_t Index = cast<ConstantInt>(II->getOperand(1))->getZExtValue();
684+
Ty = cast<StructType>(Ty)->getElementType(Index);
685+
}
680686
} else {
681687
llvm_unreachable("Unknown handle type for spv_resource_getpointer.");
682688
}

llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -957,7 +957,7 @@ SPIRVType *SPIRVGlobalRegistry::getOpTypeOpaque(const StructType *Ty,
957957
SPIRVType *SPIRVGlobalRegistry::getOpTypeStruct(
958958
const StructType *Ty, MachineIRBuilder &MIRBuilder,
959959
SPIRV::AccessQualifier::AccessQualifier AccQual,
960-
bool ExplicitLayoutRequired, bool EmitIR) {
960+
StructOffsetDecorator Decorator, bool EmitIR) {
961961
const SPIRVSubtarget &ST =
962962
cast<SPIRVSubtarget>(MIRBuilder.getMF().getSubtarget());
963963
SmallVector<Register, 4> FieldTypes;
@@ -974,7 +974,7 @@ SPIRVType *SPIRVGlobalRegistry::getOpTypeStruct(
974974

975975
for (const auto &Elem : Ty->elements()) {
976976
SPIRVType *ElemTy = findSPIRVType(toTypedPointer(Elem), MIRBuilder, AccQual,
977-
ExplicitLayoutRequired, EmitIR);
977+
Decorator != nullptr, EmitIR);
978978
assert(ElemTy && ElemTy->getOpcode() != SPIRV::OpTypeVoid &&
979979
"Invalid struct element type");
980980
FieldTypes.push_back(getSPIRVTypeID(ElemTy));
@@ -1001,9 +1001,8 @@ SPIRVType *SPIRVGlobalRegistry::getOpTypeStruct(
10011001
return MIBStruct;
10021002
});
10031003

1004-
if (ExplicitLayoutRequired)
1005-
addStructOffsetDecorations(SPVType->defs().begin()->getReg(),
1006-
const_cast<StructType *>(Ty), MIRBuilder);
1004+
if (Decorator)
1005+
Decorator(SPVType->defs().begin()->getReg());
10071006

10081007
return SPVType;
10091008
}
@@ -1142,8 +1141,15 @@ SPIRVType *SPIRVGlobalRegistry::createSPIRVType(
11421141
if (auto SType = dyn_cast<StructType>(Ty)) {
11431142
if (SType->isOpaque())
11441143
return getOpTypeOpaque(SType, MIRBuilder);
1145-
return getOpTypeStruct(SType, MIRBuilder, AccQual, ExplicitLayoutRequired,
1146-
EmitIR);
1144+
1145+
StructOffsetDecorator Decorator = nullptr;
1146+
if (ExplicitLayoutRequired) {
1147+
Decorator = [&MIRBuilder, SType, this](Register Reg) {
1148+
addStructOffsetDecorations(Reg, const_cast<StructType *>(SType),
1149+
MIRBuilder);
1150+
};
1151+
}
1152+
return getOpTypeStruct(SType, MIRBuilder, AccQual, Decorator, EmitIR);
11471153
}
11481154
if (auto FType = dyn_cast<FunctionType>(Ty)) {
11491155
SPIRVType *RetTy = findSPIRVType(FType->getReturnType(), MIRBuilder,
@@ -1460,6 +1466,32 @@ SPIRVType *SPIRVGlobalRegistry::getOrCreateVulkanBufferType(
14601466
return R;
14611467
}
14621468

1469+
SPIRVType *SPIRVGlobalRegistry::getOrCreateLayoutType(
1470+
MachineIRBuilder &MIRBuilder, const TargetExtType *T, bool EmitIr) {
1471+
auto Key = SPIRV::handle(T);
1472+
if (const MachineInstr *MI = findMI(Key, &MIRBuilder.getMF()))
1473+
return MI;
1474+
1475+
StructType *ST = cast<StructType>(T->getTypeParameter(0));
1476+
ArrayRef<uint32_t> Offsets = T->int_params().slice(1);
1477+
assert(ST->getNumElements() == Offsets.size());
1478+
1479+
StructOffsetDecorator Decorator = [&MIRBuilder, &Offsets](Register Reg) {
1480+
for (uint32_t I = 0; I < Offsets.size(); ++I) {
1481+
buildOpMemberDecorate(Reg, MIRBuilder, SPIRV::Decoration::Offset, I,
1482+
{Offsets[I]});
1483+
}
1484+
};
1485+
1486+
// We need a new OpTypeStruct instruction because decorations will be
1487+
// different from a struct with an explicit layout created from a different
1488+
// entry point.
1489+
SPIRVType *SPIRVStructType = getOpTypeStruct(
1490+
ST, MIRBuilder, SPIRV::AccessQualifier::None, Decorator, EmitIr);
1491+
add(Key, SPIRVStructType);
1492+
return SPIRVStructType;
1493+
}
1494+
14631495
SPIRVType *SPIRVGlobalRegistry::getOrCreateOpTypeImage(
14641496
MachineIRBuilder &MIRBuilder, SPIRVType *SampledType, SPIRV::Dim::Dim Dim,
14651497
uint32_t Depth, uint32_t Arrayed, uint32_t Multisampled, uint32_t Sampled,

llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
namespace llvm {
2727
class SPIRVSubtarget;
2828
using SPIRVType = const MachineInstr;
29+
using StructOffsetDecorator = std::function<void(Register)>;
2930

3031
class SPIRVGlobalRegistry : public SPIRVIRMapping {
3132
// Registers holding values which have types associated with them.
@@ -451,7 +452,7 @@ class SPIRVGlobalRegistry : public SPIRVIRMapping {
451452

452453
SPIRVType *getOpTypeStruct(const StructType *Ty, MachineIRBuilder &MIRBuilder,
453454
SPIRV::AccessQualifier::AccessQualifier AccQual,
454-
bool ExplicitLayoutRequired, bool EmitIR);
455+
StructOffsetDecorator Decorator, bool EmitIR);
455456

456457
SPIRVType *getOpTypePointer(SPIRV::StorageClass::StorageClass SC,
457458
SPIRVType *ElemType, MachineIRBuilder &MIRBuilder,
@@ -601,6 +602,9 @@ class SPIRVGlobalRegistry : public SPIRVIRMapping {
601602
SPIRV::StorageClass::StorageClass SC,
602603
bool IsWritable, bool EmitIr = false);
603604

605+
SPIRVType *getOrCreateLayoutType(MachineIRBuilder &MIRBuilder,
606+
const TargetExtType *T, bool EmitIr = false);
607+
604608
SPIRVType *
605609
getOrCreateOpTypeImage(MachineIRBuilder &MIRBuilder, SPIRVType *SampledType,
606610
SPIRV::Dim::Dim Dim, uint32_t Depth, uint32_t Arrayed,

llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -86,14 +86,15 @@ SPIRVLegalizerInfo::SPIRVLegalizerInfo(const SPIRVSubtarget &ST) {
8686
const LLT p8 = LLT::pointer(8, PSize); // Output
8787
const LLT p10 = LLT::pointer(10, PSize); // Private
8888
const LLT p11 = LLT::pointer(11, PSize); // StorageBuffer
89+
const LLT p12 = LLT::pointer(12, PSize); // Uniform
8990

9091
// TODO: remove copy-pasting here by using concatenation in some way.
9192
auto allPtrsScalarsAndVectors = {
92-
p0, p1, p2, p3, p4, p5, p6, p7, p8,
93-
p10, p11, s1, s8, s16, s32, s64, v2s1, v2s8,
94-
v2s16, v2s32, v2s64, v3s1, v3s8, v3s16, v3s32, v3s64, v4s1,
95-
v4s8, v4s16, v4s32, v4s64, v8s1, v8s8, v8s16, v8s32, v8s64,
96-
v16s1, v16s8, v16s16, v16s32, v16s64};
93+
p0, p1, p2, p3, p4, p5, p6, p7, p8,
94+
p10, p11, p12, s1, s8, s16, s32, s64, v2s1,
95+
v2s8, v2s16, v2s32, v2s64, v3s1, v3s8, v3s16, v3s32, v3s64,
96+
v4s1, v4s8, v4s16, v4s32, v4s64, v8s1, v8s8, v8s16, v8s32,
97+
v8s64, v16s1, v16s8, v16s16, v16s32, v16s64};
9798

9899
auto allVectors = {v2s1, v2s8, v2s16, v2s32, v2s64, v3s1, v3s8,
99100
v3s16, v3s32, v3s64, v4s1, v4s8, v4s16, v4s32,
@@ -120,10 +121,10 @@ SPIRVLegalizerInfo::SPIRVLegalizerInfo(const SPIRVSubtarget &ST) {
120121
s16, s32, s64, v2s16, v2s32, v2s64, v3s16, v3s32, v3s64,
121122
v4s16, v4s32, v4s64, v8s16, v8s32, v8s64, v16s16, v16s32, v16s64};
122123

123-
auto allFloatAndIntScalarsAndPtrs = {s8, s16, s32, s64, p0, p1, p2, p3,
124-
p4, p5, p6, p7, p8, p10, p11};
124+
auto allFloatAndIntScalarsAndPtrs = {s8, s16, s32, s64, p0, p1, p2, p3,
125+
p4, p5, p6, p7, p8, p10, p11, p12};
125126

126-
auto allPtrs = {p0, p1, p2, p3, p4, p5, p6, p7, p8, p10, p11};
127+
auto allPtrs = {p0, p1, p2, p3, p4, p5, p6, p7, p8, p10, p11, p12};
127128

128129
bool IsExtendedInts =
129130
ST.canUseExtension(

llvm/lib/Target/SPIRV/SPIRVUtils.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,8 @@ addressSpaceToStorageClass(unsigned AddrSpace, const SPIRVSubtarget &STI) {
262262
return SPIRV::StorageClass::Private;
263263
case 11:
264264
return SPIRV::StorageClass::StorageBuffer;
265+
case 12:
266+
return SPIRV::StorageClass::Uniform;
265267
default:
266268
report_fatal_error("Unknown address space");
267269
}

llvm/lib/Target/SPIRV/SPIRVUtils.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,8 @@ storageClassToAddressSpace(SPIRV::StorageClass::StorageClass SC) {
210210
return 10;
211211
case SPIRV::StorageClass::StorageBuffer:
212212
return 11;
213+
case SPIRV::StorageClass::Uniform:
214+
return 12;
213215
default:
214216
report_fatal_error("Unable to get address space id");
215217
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
; RUN: llc -O0 -verify-machineinstrs -mtriple=spirv1.6-unknown-vulkan1.3-library %s -o - | FileCheck %s
2+
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv1.6-unknown-vulkan1.3-library %s -o - -filetype=obj | spirv-val %}
3+
4+
target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64-G10"
5+
6+
; CHECK-DAG: OpName [[standard_layout:%[0-9]+]] "standard_layout"
7+
; CHECK-DAG: OpMemberDecorate [[standard_layout]] 0 Offset 0
8+
; CHECK-DAG: OpMemberDecorate [[standard_layout]] 1 Offset 4
9+
10+
; CHECK-DAG: OpName [[standard_layout_with_different_offset:%[0-9]+]] "standard_layout"
11+
; CHECK-DAG: OpMemberDecorate [[standard_layout_with_different_offset]] 0 Offset 0
12+
; CHECK-DAG: OpMemberDecorate [[standard_layout_with_different_offset]] 1 Offset 8
13+
%standard_layout = type { i32, i32 }
14+
15+
; CHECK-DAG: OpName [[backwards_layout:%[0-9]+]] "backwards_layout"
16+
; CHECK-DAG: OpMemberDecorate [[backwards_layout]] 0 Offset 4
17+
; CHECK-DAG: OpMemberDecorate [[backwards_layout]] 1 Offset 0
18+
%backwards_layout = type { i32, i32 }
19+
20+
; CHECK-DAG: OpName [[large_gap:%[0-9]+]] "large_gap"
21+
; CHECK-DAG: OpMemberDecorate [[large_gap]] 0 Offset 0
22+
; CHECK-DAG: OpMemberDecorate [[large_gap]] 1 Offset 64
23+
; CHECK-DAG: OpMemberDecorate [[large_gap]] 2 Offset 1020
24+
; CHECK-DAG: OpMemberDecorate [[large_gap]] 3 Offset 4
25+
%large_gap = type { i32, i32, i32, i32 }
26+
27+
; CHECK-DAG: OpName [[mixed_layout:%[0-9]+]] "mixed_layout"
28+
; CHECK-DAG: OpMemberDecorate [[mixed_layout]] 0 Offset 0
29+
; CHECK-DAG: OpMemberDecorate [[mixed_layout]] 1 Offset 8
30+
; CHECK-DAG: OpMemberDecorate [[mixed_layout]] 2 Offset 4
31+
; CHECK-DAG: OpMemberDecorate [[mixed_layout]] 3 Offset 12
32+
%mixed_layout = type { i32, i32, i32, i32 }
33+
34+
define void @main() local_unnamed_addr #1 {
35+
entry:
36+
%standard_handle = tail call target("spirv.VulkanBuffer", target("spirv.Layout", %standard_layout, 8, 0, 4), 2, 0) @llvm.spv.resource.handlefrombinding.tspirv.VulkanBuffer_tspirv.Layout_s___cblayout_Bs_8_0_4t_2_0t(i32 0, i32 1, i32 1, i32 0, i1 false)
37+
%standard_handle_with_different_offset = tail call target("spirv.VulkanBuffer", target("spirv.Layout", %standard_layout, 12, 0, 8), 2, 0) @llvm.spv.resource.handlefrombinding.tspirv.VulkanBuffer_tspirv.Layout_s___cblayout_Bs_8_0_4t_2_0t(i32 0, i32 1, i32 1, i32 0, i1 false)
38+
%backwards_handle = tail call target("spirv.VulkanBuffer", target("spirv.Layout", %backwards_layout, 8, 4, 0), 2, 0) @llvm.spv.resource.handlefrombinding.tspirv.VulkanBuffer_tspirv.Layout_s___cblayout_Bs_8_0_4t_2_0t(i32 0, i32 1, i32 1, i32 0, i1 false)
39+
%large_gap_handle = tail call target("spirv.VulkanBuffer", target("spirv.Layout", %large_gap, 1024, 0, 64, 1020, 4), 2, 0) @llvm.spv.resource.handlefrombinding.tspirv.VulkanBuffer_tspirv.Layout_s___cblayout_Bs_8_0_4t_2_0t(i32 0, i32 1, i32 1, i32 0, i1 false)
40+
%mixed_handle = tail call target("spirv.VulkanBuffer", target("spirv.Layout", %mixed_layout, 16, 0, 8, 4, 12), 2, 0) @llvm.spv.resource.handlefrombinding.tspirv.VulkanBuffer_tspirv.Layout_s___cblayout_Bs_8_0_4t_2_0t(i32 0, i32 1, i32 1, i32 0, i1 false)
41+
ret void
42+
}
43+
44+
attributes #1 = { mustprogress nofree noinline norecurse nosync nounwind willreturn memory(readwrite, argmem: write, inaccessiblemem: none) "approx-func-fp-math"="false" "frame-pointer"="all" "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
45+
46+
!llvm.module.flags = !{!0, !1}
47+
!llvm.ident = !{!2}
48+
49+
!0 = !{i32 1, !"wchar_size", i32 4}
50+
!1 = !{i32 7, !"frame-pointer", i32 2}
51+
!2 = !{!"clang version 21.0.0git ([email protected]:s-perron/llvm-project.git b02f2e80567af09576692554bc7ce048326dfd06)"}
52+
!3 = !{!4, !4, i64 0}
53+
!4 = !{!"int", !5, i64 0}
54+
!5 = !{!"omnipotent char", !6, i64 0}
55+
!6 = !{!"Simple C++ TBAA"}

0 commit comments

Comments
 (0)