Skip to content

[HLSL][NFC] Update resource metadata tests to not use obsolete annotations #130222

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Mar 12, 2025

Conversation

hekota
Copy link
Member

@hekota hekota commented Mar 7, 2025

Update resource metadata tests to generate metadata based on llvm.dx.resource.handlefrombinding data collected in DXILResourceBindingAnalysis.

  • UAVMetadata.ll is updated, renamed to uav_metadata.ll, and placed under Metadata directory in llvm/test/CodeGen/DirectX
  • srv_metadata.ll is a new test for SRV resource metadata
  • cbuf.ll and legacy_cb_layout_{0|1}.ll tests were merged into cbuffer_metadata.ll
  • legacy_cb_layout_{2|3}.ll tests we moved to cbuffer.hlsl in Clang CodeGen because there were more of a layout than metadata tests

Related to #114126

@llvmbot llvmbot added clang Clang issues not falling into any other category backend:DirectX HLSL HLSL Language Support labels Mar 7, 2025
@llvmbot
Copy link
Member

llvmbot commented Mar 7, 2025

@llvm/pr-subscribers-clang

Author: Helena Kotas (hekota)

Changes

Update resource metadata tests to generate metadata based on llvm.dx.resource.handlefrombinding data collected in DXILResourceBindingAnalysis.

  • UAVMetadata.ll is renamed to uav_metadata.ll, updated and placed under Metadata directory in llvm/test/CodeGen/DirectX
  • srv_metadata.ll is a new test for SRV resource metadata
  • cbuf.ll and legacy_cb_layout_{0|1}.ll tests were merged and updated into cbuffer_metadata.ll
  • legacy_cb_layout_{2|3}.ll tests we moved to cbuffer.hlsl in Clang CodeGen because there were more of a layout than metadata tests

Related to #114126


Patch is 38.24 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/130222.diff

10 Files Affected:

  • (modified) clang/test/CodeGenHLSL/cbuffer.hlsl (+76-2)
  • (added) llvm/test/CodeGen/DirectX/Metadata/cbuffer_metadata.ll (+80)
  • (added) llvm/test/CodeGen/DirectX/Metadata/srv_metadata.ll (+103)
  • (added) llvm/test/CodeGen/DirectX/Metadata/uav_metadata.ll (+135)
  • (removed) llvm/test/CodeGen/DirectX/UAVMetadata.ll (-77)
  • (removed) llvm/test/CodeGen/DirectX/cbuf.ll (-37)
  • (removed) llvm/test/CodeGen/DirectX/legacy_cb_layout_0.ll (-14)
  • (removed) llvm/test/CodeGen/DirectX/legacy_cb_layout_1.ll (-37)
  • (removed) llvm/test/CodeGen/DirectX/legacy_cb_layout_2.ll (-51)
  • (removed) llvm/test/CodeGen/DirectX/legacy_cb_layout_3.ll (-81)
diff --git a/clang/test/CodeGenHLSL/cbuffer.hlsl b/clang/test/CodeGenHLSL/cbuffer.hlsl
index 38093c6dfacd7..b5e435619438f 100644
--- a/clang/test/CodeGenHLSL/cbuffer.hlsl
+++ b/clang/test/CodeGenHLSL/cbuffer.hlsl
@@ -20,6 +20,14 @@
 // CHECK: %anon = type <{ float }>
 // CHECK: %anon.0 = type <{ <2 x i32> }>
 
