Skip to content

Commit 5073733

Browse files
authored
[DirectX] Introduce dx.Padding type (llvm#160957)
This introduces the `dx.Padding` type as an alternative to the `dx.Layout` types that are currently used for cbuffers. Later, we'll remove the `dx.Layout` types completely, but making the backend handle either makes it easier to stage the necessary changes to get there. See llvm#147352 for details.
1 parent 8ebbb20 commit 5073733

File tree

14 files changed

+187
-35
lines changed

14 files changed

+187
-35
lines changed

llvm/include/llvm/Analysis/DXILResource.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,25 @@ class LayoutExtType : public TargetExtType {
243243
}
244244
};
245245

246+
/// The dx.Padding target extension type
247+
///
248+
/// `target("dx.Padding", NumBytes)`
249+
class PaddingExtType : public TargetExtType {
250+
public:
251+
PaddingExtType() = delete;
252+
PaddingExtType(const PaddingExtType &) = delete;
253+
PaddingExtType &operator=(const PaddingExtType &) = delete;
254+
255+
unsigned getNumBytes() const { return getIntParameter(0); }
256+
257+
static bool classof(const TargetExtType *T) {
258+
return T->getName() == "dx.Padding";
259+
}
260+
static bool classof(const Type *T) {
261+
return isa<TargetExtType>(T) && classof(cast<TargetExtType>(T));
262+
}
263+
};
264+
246265
//===----------------------------------------------------------------------===//
247266

