[llvm] [DirectX] Add Range Overlap validation (PR #152229)

via llvm-commits llvm-commits at lists.llvm.org
Fri Aug 8 13:04:45 PDT 2025


https://github.com/joaosaffran updated https://github.com/llvm/llvm-project/pull/152229

>From c95ce6866488ee12da119bc66a864fd0d6df367f Mon Sep 17 00:00:00 2001
From: joaosaffran <joao.saffran at microsoft.com>
Date: Thu, 26 Jun 2025 19:28:01 +0000
Subject: [PATCH 01/11] refactoring

refactoring

clean up

format

formating

fix import issues

formating

refactoring

init refactoring

adding validation

clean

implementing

finish implementing && fix tests

sync parent

sync parent

address comments

fix test

fix tests

format

address changes

add preserved

addressing comments

updating

format

adding tests

clean up

address comments

adding root constants

clean

moving code arround

clean

addressing comments

address comments

update code

cleanup

address comments from inbelic
---
 llvm/include/llvm/Analysis/DXILResource.h     |  14 ++
 llvm/include/llvm/Frontend/HLSL/HLSLBinding.h |   3 +
 .../Frontend/HLSL/RootSignatureValidations.h  | 129 +++++++++++--
 .../llvm/MC/DXContainerRootSignature.h        |   2 -
 llvm/lib/Analysis/DXILResource.cpp            |  14 --
 llvm/lib/Frontend/HLSL/HLSLBinding.cpp        |  16 ++
 llvm/lib/Target/DirectX/DXILOpLowering.cpp    |   2 +
 .../DXILPostOptimizationValidation.cpp        | 178 +++++++++++++++++-
 llvm/lib/Target/DirectX/DXILPrepare.cpp       |   1 -
 llvm/lib/Target/DirectX/DXILRootSignature.cpp |   5 +-
 llvm/lib/Target/DirectX/DXILRootSignature.h   |  12 +-
 llvm/test/CodeGen/DirectX/llc-pipeline.ll     |   2 +-
 .../rootsignature-validation-constants.ll     |  22 +++
 .../rootsignature-validation-fail-cbuffer.ll  |  34 ++++
 ...rootsignature-validation-fail-constants.ll |  22 +++
 .../rootsignature-validation-fail-sampler.ll  |  31 +++
 .../rootsignature-validation-fail-srv.ll      |  30 +++
 .../rootsignature-validation-fail-uav.ll      |  30 +++
 .../DirectX/rootsignature-validation.ll       |  39 ++++
 19 files changed, 546 insertions(+), 40 deletions(-)
 create mode 100644 llvm/test/CodeGen/DirectX/rootsignature-validation-constants.ll
 create mode 100644 llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbuffer.ll
 create mode 100644 llvm/test/CodeGen/DirectX/rootsignature-validation-fail-constants.ll
 create mode 100644 llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler.ll
 create mode 100644 llvm/test/CodeGen/DirectX/rootsignature-validation-fail-srv.ll
 create mode 100644 llvm/test/CodeGen/DirectX/rootsignature-validation-fail-uav.ll
 create mode 100644 llvm/test/CodeGen/DirectX/rootsignature-validation.ll

diff --git a/llvm/include/llvm/Analysis/DXILResource.h b/llvm/include/llvm/Analysis/DXILResource.h
index 93c6bfb057ef5..96d631698af0a 100644
--- a/llvm/include/llvm/Analysis/DXILResource.h
+++ b/llvm/include/llvm/Analysis/DXILResource.h
@@ -33,6 +33,20 @@ class DXILResourceTypeMap;
 
 namespace dxil {
 
+inline StringRef getResourceClassName(ResourceClass RC) {
+  switch (RC) {
+  case ResourceClass::SRV:
+    return "SRV";
+  case ResourceClass::UAV:
+    return "UAV";
+  case ResourceClass::CBuffer:
+    return "CBuffer";
+  case ResourceClass::Sampler:
+    return "Sampler";
+  }
+  llvm_unreachable("Unhandled ResourceClass");
+}
+
 // Returns the resource name from dx_resource_handlefrombinding or
 // dx_resource_handlefromimplicitbinding call
 LLVM_ABI StringRef getResourceNameFromBindingCall(CallInst *CI);
diff --git a/llvm/include/llvm/Frontend/HLSL/HLSLBinding.h b/llvm/include/llvm/Frontend/HLSL/HLSLBinding.h
index 70a2eeb632f1b..af7f2402c0fa0 100644
--- a/llvm/include/llvm/Frontend/HLSL/HLSLBinding.h
+++ b/llvm/include/llvm/Frontend/HLSL/HLSLBinding.h
@@ -57,6 +57,7 @@ class BindingInfo {
     }
     // Size == -1 means unbounded array
     LLVM_ABI std::optional<uint32_t> findAvailableBinding(int32_t Size);
+    LLVM_ABI bool isBound(BindingRange B);
   };
 
   struct BindingSpaces {
@@ -95,6 +96,8 @@ class BindingInfo {
   LLVM_ABI std::optional<uint32_t>
   findAvailableBinding(dxil::ResourceClass RC, uint32_t Space, int32_t Size);
 
+  LLVM_ABI bool isBound(dxil::ResourceClass RC, uint32_t Space, BindingRange B);
+
   friend class BindingInfoBuilder;
 };
 
diff --git a/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h b/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h
index fde32a1fff591..bb6aeeb177412 100644
--- a/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h
+++ b/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h
@@ -16,7 +16,6 @@
 
 #include "llvm/ADT/IntervalMap.h"
 #include "llvm/Frontend/HLSL/HLSLRootSignature.h"
-#include "llvm/Support/Compiler.h"
 
 namespace llvm {
 namespace hlsl {
@@ -24,22 +23,118 @@ namespace rootsig {
 
 // Basic verification of RootElements
 
-LLVM_ABI bool verifyRootFlag(uint32_t Flags);
-LLVM_ABI bool verifyVersion(uint32_t Version);
-LLVM_ABI bool verifyRegisterValue(uint32_t RegisterValue);
-LLVM_ABI bool verifyRegisterSpace(uint32_t RegisterSpace);
-LLVM_ABI bool verifyRootDescriptorFlag(uint32_t Version, uint32_t FlagsVal);
-LLVM_ABI bool verifyRangeType(uint32_t Type);
-LLVM_ABI bool verifyDescriptorRangeFlag(uint32_t Version, uint32_t Type,
-                                        uint32_t FlagsVal);
-LLVM_ABI bool verifyNumDescriptors(uint32_t NumDescriptors);
-LLVM_ABI bool verifySamplerFilter(uint32_t Value);
-LLVM_ABI bool verifyAddress(uint32_t Address);
-LLVM_ABI bool verifyMipLODBias(float MipLODBias);
-LLVM_ABI bool verifyMaxAnisotropy(uint32_t MaxAnisotropy);
-LLVM_ABI bool verifyComparisonFunc(uint32_t ComparisonFunc);
-LLVM_ABI bool verifyBorderColor(uint32_t BorderColor);
-LLVM_ABI bool verifyLOD(float LOD);
+bool verifyRootFlag(uint32_t Flags);
+bool verifyVersion(uint32_t Version);
+bool verifyRegisterValue(uint32_t RegisterValue);
+bool verifyRegisterSpace(uint32_t RegisterSpace);
+bool verifyRootDescriptorFlag(uint32_t Version, uint32_t FlagsVal);
+bool verifyRangeType(uint32_t Type);
+bool verifyDescriptorRangeFlag(uint32_t Version, uint32_t Type,
+                               uint32_t FlagsVal);
+bool verifyNumDescriptors(uint32_t NumDescriptors);
+bool verifySamplerFilter(uint32_t Value);
+bool verifyAddress(uint32_t Address);
+bool verifyMipLODBias(float MipLODBias);
+bool verifyMaxAnisotropy(uint32_t MaxAnisotropy);
+bool verifyComparisonFunc(uint32_t ComparisonFunc);
+bool verifyBorderColor(uint32_t BorderColor);
+bool verifyLOD(float LOD);
+
+struct RangeInfo {
+  const static uint32_t Unbounded = ~0u;
+
+  // Interval information
+  uint32_t LowerBound;
+  uint32_t UpperBound;
+
+  // Information retained for determining overlap
+  llvm::dxil::ResourceClass Class;
+  uint32_t Space;
+  llvm::dxbc::ShaderVisibility Visibility;
+};
+
+class ResourceRange {
+public:
+  using MapT = llvm::IntervalMap<uint32_t, const RangeInfo *, 16,
+                                 llvm::IntervalMapInfo<uint32_t>>;
+
+private:
+  MapT Intervals;
+
+public:
+  ResourceRange(MapT::Allocator &Allocator) : Intervals(MapT(Allocator)) {}
+
+  // Returns a reference to the first RangeInfo that overlaps with
+  // [Info.LowerBound;Info.UpperBound], or, std::nullopt if there is no overlap
+  LLVM_ABI std::optional<const RangeInfo *>
+  getOverlapping(const RangeInfo &Info) const;
+
+  // Return the mapped RangeInfo at X or nullptr if no mapping exists
+  LLVM_ABI const RangeInfo *lookup(uint32_t X) const;
+
+  // Removes all entries of the ResourceRange
+  LLVM_ABI void clear();
+
+  // Insert the required (sub-)intervals such that the interval of [a;b] =
+  // [Info.LowerBound, Info.UpperBound] is covered and points to a valid
+  // RangeInfo &.
+  //
+  // For instance consider the following chain of inserting RangeInfos with the
+  // intervals denoting the Lower/Upper-bounds:
+  //
+  // A = [0;2]
+  //   insert(A) -> false
+  //   intervals: [0;2] -> &A
+  // B = [5;7]
+  //   insert(B) -> false
+  //   intervals: [0;2] -> &A, [5;7] -> &B
+  // C = [4;7]
+  //   insert(C) -> true
+  //   intervals: [0;2] -> &A, [4;7] -> &C
+  // D = [1;5]
+  //   insert(D) -> true
+  //   intervals: [0;2] -> &A, [3;3] -> &D, [4;7] -> &C
+  // E = [0;unbounded]
+  //   insert(E) -> true
+  //   intervals: [0;unbounded] -> E
+  //
+  // Returns a reference to the first RangeInfo that overlaps with
+  // [Info.LowerBound;Info.UpperBound], or, std::nullopt if there is no overlap
+  // (equivalent to getOverlapping)
+  LLVM_ABI std::optional<const RangeInfo *> insert(const RangeInfo &Info);
+};
+
+struct OverlappingRanges {
+  const RangeInfo *A;
+  const RangeInfo *B;
+
+  OverlappingRanges(const RangeInfo *A, const RangeInfo *B) : A(A), B(B) {}
+};
+
+/// The following conducts analysis on resource ranges to detect and report
+/// any overlaps in resource ranges.
+///
+/// A resource range overlaps with another resource range if they have:
+/// - equivalent ResourceClass (SRV, UAV, CBuffer, Sampler)
+/// - equivalent resource space
+/// - overlapping visbility
+///
+/// The algorithm is implemented in the following steps:
+///
+/// 1. The user will collect RangeInfo from relevant RootElements:
+///   - RangeInfo will retain the interval, ResourceClass, Space and Visibility
+///   - It will also contain an index so that it can be associated to
+/// additional diagnostic information
+/// 2. Sort the RangeInfo's such that they are grouped together by
+///  ResourceClass and Space
+/// 3. Iterate through the collected RangeInfos by their groups
+///   - For each group we will have a ResourceRange for each visibility
+///   - As we iterate through we will:
+///      A: Insert the current RangeInfo into the corresponding Visibility
+///   ResourceRange
+///      B: Check for overlap with any overlapping Visibility ResourceRange
+LLVM_ABI llvm::SmallVector<OverlappingRanges>
+findOverlappingRanges(ArrayRef<RangeInfo> Infos);
 
 } // namespace rootsig
 } // namespace hlsl
diff --git a/llvm/include/llvm/MC/DXContainerRootSignature.h b/llvm/include/llvm/MC/DXContainerRootSignature.h
index 3c7c886e79fc3..a931b1d54b65c 100644
--- a/llvm/include/llvm/MC/DXContainerRootSignature.h
+++ b/llvm/include/llvm/MC/DXContainerRootSignature.h
@@ -5,7 +5,6 @@
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
-
 #ifndef LLVM_MC_DXCONTAINERROOTSIGNATURE_H
 #define LLVM_MC_DXCONTAINERROOTSIGNATURE_H
 
@@ -120,5 +119,4 @@ struct RootSignatureDesc {
 };
 } // namespace mcdxbc
 } // namespace llvm
-
 #endif // LLVM_MC_DXCONTAINERROOTSIGNATURE_H
diff --git a/llvm/lib/Analysis/DXILResource.cpp b/llvm/lib/Analysis/DXILResource.cpp
index 629fa7cddb9d4..b476026fcc718 100644
--- a/llvm/lib/Analysis/DXILResource.cpp
+++ b/llvm/lib/Analysis/DXILResource.cpp
@@ -29,20 +29,6 @@
 using namespace llvm;
 using namespace dxil;
 
-static StringRef getResourceClassName(ResourceClass RC) {
-  switch (RC) {
-  case ResourceClass::SRV:
-    return "SRV";
-  case ResourceClass::UAV:
-    return "UAV";
-  case ResourceClass::CBuffer:
-    return "CBuffer";
-  case ResourceClass::Sampler:
-    return "Sampler";
-  }
-  llvm_unreachable("Unhandled ResourceClass");
-}
-
 static StringRef getResourceKindName(ResourceKind RK) {
   switch (RK) {
   case ResourceKind::Texture1D:
diff --git a/llvm/lib/Frontend/HLSL/HLSLBinding.cpp b/llvm/lib/Frontend/HLSL/HLSLBinding.cpp
index d581311f22028..57075ca430d44 100644
--- a/llvm/lib/Frontend/HLSL/HLSLBinding.cpp
+++ b/llvm/lib/Frontend/HLSL/HLSLBinding.cpp
@@ -66,6 +66,22 @@ BindingInfo::RegisterSpace::findAvailableBinding(int32_t Size) {
   return std::nullopt;
 }
 
+bool BindingInfo::RegisterSpace::isBound(BindingRange B) {
+  for (BindingRange &R : FreeRanges) {
+    if (B.LowerBound >= R.LowerBound && B.LowerBound < R.UpperBound &&
+        B.UpperBound > R.LowerBound && B.UpperBound <= R.UpperBound)
+      return false;
+  }
+  return true;
+}
+
+bool BindingInfo::isBound(dxil::ResourceClass RC, uint32_t Space,
+                          BindingRange B) {
+  BindingSpaces &BS = getBindingSpaces(RC);
+  RegisterSpace &RS = BS.getOrInsertSpace(Space);
+  return RS.isBound(B);
+}
+
 BindingInfo BindingInfoBuilder::calculateBindingInfo(
     llvm::function_ref<void(const BindingInfoBuilder &Builder,
                             const Binding &Overlapping)>
diff --git a/llvm/lib/Target/DirectX/DXILOpLowering.cpp b/llvm/lib/Target/DirectX/DXILOpLowering.cpp
index 0ec15a629d0a2..db7719e129ad0 100644
--- a/llvm/lib/Target/DirectX/DXILOpLowering.cpp
+++ b/llvm/lib/Target/DirectX/DXILOpLowering.cpp
@@ -9,6 +9,7 @@
 #include "DXILOpLowering.h"
 #include "DXILConstants.h"
 #include "DXILOpBuilder.h"
+#include "DXILRootSignature.h"
 #include "DXILShaderFlags.h"
 #include "DirectX.h"
 #include "llvm/ADT/SmallVector.h"
@@ -945,6 +946,7 @@ class DXILOpLoweringLegacy : public ModulePass {
     AU.addPreserved<DXILResourceWrapperPass>();
     AU.addPreserved<DXILMetadataAnalysisWrapperPass>();
     AU.addPreserved<ShaderFlagsAnalysisWrapper>();
+    AU.addPreserved<RootSignatureAnalysisWrapper>();
   }
 };
 char DXILOpLoweringLegacy::ID = 0;
diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
index 398dcbb8d1737..0e25b8ff9897b 100644
--- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
+++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "DXILPostOptimizationValidation.h"
+#include "DXILRootSignature.h"
 #include "DXILShaderFlags.h"
 #include "DirectX.h"
 #include "llvm/ADT/SmallString.h"
@@ -24,6 +25,35 @@ using namespace llvm;
 using namespace llvm::dxil;
 
 namespace {
+static ResourceClass RangeToResourceClass(uint32_t RangeType) {
+  using namespace dxbc;
+  switch (static_cast<DescriptorRangeType>(RangeType)) {
+  case DescriptorRangeType::SRV:
+    return ResourceClass::SRV;
+  case DescriptorRangeType::UAV:
+    return ResourceClass::UAV;
+  case DescriptorRangeType::CBV:
+    return ResourceClass::CBuffer;
+  case DescriptorRangeType::Sampler:
+    return ResourceClass::Sampler;
+  }
+}
+
+ResourceClass ParameterToResourceClass(uint32_t Type) {
+  using namespace dxbc;
+  switch (Type) {
+  case llvm::to_underlying(RootParameterType::Constants32Bit):
+    return ResourceClass::CBuffer;
+  case llvm::to_underlying(RootParameterType::SRV):
+    return ResourceClass::SRV;
+  case llvm::to_underlying(RootParameterType::UAV):
+    return ResourceClass::UAV;
+  case llvm::to_underlying(RootParameterType::CBV):
+    return ResourceClass::CBuffer;
+  default:
+    llvm_unreachable("Unknown RootParameterType");
+  }
+}
 
 static void reportInvalidDirection(Module &M, DXILResourceMap &DRM) {
   for (const auto &UAV : DRM.uavs()) {
@@ -84,8 +114,112 @@ static void reportOverlappingBinding(Module &M, DXILResourceMap &DRM) {
   }
 }
 
+static void
+reportRegNotBound(Module &M, ResourceClass Class,
+                  llvm::dxil::ResourceInfo::ResourceBinding Unbound) {
+  SmallString<128> Message;
+  raw_svector_ostream OS(Message);
+  OS << "register " << getResourceClassName(Class)
+     << " (space=" << Unbound.Space << ", register=" << Unbound.LowerBound
+     << ")"
+     << " does not have a binding in the Root Signature";
+  M.getContext().diagnose(DiagnosticInfoGeneric(Message));
+}
+
+static dxbc::ShaderVisibility
+tripleToVisibility(llvm::Triple::EnvironmentType ET) {
+  assert((ET == Triple::Pixel || ET == Triple::Vertex ||
+          ET == Triple::Geometry || ET == Triple::Hull ||
+          ET == Triple::Domain || ET == Triple::Mesh ||
+          ET == Triple::Compute) &&
+         "Invalid Triple to shader stage conversion");
+
+  switch (ET) {
+  case Triple::Pixel:
+    return dxbc::ShaderVisibility::Pixel;
+  case Triple::Vertex:
+    return dxbc::ShaderVisibility::Vertex;
+  case Triple::Geometry:
+    return dxbc::ShaderVisibility::Geometry;
+  case Triple::Hull:
+    return dxbc::ShaderVisibility::Hull;
+  case Triple::Domain:
+    return dxbc::ShaderVisibility::Domain;
+  case Triple::Mesh:
+    return dxbc::ShaderVisibility::Mesh;
+  case Triple::Compute:
+    return dxbc::ShaderVisibility::All;
+  default:
+    llvm_unreachable("Invalid triple to shader stage conversion");
+  }
+}
+
+static void trackRootSigDescBinding(hlsl::BindingInfoBuilder &Builder,
+                                    const mcdxbc::RootSignatureDesc &RSD,
+                                    dxbc::ShaderVisibility Visibility) {
+  for (size_t I = 0; I < RSD.ParametersContainer.size(); I++) {
+    const auto &[Type, Loc] =
+        RSD.ParametersContainer.getTypeAndLocForParameter(I);
+
+    const auto &Header = RSD.ParametersContainer.getHeader(I);
+    if (Header.ShaderVisibility !=
+            llvm::to_underlying(dxbc::ShaderVisibility::All) &&
+        Header.ShaderVisibility != llvm::to_underlying(Visibility))
+      continue;
+
+    switch (Type) {
+    case llvm::to_underlying(dxbc::RootParameterType::Constants32Bit): {
+      dxbc::RTS0::v1::RootConstants Const =
+          RSD.ParametersContainer.getConstant(Loc);
+      Builder.trackBinding(dxil::ResourceClass::CBuffer, Const.RegisterSpace,
+                           Const.ShaderRegister,
+                           Const.ShaderRegister + Const.Num32BitValues,
+                           nullptr);
+      break;
+    }
+
+    case llvm::to_underlying(dxbc::RootParameterType::SRV):
+    case llvm::to_underlying(dxbc::RootParameterType::UAV):
+    case llvm::to_underlying(dxbc::RootParameterType::CBV): {
+      dxbc::RTS0::v2::RootDescriptor Desc =
+          RSD.ParametersContainer.getRootDescriptor(Loc);
+      Builder.trackBinding(ParameterToResourceClass(Type), Desc.RegisterSpace,
+                           Desc.ShaderRegister, Desc.ShaderRegister, nullptr);
+
+      break;
+    }
+    case llvm::to_underlying(dxbc::RootParameterType::DescriptorTable): {
+      const mcdxbc::DescriptorTable &Table =
+          RSD.ParametersContainer.getDescriptorTable(Loc);
+
+      for (const dxbc::RTS0::v2::DescriptorRange &Range : Table.Ranges) {
+        Builder.trackBinding(RangeToResourceClass(Range.RangeType),
+                             Range.RegisterSpace, Range.BaseShaderRegister,
+                             Range.BaseShaderRegister + Range.NumDescriptors,
+                             nullptr);
+      }
+      break;
+    }
+    }
+  }
+}
+
+std::optional<mcdxbc::RootSignatureDesc>
+getRootSignature(RootSignatureBindingInfo &RSBI,
+                 dxil::ModuleMetadataInfo &MMI) {
+  if (MMI.EntryPropertyVec.size() == 0)
+    return std::nullopt;
+  std::optional<mcdxbc::RootSignatureDesc> RootSigDesc =
+      RSBI.getDescForFunction(MMI.EntryPropertyVec[0].Entry);
+  if (!RootSigDesc)
+    return std::nullopt;
+  return RootSigDesc;
+}
+
 static void reportErrors(Module &M, DXILResourceMap &DRM,
-                         DXILResourceBindingInfo &DRBI) {
+                         DXILResourceBindingInfo &DRBI,
+                         RootSignatureBindingInfo &RSBI,
+                         dxil::ModuleMetadataInfo &MMI) {
   if (DRM.hasInvalidCounterDirection())
     reportInvalidDirection(M, DRM);
 
@@ -94,6 +228,31 @@ static void reportErrors(Module &M, DXILResourceMap &DRM,
 
   assert(!DRBI.hasImplicitBinding() && "implicit bindings should be handled in "
                                        "DXILResourceImplicitBinding pass");
+
+  if (auto RSD = getRootSignature(RSBI, MMI)) {
+
+    hlsl::BindingInfoBuilder Builder;
+    dxbc::ShaderVisibility Visibility = tripleToVisibility(MMI.ShaderProfile);
+    trackRootSigDescBinding(Builder, *RSD, Visibility);
+
+    bool HasOverlap;
+    hlsl::BindingInfo Info = Builder.calculateBindingInfo(HasOverlap);
+
+    for (const auto &ResList :
+         {std::make_pair(ResourceClass::SRV, DRM.srvs()),
+          std::make_pair(ResourceClass::UAV, DRM.uavs()),
+          std::make_pair(ResourceClass::CBuffer, DRM.cbuffers()),
+          std::make_pair(ResourceClass::Sampler, DRM.samplers())}) {
+      for (auto Res : ResList.second) {
+        llvm::dxil::ResourceInfo::ResourceBinding ResBinding = Res.getBinding();
+        llvm::hlsl::BindingInfo::BindingRange ResRange(
+            ResBinding.LowerBound, ResBinding.LowerBound + ResBinding.Size);
+
+        if (!Info.isBound(ResList.first, ResBinding.Space, ResRange))
+          reportRegNotBound(M, ResList.first, ResBinding);
+      }
+    }
+  }
 }
 } // namespace
 
@@ -101,7 +260,10 @@ PreservedAnalyses
 DXILPostOptimizationValidation::run(Module &M, ModuleAnalysisManager &MAM) {
   DXILResourceMap &DRM = MAM.getResult<DXILResourceAnalysis>(M);
   DXILResourceBindingInfo &DRBI = MAM.getResult<DXILResourceBindingAnalysis>(M);
-  reportErrors(M, DRM, DRBI);
+  RootSignatureBindingInfo &RSBI = MAM.getResult<RootSignatureAnalysis>(M);
+  ModuleMetadataInfo &MMI = MAM.getResult<DXILMetadataAnalysis>(M);
+
+  reportErrors(M, DRM, DRBI, RSBI, MMI);
   return PreservedAnalyses::all();
 }
 
@@ -113,7 +275,12 @@ class DXILPostOptimizationValidationLegacy : public ModulePass {
         getAnalysis<DXILResourceWrapperPass>().getResourceMap();
     DXILResourceBindingInfo &DRBI =
         getAnalysis<DXILResourceBindingWrapperPass>().getBindingInfo();
-    reportErrors(M, DRM, DRBI);
+    RootSignatureBindingInfo &RSBI =
+        getAnalysis<RootSignatureAnalysisWrapper>().getRSInfo();
+    dxil::ModuleMetadataInfo &MMI =
+        getAnalysis<DXILMetadataAnalysisWrapperPass>().getModuleMetadata();
+
+    reportErrors(M, DRM, DRBI, RSBI, MMI);
     return false;
   }
   StringRef getPassName() const override {
@@ -125,10 +292,13 @@ class DXILPostOptimizationValidationLegacy : public ModulePass {
   void getAnalysisUsage(llvm::AnalysisUsage &AU) const override {
     AU.addRequired<DXILResourceWrapperPass>();
     AU.addRequired<DXILResourceBindingWrapperPass>();
+    AU.addRequired<DXILMetadataAnalysisWrapperPass>();
+    AU.addRequired<RootSignatureAnalysisWrapper>();
     AU.addPreserved<DXILResourceWrapperPass>();
     AU.addPreserved<DXILResourceBindingWrapperPass>();
     AU.addPreserved<DXILMetadataAnalysisWrapperPass>();
     AU.addPreserved<ShaderFlagsAnalysisWrapper>();
+    AU.addPreserved<RootSignatureAnalysisWrapper>();
   }
 };
 char DXILPostOptimizationValidationLegacy::ID = 0;
@@ -139,6 +309,8 @@ INITIALIZE_PASS_BEGIN(DXILPostOptimizationValidationLegacy, DEBUG_TYPE,
 INITIALIZE_PASS_DEPENDENCY(DXILResourceBindingWrapperPass)
 INITIALIZE_PASS_DEPENDENCY(DXILResourceTypeWrapperPass)
 INITIALIZE_PASS_DEPENDENCY(DXILResourceWrapperPass)
+INITIALIZE_PASS_DEPENDENCY(DXILMetadataAnalysisWrapperPass)
+INITIALIZE_PASS_DEPENDENCY(RootSignatureAnalysisWrapper)
 INITIALIZE_PASS_END(DXILPostOptimizationValidationLegacy, DEBUG_TYPE,
                     "DXIL Post Optimization Validation", false, false)
 
diff --git a/llvm/lib/Target/DirectX/DXILPrepare.cpp b/llvm/lib/Target/DirectX/DXILPrepare.cpp
index c8866bfefdfc5..9c3eba83eba7c 100644
--- a/llvm/lib/Target/DirectX/DXILPrepare.cpp
+++ b/llvm/lib/Target/DirectX/DXILPrepare.cpp
@@ -300,7 +300,6 @@ class DXILPrepareModule : public ModulePass {
   DXILPrepareModule() : ModulePass(ID) {}
   void getAnalysisUsage(AnalysisUsage &AU) const override {
     AU.addRequired<DXILMetadataAnalysisWrapperPass>();
-    AU.addRequired<RootSignatureAnalysisWrapper>();
     AU.addPreserved<RootSignatureAnalysisWrapper>();
     AU.addPreserved<ShaderFlagsAnalysisWrapper>();
     AU.addPreserved<DXILMetadataAnalysisWrapperPass>();
diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.cpp b/llvm/lib/Target/DirectX/DXILRootSignature.cpp
index a4f5086c2f428..eb9ff5ab405e4 100644
--- a/llvm/lib/Target/DirectX/DXILRootSignature.cpp
+++ b/llvm/lib/Target/DirectX/DXILRootSignature.cpp
@@ -29,6 +29,8 @@
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/raw_ostream.h"
 #include <cstdint>
+#include <optional>
+#include <utility>
 
 using namespace llvm;
 using namespace llvm::dxil;
@@ -233,7 +235,7 @@ bool RootSignatureAnalysisWrapper::runOnModule(Module &M) {
 
 void RootSignatureAnalysisWrapper::getAnalysisUsage(AnalysisUsage &AU) const {
   AU.setPreservesAll();
-  AU.addPreserved<DXILMetadataAnalysisWrapperPass>();
+  AU.addRequired<DXILMetadataAnalysisWrapperPass>();
 }
 
 char RootSignatureAnalysisWrapper::ID = 0;
@@ -241,6 +243,7 @@ char RootSignatureAnalysisWrapper::ID = 0;
 INITIALIZE_PASS_BEGIN(RootSignatureAnalysisWrapper,
                       "dxil-root-signature-analysis",
                       "DXIL Root Signature Analysis", true, true)
+INITIALIZE_PASS_DEPENDENCY(DXILMetadataAnalysisWrapperPass)
 INITIALIZE_PASS_END(RootSignatureAnalysisWrapper,
                     "dxil-root-signature-analysis",
                     "DXIL Root Signature Analysis", true, true)
diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.h b/llvm/lib/Target/DirectX/DXILRootSignature.h
index 254b7ff504633..ccffa3fd0a3e2 100644
--- a/llvm/lib/Target/DirectX/DXILRootSignature.h
+++ b/llvm/lib/Target/DirectX/DXILRootSignature.h
@@ -26,6 +26,16 @@
 namespace llvm {
 namespace dxil {
 
+enum class RootSignatureElementKind {
+  Error = 0,
+  RootFlags = 1,
+  RootConstants = 2,
+  SRV = 3,
+  UAV = 4,
+  CBV = 5,
+  DescriptorTable = 6,
+};
+
 class RootSignatureBindingInfo {
 private:
   SmallDenseMap<const Function *, mcdxbc::RootSignatureDesc> FuncToRsMap;
@@ -96,4 +106,4 @@ class RootSignatureAnalysisPrinter
 
 } // namespace dxil
 } // namespace llvm
-#endif
+#endif // LLVM_LIB_TARGET_DIRECTX_DXILROOTSIGNATURE_H
diff --git a/llvm/test/CodeGen/DirectX/llc-pipeline.ll b/llvm/test/CodeGen/DirectX/llc-pipeline.ll
index 151603a7161c5..c31d2194a8de5 100644
--- a/llvm/test/CodeGen/DirectX/llc-pipeline.ll
+++ b/llvm/test/CodeGen/DirectX/llc-pipeline.ll
@@ -33,9 +33,9 @@
 ; CHECK-NEXT:   DXIL Module Metadata analysis
 ; CHECK-NEXT:   DXIL Shader Flag Analysis
 ; CHECK-NEXT:   DXIL Translate Metadata
+; CHECK-NEXT:   DXIL Root Signature Analysis
 ; CHECK-NEXT:   DXIL Post Optimization Validation
 ; CHECK-NEXT:   DXIL Op Lowering
-; CHECK-NEXT:   DXIL Root Signature Analysis
 ; CHECK-NEXT:   DXIL Prepare Module
 
 ; CHECK-ASM-NEXT: DXIL Metadata Pretty Printer
diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-constants.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-constants.ll
new file mode 100644
index 0000000000000..3c33f1dc6bdf0
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-constants.ll
@@ -0,0 +1,22 @@
+; RUN: opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 
+; expected-no-diagnostics
+; Root Signature(RootConstants(num32BitConstants=4, b2))
+
+%__cblayout_CB = type <{ float }>
+
+ at CB.str = private unnamed_addr constant [3 x i8] c"CB\00", align 1
+
+define void @CSMain() "hlsl.shader"="compute" {
+entry:
+; cbuffer CB : register(b2, space0) {
+;  float a;
+; }
+  %CB = tail call target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 4, 0)) @llvm.dx.resource.handlefrombinding(i32 0, i32 2, i32 1, i32 0, i1 false, ptr nonnull @CB.str)
+  ret void
+}
+
+!dx.rootsignatures = !{!0}
+
+!0 = !{ptr @CSMain, !1, i32 2}
+!1 = !{!2}
+!2 = !{!"RootConstants", i32 0, i32 2, i32 0, i32 4}
diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbuffer.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbuffer.ll
new file mode 100644
index 0000000000000..e5133810c0f32
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbuffer.ll
@@ -0,0 +1,34 @@
+; RUN: not opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 | FileCheck %s
+
+; CHECK: error: register CBuffer (space=665, register=3) does not have a binding in the Root Signature
+
+; Root Signature(
+;   CBV(b3, space=666, visibility=SHADER_VISIBILITY_ALL)
+;   DescriptorTable(SRV(t0, space=0, numDescriptors=1), visibility=SHADER_VISIBILITY_ALL)
+;   DescriptorTable(Sampler(s0, numDescriptors=2), visibility=SHADER_VISIBILITY_VERTEX)
+;   DescriptorTable(UAV(u0, numDescriptors=unbounded), visibility=SHADER_VISIBILITY_ALL)
+
+%__cblayout_CB = type <{ float }>
+
+ at CB.str = private unnamed_addr constant [3 x i8] c"CB\00", align 1
+
+define void @CSMain() "hlsl.shader"="compute" {
+entry:
+; cbuffer CB : register(b3, space665) {
+;  float a;
+; }
+  %CB = tail call target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 4, 0)) @llvm.dx.resource.handlefrombinding(i32 665, i32 3, i32 1, i32 0, i1 false, ptr nonnull @CB.str)
+  ret void
+}
+
+!dx.rootsignatures = !{!0}
+
+!0 = !{ptr @CSMain, !1, i32 2}
+!1 = !{!2, !3, !5, !7}
+!2 = !{!"RootCBV", i32 0, i32 3, i32 666, i32 4}
+!3 = !{!"DescriptorTable", i32 1, !4}
+!4 = !{!"SRV", i32 1, i32 0, i32 0, i32 -1, i32 4}
+!5 = !{!"DescriptorTable", i32 0, !6}
+!6 = !{!"Sampler", i32 2, i32 0, i32 0, i32 -1, i32 0}
+!7 = !{!"DescriptorTable", i32 0, !8}
+!8 = !{!"UAV", i32 -1, i32 0, i32 0, i32 -1, i32 2}
diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-constants.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-constants.ll
new file mode 100644
index 0000000000000..dc7657e79ec97
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-constants.ll
@@ -0,0 +1,22 @@
+; RUN: not opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 | FileCheck %s
+; CHECK: error: register CBuffer (space=666, register=2) does not have a binding in the Root Signature
+; Root Signature(RootConstants(num32BitConstants=4, b2))
+
+%__cblayout_CB = type <{ float }>
+
+ at CB.str = private unnamed_addr constant [3 x i8] c"CB\00", align 1
+
+define void @CSMain() "hlsl.shader"="compute" {
+entry:
+; cbuffer CB : register(b2, space666) {
+;  float a;
+; }
+  %CB = tail call target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 4, 0)) @llvm.dx.resource.handlefrombinding(i32 666, i32 2, i32 1, i32 0, i1 false, ptr nonnull @CB.str)
+  ret void
+}
+
+!dx.rootsignatures = !{!0}
+
+!0 = !{ptr @CSMain, !1, i32 2}
+!1 = !{!2}
+!2 = !{!"RootConstants", i32 0, i32 2, i32 0, i32 4}
diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler.ll
new file mode 100644
index 0000000000000..152c363fdf75b
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler.ll
@@ -0,0 +1,31 @@
+; RUN: not opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 | FileCheck %s
+
+; CHECK: error: register Sampler (space=2, register=3) does not have a binding in the Root Signature
+
+; Root Signature(
+;   CBV(b3, space=666, visibility=SHADER_VISIBILITY_ALL)
+;   DescriptorTable(SRV(t0, space=0, numDescriptors=1), visibility=SHADER_VISIBILITY_VERTEX)
+;   DescriptorTable(Sampler(s0, numDescriptors=2), visibility=SHADER_VISIBILITY_ALL)
+;   DescriptorTable(UAV(u0, numDescriptors=unbounded), visibility=SHADER_VISIBILITY_ALL)
+
+ at Smp.str = private unnamed_addr constant [4 x i8] c"Smp\00", align 1
+
+define void @CSMain() "hlsl.shader"="compute" {
+entry:
+; SamplerState S1 : register(s3, space2);
+  %Sampler = call target("dx.Sampler", 0) @llvm.dx.resource.handlefrombinding(i32 2, i32 3, i32 1, i32 0, i1 false, ptr nonnull @Smp.str)
+
+  ret void
+}
+
+!dx.rootsignatures = !{!0}
+
+!0 = !{ptr @CSMain, !1, i32 2}
+!1 = !{!2, !3, !5, !7}
+!2 = !{!"RootCBV", i32 0, i32 3, i32 666, i32 4}
+!3 = !{!"DescriptorTable", i32 1, !4}
+!4 = !{!"SRV", i32 1, i32 0, i32 0, i32 -1, i32 4}
+!5 = !{!"DescriptorTable", i32 0, !6}
+!6 = !{!"Sampler", i32 2, i32 0, i32 0, i32 -1, i32 0}
+!7 = !{!"DescriptorTable", i32 0, !8}
+!8 = !{!"UAV", i32 -1, i32 0, i32 0, i32 -1, i32 2}
diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-srv.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-srv.ll
new file mode 100644
index 0000000000000..ebefa7b1a3d85
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-srv.ll
@@ -0,0 +1,30 @@
+; RUN: not opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 | FileCheck %s
+
+; CHECK: error: register SRV (space=0, register=0) does not have a binding in the Root Signature
+
+; Root Signature(
+;   CBV(b3, space=666, visibility=SHADER_VISIBILITY_ALL)
+;   DescriptorTable(SRV(t0, space=0, numDescriptors=1), visibility=SHADER_VISIBILITY_VERTEX)
+;   DescriptorTable(Sampler(s0, numDescriptors=2), visibility=SHADER_VISIBILITY_ALL)
+;   DescriptorTable(UAV(u0, numDescriptors=unbounded), visibility=SHADER_VISIBILITY_ALL)
+
+ at SB.str = private unnamed_addr constant [3 x i8] c"SB\00", align 1
+
+define void @CSMain() "hlsl.shader"="compute" {
+entry:
+; StructuredBuffer<int> In : register(t0, space0);
+  %SB = tail call target("dx.RawBuffer", i32, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i32_0_0t(i32 0, i32 0, i32 1, i32 0, i1 false, ptr nonnull @SB.str)
+  ret void
+}
+
+!dx.rootsignatures = !{!0}
+
+!0 = !{ptr @CSMain, !1, i32 2}
+!1 = !{!2, !3, !5, !7}
+!2 = !{!"RootCBV", i32 0, i32 3, i32 666, i32 4}
+!3 = !{!"DescriptorTable", i32 1, !4}
+!4 = !{!"SRV", i32 1, i32 0, i32 0, i32 -1, i32 4}
+!5 = !{!"DescriptorTable", i32 0, !6}
+!6 = !{!"Sampler", i32 2, i32 0, i32 0, i32 -1, i32 0}
+!7 = !{!"DescriptorTable", i32 0, !8}
+!8 = !{!"UAV", i32 -1, i32 0, i32 0, i32 -1, i32 2}
diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-uav.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-uav.ll
new file mode 100644
index 0000000000000..9cc5b6744a4a2
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-uav.ll
@@ -0,0 +1,30 @@
+; RUN: not opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 | FileCheck %s
+
+; CHECK: error: register UAV (space=0, register=4294967294) does not have a binding in the Root Signature
+
+; Root Signature(
+;   CBV(b3, space=666, visibility=SHADER_VISIBILITY_ALL)
+;   DescriptorTable(SRV(t0, space=0, numDescriptors=1), visibility=SHADER_VISIBILITY_VERTEX)
+;   DescriptorTable(Sampler(s0, numDescriptors=2), visibility=SHADER_VISIBILITY_ALL)
+;   DescriptorTable(UAV(u0, numDescriptors=unbounded), visibility=SHADER_VISIBILITY_ALL)
+
+ at RWB.str = private unnamed_addr constant [4 x i8] c"RWB\00", align 1
+
+define void @CSMain() "hlsl.shader"="compute" {
+entry:
+; RWBuffer<float> UAV : register(4294967294);
+  %RWB = tail call target("dx.TypedBuffer", float, 1, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0_0t(i32 0, i32 4294967294, i32 1, i32 0, i1 false, ptr nonnull @RWB.str)
+  ret void
+}
+
+!dx.rootsignatures = !{!0}
+
+!0 = !{ptr @CSMain, !1, i32 2}
+!1 = !{!2, !3, !5, !7}
+!2 = !{!"RootCBV", i32 0, i32 3, i32 666, i32 4}
+!3 = !{!"DescriptorTable", i32 1, !4}
+!4 = !{!"SRV", i32 1, i32 0, i32 0, i32 -1, i32 4}
+!5 = !{!"DescriptorTable", i32 0, !6}
+!6 = !{!"Sampler", i32 2, i32 0, i32 0, i32 -1, i32 0}
+!7 = !{!"DescriptorTable", i32 0, !8}
+!8 = !{!"UAV", i32 10, i32 0, i32 0, i32 -1, i32 2}
diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation.ll
new file mode 100644
index 0000000000000..750679bf743c5
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/rootsignature-validation.ll
@@ -0,0 +1,39 @@
+; RUN: opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 
+; expected-no-diagnostics
+
+
+; Root Signature(
+;   CBV(b3, space=1, visibility=SHADER_VISIBILITY_ALL)
+;   DescriptorTable(SRV(t0, space=0, numDescriptors=1), visibility=SHADER_VISIBILITY_ALL)
+;   DescriptorTable(Sampler(s0, numDescriptors=2), visibility=SHADER_VISIBILITY_VERTEX)
+;   DescriptorTable(UAV(u0, numDescriptors=unbounded), visibility=SHADER_VISIBILITY_ALL)
+
+%__cblayout_CB = type <{ float }>
+
+ at CB.str = private unnamed_addr constant [3 x i8] c"CB\00", align 1
+ at Smp.str = private unnamed_addr constant [4 x i8] c"Smp\00", align 1
+ at SB.str = private unnamed_addr constant [3 x i8] c"SB\00", align 1
+ at RWB.str = private unnamed_addr constant [4 x i8] c"RWB\00", align 1
+
+define void @CSMain() "hlsl.shader"="compute" {
+entry:
+
+  %CB = tail call target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 4, 0)) @llvm.dx.resource.handlefrombinding(i32 1, i32 3, i32 1, i32 0, i1 false, ptr nonnull @CB.str)
+  %Sampler = call target("dx.Sampler", 0) @llvm.dx.resource.handlefrombinding(i32 2, i32 3, i32 1, i32 0, i1 false, ptr nonnull @Smp.str)
+  %SB = tail call target("dx.RawBuffer", i32, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i32_0_0t(i32 0, i32 0, i32 1, i32 0, i1 false, ptr nonnull @SB.str)
+  %RWB =  tail call target("dx.TypedBuffer", float, 1, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0_0t(i32 0, i32 0, i32 1, i32 0, i1 false, ptr nonnull @RWB.str)
+
+  ret void
+}
+
+!dx.rootsignatures = !{!0}
+
+!0 = !{ptr @CSMain, !1, i32 2}
+!1 = !{!2, !3, !5, !7}
+!2 = !{!"RootCBV", i32 0, i32 3, i32 1, i32 4}
+!3 = !{!"DescriptorTable", i32 0, !4}
+!4 = !{!"SRV", i32 1, i32 0, i32 0, i32 -1, i32 0}
+!5 = !{!"DescriptorTable", i32 0, !6}
+!6 = !{!"Sampler", i32 5, i32 3, i32 2, i32 -1, i32 0}
+!7 = !{!"DescriptorTable", i32 0, !8}
+!8 = !{!"UAV", i32 -1, i32 0, i32 0, i32 -1, i32 2}

>From af6aa531329212cfe71baf720196b62d0baa67bc Mon Sep 17 00:00:00 2001
From: Joao Saffran <{ID}+{username}@users.noreply.github.com>
Date: Tue, 5 Aug 2025 13:39:56 -0700
Subject: [PATCH 02/11] add tests

---
 .../DXILPostOptimizationValidation.cpp        | 59 +++++++++----------
 ...signature-validation-fail-cbuffer-range.ll | 15 +++++
 .../rootsignature-validation-fail-cbuffer.ll  | 34 -----------
 ...rootsignature-validation-fail-constants.ll | 22 -------
 ...-validation-fail-descriptor-table-range.ll | 15 +++++
 ...e-validation-fail-root-descriptor-range.ll | 15 +++++
 .../rootsignature-validation-fail-sampler.ll  | 31 ----------
 .../rootsignature-validation-fail-srv.ll      | 30 ----------
 ...re-validation-fail-static-sampler-range.ll | 13 ++++
 .../rootsignature-validation-fail-uav.ll      | 30 ----------
 10 files changed, 87 insertions(+), 177 deletions(-)
 create mode 100644 llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbuffer-range.ll
 delete mode 100644 llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbuffer.ll
 delete mode 100644 llvm/test/CodeGen/DirectX/rootsignature-validation-fail-constants.ll
 create mode 100644 llvm/test/CodeGen/DirectX/rootsignature-validation-fail-descriptor-table-range.ll
 create mode 100644 llvm/test/CodeGen/DirectX/rootsignature-validation-fail-root-descriptor-range.ll
 delete mode 100644 llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler.ll
 delete mode 100644 llvm/test/CodeGen/DirectX/rootsignature-validation-fail-srv.ll
 create mode 100644 llvm/test/CodeGen/DirectX/rootsignature-validation-fail-static-sampler-range.ll
 delete mode 100644 llvm/test/CodeGen/DirectX/rootsignature-validation-fail-uav.ll

diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
index 0e25b8ff9897b..3da4cfbea23b8 100644
--- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
+++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
@@ -114,15 +114,18 @@ static void reportOverlappingBinding(Module &M, DXILResourceMap &DRM) {
   }
 }
 
-static void
-reportRegNotBound(Module &M, ResourceClass Class,
-                  llvm::dxil::ResourceInfo::ResourceBinding Unbound) {
+static void reportOverlappingRegisters(
+    Module &M, const llvm::hlsl::BindingInfoBuilder::Binding &Reported,
+    const llvm::hlsl::BindingInfoBuilder::Binding &Overlaping) {
   SmallString<128> Message;
   raw_svector_ostream OS(Message);
-  OS << "register " << getResourceClassName(Class)
-     << " (space=" << Unbound.Space << ", register=" << Unbound.LowerBound
-     << ")"
-     << " does not have a binding in the Root Signature";
+  OS << "register " << getResourceClassName(Reported.RC)
+     << " (space=" << Reported.Space << ", register=" << Reported.LowerBound
+     << ")" << " is overlapping with" << " register "
+     << getResourceClassName(Overlaping.RC) << " (space=" << Overlaping.Space
+     << ", register=" << Overlaping.LowerBound << ")"
+     << ", verify your root signature definition.";
+
   M.getContext().diagnose(DiagnosticInfoGeneric(Message));
 }
 
@@ -173,8 +176,7 @@ static void trackRootSigDescBinding(hlsl::BindingInfoBuilder &Builder,
           RSD.ParametersContainer.getConstant(Loc);
       Builder.trackBinding(dxil::ResourceClass::CBuffer, Const.RegisterSpace,
                            Const.ShaderRegister,
-                           Const.ShaderRegister + Const.Num32BitValues,
-                           nullptr);
+                           Const.ShaderRegister + Const.Num32BitValues, &Const);
       break;
     }
 
@@ -184,7 +186,7 @@ static void trackRootSigDescBinding(hlsl::BindingInfoBuilder &Builder,
       dxbc::RTS0::v2::RootDescriptor Desc =
           RSD.ParametersContainer.getRootDescriptor(Loc);
       Builder.trackBinding(ParameterToResourceClass(Type), Desc.RegisterSpace,
-                           Desc.ShaderRegister, Desc.ShaderRegister, nullptr);
+                           Desc.ShaderRegister, Desc.ShaderRegister, &Desc);
 
       break;
     }
@@ -195,13 +197,21 @@ static void trackRootSigDescBinding(hlsl::BindingInfoBuilder &Builder,
       for (const dxbc::RTS0::v2::DescriptorRange &Range : Table.Ranges) {
         Builder.trackBinding(RangeToResourceClass(Range.RangeType),
                              Range.RegisterSpace, Range.BaseShaderRegister,
-                             Range.BaseShaderRegister + Range.NumDescriptors,
-                             nullptr);
+                             Range.NumDescriptors == ~0U
+                                 ? Range.NumDescriptors
+                                 : Range.BaseShaderRegister +
+                                       Range.NumDescriptors,
+                             &Range);
       }
       break;
     }
     }
   }
+
+  for (auto &S : RSD.StaticSamplers) {
+    Builder.trackBinding(dxil::ResourceClass::Sampler, S.RegisterSpace,
+                         S.ShaderRegister, S.ShaderRegister, &S);
+  }
 }
 
 std::optional<mcdxbc::RootSignatureDesc>
@@ -234,24 +244,13 @@ static void reportErrors(Module &M, DXILResourceMap &DRM,
     hlsl::BindingInfoBuilder Builder;
     dxbc::ShaderVisibility Visibility = tripleToVisibility(MMI.ShaderProfile);
     trackRootSigDescBinding(Builder, *RSD, Visibility);
-
-    bool HasOverlap;
-    hlsl::BindingInfo Info = Builder.calculateBindingInfo(HasOverlap);
-
-    for (const auto &ResList :
-         {std::make_pair(ResourceClass::SRV, DRM.srvs()),
-          std::make_pair(ResourceClass::UAV, DRM.uavs()),
-          std::make_pair(ResourceClass::CBuffer, DRM.cbuffers()),
-          std::make_pair(ResourceClass::Sampler, DRM.samplers())}) {
-      for (auto Res : ResList.second) {
-        llvm::dxil::ResourceInfo::ResourceBinding ResBinding = Res.getBinding();
-        llvm::hlsl::BindingInfo::BindingRange ResRange(
-            ResBinding.LowerBound, ResBinding.LowerBound + ResBinding.Size);
-
-        if (!Info.isBound(ResList.first, ResBinding.Space, ResRange))
-          reportRegNotBound(M, ResList.first, ResBinding);
-      }
-    }
+    hlsl::BindingInfo Info = Builder.calculateBindingInfo(
+        [&M](const llvm::hlsl::BindingInfoBuilder &Builder,
+             const llvm::hlsl::BindingInfoBuilder::Binding &ReportedBinding) {
+          const llvm::hlsl::BindingInfoBuilder::Binding &Overlaping =
+              Builder.findOverlapping(ReportedBinding);
+          reportOverlappingRegisters(M, ReportedBinding, Overlaping);
+        });
   }
 }
 } // namespace
diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbuffer-range.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbuffer-range.ll
new file mode 100644
index 0000000000000..5def38af0fbeb
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbuffer-range.ll
@@ -0,0 +1,15 @@
+; RUN: not opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 | FileCheck %s
+; CHECK: error: register CBuffer (space=0, register=2) is overlapping with register CBuffer (space=0, register=0), verify your root signature definition.
+
+define void @CSMain() "hlsl.shader"="compute" {
+entry:
+  ret void
+}
+
+; RootConstants(num32BitConstants=4, b2), DescriptorTable(CBV(b0, numDescriptors=3))
+!dx.rootsignatures = !{!0}
+!0 = !{ptr @CSMain, !1, i32 2}
+!1 = !{!2, !3}
+!2 = !{!"RootConstants", i32 0, i32 2, i32 0, i32 4}
+!3 = !{!"DescriptorTable", i32 0, !4}
+!4 = !{!"CBV", i32 3, i32 0, i32 0, i32 -1, i32 4}
\ No newline at end of file
diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbuffer.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbuffer.ll
deleted file mode 100644
index e5133810c0f32..0000000000000
--- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbuffer.ll
+++ /dev/null
@@ -1,34 +0,0 @@
-; RUN: not opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 | FileCheck %s
-
-; CHECK: error: register CBuffer (space=665, register=3) does not have a binding in the Root Signature
-
-; Root Signature(
-;   CBV(b3, space=666, visibility=SHADER_VISIBILITY_ALL)
-;   DescriptorTable(SRV(t0, space=0, numDescriptors=1), visibility=SHADER_VISIBILITY_ALL)
-;   DescriptorTable(Sampler(s0, numDescriptors=2), visibility=SHADER_VISIBILITY_VERTEX)
-;   DescriptorTable(UAV(u0, numDescriptors=unbounded), visibility=SHADER_VISIBILITY_ALL)
-
-%__cblayout_CB = type <{ float }>
-
- at CB.str = private unnamed_addr constant [3 x i8] c"CB\00", align 1
-
-define void @CSMain() "hlsl.shader"="compute" {
-entry:
-; cbuffer CB : register(b3, space665) {
-;  float a;
-; }
-  %CB = tail call target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 4, 0)) @llvm.dx.resource.handlefrombinding(i32 665, i32 3, i32 1, i32 0, i1 false, ptr nonnull @CB.str)
-  ret void
-}
-
-!dx.rootsignatures = !{!0}
-
-!0 = !{ptr @CSMain, !1, i32 2}
-!1 = !{!2, !3, !5, !7}
-!2 = !{!"RootCBV", i32 0, i32 3, i32 666, i32 4}
-!3 = !{!"DescriptorTable", i32 1, !4}
-!4 = !{!"SRV", i32 1, i32 0, i32 0, i32 -1, i32 4}
-!5 = !{!"DescriptorTable", i32 0, !6}
-!6 = !{!"Sampler", i32 2, i32 0, i32 0, i32 -1, i32 0}
-!7 = !{!"DescriptorTable", i32 0, !8}
-!8 = !{!"UAV", i32 -1, i32 0, i32 0, i32 -1, i32 2}
diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-constants.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-constants.ll
deleted file mode 100644
index dc7657e79ec97..0000000000000
--- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-constants.ll
+++ /dev/null
@@ -1,22 +0,0 @@
-; RUN: not opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 | FileCheck %s
-; CHECK: error: register CBuffer (space=666, register=2) does not have a binding in the Root Signature
-; Root Signature(RootConstants(num32BitConstants=4, b2))
-
-%__cblayout_CB = type <{ float }>
-
- at CB.str = private unnamed_addr constant [3 x i8] c"CB\00", align 1
-
-define void @CSMain() "hlsl.shader"="compute" {
-entry:
-; cbuffer CB : register(b2, space666) {
-;  float a;
-; }
-  %CB = tail call target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 4, 0)) @llvm.dx.resource.handlefrombinding(i32 666, i32 2, i32 1, i32 0, i1 false, ptr nonnull @CB.str)
-  ret void
-}
-
-!dx.rootsignatures = !{!0}
-
-!0 = !{ptr @CSMain, !1, i32 2}
-!1 = !{!2}
-!2 = !{!"RootConstants", i32 0, i32 2, i32 0, i32 4}
diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-descriptor-table-range.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-descriptor-table-range.ll
new file mode 100644
index 0000000000000..7108d9834219e
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-descriptor-table-range.ll
@@ -0,0 +1,15 @@
+; RUN: not opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 | FileCheck %s
+; CHECK: error: register UAV (space=10, register=4294967295) is overlapping with register UAV (space=10, register=4294967295), verify your root signature definition.
+define void @CSMain() "hlsl.shader"="compute" {
+entry:
+  ret void
+}
+
+; DescriptorTable(UAV(u0, numDescriptors=unbounded), visibility = SHADER_VISIBILITY_HULL), DescriptorTable(UAV(u2, numDescriptors=4))
+!dx.rootsignatures = !{!0}
+!0 = !{ptr @CSMain, !1, i32 2}
+!1 = !{!2, !4}
+!2 = !{!"DescriptorTable", i32 0, !3}
+!3 = !{!"UAV", i32 -1, i32 -1, i32 10, i32 -1, i32 2}
+!4 = !{!"DescriptorTable", i32 0, !5}
+!5 = !{ !"UAV", i32 -1, i32 -1, i32 10, i32 5, i32 2 }
\ No newline at end of file
diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-root-descriptor-range.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-root-descriptor-range.ll
new file mode 100644
index 0000000000000..7790230eb07a0
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-root-descriptor-range.ll
@@ -0,0 +1,15 @@
+; RUN: not opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 | FileCheck %s
+; CHECK: error: register UAV (space=1, register=3) is overlapping with register UAV (space=1, register=0), verify your root signature definition.
+
+define void @CSMain() "hlsl.shader"="compute" {
+entry:
+  ret void
+}
+
+; DescriptorTable(UAV(u0, numDescriptors=unbounded), visibility = SHADER_VISIBILITY_HULL), UAV(u3, space=1)
+!dx.rootsignatures = !{!0}
+!0 = !{ptr @CSMain, !1, i32 2}
+!1 = !{!2, !4}
+!2 = !{!"RootUAV", i32 0, i32 3, i32 1, i32 4}
+!4 = !{!"DescriptorTable", i32 0, !5}
+!5 = !{!"UAV", i32 3, i32 0, i32 1, i32 -1, i32 2}
\ No newline at end of file
diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler.ll
deleted file mode 100644
index 152c363fdf75b..0000000000000
--- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler.ll
+++ /dev/null
@@ -1,31 +0,0 @@
-; RUN: not opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 | FileCheck %s
-
-; CHECK: error: register Sampler (space=2, register=3) does not have a binding in the Root Signature
-
-; Root Signature(
-;   CBV(b3, space=666, visibility=SHADER_VISIBILITY_ALL)
-;   DescriptorTable(SRV(t0, space=0, numDescriptors=1), visibility=SHADER_VISIBILITY_VERTEX)
-;   DescriptorTable(Sampler(s0, numDescriptors=2), visibility=SHADER_VISIBILITY_ALL)
-;   DescriptorTable(UAV(u0, numDescriptors=unbounded), visibility=SHADER_VISIBILITY_ALL)
-
- at Smp.str = private unnamed_addr constant [4 x i8] c"Smp\00", align 1
-
-define void @CSMain() "hlsl.shader"="compute" {
-entry:
-; SamplerState S1 : register(s3, space2);
-  %Sampler = call target("dx.Sampler", 0) @llvm.dx.resource.handlefrombinding(i32 2, i32 3, i32 1, i32 0, i1 false, ptr nonnull @Smp.str)
-
-  ret void
-}
-
-!dx.rootsignatures = !{!0}
-
-!0 = !{ptr @CSMain, !1, i32 2}
-!1 = !{!2, !3, !5, !7}
-!2 = !{!"RootCBV", i32 0, i32 3, i32 666, i32 4}
-!3 = !{!"DescriptorTable", i32 1, !4}
-!4 = !{!"SRV", i32 1, i32 0, i32 0, i32 -1, i32 4}
-!5 = !{!"DescriptorTable", i32 0, !6}
-!6 = !{!"Sampler", i32 2, i32 0, i32 0, i32 -1, i32 0}
-!7 = !{!"DescriptorTable", i32 0, !8}
-!8 = !{!"UAV", i32 -1, i32 0, i32 0, i32 -1, i32 2}
diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-srv.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-srv.ll
deleted file mode 100644
index ebefa7b1a3d85..0000000000000
--- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-srv.ll
+++ /dev/null
@@ -1,30 +0,0 @@
-; RUN: not opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 | FileCheck %s
-
-; CHECK: error: register SRV (space=0, register=0) does not have a binding in the Root Signature
-
-; Root Signature(
-;   CBV(b3, space=666, visibility=SHADER_VISIBILITY_ALL)
-;   DescriptorTable(SRV(t0, space=0, numDescriptors=1), visibility=SHADER_VISIBILITY_VERTEX)
-;   DescriptorTable(Sampler(s0, numDescriptors=2), visibility=SHADER_VISIBILITY_ALL)
-;   DescriptorTable(UAV(u0, numDescriptors=unbounded), visibility=SHADER_VISIBILITY_ALL)
-
- at SB.str = private unnamed_addr constant [3 x i8] c"SB\00", align 1
-
-define void @CSMain() "hlsl.shader"="compute" {
-entry:
-; StructuredBuffer<int> In : register(t0, space0);
-  %SB = tail call target("dx.RawBuffer", i32, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i32_0_0t(i32 0, i32 0, i32 1, i32 0, i1 false, ptr nonnull @SB.str)
-  ret void
-}
-
-!dx.rootsignatures = !{!0}
-
-!0 = !{ptr @CSMain, !1, i32 2}
-!1 = !{!2, !3, !5, !7}
-!2 = !{!"RootCBV", i32 0, i32 3, i32 666, i32 4}
-!3 = !{!"DescriptorTable", i32 1, !4}
-!4 = !{!"SRV", i32 1, i32 0, i32 0, i32 -1, i32 4}
-!5 = !{!"DescriptorTable", i32 0, !6}
-!6 = !{!"Sampler", i32 2, i32 0, i32 0, i32 -1, i32 0}
-!7 = !{!"DescriptorTable", i32 0, !8}
-!8 = !{!"UAV", i32 -1, i32 0, i32 0, i32 -1, i32 2}
diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-static-sampler-range.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-static-sampler-range.ll
new file mode 100644
index 0000000000000..bbcc42769d7be
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-static-sampler-range.ll
@@ -0,0 +1,13 @@
+; RUN: not opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 | FileCheck %s
+; CHECK: error: register Sampler (space=0, register=42) is overlapping with register Sampler (space=0, register=42), verify your root signature definition.
+
+define void @CSMain() "hlsl.shader"="compute" {
+entry:
+  ret void
+}
+
+!dx.rootsignatures = !{!0}
+!0 = !{ptr @CSMain, !1, i32 2}
+!1 = !{!2, !3}
+!2 = !{ !"StaticSampler", i32 5, i32 4, i32 5, i32 3, float 0x3FF7CCCCC0000000, i32 10, i32 2, i32 1, float -1.270000e+02, float 1.220000e+02, i32 42, i32 0, i32 0 }
+!3 = !{ !"StaticSampler", i32 4, i32 2, i32 3, i32 5, float 0x3FF6CCCCC0000000, i32 9, i32 3, i32 2, float -1.280000e+02, float 1.280000e+02, i32 42, i32 0, i32 0 }
\ No newline at end of file
diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-uav.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-uav.ll
deleted file mode 100644
index 9cc5b6744a4a2..0000000000000
--- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-uav.ll
+++ /dev/null
@@ -1,30 +0,0 @@
-; RUN: not opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 | FileCheck %s
-
-; CHECK: error: register UAV (space=0, register=4294967294) does not have a binding in the Root Signature
-
-; Root Signature(
-;   CBV(b3, space=666, visibility=SHADER_VISIBILITY_ALL)
-;   DescriptorTable(SRV(t0, space=0, numDescriptors=1), visibility=SHADER_VISIBILITY_VERTEX)
-;   DescriptorTable(Sampler(s0, numDescriptors=2), visibility=SHADER_VISIBILITY_ALL)
-;   DescriptorTable(UAV(u0, numDescriptors=unbounded), visibility=SHADER_VISIBILITY_ALL)
-
- at RWB.str = private unnamed_addr constant [4 x i8] c"RWB\00", align 1
-
-define void @CSMain() "hlsl.shader"="compute" {
-entry:
-; RWBuffer<float> UAV : register(4294967294);
-  %RWB = tail call target("dx.TypedBuffer", float, 1, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0_0t(i32 0, i32 4294967294, i32 1, i32 0, i1 false, ptr nonnull @RWB.str)
-  ret void
-}
-
-!dx.rootsignatures = !{!0}
-
-!0 = !{ptr @CSMain, !1, i32 2}
-!1 = !{!2, !3, !5, !7}
-!2 = !{!"RootCBV", i32 0, i32 3, i32 666, i32 4}
-!3 = !{!"DescriptorTable", i32 1, !4}
-!4 = !{!"SRV", i32 1, i32 0, i32 0, i32 -1, i32 4}
-!5 = !{!"DescriptorTable", i32 0, !6}
-!6 = !{!"Sampler", i32 2, i32 0, i32 0, i32 -1, i32 0}
-!7 = !{!"DescriptorTable", i32 0, !8}
-!8 = !{!"UAV", i32 10, i32 0, i32 0, i32 -1, i32 2}

>From 29eb893bcb28676157c6c2314f55ff6d7e33043f Mon Sep 17 00:00:00 2001
From: Joao Saffran <{ID}+{username}@users.noreply.github.com>
Date: Tue, 5 Aug 2025 14:43:51 -0700
Subject: [PATCH 03/11] cleanup

---
 llvm/include/llvm/Frontend/HLSL/HLSLBinding.h    |  3 ---
 llvm/lib/Frontend/HLSL/HLSLBinding.cpp           | 16 ----------------
 ...ature-validation-fail-static-sampler-range.ll |  2 +-
 3 files changed, 1 insertion(+), 20 deletions(-)

diff --git a/llvm/include/llvm/Frontend/HLSL/HLSLBinding.h b/llvm/include/llvm/Frontend/HLSL/HLSLBinding.h
index af7f2402c0fa0..70a2eeb632f1b 100644
--- a/llvm/include/llvm/Frontend/HLSL/HLSLBinding.h
+++ b/llvm/include/llvm/Frontend/HLSL/HLSLBinding.h
@@ -57,7 +57,6 @@ class BindingInfo {
     }
     // Size == -1 means unbounded array
     LLVM_ABI std::optional<uint32_t> findAvailableBinding(int32_t Size);
-    LLVM_ABI bool isBound(BindingRange B);
   };
 
   struct BindingSpaces {
@@ -96,8 +95,6 @@ class BindingInfo {
   LLVM_ABI std::optional<uint32_t>
   findAvailableBinding(dxil::ResourceClass RC, uint32_t Space, int32_t Size);
 
-  LLVM_ABI bool isBound(dxil::ResourceClass RC, uint32_t Space, BindingRange B);
-
   friend class BindingInfoBuilder;
 };
 
diff --git a/llvm/lib/Frontend/HLSL/HLSLBinding.cpp b/llvm/lib/Frontend/HLSL/HLSLBinding.cpp
index 57075ca430d44..d581311f22028 100644
--- a/llvm/lib/Frontend/HLSL/HLSLBinding.cpp
+++ b/llvm/lib/Frontend/HLSL/HLSLBinding.cpp
@@ -66,22 +66,6 @@ BindingInfo::RegisterSpace::findAvailableBinding(int32_t Size) {
   return std::nullopt;
 }
 
-bool BindingInfo::RegisterSpace::isBound(BindingRange B) {
-  for (BindingRange &R : FreeRanges) {
-    if (B.LowerBound >= R.LowerBound && B.LowerBound < R.UpperBound &&
-        B.UpperBound > R.LowerBound && B.UpperBound <= R.UpperBound)
-      return false;
-  }
-  return true;
-}
-
-bool BindingInfo::isBound(dxil::ResourceClass RC, uint32_t Space,
-                          BindingRange B) {
-  BindingSpaces &BS = getBindingSpaces(RC);
-  RegisterSpace &RS = BS.getOrInsertSpace(Space);
-  return RS.isBound(B);
-}
-
 BindingInfo BindingInfoBuilder::calculateBindingInfo(
     llvm::function_ref<void(const BindingInfoBuilder &Builder,
                             const Binding &Overlapping)>
diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-static-sampler-range.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-static-sampler-range.ll
index bbcc42769d7be..340b0aed6d16b 100644
--- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-static-sampler-range.ll
+++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-static-sampler-range.ll
@@ -10,4 +10,4 @@ entry:
 !0 = !{ptr @CSMain, !1, i32 2}
 !1 = !{!2, !3}
 !2 = !{ !"StaticSampler", i32 5, i32 4, i32 5, i32 3, float 0x3FF7CCCCC0000000, i32 10, i32 2, i32 1, float -1.270000e+02, float 1.220000e+02, i32 42, i32 0, i32 0 }
-!3 = !{ !"StaticSampler", i32 4, i32 2, i32 3, i32 5, float 0x3FF6CCCCC0000000, i32 9, i32 3, i32 2, float -1.280000e+02, float 1.280000e+02, i32 42, i32 0, i32 0 }
\ No newline at end of file
+!3 = !{ !"StaticSampler", i32 4, i32 2, i32 3, i32 5, float 0x3FF6CCCCC0000000, i32 9, i32 3, i32 2, float -1.280000e+02, float 1.280000e+02, i32 42, i32 0, i32 0 }

>From ed4c5539bf15b241a3d2ec243068d714fbe37acb Mon Sep 17 00:00:00 2001
From: Joao Saffran <{ID}+{username}@users.noreply.github.com>
Date: Tue, 5 Aug 2025 14:46:26 -0700
Subject: [PATCH 04/11] clean

---
 .../rootsignature-validation-fail-descriptor-table-range.ll     | 2 +-
 .../rootsignature-validation-fail-root-descriptor-range.ll      | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-descriptor-table-range.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-descriptor-table-range.ll
index 7108d9834219e..dbc75ac86db5f 100644
--- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-descriptor-table-range.ll
+++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-descriptor-table-range.ll
@@ -12,4 +12,4 @@ entry:
 !2 = !{!"DescriptorTable", i32 0, !3}
 !3 = !{!"UAV", i32 -1, i32 -1, i32 10, i32 -1, i32 2}
 !4 = !{!"DescriptorTable", i32 0, !5}
-!5 = !{ !"UAV", i32 -1, i32 -1, i32 10, i32 5, i32 2 }
\ No newline at end of file
+!5 = !{ !"UAV", i32 -1, i32 -1, i32 10, i32 5, i32 2 }
diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-root-descriptor-range.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-root-descriptor-range.ll
index 7790230eb07a0..9f70cc3f062a9 100644
--- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-root-descriptor-range.ll
+++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-root-descriptor-range.ll
@@ -12,4 +12,4 @@ entry:
 !1 = !{!2, !4}
 !2 = !{!"RootUAV", i32 0, i32 3, i32 1, i32 4}
 !4 = !{!"DescriptorTable", i32 0, !5}
-!5 = !{!"UAV", i32 3, i32 0, i32 1, i32 -1, i32 2}
\ No newline at end of file
+!5 = !{!"UAV", i32 3, i32 0, i32 1, i32 -1, i32 2}

>From 28fb609226910ef2ae4ef6caa8b5116df846d114 Mon Sep 17 00:00:00 2001
From: Joao Saffran <{ID}+{username}@users.noreply.github.com>
Date: Tue, 5 Aug 2025 17:21:18 -0700
Subject: [PATCH 05/11] clean up

---
 .../Frontend/HLSL/RootSignatureValidations.h  | 129 +++---------------
 .../llvm/MC/DXContainerRootSignature.h        |   2 +
 llvm/lib/Target/DirectX/DXILPrepare.cpp       |   1 +
 llvm/lib/Target/DirectX/DXILRootSignature.cpp |   5 +-
 llvm/lib/Target/DirectX/DXILRootSignature.h   |  12 +-
 ...signature-validation-fail-cbuffer-range.ll |   2 +-
 6 files changed, 23 insertions(+), 128 deletions(-)

diff --git a/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h b/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h
index bb6aeeb177412..fde32a1fff591 100644
--- a/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h
+++ b/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h
@@ -16,6 +16,7 @@
 
 #include "llvm/ADT/IntervalMap.h"
 #include "llvm/Frontend/HLSL/HLSLRootSignature.h"
+#include "llvm/Support/Compiler.h"
 
 namespace llvm {
 namespace hlsl {
@@ -23,118 +24,22 @@ namespace rootsig {
 
 // Basic verification of RootElements
 
-bool verifyRootFlag(uint32_t Flags);
-bool verifyVersion(uint32_t Version);
-bool verifyRegisterValue(uint32_t RegisterValue);
-bool verifyRegisterSpace(uint32_t RegisterSpace);
-bool verifyRootDescriptorFlag(uint32_t Version, uint32_t FlagsVal);
-bool verifyRangeType(uint32_t Type);
-bool verifyDescriptorRangeFlag(uint32_t Version, uint32_t Type,
-                               uint32_t FlagsVal);
-bool verifyNumDescriptors(uint32_t NumDescriptors);
-bool verifySamplerFilter(uint32_t Value);
-bool verifyAddress(uint32_t Address);
-bool verifyMipLODBias(float MipLODBias);
-bool verifyMaxAnisotropy(uint32_t MaxAnisotropy);
-bool verifyComparisonFunc(uint32_t ComparisonFunc);
-bool verifyBorderColor(uint32_t BorderColor);
-bool verifyLOD(float LOD);
-
-struct RangeInfo {
-  const static uint32_t Unbounded = ~0u;
-
-  // Interval information
-  uint32_t LowerBound;
-  uint32_t UpperBound;
-
-  // Information retained for determining overlap
-  llvm::dxil::ResourceClass Class;
-  uint32_t Space;
-  llvm::dxbc::ShaderVisibility Visibility;
-};
-
-class ResourceRange {
-public:
-  using MapT = llvm::IntervalMap<uint32_t, const RangeInfo *, 16,
-                                 llvm::IntervalMapInfo<uint32_t>>;
-
-private:
-  MapT Intervals;
-
-public:
-  ResourceRange(MapT::Allocator &Allocator) : Intervals(MapT(Allocator)) {}
-
-  // Returns a reference to the first RangeInfo that overlaps with
-  // [Info.LowerBound;Info.UpperBound], or, std::nullopt if there is no overlap
-  LLVM_ABI std::optional<const RangeInfo *>
-  getOverlapping(const RangeInfo &Info) const;
-
-  // Return the mapped RangeInfo at X or nullptr if no mapping exists
-  LLVM_ABI const RangeInfo *lookup(uint32_t X) const;
-
-  // Removes all entries of the ResourceRange
-  LLVM_ABI void clear();
-
-  // Insert the required (sub-)intervals such that the interval of [a;b] =
-  // [Info.LowerBound, Info.UpperBound] is covered and points to a valid
-  // RangeInfo &.
-  //
-  // For instance consider the following chain of inserting RangeInfos with the
-  // intervals denoting the Lower/Upper-bounds:
-  //
-  // A = [0;2]
-  //   insert(A) -> false
-  //   intervals: [0;2] -> &A
-  // B = [5;7]
-  //   insert(B) -> false
-  //   intervals: [0;2] -> &A, [5;7] -> &B
-  // C = [4;7]
-  //   insert(C) -> true
-  //   intervals: [0;2] -> &A, [4;7] -> &C
-  // D = [1;5]
-  //   insert(D) -> true
-  //   intervals: [0;2] -> &A, [3;3] -> &D, [4;7] -> &C
-  // E = [0;unbounded]
-  //   insert(E) -> true
-  //   intervals: [0;unbounded] -> E
-  //
-  // Returns a reference to the first RangeInfo that overlaps with
-  // [Info.LowerBound;Info.UpperBound], or, std::nullopt if there is no overlap
-  // (equivalent to getOverlapping)
-  LLVM_ABI std::optional<const RangeInfo *> insert(const RangeInfo &Info);
-};
-
-struct OverlappingRanges {
-  const RangeInfo *A;
-  const RangeInfo *B;
-
-  OverlappingRanges(const RangeInfo *A, const RangeInfo *B) : A(A), B(B) {}
-};
-
-/// The following conducts analysis on resource ranges to detect and report
-/// any overlaps in resource ranges.
-///
-/// A resource range overlaps with another resource range if they have:
-/// - equivalent ResourceClass (SRV, UAV, CBuffer, Sampler)
-/// - equivalent resource space
-/// - overlapping visbility
-///
-/// The algorithm is implemented in the following steps:
-///
-/// 1. The user will collect RangeInfo from relevant RootElements:
-///   - RangeInfo will retain the interval, ResourceClass, Space and Visibility
-///   - It will also contain an index so that it can be associated to
-/// additional diagnostic information
-/// 2. Sort the RangeInfo's such that they are grouped together by
-///  ResourceClass and Space
-/// 3. Iterate through the collected RangeInfos by their groups
-///   - For each group we will have a ResourceRange for each visibility
-///   - As we iterate through we will:
-///      A: Insert the current RangeInfo into the corresponding Visibility
-///   ResourceRange
-///      B: Check for overlap with any overlapping Visibility ResourceRange
-LLVM_ABI llvm::SmallVector<OverlappingRanges>
-findOverlappingRanges(ArrayRef<RangeInfo> Infos);
+LLVM_ABI bool verifyRootFlag(uint32_t Flags);
+LLVM_ABI bool verifyVersion(uint32_t Version);
+LLVM_ABI bool verifyRegisterValue(uint32_t RegisterValue);
+LLVM_ABI bool verifyRegisterSpace(uint32_t RegisterSpace);
+LLVM_ABI bool verifyRootDescriptorFlag(uint32_t Version, uint32_t FlagsVal);
+LLVM_ABI bool verifyRangeType(uint32_t Type);
+LLVM_ABI bool verifyDescriptorRangeFlag(uint32_t Version, uint32_t Type,
+                                        uint32_t FlagsVal);
+LLVM_ABI bool verifyNumDescriptors(uint32_t NumDescriptors);
+LLVM_ABI bool verifySamplerFilter(uint32_t Value);
+LLVM_ABI bool verifyAddress(uint32_t Address);
+LLVM_ABI bool verifyMipLODBias(float MipLODBias);
+LLVM_ABI bool verifyMaxAnisotropy(uint32_t MaxAnisotropy);
+LLVM_ABI bool verifyComparisonFunc(uint32_t ComparisonFunc);
+LLVM_ABI bool verifyBorderColor(uint32_t BorderColor);
+LLVM_ABI bool verifyLOD(float LOD);
 
 } // namespace rootsig
 } // namespace hlsl
diff --git a/llvm/include/llvm/MC/DXContainerRootSignature.h b/llvm/include/llvm/MC/DXContainerRootSignature.h
index a931b1d54b65c..3c7c886e79fc3 100644
--- a/llvm/include/llvm/MC/DXContainerRootSignature.h
+++ b/llvm/include/llvm/MC/DXContainerRootSignature.h
@@ -5,6 +5,7 @@
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
+
 #ifndef LLVM_MC_DXCONTAINERROOTSIGNATURE_H
 #define LLVM_MC_DXCONTAINERROOTSIGNATURE_H
 
@@ -119,4 +120,5 @@ struct RootSignatureDesc {
 };
 } // namespace mcdxbc
 } // namespace llvm
+
 #endif // LLVM_MC_DXCONTAINERROOTSIGNATURE_H
diff --git a/llvm/lib/Target/DirectX/DXILPrepare.cpp b/llvm/lib/Target/DirectX/DXILPrepare.cpp
index 9c3eba83eba7c..c8866bfefdfc5 100644
--- a/llvm/lib/Target/DirectX/DXILPrepare.cpp
+++ b/llvm/lib/Target/DirectX/DXILPrepare.cpp
@@ -300,6 +300,7 @@ class DXILPrepareModule : public ModulePass {
   DXILPrepareModule() : ModulePass(ID) {}
   void getAnalysisUsage(AnalysisUsage &AU) const override {
     AU.addRequired<DXILMetadataAnalysisWrapperPass>();
+    AU.addRequired<RootSignatureAnalysisWrapper>();
     AU.addPreserved<RootSignatureAnalysisWrapper>();
     AU.addPreserved<ShaderFlagsAnalysisWrapper>();
     AU.addPreserved<DXILMetadataAnalysisWrapperPass>();
diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.cpp b/llvm/lib/Target/DirectX/DXILRootSignature.cpp
index eb9ff5ab405e4..a4f5086c2f428 100644
--- a/llvm/lib/Target/DirectX/DXILRootSignature.cpp
+++ b/llvm/lib/Target/DirectX/DXILRootSignature.cpp
@@ -29,8 +29,6 @@
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/raw_ostream.h"
 #include <cstdint>
-#include <optional>
-#include <utility>
 
 using namespace llvm;
 using namespace llvm::dxil;
@@ -235,7 +233,7 @@ bool RootSignatureAnalysisWrapper::runOnModule(Module &M) {
 
 void RootSignatureAnalysisWrapper::getAnalysisUsage(AnalysisUsage &AU) const {
   AU.setPreservesAll();
-  AU.addRequired<DXILMetadataAnalysisWrapperPass>();
+  AU.addPreserved<DXILMetadataAnalysisWrapperPass>();
 }
 
 char RootSignatureAnalysisWrapper::ID = 0;
@@ -243,7 +241,6 @@ char RootSignatureAnalysisWrapper::ID = 0;
 INITIALIZE_PASS_BEGIN(RootSignatureAnalysisWrapper,
                       "dxil-root-signature-analysis",
                       "DXIL Root Signature Analysis", true, true)
-INITIALIZE_PASS_DEPENDENCY(DXILMetadataAnalysisWrapperPass)
 INITIALIZE_PASS_END(RootSignatureAnalysisWrapper,
                     "dxil-root-signature-analysis",
                     "DXIL Root Signature Analysis", true, true)
diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.h b/llvm/lib/Target/DirectX/DXILRootSignature.h
index ccffa3fd0a3e2..254b7ff504633 100644
--- a/llvm/lib/Target/DirectX/DXILRootSignature.h
+++ b/llvm/lib/Target/DirectX/DXILRootSignature.h
@@ -26,16 +26,6 @@
 namespace llvm {
 namespace dxil {
 
-enum class RootSignatureElementKind {
-  Error = 0,
-  RootFlags = 1,
-  RootConstants = 2,
-  SRV = 3,
-  UAV = 4,
-  CBV = 5,
-  DescriptorTable = 6,
-};
-
 class RootSignatureBindingInfo {
 private:
   SmallDenseMap<const Function *, mcdxbc::RootSignatureDesc> FuncToRsMap;
@@ -106,4 +96,4 @@ class RootSignatureAnalysisPrinter
 
 } // namespace dxil
 } // namespace llvm
-#endif // LLVM_LIB_TARGET_DIRECTX_DXILROOTSIGNATURE_H
+#endif
diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbuffer-range.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbuffer-range.ll
index 5def38af0fbeb..47d2a5b8d5aab 100644
--- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbuffer-range.ll
+++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbuffer-range.ll
@@ -12,4 +12,4 @@ entry:
 !1 = !{!2, !3}
 !2 = !{!"RootConstants", i32 0, i32 2, i32 0, i32 4}
 !3 = !{!"DescriptorTable", i32 0, !4}
-!4 = !{!"CBV", i32 3, i32 0, i32 0, i32 -1, i32 4}
\ No newline at end of file
+!4 = !{!"CBV", i32 3, i32 0, i32 0, i32 -1, i32 4}

>From 403972dbde579a83de8c6a2b7ec2468be2c2b202 Mon Sep 17 00:00:00 2001
From: Joao Saffran <jderezende at microsoft.com>
Date: Thu, 7 Aug 2025 15:07:56 -0700
Subject: [PATCH 06/11] addressing comments from bogner and inbelic

---
 llvm/include/llvm/Analysis/DXILResource.h     |  15 --
 llvm/include/llvm/Support/DXILABI.h           |   3 +
 llvm/lib/Support/DXILABI.cpp                  |  19 +++
 llvm/lib/Target/DirectX/DXILOpLowering.cpp    |   1 +
 .../DXILPostOptimizationValidation.cpp        | 135 ++++++++----------
 llvm/lib/Target/DirectX/DXILRootSignature.h   |   8 +-
 ...e-validation-fail-root-descriptor-range.ll |   3 +-
 7 files changed, 90 insertions(+), 94 deletions(-)
 create mode 100644 llvm/lib/Support/DXILABI.cpp

diff --git a/llvm/include/llvm/Analysis/DXILResource.h b/llvm/include/llvm/Analysis/DXILResource.h
index 96d631698af0a..557fc513c2a57 100644
--- a/llvm/include/llvm/Analysis/DXILResource.h
+++ b/llvm/include/llvm/Analysis/DXILResource.h
@@ -32,21 +32,6 @@ class Value;
 class DXILResourceTypeMap;
 
 namespace dxil {
-
-inline StringRef getResourceClassName(ResourceClass RC) {
-  switch (RC) {
-  case ResourceClass::SRV:
-    return "SRV";
-  case ResourceClass::UAV:
-    return "UAV";
-  case ResourceClass::CBuffer:
-    return "CBuffer";
-  case ResourceClass::Sampler:
-    return "Sampler";
-  }
-  llvm_unreachable("Unhandled ResourceClass");
-}
-
 // Returns the resource name from dx_resource_handlefrombinding or
 // dx_resource_handlefromimplicitbinding call
 LLVM_ABI StringRef getResourceNameFromBindingCall(CallInst *CI);
diff --git a/llvm/include/llvm/Support/DXILABI.h b/llvm/include/llvm/Support/DXILABI.h
index b479f7c73eba3..397906a3466c5 100644
--- a/llvm/include/llvm/Support/DXILABI.h
+++ b/llvm/include/llvm/Support/DXILABI.h
@@ -17,6 +17,7 @@
 #ifndef LLVM_SUPPORT_DXILABI_H
 #define LLVM_SUPPORT_DXILABI_H
 
+#include "llvm/ADT/StringRef.h"
 #include <cstdint>
 
 namespace llvm {
@@ -99,6 +100,8 @@ enum class SamplerFeedbackType : uint32_t {
 const unsigned MinWaveSize = 4;
 const unsigned MaxWaveSize = 128;
 
+StringRef getResourceClassName(ResourceClass RC);
+
 } // namespace dxil
 } // namespace llvm
 
diff --git a/llvm/lib/Support/DXILABI.cpp b/llvm/lib/Support/DXILABI.cpp
new file mode 100644
index 0000000000000..510e15b403ab1
--- /dev/null
+++ b/llvm/lib/Support/DXILABI.cpp
@@ -0,0 +1,19 @@
+
+#include "llvm/Support/DXILABI.h"
+#include "llvm/Support/ErrorHandling.h"
+
+using namespace llvm;
+
+StringRef getResourceClassName(dxil::ResourceClass RC) {
+  switch (RC) {
+  case dxil::ResourceClass::SRV:
+    return "SRV";
+  case dxil::ResourceClass::UAV:
+    return "UAV";
+  case dxil::ResourceClass::CBuffer:
+    return "CBuffer";
+  case dxil::ResourceClass::Sampler:
+    return "Sampler";
+  }
+  llvm_unreachable("Unhandled ResourceClass");
+}
\ No newline at end of file
diff --git a/llvm/lib/Target/DirectX/DXILOpLowering.cpp b/llvm/lib/Target/DirectX/DXILOpLowering.cpp
index db7719e129ad0..1cfba523183c8 100644
--- a/llvm/lib/Target/DirectX/DXILOpLowering.cpp
+++ b/llvm/lib/Target/DirectX/DXILOpLowering.cpp
@@ -919,6 +919,7 @@ PreservedAnalyses DXILOpLowering::run(Module &M, ModuleAnalysisManager &MAM) {
   PA.preserve<DXILResourceAnalysis>();
   PA.preserve<DXILMetadataAnalysis>();
   PA.preserve<ShaderFlagsAnalysis>();
+  PA.preserve<RootSignatureAnalysisWrapper>();
   return PA;
 }
 
diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
index 3da4cfbea23b8..368c8c6b5dbba 100644
--- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
+++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
@@ -13,21 +13,22 @@
 #include "llvm/ADT/SmallString.h"
 #include "llvm/Analysis/DXILMetadataAnalysis.h"
 #include "llvm/Analysis/DXILResource.h"
+#include "llvm/BinaryFormat/DXContainer.h"
 #include "llvm/IR/DiagnosticInfo.h"
 #include "llvm/IR/Instructions.h"
 #include "llvm/IR/IntrinsicsDirectX.h"
 #include "llvm/IR/Module.h"
 #include "llvm/InitializePasses.h"
+#include <cstdint>
 
 #define DEBUG_TYPE "dxil-post-optimization-validation"
 
 using namespace llvm;
 using namespace llvm::dxil;
 
-namespace {
-static ResourceClass RangeToResourceClass(uint32_t RangeType) {
+static ResourceClass toResourceClass(dxbc::DescriptorRangeType RangeType) {
   using namespace dxbc;
-  switch (static_cast<DescriptorRangeType>(RangeType)) {
+  switch (RangeType) {
   case DescriptorRangeType::SRV:
     return ResourceClass::SRV;
   case DescriptorRangeType::UAV:
@@ -39,20 +40,21 @@ static ResourceClass RangeToResourceClass(uint32_t RangeType) {
   }
 }
 
-ResourceClass ParameterToResourceClass(uint32_t Type) {
+static ResourceClass toResourceClass(dxbc::RootParameterType Type) {
   using namespace dxbc;
   switch (Type) {
-  case llvm::to_underlying(RootParameterType::Constants32Bit):
+  case RootParameterType::Constants32Bit:
     return ResourceClass::CBuffer;
-  case llvm::to_underlying(RootParameterType::SRV):
+  case RootParameterType::SRV:
     return ResourceClass::SRV;
-  case llvm::to_underlying(RootParameterType::UAV):
+  case RootParameterType::UAV:
     return ResourceClass::UAV;
-  case llvm::to_underlying(RootParameterType::CBV):
+  case RootParameterType::CBV:
     return ResourceClass::CBuffer;
-  default:
-    llvm_unreachable("Unknown RootParameterType");
+  case dxbc::RootParameterType::DescriptorTable:
+    break;
   }
+  llvm_unreachable("Unconvertible RootParameterType");
 }
 
 static void reportInvalidDirection(Module &M, DXILResourceMap &DRM) {
@@ -131,12 +133,6 @@ static void reportOverlappingRegisters(
 
 static dxbc::ShaderVisibility
 tripleToVisibility(llvm::Triple::EnvironmentType ET) {
-  assert((ET == Triple::Pixel || ET == Triple::Vertex ||
-          ET == Triple::Geometry || ET == Triple::Hull ||
-          ET == Triple::Domain || ET == Triple::Mesh ||
-          ET == Triple::Compute) &&
-         "Invalid Triple to shader stage conversion");
-
   switch (ET) {
   case Triple::Pixel:
     return dxbc::ShaderVisibility::Pixel;
@@ -157,73 +153,80 @@ tripleToVisibility(llvm::Triple::EnvironmentType ET) {
   }
 }
 
-static void trackRootSigDescBinding(hlsl::BindingInfoBuilder &Builder,
-                                    const mcdxbc::RootSignatureDesc &RSD,
-                                    dxbc::ShaderVisibility Visibility) {
-  for (size_t I = 0; I < RSD.ParametersContainer.size(); I++) {
-    const auto &[Type, Loc] =
-        RSD.ParametersContainer.getTypeAndLocForParameter(I);
-
-    const auto &Header = RSD.ParametersContainer.getHeader(I);
-    if (Header.ShaderVisibility !=
-            llvm::to_underlying(dxbc::ShaderVisibility::All) &&
-        Header.ShaderVisibility != llvm::to_underlying(Visibility))
-      continue;
+static void validateRootSignature(Module &M,
+                                  const mcdxbc::RootSignatureDesc &RSD,
+                                  dxil::ModuleMetadataInfo &MMI) {
 
-    switch (Type) {
-    case llvm::to_underlying(dxbc::RootParameterType::Constants32Bit): {
+  hlsl::BindingInfoBuilder Builder;
+  dxbc::ShaderVisibility Visibility = tripleToVisibility(MMI.ShaderProfile);
+
+  for (const mcdxbc::RootParameterInfo &ParamInfo : RSD.ParametersContainer) {
+    dxbc::ShaderVisibility ParamVisibility =
+        static_cast<dxbc::ShaderVisibility>(ParamInfo.Header.ShaderVisibility);
+    if (ParamVisibility != dxbc::ShaderVisibility::All &&
+        ParamVisibility != Visibility)
+      continue;
+    dxbc::RootParameterType ParamType =
+        static_cast<dxbc::RootParameterType>(ParamInfo.Header.ParameterType);
+    switch (ParamType) {
+    case dxbc::RootParameterType::Constants32Bit: {
       dxbc::RTS0::v1::RootConstants Const =
-          RSD.ParametersContainer.getConstant(Loc);
+          RSD.ParametersContainer.getConstant(ParamInfo.Location);
       Builder.trackBinding(dxil::ResourceClass::CBuffer, Const.RegisterSpace,
-                           Const.ShaderRegister,
-                           Const.ShaderRegister + Const.Num32BitValues, &Const);
+                           Const.ShaderRegister, Const.ShaderRegister, nullptr);
       break;
     }
 
-    case llvm::to_underlying(dxbc::RootParameterType::SRV):
-    case llvm::to_underlying(dxbc::RootParameterType::UAV):
-    case llvm::to_underlying(dxbc::RootParameterType::CBV): {
+    case dxbc::RootParameterType::SRV:
+    case dxbc::RootParameterType::UAV:
+    case dxbc::RootParameterType::CBV: {
       dxbc::RTS0::v2::RootDescriptor Desc =
-          RSD.ParametersContainer.getRootDescriptor(Loc);
-      Builder.trackBinding(ParameterToResourceClass(Type), Desc.RegisterSpace,
-                           Desc.ShaderRegister, Desc.ShaderRegister, &Desc);
+          RSD.ParametersContainer.getRootDescriptor(ParamInfo.Location);
+      Builder.trackBinding(toResourceClass(static_cast<dxbc::RootParameterType>(
+                               ParamInfo.Header.ParameterType)),
+                           Desc.RegisterSpace, Desc.ShaderRegister,
+                           Desc.ShaderRegister, nullptr);
 
       break;
     }
-    case llvm::to_underlying(dxbc::RootParameterType::DescriptorTable): {
+    case dxbc::RootParameterType::DescriptorTable: {
       const mcdxbc::DescriptorTable &Table =
-          RSD.ParametersContainer.getDescriptorTable(Loc);
+          RSD.ParametersContainer.getDescriptorTable(ParamInfo.Location);
 
       for (const dxbc::RTS0::v2::DescriptorRange &Range : Table.Ranges) {
-        Builder.trackBinding(RangeToResourceClass(Range.RangeType),
-                             Range.RegisterSpace, Range.BaseShaderRegister,
-                             Range.NumDescriptors == ~0U
-                                 ? Range.NumDescriptors
-                                 : Range.BaseShaderRegister +
-                                       Range.NumDescriptors,
-                             &Range);
+        uint32_t UpperBound =
+            Range.NumDescriptors == ~0U
+                ? Range.BaseShaderRegister
+                : Range.BaseShaderRegister + Range.NumDescriptors - 1;
+        Builder.trackBinding(
+            toResourceClass(
+                static_cast<dxbc::DescriptorRangeType>(Range.RangeType)),
+            Range.RegisterSpace, Range.BaseShaderRegister, UpperBound, nullptr);
       }
       break;
     }
     }
   }
 
-  for (auto &S : RSD.StaticSamplers) {
+  for (const dxbc::RTS0::v1::StaticSampler &S : RSD.StaticSamplers)
     Builder.trackBinding(dxil::ResourceClass::Sampler, S.RegisterSpace,
-                         S.ShaderRegister, S.ShaderRegister, &S);
-  }
+                         S.ShaderRegister, S.ShaderRegister, nullptr);
+
+  hlsl::BindingInfo Info = Builder.calculateBindingInfo(
+      [&M](const llvm::hlsl::BindingInfoBuilder &Builder,
+           const llvm::hlsl::BindingInfoBuilder::Binding &ReportedBinding) {
+        const llvm::hlsl::BindingInfoBuilder::Binding &Overlaping =
+            Builder.findOverlapping(ReportedBinding);
+        reportOverlappingRegisters(M, ReportedBinding, Overlaping);
+      });
 }
 
-std::optional<mcdxbc::RootSignatureDesc>
+static mcdxbc::RootSignatureDesc *
 getRootSignature(RootSignatureBindingInfo &RSBI,
                  dxil::ModuleMetadataInfo &MMI) {
   if (MMI.EntryPropertyVec.size() == 0)
-    return std::nullopt;
-  std::optional<mcdxbc::RootSignatureDesc> RootSigDesc =
-      RSBI.getDescForFunction(MMI.EntryPropertyVec[0].Entry);
-  if (!RootSigDesc)
-    return std::nullopt;
-  return RootSigDesc;
+    return nullptr;
+  return RSBI.getDescForFunction(MMI.EntryPropertyVec[0].Entry);
 }
 
 static void reportErrors(Module &M, DXILResourceMap &DRM,
@@ -239,21 +242,9 @@ static void reportErrors(Module &M, DXILResourceMap &DRM,
   assert(!DRBI.hasImplicitBinding() && "implicit bindings should be handled in "
                                        "DXILResourceImplicitBinding pass");
 
-  if (auto RSD = getRootSignature(RSBI, MMI)) {
-
-    hlsl::BindingInfoBuilder Builder;
-    dxbc::ShaderVisibility Visibility = tripleToVisibility(MMI.ShaderProfile);
-    trackRootSigDescBinding(Builder, *RSD, Visibility);
-    hlsl::BindingInfo Info = Builder.calculateBindingInfo(
-        [&M](const llvm::hlsl::BindingInfoBuilder &Builder,
-             const llvm::hlsl::BindingInfoBuilder::Binding &ReportedBinding) {
-          const llvm::hlsl::BindingInfoBuilder::Binding &Overlaping =
-              Builder.findOverlapping(ReportedBinding);
-          reportOverlappingRegisters(M, ReportedBinding, Overlaping);
-        });
-  }
+  if (mcdxbc::RootSignatureDesc *RSD = getRootSignature(RSBI, MMI))
+    validateRootSignature(M, *RSD, MMI);
 }
-} // namespace
 
 PreservedAnalyses
 DXILPostOptimizationValidation::run(Module &M, ModuleAnalysisManager &MAM) {
diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.h b/llvm/lib/Target/DirectX/DXILRootSignature.h
index 254b7ff504633..b990b6c7410ac 100644
--- a/llvm/lib/Target/DirectX/DXILRootSignature.h
+++ b/llvm/lib/Target/DirectX/DXILRootSignature.h
@@ -43,13 +43,11 @@ class RootSignatureBindingInfo {
 
   iterator end() { return FuncToRsMap.end(); }
 
-  std::optional<mcdxbc::RootSignatureDesc>
-  getDescForFunction(const Function *F) {
+  mcdxbc::RootSignatureDesc *getDescForFunction(const Function *F) {
     const auto FuncRs = find(F);
     if (FuncRs == end())
-      return std::nullopt;
-
-    return FuncRs->second;
+      return nullptr;
+    return &FuncRs->second;
   }
 };
 
diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-root-descriptor-range.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-root-descriptor-range.ll
index 9f70cc3f062a9..38674d9ba0c6d 100644
--- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-root-descriptor-range.ll
+++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-root-descriptor-range.ll
@@ -6,10 +6,9 @@ entry:
   ret void
 }
 
-; DescriptorTable(UAV(u0, numDescriptors=unbounded), visibility = SHADER_VISIBILITY_HULL), UAV(u3, space=1)
 !dx.rootsignatures = !{!0}
 !0 = !{ptr @CSMain, !1, i32 2}
 !1 = !{!2, !4}
 !2 = !{!"RootUAV", i32 0, i32 3, i32 1, i32 4}
 !4 = !{!"DescriptorTable", i32 0, !5}
-!5 = !{!"UAV", i32 3, i32 0, i32 1, i32 -1, i32 2}
+!5 = !{!"UAV", i32 4, i32 0, i32 1, i32 -1, i32 2}

>From 0f0435d6b43a0364c2a0dfc89bd94df57b6a6c99 Mon Sep 17 00:00:00 2001
From: Joao Saffran <jderezende at microsoft.com>
Date: Thu, 7 Aug 2025 15:16:14 -0700
Subject: [PATCH 07/11] clean up

---
 llvm/include/llvm/Analysis/DXILResource.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/llvm/include/llvm/Analysis/DXILResource.h b/llvm/include/llvm/Analysis/DXILResource.h
index 557fc513c2a57..93c6bfb057ef5 100644
--- a/llvm/include/llvm/Analysis/DXILResource.h
+++ b/llvm/include/llvm/Analysis/DXILResource.h
@@ -32,6 +32,7 @@ class Value;
 class DXILResourceTypeMap;
 
 namespace dxil {
+
 // Returns the resource name from dx_resource_handlefrombinding or
 // dx_resource_handlefromimplicitbinding call
 LLVM_ABI StringRef getResourceNameFromBindingCall(CallInst *CI);

>From e841a98b1cefbcd92c4f3f9ed050dc33f07b0299 Mon Sep 17 00:00:00 2001
From: Joao Saffran <jderezende at microsoft.com>
Date: Thu, 7 Aug 2025 15:18:21 -0700
Subject: [PATCH 08/11] clean up

---
 llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp | 2 --
 1 file changed, 2 deletions(-)

diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
index 368c8c6b5dbba..80cbc9b6bee57 100644
--- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
+++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
@@ -13,13 +13,11 @@
 #include "llvm/ADT/SmallString.h"
 #include "llvm/Analysis/DXILMetadataAnalysis.h"
 #include "llvm/Analysis/DXILResource.h"
-#include "llvm/BinaryFormat/DXContainer.h"
 #include "llvm/IR/DiagnosticInfo.h"
 #include "llvm/IR/Instructions.h"
 #include "llvm/IR/IntrinsicsDirectX.h"
 #include "llvm/IR/Module.h"
 #include "llvm/InitializePasses.h"
-#include <cstdint>
 
 #define DEBUG_TYPE "dxil-post-optimization-validation"
 

>From ae6d67a18553ab4d2608e46ccc0ca7c9edfba591 Mon Sep 17 00:00:00 2001
From: Joao Saffran <jderezende at microsoft.com>
Date: Thu, 7 Aug 2025 16:34:12 -0700
Subject: [PATCH 09/11] fix build

---
 llvm/lib/Analysis/DXILResource.cpp                         | 1 +
 llvm/lib/Support/CMakeLists.txt                            | 1 +
 llvm/lib/Support/DXILABI.cpp                               | 7 +++++--
 llvm/lib/Target/DirectX/DXContainerGlobals.cpp             | 3 +--
 llvm/lib/Target/DirectX/DXILOpLowering.cpp                 | 2 +-
 llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp | 1 +
 6 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/llvm/lib/Analysis/DXILResource.cpp b/llvm/lib/Analysis/DXILResource.cpp
index b476026fcc718..5aeee6f681114 100644
--- a/llvm/lib/Analysis/DXILResource.cpp
+++ b/llvm/lib/Analysis/DXILResource.cpp
@@ -20,6 +20,7 @@
 #include "llvm/IR/Metadata.h"
 #include "llvm/IR/Module.h"
 #include "llvm/InitializePasses.h"
+#include "llvm/Support/DXILABI.h"
 #include "llvm/Support/FormatVariadic.h"
 #include <cstdint>
 #include <optional>
diff --git a/llvm/lib/Support/CMakeLists.txt b/llvm/lib/Support/CMakeLists.txt
index 10b6101d73277..b7578dd580072 100644
--- a/llvm/lib/Support/CMakeLists.txt
+++ b/llvm/lib/Support/CMakeLists.txt
@@ -182,6 +182,7 @@ add_llvm_component_library(LLVMSupport
   DivisionByConstantInfo.cpp
   DAGDeltaAlgorithm.cpp
   DJB.cpp
+  DXILABI.cpp
   DynamicAPInt.cpp
   ELFAttributes.cpp
   ELFAttrParserCompact.cpp
diff --git a/llvm/lib/Support/DXILABI.cpp b/llvm/lib/Support/DXILABI.cpp
index 510e15b403ab1..e45e86922cb39 100644
--- a/llvm/lib/Support/DXILABI.cpp
+++ b/llvm/lib/Support/DXILABI.cpp
@@ -3,7 +3,8 @@
 #include "llvm/Support/ErrorHandling.h"
 
 using namespace llvm;
-
+namespace llvm {
+namespace dxil {
 StringRef getResourceClassName(dxil::ResourceClass RC) {
   switch (RC) {
   case dxil::ResourceClass::SRV:
@@ -16,4 +17,6 @@ StringRef getResourceClassName(dxil::ResourceClass RC) {
     return "Sampler";
   }
   llvm_unreachable("Unhandled ResourceClass");
-}
\ No newline at end of file
+}
+} // namespace dxil
+} // namespace llvm
\ No newline at end of file
diff --git a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp
index 26a113d2d5260..a1ef2578f00aa 100644
--- a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp
+++ b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp
@@ -162,8 +162,7 @@ void DXContainerGlobals::addRootSignature(Module &M,
 
   auto &RSA = getAnalysis<RootSignatureAnalysisWrapper>().getRSInfo();
   const Function *EntryFunction = MMI.EntryPropertyVec[0].Entry;
-  const std::optional<mcdxbc::RootSignatureDesc> &RS =
-      RSA.getDescForFunction(EntryFunction);
+  const mcdxbc::RootSignatureDesc *RS = RSA.getDescForFunction(EntryFunction);
 
   if (!RS)
     return;
diff --git a/llvm/lib/Target/DirectX/DXILOpLowering.cpp b/llvm/lib/Target/DirectX/DXILOpLowering.cpp
index 1cfba523183c8..247ba7d93b3c2 100644
--- a/llvm/lib/Target/DirectX/DXILOpLowering.cpp
+++ b/llvm/lib/Target/DirectX/DXILOpLowering.cpp
@@ -919,7 +919,7 @@ PreservedAnalyses DXILOpLowering::run(Module &M, ModuleAnalysisManager &MAM) {
   PA.preserve<DXILResourceAnalysis>();
   PA.preserve<DXILMetadataAnalysis>();
   PA.preserve<ShaderFlagsAnalysis>();
-  PA.preserve<RootSignatureAnalysisWrapper>();
+  PA.preserve<RootSignatureAnalysis>();
   return PA;
 }
 
diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
index 80cbc9b6bee57..cbb4307949f86 100644
--- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
+++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
@@ -18,6 +18,7 @@
 #include "llvm/IR/IntrinsicsDirectX.h"
 #include "llvm/IR/Module.h"
 #include "llvm/InitializePasses.h"
+#include "llvm/Support/DXILABI.h"
 
 #define DEBUG_TYPE "dxil-post-optimization-validation"
 

>From 41f32bd5ded0e14cfef0f2dd3ec8f5b9594d0f72 Mon Sep 17 00:00:00 2001
From: Joao Saffran <jderezende at microsoft.com>
Date: Fri, 8 Aug 2025 10:44:24 -0700
Subject: [PATCH 10/11] fix tests

---
 .../DirectX/DXILPostOptimizationValidation.cpp      | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
index cbb4307949f86..7dc1ac0a5c0f2 100644
--- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
+++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
@@ -158,7 +158,7 @@ static void validateRootSignature(Module &M,
 
   hlsl::BindingInfoBuilder Builder;
   dxbc::ShaderVisibility Visibility = tripleToVisibility(MMI.ShaderProfile);
-
+  SmallVector<char> IDs;
   for (const mcdxbc::RootParameterInfo &ParamInfo : RSD.ParametersContainer) {
     dxbc::ShaderVisibility ParamVisibility =
         static_cast<dxbc::ShaderVisibility>(ParamInfo.Header.ShaderVisibility);
@@ -172,7 +172,8 @@ static void validateRootSignature(Module &M,
       dxbc::RTS0::v1::RootConstants Const =
           RSD.ParametersContainer.getConstant(ParamInfo.Location);
       Builder.trackBinding(dxil::ResourceClass::CBuffer, Const.RegisterSpace,
-                           Const.ShaderRegister, Const.ShaderRegister, nullptr);
+                           Const.ShaderRegister, Const.ShaderRegister,
+                           &IDs.emplace_back());
       break;
     }
 
@@ -184,7 +185,7 @@ static void validateRootSignature(Module &M,
       Builder.trackBinding(toResourceClass(static_cast<dxbc::RootParameterType>(
                                ParamInfo.Header.ParameterType)),
                            Desc.RegisterSpace, Desc.ShaderRegister,
-                           Desc.ShaderRegister, nullptr);
+                           Desc.ShaderRegister, &IDs.emplace_back());
 
       break;
     }
@@ -200,7 +201,8 @@ static void validateRootSignature(Module &M,
         Builder.trackBinding(
             toResourceClass(
                 static_cast<dxbc::DescriptorRangeType>(Range.RangeType)),
-            Range.RegisterSpace, Range.BaseShaderRegister, UpperBound, nullptr);
+            Range.RegisterSpace, Range.BaseShaderRegister, UpperBound,
+            &IDs.emplace_back());
       }
       break;
     }
@@ -209,7 +211,8 @@ static void validateRootSignature(Module &M,
 
   for (const dxbc::RTS0::v1::StaticSampler &S : RSD.StaticSamplers)
     Builder.trackBinding(dxil::ResourceClass::Sampler, S.RegisterSpace,
-                         S.ShaderRegister, S.ShaderRegister, nullptr);
+                         S.ShaderRegister, S.ShaderRegister,
+                         &IDs.emplace_back());
 
   hlsl::BindingInfo Info = Builder.calculateBindingInfo(
       [&M](const llvm::hlsl::BindingInfoBuilder &Builder,

>From db73d716287c775686245455884327d734749ec2 Mon Sep 17 00:00:00 2001
From: Joao Saffran <{ID}+{username}@users.noreply.github.com>
Date: Fri, 8 Aug 2025 13:04:21 -0700
Subject: [PATCH 11/11] update

---
 llvm/lib/Support/DXILABI.cpp                       | 14 +++-----------
 .../rootsignature-validation-fail-cbuffer-range.ll |  2 +-
 2 files changed, 4 insertions(+), 12 deletions(-)

diff --git a/llvm/lib/Support/DXILABI.cpp b/llvm/lib/Support/DXILABI.cpp
index e45e86922cb39..3596a766b4388 100644
--- a/llvm/lib/Support/DXILABI.cpp
+++ b/llvm/lib/Support/DXILABI.cpp
@@ -1,22 +1,14 @@
 
 #include "llvm/Support/DXILABI.h"
+#include "llvm/BinaryFormat/DXContainer.h"
 #include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/ScopedPrinter.h"
 
 using namespace llvm;
 namespace llvm {
 namespace dxil {
 StringRef getResourceClassName(dxil::ResourceClass RC) {
-  switch (RC) {
-  case dxil::ResourceClass::SRV:
-    return "SRV";
-  case dxil::ResourceClass::UAV:
-    return "UAV";
-  case dxil::ResourceClass::CBuffer:
-    return "CBuffer";
-  case dxil::ResourceClass::Sampler:
-    return "Sampler";
-  }
-  llvm_unreachable("Unhandled ResourceClass");
+  return enumToStringRef(RC, dxbc::getResourceClasses());
 }
 } // namespace dxil
 } // namespace llvm
\ No newline at end of file
diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbuffer-range.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbuffer-range.ll
index 47d2a5b8d5aab..2f206702394a1 100644
--- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbuffer-range.ll
+++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbuffer-range.ll
@@ -1,5 +1,5 @@
 ; RUN: not opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 | FileCheck %s
-; CHECK: error: register CBuffer (space=0, register=2) is overlapping with register CBuffer (space=0, register=0), verify your root signature definition.
+; CHECK: error: register CBV (space=0, register=2) is overlapping with register CBV (space=0, register=0), verify your root signature definition.
 
 define void @CSMain() "hlsl.shader"="compute" {
 entry:



More information about the llvm-commits mailing list