+// CHECK: %__cblayout_CB_A = type <{ [2 x double], [3 x <3 x float>], float, [3 x double], half, [1 x <2 x double>], float, [2 x <3 x half>], <3 x half> }>
+// CHECK: %__cblayout_CB_B = type <{ [3 x <3 x double>], <3 x half> }>
+// CHECK: %__cblayout_CB_C = type <{ i32, target("dx.Layout", %F, 96, 0, 16, 28, 32, 56, 64, 80, 84, 90), half, target("dx.Layout", %G, 258, 0, 48, 64, 256), double }>
+
+// CHECK: %F = type <{ double, <3 x float>, float, <3 x double>, half, <2 x double>, float, <3 x half>, <3 x half> }>
+// CHECK: %G = type <{ target("dx.Layout", %E, 36, 0, 8, 16, 20, 22, 24, 32), [1 x float], [2 x target("dx.Layout", %F, 96, 0, 16, 28, 32, 56, 64, 80, 84, 90)], half }>
+// CHECK: %E = type <{ float, double, float, half, i16, i64, i32 }>
+
 cbuffer CBScalars : register(b1, space5) {
   float a1;
   double a2;
@@ -155,6 +163,64 @@ cbuffer CBMix {
     uint16_t f9;
 };  
 
+// CHECK: @CB_A.cb = external constant target("dx.CBuffer", target("dx.Layout", %__cblayout_CB_A, 188, 0, 32, 76, 80, 120, 128, 144, 160, 182))
+
+cbuffer CB_A {
+  double B0[2];
+  float3 B1[3];
+  float B2;
+  double B3[3];
+  half B4;
+  double2 B5[1];
+  float B6;
+  half3 B7[2];
+  half3 B8;
+}
+
+// CHECK: @CB_B.cb = external constant target("dx.CBuffer", target("dx.Layout", %__cblayout_CB_B, 94, 0, 88))
+cbuffer CB_B {
+  double3 B9[3];
+  half3 B10;
+}
+
+struct E {
+  float A0;
+  double A1;
+  float A2;
+  half A3;
+  int16_t A4;
+  int64_t A5;
+  int A6;
+};
+
+struct F {
+  double B0;
+  float3 B1;
+  float B2;
+  double3 B3;
+  half B4;
+  double2 B5;
+  float B6;
+  half3 B7;
+  half3 B8;
+};
+
+struct G {
+  E C0;
+  float C1[1];
+  F C2[2];
+  half C3;
+};
+
+// CHECK: @CB_C.cb = external constant target("dx.CBuffer", target("dx.Layout", %__cblayout_CB_C, 400, 0, 16, 112, 128, 392))
+cbuffer CB_C {
+  int D0;
+  F D1;
+  half D2;
+  G D3;
+  double D4;
+}
+
 // CHECK: define internal void @_init_resource_CBScalars.cb()
 // CHECK-NEXT: entry:
 // CHECK-NEXT: %[[HANDLE1:.*]] = call target("dx.CBuffer", target("dx.Layout", %__cblayout_CBScalars, 56, 0, 8, 16, 24, 32, 36, 40, 48))
@@ -171,7 +237,7 @@ RWBuffer<float> Buf;
 
 [numthreads(4,1,1)]
 void main() {
-  Buf[0] = a1 + b1.z + c1[2] + a.f1.y + f1;
+  Buf[0] = a1 + b1.z + c1[2] + a.f1.y + f1 + B1[0].x + B10.z + D1.B2;
 }
 
 // CHECK: define internal void @_GLOBAL__sub_I_cbuffer.hlsl()
@@ -179,7 +245,8 @@ void main() {
 // CHECK-NEXT: call void @_init_resource_CBScalars.cb()
 // CHECK-NEXT: call void @_init_resource_CBArrays.cb()
 
-// CHECK: !hlsl.cbs = !{![[CBSCALARS:[0-9]+]], ![[CBVECTORS:[0-9]+]], ![[CBARRAYS:[0-9]+]], ![[CBSTRUCTS:[0-9]+]], ![[CBMIX:[0-9]+]]}
+// CHECK: !hlsl.cbs = !{![[CBSCALARS:[0-9]+]], ![[CBVECTORS:[0-9]+]], ![[CBARRAYS:[0-9]+]], ![[CBSTRUCTS:[0-9]+]], ![[CBMIX:[0-9]+]],
+// CHECK-SAME: ![[CB_A:[0-9]+]], ![[CB_B:[0-9]+]], ![[CB_C:[0-9]+]]}
 
 // CHECK: ![[CBSCALARS]] = !{ptr @CBScalars.cb, ptr addrspace(2) @a1, ptr addrspace(2) @a2, ptr addrspace(2) @a3, ptr addrspace(2) @a4,
 // CHECK-SAME: ptr addrspace(2) @a5, ptr addrspace(2) @a6, ptr addrspace(2) @a7, ptr addrspace(2) @a8}
@@ -195,3 +262,10 @@ void main() {
 
 // CHECK: ![[CBMIX]] = !{ptr @CBMix.cb, ptr addrspace(2) @test, ptr addrspace(2) @f1, ptr addrspace(2) @f2, ptr addrspace(2) @f3,
 // CHECK-SAME: ptr addrspace(2) @f4, ptr addrspace(2) @f5, ptr addrspace(2) @f6, ptr addrspace(2) @f7, ptr addrspace(2) @f8, ptr addrspace(2) @f9}
+
+// CHECK: ![[CB_A]] = !{ptr @CB_A.cb, ptr addrspace(2) @B0, ptr addrspace(2) @B1, ptr addrspace(2) @B2, ptr addrspace(2) @B3, ptr addrspace(2) @B4,
+// CHECK-SAME: ptr addrspace(2) @B5, ptr addrspace(2) @B6, ptr addrspace(2) @B7, ptr addrspace(2) @B8}
+
+// CHECK: ![[CB_B]] = !{ptr @CB_B.cb, ptr addrspace(2) @B9, ptr addrspace(2) @B10}
+
+// CHECK: ![[CB_C]] = !{ptr @CB_C.cb, ptr addrspace(2) @D0, ptr addrspace(2) @D1, ptr addrspace(2) @D2, ptr addrspace(2) @D3, ptr addrspace(2) @D4}
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..b3dda74bf8bbf
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/Metadata/cbuffer_metadata.ll
@@ -0,0 +1,80 @@
+; 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 datalayout = "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:32-f64:64-n8:16:32:64"
+target triple = "dxil-pc-shadermodel6.6-compute"
+
+%__cblayout_CB1 = type <{ float, i32, double, <2 x i32> }>
+@CB1.cb = external constant target("dx.CBuffer", target("dx.Layout", %__cblayout_CB1, 24, 0, 4, 8, 16))
+
+%__cblayout_CB2 = type <{ float, double, float, half, i16, i64, i32 }>
+@CB2.cb = external constant target("dx.CBuffer", target("dx.Layout", %__cblayout_CB2, 36, 0, 8, 16, 20, 22, 24, 32))
+
+%__cblayout_CB3 = type <{ double, <3 x float>, float, <3 x double>, half, <2 x double>, float, <3 x half>, <3 x half> }>
+@CB3.cb = external constant target("dx.CBuffer", target("dx.Layout", %__cblayout_CB3, 96, 0, 16, 28, 32, 56, 64, 80, 84, 90))
+
+; PRINT:; Resource Bindings:
+; PRINT-NEXT:;
+; PRINT-NEXT:; Name                                 Type  Format         Dim      ID      HLSL Bind  Count
+; PRINT-NEXT:; ------------------------------ ---------- ------- ----------- ------- -------------- ------
+; PRINT-NEXT:;                                   cbuffer      NA          NA     CB0            cb0     1
+; PRINT-NEXT:;                                   cbuffer      NA          NA     CB1            cb1     1
+; PRINT-NEXT:;                                   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", target("dx.Layout", %__cblayout_CB1, 24, 0, 4, 8, 16))
+            @llvm.dx.resource.handlefrombinding.tdx.CBuffer_tdx.Layout_s___cblayout_CB1s_24_0_4_8_16tt(
+                i32 0, i32 0, i32 1, i32 0, i1 false)
+  store target("dx.CBuffer", target("dx.Layout", %__cblayout_CB1, 24, 0, 4, 8, 16)) %CB1.cb_h, ptr @CB1.cb, align 4
+
+  ; 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", target("dx.Layout", %__cblayout_CB2, 36, 0, 8, 16, 20, 22, 24, 32))
+            @llvm.dx.resource.handlefrombinding.tdx.CBuffer_tdx.Layout_s___cblayout_CB2s_36_0_8_16_20_22_24_32tt(
+                i32 0, i32 1, i32 1, i32 0, i1 false)
+  store target("dx.CBuffer", target("dx.Layout", %__cblayout_CB2, 36, 0, 8, 16, 20, 22, 24, 32)) %CB2.cb_h, ptr @CB2.cb, align 4
+
+  ; 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", target("dx.Layout", %__cblayout_CB3, 96, 0, 16, 28, 32, 56, 64, 80, 84, 90))
+            @llvm.dx.resource.handlefrombinding.tdx.CBuffer_tdx.Layout_s___cblayout_CB3s_96_0_16_28_32_56_64_80_84_90tt(
+                i32 15, i32 5, i32 1, i32 0, i1 false)
+  store target("dx.CBuffer", target("dx.Layout", %__cblayout_CB3, 96, 0, 16, 28, 32, 56, 64, 80, 84, 90)) %CB3.cb_h, ptr @CB3.cb, align 4
+
+  ret void
+}
+
+attributes #0 = { noinline nounwind "hlsl.shader"="compute" }
+
+; CHECK: !dx.resources = !{[[ResList:[!][0-9]+]]}
+
+; CHECK: [[ResList]] = !{null, null, [[CBList:[!][0-9]+]], null}
+; CHECK: [[CBList]] = !{![[CB1:[0-9]+]], ![[CB2:[0-9]+]], ![[CB3:[0-9]+]]}
+; CHECK: ![[CB1]] = !{i32 0, ptr @0, !"", i32 0, i32 0, i32 1, i32 24, null}
+; CHECK: ![[CB2]] = !{i32 1, ptr @1, !"", i32 0, i32 1, i32 1, i32 36, null}
+; CHECK: ![[CB3]] = !{i32 2, ptr @2, !"", i32 15, i32 5, i32 1, i32 96, null}
diff --git a/llvm/test/CodeGen/DirectX/Metadata/srv_metadata.ll b/llvm/test/CodeGen/DirectX/Metadata/srv_metadata.ll
new file mode 100644
index 0000000000000..e1344035e01a7
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/Metadata/srv_metadata.ll
@@ -0,0 +1,103 @@
+; 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 datalayout = "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:32-f64:64-n8:16:32:64"
+target triple = "dxil-pc-shadermodel6.6-compute"
+
+%"class.hlsl::Buffer" = type { target("dx.TypedBuffer", <4 x half>, 0, 0, 0) }
+%"class.hlsl::Buffer.1" = type { target("dx.TypedBuffer", <2 x float>, 0, 0, 0) }
+%"class.hlsl::Buffer.2" = type { target("dx.TypedBuffer", double, 0, 0, 0) }
+%"class.hlsl::Buffer.3" = type { target("dx.TypedBuffer", i32, 0, 0, 1) }
+%"class.hlsl::ByteAddressBuffer" = type { target("dx.RawBuffer", i8, 0, 0) }
+%"class.hlsl::StructuredBuffer" = type { target("dx.RawBuffer", i16, 0, 0) }
+%"class.hlsl::Buffer.4" = type { target("dx.TypedBuffer", i64, 0, 0, 0) }
+
+@Zero = internal global %"class.hlsl::Buffer" poison, align 4
+@One = internal global %"class.hlsl::Buffer.1" poison, align 4
+@Two = internal global %"class.hlsl::Buffer.2" poison, align 4
+@Three = internal global %"class.hlsl::Buffer.3" poison, align 4
+@Four = internal global %"class.hlsl::ByteAddressBuffer" poison, align 4
+@Five = internal global %"class.hlsl::StructuredBuffer" poison, align 4
+@Six = internal global %"class.hlsl::Buffer.4" poison, align 4
+
+; PRINT:; Resource Bindings:
+; PRINT-NEXT:;
+; PRINT-NEXT:; Name                                 Type  Format         Dim      ID      HLSL Bind  Count
+; PRINT-NEXT:; ------------------------------ ---------- ------- ----------- ------- -------------- ------
+; PRINT-NEXT:;                                       SRV     f16         buf      T0             t0     1
+; PRINT-NEXT:;                                       SRV     f32         buf      T1             t1     1
+; PRINT-NEXT:;                                       SRV     f64         buf      T2             t2     1
+; PRINT-NEXT:;                                       SRV     i32         buf      T3             t3     1
+; PRINT-NEXT:;                                       SRV    byte         r/o      T4             t5     1
+; PRINT-NEXT:;                                       SRV  struct         r/o      T5             t6     1
+; PRINT-NEXT:;                                       SRV     u64         buf      T6     t10,space2     1
+
+define void @test() #0 {
+  ; RWBuffer<half4> Buf : register(u0)
+  %Zero_h = call target("dx.TypedBuffer", <4 x half>, 0, 0, 0)
+            @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_v4f16_0_0_0t(
+                  i32 0, i32 0, i32 1, i32 0, i1 false)
+  store target("dx.TypedBuffer", <4 x half>, 0, 0, 0) %Zero_h, ptr @Zero, align 4
+ 
+  ; RWBuffer<float4> Buf : register(u1)
+  %One_h = call target("dx.TypedBuffer", <2 x float>, 0, 0, 0)
+            @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_v2f32_0_0_0t(
+                  i32 0, i32 1, i32 1, i32 0, i1 false)
+  store target("dx.TypedBuffer", <2 x float>, 0, 0, 0) %One_h, ptr @One, align 4
+ 
+  ; RWBuffer<double> Two : register(u2);
+  %Two_h = call target("dx.TypedBuffer", double, 0, 0, 0)
+            @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f64_0_0_0t(
+                  i32 0, i32 2, i32 1, i32 0, i1 false)
+  store target("dx.TypedBuffer", double, 0, 0, 0) %Two_h, ptr @Two, align 4
+
+  ; RWBuffer<int4> Three : register(u3);
+  %Three_h = call target("dx.TypedBuffer", <4 x i32>, 0, 0, 1)
+            @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_i32_0_0_1t(
+                  i32 0, i32 3, i32 1, i32 0, i1 false)
+  store target("dx.TypedBuffer", <4 x i32>, 0, 0, 1) %Three_h, ptr @Three, align 4
+
+  ; ByteAddressBuffer Four : register(u4)
+  %Four_h = call target("dx.RawBuffer", i8, 0, 0)
+            @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i8_0_0t(
+                  i32 0, i32 5, i32 1, i32 0, i1 false)
+  store target("dx.RawBuffer", i8, 0, 0) %Four_h, ptr @Four, align 4
+
+; StructuredBuffer<int16_t> Five : register(u6);
+  %Five_h = call target("dx.RawBuffer", i16, 0, 0)
+            @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i16_0_0t(
+                  i32 0, i32 6, i32 1, i32 0, i1 false)
+  store target("dx.RawBuffer", i16, 0, 0) %Five_h, ptr @Five, align 4  
+  
+  ; RWBuffer<double> Two : register(u2);
+  %Six_h = call target("dx.TypedBuffer", i64, 0, 0, 0)
+            @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f64_0_0_0t(
+                  i32 2, i32 10, i32 1, i32 0, i1 false)
+  store target("dx.TypedBuffer", i64, 0, 0, 0) %Six_h, ptr @Six, align 4
+
+  ret void
+}
+
+attributes #0 = { noinline nounwind "hlsl.shader"="compute" }
+
+; CHECK: !dx.resources = !{[[ResList:[!][0-9]+]]}
+
+; CHECK: [[ResList]] = !{[[SRVList:[!][0-9]+]], null, null, null}
+; CHECK: [[SRVList]] = !{![[Zero:[0-9]+]], ![[One:[0-9]+]], ![[Two:[0-9]+]],
+; CHECK-SAME: ![[Three:[0-9]+]], ![[Four:[0-9]+]], ![[Five:[0-9]+]],
+; CHECK-SAME: ![[Six:[0-9]+]]}
+
+; CHECK: ![[Zero]] = !{i32 0, ptr @0, !"", i32 0, i32 0, i32 1, i32 10, i32 0, ![[Half:[0-9]+]]}
+; CHECK: ![[Half]] = !{i32 0, i32 8}
+; CHECK: ![[One]] = !{i32 1, ptr @1, !"", i32 0, i32 1, i32 1, i32 10, i32 0, ![[Float:[0-9]+]]}
+; CHECK: ![[Float]] = !{i32 0, i32 9}
+; CHECK: ![[Two]] = !{i32 2, ptr @2, !"", i32 0, i32 2, i32 1, i32 10, i32 0, ![[Double:[0-9]+]]}
+; CHECK: ![[Double]] = !{i32 0, i32 10}
+; CHECK: ![[Three]] = !{i32 3, ptr @3, !"", i32 0, i32 3, i32 1, i32 10, i32 0, ![[I32:[0-9]+]]}
+; CHECK: ![[I32]] = !{i32 0, i32 4}
+; CHECK: ![[Four]] = !{i32 4, ptr @4, !"", i32 0, i32 5, i32 1, i32 11, i32 0, null}
+; CHECK: ![[Five]] = !{i32 5, ptr @5, !"", i32 0, i32 6, i32 1, i32 12, i32 0, ![[FiveStride:[0-9]+]]}
+; CHECK: ![[FiveStride]] = !{i32 1, i32 2}
+; CHECK: ![[Six]] = !{i32 6, ptr @6, !"", i32 2, i32 10, i32 1, i32 10, i32 0, ![[U64:[0-9]+]]}
+; CHECK: ![[U64]] = !{i32 0, i32 7}
diff --git a/llvm/test/CodeGen/DirectX/Metadata/uav_metadata.ll b/llvm/test/CodeGen/DirectX/Metadata/uav_metadata.ll
new file mode 100644
index 0000000000000..2c98c5d4a1809
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/Metadata/uav_metadata.ll
@@ -0,0 +1,135 @@
+; 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 datalayout = "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:32-f64:64-n8:16:32:64"
+target triple = "dxil-pc-shadermodel6.6-compute"
+
+%"class.hlsl::RWBuffer" = type { target("dx.TypedBuffer", <4 x half>, 1, 0, 0) }
+%"class.hlsl::RWBuffer.1" = type { target("dx.TypedBuffer", <2 x float>, 1, 0, 0) }
+%"class.hlsl::RWBuffer.2" = type { target("dx.TypedBuffer", double, 1, 0, 0) }
+%"class.hlsl::RWBuffer.3" = type { target("dx.TypedBuffer", i32, 1, 0, 1) }
+%"class.hlsl::RWByteAddressBuffer" = type { target("dx.RawBuffer", i8, 1, 0) }
+%"class.hlsl::RWStructuredBuffer" = type { target("dx.RawBuffer", i16, 1, 0) }
+%"class.hlsl::RasterizerOrderedBuffer" = type { target("dx.TypedBuffer", <4 x i32>, 1, 1, 1) }
+%"class.hlsl::RasterizerOrderedStructuredBuffer" = type { target("dx.RawBuffer", <4 x i32>, 1, 1) }
+%"class.hlsl::RasterizerOrderedByteAddressBuffer" = type { target("dx.RawBuffer", i8, 1, 1) }
+%"class.hlsl::RWBuffer.4" = type { target("dx.TypedBuffer", i64, 1, 0, 0) }
+
+@Zero = internal global %"class.hlsl::RWBuffer" poison, align 4
+@One = internal global %"class.hlsl::RWBuffer.1" poison, align 4
+@Two = internal global %"class.hlsl::RWBuffer.2" poison, align 4
+@Three = internal global %"class.hlsl::RWBuffer.3" poison, align 4
+@Four = internal global %"class.hlsl::RWByteAddressBuffer" poison, align 4
+@Five = internal global %"class.hlsl::RWStructuredBuffer" poison, align 4
+@Six = internal global %"class.hlsl::RasterizerOrderedBuffer" poison, align 4
+@Seven = internal global %"class.hlsl::RasterizerOrderedStructuredBuffer" poison, align 4
+@Eight = internal global %"class.hlsl::RasterizerOrderedByteAddressBuffer" poison, align 4
+@Nine = internal global %"class.hlsl::RWBuffer.4" poison, align 4
+
+; PRINT:; Resource Bindings:
+; PRINT-NEXT:;
+; PRINT-NEXT:; Name                                 Type  Format         Dim      ID      HLSL Bind  Count
+; PRINT-NEXT:; ------------------------------ ---------- ------- ----------- ------- -------------- ------
+; PRINT-NEXT:;                                       UAV     f16         buf      U0             u0     1
+; PRINT-NEXT:;                                       UAV     f32         buf      U1             u1     1
+; PRINT-NEXT:;                                       UAV     f64         buf      U2             u2     1
+; PRINT-NEXT:;                                       UAV     i32         buf      U3             u3     1
+; PRINT-NEXT:;                                       UAV    byte         r/w      U4             u5     1
+; PRINT-NEXT:;                                       UAV  struct         r/w      U5             u6     1
+; PRINT-NEXT:;                                       UAV     i32         buf      U6             u7     1
+; PRINT-NEXT:;                                       UAV  struct         r/w      U7             u8     1
+; PRINT-NEXT:;                                       UAV    byte         r/w      U8             u9     1
+; PRINT-NEXT:;                                       UAV     u64         buf      U9     u10,space2     1
+
+define void @test() #0 {
+  ; RWBuffer<half4> Zero : register(u0)
+  %Zero_h = call target("dx.TypedBuffer", <4 x half>, 1, 0, 0)
+            @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_v4f16_1_0_0t(
+                  i32 0, i32 0, i32 1, i32 0, i1 false)
+  store target("dx.TypedBuffer", <4 x half>, 1, 0, 0) %Zero_h, ptr @Zero, align 4
+ 
+  ; RWBuffer<float4> One : register(u1)
+  %One_h = call target("dx.TypedBuffer", <2 x float>, 1, 0, 0)
+            @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_v2f32_1_0_0t(
+                  i32 0, i32 1, i32 1, i32 0, i1 false)
+  store target("dx.TypedBuffer", <2 x float>, 1, 0, 0) %One_h, ptr @One, align 4
+ 
+  ; RWBuffer<double> Two : register(u2);
+  %Two_h = call target("dx.TypedBuffer", double, 1, 0, 0)
+            @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f64_1_0_0t(
+                  i32 0, i32 2, i32 1, i32 0, i1 false)
+  store target("dx.TypedBuffer", double, 1, 0, 0) %Two_h, ptr @Two, align 4
+
+  ; RWBuffer<int4> Three : register(u3);
+  %Three_h = call target("dx.TypedBuffer", <4 x i32>, 1, 0, 1)
+            @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_i32_1_0_1t(
+                  i32 0, i32 3, i32 1, i32 0, i1 false)
+  store target("dx.TypedBuffer", <4 x i32>, 1, 0, 1) %Three_h, ptr @Three, align 4
+
+  ; ByteAddressBuffer Four : register(u5)
+  %Four_h = call target("dx.RawBuffer", i8, 1, 0)
+            @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i8_1_0t(
+                  i32 0, i32 5, i32 1, i32 0, i1 false)
+  store target("dx.RawBuffer", i8, 1, 0) %Four_h, ptr @Four, align 4
+
+  ; RWStructuredBuffer<int16_t> Five : register(u6);
+  %Five_h = call target("dx.RawBuffer", i16, 1, 0)
+            @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i16_1_0t(
+                  i32 0, i32 6, i32 1, i32 0, i1 false)
+  store target("dx.RawBuffer", i16, 1, 0) %Five_h, ptr @Five, align 4
+  
+  ; RasterizerOrderedBuffer<int4> Six : register(u7);
+  %Six_h = call target("dx.TypedBuffer", <4 x i32>, 1, 1, 1)
+            @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_v4i32_1_1_1t(
+                  i32 0, i32 7, i32 1, i32 0, i1 false)
+  store target("dx.TypedBuffer", <4 x i32>, 1, 1, 1) %Six_h, ptr @Six, align 4
+
+  ; Rasterize...
[truncated]

@llvmbot
Copy link
Member

llvmbot commented Mar 7, 2025

@llvm/pr-subscribers-backend-directx

Author: Helena Kotas (hekota)

Changes

Update resource metadata tests to generate metadata based on llvm.dx.resource.handlefrombinding data collected in DXILResourceBindingAnalysis.

  • UAVMetadata.ll is renamed to uav_metadata.ll, updated and placed under Metadata directory in llvm/test/CodeGen/DirectX
  • srv_metadata.ll is a new test for SRV resource metadata
  • cbuf.ll and legacy_cb_layout_{0|1}.ll tests were merged and updated into cbuffer_metadata.ll
  • legacy_cb_layout_{2|3}.ll tests we moved to cbuffer.hlsl in Clang CodeGen because there were more of a layout than metadata tests

Related to #114126


Patch is 38.24 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/130222.diff

10 Files Affected:

  • (modified) clang/test/CodeGenHLSL/cbuffer.hlsl (+76-2)
  • (added) llvm/test/CodeGen/DirectX/Metadata/cbuffer_metadata.ll (+80)
  • (added) llvm/test/CodeGen/DirectX/Metadata/srv_metadata.ll (+103)
  • (added) llvm/test/CodeGen/DirectX/Metadata/uav_metadata.ll (+135)
  • (removed) llvm/test/CodeGen/DirectX/UAVMetadata.ll (-77)
  • (removed) llvm/test/CodeGen/DirectX/cbuf.ll (-37)
  • (removed) llvm/test/CodeGen/DirectX/legacy_cb_layout_0.ll (-14)
  • (removed) llvm/test/CodeGen/DirectX/legacy_cb_layout_1.ll (-37)
  • (removed) llvm/test/CodeGen/DirectX/legacy_cb_layout_2.ll (-51)
  • (removed) llvm/test/CodeGen/DirectX/legacy_cb_layout_3.ll (-81)
diff --git a/clang/test/CodeGenHLSL/cbuffer.hlsl b/clang/test/CodeGenHLSL/cbuffer.hlsl
index 38093c6dfacd7..b5e435619438f 100644
--- a/clang/test/CodeGenHLSL/cbuffer.hlsl
+++ b/clang/test/CodeGenHLSL/cbuffer.hlsl
@@ -20,6 +20,14 @@
 // CHECK: %anon = type <{ float }>
 // CHECK: %anon.0 = type <{ <2 x i32> }>
 
+// CHECK: %__cblayout_CB_A = type <{ [2 x double], [3 x <3 x float>], float, [3 x double], half, [1 x <2 x double>], float, [2 x <3 x half>], <3 x half> }>
+// CHECK: %__cblayout_CB_B = type <{ [3 x <3 x double>], <3 x half> }>
+// CHECK: %__cblayout_CB_C = type <{ i32, target("dx.Layout", %F, 96, 0, 16, 28, 32, 56, 64, 80, 84, 90), half, target("dx.Layout", %G, 258, 0, 48, 64, 256), double }>
+
+// CHECK: %F = type <{ double, <3 x float>, float, <3 x double>, half, <2 x double>, float, <3 x half>, <3 x half> }>
+// CHECK: %G = type <{ target("dx.Layout", %E, 36, 0, 8, 16, 20, 22, 24, 32), [1 x float], [2 x target("dx.Layout", %F, 96, 0, 16, 28, 32, 56, 64, 80, 84, 90)], half }>
+// CHECK: %E = type <{ float, double, float, half, i16, i64, i32 }>
+
 cbuffer CBScalars : register(b1, space5) {
   float a1;
   double a2;
@@ -155,6 +163,64 @@ cbuffer CBMix {
     uint16_t f9;
 };  
 
+// CHECK: @CB_A.cb = external constant target("dx.CBuffer", target("dx.Layout", %__cblayout_CB_A, 188, 0, 32, 76, 80, 120, 128, 144, 160, 182))
+
+cbuffer CB_A {
+  double B0[2];
+  float3 B1[3];
+  float B2;
+  double B3[3];
+  half B4;
+  double2 B5[1];
+  float B6;
+  half3 B7[2];
+  half3 B8;
+}
+
+// CHECK: @CB_B.cb = external constant target("dx.CBuffer", target("dx.Layout", %__cblayout_CB_B, 94, 0, 88))
+cbuffer CB_B {
+  double3 B9[3];
+  half3 B10;
+}
+
+struct E {
+  float A0;
+  double A1;
+  float A2;
+  half A3;
+  int16_t A4;
+  int64_t A5;
+  int A6;
+};
+
+struct F {
+  double B0;
+  float3 B1;
+  float B2;
+  double3 B3;
+  half B4;
+  double2 B5;
+  float B6;
+  half3 B7;
+  half3 B8;
+};
+
+struct G {
+  E C0;
+  float C1[1];
+  F C2[2];
+  half C3;
+};
+
+// CHECK: @CB_C.cb = external constant target("dx.CBuffer", target("dx.Layout", %__cblayout_CB_C, 400, 0, 16, 112, 128, 392))
+cbuffer CB_C {
+  int D0;
+  F D1;
+  half D2;
+  G D3;
+  double D4;
+}
+
 // CHECK: define internal void @_init_resource_CBScalars.cb()
 // CHECK-NEXT: entry:
 // CHECK-NEXT: %[[HANDLE1:.*]] = call target("dx.CBuffer", target("dx.Layout", %__cblayout_CBScalars, 56, 0, 8, 16, 24, 32, 36, 40, 48))
@@ -171,7 +237,7 @@ RWBuffer<float> Buf;
 
 [numthreads(4,1,1)]
 void main() {
-  Buf[0] = a1 + b1.z + c1[2] + a.f1.y + f1;
+  Buf[0] = a1 + b1.z + c1[2] + a.f1.y + f1 + B1[0].x + B10.z + D1.B2;
 }
 
 // CHECK: define internal void @_GLOBAL__sub_I_cbuffer.hlsl()
@@ -179,7 +245,8 @@ void main() {
 // CHECK-NEXT: call void @_init_resource_CBScalars.cb()
 // CHECK-NEXT: call void @_init_resource_CBArrays.cb()
 
-// CHECK: !hlsl.cbs = !{![[CBSCALARS:[0-9]+]], ![[CBVECTORS:[0-9]+]], ![[CBARRAYS:[0-9]+]], ![[CBSTRUCTS:[0-9]+]], ![[CBMIX:[0-9]+]]}
+// CHECK: !hlsl.cbs = !{![[CBSCALARS:[0-9]+]], ![[CBVECTORS:[0-9]+]], ![[CBARRAYS:[0-9]+]], ![[CBSTRUCTS:[0-9]+]], ![[CBMIX:[0-9]+]],
+// CHECK-SAME: ![[CB_A:[0-9]+]], ![[CB_B:[0-9]+]], ![[CB_C:[0-9]+]]}
 
 // CHECK: ![[CBSCALARS]] = !{ptr @CBScalars.cb, ptr addrspace(2) @a1, ptr addrspace(2) @a2, ptr addrspace(2) @a3, ptr addrspace(2) @a4,
 // CHECK-SAME: ptr addrspace(2) @a5, ptr addrspace(2) @a6, ptr addrspace(2) @a7, ptr addrspace(2) @a8}
@@ -195,3 +262,10 @@ void main() {
 
 // CHECK: ![[CBMIX]] = !{ptr @CBMix.cb, ptr addrspace(2) @test, ptr addrspace(2) @f1, ptr addrspace(2) @f2, ptr addrspace(2) @f3,
 // CHECK-SAME: ptr addrspace(2) @f4, ptr addrspace(2) @f5, ptr addrspace(2) @f6, ptr addrspace(2) @f7, ptr addrspace(2) @f8, ptr addrspace(2) @f9}
+
+// CHECK: ![[CB_A]] = !{ptr @CB_A.cb, ptr addrspace(2) @B0, ptr addrspace(2) @B1, ptr addrspace(2) @B2, ptr addrspace(2) @B3, ptr addrspace(2) @B4,
+// CHECK-SAME: ptr addrspace(2) @B5, ptr addrspace(2) @B6, ptr addrspace(2) @B7, ptr addrspace(2) @B8}
+
+// CHECK: ![[CB_B]] = !{ptr @CB_B.cb, ptr addrspace(2) @B9, ptr addrspace(2) @B10}
+
+// CHECK: ![[CB_C]] = !{ptr @CB_C.cb, ptr addrspace(2) @D0, ptr addrspace(2) @D1, ptr addrspace(2) @D2, ptr addrspace(2) @D3, ptr addrspace(2) @D4}
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..b3dda74bf8bbf
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/Metadata/cbuffer_metadata.ll
@@ -0,0 +1,80 @@
+; 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 datalayout = "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:32-f64:64-n8:16:32:64"
+target triple = "dxil-pc-shadermodel6.6-compute"
+
+%__cblayout_CB1 = type <{ float, i32, double, <2 x i32> }>
+@CB1.cb = external constant target("dx.CBuffer", target("dx.Layout", %__cblayout_CB1, 24, 0, 4, 8, 16))
+
+%__cblayout_CB2 = type <{ float, double, float, half, i16, i64, i32 }>
+@CB2.cb = external constant target("dx.CBuffer", target("dx.Layout", %__cblayout_CB2, 36, 0, 8, 16, 20, 22, 24, 32))
+
+%__cblayout_CB3 = type <{ double, <3 x float>, float, <3 x double>, half, <2 x double>, float, <3 x half>, <3 x half> }>
+@CB3.cb = external constant target("dx.CBuffer", target("dx.Layout", %__cblayout_CB3, 96, 0, 16, 28, 32, 56, 64, 80, 84, 90))
+
+; PRINT:; Resource Bindings:
+; PRINT-NEXT:;
+; PRINT-NEXT:; Name                                 Type  Format         Dim      ID      HLSL Bind  Count
+; PRINT-NEXT:; ------------------------------ ---------- ------- ----------- ------- -------------- ------
+; PRINT-NEXT:;                                   cbuffer      NA          NA     CB0            cb0     1
+; PRINT-NEXT:;                                   cbuffer      NA          NA     CB1            cb1     1
+; PRINT-NEXT:;                                   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", target("dx.Layout", %__cblayout_CB1, 24, 0, 4, 8, 16))
+            @llvm.dx.resource.handlefrombinding.tdx.CBuffer_tdx.Layout_s___cblayout_CB1s_24_0_4_8_16tt(
+                i32 0, i32 0, i32 1, i32 0, i1 false)
+  store target("dx.CBuffer", target("dx.Layout", %__cblayout_CB1, 24, 0, 4, 8, 16)) %CB1.cb_h, ptr @CB1.cb, align 4
+
+  ; 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", target("dx.Layout", %__cblayout_CB2, 36, 0, 8, 16, 20, 22, 24, 32))
+            @llvm.dx.resource.handlefrombinding.tdx.CBuffer_tdx.Layout_s___cblayout_CB2s_36_0_8_16_20_22_24_32tt(
+                i32 0, i32 1, i32 1, i32 0, i1 false)
+  store target("dx.CBuffer", target("dx.Layout", %__cblayout_CB2, 36, 0, 8, 16, 20, 22, 24, 32)) %CB2.cb_h, ptr @CB2.cb, align 4
+
+  ; 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", target("dx.Layout", %__cblayout_CB3, 96, 0, 16, 28, 32, 56, 64, 80, 84, 90))
+            @llvm.dx.resource.handlefrombinding.tdx.CBuffer_tdx.Layout_s___cblayout_CB3s_96_0_16_28_32_56_64_80_84_90tt(
+                i32 15, i32 5, i32 1, i32 0, i1 false)
+  store target("dx.CBuffer", target("dx.Layout", %__cblayout_CB3, 96, 0, 16, 28, 32, 56, 64, 80, 84, 90)) %CB3.cb_h, ptr @CB3.cb, align 4
+
+  ret void
+}
+
+attributes #0 = { noinline nounwind "hlsl.shader"="compute" }
+
+; CHECK: !dx.resources = !{[[ResList:[!][0-9]+]]}
+
+; CHECK: [[ResList]] = !{null, null, [[CBList:[!][0-9]+]], null}
+; CHECK: [[CBList]] = !{![[CB1:[0-9]+]], ![[CB2:[0-9]+]], ![[CB3:[0-9]+]]}
+; CHECK: ![[CB1]] = !{i32 0, ptr @0, !"", i32 0, i32 0, i32 1, i32 24, null}
+; CHECK: ![[CB2]] = !{i32 1, ptr @1, !"", i32 0, i32 1, i32 1, i32 36, null}
+; CHECK: ![[CB3]] = !{i32 2, ptr @2, !"", i32 15, i32 5, i32 1, i32 96, null}
diff --git a/llvm/test/CodeGen/DirectX/Metadata/srv_metadata.ll b/llvm/test/CodeGen/DirectX/Metadata/srv_metadata.ll
new file mode 100644
index 0000000000000..e1344035e01a7
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/Metadata/srv_metadata.ll
@@ -0,0 +1,103 @@
+; 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 datalayout = "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:32-f64:64-n8:16:32:64"
+target triple = "dxil-pc-shadermodel6.6-compute"
+
+%"class.hlsl::Buffer" = type { target("dx.TypedBuffer", <4 x half>, 0, 0, 0) }
+%"class.hlsl::Buffer.1" = type { target("dx.TypedBuffer", <2 x float>, 0, 0, 0) }
+%"class.hlsl::Buffer.2" = type { target("dx.TypedBuffer", double, 0, 0, 0) }
+%"class.hlsl::Buffer.3" = type { target("dx.TypedBuffer", i32, 0, 0, 1) }
+%"class.hlsl::ByteAddressBuffer" = type { target("dx.RawBuffer", i8, 0, 0) }
+%"class.hlsl::StructuredBuffer" = type { target("dx.RawBuffer", i16, 0, 0) }
+%"class.hlsl::Buffer.4" = type { target("dx.TypedBuffer", i64, 0, 0, 0) }
+
+@Zero = internal global %"class.hlsl::Buffer" poison, align 4
+@One = internal global %"class.hlsl::Buffer.1" poison, align 4
+@Two = internal global %"class.hlsl::Buffer.2" poison, align 4
+@Three = internal global %"class.hlsl::Buffer.3" poison, align 4
+@Four = internal global %"class.hlsl::ByteAddressBuffer" poison, align 4
+@Five = internal global %"class.hlsl::StructuredBuffer" poison, align 4
+@Six = internal global %"class.hlsl::Buffer.4" poison, align 4
+
+; PRINT:; Resource Bindings:
+; PRINT-NEXT:;
+; PRINT-NEXT:; Name                                 Type  Format         Dim      ID      HLSL Bind  Count
+; PRINT-NEXT:; ------------------------------ ---------- ------- ----------- ------- -------------- ------
+; PRINT-NEXT:;                                       SRV     f16         buf      T0             t0     1
+; PRINT-NEXT:;                                       SRV     f32         buf      T1             t1     1
+; PRINT-NEXT:;                                       SRV     f64         buf      T2             t2     1
+; PRINT-NEXT:;                                       SRV     i32         buf      T3             t3     1
+; PRINT-NEXT:;                                       SRV    byte         r/o      T4             t5     1
+; PRINT-NEXT:;                                       SRV  struct         r/o      T5             t6     1
+; PRINT-NEXT:;                                       SRV     u64         buf      T6     t10,space2     1
+
+define void @test() #0 {
+  ; RWBuffer<half4> Buf : register(u0)
+  %Zero_h = call target("dx.TypedBuffer", <4 x half>, 0, 0, 0)
+            @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_v4f16_0_0_0t(
+                  i32 0, i32 0, i32 1, i32 0, i1 false)
+  store target("dx.TypedBuffer", <4 x half>, 0, 0, 0) %Zero_h, ptr @Zero, align 4
+ 
+  ; RWBuffer<float4> Buf : register(u1)
+  %One_h = call target("dx.TypedBuffer", <2 x float>, 0, 0, 0)
+            @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_v2f32_0_0_0t(
+                  i32 0, i32 1, i32 1, i32 0, i1 false)
+  store target("dx.TypedBuffer", <2 x float>, 0, 0, 0) %One_h, ptr @One, align 4
+ 
+  ; RWBuffer<double> Two : register(u2);
+  %Two_h = call target("dx.TypedBuffer", double, 0, 0, 0)
+            @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f64_0_0_0t(
+                  i32 0, i32 2, i32 1, i32 0, i1 false)
+  store target("dx.TypedBuffer", double, 0, 0, 0) %Two_h, ptr @Two, align 4
+
+  ; RWBuffer<int4> Three : register(u3);
+  %Three_h = call target("dx.TypedBuffer", <4 x i32>, 0, 0, 1)
+            @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_i32_0_0_1t(
+                  i32 0, i32 3, i32 1, i32 0, i1 false)
+  store target("dx.TypedBuffer", <4 x i32>, 0, 0, 1) %Three_h, ptr @Three, align 4
+
+  ; ByteAddressBuffer Four : register(u4)
+  %Four_h = call target("dx.RawBuffer", i8, 0, 0)
+            @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i8_0_0t(
+                  i32 0, i32 5, i32 1, i32 0, i1 false)
+  store target("dx.RawBuffer", i8, 0, 0) %Four_h, ptr @Four, align 4
+
+; StructuredBuffer<int16_t> Five : register(u6);
+  %Five_h = call target("dx.RawBuffer", i16, 0, 0)
+            @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i16_0_0t(
+                  i32 0, i32 6, i32 1, i32 0, i1 false)
+  store target("dx.RawBuffer", i16, 0, 0) %Five_h, ptr @Five, align 4  
+  
+  ; RWBuffer<double> Two : register(u2);
+  %Six_h = call target("dx.TypedBuffer", i64, 0, 0, 0)
+            @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f64_0_0_0t(
+                  i32 2, i32 10, i32 1, i32 0, i1 false)
+  store target("dx.TypedBuffer", i64, 0, 0, 0) %Six_h, ptr @Six, align 4
+
+  ret void
+}
+
+attributes #0 = { noinline nounwind "hlsl.shader"="compute" }
+
+; CHECK: !dx.resources = !{[[ResList:[!][0-9]+]]}
+
+; CHECK: [[ResList]] = !{[[SRVList:[!][0-9]+]], null, null, null}
+; CHECK: [[SRVList]] = !{![[Zero:[0-9]+]], ![[One:[0-9]+]], ![[Two:[0-9]+]],
+; CHECK-SAME: ![[Three:[0-9]+]], ![[Four:[0-9]+]], ![[Five:[0-9]+]],
+; CHECK-SAME: ![[Six:[0-9]+]]}
+
+; CHECK: ![[Zero]] = !{i32 0, ptr @0, !"", i32 0, i32 0, i32 1, i32 10, i32 0, ![[Half:[0-9]+]]}
+; CHECK: ![[Half]] = !{i32 0, i32 8}
+; CHECK: ![[One]] = !{i32 1, ptr @1, !"", i32 0, i32 1, i32 1, i32 10, i32 0, ![[Float:[0-9]+]]}
+; CHECK: ![[Float]] = !{i32 0, i32 9}
+; CHECK: ![[Two]] = !{i32 2, ptr @2, !"", i32 0, i32 2, i32 1, i32 10, i32 0, ![[Double:[0-9]+]]}
+; CHECK: ![[Double]] = !{i32 0, i32 10}
+; CHECK: ![[Three]] = !{i32 3, ptr @3, !"", i32 0, i32 3, i32 1, i32 10, i32 0, ![[I32:[0-9]+]]}
+; CHECK: ![[I32]] = !{i32 0, i32 4}
+; CHECK: ![[Four]] = !{i32 4, ptr @4, !"", i32 0, i32 5, i32 1, i32 11, i32 0, null}
+; CHECK: ![[Five]] = !{i32 5, ptr @5, !"", i32 0, i32 6, i32 1, i32 12, i32 0, ![[FiveStride:[0-9]+]]}
+; CHECK: ![[FiveStride]] = !{i32 1, i32 2}
+; CHECK: ![[Six]] = !{i32 6, ptr @6, !"", i32 2, i32 10, i32 1, i32 10, i32 0, ![[U64:[0-9]+]]}
+; CHECK: ![[U64]] = !{i32 0, i32 7}
diff --git a/llvm/test/CodeGen/DirectX/Metadata/uav_metadata.ll b/llvm/test/CodeGen/DirectX/Metadata/uav_metadata.ll
new file mode 100644
index 0000000000000..2c98c5d4a1809
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/Metadata/uav_metadata.ll
@@ -0,0 +1,135 @@
+; 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 datalayout = "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:32-f64:64-n8:16:32:64"
+target triple = "dxil-pc-shadermodel6.6-compute"
+
+%"class.hlsl::RWBuffer" = type { target("dx.TypedBuffer", <4 x half>, 1, 0, 0) }
+%"class.hlsl::RWBuffer.1" = type { target("dx.TypedBuffer", <2 x float>, 1, 0, 0) }
+%"class.hlsl::RWBuffer.2" = type { target("dx.TypedBuffer", double, 1, 0, 0) }
+%"class.hlsl::RWBuffer.3" = type { target("dx.TypedBuffer", i32, 1, 0, 1) }
+%"class.hlsl::RWByteAddressBuffer" = type { target("dx.RawBuffer", i8, 1, 0) }
+%"class.hlsl::RWStructuredBuffer" = type { target("dx.RawBuffer", i16, 1, 0) }
+%"class.hlsl::RasterizerOrderedBuffer" = type { target("dx.TypedBuffer", <4 x i32>, 1, 1, 1) }
+%"class.hlsl::RasterizerOrderedStructuredBuffer" = type { target("dx.RawBuffer", <4 x i32>, 1, 1) }
+%"class.hlsl::RasterizerOrderedByteAddressBuffer" = type { target("dx.RawBuffer", i8, 1, 1) }
+%"class.hlsl::RWBuffer.4" = type { target("dx.TypedBuffer", i64, 1, 0, 0) }
+
+@Zero = internal global %"class.hlsl::RWBuffer" poison, align 4
+@One = internal global %"class.hlsl::RWBuffer.1" poison, align 4
+@Two = internal global %"class.hlsl::RWBuffer.2" poison, align 4
+@Three = internal global %"class.hlsl::RWBuffer.3" poison, align 4
+@Four = internal global %"class.hlsl::RWByteAddressBuffer" poison, align 4
+@Five = internal global %"class.hlsl::RWStructuredBuffer" poison, align 4
+@Six = internal global %"class.hlsl::RasterizerOrderedBuffer" poison, align 4
+@Seven = internal global %"class.hlsl::RasterizerOrderedStructuredBuffer" poison, align 4
+@Eight = internal global %"class.hlsl::RasterizerOrderedByteAddressBuffer" poison, align 4
+@Nine = internal global %"class.hlsl::RWBuffer.4" poison, align 4
+
+; PRINT:; Resource Bindings:
+; PRINT-NEXT:;
+; PRINT-NEXT:; Name                                 Type  Format         Dim      ID      HLSL Bind  Count
+; PRINT-NEXT:; ------------------------------ ---------- ------- ----------- ------- -------------- ------
+; PRINT-NEXT:;                                       UAV     f16         buf      U0             u0     1
+; PRINT-NEXT:;                                       UAV     f32         buf      U1             u1     1
+; PRINT-NEXT:;                                       UAV     f64         buf      U2             u2     1
+; PRINT-NEXT:;                                       UAV     i32         buf      U3             u3     1
+; PRINT-NEXT:;                                       UAV    byte         r/w      U4             u5     1
+; PRINT-NEXT:;                                       UAV  struct         r/w      U5             u6     1
+; PRINT-NEXT:;                                       UAV     i32         buf      U6             u7     1
+; PRINT-NEXT:;                                       UAV  struct         r/w      U7             u8     1
+; PRINT-NEXT:;                                       UAV    byte         r/w      U8             u9     1
+; PRINT-NEXT:;                                       UAV     u64         buf      U9     u10,space2     1
+
+define void @test() #0 {
+  ; RWBuffer<half4> Zero : register(u0)
+  %Zero_h = call target("dx.TypedBuffer", <4 x half>, 1, 0, 0)
+            @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_v4f16_1_0_0t(
+                  i32 0, i32 0, i32 1, i32 0, i1 false)
+  store target("dx.TypedBuffer", <4 x half>, 1, 0, 0) %Zero_h, ptr @Zero, align 4
+ 
+  ; RWBuffer<float4> One : register(u1)
+  %One_h = call target("dx.TypedBuffer", <2 x float>, 1, 0, 0)
+            @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_v2f32_1_0_0t(
+                  i32 0, i32 1, i32 1, i32 0, i1 false)
+  store target("dx.TypedBuffer", <2 x float>, 1, 0, 0) %One_h, ptr @One, align 4
+ 
+  ; RWBuffer<double> Two : register(u2);
+  %Two_h = call target("dx.TypedBuffer", double, 1, 0, 0)
+            @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f64_1_0_0t(
+                  i32 0, i32 2, i32 1, i32 0, i1 false)
+  store target("dx.TypedBuffer", double, 1, 0, 0) %Two_h, ptr @Two, align 4
+
+  ; RWBuffer<int4> Three : register(u3);
+  %Three_h = call target("dx.TypedBuffer", <4 x i32>, 1, 0, 1)
+            @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_i32_1_0_1t(
+                  i32 0, i32 3, i32 1, i32 0, i1 false)
+  store target("dx.TypedBuffer", <4 x i32>, 1, 0, 1) %Three_h, ptr @Three, align 4
+
+  ; ByteAddressBuffer Four : register(u5)
+  %Four_h = call target("dx.RawBuffer", i8, 1, 0)
+            @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i8_1_0t(
+                  i32 0, i32 5, i32 1, i32 0, i1 false)
+  store target("dx.RawBuffer", i8, 1, 0) %Four_h, ptr @Four, align 4
+
+  ; RWStructuredBuffer<int16_t> Five : register(u6);
+  %Five_h = call target("dx.RawBuffer", i16, 1, 0)
+            @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i16_1_0t(
+                  i32 0, i32 6, i32 1, i32 0, i1 false)
+  store target("dx.RawBuffer", i16, 1, 0) %Five_h, ptr @Five, align 4
+  
+  ; RasterizerOrderedBuffer<int4> Six : register(u7);
+  %Six_h = call target("dx.TypedBuffer", <4 x i32>, 1, 1, 1)
+            @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_v4i32_1_1_1t(
+                  i32 0, i32 7, i32 1, i32 0, i1 false)
+  store target("dx.TypedBuffer", <4 x i32>, 1, 1, 1) %Six_h, ptr @Six, align 4
+
+  ; Rasterize...
[truncated]

@llvmbot
Copy link
Member

llvmbot commented Mar 7, 2025

@llvm/pr-subscribers-hlsl

Author: Helena Kotas (hekota)

Changes

Update resource metadata tests to generate metadata based on llvm.dx.resource.handlefrombinding data collected in DXILResourceBindingAnalysis.

  • UAVMetadata.ll is renamed to uav_metadata.ll, updated and placed under Metadata directory in llvm/test/CodeGen/DirectX
  • srv_metadata.ll is a new test for SRV resource metadata
  • cbuf.ll and legacy_cb_layout_{0|1}.ll tests were merged and updated into cbuffer_metadata.ll
  • legacy_cb_layout_{2|3}.ll tests we moved to cbuffer.hlsl in Clang CodeGen because there were more of a layout than metadata tests

Related to #114126


Patch is 38.24 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/130222.diff

10 Files Affected:

  • (modified) clang/test/CodeGenHLSL/cbuffer.hlsl (+76-2)
  • (added) llvm/test/CodeGen/DirectX/Metadata/cbuffer_metadata.ll (+80)
  • (added) llvm/test/CodeGen/DirectX/Metadata/srv_metadata.ll (+103)
  • (added) llvm/test/CodeGen/DirectX/Metadata/uav_metadata.ll (+135)
  • (removed) llvm/test/CodeGen/DirectX/UAVMetadata.ll (-77)
  • (removed) llvm/test/CodeGen/DirectX/cbuf.ll (-37)
  • (removed) llvm/test/CodeGen/DirectX/legacy_cb_layout_0.ll (-14)
  • (removed) llvm/test/CodeGen/DirectX/legacy_cb_layout_1.ll (-37)
  • (removed) llvm/test/CodeGen/DirectX/legacy_cb_layout_2.ll (-51)
  • (removed) llvm/test/CodeGen/DirectX/legacy_cb_layout_3.ll (-81)
diff --git a/clang/test/CodeGenHLSL/cbuffer.hlsl b/clang/test/CodeGenHLSL/cbuffer.hlsl
index 38093c6dfacd7..b5e435619438f 100644
--- a/clang/test/CodeGenHLSL/cbuffer.hlsl
+++ b/clang/test/CodeGenHLSL/cbuffer.hlsl
@@ -20,6 +20,14 @@
 // CHECK: %anon = type <{ float }>
 // CHECK: %anon.0 = type <{ <2 x i32> }>
 
+// CHECK: %__cblayout_CB_A = type <{ [2 x double], [3 x <3 x float>], float, [3 x double], half, [1 x <2 x double>], float, [2 x <3 x half>], <3 x half> }>
+// CHECK: %__cblayout_CB_B = type <{ [3 x <3 x double>], <3 x half> }>
+// CHECK: %__cblayout_CB_C = type <{ i32, target("dx.Layout", %F, 96, 0, 16, 28, 32, 56, 64, 80, 84, 90), half, target("dx.Layout", %G, 258, 0, 48, 64, 256), double }>
+
+// CHECK: %F = type <{ double, <3 x float>, float, <3 x double>, half, <2 x double>, float, <3 x half>, <3 x half> }>
+// CHECK: %G = type <{ target("dx.Layout", %E, 36, 0, 8, 16, 20, 22, 24, 32), [1 x float], [2 x target("dx.Layout", %F, 96, 0, 16, 28, 32, 56, 64, 80, 84, 90)], half }>
+// CHECK: %E = type <{ float, double, float, half, i16, i64, i32 }>
+
 cbuffer CBScalars : register(b1, space5) {
   float a1;
   double a2;
@@ -155,6 +163,64 @@ cbuffer CBMix {
     uint16_t f9;
 };  
 
+// CHECK: @CB_A.cb = external constant target("dx.CBuffer", target("dx.Layout", %__cblayout_CB_A, 188, 0, 32, 76, 80, 120, 128, 144, 160, 182))
+
+cbuffer CB_A {
+  double B0[2];
+  float3 B1[3];
+  float B2;
+  double B3[3];
+  half B4;
+  double2 B5[1];
+  float B6;
+  half3 B7[2];
+  half3 B8;
+}
+
+// CHECK: @CB_B.cb = external constant target("dx.CBuffer", target("dx.Layout", %__cblayout_CB_B, 94, 0, 88))
+cbuffer CB_B {
+  double3 B9[3];
+  half3 B10;
+}
+
+struct E {
+  float A0;
+  double A1;
+  float A2;
+  half A3;
+  int16_t A4;
+  int64_t A5;
+  int A6;
+};
+
+struct F {
+  double B0;
+  float3 B1;
+  float B2;
+  double3 B3;
+  half B4;
+  double2 B5;
+  float B6;
+  half3 B7;
+  half3 B8;
+};
+
+struct G {
+  E C0;
+  float C1[1];
+  F C2[2];
+  half C3;
+};
+
+// CHECK: @CB_C.cb = external constant target("dx.CBuffer", target("dx.Layout", %__cblayout_CB_C, 400, 0, 16, 112, 128, 392))
+cbuffer CB_C {
+  int D0;
+  F D1;
+  half D2;
+  G D3;
+  double D4;
+}
+
 // CHECK: define internal void @_init_resource_CBScalars.cb()
 // CHECK-NEXT: entry:
 // CHECK-NEXT: %[[HANDLE1:.*]] = call target("dx.CBuffer", target("dx.Layout", %__cblayout_CBScalars, 56, 0, 8, 16, 24, 32, 36, 40, 48))
@@ -171,7 +237,7 @@ RWBuffer<float> Buf;
 
 [numthreads(4,1,1)]
 void main() {
-  Buf[0] = a1 + b1.z + c1[2] + a.f1.y + f1;
+  Buf[0] = a1 + b1.z + c1[2] + a.f1.y + f1 + B1[0].x + B10.z + D1.B2;
 }
 
 // CHECK: define internal void @_GLOBAL__sub_I_cbuffer.hlsl()
@@ -179,7 +245,8 @@ void main() {
 // CHECK-NEXT: call void @_init_resource_CBScalars.cb()
 // CHECK-NEXT: call void @_init_resource_CBArrays.cb()
 
-// CHECK: !hlsl.cbs = !{![[CBSCALARS:[0-9]+]], ![[CBVECTORS:[0-9]+]], ![[CBARRAYS:[0-9]+]], ![[CBSTRUCTS:[0-9]+]], ![[CBMIX:[0-9]+]]}
+// CHECK: !hlsl.cbs = !{![[CBSCALARS:[0-9]+]], ![[CBVECTORS:[0-9]+]], ![[CBARRAYS:[0-9]+]], ![[CBSTRUCTS:[0-9]+]], ![[CBMIX:[0-9]+]],
+// CHECK-SAME: ![[CB_A:[0-9]+]], ![[CB_B:[0-9]+]], ![[CB_C:[0-9]+]]}
 
 // CHECK: ![[CBSCALARS]] = !{ptr @CBScalars.cb, ptr addrspace(2) @a1, ptr addrspace(2) @a2, ptr addrspace(2) @a3, ptr addrspace(2) @a4,
 // CHECK-SAME: ptr addrspace(2) @a5, ptr addrspace(2) @a6, ptr addrspace(2) @a7, ptr addrspace(2) @a8}
@@ -195,3 +262,10 @@ void main() {
 
 // CHECK: ![[CBMIX]] = !{ptr @CBMix.cb, ptr addrspace(2) @test, ptr addrspace(2) @f1, ptr addrspace(2) @f2, ptr addrspace(2) @f3,
 // CHECK-SAME: ptr addrspace(2) @f4, ptr addrspace(2) @f5, ptr addrspace(2) @f6, ptr addrspace(2) @f7, ptr addrspace(2) @f8, ptr addrspace(2) @f9}
+
+// CHECK: ![[CB_A]] = !{ptr @CB_A.cb, ptr addrspace(2) @B0, ptr addrspace(2) @B1, ptr addrspace(2) @B2, ptr addrspace(2) @B3, ptr addrspace(2) @B4,
+// CHECK-SAME: ptr addrspace(2) @B5, ptr addrspace(2) @B6, ptr addrspace(2) @B7, ptr addrspace(2) @B8}
+
+// CHECK: ![[CB_B]] = !{ptr @CB_B.cb, ptr addrspace(2) @B9, ptr addrspace(2) @B10}
+
+// CHECK: ![[CB_C]] = !{ptr @CB_C.cb, ptr addrspace(2) @D0, ptr addrspace(2) @D1, ptr addrspace(2) @D2, ptr addrspace(2) @D3, ptr addrspace(2) @D4}
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..b3dda74bf8bbf
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/Metadata/cbuffer_metadata.ll
@@ -0,0 +1,80 @@
+; 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 datalayout = "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:32-f64:64-n8:16:32:64"
+target triple = "dxil-pc-shadermodel6.6-compute"
+
+%__cblayout_CB1 = type <{ float, i32, double, <2 x i32> }>
+@CB1.cb = external constant target("dx.CBuffer", target("dx.Layout", %__cblayout_CB1, 24, 0, 4, 8, 16))
+
+%__cblayout_CB2 = type <{ float, double, float, half, i16, i64, i32 }>
+@CB2.cb = external constant target("dx.CBuffer", target("dx.Layout", %__cblayout_CB2, 36, 0, 8, 16, 20, 22, 24, 32))
+
+%__cblayout_CB3 = type <{ double, <3 x float>, float, <3 x double>, half, <2 x double>, float, <3 x half>, <3 x half> }>
+@CB3.cb = external constant target("dx.CBuffer", target("dx.Layout", %__cblayout_CB3, 96, 0, 16, 28, 32, 56, 64, 80, 84, 90))
+
+; PRINT:; Resource Bindings:
+; PRINT-NEXT:;
+; PRINT-NEXT:; Name                                 Type  Format         Dim      ID      HLSL Bind  Count
+; PRINT-NEXT:; ------------------------------ ---------- ------- ----------- ------- -------------- ------
+; PRINT-NEXT:;                                   cbuffer      NA          NA     CB0            cb0     1
+; PRINT-NEXT:;                                   cbuffer      NA          NA     CB1            cb1     1
+; PRINT-NEXT:;                                   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", target("dx.Layout", %__cblayout_CB1, 24, 0, 4, 8, 16))
+            @llvm.dx.resource.handlefrombinding.tdx.CBuffer_tdx.Layout_s___cblayout_CB1s_24_0_4_8_16tt(
+                i32 0, i32 0, i32 1, i32 0, i1 false)
+  store target("dx.CBuffer", target("dx.Layout", %__cblayout_CB1, 24, 0, 4, 8, 16)) %CB1.cb_h, ptr @CB1.cb, align 4
+
+  ; 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", target("dx.Layout", %__cblayout_CB2, 36, 0, 8, 16, 20, 22, 24, 32))
+            @llvm.dx.resource.handlefrombinding.tdx.CBuffer_tdx.Layout_s___cblayout_CB2s_36_0_8_16_20_22_24_32tt(
+                i32 0, i32 1, i32 1, i32 0, i1 false)
+  store target("dx.CBuffer", target("dx.Layout", %__cblayout_CB2, 36, 0, 8, 16, 20, 22, 24, 32)) %CB2.cb_h, ptr @CB2.cb, align 4
+
+  ; 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", target("dx.Layout", %__cblayout_CB3, 96, 0, 16, 28, 32, 56, 64, 80, 84, 90))
+            @llvm.dx.resource.handlefrombinding.tdx.CBuffer_tdx.Layout_s___cblayout_CB3s_96_0_16_28_32_56_64_80_84_90tt(
+                i32 15, i32 5, i32 1, i32 0, i1 false)
+  store target("dx.CBuffer", target("dx.Layout", %__cblayout_CB3, 96, 0, 16, 28, 32, 56, 64, 80, 84, 90)) %CB3.cb_h, ptr @CB3.cb, align 4
+
+  ret void
+}
+
+attributes #0 = { noinline nounwind "hlsl.shader"="compute" }
+
+; CHECK: !dx.resources = !{[[ResList:[!][0-9]+]]}
+
+; CHECK: [[ResList]] = !{null, null, [[CBList:[!][0-9]+]], null}
+; CHECK: [[CBList]] = !{![[CB1:[0-9]+]], ![[CB2:[0-9]+]], ![[CB3:[0-9]+]]}
+; CHECK: ![[CB1]] = !{i32 0, ptr @0, !"", i32 0, i32 0, i32 1, i32 24, null}
+; CHECK: ![[CB2]] = !{i32 1, ptr @1, !"", i32 0, i32 1, i32 1, i32 36, null}
+; CHECK: ![[CB3]] = !{i32 2, ptr @2, !"", i32 15, i32 5, i32 1, i32 96, null}
diff --git a/llvm/test/CodeGen/DirectX/Metadata/srv_metadata.ll b/llvm/test/CodeGen/DirectX/Metadata/srv_metadata.ll
new file mode 100644
index 0000000000000..e1344035e01a7
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/Metadata/srv_metadata.ll
@@ -0,0 +1,103 @@
+; 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 datalayout = "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:32-f64:64-n8:16:32:64"
+target triple = "dxil-pc-shadermodel6.6-compute"
+
+%"class.hlsl::Buffer" = type { target("dx.TypedBuffer", <4 x half>, 0, 0, 0) }
+%"class.hlsl::Buffer.1" = type { target("dx.TypedBuffer", <2 x float>, 0, 0, 0) }
+%"class.hlsl::Buffer.2" = type { target("dx.TypedBuffer", double, 0, 0, 0) }
+%"class.hlsl::Buffer.3" = type { target("dx.TypedBuffer", i32, 0, 0, 1) }
+%"class.hlsl::ByteAddressBuffer" = type { target("dx.RawBuffer", i8, 0, 0) }
+%"class.hlsl::StructuredBuffer" = type { target("dx.RawBuffer", i16, 0, 0) }
+%"class.hlsl::Buffer.4" = type { target("dx.TypedBuffer", i64, 0, 0, 0) }
+
+@Zero = internal global %"class.hlsl::Buffer" poison, align 4
+@One = internal global %"class.hlsl::Buffer.1" poison, align 4
+@Two = internal global %"class.hlsl::Buffer.2" poison, align 4
+@Three = internal global %"class.hlsl::Buffer.3" poison, align 4
+@Four = internal global %"class.hlsl::ByteAddressBuffer" poison, align 4
+@Five = internal global %"class.hlsl::StructuredBuffer" poison, align 4
+@Six = internal global %"class.hlsl::Buffer.4" poison, align 4
+
+; PRINT:; Resource Bindings:
+; PRINT-NEXT:;
+; PRINT-NEXT:; Name                                 Type  Format         Dim      ID      HLSL Bind  Count
+; PRINT-NEXT:; ------------------------------ ---------- ------- ----------- ------- -------------- ------
+; PRINT-NEXT:;                                       SRV     f16         buf      T0             t0     1
+; PRINT-NEXT:;                                       SRV     f32         buf      T1             t1     1
+; PRINT-NEXT:;                                       SRV     f64         buf      T2             t2     1
+; PRINT-NEXT:;                                       SRV     i32         buf      T3             t3     1
+; PRINT-NEXT:;                                       SRV    byte         r/o      T4             t5     1
+; PRINT-NEXT:;                                       SRV  struct         r/o      T5             t6     1
+; PRINT-NEXT:;                                       SRV     u64         buf      T6     t10,space2     1
+
+define void @test() #0 {
+  ; RWBuffer<half4> Buf : register(u0)
+  %Zero_h = call target("dx.TypedBuffer", <4 x half>, 0, 0, 0)
+            @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_v4f16_0_0_0t(
+                  i32 0, i32 0, i32 1, i32 0, i1 false)
+  store target("dx.TypedBuffer", <4 x half>, 0, 0, 0) %Zero_h, ptr @Zero, align 4
+ 
+  ; RWBuffer<float4> Buf : register(u1)
+  %One_h = call target("dx.TypedBuffer", <2 x float>, 0, 0, 0)
+            @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_v2f32_0_0_0t(
+                  i32 0, i32 1, i32 1, i32 0, i1 false)
+  store target("dx.TypedBuffer", <2 x float>, 0, 0, 0) %One_h, ptr @One, align 4
+ 
+  ; RWBuffer<double> Two : register(u2);
+  %Two_h = call target("dx.TypedBuffer", double, 0, 0, 0)
+            @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f64_0_0_0t(
+                  i32 0, i32 2, i32 1, i32 0, i1 false)
+  store target("dx.TypedBuffer", double, 0, 0, 0) %Two_h, ptr @Two, align 4
+
+  ; RWBuffer<int4> Three : register(u3);
+  %Three_h = call target("dx.TypedBuffer", <4 x i32>, 0, 0, 1)
+            @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_i32_0_0_1t(
+                  i32 0, i32 3, i32 1, i32 0, i1 false)
+  store target("dx.TypedBuffer", <4 x i32>, 0, 0, 1) %Three_h, ptr @Three, align 4
+
+  ; ByteAddressBuffer Four : register(u4)
+  %Four_h = call target("dx.RawBuffer", i8, 0, 0)
+            @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i8_0_0t(
+                  i32 0, i32 5, i32 1, i32 0, i1 false)
+  store target("dx.RawBuffer", i8, 0, 0) %Four_h, ptr @Four, align 4
+
+; StructuredBuffer<int16_t> Five : register(u6);
+  %Five_h = call target("dx.RawBuffer", i16, 0, 0)
+            @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i16_0_0t(
+                  i32 0, i32 6, i32 1, i32 0, i1 false)
+  store target("dx.RawBuffer", i16, 0, 0) %Five_h, ptr @Five, align 4  
+  
+  ; RWBuffer<double> Two : register(u2);
+  %Six_h = call target("dx.TypedBuffer", i64, 0, 0, 0)
+            @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f64_0_0_0t(
+                  i32 2, i32 10, i32 1, i32 0, i1 false)
+  store target("dx.TypedBuffer", i64, 0, 0, 0) %Six_h, ptr @Six, align 4
+
+  ret void
+}
+
+attributes #0 = { noinline nounwind "hlsl.shader"="compute" }
+
+; CHECK: !dx.resources = !{[[ResList:[!][0-9]+]]}
+
+; CHECK: [[ResList]] = !{[[SRVList:[!][0-9]+]], null, null, null}
+; CHECK: [[SRVList]] = !{![[Zero:[0-9]+]], ![[One:[0-9]+]], ![[Two:[0-9]+]],
+; CHECK-SAME: ![[Three:[0-9]+]], ![[Four:[0-9]+]], ![[Five:[0-9]+]],
+; CHECK-SAME: ![[Six:[0-9]+]]}
+
+; CHECK: ![[Zero]] = !{i32 0, ptr @0, !"", i32 0, i32 0, i32 1, i32 10, i32 0, ![[Half:[0-9]+]]}
+; CHECK: ![[Half]] = !{i32 0, i32 8}
+; CHECK: ![[One]] = !{i32 1, ptr @1, !"", i32 0, i32 1, i32 1, i32 10, i32 0, ![[Float:[0-9]+]]}
+; CHECK: ![[Float]] = !{i32 0, i32 9}
+; CHECK: ![[Two]] = !{i32 2, ptr @2, !"", i32 0, i32 2, i32 1, i32 10, i32 0, ![[Double:[0-9]+]]}
+; CHECK: ![[Double]] = !{i32 0, i32 10}
+; CHECK: ![[Three]] = !{i32 3, ptr @3, !"", i32 0, i32 3, i32 1, i32 10, i32 0, ![[I32:[0-9]+]]}
+; CHECK: ![[I32]] = !{i32 0, i32 4}
+; CHECK: ![[Four]] = !{i32 4, ptr @4, !"", i32 0, i32 5, i32 1, i32 11, i32 0, null}
+; CHECK: ![[Five]] = !{i32 5, ptr @5, !"", i32 0, i32 6, i32 1, i32 12, i32 0, ![[FiveStride:[0-9]+]]}
+; CHECK: ![[FiveStride]] = !{i32 1, i32 2}
+; CHECK: ![[Six]] = !{i32 6, ptr @6, !"", i32 2, i32 10, i32 1, i32 10, i32 0, ![[U64:[0-9]+]]}
+; CHECK: ![[U64]] = !{i32 0, i32 7}
diff --git a/llvm/test/CodeGen/DirectX/Metadata/uav_metadata.ll b/llvm/test/CodeGen/DirectX/Metadata/uav_metadata.ll
new file mode 100644
index 0000000000000..2c98c5d4a1809
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/Metadata/uav_metadata.ll
@@ -0,0 +1,135 @@
+; 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 datalayout = "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:32-f64:64-n8:16:32:64"
+target triple = "dxil-pc-shadermodel6.6-compute"
+
+%"class.hlsl::RWBuffer" = type { target("dx.TypedBuffer", <4 x half>, 1, 0, 0) }
+%"class.hlsl::RWBuffer.1" = type { target("dx.TypedBuffer", <2 x float>, 1, 0, 0) }
+%"class.hlsl::RWBuffer.2" = type { target("dx.TypedBuffer", double, 1, 0, 0) }
+%"class.hlsl::RWBuffer.3" = type { target("dx.TypedBuffer", i32, 1, 0, 1) }
+%"class.hlsl::RWByteAddressBuffer" = type { target("dx.RawBuffer", i8, 1, 0) }
+%"class.hlsl::RWStructuredBuffer" = type { target("dx.RawBuffer", i16, 1, 0) }
+%"class.hlsl::RasterizerOrderedBuffer" = type { target("dx.TypedBuffer", <4 x i32>, 1, 1, 1) }
+%"class.hlsl::RasterizerOrderedStructuredBuffer" = type { target("dx.RawBuffer", <4 x i32>, 1, 1) }
+%"class.hlsl::RasterizerOrderedByteAddressBuffer" = type { target("dx.RawBuffer", i8, 1, 1) }
+%"class.hlsl::RWBuffer.4" = type { target("dx.TypedBuffer", i64, 1, 0, 0) }
+
+@Zero = internal global %"class.hlsl::RWBuffer" poison, align 4
+@One = internal global %"class.hlsl::RWBuffer.1" poison, align 4
+@Two = internal global %"class.hlsl::RWBuffer.2" poison, align 4
+@Three = internal global %"class.hlsl::RWBuffer.3" poison, align 4
+@Four = internal global %"class.hlsl::RWByteAddressBuffer" poison, align 4
+@Five = internal global %"class.hlsl::RWStructuredBuffer" poison, align 4
+@Six = internal global %"class.hlsl::RasterizerOrderedBuffer" poison, align 4
+@Seven = internal global %"class.hlsl::RasterizerOrderedStructuredBuffer" poison, align 4
+@Eight = internal global %"class.hlsl::RasterizerOrderedByteAddressBuffer" poison, align 4
+@Nine = internal global %"class.hlsl::RWBuffer.4" poison, align 4
+
+; PRINT:; Resource Bindings:
+; PRINT-NEXT:;
+; PRINT-NEXT:; Name                                 Type  Format         Dim      ID      HLSL Bind  Count
+; PRINT-NEXT:; ------------------------------ ---------- ------- ----------- ------- -------------- ------
+; PRINT-NEXT:;                                       UAV     f16         buf      U0             u0     1
+; PRINT-NEXT:;                                       UAV     f32         buf      U1             u1     1
+; PRINT-NEXT:;                                       UAV     f64         buf      U2             u2     1
+; PRINT-NEXT:;                                       UAV     i32         buf      U3             u3     1
+; PRINT-NEXT:;                                       UAV    byte         r/w      U4             u5     1
+; PRINT-NEXT:;                                       UAV  struct         r/w      U5             u6     1
+; PRINT-NEXT:;                                       UAV     i32         buf      U6             u7     1
+; PRINT-NEXT:;                                       UAV  struct         r/w      U7             u8     1
+; PRINT-NEXT:;                                       UAV    byte         r/w      U8             u9     1
+; PRINT-NEXT:;                                       UAV     u64         buf      U9     u10,space2     1
+
+define void @test() #0 {
+  ; RWBuffer<half4> Zero : register(u0)
+  %Zero_h = call target("dx.TypedBuffer", <4 x half>, 1, 0, 0)
+            @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_v4f16_1_0_0t(
+                  i32 0, i32 0, i32 1, i32 0, i1 false)
+  store target("dx.TypedBuffer", <4 x half>, 1, 0, 0) %Zero_h, ptr @Zero, align 4
+ 
+  ; RWBuffer<float4> One : register(u1)
+  %One_h = call target("dx.TypedBuffer", <2 x float>, 1, 0, 0)
+            @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_v2f32_1_0_0t(
+                  i32 0, i32 1, i32 1, i32 0, i1 false)
+  store target("dx.TypedBuffer", <2 x float>, 1, 0, 0) %One_h, ptr @One, align 4
+ 
+  ; RWBuffer<double> Two : register(u2);
+  %Two_h = call target("dx.TypedBuffer", double, 1, 0, 0)
+            @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f64_1_0_0t(
+                  i32 0, i32 2, i32 1, i32 0, i1 false)
+  store target("dx.TypedBuffer", double, 1, 0, 0) %Two_h, ptr @Two, align 4
+
+  ; RWBuffer<int4> Three : register(u3);
+  %Three_h = call target("dx.TypedBuffer", <4 x i32>, 1, 0, 1)
+            @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_i32_1_0_1t(
+                  i32 0, i32 3, i32 1, i32 0, i1 false)
+  store target("dx.TypedBuffer", <4 x i32>, 1, 0, 1) %Three_h, ptr @Three, align 4
+
+  ; ByteAddressBuffer Four : register(u5)
+  %Four_h = call target("dx.RawBuffer", i8, 1, 0)
+            @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i8_1_0t(
+                  i32 0, i32 5, i32 1, i32 0, i1 false)
+  store target("dx.RawBuffer", i8, 1, 0) %Four_h, ptr @Four, align 4
+
+  ; RWStructuredBuffer<int16_t> Five : register(u6);
+  %Five_h = call target("dx.RawBuffer", i16, 1, 0)
+            @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i16_1_0t(
+                  i32 0, i32 6, i32 1, i32 0, i1 false)
+  store target("dx.RawBuffer", i16, 1, 0) %Five_h, ptr @Five, align 4
+  
+  ; RasterizerOrderedBuffer<int4> Six : register(u7);
+  %Six_h = call target("dx.TypedBuffer", <4 x i32>, 1, 1, 1)
+            @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_v4i32_1_1_1t(
+                  i32 0, i32 7, i32 1, i32 0, i1 false)
+  store target("dx.TypedBuffer", <4 x i32>, 1, 1, 1) %Six_h, ptr @Six, align 4
+
+  ; Rasterize...
[truncated]

Copy link
Contributor

@bogner bogner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One issue with inaccurate comments but otherwise LGTM!

@hekota hekota changed the title [HLSL][NFC] Update resource metadata tests to not use obsolete metadata annotations [HLSL][NFC] Update resource metadata tests to not use obsolete annotations Mar 7, 2025
@tex3d tex3d self-assigned this Mar 11, 2025
Copy link
Contributor

@tex3d tex3d left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@tex3d tex3d removed their assignment Mar 11, 2025
@hekota hekota merged commit 8d7cb5d into llvm:main Mar 12, 2025
12 checks passed
@damyanp damyanp moved this to Closed in HLSL Support Apr 25, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend:DirectX clang Clang issues not falling into any other category HLSL HLSL Language Support
Projects
Status: Closed
Development

Successfully merging this pull request may close these issues.

4 participants