248267
class ResourceTypeInfo {

llvm/lib/Analysis/DXILResource.cpp

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,38 @@ static StructType *getOrCreateElementStruct(Type *ElemType, StringRef Name) {
281281
return StructType::create(ElemType, Name);
282282
}
283283

284+
static Type *getTypeWithoutPadding(Type *Ty) {
285+
// Recursively remove padding from structures.
286+
if (auto *ST = dyn_cast<StructType>(Ty)) {
287+
LLVMContext &Ctx = Ty->getContext();
288+
SmallVector<Type *> ElementTypes;
289+
ElementTypes.reserve(ST->getNumElements());
290+
for (Type *ElTy : ST->elements()) {
291+
if (isa<PaddingExtType>(ElTy))
292+
continue;
293+
ElementTypes.push_back(getTypeWithoutPadding(ElTy));
294+
}
295+
296+
// Handle explicitly padded cbuffer arrays like { [ n x paddedty ], ty }
297+
if (ElementTypes.size() == 2)
298+
if (auto *AT = dyn_cast<ArrayType>(ElementTypes[0]))
299+
if (ElementTypes[1] == AT->getElementType())
300+
return ArrayType::get(ElementTypes[1], AT->getNumElements() + 1);
301+
302+
// If we only have a single element, don't wrap it in a struct.
303+
if (ElementTypes.size() == 1)
304+
return ElementTypes[0];
305+
306+
return StructType::get(Ctx, ElementTypes, /*IsPacked=*/false);
307+
}
308+
// Arrays just need to have their element type adjusted.
309+
if (auto *AT = dyn_cast<ArrayType>(Ty))
310+
return ArrayType::get(getTypeWithoutPadding(AT->getElementType()),
311+
AT->getNumElements());
312+
// Anything else should be good as is.
313+
return Ty;
314+
}
315+
284316
StructType *ResourceTypeInfo::createElementStruct(StringRef CBufferName) {
285317
SmallString<64> TypeName;
286318

@@ -334,14 +366,21 @@ StructType *ResourceTypeInfo::createElementStruct(StringRef CBufferName) {
334366
}
335367
case ResourceKind::CBuffer: {
336368
auto *RTy = cast<CBufferExtType>(HandleTy);
337-
LayoutExtType *LayoutType = cast<LayoutExtType>(RTy->getResourceType());
338-
StructType *Ty = cast<StructType>(LayoutType->getWrappedType());
339369
SmallString<64> Name = getResourceKindName(Kind);
340370
if (!CBufferName.empty()) {
341371
Name.append(".");
342372
Name.append(CBufferName);
343373
}
344-
return StructType::create(Ty->elements(), Name);
374+
375+
// TODO: Remove this when we update the frontend to use explicit padding.
376+
if (LayoutExtType *LayoutType =
377+
dyn_cast<LayoutExtType>(RTy->getResourceType())) {
378+
StructType *Ty = cast<StructType>(LayoutType->getWrappedType());
379+
return StructType::create(Ty->elements(), Name);
380+
}
381+
382+
return getOrCreateElementStruct(
383+
getTypeWithoutPadding(RTy->getResourceType()), Name);
345384
}
346385
case ResourceKind::Sampler: {
347386
auto *RTy = cast<SamplerExtType>(HandleTy);
@@ -454,10 +493,10 @@ uint32_t ResourceTypeInfo::getCBufferSize(const DataLayout &DL) const {
454493

455494
Type *ElTy = cast<CBufferExtType>(HandleTy)->getResourceType();
456495

496+
// TODO: Remove this when we update the frontend to use explicit padding.
457497
if (auto *LayoutTy = dyn_cast<LayoutExtType>(ElTy))
458498
return LayoutTy->getSize();
459499

460-
// TODO: What should we do with unannotated arrays?
461500
return DL.getTypeAllocSize(ElTy);
462501
}
463502

llvm/lib/IR/Type.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1034,6 +1034,10 @@ static TargetTypeInfo getTargetTypeInfo(const TargetExtType *Ty) {
10341034
}
10351035

10361036
// DirectX resources
1037+
if (Name == "dx.Padding")
1038+
return TargetTypeInfo(
1039+
ArrayType::get(Type::getInt8Ty(C), Ty->getIntParameter(0)),
1040+
TargetExtType::CanBeGlobal);
10371041
if (Name.starts_with("dx."))
10381042
return TargetTypeInfo(PointerType::get(C, 0), TargetExtType::CanBeGlobal,
10391043
TargetExtType::CanBeLocal,

llvm/test/Analysis/DXILResource/buffer-frombinding.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ define void @test_typedbuffer() {
150150
; CHECK: Kind: CBuffer
151151
; CHECK: CBuffer size: 4
152152

153-
%cb1 = call target("dx.CBuffer", target("dx.Layout", {float}, 4, 0))
153+
%cb1 = call target("dx.CBuffer", <{ [2 x <{ float, target("dx.Padding", 12) }>], float }>)
154154
@llvm.dx.resource.handlefrombinding(i32 1, i32 8, i32 1, i32 0, ptr @Constants.str)
155155
; CHECK: Resource [[CB1:[0-9]+]]:
156156
; CHECK: Name: Constants
@@ -161,7 +161,7 @@ define void @test_typedbuffer() {
161161
; CHECK: Size: 1
162162
; CHECK: Class: CBV
163163
; CHECK: Kind: CBuffer
164-
; CHECK: CBuffer size: 4
164+
; CHECK: CBuffer size: 36
165165

166166
; CHECK-NOT: Resource {{[0-9]+}}:
167167

llvm/test/CodeGen/DirectX/CBufferLoadLegacy-errors.ll

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@ declare void @f16_user(half)
1111
; CHECK-SAME: in function four64
1212
; CHECK-SAME: Type mismatch between intrinsic and DXIL op
1313
define void @four64() "hlsl.export" {
14-
%buffer = call target("dx.CBuffer", target("dx.Layout", {double}, 8, 0))
14+
%buffer = call target("dx.CBuffer", <{ double }>)
1515
@llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 1, i32 0, ptr null)
1616

1717
%load = call {double, double, double, double} @llvm.dx.resource.load.cbufferrow.4(
18-
target("dx.CBuffer", target("dx.Layout", {double}, 8, 0)) %buffer,
18+
target("dx.CBuffer", <{ double }>) %buffer,
1919
i32 0)
2020
%data = extractvalue {double, double, double, double} %load, 0
2121

@@ -28,11 +28,11 @@ define void @four64() "hlsl.export" {
2828
; CHECK-SAME: in function two32
2929
; CHECK-SAME: Type mismatch between intrinsic and DXIL op
3030
define void @two32() "hlsl.export" {
31-
%buffer = call target("dx.CBuffer", target("dx.Layout", {float}, 4, 0))
31+
%buffer = call target("dx.CBuffer", <{ float }>)
3232
@llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 1, i32 0, ptr null)
3333

3434
%load = call {float, float} @llvm.dx.resource.load.cbufferrow.2(
35-
target("dx.CBuffer", target("dx.Layout", {float}, 4, 0)) %buffer,
35+
target("dx.CBuffer", <{ float }>) %buffer,
3636
i32 0)
3737
%data = extractvalue {float, float} %load, 0
3838

@@ -41,5 +41,5 @@ define void @two32() "hlsl.export" {
4141
ret void
4242
}
4343

44-
declare { double, double, double, double } @llvm.dx.resource.load.cbufferrow.4.f64.f64.f64.f64.tdx.CBuffer_tdx.Layout_sl_f64s_8_0tt(target("dx.CBuffer", target("dx.Layout", { double }, 8, 0)), i32)
45-
declare { float, float } @llvm.dx.resource.load.cbufferrow.2.f32.f32.tdx.CBuffer_tdx.Layout_sl_f32s_4_0tt(target("dx.CBuffer", target("dx.Layout", { float }, 4, 0)), i32)
44+
declare { double, double, double, double } @llvm.dx.resource.load.cbufferrow.4.f64.f64.f64.f64.tdx.CBuffer_sl_f64st(target("dx.CBuffer", <{ double }>), i32)
45+
declare { float, float } @llvm.dx.resource.load.cbufferrow.2.f32.f32.tdx.CBuffer_sl_f32st(target("dx.CBuffer", <{ float }>), i32)

llvm/test/CodeGen/DirectX/CBufferLoadLegacy.ll

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@ declare void @f16_user(half)
88

99
; CHECK-LABEL: define void @loadf32
1010
define void @loadf32() {
11-
%buffer = call target("dx.CBuffer", target("dx.Layout", {float}, 4, 0))
11+
%buffer = call target("dx.CBuffer", <{ float }>)
1212
@llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 1, i32 0, ptr null)
1313

1414
; CHECK: [[DATA:%.*]] = call %dx.types.CBufRet.f32 @dx.op.cbufferLoadLegacy.f32(i32 59, %dx.types.Handle %{{.*}}, i32 0)
1515
%load = call {float, float, float, float} @llvm.dx.resource.load.cbufferrow.4(
16-
target("dx.CBuffer", target("dx.Layout", {float}, 4, 0)) %buffer,
16+
target("dx.CBuffer", <{ float }>) %buffer,
1717
i32 0)
1818
%data = extractvalue {float, float, float, float} %load, 0
1919

@@ -27,12 +27,12 @@ define void @loadf32() {
2727
; CHECK-LABEL: define void @loadf64
2828
define void @loadf64() {
2929
%buffer = call
30-
target("dx.CBuffer", target("dx.Layout", {double, double, double, double}, 64, 0, 8, 16, 24))
30+
target("dx.CBuffer", <{ <4 x double> }>)
3131
@llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 1, i32 0, ptr null)
3232

3333
; CHECK: [[DATA:%.*]] = call %dx.types.CBufRet.f64 @dx.op.cbufferLoadLegacy.f64(i32 59, %dx.types.Handle %{{.*}}, i32 1)
3434
%load = call {double, double} @llvm.dx.resource.load.cbufferrow.2(
35-
target("dx.CBuffer", target("dx.Layout", {double, double, double, double}, 64, 0, 8, 16, 24)) %buffer,
35+
target("dx.CBuffer", <{ <4 x double> }>) %buffer,
3636
i32 1)
3737
%data = extractvalue {double, double} %load, 1
3838

@@ -46,12 +46,12 @@ define void @loadf64() {
4646
; CHECK-LABEL: define void @loadf16
4747
define void @loadf16() {
4848
%buffer = call
49-
target("dx.CBuffer", target("dx.Layout", {half}, 2, 0))
49+
target("dx.CBuffer", <{ half }>)
5050
@llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 1, i32 0, ptr null)
5151

5252
; CHECK: [[DATA:%.*]] = call %dx.types.CBufRet.f16.8 @dx.op.cbufferLoadLegacy.f16(i32 59, %dx.types.Handle %{{.*}}, i32 0)
5353
%load = call {half, half, half, half, half, half, half, half} @llvm.dx.resource.load.cbufferrow.8(
54-
target("dx.CBuffer", target("dx.Layout", {half}, 2, 0)) %buffer,
54+
target("dx.CBuffer", <{ half }>) %buffer,
5555
i32 0)
5656
%data = extractvalue {half, half, half, half, half, half, half, half} %load, 0
5757

llvm/test/CodeGen/DirectX/ContainerData/PSVResources-order.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ define void @main() #0 {
1818
%srv0 = call target("dx.RawBuffer", i8, 0, 0)
1919
@llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i8_0_0t(
2020
i32 1, i32 8, i32 1, i32 0, ptr null)
21-
%cbuf = call target("dx.CBuffer", target("dx.Layout", {float}, 4, 0))
21+
%cbuf = call target("dx.CBuffer", <{ float }>)
2222
@llvm.dx.resource.handlefrombinding(i32 3, i32 2, i32 1, i32 0, ptr null)
2323
ret void
2424
}

llvm/test/CodeGen/DirectX/ContainerData/PSVResources.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ define void @main() #0 {
1414
; CHECK: Kind: CBuffer
1515
; CHECK: Flags:
1616
; CHECK: UsedByAtomic64: false
17-
%cbuf = call target("dx.CBuffer", target("dx.Layout", {float}, 4, 0))
17+
%cbuf = call target("dx.CBuffer", <{ float }>)
1818
@llvm.dx.resource.handlefrombinding(i32 3, i32 2, i32 1, i32 0, ptr null)
1919

2020
; ByteAddressBuffer Buf : register(t8, space1)

llvm/test/CodeGen/DirectX/CreateHandleFromBinding.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ define void @test_bindings() {
7272
; CHECK: call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle [[BUF5]], %dx.types.ResourceProperties { i32 10, i32 1033 }) #[[#ATTR]]
7373

7474
; cbuffer cb0 : register(b0) { int4 i; float4 f; }
75-
%cb0 = call target("dx.CBuffer", target("dx.Layout", {<4 x i32>, <4 x float>}, 32, 0, 16))
75+
%cb0 = call target("dx.CBuffer", <{ <4 x i32>, <4 x float> }>)
7676
@llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 1, i32 0, ptr null)
7777
; CHECK: [[BUF6:%.*]] = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 217, %dx.types.ResBind { i32 0, i32 0, i32 0, i8 2 }, i32 0, i1 false) #[[#ATTR]]
7878
; CHECK: call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle [[BUF6]], %dx.types.ResourceProperties { i32 13, i32 32 }) #[[#ATTR]]

llvm/test/CodeGen/DirectX/ForwardHandleAccesses/cbuffer-access.ll

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,27 +4,27 @@
44
%__cblayout_CB2 = type <{ float }>
55
%struct.Scalars = type { float, i32, i32 }
66

7-
@CB.cb = local_unnamed_addr global target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 12, 0, 4, 8)) poison
8-
@CB2.cb = local_unnamed_addr global target("dx.CBuffer", target("dx.Layout", %__cblayout_CB2, 4, 0)) poison
7+
@CB.cb = local_unnamed_addr global target("dx.CBuffer", %__cblayout_CB) poison
8+
@CB2.cb = local_unnamed_addr global target("dx.CBuffer", %__cblayout_CB2) poison
99

1010
define void @main() local_unnamed_addr #1 {
1111
entry:
1212
; CHECK: [[CB:%.*]] = tail call target({{.*}}) @llvm.dx.resource.handlefrombinding
13-
%h = tail call target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 12, 0, 4, 8)) @llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 1, i32 0, ptr null)
14-
store target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 12, 0, 4, 8)) %h, ptr @CB.cb, align 4
13+
%h = tail call target("dx.CBuffer", %__cblayout_CB) @llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 1, i32 0, ptr null)
14+
store target("dx.CBuffer", %__cblayout_CB) %h, ptr @CB.cb, align 4
1515
%_ZL3Out_h.i.i = tail call target("dx.RawBuffer", %struct.Scalars, 1, 0) @llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 1, i32 0, ptr null)
1616
; CHECK-NOT: load target({{.*}}), ptr @CB.cb
17-
%cb = load target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 12, 0, 4, 8)), ptr @CB.cb, align 4
17+
%cb = load target("dx.CBuffer", %__cblayout_CB), ptr @CB.cb, align 4
1818
; CHECK: call { float, float, float, float } @llvm.dx.resource.load.cbufferrow.4.{{.*}}(target({{.*}}) [[CB]], i32 0)
19-
%0 = call { float, float, float, float } @llvm.dx.resource.load.cbufferrow.4(target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 12, 0, 4, 8)) %cb, i32 0)
19+
%0 = call { float, float, float, float } @llvm.dx.resource.load.cbufferrow.4(target("dx.CBuffer", %__cblayout_CB) %cb, i32 0)
2020
%1 = extractvalue { float, float, float, float } %0, 0
2121
call void @llvm.dx.resource.store.rawbuffer(target("dx.RawBuffer", %struct.Scalars, 1, 0) %_ZL3Out_h.i.i, i32 0, i32 0, float %1)
22-
22+
2323
; CHECK: [[CB2:%.*]] = tail call target({{.*}}) @llvm.dx.resource.handlefromimplicitbinding
24-
%h2 = tail call target("dx.CBuffer", target("dx.Layout", %__cblayout_CB2, 4, 0)) @llvm.dx.resource.handlefromimplicitbinding(i32 100, i32 0, i32 1, i32 0, ptr null)
25-
store target("dx.CBuffer", target("dx.Layout", %__cblayout_CB2, 4, 0)) %h2, ptr @CB2.cb, align 4
24+
%h2 = tail call target("dx.CBuffer", %__cblayout_CB2) @llvm.dx.resource.handlefromimplicitbinding(i32 100, i32 0, i32 1, i32 0, ptr null)
25+
store target("dx.CBuffer", %__cblayout_CB2) %h2, ptr @CB2.cb, align 4
2626
; CHECK-NOT: load target({{.*}}), ptr @CB2.cb
27-
%cb2 = load target("dx.CBuffer", target("dx.Layout", %__cblayout_CB2, 4, 0)), ptr @CB2.cb, align 4
27+
%cb2 = load target("dx.CBuffer", %__cblayout_CB2), ptr @CB2.cb, align 4
2828

2929
ret void
3030
}

0 commit comments

Comments
 (0)