[llvm-branch-commits] [llvm] [DirectX] Introduce `dx.Padding` type (PR #160957)
Justin Bogner via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Sun Sep 28 09:40:25 PDT 2025
https://github.com/bogner updated https://github.com/llvm/llvm-project/pull/160957
>From d8512f795eb6034050044ebbab3a7dfa44b133dc Mon Sep 17 00:00:00 2001
From: Justin Bogner <mail at justinbogner.com>
Date: Thu, 7 Aug 2025 15:02:49 -0700
Subject: [PATCH 1/2] [DirectX] Introduce `dx.Padding` type
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 #147352 for details.
---
llvm/include/llvm/Analysis/DXILResource.h | 19 +++++
llvm/lib/Analysis/DXILResource.cpp | 47 ++++++++++-
llvm/lib/IR/Type.cpp | 4 +
.../DXILResource/buffer-frombinding.ll | 4 +-
.../DirectX/CBufferLoadLegacy-errors.ll | 12 +--
.../test/CodeGen/DirectX/CBufferLoadLegacy.ll | 12 +--
.../ContainerData/PSVResources-order.ll | 2 +-
.../DirectX/ContainerData/PSVResources.ll | 2 +-
.../DirectX/CreateHandleFromBinding.ll | 2 +-
.../ForwardHandleAccesses/cbuffer-access.ll | 20 ++---
...ffer_metadata.ll => cbuffer-layouttype.ll} | 3 +
.../DirectX/Metadata/cbuffer-metadata.ll | 84 +++++++++++++++++++
.../CodeGen/DirectX/Metadata/cbuffer-only.ll | 2 +-
llvm/unittests/Analysis/DXILResourceTest.cpp | 4 +-
14 files changed, 182 insertions(+), 35 deletions(-)
rename llvm/test/CodeGen/DirectX/Metadata/{cbuffer_metadata.ll => cbuffer-layouttype.ll} (96%)
create mode 100644 llvm/test/CodeGen/DirectX/Metadata/cbuffer-metadata.ll
diff --git a/llvm/include/llvm/Analysis/DXILResource.h b/llvm/include/llvm/Analysis/DXILResource.h
index 88ac0a11fe5a2..c7aff167324e6 100644
--- a/llvm/include/llvm/Analysis/DXILResource.h
+++ b/llvm/include/llvm/Analysis/DXILResource.h
@@ -243,6 +243,25 @@ class LayoutExtType : public TargetExtType {
}
};
+/// The dx.Padding target extension type
+///
+/// `target("dx.Padding", NumBytes)`
+class PaddingExtType : public TargetExtType {
+public:
+ PaddingExtType() = delete;
+ PaddingExtType(const PaddingExtType &) = delete;
+ PaddingExtType &operator=(const PaddingExtType &) = delete;
+
+ unsigned getNumBytes() const { return getIntParameter(0); }
+
+ static bool classof(const TargetExtType *T) {
+ return T->getName() == "dx.Padding";
+ }
+ static bool classof(const Type *T) {
+ return isa<TargetExtType>(T) && classof(cast<TargetExtType>(T));
+ }
+};
+
//===----------------------------------------------------------------------===//
class ResourceTypeInfo {
diff --git a/llvm/lib/Analysis/DXILResource.cpp b/llvm/lib/Analysis/DXILResource.cpp
index b78cc03e34dbc..f9bf09262dd1f 100644
--- a/llvm/lib/Analysis/DXILResource.cpp
+++ b/llvm/lib/Analysis/DXILResource.cpp
@@ -281,6 +281,38 @@ static StructType *getOrCreateElementStruct(Type *ElemType, StringRef Name) {
return StructType::create(ElemType, Name);
}
+static Type *getTypeWithoutPadding(Type *Ty) {
+ // Recursively remove padding from structures.
+ if (auto *ST = dyn_cast<StructType>(Ty)) {
+ LLVMContext &Ctx = Ty->getContext();
+ SmallVector<Type *> ElementTypes;
+ ElementTypes.reserve(ST->getNumElements());
+ for (Type *ElTy : ST->elements()) {
+ if (isa<PaddingExtType>(ElTy))
+ continue;
+ ElementTypes.push_back(getTypeWithoutPadding(ElTy));
+ }
+
+ // Handle explicitly padded cbuffer arrays like { [ n x paddedty ], ty }
+ if (ElementTypes.size() == 2)
+ if (auto *AT = dyn_cast<ArrayType>(ElementTypes[0]))
+ if (ElementTypes[1] == AT->getElementType())
+ return ArrayType::get(ElementTypes[1], AT->getNumElements() + 1);
+
+ // If we only have a single element, don't wrap it in a struct.
+ if (ElementTypes.size() == 1)
+ return ElementTypes[0];
+
+ return StructType::get(Ctx, ElementTypes, /*IsPacked=*/false);
+ }
+ // Arrays just need to have their element type adjusted.
+ if (auto *AT = dyn_cast<ArrayType>(Ty))
+ return ArrayType::get(getTypeWithoutPadding(AT->getElementType()),
+ AT->getNumElements());
+ // Anything else should be good as is.
+ return Ty;
+}
+
StructType *ResourceTypeInfo::createElementStruct(StringRef CBufferName) {
SmallString<64> TypeName;
@@ -334,14 +366,21 @@ StructType *ResourceTypeInfo::createElementStruct(StringRef CBufferName) {
}
case ResourceKind::CBuffer: {
auto *RTy = cast<CBufferExtType>(HandleTy);
- LayoutExtType *LayoutType = cast<LayoutExtType>(RTy->getResourceType());
- StructType *Ty = cast<StructType>(LayoutType->getWrappedType());
SmallString<64> Name = getResourceKindName(Kind);
if (!CBufferName.empty()) {
Name.append(".");
Name.append(CBufferName);
}
- return StructType::create(Ty->elements(), Name);
+
+ // TODO: Remove this when we update the frontend to use explicit padding.
+ if (LayoutExtType *LayoutType =
+ dyn_cast<LayoutExtType>(RTy->getResourceType())) {
+ StructType *Ty = cast<StructType>(LayoutType->getWrappedType());
+ return StructType::create(Ty->elements(), Name);
+ }
+
+ return getOrCreateElementStruct(
+ getTypeWithoutPadding(RTy->getResourceType()), Name);
}
case ResourceKind::Sampler: {
auto *RTy = cast<SamplerExtType>(HandleTy);
@@ -454,10 +493,10 @@ uint32_t ResourceTypeInfo::getCBufferSize(const DataLayout &DL) const {
Type *ElTy = cast<CBufferExtType>(HandleTy)->getResourceType();
+ // TODO: Remove this when we update the frontend to use explicit padding.
if (auto *LayoutTy = dyn_cast<LayoutExtType>(ElTy))
return LayoutTy->getSize();
- // TODO: What should we do with unannotated arrays?
return DL.getTypeAllocSize(ElTy);
}
diff --git a/llvm/lib/IR/Type.cpp b/llvm/lib/IR/Type.cpp
index 9db48e8f6a96b..0e9535d24a4cc 100644
--- a/llvm/lib/IR/Type.cpp
+++ b/llvm/lib/IR/Type.cpp
@@ -1034,6 +1034,10 @@ static TargetTypeInfo getTargetTypeInfo(const TargetExtType *Ty) {
}
// DirectX resources
+ if (Name == "dx.Padding")
+ return TargetTypeInfo(
+ ArrayType::get(Type::getInt8Ty(C), Ty->getIntParameter(0)),
+ TargetExtType::CanBeGlobal);
if (Name.starts_with("dx."))
return TargetTypeInfo(PointerType::get(C, 0), TargetExtType::CanBeGlobal,
TargetExtType::CanBeLocal,
diff --git a/llvm/test/Analysis/DXILResource/buffer-frombinding.ll b/llvm/test/Analysis/DXILResource/buffer-frombinding.ll
index aeeb21ebb3201..ab1945d2921cc 100644
--- a/llvm/test/Analysis/DXILResource/buffer-frombinding.ll
+++ b/llvm/test/Analysis/DXILResource/buffer-frombinding.ll
@@ -150,7 +150,7 @@ define void @test_typedbuffer() {
; CHECK: Kind: CBuffer
; CHECK: CBuffer size: 4
- %cb1 = call target("dx.CBuffer", target("dx.Layout", {float}, 4, 0))
+ %cb1 = call target("dx.CBuffer", <{ [2 x <{ float, target("dx.Padding", 12) }>], float }>)
@llvm.dx.resource.handlefrombinding(i32 1, i32 8, i32 1, i32 0, ptr @Constants.str)
; CHECK: Resource [[CB1:[0-9]+]]:
; CHECK: Name: Constants
@@ -161,7 +161,7 @@ define void @test_typedbuffer() {
; CHECK: Size: 1
; CHECK: Class: CBV
; CHECK: Kind: CBuffer
- ; CHECK: CBuffer size: 4
+ ; CHECK: CBuffer size: 36
; CHECK-NOT: Resource {{[0-9]+}}:
diff --git a/llvm/test/CodeGen/DirectX/CBufferLoadLegacy-errors.ll b/llvm/test/CodeGen/DirectX/CBufferLoadLegacy-errors.ll
index 71dcf11b9dc88..196560f551f5f 100644
--- a/llvm/test/CodeGen/DirectX/CBufferLoadLegacy-errors.ll
+++ b/llvm/test/CodeGen/DirectX/CBufferLoadLegacy-errors.ll
@@ -11,11 +11,11 @@ declare void @f16_user(half)
; CHECK-SAME: in function four64
; CHECK-SAME: Type mismatch between intrinsic and DXIL op
define void @four64() "hlsl.export" {
- %buffer = call target("dx.CBuffer", target("dx.Layout", {double}, 8, 0))
+ %buffer = call target("dx.CBuffer", <{ double }>)
@llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 1, i32 0, ptr null)
%load = call {double, double, double, double} @llvm.dx.resource.load.cbufferrow.4(
- target("dx.CBuffer", target("dx.Layout", {double}, 8, 0)) %buffer,
+ target("dx.CBuffer", <{ double }>) %buffer,
i32 0)
%data = extractvalue {double, double, double, double} %load, 0
@@ -28,11 +28,11 @@ define void @four64() "hlsl.export" {
; CHECK-SAME: in function two32
; CHECK-SAME: Type mismatch between intrinsic and DXIL op
define void @two32() "hlsl.export" {
- %buffer = call target("dx.CBuffer", target("dx.Layout", {float}, 4, 0))
+ %buffer = call target("dx.CBuffer", <{ float }>)
@llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 1, i32 0, ptr null)
%load = call {float, float} @llvm.dx.resource.load.cbufferrow.2(
- target("dx.CBuffer", target("dx.Layout", {float}, 4, 0)) %buffer,
+ target("dx.CBuffer", <{ float }>) %buffer,
i32 0)
%data = extractvalue {float, float} %load, 0
@@ -41,5 +41,5 @@ define void @two32() "hlsl.export" {
ret void
}
-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)
-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)
+declare { double, double, double, double } @llvm.dx.resource.load.cbufferrow.4.f64.f64.f64.f64.tdx.CBuffer_sl_f64st(target("dx.CBuffer", <{ double }>), i32)
+declare { float, float } @llvm.dx.resource.load.cbufferrow.2.f32.f32.tdx.CBuffer_sl_f32st(target("dx.CBuffer", <{ float }>), i32)
diff --git a/llvm/test/CodeGen/DirectX/CBufferLoadLegacy.ll b/llvm/test/CodeGen/DirectX/CBufferLoadLegacy.ll
index d6906516b716d..dd40aa8d8d31c 100644
--- a/llvm/test/CodeGen/DirectX/CBufferLoadLegacy.ll
+++ b/llvm/test/CodeGen/DirectX/CBufferLoadLegacy.ll
@@ -8,12 +8,12 @@ declare void @f16_user(half)
; CHECK-LABEL: define void @loadf32
define void @loadf32() {
- %buffer = call target("dx.CBuffer", target("dx.Layout", {float}, 4, 0))
+ %buffer = call target("dx.CBuffer", <{ float }>)
@llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 1, i32 0, ptr null)
; CHECK: [[DATA:%.*]] = call %dx.types.CBufRet.f32 @dx.op.cbufferLoadLegacy.f32(i32 59, %dx.types.Handle %{{.*}}, i32 0)
%load = call {float, float, float, float} @llvm.dx.resource.load.cbufferrow.4(
- target("dx.CBuffer", target("dx.Layout", {float}, 4, 0)) %buffer,
+ target("dx.CBuffer", <{ float }>) %buffer,
i32 0)
%data = extractvalue {float, float, float, float} %load, 0
@@ -27,12 +27,12 @@ define void @loadf32() {
; CHECK-LABEL: define void @loadf64
define void @loadf64() {
%buffer = call
- target("dx.CBuffer", target("dx.Layout", {double, double, double, double}, 64, 0, 8, 16, 24))
+ target("dx.CBuffer", <{ <4 x double> }>)
@llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 1, i32 0, ptr null)
; CHECK: [[DATA:%.*]] = call %dx.types.CBufRet.f64 @dx.op.cbufferLoadLegacy.f64(i32 59, %dx.types.Handle %{{.*}}, i32 1)
%load = call {double, double} @llvm.dx.resource.load.cbufferrow.2(
- target("dx.CBuffer", target("dx.Layout", {double, double, double, double}, 64, 0, 8, 16, 24)) %buffer,
+ target("dx.CBuffer", <{ <4 x double> }>) %buffer,
i32 1)
%data = extractvalue {double, double} %load, 1
@@ -46,12 +46,12 @@ define void @loadf64() {
; CHECK-LABEL: define void @loadf16
define void @loadf16() {
%buffer = call
- target("dx.CBuffer", target("dx.Layout", {half}, 2, 0))
+ target("dx.CBuffer", <{ half }>)
@llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 1, i32 0, ptr null)
; CHECK: [[DATA:%.*]] = call %dx.types.CBufRet.f16.8 @dx.op.cbufferLoadLegacy.f16(i32 59, %dx.types.Handle %{{.*}}, i32 0)
%load = call {half, half, half, half, half, half, half, half} @llvm.dx.resource.load.cbufferrow.8(
- target("dx.CBuffer", target("dx.Layout", {half}, 2, 0)) %buffer,
+ target("dx.CBuffer", <{ half }>) %buffer,
i32 0)
%data = extractvalue {half, half, half, half, half, half, half, half} %load, 0
diff --git a/llvm/test/CodeGen/DirectX/ContainerData/PSVResources-order.ll b/llvm/test/CodeGen/DirectX/ContainerData/PSVResources-order.ll
index bcf82a67a55df..5cd67be1a4a28 100644
--- a/llvm/test/CodeGen/DirectX/ContainerData/PSVResources-order.ll
+++ b/llvm/test/CodeGen/DirectX/ContainerData/PSVResources-order.ll
@@ -18,7 +18,7 @@ define void @main() #0 {
%srv0 = call target("dx.RawBuffer", i8, 0, 0)
@llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i8_0_0t(
i32 1, i32 8, i32 1, i32 0, ptr null)
- %cbuf = call target("dx.CBuffer", target("dx.Layout", {float}, 4, 0))
+ %cbuf = call target("dx.CBuffer", <{ float }>)
@llvm.dx.resource.handlefrombinding(i32 3, i32 2, i32 1, i32 0, ptr null)
ret void
}
diff --git a/llvm/test/CodeGen/DirectX/ContainerData/PSVResources.ll b/llvm/test/CodeGen/DirectX/ContainerData/PSVResources.ll
index bea03102e4ccf..a1beccab68f5d 100644
--- a/llvm/test/CodeGen/DirectX/ContainerData/PSVResources.ll
+++ b/llvm/test/CodeGen/DirectX/ContainerData/PSVResources.ll
@@ -14,7 +14,7 @@ define void @main() #0 {
; CHECK: Kind: CBuffer
; CHECK: Flags:
; CHECK: UsedByAtomic64: false
- %cbuf = call target("dx.CBuffer", target("dx.Layout", {float}, 4, 0))
+ %cbuf = call target("dx.CBuffer", <{ float }>)
@llvm.dx.resource.handlefrombinding(i32 3, i32 2, i32 1, i32 0, ptr null)
; ByteAddressBuffer Buf : register(t8, space1)
diff --git a/llvm/test/CodeGen/DirectX/CreateHandleFromBinding.ll b/llvm/test/CodeGen/DirectX/CreateHandleFromBinding.ll
index 38f2de28dbe59..671fcef281314 100644
--- a/llvm/test/CodeGen/DirectX/CreateHandleFromBinding.ll
+++ b/llvm/test/CodeGen/DirectX/CreateHandleFromBinding.ll
@@ -72,7 +72,7 @@ define void @test_bindings() {
; CHECK: call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle [[BUF5]], %dx.types.ResourceProperties { i32 10, i32 1033 }) #[[#ATTR]]
; cbuffer cb0 : register(b0) { int4 i; float4 f; }
- %cb0 = call target("dx.CBuffer", target("dx.Layout", {<4 x i32>, <4 x float>}, 32, 0, 16))
+ %cb0 = call target("dx.CBuffer", <{ <4 x i32>, <4 x float> }>)
@llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 1, i32 0, ptr null)
; 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]]
; CHECK: call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle [[BUF6]], %dx.types.ResourceProperties { i32 13, i32 32 }) #[[#ATTR]]
diff --git a/llvm/test/CodeGen/DirectX/ForwardHandleAccesses/cbuffer-access.ll b/llvm/test/CodeGen/DirectX/ForwardHandleAccesses/cbuffer-access.ll
index 26b157f35a3e4..d67486324d220 100644
--- a/llvm/test/CodeGen/DirectX/ForwardHandleAccesses/cbuffer-access.ll
+++ b/llvm/test/CodeGen/DirectX/ForwardHandleAccesses/cbuffer-access.ll
@@ -4,27 +4,27 @@
%__cblayout_CB2 = type <{ float }>
%struct.Scalars = type { float, i32, i32 }
- at CB.cb = local_unnamed_addr global target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 12, 0, 4, 8)) poison
- at CB2.cb = local_unnamed_addr global target("dx.CBuffer", target("dx.Layout", %__cblayout_CB2, 4, 0)) poison
+ at CB.cb = local_unnamed_addr global target("dx.CBuffer", %__cblayout_CB) poison
+ at CB2.cb = local_unnamed_addr global target("dx.CBuffer", %__cblayout_CB2) poison
define void @main() local_unnamed_addr #1 {
entry:
; CHECK: [[CB:%.*]] = tail call target({{.*}}) @llvm.dx.resource.handlefrombinding
- %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)
- store target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 12, 0, 4, 8)) %h, ptr @CB.cb, align 4
+ %h = tail call target("dx.CBuffer", %__cblayout_CB) @llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 1, i32 0, ptr null)
+ store target("dx.CBuffer", %__cblayout_CB) %h, ptr @CB.cb, align 4
%_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)
; CHECK-NOT: load target({{.*}}), ptr @CB.cb
- %cb = load target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 12, 0, 4, 8)), ptr @CB.cb, align 4
+ %cb = load target("dx.CBuffer", %__cblayout_CB), ptr @CB.cb, align 4
; CHECK: call { float, float, float, float } @llvm.dx.resource.load.cbufferrow.4.{{.*}}(target({{.*}}) [[CB]], i32 0)
- %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)
+ %0 = call { float, float, float, float } @llvm.dx.resource.load.cbufferrow.4(target("dx.CBuffer", %__cblayout_CB) %cb, i32 0)
%1 = extractvalue { float, float, float, float } %0, 0
call void @llvm.dx.resource.store.rawbuffer(target("dx.RawBuffer", %struct.Scalars, 1, 0) %_ZL3Out_h.i.i, i32 0, i32 0, float %1)
-
+
; CHECK: [[CB2:%.*]] = tail call target({{.*}}) @llvm.dx.resource.handlefromimplicitbinding
- %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)
- store target("dx.CBuffer", target("dx.Layout", %__cblayout_CB2, 4, 0)) %h2, ptr @CB2.cb, align 4
+ %h2 = tail call target("dx.CBuffer", %__cblayout_CB2) @llvm.dx.resource.handlefromimplicitbinding(i32 100, i32 0, i32 1, i32 0, ptr null)
+ store target("dx.CBuffer", %__cblayout_CB2) %h2, ptr @CB2.cb, align 4
; CHECK-NOT: load target({{.*}}), ptr @CB2.cb
- %cb2 = load target("dx.CBuffer", target("dx.Layout", %__cblayout_CB2, 4, 0)), ptr @CB2.cb, align 4
+ %cb2 = load target("dx.CBuffer", %__cblayout_CB2), ptr @CB2.cb, align 4
ret void
}
diff --git a/llvm/test/CodeGen/DirectX/Metadata/cbuffer_metadata.ll b/llvm/test/CodeGen/DirectX/Metadata/cbuffer-layouttype.ll
similarity index 96%
rename from llvm/test/CodeGen/DirectX/Metadata/cbuffer_metadata.ll
rename to llvm/test/CodeGen/DirectX/Metadata/cbuffer-layouttype.ll
index 7ba2ed2988312..6595e51992b48 100644
--- a/llvm/test/CodeGen/DirectX/Metadata/cbuffer_metadata.ll
+++ b/llvm/test/CodeGen/DirectX/Metadata/cbuffer-layouttype.ll
@@ -1,3 +1,6 @@
+; TODO: Remove this test once we've updated the frontend to use explicit
+; padding. The cbuffer-metadata.ll test covers the newer logic.
+
; RUN: opt -S -dxil-translate-metadata < %s | FileCheck %s
; RUN: opt -S --passes="dxil-pretty-printer" < %s 2>&1 | FileCheck %s --check-prefix=PRINT
; RUN: llc %s --filetype=asm -o - < %s 2>&1 | FileCheck %s --check-prefixes=CHECK,PRINT
diff --git a/llvm/test/CodeGen/DirectX/Metadata/cbuffer-metadata.ll b/llvm/test/CodeGen/DirectX/Metadata/cbuffer-metadata.ll
new file mode 100644
index 0000000000000..7d333a8c8807a
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/Metadata/cbuffer-metadata.ll
@@ -0,0 +1,84 @@
+; RUN: opt -S -dxil-translate-metadata < %s | FileCheck %s
+; RUN: opt -S --passes="dxil-pretty-printer" < %s 2>&1 | FileCheck %s --check-prefix=PRINT
+; RUN: llc %s --filetype=asm -o - < %s 2>&1 | FileCheck %s --check-prefixes=CHECK,PRINT
+
+target triple = "dxil-pc-shadermodel6.6-compute"
+
+%__cblayout_CB1 = type <{ float, i32, double, <2 x i32> }>
+ at CB1.cb = global target("dx.CBuffer", %__cblayout_CB1) poison
+ at CB1.str = private unnamed_addr constant [4 x i8] c"CB1\00", align 1
+
+%__cblayout_CB2 = type <{ float, [4 x i8], double, float, half, i16, i64, i32 }>
+ at CB2.cb = global target("dx.CBuffer", %__cblayout_CB2) poison
+ at CB2.str = private unnamed_addr constant [4 x i8] c"CB2\00", align 1
+
+%__cblayout_MyConstants = type <{
+ double, target("dx.Padding", 8),
+ <3 x float>, float,
+ <3 x double>, half, target("dx.Padding", 6),
+ <2 x double>,
+ float, <3 x half>, <3 x half>
+}>
+ at MyConstants.cb = global target("dx.CBuffer", %__cblayout_MyConstants) poison
+ at MyConstants.str = private unnamed_addr constant [12 x i8] c"MyConstants\00", align 1
+
+; PRINT:; Resource Bindings:
+; PRINT-NEXT:;
+; PRINT-NEXT:; Name Type Format Dim ID HLSL Bind Count
+; PRINT-NEXT:; ----
+; PRINT-NEXT:; CB1 cbuffer NA NA CB0 cb0 1
+; PRINT-NEXT:; CB2 cbuffer NA NA CB1 cb1 1
+; PRINT-NEXT:; MyConstants cbuffer NA NA CB2 cb5,space15 1
+
+define void @test() #0 {
+
+ ; cbuffer CB1 : register(b0) {
+ ; float a;
+ ; int b;
+ ; double c;
+ ; int2 d;
+ ; }
+ %CB1.cb_h = call target("dx.CBuffer", %__cblayout_CB1)
+ @llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 1, i32 0, ptr @CB1.str)
+ ; cbuffer CB2 : register(b0) {
+ ; float a;
+ ; double b;
+ ; float c;
+ ; half d;
+ ; uint16_t e;
+ ; int64_t f;
+ ; int g;
+ ;}
+
+ %CB2.cb_h = call target("dx.CBuffer", %__cblayout_CB2)
+ @llvm.dx.resource.handlefrombinding(i32 0, i32 1, i32 1, i32 0, ptr @CB2.str)
+ ; cbuffer CB3 : register(b5) {
+ ; double B0;
+ ; float3 B1;
+ ; float B2;
+ ; double3 B3;
+ ; half B4;
+ ; double2 B5;
+ ; float B6;
+ ; half3 B7;
+ ; half3 B8;
+ ; }
+ %CB3.cb_h = call target("dx.CBuffer", %__cblayout_MyConstants)
+ @llvm.dx.resource.handlefrombinding(i32 15, i32 5, i32 1, i32 0, ptr @MyConstants.str)
+
+ ret void
+}
+
+attributes #0 = { noinline nounwind "hlsl.shader"="compute" }
+
+; CHECK: @CB1 = external constant %CBuffer.CB1
+; CHECK: @CB2 = external constant %CBuffer.CB2
+; CHECK: @MyConstants = external constant %CBuffer.MyConstants
+
+; CHECK: !dx.resources = !{[[ResList:[!][0-9]+]]}
+
+; CHECK: [[ResList]] = !{null, null, [[CBList:[!][0-9]+]], null}
+; CHECK: [[CBList]] = !{![[CB1:[0-9]+]], ![[CB2:[0-9]+]], ![[MYCONSTANTS:[0-9]+]]}
+; CHECK: ![[CB1]] = !{i32 0, ptr @CB1, !"CB1", i32 0, i32 0, i32 1, i32 24, null}
+; CHECK: ![[CB2]] = !{i32 1, ptr @CB2, !"CB2", i32 0, i32 1, i32 1, i32 36, null}
+; CHECK: ![[MYCONSTANTS]] = !{i32 2, ptr @MyConstants, !"MyConstants", i32 15, i32 5, i32 1, i32 96, null}
diff --git a/llvm/test/CodeGen/DirectX/Metadata/cbuffer-only.ll b/llvm/test/CodeGen/DirectX/Metadata/cbuffer-only.ll
index e2a1c09c13038..0b454c12a74a2 100644
--- a/llvm/test/CodeGen/DirectX/Metadata/cbuffer-only.ll
+++ b/llvm/test/CodeGen/DirectX/Metadata/cbuffer-only.ll
@@ -7,7 +7,7 @@
target triple = "dxil-pc-shadermodel6.6-compute"
define void @cbuffer_is_only_binding() {
- %cbuf = call target("dx.CBuffer", target("dx.Layout", {float}, 4, 0))
+ %cbuf = call target("dx.CBuffer", <{ float }>)
@llvm.dx.resource.handlefrombinding(i32 1, i32 8, i32 1, i32 0, ptr null)
; CHECK: %CBuffer = type { float }
diff --git a/llvm/unittests/Analysis/DXILResourceTest.cpp b/llvm/unittests/Analysis/DXILResourceTest.cpp
index ee37fad04f389..8c3a2134ae0d6 100644
--- a/llvm/unittests/Analysis/DXILResourceTest.cpp
+++ b/llvm/unittests/Analysis/DXILResourceTest.cpp
@@ -369,10 +369,8 @@ TEST(DXILResource, AnnotationsAndMetadata) {
{
StructType *CBufStruct =
StructType::create(Context, {Floatx4Ty, Floatx4Ty}, "cb0");
- TargetExtType *CBufLayoutType =
- llvm::TargetExtType::get(Context, "dx.Layout", CBufStruct, {32, 0, 16});
ResourceTypeInfo RTI(
- llvm::TargetExtType::get(Context, "dx.CBuffer", CBufLayoutType));
+ llvm::TargetExtType::get(Context, "dx.CBuffer", CBufStruct));
EXPECT_EQ(RTI.getResourceClass(), ResourceClass::CBuffer);
EXPECT_EQ(RTI.getCBufferSize(DL), 32u);
EXPECT_EQ(RTI.getResourceKind(), ResourceKind::CBuffer);
>From 082cef0ec993675074490d6b50d5b5b356e8dd73 Mon Sep 17 00:00:00 2001
From: Justin Bogner <mail at justinbogner.com>
Date: Sun, 28 Sep 2025 09:39:46 -0700
Subject: [PATCH 2/2] fixup: whitespace and testing of filtered types
---
llvm/test/CodeGen/DirectX/Metadata/cbuffer-metadata.ll | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/llvm/test/CodeGen/DirectX/Metadata/cbuffer-metadata.ll b/llvm/test/CodeGen/DirectX/Metadata/cbuffer-metadata.ll
index 7d333a8c8807a..6b90e17816991 100644
--- a/llvm/test/CodeGen/DirectX/Metadata/cbuffer-metadata.ll
+++ b/llvm/test/CodeGen/DirectX/Metadata/cbuffer-metadata.ll
@@ -8,7 +8,7 @@ target triple = "dxil-pc-shadermodel6.6-compute"
@CB1.cb = global target("dx.CBuffer", %__cblayout_CB1) poison
@CB1.str = private unnamed_addr constant [4 x i8] c"CB1\00", align 1
-%__cblayout_CB2 = type <{ float, [4 x i8], double, float, half, i16, i64, i32 }>
+%__cblayout_CB2 = type <{ float, target("dx.Padding", 4), double, float, half, i16, i64, i32 }>
@CB2.cb = global target("dx.CBuffer", %__cblayout_CB2) poison
@CB2.str = private unnamed_addr constant [4 x i8] c"CB2\00", align 1
@@ -40,6 +40,7 @@ define void @test() #0 {
; }
%CB1.cb_h = call target("dx.CBuffer", %__cblayout_CB1)
@llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 1, i32 0, ptr @CB1.str)
+
; cbuffer CB2 : register(b0) {
; float a;
; double b;
@@ -49,9 +50,9 @@ define void @test() #0 {
; int64_t f;
; int g;
;}
-
%CB2.cb_h = call target("dx.CBuffer", %__cblayout_CB2)
@llvm.dx.resource.handlefrombinding(i32 0, i32 1, i32 1, i32 0, ptr @CB2.str)
+
; cbuffer CB3 : register(b5) {
; double B0;
; float3 B1;
@@ -71,6 +72,10 @@ define void @test() #0 {
attributes #0 = { noinline nounwind "hlsl.shader"="compute" }
+; CHECK: %CBuffer.CB1 = type { { float, i32, double, <2 x i32> } }
+; CHECK: %CBuffer.CB2 = type { { float, double, float, half, i16, i64, i32 } }
+; CHECK: %CBuffer.MyConstants = type { { double, <3 x float>, float, <3 x double>, half, <2 x double>, float, <3 x half>, <3 x half> } }
+
; CHECK: @CB1 = external constant %CBuffer.CB1
; CHECK: @CB2 = external constant %CBuffer.CB2
; CHECK: @MyConstants = external constant %CBuffer.MyConstants
More information about the llvm-branch-commits
mailing list