[llvm] [HLSL] Move Resouce Instance Properties from TypeInfo (PR #135259)

Ashley Coleman via llvm-commits llvm-commits at lists.llvm.org
Fri Apr 11 09:10:34 PDT 2025


https://github.com/V-FEXrt updated https://github.com/llvm/llvm-project/pull/135259

>From a7998f34a897cbcdefb836e394983830610957c5 Mon Sep 17 00:00:00 2001
From: Ashley Coleman <ascoleman at microsoft.com>
Date: Thu, 10 Apr 2025 14:55:56 -0600
Subject: [PATCH 1/2] [HLSL] Move Resouce Instance Properties from TypeInfo

---
 llvm/include/llvm/Analysis/DXILResource.h     | 41 +++++++-----------
 llvm/lib/Analysis/DXILResource.cpp            | 28 ++++++-------
 .../lib/Target/DirectX/DXContainerGlobals.cpp |  2 +-
 llvm/lib/Target/DirectX/DXILPrettyPrinter.cpp |  4 +-
 .../DXILResource/buffer-frombinding.ll        | 30 ++++++-------
 llvm/unittests/Analysis/DXILResourceTest.cpp  | 42 +++++++++----------
 6 files changed, 66 insertions(+), 81 deletions(-)

diff --git a/llvm/include/llvm/Analysis/DXILResource.h b/llvm/include/llvm/Analysis/DXILResource.h
index ff7961c9ad51c..6ff4e2fb56006 100644
--- a/llvm/include/llvm/Analysis/DXILResource.h
+++ b/llvm/include/llvm/Analysis/DXILResource.h
@@ -222,19 +222,11 @@ class LayoutExtType : public TargetExtType {
 class ResourceTypeInfo {
 public:
   struct UAVInfo {
-    bool GloballyCoherent;
-    bool HasCounter;
     bool IsROV;
 
-    bool operator==(const UAVInfo &RHS) const {
-      return std::tie(GloballyCoherent, HasCounter, IsROV) ==
-             std::tie(RHS.GloballyCoherent, RHS.HasCounter, RHS.IsROV);
-    }
+    bool operator==(const UAVInfo &RHS) const { return IsROV == RHS.IsROV; }
     bool operator!=(const UAVInfo &RHS) const { return !(*this == RHS); }
-    bool operator<(const UAVInfo &RHS) const {
-      return std::tie(GloballyCoherent, HasCounter, IsROV) <
-             std::tie(RHS.GloballyCoherent, RHS.HasCounter, RHS.IsROV);
-    }
+    bool operator<(const UAVInfo &RHS) const { return IsROV < RHS.IsROV; }
   };
 
   struct StructInfo {
@@ -272,23 +264,14 @@ class ResourceTypeInfo {
 private:
   TargetExtType *HandleTy;
 
-  // GloballyCoherent and HasCounter aren't really part of the type and need to
-  // be determined by analysis, so they're just provided directly by the
-  // DXILResourceTypeMap when we construct these.
-  bool GloballyCoherent;
-  bool HasCounter;
-
   dxil::ResourceClass RC;
   dxil::ResourceKind Kind;
 
 public:
   ResourceTypeInfo(TargetExtType *HandleTy, const dxil::ResourceClass RC,
-                   const dxil::ResourceKind Kind, bool GloballyCoherent = false,
-                   bool HasCounter = false);
-  ResourceTypeInfo(TargetExtType *HandleTy, bool GloballyCoherent = false,
-                   bool HasCounter = false)
-      : ResourceTypeInfo(HandleTy, {}, dxil::ResourceKind::Invalid,
-                         GloballyCoherent, HasCounter) {}
+                   const dxil::ResourceKind Kind);
+  ResourceTypeInfo(TargetExtType *HandleTy)
+      : ResourceTypeInfo(HandleTy, {}, dxil::ResourceKind::Invalid) {}
 
   TargetExtType *getHandleTy() const { return HandleTy; }
   StructType *createElementStruct();
@@ -314,9 +297,6 @@ class ResourceTypeInfo {
   dxil::ResourceClass getResourceClass() const { return RC; }
   dxil::ResourceKind getResourceKind() const { return Kind; }
 
-  void setGloballyCoherent(bool V) { GloballyCoherent = V; }
-  void setHasCounter(bool V) { HasCounter = V; }
-
   bool operator==(const ResourceTypeInfo &RHS) const;
   bool operator!=(const ResourceTypeInfo &RHS) const { return !(*this == RHS); }
   bool operator<(const ResourceTypeInfo &RHS) const;
@@ -353,13 +333,20 @@ class ResourceInfo {
   GlobalVariable *Symbol = nullptr;
 
 public:
+  bool GloballyCoherent;
+  bool HasCounter;
+
   ResourceInfo(uint32_t RecordID, uint32_t Space, uint32_t LowerBound,
                uint32_t Size, TargetExtType *HandleTy,
-               GlobalVariable *Symbol = nullptr)
+               GlobalVariable *Symbol = nullptr, bool GloballyCoherent = false,
+               bool HasCounter = false)
       : Binding{RecordID, Space, LowerBound, Size}, HandleTy(HandleTy),
-        Symbol(Symbol) {}
+        Symbol(Symbol), GloballyCoherent(GloballyCoherent),
+        HasCounter(HasCounter) {}
 
   void setBindingID(unsigned ID) { Binding.RecordID = ID; }
+  void setGloballyCoherent(bool V) { GloballyCoherent = V; }
+  void setHasCounter(bool V) { HasCounter = V; }
 
   const ResourceBinding &getBinding() const { return Binding; }
   TargetExtType *getHandleTy() const { return HandleTy; }
diff --git a/llvm/lib/Analysis/DXILResource.cpp b/llvm/lib/Analysis/DXILResource.cpp
index b4bd43206b6e4..d4f0127a931dc 100644
--- a/llvm/lib/Analysis/DXILResource.cpp
+++ b/llvm/lib/Analysis/DXILResource.cpp
@@ -179,10 +179,8 @@ static dxil::ElementType toDXILElementType(Type *Ty, bool IsSigned) {
 
 ResourceTypeInfo::ResourceTypeInfo(TargetExtType *HandleTy,
                                    const dxil::ResourceClass RC_,
-                                   const dxil::ResourceKind Kind_,
-                                   bool GloballyCoherent, bool HasCounter)
-    : HandleTy(HandleTy), GloballyCoherent(GloballyCoherent),
-      HasCounter(HasCounter) {
+                                   const dxil::ResourceKind Kind_)
+    : HandleTy(HandleTy) {
   // If we're provided a resource class and kind, trust them.
   if (Kind_ != dxil::ResourceKind::Invalid) {
     RC = RC_;
@@ -377,7 +375,7 @@ static bool isROV(dxil::ResourceKind Kind, TargetExtType *Ty) {
 
 ResourceTypeInfo::UAVInfo ResourceTypeInfo::getUAV() const {
   assert(isUAV() && "Not a UAV");
-  return {GloballyCoherent, HasCounter, isROV(Kind, HandleTy)};
+  return {isROV(Kind, HandleTy)};
 }
 
 uint32_t ResourceTypeInfo::getCBufferSize(const DataLayout &DL) const {
@@ -469,8 +467,7 @@ uint32_t ResourceTypeInfo::getMultiSampleCount() const {
 }
 
 bool ResourceTypeInfo::operator==(const ResourceTypeInfo &RHS) const {
-  return std::tie(HandleTy, GloballyCoherent, HasCounter) ==
-         std::tie(RHS.HandleTy, RHS.GloballyCoherent, RHS.HasCounter);
+  return std::tie(HandleTy) == std::tie(RHS.HandleTy);
 }
 
 bool ResourceTypeInfo::operator<(const ResourceTypeInfo &RHS) const {
@@ -510,9 +507,7 @@ void ResourceTypeInfo::print(raw_ostream &OS, const DataLayout &DL) const {
   } else {
     if (isUAV()) {
       UAVInfo UAVFlags = getUAV();
-      OS << "  Globally Coherent: " << UAVFlags.GloballyCoherent << "\n"
-         << "  HasCounter: " << UAVFlags.HasCounter << "\n"
-         << "  IsROV: " << UAVFlags.IsROV << "\n";
+      OS << "  IsROV: " << UAVFlags.IsROV << "\n";
     }
     if (isMultiSample())
       OS << "  Sample Count: " << getMultiSampleCount() << "\n";
@@ -577,8 +572,8 @@ MDTuple *ResourceInfo::getAsMetadata(Module &M,
 
     if (RTI.isUAV()) {
       ResourceTypeInfo::UAVInfo UAVFlags = RTI.getUAV();
-      MDVals.push_back(getBoolMD(UAVFlags.GloballyCoherent));
-      MDVals.push_back(getBoolMD(UAVFlags.HasCounter));
+      MDVals.push_back(getBoolMD(GloballyCoherent));
+      MDVals.push_back(getBoolMD(HasCounter));
       MDVals.push_back(getBoolMD(UAVFlags.IsROV));
     } else {
       // All SRVs include sample count in the metadata, but it's only meaningful
@@ -619,10 +614,10 @@ ResourceInfo::getAnnotateProps(Module &M, dxil::ResourceTypeInfo &RTI) const {
   ResourceTypeInfo::UAVInfo UAVFlags =
       IsUAV ? RTI.getUAV() : ResourceTypeInfo::UAVInfo{};
   bool IsROV = IsUAV && UAVFlags.IsROV;
-  bool IsGloballyCoherent = IsUAV && UAVFlags.GloballyCoherent;
+  bool IsGloballyCoherent = IsUAV && GloballyCoherent;
   uint8_t SamplerCmpOrHasCounter = 0;
   if (IsUAV)
-    SamplerCmpOrHasCounter = UAVFlags.HasCounter;
+    SamplerCmpOrHasCounter = HasCounter;
   else if (RTI.isSampler())
     SamplerCmpOrHasCounter = RTI.getSamplerType() == SamplerType::Comparison;
 
@@ -671,6 +666,9 @@ void ResourceInfo::print(raw_ostream &OS, dxil::ResourceTypeInfo &RTI,
      << "    Lower Bound: " << Binding.LowerBound << "\n"
      << "    Size: " << Binding.Size << "\n";
 
+  OS << "  Globally Coherent: " << GloballyCoherent << "\n";
+  OS << "  HasCounter: " << HasCounter << "\n";
+
   RTI.print(OS, DL);
 }
 
@@ -767,7 +765,7 @@ void DXILResourceMap::populate(Module &M, DXILResourceTypeMap &DRTM) {
 void DXILResourceMap::print(raw_ostream &OS, DXILResourceTypeMap &DRTM,
                             const DataLayout &DL) const {
   for (unsigned I = 0, E = Infos.size(); I != E; ++I) {
-    OS << "Binding " << I << ":\n";
+    OS << "Resource " << I << ":\n";
     const dxil::ResourceInfo &RI = Infos[I];
     RI.print(OS, DRTM[RI.getHandleTy()], DL);
     OS << "\n";
diff --git a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp
index 27451074581ee..9576dd4a5e27b 100644
--- a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp
+++ b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp
@@ -229,7 +229,7 @@ void DXContainerGlobals::addResourcesForPSV(Module &M, PSVRuntimeInfo &PSV) {
 
     dxil::ResourceTypeInfo &TypeInfo = DRTM[RI.getHandleTy()];
     dxbc::PSV::ResourceType ResType;
-    if (TypeInfo.getUAV().HasCounter)
+    if (RI.HasCounter)
       ResType = dxbc::PSV::ResourceType::UAVStructuredWithCounter;
     else if (TypeInfo.isStruct())
       ResType = dxbc::PSV::ResourceType::UAVStructured;
diff --git a/llvm/lib/Target/DirectX/DXILPrettyPrinter.cpp b/llvm/lib/Target/DirectX/DXILPrettyPrinter.cpp
index 88e23479cba2a..095e79832f39f 100644
--- a/llvm/lib/Target/DirectX/DXILPrettyPrinter.cpp
+++ b/llvm/lib/Target/DirectX/DXILPrettyPrinter.cpp
@@ -155,8 +155,8 @@ struct FormatResourceDimension
     case dxil::ResourceKind::StructuredBuffer:
       if (!Item.isUAV())
         OS << "r/o";
-      else if (Item.getUAV().HasCounter)
-        OS << "r/w+cnt";
+      //      else if (Item.getUAV().HasCounter)
+      //        OS << "r/w+cnt";
       else
         OS << "r/w";
       break;
diff --git a/llvm/test/Analysis/DXILResource/buffer-frombinding.ll b/llvm/test/Analysis/DXILResource/buffer-frombinding.ll
index 9b4d7722b72ac..b8f092ab4e514 100644
--- a/llvm/test/Analysis/DXILResource/buffer-frombinding.ll
+++ b/llvm/test/Analysis/DXILResource/buffer-frombinding.ll
@@ -7,7 +7,7 @@ define void @test_typedbuffer() {
   %srv0 = call target("dx.RawBuffer", void, 0, 0)
       @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i8_0_0t(
           i32 1, i32 8, i32 1, i32 0, i1 false)
-  ; CHECK: Binding [[SRV0:[0-9]+]]:
+  ; CHECK: Resource [[SRV0:[0-9]+]]:
   ; CHECK:   Binding:
   ; CHECK:     Record ID: 0
   ; CHECK:     Space: 1
@@ -21,7 +21,7 @@ define void @test_typedbuffer() {
   %srv1 = call target("dx.RawBuffer", {<4 x float>, <4 x i32>}, 0, 0)
       @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_sl_v4f32v4i32s_0_0t(
           i32 4, i32 2, i32 1, i32 0, i1 false)
-  ; CHECK: Binding [[SRV1:[0-9]+]]:
+  ; CHECK: Resource [[SRV1:[0-9]+]]:
   ; CHECK:   Binding:
   ; CHECK:     Record ID: 1
   ; CHECK:     Space: 4
@@ -36,7 +36,7 @@ define void @test_typedbuffer() {
   %srv2 = call target("dx.TypedBuffer", <4 x i32>, 0, 0, 0)
       @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_i32_0_0t(
           i32 5, i32 3, i32 24, i32 0, i1 false)
-  ; CHECK: Binding [[SRV2:[0-9]+]]:
+  ; CHECK: Resource [[SRV2:[0-9]+]]:
   ; CHECK:   Binding:
   ; CHECK:     Record ID: 2
   ; CHECK:     Space: 5
@@ -51,16 +51,16 @@ define void @test_typedbuffer() {
   %uav0 = call target("dx.TypedBuffer", i32, 1, 0, 1)
       @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_i32_1_0t(
           i32 2, i32 7, i32 1, i32 0, i1 false)
-  ; CHECK: Binding [[UAV0:[0-9]+]]:
+  ; CHECK: Resource [[UAV0:[0-9]+]]:
   ; CHECK:   Binding:
   ; CHECK:     Record ID: 0
   ; CHECK:     Space: 2
   ; CHECK:     Lower Bound: 7
   ; CHECK:     Size: 1
-  ; CHECK:   Class: UAV
-  ; CHECK:   Kind: TypedBuffer
   ; CHECK:   Globally Coherent: 0
   ; CHECK:   HasCounter: 0
+  ; CHECK:   Class: UAV
+  ; CHECK:   Kind: TypedBuffer
   ; CHECK:   IsROV: 0
   ; CHECK:   Element Type: i32
   ; CHECK:   Element Count: 1
@@ -69,16 +69,16 @@ define void @test_typedbuffer() {
   %uav1 = call target("dx.TypedBuffer", <4 x float>, 1, 0, 0)
               @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0(
                   i32 3, i32 5, i32 1, i32 0, i1 false)
-  ; CHECK: Binding [[UAV1:[0-9]+]]:
+  ; CHECK: Resource [[UAV1:[0-9]+]]:
   ; CHECK:   Binding:
   ; CHECK:     Record ID: 1
   ; CHECK:     Space: 3
   ; CHECK:     Lower Bound: 5
   ; CHECK:     Size: 1
-  ; CHECK:   Class: UAV
-  ; CHECK:   Kind: TypedBuffer
   ; CHECK:   Globally Coherent: 0
   ; CHECK:   HasCounter: 0
+  ; CHECK:   Class: UAV
+  ; CHECK:   Kind: TypedBuffer
   ; CHECK:   IsROV: 0
   ; CHECK:   Element Type: f32
   ; CHECK:   Element Count: 4
@@ -92,23 +92,23 @@ define void @test_typedbuffer() {
   %uav2_2 = call target("dx.TypedBuffer", <4 x float>, 1, 0, 0)
               @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0(
                   i32 4, i32 0, i32 10, i32 5, i1 false)
-  ; CHECK: Binding [[UAV2:[0-9]+]]:
+  ; CHECK: Resource [[UAV2:[0-9]+]]:
   ; CHECK:   Binding:
   ; CHECK:     Record ID: 2
   ; CHECK:     Space: 4
   ; CHECK:     Lower Bound: 0
   ; CHECK:     Size: 10
-  ; CHECK:   Class: UAV
-  ; CHECK:   Kind: TypedBuffer
   ; CHECK:   Globally Coherent: 0
   ; CHECK:   HasCounter: 0
+  ; CHECK:   Class: UAV
+  ; CHECK:   Kind: TypedBuffer
   ; CHECK:   IsROV: 0
   ; CHECK:   Element Type: f32
   ; CHECK:   Element Count: 4
 
   %cb0 = call target("dx.CBuffer", {float})
       @llvm.dx.resource.handlefrombinding(i32 1, i32 0, i32 1, i32 0, i1 false)
-  ; CHECK: Binding [[CB0:[0-9]+]]:
+  ; CHECK: Resource [[CB0:[0-9]+]]:
   ; CHECK:   Binding:
   ; CHECK:     Record ID: 0
   ; CHECK:     Space: 1
@@ -120,7 +120,7 @@ define void @test_typedbuffer() {
 
   %cb1 = call target("dx.CBuffer", target("dx.Layout", {float}, 4, 0))
       @llvm.dx.resource.handlefrombinding(i32 1, i32 8, i32 1, i32 0, i1 false)
-  ; CHECK: Binding [[CB1:[0-9]+]]:
+  ; CHECK: Resource [[CB1:[0-9]+]]:
   ; CHECK:   Binding:
   ; CHECK:     Record ID: 1
   ; CHECK:     Space: 1
@@ -130,7 +130,7 @@ define void @test_typedbuffer() {
   ; CHECK:   Kind: CBuffer
   ; CHECK:   CBuffer size: 4
 
-  ; CHECK-NOT: Binding {{[0-9]+}}:
+  ; CHECK-NOT: Resource {{[0-9]+}}:
 
   ret void
 }
diff --git a/llvm/unittests/Analysis/DXILResourceTest.cpp b/llvm/unittests/Analysis/DXILResourceTest.cpp
index 6f25983801fc3..3a7c7ab6efd92 100644
--- a/llvm/unittests/Analysis/DXILResourceTest.cpp
+++ b/llvm/unittests/Analysis/DXILResourceTest.cpp
@@ -114,8 +114,6 @@ TEST(DXILResource, AnnotationsAndMetadata) {
     ResourceTypeInfo RTI(llvm::TargetExtType::get(
         Context, "dx.RawBuffer", Int8Ty, {/*IsWriteable=*/1, /*IsROV=*/0}));
     EXPECT_EQ(RTI.getResourceClass(), ResourceClass::UAV);
-    EXPECT_EQ(RTI.getUAV().GloballyCoherent, false);
-    EXPECT_EQ(RTI.getUAV().HasCounter, false);
     EXPECT_EQ(RTI.getUAV().IsROV, false);
     EXPECT_EQ(RTI.getResourceKind(), ResourceKind::RawBuffer);
 
@@ -128,6 +126,8 @@ TEST(DXILResource, AnnotationsAndMetadata) {
     EXPECT_MDEQ(RI.getAsMetadata(M, RTI),
                 TestMD.get(1, GV, "BufferOut", 2, 3, 1, 11, false, false, false,
                            nullptr));
+    EXPECT_EQ(RI.GloballyCoherent, false);
+    EXPECT_EQ(RI.HasCounter, false);
   }
 
   // struct BufType0 { int i; float f; double d; };
@@ -268,27 +268,28 @@ TEST(DXILResource, AnnotationsAndMetadata) {
   // globallycoherent RWTexture2D<int2> OutputTexture : register(u0, space2);
   {
     ResourceTypeInfo RTI(llvm::TargetExtType::get(
-                             Context, "dx.Texture", Int32x2Ty,
-                             {/*IsWriteable=*/1,
-                              /*IsROV=*/0, /*IsSigned=*/1,
-                              llvm::to_underlying(ResourceKind::Texture2D)}),
-                         /*GloballyCoherent=*/true, /*HasCounter=*/false);
+        Context, "dx.Texture", Int32x2Ty,
+        {/*IsWriteable=*/1,
+         /*IsROV=*/0, /*IsSigned=*/1,
+         llvm::to_underlying(ResourceKind::Texture2D)}));
 
     EXPECT_EQ(RTI.getResourceClass(), ResourceClass::UAV);
-    EXPECT_EQ(RTI.getUAV().GloballyCoherent, true);
-    EXPECT_EQ(RTI.getUAV().HasCounter, false);
     EXPECT_EQ(RTI.getUAV().IsROV, false);
     EXPECT_EQ(RTI.getResourceKind(), ResourceKind::Texture2D);
 
     ResourceInfo RI(
         /*RecordID=*/0, /*Space=*/2, /*LowerBound=*/0, /*Size=*/1,
-        RTI.getHandleTy());
+        RTI.getHandleTy(),
+        /*Symbol=*/nullptr, /*GloballyCoherent=*/true, /*HasCounter=*/false);
     GlobalVariable *GV =
         RI.createSymbol(M, RTI.createElementStruct(), "OutputTexture");
     EXPECT_PROPS_EQ(RI.getAnnotateProps(M, RTI), 0x00005002U, 0x00000204U);
     EXPECT_MDEQ(RI.getAsMetadata(M, RTI),
                 TestMD.get(0, GV, "OutputTexture", 2, 0, 1, 2, true, false,
                            false, TestMD.get(0, 4)));
+
+    EXPECT_EQ(RI.GloballyCoherent, true);
+    EXPECT_EQ(RI.HasCounter, false);
   }
 
   // RasterizerOrderedBuffer<float4> ROB;
@@ -297,8 +298,6 @@ TEST(DXILResource, AnnotationsAndMetadata) {
         Context, "dx.TypedBuffer", Floatx4Ty,
         {/*IsWriteable=*/1, /*IsROV=*/1, /*IsSigned=*/0}));
     EXPECT_EQ(RTI.getResourceClass(), ResourceClass::UAV);
-    EXPECT_EQ(RTI.getUAV().GloballyCoherent, false);
-    EXPECT_EQ(RTI.getUAV().HasCounter, false);
     EXPECT_EQ(RTI.getUAV().IsROV, true);
     ASSERT_EQ(RTI.isTyped(), true);
     EXPECT_EQ(RTI.getTyped().ElementTy, ElementType::F32);
@@ -313,19 +312,17 @@ TEST(DXILResource, AnnotationsAndMetadata) {
     EXPECT_MDEQ(RI.getAsMetadata(M, RTI),
                 TestMD.get(0, GV, "ROB", 0, 0, 1, 10, false, false, true,
                            TestMD.get(0, 9)));
+    EXPECT_EQ(RI.GloballyCoherent, false);
+    EXPECT_EQ(RI.HasCounter, false);
   }
 
   // RWStructuredBuffer<ParticleMotion> g_OutputBuffer : register(u2);
   {
     StructType *BufType1 = StructType::create(
         Context, {Floatx3Ty, FloatTy, Int32Ty}, "ParticleMotion");
-    ResourceTypeInfo RTI(
-        llvm::TargetExtType::get(Context, "dx.RawBuffer", BufType1,
-                                 {/*IsWriteable=*/1, /*IsROV=*/0}),
-        /*GloballyCoherent=*/false, /*HasCounter=*/true);
+    ResourceTypeInfo RTI(llvm::TargetExtType::get(
+        Context, "dx.RawBuffer", BufType1, {/*IsWriteable=*/1, /*IsROV=*/0}));
     EXPECT_EQ(RTI.getResourceClass(), ResourceClass::UAV);
-    EXPECT_EQ(RTI.getUAV().GloballyCoherent, false);
-    EXPECT_EQ(RTI.getUAV().HasCounter, true);
     EXPECT_EQ(RTI.getUAV().IsROV, false);
     ASSERT_EQ(RTI.isStruct(), true);
     EXPECT_EQ(RTI.getStruct(DL).Stride, 20u);
@@ -334,13 +331,16 @@ TEST(DXILResource, AnnotationsAndMetadata) {
 
     ResourceInfo RI(
         /*RecordID=*/0, /*Space=*/0, /*LowerBound=*/2, /*Size=*/1,
-        RTI.getHandleTy());
+        RTI.getHandleTy(),
+        /*Symbol=*/nullptr, /*GloballyCoherent=*/false, /*HasCounter=*/true);
     GlobalVariable *GV =
         RI.createSymbol(M, RTI.createElementStruct(), "g_OutputBuffer");
     EXPECT_PROPS_EQ(RI.getAnnotateProps(M, RTI), 0x0000920cU, 0x00000014U);
     EXPECT_MDEQ(RI.getAsMetadata(M, RTI),
                 TestMD.get(0, GV, "g_OutputBuffer", 0, 2, 1, 12, false, true,
                            false, TestMD.get(1, 20)));
+    EXPECT_EQ(RI.GloballyCoherent, false);
+    EXPECT_EQ(RI.HasCounter, true);
   }
 
   // RWTexture2DMSArray<uint, 8> g_rw_t2dmsa;
@@ -350,8 +350,6 @@ TEST(DXILResource, AnnotationsAndMetadata) {
         {/*IsWriteable=*/1, /*SampleCount=*/8, /*IsSigned=*/0,
          llvm::to_underlying(ResourceKind::Texture2DMSArray)}));
     EXPECT_EQ(RTI.getResourceClass(), ResourceClass::UAV);
-    EXPECT_EQ(RTI.getUAV().GloballyCoherent, false);
-    EXPECT_EQ(RTI.getUAV().HasCounter, false);
     EXPECT_EQ(RTI.getUAV().IsROV, false);
     ASSERT_EQ(RTI.isTyped(), true);
     EXPECT_EQ(RTI.getTyped().ElementTy, ElementType::U32);
@@ -369,6 +367,8 @@ TEST(DXILResource, AnnotationsAndMetadata) {
     EXPECT_MDEQ(RI.getAsMetadata(M, RTI),
                 TestMD.get(0, GV, "g_rw_t2dmsa", 0, 0, 1, 8, false, false,
                            false, TestMD.get(0, 5)));
+    EXPECT_EQ(RI.GloballyCoherent, false);
+    EXPECT_EQ(RI.HasCounter, false);
   }
 
   // cbuffer cb0 { float4 g_X; float4 g_Y; }

>From 8c8a560dfc596bf9f87ed1f9f3042b17b0605a01 Mon Sep 17 00:00:00 2001
From: Ashley Coleman <ascoleman at microsoft.com>
Date: Fri, 11 Apr 2025 10:10:00 -0600
Subject: [PATCH 2/2] Address Comments

---
 llvm/include/llvm/Analysis/DXILResource.h     | 23 +++++++++++++------
 llvm/lib/Analysis/DXILResource.cpp            | 21 ++++++++++++++---
 .../lib/Target/DirectX/DXContainerGlobals.cpp |  2 +-
 .../DXILResource/buffer-frombinding.ll        |  6 ++---
 llvm/unittests/Analysis/DXILResourceTest.cpp  | 23 +++++++++++--------
 5 files changed, 52 insertions(+), 23 deletions(-)

diff --git a/llvm/include/llvm/Analysis/DXILResource.h b/llvm/include/llvm/Analysis/DXILResource.h
index 6ff4e2fb56006..e9b746d8096ee 100644
--- a/llvm/include/llvm/Analysis/DXILResource.h
+++ b/llvm/include/llvm/Analysis/DXILResource.h
@@ -306,6 +306,13 @@ class ResourceTypeInfo {
 
 //===----------------------------------------------------------------------===//
 
+enum class ResourceCounterDirection {
+  Increment,
+  Decrement,
+  Unknown,
+  Invalid,
+};
+
 class ResourceInfo {
 public:
   struct ResourceBinding {
@@ -333,20 +340,22 @@ class ResourceInfo {
   GlobalVariable *Symbol = nullptr;
 
 public:
-  bool GloballyCoherent;
-  bool HasCounter;
+  bool GloballyCoherent = false;
+  ResourceCounterDirection CounterDirection = ResourceCounterDirection::Unknown;
 
   ResourceInfo(uint32_t RecordID, uint32_t Space, uint32_t LowerBound,
                uint32_t Size, TargetExtType *HandleTy,
-               GlobalVariable *Symbol = nullptr, bool GloballyCoherent = false,
-               bool HasCounter = false)
+               GlobalVariable *Symbol = nullptr)
       : Binding{RecordID, Space, LowerBound, Size}, HandleTy(HandleTy),
-        Symbol(Symbol), GloballyCoherent(GloballyCoherent),
-        HasCounter(HasCounter) {}
+        Symbol(Symbol) {}
 
   void setBindingID(unsigned ID) { Binding.RecordID = ID; }
   void setGloballyCoherent(bool V) { GloballyCoherent = V; }
-  void setHasCounter(bool V) { HasCounter = V; }
+  void setCounterDirection(ResourceCounterDirection V) { CounterDirection = V; }
+
+  bool hasCounter() const {
+    return CounterDirection != ResourceCounterDirection::Unknown;
+  }
 
   const ResourceBinding &getBinding() const { return Binding; }
   TargetExtType *getHandleTy() const { return HandleTy; }
diff --git a/llvm/lib/Analysis/DXILResource.cpp b/llvm/lib/Analysis/DXILResource.cpp
index d4f0127a931dc..7777e16ea9768 100644
--- a/llvm/lib/Analysis/DXILResource.cpp
+++ b/llvm/lib/Analysis/DXILResource.cpp
@@ -573,7 +573,7 @@ MDTuple *ResourceInfo::getAsMetadata(Module &M,
     if (RTI.isUAV()) {
       ResourceTypeInfo::UAVInfo UAVFlags = RTI.getUAV();
       MDVals.push_back(getBoolMD(GloballyCoherent));
-      MDVals.push_back(getBoolMD(HasCounter));
+      MDVals.push_back(getBoolMD(hasCounter()));
       MDVals.push_back(getBoolMD(UAVFlags.IsROV));
     } else {
       // All SRVs include sample count in the metadata, but it's only meaningful
@@ -617,7 +617,7 @@ ResourceInfo::getAnnotateProps(Module &M, dxil::ResourceTypeInfo &RTI) const {
   bool IsGloballyCoherent = IsUAV && GloballyCoherent;
   uint8_t SamplerCmpOrHasCounter = 0;
   if (IsUAV)
-    SamplerCmpOrHasCounter = HasCounter;
+    SamplerCmpOrHasCounter = hasCounter();
   else if (RTI.isSampler())
     SamplerCmpOrHasCounter = RTI.getSamplerType() == SamplerType::Comparison;
 
@@ -667,7 +667,22 @@ void ResourceInfo::print(raw_ostream &OS, dxil::ResourceTypeInfo &RTI,
      << "    Size: " << Binding.Size << "\n";
 
   OS << "  Globally Coherent: " << GloballyCoherent << "\n";
-  OS << "  HasCounter: " << HasCounter << "\n";
+  OS << "  Counter Direction: ";
+
+  switch (CounterDirection) {
+  case ResourceCounterDirection::Increment:
+    OS << "Increment\n";
+    break;
+  case ResourceCounterDirection::Decrement:
+    OS << "Decrement\n";
+    break;
+  case ResourceCounterDirection::Unknown:
+    OS << "Unknown\n";
+    break;
+  case ResourceCounterDirection::Invalid:
+    OS << "Invalid\n";
+    break;
+  }
 
   RTI.print(OS, DL);
 }
diff --git a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp
index 9576dd4a5e27b..0aa6516db636c 100644
--- a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp
+++ b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp
@@ -229,7 +229,7 @@ void DXContainerGlobals::addResourcesForPSV(Module &M, PSVRuntimeInfo &PSV) {
 
     dxil::ResourceTypeInfo &TypeInfo = DRTM[RI.getHandleTy()];
     dxbc::PSV::ResourceType ResType;
-    if (RI.HasCounter)
+    if (RI.hasCounter())
       ResType = dxbc::PSV::ResourceType::UAVStructuredWithCounter;
     else if (TypeInfo.isStruct())
       ResType = dxbc::PSV::ResourceType::UAVStructured;
diff --git a/llvm/test/Analysis/DXILResource/buffer-frombinding.ll b/llvm/test/Analysis/DXILResource/buffer-frombinding.ll
index b8f092ab4e514..81c8b5530afb6 100644
--- a/llvm/test/Analysis/DXILResource/buffer-frombinding.ll
+++ b/llvm/test/Analysis/DXILResource/buffer-frombinding.ll
@@ -58,7 +58,7 @@ define void @test_typedbuffer() {
   ; CHECK:     Lower Bound: 7
   ; CHECK:     Size: 1
   ; CHECK:   Globally Coherent: 0
-  ; CHECK:   HasCounter: 0
+  ; CHECK:   Counter Direction: Unknown
   ; CHECK:   Class: UAV
   ; CHECK:   Kind: TypedBuffer
   ; CHECK:   IsROV: 0
@@ -76,7 +76,7 @@ define void @test_typedbuffer() {
   ; CHECK:     Lower Bound: 5
   ; CHECK:     Size: 1
   ; CHECK:   Globally Coherent: 0
-  ; CHECK:   HasCounter: 0
+  ; CHECK:   Counter Direction: Unknown
   ; CHECK:   Class: UAV
   ; CHECK:   Kind: TypedBuffer
   ; CHECK:   IsROV: 0
@@ -99,7 +99,7 @@ define void @test_typedbuffer() {
   ; CHECK:     Lower Bound: 0
   ; CHECK:     Size: 10
   ; CHECK:   Globally Coherent: 0
-  ; CHECK:   HasCounter: 0
+  ; CHECK:   Counter Direction: Unknown
   ; CHECK:   Class: UAV
   ; CHECK:   Kind: TypedBuffer
   ; CHECK:   IsROV: 0
diff --git a/llvm/unittests/Analysis/DXILResourceTest.cpp b/llvm/unittests/Analysis/DXILResourceTest.cpp
index 3a7c7ab6efd92..ed82a1ba0730a 100644
--- a/llvm/unittests/Analysis/DXILResourceTest.cpp
+++ b/llvm/unittests/Analysis/DXILResourceTest.cpp
@@ -127,7 +127,8 @@ TEST(DXILResource, AnnotationsAndMetadata) {
                 TestMD.get(1, GV, "BufferOut", 2, 3, 1, 11, false, false, false,
                            nullptr));
     EXPECT_EQ(RI.GloballyCoherent, false);
-    EXPECT_EQ(RI.HasCounter, false);
+    EXPECT_EQ(RI.hasCounter(), false);
+    EXPECT_EQ(RI.CounterDirection, ResourceCounterDirection::Unknown);
   }
 
   // struct BufType0 { int i; float f; double d; };
@@ -279,8 +280,8 @@ TEST(DXILResource, AnnotationsAndMetadata) {
 
     ResourceInfo RI(
         /*RecordID=*/0, /*Space=*/2, /*LowerBound=*/0, /*Size=*/1,
-        RTI.getHandleTy(),
-        /*Symbol=*/nullptr, /*GloballyCoherent=*/true, /*HasCounter=*/false);
+        RTI.getHandleTy());
+    RI.setGloballyCoherent(true);
     GlobalVariable *GV =
         RI.createSymbol(M, RTI.createElementStruct(), "OutputTexture");
     EXPECT_PROPS_EQ(RI.getAnnotateProps(M, RTI), 0x00005002U, 0x00000204U);
@@ -289,7 +290,8 @@ TEST(DXILResource, AnnotationsAndMetadata) {
                            false, TestMD.get(0, 4)));
 
     EXPECT_EQ(RI.GloballyCoherent, true);
-    EXPECT_EQ(RI.HasCounter, false);
+    EXPECT_EQ(RI.hasCounter(), false);
+    EXPECT_EQ(RI.CounterDirection, ResourceCounterDirection::Unknown);
   }
 
   // RasterizerOrderedBuffer<float4> ROB;
@@ -313,7 +315,8 @@ TEST(DXILResource, AnnotationsAndMetadata) {
                 TestMD.get(0, GV, "ROB", 0, 0, 1, 10, false, false, true,
                            TestMD.get(0, 9)));
     EXPECT_EQ(RI.GloballyCoherent, false);
-    EXPECT_EQ(RI.HasCounter, false);
+    EXPECT_EQ(RI.hasCounter(), false);
+    EXPECT_EQ(RI.CounterDirection, ResourceCounterDirection::Unknown);
   }
 
   // RWStructuredBuffer<ParticleMotion> g_OutputBuffer : register(u2);
@@ -331,8 +334,8 @@ TEST(DXILResource, AnnotationsAndMetadata) {
 
     ResourceInfo RI(
         /*RecordID=*/0, /*Space=*/0, /*LowerBound=*/2, /*Size=*/1,
-        RTI.getHandleTy(),
-        /*Symbol=*/nullptr, /*GloballyCoherent=*/false, /*HasCounter=*/true);
+        RTI.getHandleTy());
+    RI.setCounterDirection(ResourceCounterDirection::Increment);
     GlobalVariable *GV =
         RI.createSymbol(M, RTI.createElementStruct(), "g_OutputBuffer");
     EXPECT_PROPS_EQ(RI.getAnnotateProps(M, RTI), 0x0000920cU, 0x00000014U);
@@ -340,7 +343,8 @@ TEST(DXILResource, AnnotationsAndMetadata) {
                 TestMD.get(0, GV, "g_OutputBuffer", 0, 2, 1, 12, false, true,
                            false, TestMD.get(1, 20)));
     EXPECT_EQ(RI.GloballyCoherent, false);
-    EXPECT_EQ(RI.HasCounter, true);
+    EXPECT_EQ(RI.hasCounter(), true);
+    EXPECT_EQ(RI.CounterDirection, ResourceCounterDirection::Increment);
   }
 
   // RWTexture2DMSArray<uint, 8> g_rw_t2dmsa;
@@ -368,7 +372,8 @@ TEST(DXILResource, AnnotationsAndMetadata) {
                 TestMD.get(0, GV, "g_rw_t2dmsa", 0, 0, 1, 8, false, false,
                            false, TestMD.get(0, 5)));
     EXPECT_EQ(RI.GloballyCoherent, false);
-    EXPECT_EQ(RI.HasCounter, false);
+    EXPECT_EQ(RI.hasCounter(), false);
+    EXPECT_EQ(RI.CounterDirection, ResourceCounterDirection::Unknown);
   }
 
   // cbuffer cb0 { float4 g_X; float4 g_Y; }



More information about the llvm-commits mailing list