[clang] [llvm] [DirectX] Validate registers are bound to root signature (PR #146785)

via llvm-commits llvm-commits at lists.llvm.org
Tue Jul 15 11:18:16 PDT 2025


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

>From 0e8828c291d6e7e35ed3c0bce0504d8f731f9667 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/29] refactoring

---
 .../lib/Target/DirectX/DXContainerGlobals.cpp |  2 +-
 llvm/lib/Target/DirectX/DXILRootSignature.cpp | 12 ++---
 llvm/lib/Target/DirectX/DXILRootSignature.h   | 45 ++++++++++++++-----
 3 files changed, 41 insertions(+), 18 deletions(-)

diff --git a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp
index 9c38901f6821f..83f787da66403 100644
--- a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp
+++ b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp
@@ -160,7 +160,7 @@ void DXContainerGlobals::addRootSignature(Module &M,
 
   assert(MMI.EntryPropertyVec.size() == 1);
 
-  auto &RSA = getAnalysis<RootSignatureAnalysisWrapper>();
+  auto &RSA = getAnalysis<RootSignatureAnalysisWrapper>().getRSInfo();
   const Function *EntryFunction = MMI.EntryPropertyVec[0].Entry;
   const auto &FuncRs = RSA.find(EntryFunction);
 
diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.cpp b/llvm/lib/Target/DirectX/DXILRootSignature.cpp
index 29e78fcce5262..4094df160ef6f 100644
--- a/llvm/lib/Target/DirectX/DXILRootSignature.cpp
+++ b/llvm/lib/Target/DirectX/DXILRootSignature.cpp
@@ -554,9 +554,9 @@ analyzeModule(Module &M) {
 
 AnalysisKey RootSignatureAnalysis::Key;
 
-SmallDenseMap<const Function *, mcdxbc::RootSignatureDesc>
-RootSignatureAnalysis::run(Module &M, ModuleAnalysisManager &AM) {
-  return analyzeModule(M);
+RootSignatureBindingInfo RootSignatureAnalysis::run(Module &M,
+                                                    ModuleAnalysisManager &AM) {
+  return RootSignatureBindingInfo(analyzeModule(M));
 }
 
 //===----------------------------------------------------------------------===//
@@ -564,8 +564,7 @@ RootSignatureAnalysis::run(Module &M, ModuleAnalysisManager &AM) {
 PreservedAnalyses RootSignatureAnalysisPrinter::run(Module &M,
                                                     ModuleAnalysisManager &AM) {
 
-  SmallDenseMap<const Function *, mcdxbc::RootSignatureDesc> &RSDMap =
-      AM.getResult<RootSignatureAnalysis>(M);
+  RootSignatureBindingInfo &RSDMap = AM.getResult<RootSignatureAnalysis>(M);
 
   OS << "Root Signature Definitions"
      << "\n";
@@ -636,7 +635,8 @@ PreservedAnalyses RootSignatureAnalysisPrinter::run(Module &M,
 
 //===----------------------------------------------------------------------===//
 bool RootSignatureAnalysisWrapper::runOnModule(Module &M) {
-  FuncToRsMap = analyzeModule(M);
+  FuncToRsMap = std::make_unique<RootSignatureBindingInfo>(
+      RootSignatureBindingInfo(analyzeModule(M)));
   return false;
 }
 
diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.h b/llvm/lib/Target/DirectX/DXILRootSignature.h
index b45cebc15fd39..fef933811f840 100644
--- a/llvm/lib/Target/DirectX/DXILRootSignature.h
+++ b/llvm/lib/Target/DirectX/DXILRootSignature.h
@@ -33,16 +33,43 @@ enum class RootSignatureElementKind {
   CBV = 5,
   DescriptorTable = 6,
 };
+
+class RootSignatureBindingInfo {
+  private:
+    SmallDenseMap<const Function *, mcdxbc::RootSignatureDesc> FuncToRsMap;
+
+  public:
+  using iterator =
+        SmallDenseMap<const Function *, mcdxbc::RootSignatureDesc>::iterator;
+
+  RootSignatureBindingInfo () = default;
+  RootSignatureBindingInfo(SmallDenseMap<const Function *, mcdxbc::RootSignatureDesc> Map) : FuncToRsMap(Map) {};
+
+  iterator find(const Function *F) { return FuncToRsMap.find(F); }
+
+  iterator end() { return FuncToRsMap.end(); }
+
+  std::optional<mcdxbc::RootSignatureDesc> getDescForFunction(const Function* F) {
+    const auto FuncRs = find(F);
+    if (FuncRs == end())
+      return std::nullopt;
+
+    return FuncRs->second;
+  }
+  
+};
+
 class RootSignatureAnalysis : public AnalysisInfoMixin<RootSignatureAnalysis> {
   friend AnalysisInfoMixin<RootSignatureAnalysis>;
   static AnalysisKey Key;
 
 public:
-  RootSignatureAnalysis() = default;
 
-  using Result = SmallDenseMap<const Function *, mcdxbc::RootSignatureDesc>;
+RootSignatureAnalysis() = default;
 
-  SmallDenseMap<const Function *, mcdxbc::RootSignatureDesc>
+  using Result = RootSignatureBindingInfo;
+  
+  RootSignatureBindingInfo
   run(Module &M, ModuleAnalysisManager &AM);
 };
 
@@ -52,20 +79,16 @@ class RootSignatureAnalysis : public AnalysisInfoMixin<RootSignatureAnalysis> {
 /// passes which run through the legacy pass manager.
 class RootSignatureAnalysisWrapper : public ModulePass {
 private:
-  SmallDenseMap<const Function *, mcdxbc::RootSignatureDesc> FuncToRsMap;
+  std::unique_ptr<RootSignatureBindingInfo> FuncToRsMap;
 
 public:
   static char ID;
+  using Result = RootSignatureBindingInfo;
 
   RootSignatureAnalysisWrapper() : ModulePass(ID) {}
 
-  using iterator =
-      SmallDenseMap<const Function *, mcdxbc::RootSignatureDesc>::iterator;
-
-  iterator find(const Function *F) { return FuncToRsMap.find(F); }
-
-  iterator end() { return FuncToRsMap.end(); }
-
+  RootSignatureBindingInfo& getRSInfo() {return *FuncToRsMap;}
+  
   bool runOnModule(Module &M) override;
 
   void getAnalysisUsage(AnalysisUsage &AU) const override;

>From 2edd215e118e9dc947b1a6d2bc52bb8b6c78e3b2 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 02/29] refactoring

---
 llvm/lib/Target/DirectX/DXContainerGlobals.cpp |  7 +++----
 llvm/lib/Target/DirectX/DXILRootSignature.cpp  | 12 +++++++++---
 llvm/lib/Target/DirectX/DXILRootSignature.h    | 10 +++++++---
 3 files changed, 19 insertions(+), 10 deletions(-)

diff --git a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp
index 83f787da66403..6c8ae8eaaea77 100644
--- a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp
+++ b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp
@@ -162,16 +162,15 @@ void DXContainerGlobals::addRootSignature(Module &M,
 
   auto &RSA = getAnalysis<RootSignatureAnalysisWrapper>().getRSInfo();
   const Function *EntryFunction = MMI.EntryPropertyVec[0].Entry;
-  const auto &FuncRs = RSA.find(EntryFunction);
+  const auto &RS = RSA.getDescForFunction(EntryFunction);
 
-  if (FuncRs == RSA.end())
+  if (!RS)
     return;
 
-  const RootSignatureDesc &RS = FuncRs->second;
   SmallString<256> Data;
   raw_svector_ostream OS(Data);
 
-  RS.write(OS);
+  RS->write(OS);
 
   Constant *Constant =
       ConstantDataArray::getString(M.getContext(), Data, /*AddNull*/ false);
diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.cpp b/llvm/lib/Target/DirectX/DXILRootSignature.cpp
index 4094df160ef6f..12b0f0b74837a 100644
--- a/llvm/lib/Target/DirectX/DXILRootSignature.cpp
+++ b/llvm/lib/Target/DirectX/DXILRootSignature.cpp
@@ -28,6 +28,7 @@
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/raw_ostream.h"
 #include <cstdint>
+#include <memory>
 #include <optional>
 #include <utility>
 
@@ -554,9 +555,12 @@ analyzeModule(Module &M) {
 
 AnalysisKey RootSignatureAnalysis::Key;
 
-RootSignatureBindingInfo RootSignatureAnalysis::run(Module &M,
-                                                    ModuleAnalysisManager &AM) {
-  return RootSignatureBindingInfo(analyzeModule(M));
+RootSignatureAnalysis::Result
+RootSignatureAnalysis::run(Module &M, ModuleAnalysisManager &AM) {
+  if (!AnalysisResult)
+    AnalysisResult = std::make_unique<RootSignatureBindingInfo>(
+        RootSignatureBindingInfo(analyzeModule(M)));
+  return *AnalysisResult;
 }
 
 //===----------------------------------------------------------------------===//
@@ -635,6 +639,8 @@ PreservedAnalyses RootSignatureAnalysisPrinter::run(Module &M,
 
 //===----------------------------------------------------------------------===//
 bool RootSignatureAnalysisWrapper::runOnModule(Module &M) {
+  if (HasRun)
+    return false;
   FuncToRsMap = std::make_unique<RootSignatureBindingInfo>(
       RootSignatureBindingInfo(analyzeModule(M)));
   return false;
diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.h b/llvm/lib/Target/DirectX/DXILRootSignature.h
index fef933811f840..c143d45a13d88 100644
--- a/llvm/lib/Target/DirectX/DXILRootSignature.h
+++ b/llvm/lib/Target/DirectX/DXILRootSignature.h
@@ -19,6 +19,7 @@
 #include "llvm/IR/PassManager.h"
 #include "llvm/MC/DXContainerRootSignature.h"
 #include "llvm/Pass.h"
+#include <memory>
 #include <optional>
 
 namespace llvm {
@@ -68,9 +69,11 @@ class RootSignatureAnalysis : public AnalysisInfoMixin<RootSignatureAnalysis> {
 RootSignatureAnalysis() = default;
 
   using Result = RootSignatureBindingInfo;
-  
-  RootSignatureBindingInfo
-  run(Module &M, ModuleAnalysisManager &AM);
+
+  Result run(Module &M, ModuleAnalysisManager &AM);
+
+private:
+  std::unique_ptr<RootSignatureBindingInfo> AnalysisResult;
 };
 
 /// Wrapper pass for the legacy pass manager.
@@ -80,6 +83,7 @@ RootSignatureAnalysis() = default;
 class RootSignatureAnalysisWrapper : public ModulePass {
 private:
   std::unique_ptr<RootSignatureBindingInfo> FuncToRsMap;
+  bool HasRun = false;
 
 public:
   static char ID;

>From 242545e5f40ccbf698e7f6935d8d9efa86cf5cb4 Mon Sep 17 00:00:00 2001
From: joaosaffran <joao.saffran at microsoft.com>
Date: Wed, 2 Jul 2025 21:10:21 +0000
Subject: [PATCH 03/29] clean up

---
 llvm/lib/Target/DirectX/DXILRootSignature.cpp | 8 +++-----
 llvm/lib/Target/DirectX/DXILRootSignature.h   | 2 --
 2 files changed, 3 insertions(+), 7 deletions(-)

diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.cpp b/llvm/lib/Target/DirectX/DXILRootSignature.cpp
index 12b0f0b74837a..5a53ea8a3631b 100644
--- a/llvm/lib/Target/DirectX/DXILRootSignature.cpp
+++ b/llvm/lib/Target/DirectX/DXILRootSignature.cpp
@@ -28,7 +28,6 @@
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/raw_ostream.h"
 #include <cstdint>
-#include <memory>
 #include <optional>
 #include <utility>
 
@@ -639,10 +638,9 @@ PreservedAnalyses RootSignatureAnalysisPrinter::run(Module &M,
 
 //===----------------------------------------------------------------------===//
 bool RootSignatureAnalysisWrapper::runOnModule(Module &M) {
-  if (HasRun)
-    return false;
-  FuncToRsMap = std::make_unique<RootSignatureBindingInfo>(
-      RootSignatureBindingInfo(analyzeModule(M)));
+  if (!FuncToRsMap)
+    FuncToRsMap = std::make_unique<RootSignatureBindingInfo>(
+        RootSignatureBindingInfo(analyzeModule(M)));
   return false;
 }
 
diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.h b/llvm/lib/Target/DirectX/DXILRootSignature.h
index c143d45a13d88..8a057404e01c1 100644
--- a/llvm/lib/Target/DirectX/DXILRootSignature.h
+++ b/llvm/lib/Target/DirectX/DXILRootSignature.h
@@ -19,7 +19,6 @@
 #include "llvm/IR/PassManager.h"
 #include "llvm/MC/DXContainerRootSignature.h"
 #include "llvm/Pass.h"
-#include <memory>
 #include <optional>
 
 namespace llvm {
@@ -83,7 +82,6 @@ RootSignatureAnalysis() = default;
 class RootSignatureAnalysisWrapper : public ModulePass {
 private:
   std::unique_ptr<RootSignatureBindingInfo> FuncToRsMap;
-  bool HasRun = false;
 
 public:
   static char ID;

>From 3f8dec410b55a610f41cec9d7b38c15c52f82837 Mon Sep 17 00:00:00 2001
From: joaosaffran <joao.saffran at microsoft.com>
Date: Wed, 2 Jul 2025 21:22:55 +0000
Subject: [PATCH 04/29] format

---
 llvm/lib/Target/DirectX/DXILRootSignature.h | 25 +++++++++++----------
 1 file changed, 13 insertions(+), 12 deletions(-)

diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.h b/llvm/lib/Target/DirectX/DXILRootSignature.h
index 8a057404e01c1..60ae7c0a6b2b1 100644
--- a/llvm/lib/Target/DirectX/DXILRootSignature.h
+++ b/llvm/lib/Target/DirectX/DXILRootSignature.h
@@ -35,28 +35,30 @@ enum class RootSignatureElementKind {
 };
 
 class RootSignatureBindingInfo {
-  private:
-    SmallDenseMap<const Function *, mcdxbc::RootSignatureDesc> FuncToRsMap;
+private:
+  SmallDenseMap<const Function *, mcdxbc::RootSignatureDesc> FuncToRsMap;
 
-  public:
+public:
   using iterator =
-        SmallDenseMap<const Function *, mcdxbc::RootSignatureDesc>::iterator;
+      SmallDenseMap<const Function *, mcdxbc::RootSignatureDesc>::iterator;
 
-  RootSignatureBindingInfo () = default;
-  RootSignatureBindingInfo(SmallDenseMap<const Function *, mcdxbc::RootSignatureDesc> Map) : FuncToRsMap(Map) {};
+  RootSignatureBindingInfo() = default;
+  RootSignatureBindingInfo(
+      SmallDenseMap<const Function *, mcdxbc::RootSignatureDesc> Map)
+      : FuncToRsMap(Map){};
 
   iterator find(const Function *F) { return FuncToRsMap.find(F); }
 
   iterator end() { return FuncToRsMap.end(); }
 
-  std::optional<mcdxbc::RootSignatureDesc> getDescForFunction(const Function* F) {
+  std::optional<mcdxbc::RootSignatureDesc>
+  getDescForFunction(const Function *F) {
     const auto FuncRs = find(F);
     if (FuncRs == end())
       return std::nullopt;
 
     return FuncRs->second;
   }
-  
 };
 
 class RootSignatureAnalysis : public AnalysisInfoMixin<RootSignatureAnalysis> {
@@ -64,8 +66,7 @@ class RootSignatureAnalysis : public AnalysisInfoMixin<RootSignatureAnalysis> {
   static AnalysisKey Key;
 
 public:
-
-RootSignatureAnalysis() = default;
+  RootSignatureAnalysis() = default;
 
   using Result = RootSignatureBindingInfo;
 
@@ -89,8 +90,8 @@ class RootSignatureAnalysisWrapper : public ModulePass {
 
   RootSignatureAnalysisWrapper() : ModulePass(ID) {}
 
-  RootSignatureBindingInfo& getRSInfo() {return *FuncToRsMap;}
-  
+  RootSignatureBindingInfo &getRSInfo() { return *FuncToRsMap; }
+
   bool runOnModule(Module &M) override;
 
   void getAnalysisUsage(AnalysisUsage &AU) const override;

>From 3b1ce3bee8112f55b22ed55c2881bd128793b3e2 Mon Sep 17 00:00:00 2001
From: joaosaffran <joao.saffran at microsoft.com>
Date: Wed, 2 Jul 2025 21:49:19 +0000
Subject: [PATCH 05/29] formating

---
 llvm/lib/Target/DirectX/DXILRootSignature.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.h b/llvm/lib/Target/DirectX/DXILRootSignature.h
index 60ae7c0a6b2b1..41c2251c5f1e2 100644
--- a/llvm/lib/Target/DirectX/DXILRootSignature.h
+++ b/llvm/lib/Target/DirectX/DXILRootSignature.h
@@ -45,7 +45,7 @@ class RootSignatureBindingInfo {
   RootSignatureBindingInfo() = default;
   RootSignatureBindingInfo(
       SmallDenseMap<const Function *, mcdxbc::RootSignatureDesc> Map)
-      : FuncToRsMap(Map){};
+      : FuncToRsMap(Map) {};
 
   iterator find(const Function *F) { return FuncToRsMap.find(F); }
 

>From f5720afd4c34075e17c2220dd92d0f10a60bbb43 Mon Sep 17 00:00:00 2001
From: joaosaffran <joao.saffran at microsoft.com>
Date: Fri, 4 Jul 2025 02:10:03 +0000
Subject: [PATCH 06/29] fix import issues

---
 llvm/lib/Target/DirectX/DXILRootSignature.h | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.h b/llvm/lib/Target/DirectX/DXILRootSignature.h
index 41c2251c5f1e2..e02f47ff60ae8 100644
--- a/llvm/lib/Target/DirectX/DXILRootSignature.h
+++ b/llvm/lib/Target/DirectX/DXILRootSignature.h
@@ -10,6 +10,8 @@
 ///       Root Signatures.
 ///
 //===----------------------------------------------------------------------===//
+#ifndef LLVM_LIB_TARGET_DIRECTX_DXILROOTSIGNATURE_H
+#define LLVM_LIB_TARGET_DIRECTX_DXILROOTSIGNATURE_H
 
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/Analysis/DXILMetadataAnalysis.h"
@@ -45,7 +47,7 @@ class RootSignatureBindingInfo {
   RootSignatureBindingInfo() = default;
   RootSignatureBindingInfo(
       SmallDenseMap<const Function *, mcdxbc::RootSignatureDesc> Map)
-      : FuncToRsMap(Map) {};
+      : FuncToRsMap(Map){};
 
   iterator find(const Function *F) { return FuncToRsMap.find(F); }
 
@@ -109,3 +111,4 @@ class RootSignatureAnalysisPrinter
 
 } // namespace dxil
 } // namespace llvm
+#endif

>From ea54904cdc29c624cd40ecff7f4ce5fe0af17af6 Mon Sep 17 00:00:00 2001
From: joaosaffran <joao.saffran at microsoft.com>
Date: Fri, 4 Jul 2025 19:28:15 +0000
Subject: [PATCH 07/29] formating

---
 llvm/lib/Target/DirectX/DXILRootSignature.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.h b/llvm/lib/Target/DirectX/DXILRootSignature.h
index e02f47ff60ae8..3832182277050 100644
--- a/llvm/lib/Target/DirectX/DXILRootSignature.h
+++ b/llvm/lib/Target/DirectX/DXILRootSignature.h
@@ -47,7 +47,7 @@ class RootSignatureBindingInfo {
   RootSignatureBindingInfo() = default;
   RootSignatureBindingInfo(
       SmallDenseMap<const Function *, mcdxbc::RootSignatureDesc> Map)
-      : FuncToRsMap(Map){};
+      : FuncToRsMap(Map) {};
 
   iterator find(const Function *F) { return FuncToRsMap.find(F); }
 

>From a49aa19297811e5800ffce364d8d6a225109d93f 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 08/29] refactoring

---
 .../lib/Target/DirectX/DXContainerGlobals.cpp |  4 ++-
 llvm/lib/Target/DirectX/DXILRootSignature.cpp | 14 +++-----
 llvm/lib/Target/DirectX/DXILRootSignature.h   | 33 +++++++++----------
 3 files changed, 23 insertions(+), 28 deletions(-)

diff --git a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp
index 6c8ae8eaaea77..e076283b65193 100644
--- a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp
+++ b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp
@@ -160,11 +160,13 @@ void DXContainerGlobals::addRootSignature(Module &M,
 
   assert(MMI.EntryPropertyVec.size() == 1);
 
+  auto &RSA = getAnalysis<RootSignatureAnalysisWrapper>().getRSInfo();
   auto &RSA = getAnalysis<RootSignatureAnalysisWrapper>().getRSInfo();
   const Function *EntryFunction = MMI.EntryPropertyVec[0].Entry;
   const auto &RS = RSA.getDescForFunction(EntryFunction);
+  const auto &RS = RSA.getDescForFunction(EntryFunction);
 
-  if (!RS)
+  if (!RS )
     return;
 
   SmallString<256> Data;
diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.cpp b/llvm/lib/Target/DirectX/DXILRootSignature.cpp
index 5a53ea8a3631b..4094df160ef6f 100644
--- a/llvm/lib/Target/DirectX/DXILRootSignature.cpp
+++ b/llvm/lib/Target/DirectX/DXILRootSignature.cpp
@@ -554,12 +554,9 @@ analyzeModule(Module &M) {
 
 AnalysisKey RootSignatureAnalysis::Key;
 
-RootSignatureAnalysis::Result
-RootSignatureAnalysis::run(Module &M, ModuleAnalysisManager &AM) {
-  if (!AnalysisResult)
-    AnalysisResult = std::make_unique<RootSignatureBindingInfo>(
-        RootSignatureBindingInfo(analyzeModule(M)));
-  return *AnalysisResult;
+RootSignatureBindingInfo RootSignatureAnalysis::run(Module &M,
+                                                    ModuleAnalysisManager &AM) {
+  return RootSignatureBindingInfo(analyzeModule(M));
 }
 
 //===----------------------------------------------------------------------===//
@@ -638,9 +635,8 @@ PreservedAnalyses RootSignatureAnalysisPrinter::run(Module &M,
 
 //===----------------------------------------------------------------------===//
 bool RootSignatureAnalysisWrapper::runOnModule(Module &M) {
-  if (!FuncToRsMap)
-    FuncToRsMap = std::make_unique<RootSignatureBindingInfo>(
-        RootSignatureBindingInfo(analyzeModule(M)));
+  FuncToRsMap = std::make_unique<RootSignatureBindingInfo>(
+      RootSignatureBindingInfo(analyzeModule(M)));
   return false;
 }
 
diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.h b/llvm/lib/Target/DirectX/DXILRootSignature.h
index 3832182277050..24b1a8d3d2abe 100644
--- a/llvm/lib/Target/DirectX/DXILRootSignature.h
+++ b/llvm/lib/Target/DirectX/DXILRootSignature.h
@@ -37,30 +37,28 @@ enum class RootSignatureElementKind {
 };
 
 class RootSignatureBindingInfo {
-private:
-  SmallDenseMap<const Function *, mcdxbc::RootSignatureDesc> FuncToRsMap;
+  private:
+    SmallDenseMap<const Function *, mcdxbc::RootSignatureDesc> FuncToRsMap;
 
-public:
+  public:
   using iterator =
-      SmallDenseMap<const Function *, mcdxbc::RootSignatureDesc>::iterator;
+        SmallDenseMap<const Function *, mcdxbc::RootSignatureDesc>::iterator;
 
-  RootSignatureBindingInfo() = default;
-  RootSignatureBindingInfo(
-      SmallDenseMap<const Function *, mcdxbc::RootSignatureDesc> Map)
-      : FuncToRsMap(Map) {};
+  RootSignatureBindingInfo () = default;
+  RootSignatureBindingInfo(SmallDenseMap<const Function *, mcdxbc::RootSignatureDesc> Map) : FuncToRsMap(Map) {};
 
   iterator find(const Function *F) { return FuncToRsMap.find(F); }
 
   iterator end() { return FuncToRsMap.end(); }
 
-  std::optional<mcdxbc::RootSignatureDesc>
-  getDescForFunction(const Function *F) {
+  std::optional<mcdxbc::RootSignatureDesc> getDescForFunction(const Function* F) {
     const auto FuncRs = find(F);
     if (FuncRs == end())
       return std::nullopt;
 
     return FuncRs->second;
   }
+  
 };
 
 class RootSignatureAnalysis : public AnalysisInfoMixin<RootSignatureAnalysis> {
@@ -68,14 +66,13 @@ class RootSignatureAnalysis : public AnalysisInfoMixin<RootSignatureAnalysis> {
   static AnalysisKey Key;
 
 public:
-  RootSignatureAnalysis() = default;
-
-  using Result = RootSignatureBindingInfo;
 
-  Result run(Module &M, ModuleAnalysisManager &AM);
+RootSignatureAnalysis() = default;
 
-private:
-  std::unique_ptr<RootSignatureBindingInfo> AnalysisResult;
+  using Result = RootSignatureBindingInfo;
+  
+  RootSignatureBindingInfo
+  run(Module &M, ModuleAnalysisManager &AM);
 };
 
 /// Wrapper pass for the legacy pass manager.
@@ -92,8 +89,8 @@ class RootSignatureAnalysisWrapper : public ModulePass {
 
   RootSignatureAnalysisWrapper() : ModulePass(ID) {}
 
-  RootSignatureBindingInfo &getRSInfo() { return *FuncToRsMap; }
-
+  RootSignatureBindingInfo& getRSInfo() {return *FuncToRsMap;}
+  
   bool runOnModule(Module &M) override;
 
   void getAnalysisUsage(AnalysisUsage &AU) const override;

>From d90676feb6bfc0ca8bbdaee5c347ecc49e396b5b Mon Sep 17 00:00:00 2001
From: joaosaffran <joao.saffran at microsoft.com>
Date: Thu, 26 Jun 2025 21:37:11 +0000
Subject: [PATCH 09/29] init refactoring

---
 .../SemaHLSL/RootSignature-Validation.hlsl    | 42 +++++++++++++++++
 .../lib/Target/DirectX/DXContainerGlobals.cpp |  2 +-
 .../DXILPostOptimizationValidation.cpp        | 47 +++++++++++++++++--
 llvm/lib/Target/DirectX/DXILRootSignature.h   | 30 ++++++------
 4 files changed, 102 insertions(+), 19 deletions(-)
 create mode 100644 clang/test/SemaHLSL/RootSignature-Validation.hlsl

diff --git a/clang/test/SemaHLSL/RootSignature-Validation.hlsl b/clang/test/SemaHLSL/RootSignature-Validation.hlsl
new file mode 100644
index 0000000000000..8a4a97f87cb65
--- /dev/null
+++ b/clang/test/SemaHLSL/RootSignature-Validation.hlsl
@@ -0,0 +1,42 @@
+// RUN: %clang_dxc -triple dxil-pc-shadermodel6.3-library -x hlsl -o - %s -verify
+
+#define ROOT_SIGNATURE \
+    "RootFlags(ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT), " \
+    "CBV(b0, visibility=SHADER_VISIBILITY_ALL), " \
+    "DescriptorTable(SRV(t0, numDescriptors=3), visibility=SHADER_VISIBILITY_PIXEL), " \
+    "DescriptorTable(Sampler(s0, numDescriptors=2), visibility=SHADER_VISIBILITY_PIXEL), " \
+    "DescriptorTable(UAV(u0, numDescriptors=1), visibility=SHADER_VISIBILITY_ALL)"
+
+cbuffer CB : register(b3, space2) {
+  float a;
+}
+
+StructuredBuffer<int> In : register(t0);
+RWStructuredBuffer<int> Out : register(u0);
+
+RWBuffer<float> UAV : register(u3);
+
+RWBuffer<float> UAV1 : register(u2), UAV2 : register(u4);
+
+RWBuffer<float> UAV3 : register(space5);
+
+float f : register(c5);
+
+int4 intv : register(c2);
+
+double dar[5] :  register(c3);
+
+struct S {
+  int a;
+};
+
+S s : register(c10);
+
+// Compute Shader for UAV testing
+[numthreads(8, 8, 1)]
+[RootSignature(ROOT_SIGNATURE)]
+void CSMain(uint3 id : SV_DispatchThreadID)
+{
+    In[0] = id;
+    Out[0] = In[0];
+}
diff --git a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp
index e076283b65193..5c763c24a210a 100644
--- a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp
+++ b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp
@@ -166,7 +166,7 @@ void DXContainerGlobals::addRootSignature(Module &M,
   const auto &RS = RSA.getDescForFunction(EntryFunction);
   const auto &RS = RSA.getDescForFunction(EntryFunction);
 
-  if (!RS )
+  if (!RS)
     return;
 
   SmallString<256> Data;
diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
index 398dcbb8d1737..daf53fefe5f17 100644
--- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
+++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
@@ -7,11 +7,14 @@
 //===----------------------------------------------------------------------===//
 
 #include "DXILPostOptimizationValidation.h"
+#include "DXILRootSignature.h"
 #include "DXILShaderFlags.h"
 #include "DirectX.h"
+#include "llvm/ADT/STLForwardCompat.h"
 #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"
@@ -85,7 +88,9 @@ static void reportOverlappingBinding(Module &M, DXILResourceMap &DRM) {
 }
 
 static void reportErrors(Module &M, DXILResourceMap &DRM,
-                         DXILResourceBindingInfo &DRBI) {
+                         DXILResourceBindingInfo &DRBI,
+                         RootSignatureBindingInfo &RSBI,
+                         dxil::ModuleMetadataInfo &MMI) {
   if (DRM.hasInvalidCounterDirection())
     reportInvalidDirection(M, DRM);
 
@@ -94,6 +99,30 @@ static void reportErrors(Module &M, DXILResourceMap &DRM,
 
   assert(!DRBI.hasImplicitBinding() && "implicit bindings should be handled in "
                                        "DXILResourceImplicitBinding pass");
+  // Assuming this is used to validate only the root signature assigned to the
+  // entry function.
+  std::optional<mcdxbc::RootSignatureDesc> RootSigDesc =
+      RSBI.getDescForFunction(MMI.EntryPropertyVec[0].Entry);
+  if (!RootSigDesc)
+    return;
+
+  for (const mcdxbc::RootParameterInfo &Info :
+       RootSigDesc->ParametersContainer) {
+    const auto &[Type, Loc] =
+        RootSigDesc->ParametersContainer.getTypeAndLocForParameter(
+            Info.Location);
+    switch (Type) {
+    case llvm::to_underlying(dxbc::RootParameterType::CBV):
+      dxbc::RTS0::v2::RootDescriptor Desc =
+          RootSigDesc->ParametersContainer.getRootDescriptor(Loc);
+
+      llvm::dxil::ResourceInfo::ResourceBinding Binding;
+      Binding.LowerBound = Desc.ShaderRegister;
+      Binding.Space = Desc.RegisterSpace;
+      Binding.Size = 1;
+      break;
+    }
+  }
 }
 } // namespace
 
@@ -101,7 +130,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 +145,13 @@ 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 +163,13 @@ class DXILPostOptimizationValidationLegacy : public ModulePass {
   void getAnalysisUsage(llvm::AnalysisUsage &AU) const override {
     AU.addRequired<DXILResourceWrapperPass>();
     AU.addRequired<DXILResourceBindingWrapperPass>();
+    AU.addRequired<RootSignatureAnalysisWrapper>();
+    AU.addRequired<DXILMetadataAnalysisWrapperPass>();
     AU.addPreserved<DXILResourceWrapperPass>();
     AU.addPreserved<DXILResourceBindingWrapperPass>();
     AU.addPreserved<DXILMetadataAnalysisWrapperPass>();
     AU.addPreserved<ShaderFlagsAnalysisWrapper>();
+    AU.addPreserved<RootSignatureAnalysisWrapper>();
   }
 };
 char DXILPostOptimizationValidationLegacy::ID = 0;
diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.h b/llvm/lib/Target/DirectX/DXILRootSignature.h
index 24b1a8d3d2abe..ecfc577d1b97d 100644
--- a/llvm/lib/Target/DirectX/DXILRootSignature.h
+++ b/llvm/lib/Target/DirectX/DXILRootSignature.h
@@ -37,28 +37,30 @@ enum class RootSignatureElementKind {
 };
 
 class RootSignatureBindingInfo {
-  private:
-    SmallDenseMap<const Function *, mcdxbc::RootSignatureDesc> FuncToRsMap;
+private:
+  SmallDenseMap<const Function *, mcdxbc::RootSignatureDesc> FuncToRsMap;
 
-  public:
+public:
   using iterator =
-        SmallDenseMap<const Function *, mcdxbc::RootSignatureDesc>::iterator;
+      SmallDenseMap<const Function *, mcdxbc::RootSignatureDesc>::iterator;
 
-  RootSignatureBindingInfo () = default;
-  RootSignatureBindingInfo(SmallDenseMap<const Function *, mcdxbc::RootSignatureDesc> Map) : FuncToRsMap(Map) {};
+  RootSignatureBindingInfo() = default;
+  RootSignatureBindingInfo(
+      SmallDenseMap<const Function *, mcdxbc::RootSignatureDesc> Map)
+      : FuncToRsMap(Map){};
 
   iterator find(const Function *F) { return FuncToRsMap.find(F); }
 
   iterator end() { return FuncToRsMap.end(); }
 
-  std::optional<mcdxbc::RootSignatureDesc> getDescForFunction(const Function* F) {
+  std::optional<mcdxbc::RootSignatureDesc>
+  getDescForFunction(const Function *F) {
     const auto FuncRs = find(F);
     if (FuncRs == end())
       return std::nullopt;
 
     return FuncRs->second;
   }
-  
 };
 
 class RootSignatureAnalysis : public AnalysisInfoMixin<RootSignatureAnalysis> {
@@ -66,13 +68,11 @@ class RootSignatureAnalysis : public AnalysisInfoMixin<RootSignatureAnalysis> {
   static AnalysisKey Key;
 
 public:
-
-RootSignatureAnalysis() = default;
+  RootSignatureAnalysis() = default;
 
   using Result = RootSignatureBindingInfo;
-  
-  RootSignatureBindingInfo
-  run(Module &M, ModuleAnalysisManager &AM);
+
+  RootSignatureBindingInfo run(Module &M, ModuleAnalysisManager &AM);
 };
 
 /// Wrapper pass for the legacy pass manager.
@@ -89,8 +89,8 @@ class RootSignatureAnalysisWrapper : public ModulePass {
 
   RootSignatureAnalysisWrapper() : ModulePass(ID) {}
 
-  RootSignatureBindingInfo& getRSInfo() {return *FuncToRsMap;}
-  
+  RootSignatureBindingInfo &getRSInfo() { return *FuncToRsMap; }
+
   bool runOnModule(Module &M) override;
 
   void getAnalysisUsage(AnalysisUsage &AU) const override;

>From a04eb9ff37d20499f05c7b1cc0ab3187f729609b Mon Sep 17 00:00:00 2001
From: joaosaffran <joao.saffran at microsoft.com>
Date: Wed, 2 Jul 2025 17:58:56 +0000
Subject: [PATCH 10/29] adding validation

---
 .../SemaHLSL/RootSignature-Validation.hlsl    | 28 ++++---------
 .../DXILPostOptimizationValidation.cpp        | 42 +++++++++++++++----
 2 files changed, 43 insertions(+), 27 deletions(-)

diff --git a/clang/test/SemaHLSL/RootSignature-Validation.hlsl b/clang/test/SemaHLSL/RootSignature-Validation.hlsl
index 8a4a97f87cb65..62ba704b95c7d 100644
--- a/clang/test/SemaHLSL/RootSignature-Validation.hlsl
+++ b/clang/test/SemaHLSL/RootSignature-Validation.hlsl
@@ -1,42 +1,30 @@
-// RUN: %clang_dxc -triple dxil-pc-shadermodel6.3-library -x hlsl -o - %s -verify
 
 #define ROOT_SIGNATURE \
     "RootFlags(ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT), " \
-    "CBV(b0, visibility=SHADER_VISIBILITY_ALL), " \
-    "DescriptorTable(SRV(t0, numDescriptors=3), visibility=SHADER_VISIBILITY_PIXEL), " \
-    "DescriptorTable(Sampler(s0, numDescriptors=2), visibility=SHADER_VISIBILITY_PIXEL), " \
-    "DescriptorTable(UAV(u0, numDescriptors=1), visibility=SHADER_VISIBILITY_ALL)"
+    "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_ALL), " \
+    "DescriptorTable(UAV(u0, numDescriptors=unbounded), visibility=SHADER_VISIBILITY_ALL)"
 
 cbuffer CB : register(b3, space2) {
   float a;
 }
 
-StructuredBuffer<int> In : register(t0);
+StructuredBuffer<int> In : register(t0, space0);
 RWStructuredBuffer<int> Out : register(u0);
 
 RWBuffer<float> UAV : register(u3);
 
 RWBuffer<float> UAV1 : register(u2), UAV2 : register(u4);
 
-RWBuffer<float> UAV3 : register(space5);
+RWBuffer<float> UAV3 : register(space0);
 
-float f : register(c5);
 
-int4 intv : register(c2);
-
-double dar[5] :  register(c3);
-
-struct S {
-  int a;
-};
-
-S s : register(c10);
 
 // Compute Shader for UAV testing
 [numthreads(8, 8, 1)]
 [RootSignature(ROOT_SIGNATURE)]
-void CSMain(uint3 id : SV_DispatchThreadID)
+void CSMain(uint id : SV_GroupID)
 {
-    In[0] = id;
-    Out[0] = In[0];
+    Out[0] = a + id + In[0] + UAV[0] + UAV1[0] + UAV3[0];
 }
diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
index daf53fefe5f17..3e542e502c2d5 100644
--- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
+++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
@@ -10,6 +10,7 @@
 #include "DXILRootSignature.h"
 #include "DXILShaderFlags.h"
 #include "DirectX.h"
+#include "llvm/ADT/IntervalMap.h"
 #include "llvm/ADT/STLForwardCompat.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/Analysis/DXILMetadataAnalysis.h"
@@ -86,7 +87,9 @@ static void reportOverlappingBinding(Module &M, DXILResourceMap &DRM) {
     }
   }
 }
-
+  uint64_t combine_uint32_to_uint64(uint32_t high, uint32_t low) {
+      return (static_cast<uint64_t>(high) << 32) | low;
+  }
 static void reportErrors(Module &M, DXILResourceMap &DRM,
                          DXILResourceBindingInfo &DRBI,
                          RootSignatureBindingInfo &RSBI,
@@ -101,18 +104,24 @@ static void reportErrors(Module &M, DXILResourceMap &DRM,
                                        "DXILResourceImplicitBinding pass");
   // Assuming this is used to validate only the root signature assigned to the
   // entry function.
+  //Start test stuff
+  if(MMI.EntryPropertyVec.size() == 0)
+    return;
+
   std::optional<mcdxbc::RootSignatureDesc> RootSigDesc =
       RSBI.getDescForFunction(MMI.EntryPropertyVec[0].Entry);
   if (!RootSigDesc)
     return;
 
-  for (const mcdxbc::RootParameterInfo &Info :
-       RootSigDesc->ParametersContainer) {
+  using MapT = llvm::IntervalMap<uint64_t, llvm::dxil::ResourceInfo::ResourceBinding, sizeof(llvm::dxil::ResourceInfo::ResourceBinding), llvm::IntervalMapInfo<uint64_t>>;
+  MapT::Allocator Allocator;
+  MapT BindingsMap(Allocator);
+  auto RSD = *RootSigDesc;
+   for (size_t I = 0; I < RSD.ParametersContainer.size(); I++) {
     const auto &[Type, Loc] =
-        RootSigDesc->ParametersContainer.getTypeAndLocForParameter(
-            Info.Location);
+        RootSigDesc->ParametersContainer.getTypeAndLocForParameter(I);
     switch (Type) {
-    case llvm::to_underlying(dxbc::RootParameterType::CBV):
+    case llvm::to_underlying(dxbc::RootParameterType::CBV):{
       dxbc::RTS0::v2::RootDescriptor Desc =
           RootSigDesc->ParametersContainer.getRootDescriptor(Loc);
 
@@ -120,8 +129,27 @@ static void reportErrors(Module &M, DXILResourceMap &DRM,
       Binding.LowerBound = Desc.ShaderRegister;
       Binding.Space = Desc.RegisterSpace;
       Binding.Size = 1;
+
+      BindingsMap.insert(combine_uint32_to_uint64(Binding.Space, Binding.LowerBound), combine_uint32_to_uint64(Binding.Space, Binding.LowerBound + Binding.Size -1), Binding);
       break;
     }
+    // case llvm::to_underlying(dxbc::RootParameterType::DescriptorTable):{
+    //   mcdxbc::DescriptorTable Table =
+    //       RootSigDesc->ParametersContainer.getDescriptorTable(Loc);
+    //   for (const dxbc::RTS0::v2::DescriptorRange &Range : Table){
+    //     Range.
+    //   }
+      
+    //   break;
+    // }
+    }
+
+  }
+
+  for(const auto &CBuf : DRM.cbuffers()) {
+    auto Binding = CBuf.getBinding();
+    if(!BindingsMap.overlaps(combine_uint32_to_uint64(Binding.Space, Binding.LowerBound), combine_uint32_to_uint64(Binding.Space, Binding.LowerBound + Binding.Size -1)))
+      auto X = 1;
   }
 }
 } // namespace
@@ -146,7 +174,7 @@ class DXILPostOptimizationValidationLegacy : public ModulePass {
     DXILResourceBindingInfo &DRBI =
         getAnalysis<DXILResourceBindingWrapperPass>().getBindingInfo();
 
-    RootSignatureBindingInfo &RSBI =
+    RootSignatureBindingInfo& RSBI =
         getAnalysis<RootSignatureAnalysisWrapper>().getRSInfo();
     dxil::ModuleMetadataInfo &MMI =
         getAnalysis<DXILMetadataAnalysisWrapperPass>().getModuleMetadata();

>From 5994b8f8f4ea24115a66c0046c8fc344905b41d4 Mon Sep 17 00:00:00 2001
From: joaosaffran <joao.saffran at microsoft.com>
Date: Wed, 2 Jul 2025 21:19:37 +0000
Subject: [PATCH 11/29] clean

---
 .../DXILPostOptimizationValidation.cpp        |  6 +----
 .../DirectX/DXILPostOptimizationValidation.h  |  3 +++
 llvm/lib/Target/DirectX/DXILRootSignature.h   | 24 +++++++++----------
 3 files changed, 15 insertions(+), 18 deletions(-)

diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
index 3e542e502c2d5..4c29b56304391 100644
--- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
+++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
@@ -10,12 +10,9 @@
 #include "DXILRootSignature.h"
 #include "DXILShaderFlags.h"
 #include "DirectX.h"
-#include "llvm/ADT/IntervalMap.h"
-#include "llvm/ADT/STLForwardCompat.h"
 #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"
@@ -173,8 +170,7 @@ class DXILPostOptimizationValidationLegacy : public ModulePass {
         getAnalysis<DXILResourceWrapperPass>().getResourceMap();
     DXILResourceBindingInfo &DRBI =
         getAnalysis<DXILResourceBindingWrapperPass>().getBindingInfo();
-
-    RootSignatureBindingInfo& RSBI =
+    RootSignatureBindingInfo &RSBI =
         getAnalysis<RootSignatureAnalysisWrapper>().getRSInfo();
     dxil::ModuleMetadataInfo &MMI =
         getAnalysis<DXILMetadataAnalysisWrapperPass>().getModuleMetadata();
diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h
index cb5e624514272..151843daf068d 100644
--- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h
+++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h
@@ -14,6 +14,9 @@
 #ifndef LLVM_LIB_TARGET_DIRECTX_DXILPOSTOPTIMIZATIONVALIDATION_H
 #define LLVM_LIB_TARGET_DIRECTX_DXILPOSTOPTIMIZATIONVALIDATION_H
 
+#include "DXILRootSignature.h"
+#include "llvm/ADT/IntervalMap.h"
+#include "llvm/Analysis/DXILResource.h"
 #include "llvm/IR/PassManager.h"
 
 namespace llvm {
diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.h b/llvm/lib/Target/DirectX/DXILRootSignature.h
index ecfc577d1b97d..d0d5c7785bda3 100644
--- a/llvm/lib/Target/DirectX/DXILRootSignature.h
+++ b/llvm/lib/Target/DirectX/DXILRootSignature.h
@@ -37,30 +37,28 @@ enum class RootSignatureElementKind {
 };
 
 class RootSignatureBindingInfo {
-private:
-  SmallDenseMap<const Function *, mcdxbc::RootSignatureDesc> FuncToRsMap;
+  private:
+    SmallDenseMap<const Function *, mcdxbc::RootSignatureDesc> FuncToRsMap;
 
-public:
+  public:
   using iterator =
-      SmallDenseMap<const Function *, mcdxbc::RootSignatureDesc>::iterator;
+        SmallDenseMap<const Function *, mcdxbc::RootSignatureDesc>::iterator;
 
-  RootSignatureBindingInfo() = default;
-  RootSignatureBindingInfo(
-      SmallDenseMap<const Function *, mcdxbc::RootSignatureDesc> Map)
-      : FuncToRsMap(Map){};
+RootSignatureBindingInfo () = default;
+  RootSignatureBindingInfo(SmallDenseMap<const Function *, mcdxbc::RootSignatureDesc> Map) : FuncToRsMap(Map) {};
 
   iterator find(const Function *F) { return FuncToRsMap.find(F); }
 
   iterator end() { return FuncToRsMap.end(); }
 
-  std::optional<mcdxbc::RootSignatureDesc>
-  getDescForFunction(const Function *F) {
+  std::optional<mcdxbc::RootSignatureDesc> getDescForFunction(const Function *F) {
     const auto FuncRs = find(F);
     if (FuncRs == end())
       return std::nullopt;
 
     return FuncRs->second;
   }
+
 };
 
 class RootSignatureAnalysis : public AnalysisInfoMixin<RootSignatureAnalysis> {
@@ -68,7 +66,7 @@ class RootSignatureAnalysis : public AnalysisInfoMixin<RootSignatureAnalysis> {
   static AnalysisKey Key;
 
 public:
-  RootSignatureAnalysis() = default;
+RootSignatureAnalysis() = default;
 
   using Result = RootSignatureBindingInfo;
 
@@ -88,8 +86,8 @@ class RootSignatureAnalysisWrapper : public ModulePass {
   using Result = RootSignatureBindingInfo;
 
   RootSignatureAnalysisWrapper() : ModulePass(ID) {}
-
-  RootSignatureBindingInfo &getRSInfo() { return *FuncToRsMap; }
+  
+  RootSignatureBindingInfo& getRSInfo() {return *FuncToRsMap;}
 
   bool runOnModule(Module &M) override;
 

>From e8b14bf32e47cf8c059d2f492e57a602375ceeaa Mon Sep 17 00:00:00 2001
From: joaosaffran <joao.saffran at microsoft.com>
Date: Fri, 4 Jul 2025 02:03:26 +0000
Subject: [PATCH 12/29] implementing

---
 .../RootSignature-Validation-Fail.hlsl        |  35 ++++
 .../SemaHLSL/RootSignature-Validation.hlsl    |  11 +-
 .../DXILPostOptimizationValidation.cpp        | 166 +++++++++++++-----
 .../DirectX/DXILPostOptimizationValidation.h  |  88 ++++++++++
 llvm/lib/Target/DirectX/DXILRootSignature.h   |  24 +--
 .../RootSignature-DescriptorTable.ll          |   4 +-
 6 files changed, 271 insertions(+), 57 deletions(-)
 create mode 100644 clang/test/SemaHLSL/RootSignature-Validation-Fail.hlsl

diff --git a/clang/test/SemaHLSL/RootSignature-Validation-Fail.hlsl b/clang/test/SemaHLSL/RootSignature-Validation-Fail.hlsl
new file mode 100644
index 0000000000000..b590ed67e7085
--- /dev/null
+++ b/clang/test/SemaHLSL/RootSignature-Validation-Fail.hlsl
@@ -0,0 +1,35 @@
+// RUN: not %clang_dxc -T cs_6_6 -E CSMain %s 2>&1 | FileCheck %s
+
+// CHECK: error: register cbuffer (space=665, register=3) is not defined in Root Signature
+// CHECK: error: register srv (space=0, register=0) is not defined in Root Signature
+// CHECK: error: register uav (space=0, register=4294967295) is not defined in Root Signature
+
+
+#define 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)"
+
+cbuffer CB : register(b3, space665) {
+  float a;
+}
+
+StructuredBuffer<int> In : register(t0, space0);
+RWStructuredBuffer<int> Out : register(u0);
+
+RWBuffer<float> UAV : register(u4294967295);
+
+RWBuffer<float> UAV1 : register(u2), UAV2 : register(u4);
+
+RWBuffer<float> UAV3 : register(space0);
+
+
+
+// Compute Shader for UAV testing
+[numthreads(8, 8, 1)]
+[RootSignature(ROOT_SIGNATURE)]
+void CSMain(uint id : SV_GroupID)
+{
+    Out[0] = a + id + In[0] + UAV[0] + UAV1[0] + UAV3[0];
+}
diff --git a/clang/test/SemaHLSL/RootSignature-Validation.hlsl b/clang/test/SemaHLSL/RootSignature-Validation.hlsl
index 62ba704b95c7d..5a7f5baf00619 100644
--- a/clang/test/SemaHLSL/RootSignature-Validation.hlsl
+++ b/clang/test/SemaHLSL/RootSignature-Validation.hlsl
@@ -1,19 +1,22 @@
+// RUN: %clang_dxc -T cs_6_6 -E CSMain %s 2>&1 
+
+// expected-no-diagnostics
+
 
 #define ROOT_SIGNATURE \
-    "RootFlags(ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT), " \
     "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_ALL), " \
+    "DescriptorTable(Sampler(s0, numDescriptors=2), visibility=SHADER_VISIBILITY_VERTEX), " \
     "DescriptorTable(UAV(u0, numDescriptors=unbounded), visibility=SHADER_VISIBILITY_ALL)"
 
-cbuffer CB : register(b3, space2) {
+cbuffer CB : register(b3, space1) {
   float a;
 }
 
 StructuredBuffer<int> In : register(t0, space0);
 RWStructuredBuffer<int> Out : register(u0);
 
-RWBuffer<float> UAV : register(u3);
+RWBuffer<float> UAV : register(u4294967294);
 
 RWBuffer<float> UAV1 : register(u2), UAV2 : register(u4);
 
diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
index 4c29b56304391..23bb5d1a7f651 100644
--- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
+++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
@@ -84,9 +84,57 @@ static void reportOverlappingBinding(Module &M, DXILResourceMap &DRM) {
     }
   }
 }
-  uint64_t combine_uint32_to_uint64(uint32_t high, uint32_t low) {
-      return (static_cast<uint64_t>(high) << 32) | low;
+
+static void reportRegNotBound(Module &M, Twine Type,
+                              ResourceInfo::ResourceBinding Binding) {
+  SmallString<128> Message;
+  raw_svector_ostream OS(Message);
+  OS << "register " << Type << " (space=" << Binding.Space
+     << ", register=" << Binding.LowerBound << ")"
+     << " is not defined in 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");
   }
+}
+
+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,
                          RootSignatureBindingInfo &RSBI,
@@ -99,57 +147,95 @@ static void reportErrors(Module &M, DXILResourceMap &DRM,
 
   assert(!DRBI.hasImplicitBinding() && "implicit bindings should be handled in "
                                        "DXILResourceImplicitBinding pass");
-  // Assuming this is used to validate only the root signature assigned to the
-  // entry function.
-  //Start test stuff
-  if(MMI.EntryPropertyVec.size() == 0)
-    return;
 
-  std::optional<mcdxbc::RootSignatureDesc> RootSigDesc =
-      RSBI.getDescForFunction(MMI.EntryPropertyVec[0].Entry);
-  if (!RootSigDesc)
-    return;
+  if (auto RSD = getRootSignature(RSBI, MMI)) {
+
+    RootSignatureBindingValidation Validation;
+    Validation.addRsBindingInfo(*RSD, tripleToVisibility(MMI.ShaderProfile));
+
+    for (const auto &CBuf : DRM.cbuffers()) {
+      ResourceInfo::ResourceBinding Binding = CBuf.getBinding();
+      if (!Validation.checkCregBinding(Binding))
+        reportRegNotBound(M, "cbuffer", Binding);
+    }
+
+    for (const auto &CBuf : DRM.srvs()) {
+      ResourceInfo::ResourceBinding Binding = CBuf.getBinding();
+      if (!Validation.checkTRegBinding(Binding))
+        reportRegNotBound(M, "srv", Binding);
+    }
 
-  using MapT = llvm::IntervalMap<uint64_t, llvm::dxil::ResourceInfo::ResourceBinding, sizeof(llvm::dxil::ResourceInfo::ResourceBinding), llvm::IntervalMapInfo<uint64_t>>;
-  MapT::Allocator Allocator;
-  MapT BindingsMap(Allocator);
-  auto RSD = *RootSigDesc;
-   for (size_t I = 0; I < RSD.ParametersContainer.size(); I++) {
+    for (const auto &CBuf : DRM.uavs()) {
+      ResourceInfo::ResourceBinding Binding = CBuf.getBinding();
+      if (!Validation.checkURegBinding(Binding))
+        reportRegNotBound(M, "uav", Binding);
+    }
+  }
+}
+} // namespace
+
+void RootSignatureBindingValidation::addRsBindingInfo(
+    mcdxbc::RootSignatureDesc &RSD, dxbc::ShaderVisibility Visibility) {
+  for (size_t I = 0; I < RSD.ParametersContainer.size(); I++) {
     const auto &[Type, Loc] =
-        RootSigDesc->ParametersContainer.getTypeAndLocForParameter(I);
+        RSD.ParametersContainer.getTypeAndLocForParameter(I);
+
+    const auto &Header = RSD.ParametersContainer.getHeader(I);
     switch (Type) {
-    case llvm::to_underlying(dxbc::RootParameterType::CBV):{
+    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 =
-          RootSigDesc->ParametersContainer.getRootDescriptor(Loc);
+          RSD.ParametersContainer.getRootDescriptor(Loc);
 
-      llvm::dxil::ResourceInfo::ResourceBinding Binding;
-      Binding.LowerBound = Desc.ShaderRegister;
-      Binding.Space = Desc.RegisterSpace;
-      Binding.Size = 1;
+      if (Header.ShaderVisibility ==
+              llvm::to_underlying(dxbc::ShaderVisibility::All) ||
+          Header.ShaderVisibility == llvm::to_underlying(Visibility))
+        addRange(Desc, Type);
+      break;
+    }
+    case llvm::to_underlying(dxbc::RootParameterType::DescriptorTable): {
+      const mcdxbc::DescriptorTable &Table =
+          RSD.ParametersContainer.getDescriptorTable(Loc);
 
-      BindingsMap.insert(combine_uint32_to_uint64(Binding.Space, Binding.LowerBound), combine_uint32_to_uint64(Binding.Space, Binding.LowerBound + Binding.Size -1), Binding);
+      for (const dxbc::RTS0::v2::DescriptorRange &Range : Table.Ranges) {
+        if (Range.RangeType ==
+            llvm::to_underlying(dxbc::DescriptorRangeType::Sampler))
+          continue;
+
+        if (Header.ShaderVisibility ==
+                llvm::to_underlying(dxbc::ShaderVisibility::All) ||
+            Header.ShaderVisibility == llvm::to_underlying(Visibility))
+          addRange(Range);
+      }
       break;
     }
-    // case llvm::to_underlying(dxbc::RootParameterType::DescriptorTable):{
-    //   mcdxbc::DescriptorTable Table =
-    //       RootSigDesc->ParametersContainer.getDescriptorTable(Loc);
-    //   for (const dxbc::RTS0::v2::DescriptorRange &Range : Table){
-    //     Range.
-    //   }
-      
-    //   break;
-    // }
     }
-
   }
+}
 
-  for(const auto &CBuf : DRM.cbuffers()) {
-    auto Binding = CBuf.getBinding();
-    if(!BindingsMap.overlaps(combine_uint32_to_uint64(Binding.Space, Binding.LowerBound), combine_uint32_to_uint64(Binding.Space, Binding.LowerBound + Binding.Size -1)))
-      auto X = 1;
-  }
+bool RootSignatureBindingValidation::checkCregBinding(
+    ResourceInfo::ResourceBinding Binding) {
+  return CRegBindingsMap.overlaps(
+      combineUint32ToUint64(Binding.Space, Binding.LowerBound),
+      combineUint32ToUint64(Binding.Space,
+                            Binding.LowerBound + Binding.Size - 1));
+}
+
+bool RootSignatureBindingValidation::checkTRegBinding(
+    ResourceInfo::ResourceBinding Binding) {
+  return TRegBindingsMap.overlaps(
+      combineUint32ToUint64(Binding.Space, Binding.LowerBound),
+      combineUint32ToUint64(Binding.Space, Binding.LowerBound + Binding.Size));
+}
+
+bool RootSignatureBindingValidation::checkURegBinding(
+    ResourceInfo::ResourceBinding Binding) {
+  return URegBindingsMap.overlaps(
+      combineUint32ToUint64(Binding.Space, Binding.LowerBound),
+      combineUint32ToUint64(Binding.Space,
+                            Binding.LowerBound + Binding.Size - 1));
 }
-} // namespace
 
 PreservedAnalyses
 DXILPostOptimizationValidation::run(Module &M, ModuleAnalysisManager &MAM) {
diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h
index 151843daf068d..58113bf9f93c7 100644
--- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h
+++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h
@@ -21,6 +21,94 @@
 
 namespace llvm {
 
+static uint64_t combineUint32ToUint64(uint32_t High, uint32_t Low) {
+  return (static_cast<uint64_t>(High) << 32) | Low;
+}
+
+class RootSignatureBindingValidation {
+  using MapT =
+      llvm::IntervalMap<uint64_t, dxil::ResourceInfo::ResourceBinding,
+                        sizeof(llvm::dxil::ResourceInfo::ResourceBinding),
+                        llvm::IntervalMapInfo<uint64_t>>;
+
+private:
+  MapT::Allocator Allocator;
+  MapT CRegBindingsMap;
+  MapT TRegBindingsMap;
+  MapT URegBindingsMap;
+
+  void addRange(const dxbc::RTS0::v2::RootDescriptor &Desc, uint32_t Type) {
+    assert((Type == llvm::to_underlying(dxbc::RootParameterType::CBV) ||
+            Type == llvm::to_underlying(dxbc::RootParameterType::SRV) ||
+            Type == llvm::to_underlying(dxbc::RootParameterType::UAV)) &&
+           "Invalid Type");
+
+    llvm::dxil::ResourceInfo::ResourceBinding Binding;
+    Binding.LowerBound = Desc.ShaderRegister;
+    Binding.Space = Desc.RegisterSpace;
+    Binding.Size = 1;
+
+    uint64_t LowRange =
+        combineUint32ToUint64(Binding.Space, Binding.LowerBound);
+    uint64_t HighRange = combineUint32ToUint64(
+        Binding.Space, Binding.LowerBound + Binding.Size - 1);
+
+    switch (Type) {
+
+    case llvm::to_underlying(dxbc::RootParameterType::CBV):
+      CRegBindingsMap.insert(LowRange, HighRange, Binding);
+      return;
+    case llvm::to_underlying(dxbc::RootParameterType::SRV):
+      TRegBindingsMap.insert(LowRange, HighRange, Binding);
+      return;
+    case llvm::to_underlying(dxbc::RootParameterType::UAV):
+      URegBindingsMap.insert(LowRange, HighRange, Binding);
+      return;
+    }
+    llvm_unreachable("Invalid Type in add Range Method");
+  }
+
+  void addRange(const dxbc::RTS0::v2::DescriptorRange &Range) {
+
+    llvm::dxil::ResourceInfo::ResourceBinding Binding;
+    Binding.LowerBound = Range.BaseShaderRegister;
+    Binding.Space = Range.RegisterSpace;
+    Binding.Size = Range.NumDescriptors;
+
+    uint64_t LowRange =
+        combineUint32ToUint64(Binding.Space, Binding.LowerBound);
+    uint64_t HighRange = combineUint32ToUint64(
+        Binding.Space, Binding.LowerBound + Binding.Size - 1);
+
+    switch (Range.RangeType) {
+    case llvm::to_underlying(dxbc::DescriptorRangeType::CBV):
+      CRegBindingsMap.insert(LowRange, HighRange, Binding);
+      return;
+    case llvm::to_underlying(dxbc::DescriptorRangeType::SRV):
+      TRegBindingsMap.insert(LowRange, HighRange, Binding);
+      return;
+    case llvm::to_underlying(dxbc::DescriptorRangeType::UAV):
+      URegBindingsMap.insert(LowRange, HighRange, Binding);
+      return;
+    }
+    llvm_unreachable("Invalid Type in add Range Method");
+  }
+
+public:
+  RootSignatureBindingValidation()
+      : Allocator(), CRegBindingsMap(Allocator), TRegBindingsMap(Allocator),
+        URegBindingsMap(Allocator) {}
+
+  void addRsBindingInfo(mcdxbc::RootSignatureDesc &RSD,
+                        dxbc::ShaderVisibility Visibility);
+
+  bool checkCregBinding(dxil::ResourceInfo::ResourceBinding Binding);
+
+  bool checkTRegBinding(dxil::ResourceInfo::ResourceBinding Binding);
+
+  bool checkURegBinding(dxil::ResourceInfo::ResourceBinding Binding);
+};
+
 class DXILPostOptimizationValidation
     : public PassInfoMixin<DXILPostOptimizationValidation> {
 public:
diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.h b/llvm/lib/Target/DirectX/DXILRootSignature.h
index d0d5c7785bda3..ecfc577d1b97d 100644
--- a/llvm/lib/Target/DirectX/DXILRootSignature.h
+++ b/llvm/lib/Target/DirectX/DXILRootSignature.h
@@ -37,28 +37,30 @@ enum class RootSignatureElementKind {
 };
 
 class RootSignatureBindingInfo {
-  private:
-    SmallDenseMap<const Function *, mcdxbc::RootSignatureDesc> FuncToRsMap;
+private:
+  SmallDenseMap<const Function *, mcdxbc::RootSignatureDesc> FuncToRsMap;
 
-  public:
+public:
   using iterator =
-        SmallDenseMap<const Function *, mcdxbc::RootSignatureDesc>::iterator;
+      SmallDenseMap<const Function *, mcdxbc::RootSignatureDesc>::iterator;
 
-RootSignatureBindingInfo () = default;
-  RootSignatureBindingInfo(SmallDenseMap<const Function *, mcdxbc::RootSignatureDesc> Map) : FuncToRsMap(Map) {};
+  RootSignatureBindingInfo() = default;
+  RootSignatureBindingInfo(
+      SmallDenseMap<const Function *, mcdxbc::RootSignatureDesc> Map)
+      : FuncToRsMap(Map){};
 
   iterator find(const Function *F) { return FuncToRsMap.find(F); }
 
   iterator end() { return FuncToRsMap.end(); }
 
-  std::optional<mcdxbc::RootSignatureDesc> getDescForFunction(const Function *F) {
+  std::optional<mcdxbc::RootSignatureDesc>
+  getDescForFunction(const Function *F) {
     const auto FuncRs = find(F);
     if (FuncRs == end())
       return std::nullopt;
 
     return FuncRs->second;
   }
-
 };
 
 class RootSignatureAnalysis : public AnalysisInfoMixin<RootSignatureAnalysis> {
@@ -66,7 +68,7 @@ class RootSignatureAnalysis : public AnalysisInfoMixin<RootSignatureAnalysis> {
   static AnalysisKey Key;
 
 public:
-RootSignatureAnalysis() = default;
+  RootSignatureAnalysis() = default;
 
   using Result = RootSignatureBindingInfo;
 
@@ -86,8 +88,8 @@ class RootSignatureAnalysisWrapper : public ModulePass {
   using Result = RootSignatureBindingInfo;
 
   RootSignatureAnalysisWrapper() : ModulePass(ID) {}
-  
-  RootSignatureBindingInfo& getRSInfo() {return *FuncToRsMap;}
+
+  RootSignatureBindingInfo &getRSInfo() { return *FuncToRsMap; }
 
   bool runOnModule(Module &M) override;
 
diff --git a/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-DescriptorTable.ll b/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-DescriptorTable.ll
index b516d66180247..8e9b4b43b11a6 100644
--- a/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-DescriptorTable.ll
+++ b/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-DescriptorTable.ll
@@ -16,7 +16,7 @@ attributes #0 = { "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" }
 !2 = !{ ptr @main, !3, i32 2 } ; function, root signature
 !3 = !{ !5 } ; list of root signature elements
 !5 = !{ !"DescriptorTable", i32 0, !6, !7 }
-!6 = !{ !"SRV", i32 0, i32 1, i32 0, i32 -1, i32 4 }
+!6 = !{ !"SRV", i32 1, i32 1, i32 0, i32 -1, i32 4 }
 !7 = !{ !"UAV", i32 5, i32 1, i32 10, i32 5, i32 2 }
 
 ; DXC:  - Name:            RTS0
@@ -35,7 +35,7 @@ attributes #0 = { "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" }
 ; DXC-NEXT:            RangesOffset:    44
 ; DXC-NEXT:            Ranges:
 ; DXC-NEXT:              - RangeType:       0
-; DXC-NEXT:                NumDescriptors:  0
+; DXC-NEXT:                NumDescriptors:  1
 ; DXC-NEXT:                BaseShaderRegister: 1
 ; DXC-NEXT:                RegisterSpace:   0
 ; DXC-NEXT:                OffsetInDescriptorsFromTableStart: 4294967295

>From 8f40e83ab0db147e90070f15708d0a0f4e1a9d1f Mon Sep 17 00:00:00 2001
From: joaosaffran <joao.saffran at microsoft.com>
Date: Fri, 4 Jul 2025 19:24:25 +0000
Subject: [PATCH 13/29] finish implementing && fix tests

---
 .../DXILPostOptimizationValidation.cpp        | 45 +++++-----------
 .../DirectX/DXILPostOptimizationValidation.h  | 54 ++++++++++++++-----
 llvm/lib/Target/DirectX/DXILRootSignature.cpp |  5 +-
 ...criptorTable-AllValidFlagCombinationsV1.ll |  4 +-
 llvm/test/CodeGen/DirectX/llc-pipeline.ll     |  1 +
 5 files changed, 59 insertions(+), 50 deletions(-)

diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
index 23bb5d1a7f651..a52a04323514c 100644
--- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
+++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
@@ -153,23 +153,29 @@ static void reportErrors(Module &M, DXILResourceMap &DRM,
     RootSignatureBindingValidation Validation;
     Validation.addRsBindingInfo(*RSD, tripleToVisibility(MMI.ShaderProfile));
 
-    for (const auto &CBuf : DRM.cbuffers()) {
+    for (const ResourceInfo &CBuf : DRM.cbuffers()) {
       ResourceInfo::ResourceBinding Binding = CBuf.getBinding();
-      if (!Validation.checkCregBinding(Binding))
+      if (!Validation.checkCRegBinding(Binding))
         reportRegNotBound(M, "cbuffer", Binding);
     }
 
-    for (const auto &CBuf : DRM.srvs()) {
-      ResourceInfo::ResourceBinding Binding = CBuf.getBinding();
+    for (const ResourceInfo &SRV : DRM.srvs()) {
+      ResourceInfo::ResourceBinding Binding = SRV.getBinding();
       if (!Validation.checkTRegBinding(Binding))
         reportRegNotBound(M, "srv", Binding);
     }
 
-    for (const auto &CBuf : DRM.uavs()) {
-      ResourceInfo::ResourceBinding Binding = CBuf.getBinding();
+    for (const ResourceInfo &UAV : DRM.uavs()) {
+      ResourceInfo::ResourceBinding Binding = UAV.getBinding();
       if (!Validation.checkURegBinding(Binding))
         reportRegNotBound(M, "uav", Binding);
     }
+
+    for (const ResourceInfo &Sampler : DRM.samplers()) {
+      ResourceInfo::ResourceBinding Binding = Sampler.getBinding();
+      if (!Validation.checkSamplerBinding(Binding))
+        reportRegNotBound(M, "sampler", Binding);
+    }
   }
 }
 } // namespace
@@ -199,10 +205,6 @@ void RootSignatureBindingValidation::addRsBindingInfo(
           RSD.ParametersContainer.getDescriptorTable(Loc);
 
       for (const dxbc::RTS0::v2::DescriptorRange &Range : Table.Ranges) {
-        if (Range.RangeType ==
-            llvm::to_underlying(dxbc::DescriptorRangeType::Sampler))
-          continue;
-
         if (Header.ShaderVisibility ==
                 llvm::to_underlying(dxbc::ShaderVisibility::All) ||
             Header.ShaderVisibility == llvm::to_underlying(Visibility))
@@ -214,29 +216,6 @@ void RootSignatureBindingValidation::addRsBindingInfo(
   }
 }
 
-bool RootSignatureBindingValidation::checkCregBinding(
-    ResourceInfo::ResourceBinding Binding) {
-  return CRegBindingsMap.overlaps(
-      combineUint32ToUint64(Binding.Space, Binding.LowerBound),
-      combineUint32ToUint64(Binding.Space,
-                            Binding.LowerBound + Binding.Size - 1));
-}
-
-bool RootSignatureBindingValidation::checkTRegBinding(
-    ResourceInfo::ResourceBinding Binding) {
-  return TRegBindingsMap.overlaps(
-      combineUint32ToUint64(Binding.Space, Binding.LowerBound),
-      combineUint32ToUint64(Binding.Space, Binding.LowerBound + Binding.Size));
-}
-
-bool RootSignatureBindingValidation::checkURegBinding(
-    ResourceInfo::ResourceBinding Binding) {
-  return URegBindingsMap.overlaps(
-      combineUint32ToUint64(Binding.Space, Binding.LowerBound),
-      combineUint32ToUint64(Binding.Space,
-                            Binding.LowerBound + Binding.Size - 1));
-}
-
 PreservedAnalyses
 DXILPostOptimizationValidation::run(Module &M, ModuleAnalysisManager &MAM) {
   DXILResourceMap &DRM = MAM.getResult<DXILResourceAnalysis>(M);
diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h
index 58113bf9f93c7..0fa0285425d7e 100644
--- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h
+++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h
@@ -36,12 +36,13 @@ class RootSignatureBindingValidation {
   MapT CRegBindingsMap;
   MapT TRegBindingsMap;
   MapT URegBindingsMap;
+  MapT SamplersBindingsMap;
 
   void addRange(const dxbc::RTS0::v2::RootDescriptor &Desc, uint32_t Type) {
     assert((Type == llvm::to_underlying(dxbc::RootParameterType::CBV) ||
             Type == llvm::to_underlying(dxbc::RootParameterType::SRV) ||
             Type == llvm::to_underlying(dxbc::RootParameterType::UAV)) &&
-           "Invalid Type");
+           "Invalid Type in add Range Method");
 
     llvm::dxil::ResourceInfo::ResourceBinding Binding;
     Binding.LowerBound = Desc.ShaderRegister;
@@ -53,19 +54,20 @@ class RootSignatureBindingValidation {
     uint64_t HighRange = combineUint32ToUint64(
         Binding.Space, Binding.LowerBound + Binding.Size - 1);
 
+    assert(LowRange <= HighRange && "Invalid range configuration");
+
     switch (Type) {
 
     case llvm::to_underlying(dxbc::RootParameterType::CBV):
       CRegBindingsMap.insert(LowRange, HighRange, Binding);
-      return;
+      break;
     case llvm::to_underlying(dxbc::RootParameterType::SRV):
       TRegBindingsMap.insert(LowRange, HighRange, Binding);
-      return;
+      break;
     case llvm::to_underlying(dxbc::RootParameterType::UAV):
       URegBindingsMap.insert(LowRange, HighRange, Binding);
-      return;
+      break;
     }
-    llvm_unreachable("Invalid Type in add Range Method");
   }
 
   void addRange(const dxbc::RTS0::v2::DescriptorRange &Range) {
@@ -80,33 +82,59 @@ class RootSignatureBindingValidation {
     uint64_t HighRange = combineUint32ToUint64(
         Binding.Space, Binding.LowerBound + Binding.Size - 1);
 
+    assert(LowRange <= HighRange && "Invalid range configuration");
+
     switch (Range.RangeType) {
     case llvm::to_underlying(dxbc::DescriptorRangeType::CBV):
       CRegBindingsMap.insert(LowRange, HighRange, Binding);
-      return;
+      break;
     case llvm::to_underlying(dxbc::DescriptorRangeType::SRV):
       TRegBindingsMap.insert(LowRange, HighRange, Binding);
-      return;
+      break;
     case llvm::to_underlying(dxbc::DescriptorRangeType::UAV):
       URegBindingsMap.insert(LowRange, HighRange, Binding);
-      return;
+      break;
+    case llvm::to_underlying(dxbc::DescriptorRangeType::Sampler):
+      SamplersBindingsMap.insert(LowRange, HighRange, Binding);
+      break;
     }
-    llvm_unreachable("Invalid Type in add Range Method");
   }
 
 public:
   RootSignatureBindingValidation()
       : Allocator(), CRegBindingsMap(Allocator), TRegBindingsMap(Allocator),
-        URegBindingsMap(Allocator) {}
+        URegBindingsMap(Allocator), SamplersBindingsMap(Allocator) {}
 
   void addRsBindingInfo(mcdxbc::RootSignatureDesc &RSD,
                         dxbc::ShaderVisibility Visibility);
 
-  bool checkCregBinding(dxil::ResourceInfo::ResourceBinding Binding);
+  bool checkCRegBinding(dxil::ResourceInfo::ResourceBinding Binding) {
+    return CRegBindingsMap.overlaps(
+        combineUint32ToUint64(Binding.Space, Binding.LowerBound),
+        combineUint32ToUint64(Binding.Space,
+                              Binding.LowerBound + Binding.Size - 1));
+  }
 
-  bool checkTRegBinding(dxil::ResourceInfo::ResourceBinding Binding);
+  bool checkTRegBinding(dxil::ResourceInfo::ResourceBinding Binding) {
+    return TRegBindingsMap.overlaps(
+        combineUint32ToUint64(Binding.Space, Binding.LowerBound),
+        combineUint32ToUint64(Binding.Space,
+                              Binding.LowerBound + Binding.Size - 1));
+  }
 
-  bool checkURegBinding(dxil::ResourceInfo::ResourceBinding Binding);
+  bool checkURegBinding(dxil::ResourceInfo::ResourceBinding Binding) {
+    return URegBindingsMap.overlaps(
+        combineUint32ToUint64(Binding.Space, Binding.LowerBound),
+        combineUint32ToUint64(Binding.Space,
+                              Binding.LowerBound + Binding.Size - 1));
+  }
+
+  bool checkSamplerBinding(dxil::ResourceInfo::ResourceBinding Binding) {
+    return SamplersBindingsMap.overlaps(
+        combineUint32ToUint64(Binding.Space, Binding.LowerBound),
+        combineUint32ToUint64(Binding.Space,
+                              Binding.LowerBound + Binding.Size - 1));
+  }
 };
 
 class DXILPostOptimizationValidation
diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.cpp b/llvm/lib/Target/DirectX/DXILRootSignature.cpp
index 4094df160ef6f..2a68a4c324a09 100644
--- a/llvm/lib/Target/DirectX/DXILRootSignature.cpp
+++ b/llvm/lib/Target/DirectX/DXILRootSignature.cpp
@@ -635,8 +635,9 @@ PreservedAnalyses RootSignatureAnalysisPrinter::run(Module &M,
 
 //===----------------------------------------------------------------------===//
 bool RootSignatureAnalysisWrapper::runOnModule(Module &M) {
-  FuncToRsMap = std::make_unique<RootSignatureBindingInfo>(
-      RootSignatureBindingInfo(analyzeModule(M)));
+  if (!FuncToRsMap)
+    FuncToRsMap = std::make_unique<RootSignatureBindingInfo>(
+        RootSignatureBindingInfo(analyzeModule(M)));
   return false;
 }
 
diff --git a/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-DescriptorTable-AllValidFlagCombinationsV1.ll b/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-DescriptorTable-AllValidFlagCombinationsV1.ll
index 9d89dbdd9107b..053721de1eb1f 100644
--- a/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-DescriptorTable-AllValidFlagCombinationsV1.ll
+++ b/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-DescriptorTable-AllValidFlagCombinationsV1.ll
@@ -13,7 +13,7 @@ attributes #0 = { "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" }
 !2 = !{ ptr @main, !3, i32 1 } ; function, root signature
 !3 = !{ !5 } ; list of root signature elements
 !5 = !{ !"DescriptorTable", i32 0, !6, !7 }
-!6 = !{ !"Sampler", i32 0, i32 1, i32 0, i32 -1, i32 1 }
+!6 = !{ !"Sampler", i32 1, i32 1, i32 0, i32 -1, i32 1 }
 !7 = !{ !"UAV", i32 5, i32 1, i32 10, i32 5, i32 3 }
 
 
@@ -33,7 +33,7 @@ attributes #0 = { "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" }
 ; DXC-NEXT:             RangesOffset:    44
 ; DXC-NEXT:             Ranges:
 ; DXC-NEXT:               - RangeType:       3
-; DXC-NEXT:                 NumDescriptors:  0
+; DXC-NEXT:                 NumDescriptors:  1
 ; DXC-NEXT:                 BaseShaderRegister: 1
 ; DXC-NEXT:                 RegisterSpace:   0
 ; DXC-NEXT:                 OffsetInDescriptorsFromTableStart: 4294967295
diff --git a/llvm/test/CodeGen/DirectX/llc-pipeline.ll b/llvm/test/CodeGen/DirectX/llc-pipeline.ll
index 2b29fd30a7a56..8d75249dc6ecb 100644
--- a/llvm/test/CodeGen/DirectX/llc-pipeline.ll
+++ b/llvm/test/CodeGen/DirectX/llc-pipeline.ll
@@ -31,6 +31,7 @@
 ; 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 Prepare Module

>From 28350b2dfe2a896b2199260953c1d061550badba Mon Sep 17 00:00:00 2001
From: joaosaffran <joao.saffran at microsoft.com>
Date: Sat, 5 Jul 2025 00:35:07 +0000
Subject: [PATCH 14/29] fix issue

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

diff --git a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp
index 5c763c24a210a..6c8ae8eaaea77 100644
--- a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp
+++ b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp
@@ -160,11 +160,9 @@ void DXContainerGlobals::addRootSignature(Module &M,
 
   assert(MMI.EntryPropertyVec.size() == 1);
 
-  auto &RSA = getAnalysis<RootSignatureAnalysisWrapper>().getRSInfo();
   auto &RSA = getAnalysis<RootSignatureAnalysisWrapper>().getRSInfo();
   const Function *EntryFunction = MMI.EntryPropertyVec[0].Entry;
   const auto &RS = RSA.getDescForFunction(EntryFunction);
-  const auto &RS = RSA.getDescForFunction(EntryFunction);
 
   if (!RS)
     return;

>From 4fd2e0bfdda5f87a3204982aa01d8b158945eadf Mon Sep 17 00:00:00 2001
From: joaosaffran <joao.saffran at microsoft.com>
Date: Sat, 5 Jul 2025 00:37:12 +0000
Subject: [PATCH 15/29] sync parent

---
 llvm/lib/Target/DirectX/DXILRootSignature.h | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.h b/llvm/lib/Target/DirectX/DXILRootSignature.h
index ecfc577d1b97d..3832182277050 100644
--- a/llvm/lib/Target/DirectX/DXILRootSignature.h
+++ b/llvm/lib/Target/DirectX/DXILRootSignature.h
@@ -47,7 +47,7 @@ class RootSignatureBindingInfo {
   RootSignatureBindingInfo() = default;
   RootSignatureBindingInfo(
       SmallDenseMap<const Function *, mcdxbc::RootSignatureDesc> Map)
-      : FuncToRsMap(Map){};
+      : FuncToRsMap(Map) {};
 
   iterator find(const Function *F) { return FuncToRsMap.find(F); }
 
@@ -72,7 +72,10 @@ class RootSignatureAnalysis : public AnalysisInfoMixin<RootSignatureAnalysis> {
 
   using Result = RootSignatureBindingInfo;
 
-  RootSignatureBindingInfo run(Module &M, ModuleAnalysisManager &AM);
+  Result run(Module &M, ModuleAnalysisManager &AM);
+
+private:
+  std::unique_ptr<RootSignatureBindingInfo> AnalysisResult;
 };
 
 /// Wrapper pass for the legacy pass manager.

>From e25ee87104bbb7013da38761df2beee7c98f4a9a Mon Sep 17 00:00:00 2001
From: joaosaffran <joao.saffran at microsoft.com>
Date: Sat, 5 Jul 2025 00:39:18 +0000
Subject: [PATCH 16/29] sync parent

---
 llvm/lib/Target/DirectX/DXILRootSignature.cpp | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.cpp b/llvm/lib/Target/DirectX/DXILRootSignature.cpp
index 2a68a4c324a09..5a53ea8a3631b 100644
--- a/llvm/lib/Target/DirectX/DXILRootSignature.cpp
+++ b/llvm/lib/Target/DirectX/DXILRootSignature.cpp
@@ -554,9 +554,12 @@ analyzeModule(Module &M) {
 
 AnalysisKey RootSignatureAnalysis::Key;
 
-RootSignatureBindingInfo RootSignatureAnalysis::run(Module &M,
-                                                    ModuleAnalysisManager &AM) {
-  return RootSignatureBindingInfo(analyzeModule(M));
+RootSignatureAnalysis::Result
+RootSignatureAnalysis::run(Module &M, ModuleAnalysisManager &AM) {
+  if (!AnalysisResult)
+    AnalysisResult = std::make_unique<RootSignatureBindingInfo>(
+        RootSignatureBindingInfo(analyzeModule(M)));
+  return *AnalysisResult;
 }
 
 //===----------------------------------------------------------------------===//

>From 881dd365da77a817dd2be4f2aed2426b15a38d24 Mon Sep 17 00:00:00 2001
From: joaosaffran <joao.saffran at microsoft.com>
Date: Mon, 7 Jul 2025 20:14:49 +0000
Subject: [PATCH 17/29] address comments

---
 llvm/lib/Target/DirectX/DXContainerGlobals.cpp | 3 ++-
 llvm/lib/Target/DirectX/DXILRootSignature.h    | 4 +---
 2 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp
index 6c8ae8eaaea77..b6e8ce7d78b23 100644
--- a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp
+++ b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp
@@ -162,7 +162,8 @@ void DXContainerGlobals::addRootSignature(Module &M,
 
   auto &RSA = getAnalysis<RootSignatureAnalysisWrapper>().getRSInfo();
   const Function *EntryFunction = MMI.EntryPropertyVec[0].Entry;
-  const auto &RS = RSA.getDescForFunction(EntryFunction);
+  const std::optional<mcdxbc::RootSignatureDesc> &RS =
+      RSA.getDescForFunction(EntryFunction);
 
   if (!RS)
     return;
diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.h b/llvm/lib/Target/DirectX/DXILRootSignature.h
index 3832182277050..e975ceb22ea54 100644
--- a/llvm/lib/Target/DirectX/DXILRootSignature.h
+++ b/llvm/lib/Target/DirectX/DXILRootSignature.h
@@ -47,7 +47,7 @@ class RootSignatureBindingInfo {
   RootSignatureBindingInfo() = default;
   RootSignatureBindingInfo(
       SmallDenseMap<const Function *, mcdxbc::RootSignatureDesc> Map)
-      : FuncToRsMap(Map) {};
+      : FuncToRsMap(Map){};
 
   iterator find(const Function *F) { return FuncToRsMap.find(F); }
 
@@ -88,8 +88,6 @@ class RootSignatureAnalysisWrapper : public ModulePass {
 
 public:
   static char ID;
-  using Result = RootSignatureBindingInfo;
-
   RootSignatureAnalysisWrapper() : ModulePass(ID) {}
 
   RootSignatureBindingInfo &getRSInfo() { return *FuncToRsMap; }

>From c16f15b4cd469a3f6efc2e4b0e098190d7fd0787 Mon Sep 17 00:00:00 2001
From: joaosaffran <joao.saffran at microsoft.com>
Date: Tue, 8 Jul 2025 17:00:28 +0000
Subject: [PATCH 18/29] fix test

---
 clang/test/SemaHLSL/RootSignature-Validation.hlsl | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/clang/test/SemaHLSL/RootSignature-Validation.hlsl b/clang/test/SemaHLSL/RootSignature-Validation.hlsl
index 5a7f5baf00619..c4ea897c6f490 100644
--- a/clang/test/SemaHLSL/RootSignature-Validation.hlsl
+++ b/clang/test/SemaHLSL/RootSignature-Validation.hlsl
@@ -16,11 +16,11 @@ cbuffer CB : register(b3, space1) {
 StructuredBuffer<int> In : register(t0, space0);
 RWStructuredBuffer<int> Out : register(u0);
 
-RWBuffer<float> UAV : register(u4294967294);
+RWStructuredBuffer<float> UAV : register(u4294967294);
 
-RWBuffer<float> UAV1 : register(u2), UAV2 : register(u4);
+RWStructuredBuffer<float> UAV1 : register(u2), UAV2 : register(u4);
 
-RWBuffer<float> UAV3 : register(space0);
+RWStructuredBuffer<float> UAV3 : register(space0);
 
 
 

>From c7d5be77bd7c5421aca2e105dbab84854e335703 Mon Sep 17 00:00:00 2001
From: joaosaffran <joao.saffran at microsoft.com>
Date: Tue, 8 Jul 2025 17:18:15 +0000
Subject: [PATCH 19/29] format

---
 llvm/lib/Target/DirectX/DXILRootSignature.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.h b/llvm/lib/Target/DirectX/DXILRootSignature.h
index e975ceb22ea54..41c63939f93a6 100644
--- a/llvm/lib/Target/DirectX/DXILRootSignature.h
+++ b/llvm/lib/Target/DirectX/DXILRootSignature.h
@@ -47,7 +47,7 @@ class RootSignatureBindingInfo {
   RootSignatureBindingInfo() = default;
   RootSignatureBindingInfo(
       SmallDenseMap<const Function *, mcdxbc::RootSignatureDesc> Map)
-      : FuncToRsMap(Map){};
+      : FuncToRsMap(Map) {};
 
   iterator find(const Function *F) { return FuncToRsMap.find(F); }
 

>From cc5afaefcafe97e92547c42c43c8747c0c7981fe Mon Sep 17 00:00:00 2001
From: joaosaffran <joao.saffran at microsoft.com>
Date: Tue, 8 Jul 2025 19:02:00 +0000
Subject: [PATCH 20/29] address changes

---
 llvm/lib/Target/DirectX/DXILRootSignature.cpp | 12 ++++--------
 llvm/lib/Target/DirectX/DXILRootSignature.h   |  3 ---
 2 files changed, 4 insertions(+), 11 deletions(-)

diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.cpp b/llvm/lib/Target/DirectX/DXILRootSignature.cpp
index 5a53ea8a3631b..3848ad63dc468 100644
--- a/llvm/lib/Target/DirectX/DXILRootSignature.cpp
+++ b/llvm/lib/Target/DirectX/DXILRootSignature.cpp
@@ -556,10 +556,7 @@ AnalysisKey RootSignatureAnalysis::Key;
 
 RootSignatureAnalysis::Result
 RootSignatureAnalysis::run(Module &M, ModuleAnalysisManager &AM) {
-  if (!AnalysisResult)
-    AnalysisResult = std::make_unique<RootSignatureBindingInfo>(
-        RootSignatureBindingInfo(analyzeModule(M)));
-  return *AnalysisResult;
+  return RootSignatureBindingInfo(analyzeModule(M));
 }
 
 //===----------------------------------------------------------------------===//
@@ -638,15 +635,14 @@ PreservedAnalyses RootSignatureAnalysisPrinter::run(Module &M,
 
 //===----------------------------------------------------------------------===//
 bool RootSignatureAnalysisWrapper::runOnModule(Module &M) {
-  if (!FuncToRsMap)
-    FuncToRsMap = std::make_unique<RootSignatureBindingInfo>(
-        RootSignatureBindingInfo(analyzeModule(M)));
+  FuncToRsMap = std::make_unique<RootSignatureBindingInfo>(
+      RootSignatureBindingInfo(analyzeModule(M)));
   return false;
 }
 
 void RootSignatureAnalysisWrapper::getAnalysisUsage(AnalysisUsage &AU) const {
   AU.setPreservesAll();
-  AU.addRequired<DXILMetadataAnalysisWrapperPass>();
+  AU.addPreserved<DXILMetadataAnalysisWrapperPass>();
 }
 
 char RootSignatureAnalysisWrapper::ID = 0;
diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.h b/llvm/lib/Target/DirectX/DXILRootSignature.h
index 41c63939f93a6..07dbd51bed391 100644
--- a/llvm/lib/Target/DirectX/DXILRootSignature.h
+++ b/llvm/lib/Target/DirectX/DXILRootSignature.h
@@ -73,9 +73,6 @@ class RootSignatureAnalysis : public AnalysisInfoMixin<RootSignatureAnalysis> {
   using Result = RootSignatureBindingInfo;
 
   Result run(Module &M, ModuleAnalysisManager &AM);
-
-private:
-  std::unique_ptr<RootSignatureBindingInfo> AnalysisResult;
 };
 
 /// Wrapper pass for the legacy pass manager.

>From 571a0ef25df4ffffe56cdc7d7274ebe9d23996be Mon Sep 17 00:00:00 2001
From: joaosaffran <joao.saffran at microsoft.com>
Date: Tue, 8 Jul 2025 20:31:43 +0000
Subject: [PATCH 21/29] fix tests

---
 .../RootSignature-Validation-Fail.hlsl        |  35 ----
 .../SemaHLSL/RootSignature-Validation.hlsl    |  33 ----
 .../DirectX/rootsignature-validation-fail.ll  | 160 ++++++++++++++++++
 .../DirectX/rootsignature-validation.ll       | 149 ++++++++++++++++
 4 files changed, 309 insertions(+), 68 deletions(-)
 delete mode 100644 clang/test/SemaHLSL/RootSignature-Validation-Fail.hlsl
 delete mode 100644 clang/test/SemaHLSL/RootSignature-Validation.hlsl
 create mode 100644 llvm/test/CodeGen/DirectX/rootsignature-validation-fail.ll
 create mode 100644 llvm/test/CodeGen/DirectX/rootsignature-validation.ll

diff --git a/clang/test/SemaHLSL/RootSignature-Validation-Fail.hlsl b/clang/test/SemaHLSL/RootSignature-Validation-Fail.hlsl
deleted file mode 100644
index b590ed67e7085..0000000000000
--- a/clang/test/SemaHLSL/RootSignature-Validation-Fail.hlsl
+++ /dev/null
@@ -1,35 +0,0 @@
-// RUN: not %clang_dxc -T cs_6_6 -E CSMain %s 2>&1 | FileCheck %s
-
-// CHECK: error: register cbuffer (space=665, register=3) is not defined in Root Signature
-// CHECK: error: register srv (space=0, register=0) is not defined in Root Signature
-// CHECK: error: register uav (space=0, register=4294967295) is not defined in Root Signature
-
-
-#define 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)"
-
-cbuffer CB : register(b3, space665) {
-  float a;
-}
-
-StructuredBuffer<int> In : register(t0, space0);
-RWStructuredBuffer<int> Out : register(u0);
-
-RWBuffer<float> UAV : register(u4294967295);
-
-RWBuffer<float> UAV1 : register(u2), UAV2 : register(u4);
-
-RWBuffer<float> UAV3 : register(space0);
-
-
-
-// Compute Shader for UAV testing
-[numthreads(8, 8, 1)]
-[RootSignature(ROOT_SIGNATURE)]
-void CSMain(uint id : SV_GroupID)
-{
-    Out[0] = a + id + In[0] + UAV[0] + UAV1[0] + UAV3[0];
-}
diff --git a/clang/test/SemaHLSL/RootSignature-Validation.hlsl b/clang/test/SemaHLSL/RootSignature-Validation.hlsl
deleted file mode 100644
index c4ea897c6f490..0000000000000
--- a/clang/test/SemaHLSL/RootSignature-Validation.hlsl
+++ /dev/null
@@ -1,33 +0,0 @@
-// RUN: %clang_dxc -T cs_6_6 -E CSMain %s 2>&1 
-
-// expected-no-diagnostics
-
-
-#define 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)"
-
-cbuffer CB : register(b3, space1) {
-  float a;
-}
-
-StructuredBuffer<int> In : register(t0, space0);
-RWStructuredBuffer<int> Out : register(u0);
-
-RWStructuredBuffer<float> UAV : register(u4294967294);
-
-RWStructuredBuffer<float> UAV1 : register(u2), UAV2 : register(u4);
-
-RWStructuredBuffer<float> UAV3 : register(space0);
-
-
-
-// Compute Shader for UAV testing
-[numthreads(8, 8, 1)]
-[RootSignature(ROOT_SIGNATURE)]
-void CSMain(uint id : SV_GroupID)
-{
-    Out[0] = a + id + In[0] + UAV[0] + UAV1[0] + UAV3[0];
-}
diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail.ll
new file mode 100644
index 0000000000000..54802c9e7ed22
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail.ll
@@ -0,0 +1,160 @@
+; RUN: not opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 
+
+; CHECK: error: register cbuffer (space=665, register=3) is not defined in Root Signature
+; CHECK: error: register srv (space=0, register=0) is not defined in Root Signature
+; CHECK: error: register uav (space=0, register=4294967295) is not defined in Root Signature
+
+;
+; Resource Bindings:
+;
+; Name                                 Type  Format         Dim      ID      HLSL Bind     Count
+; ------------------------------ ---------- ------- ----------- ------- -------------- ---------
+; In                                texture  struct         r/o      T0             t0         1
+; Out                                   UAV  struct         r/w      U0             u0         1
+; UAV3                                  UAV     f32         buf      U1             u1         1
+; UAV1                                  UAV     f32         buf      U2             u2         1
+; UAV                                   UAV     f32         buf      U3    u4294967295         1
+; CB                                cbuffer      NA          NA     CB0   cb3,space665         1
+;
+; ModuleID = '../clang/test/SemaHLSL/RootSignature-Validation-Fail.hlsl'
+target datalayout = "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:32-f64:64-n8:16:32:64"
+target triple = "dxilv1.5-unknown-shadermodel6.5-compute"
+
+%__cblayout_CB = type <{ float }>
+%"StructuredBuffer<int32_t>" = type { i32 }
+%"RWStructuredBuffer<int32_t>" = type { i32 }
+%"RWBuffer<float>" = type { float }
+%CBuffer.CB = type { float }
+
+ at CB.cb = local_unnamed_addr global target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 4, 0)) poison
+ at CB.str = private unnamed_addr constant [3 x i8] c"CB\00", align 1
+ at .str = private unnamed_addr constant [3 x i8] c"In\00", align 1
+ at .str.2 = private unnamed_addr constant [4 x i8] c"Out\00", align 1
+ at .str.4 = private unnamed_addr constant [4 x i8] c"UAV\00", align 1
+ at .str.6 = private unnamed_addr constant [5 x i8] c"UAV1\00", align 1
+ at .str.10 = private unnamed_addr constant [5 x i8] c"UAV3\00", align 1
+ at In = external constant %"StructuredBuffer<int32_t>"
+ at Out = external constant %"RWStructuredBuffer<int32_t>"
+ at UAV3 = external constant %"RWBuffer<float>"
+ at UAV1 = external constant %"RWBuffer<float>"
+ at UAV = external constant %"RWBuffer<float>"
+ at CB = external constant %CBuffer.CB
+
+; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(none)
+declare target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 4, 0)) @llvm.dx.resource.handlefrombinding.tdx.CBuffer_tdx.Layout_s___cblayout_CBs_4_0tt(i32, i32, i32, i32, i1, ptr) #0
+
+; Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(readwrite, inaccessiblemem: none)
+define void @CSMain() local_unnamed_addr #1 {
+entry:
+  %CB.cb_h.i.i = tail call target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 4, 0)) @llvm.dx.resource.handlefrombinding.tdx.CBuffer_tdx.Layout_s___cblayout_CBs_4_0tt(i32 665, i32 3, i32 1, i32 0, i1 false, ptr nonnull @CB.str)
+  store target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 4, 0)) %CB.cb_h.i.i, ptr @CB.cb, align 4
+  %0 = 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 @.str)
+  %1 = tail call target("dx.RawBuffer", i32, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i32_1_0t(i32 0, i32 0, i32 1, i32 0, i1 false, ptr nonnull @.str.2)
+  %2 = tail call target("dx.TypedBuffer", float, 1, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0_0t(i32 0, i32 -1, i32 1, i32 0, i1 false, ptr nonnull @.str.4)
+  %3 = tail call target("dx.TypedBuffer", float, 1, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0_0t(i32 0, i32 2, i32 1, i32 0, i1 false, ptr nonnull @.str.6)
+  %4 = call target("dx.TypedBuffer", float, 1, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0_0t(i32 0, i32 1, i32 1, i32 0, i1 false, ptr @.str.10)
+  %5 = tail call i32 @llvm.dx.group.id(i32 0)
+  %6 = call { float, float, float, float } @llvm.dx.resource.load.cbufferrow.4.f32.f32.f32.f32.tdx.CBuffer_tdx.Layout_s___cblayout_CBs_4_0tt(target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 4, 0)) %CB.cb_h.i.i, i32 0)
+  %7 = extractvalue { float, float, float, float } %6, 0
+  %conv.i = uitofp i32 %5 to float
+  %add.i = fadd reassoc nnan ninf nsz arcp afn float %7, %conv.i
+  %8 = call { i32, i1 } @llvm.dx.resource.load.rawbuffer.i32.tdx.RawBuffer_i32_0_0t(target("dx.RawBuffer", i32, 0, 0) %0, i32 0, i32 0)
+  %9 = extractvalue { i32, i1 } %8, 0
+  %conv1.i = sitofp i32 %9 to float
+  %add2.i = fadd reassoc nnan ninf nsz arcp afn float %add.i, %conv1.i
+  %10 = call { float, i1 } @llvm.dx.resource.load.typedbuffer.f32.tdx.TypedBuffer_f32_1_0_0t(target("dx.TypedBuffer", float, 1, 0, 0) %2, i32 0)
+  %11 = extractvalue { float, i1 } %10, 0
+  %add4.i = fadd reassoc nnan ninf nsz arcp afn float %add2.i, %11
+  %12 = call { float, i1 } @llvm.dx.resource.load.typedbuffer.f32.tdx.TypedBuffer_f32_1_0_0t(target("dx.TypedBuffer", float, 1, 0, 0) %3, i32 0)
+  %13 = extractvalue { float, i1 } %12, 0
+  %add6.i = fadd reassoc nnan ninf nsz arcp afn float %add4.i, %13
+  %14 = call { float, i1 } @llvm.dx.resource.load.typedbuffer.f32.tdx.TypedBuffer_f32_1_0_0t(target("dx.TypedBuffer", float, 1, 0, 0) %4, i32 0)
+  %15 = extractvalue { float, i1 } %14, 0
+  %add8.i = fadd reassoc nnan ninf nsz arcp afn float %add6.i, %15
+  %conv9.i = fptosi float %add8.i to i32
+  call void @llvm.dx.resource.store.rawbuffer.tdx.RawBuffer_i32_1_0t.i32(target("dx.RawBuffer", i32, 1, 0) %1, i32 0, i32 0, i32 %conv9.i)
+  ret void
+}
+
+; Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
+declare i32 @llvm.dx.group.id(i32) #2
+
+; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(none)
+declare target("dx.RawBuffer", i32, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i32_0_0t(i32, i32, i32, i32, i1, ptr) #0
+
+; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(none)
+declare target("dx.RawBuffer", i32, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i32_1_0t(i32, i32, i32, i32, i1, ptr) #0
+
+; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(none)
+declare target("dx.TypedBuffer", float, 1, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0_0t(i32, i32, i32, i32, i1, ptr) #0
+
+; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(none)
+declare ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_i32_1_0t(target("dx.RawBuffer", i32, 1, 0), i32) #0
+
+; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(none)
+declare ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_i32_0_0t(target("dx.RawBuffer", i32, 0, 0), i32) #0
+
+; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(none)
+declare ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_f32_1_0_0t(target("dx.TypedBuffer", float, 1, 0, 0), i32) #0
+
+; Function Attrs: nocallback nofree nosync nounwind willreturn memory(read)
+declare { i32, i1 } @llvm.dx.resource.load.rawbuffer.i32.tdx.RawBuffer_i32_0_0t(target("dx.RawBuffer", i32, 0, 0), i32, i32) #3
+
+; Function Attrs: nocallback nofree nosync nounwind willreturn memory(read)
+declare { float, i1 } @llvm.dx.resource.load.typedbuffer.f32.tdx.TypedBuffer_f32_1_0_0t(target("dx.TypedBuffer", float, 1, 0, 0), i32) #3
+
+; Function Attrs: nocallback nofree nosync nounwind willreturn memory(write)
+declare void @llvm.dx.resource.store.rawbuffer.tdx.RawBuffer_i32_1_0t.i32(target("dx.RawBuffer", i32, 1, 0), i32, i32, i32) #4
+
+; Function Attrs: nocallback nofree nosync nounwind willreturn memory(read)
+declare { float, float, float, float } @llvm.dx.resource.load.cbufferrow.4.f32.f32.f32.f32.tdx.CBuffer_tdx.Layout_s___cblayout_CBs_4_0tt(target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 4, 0)), i32) #3
+
+; uselistorder directives
+uselistorder ptr @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0_0t, { 2, 1, 0 }
+uselistorder ptr @llvm.dx.resource.load.typedbuffer.f32.tdx.TypedBuffer_f32_1_0_0t, { 2, 1, 0 }
+
+attributes #0 = { mustprogress nocallback nofree nosync nounwind willreturn memory(none) }
+attributes #1 = { mustprogress nofree noinline norecurse nosync nounwind willreturn memory(readwrite, inaccessiblemem: none) "approx-func-fp-math"="false" "frame-pointer"="all" "hlsl.numthreads"="8,8,1" "hlsl.shader"="compute" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
+attributes #2 = { mustprogress nofree nosync nounwind willreturn memory(none) }
+attributes #3 = { nocallback nofree nosync nounwind willreturn memory(read) }
+attributes #4 = { nocallback nofree nosync nounwind willreturn memory(write) }
+
+!dx.rootsignatures = !{!0}
+!llvm.module.flags = !{!9, !10}
+!dx.valver = !{!11}
+!llvm.ident = !{!12}
+!dx.shaderModel = !{!13}
+!dx.version = !{!14}
+!dx.resources = !{!15}
+!dx.entryPoints = !{!27}
+
+!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}
+!9 = !{i32 1, !"wchar_size", i32 4}
+!10 = !{i32 7, !"frame-pointer", i32 2}
+!11 = !{i32 1, i32 8}
+!12 = !{!"clang version 21.0.0git (https://github.com/joaosaffran/llvm-project.git c16f15b4cd469a3f6efc2e4b0e098190d7fd0787)"}
+!13 = !{!"cs", i32 6, i32 5}
+!14 = !{i32 1, i32 5}
+!15 = !{!16, !19, !25, null}
+!16 = !{!17}
+!17 = !{i32 0, ptr @In, !"In", i32 0, i32 0, i32 1, i32 12, i32 0, !18}
+!18 = !{i32 1, i32 4}
+!19 = !{!20, !21, !23, !24}
+!20 = !{i32 0, ptr @Out, !"Out", i32 0, i32 0, i32 1, i32 12, i1 false, i1 false, i1 false, !18}
+!21 = !{i32 1, ptr @UAV3, !"UAV3", i32 0, i32 1, i32 1, i32 10, i1 false, i1 false, i1 false, !22}
+!22 = !{i32 0, i32 9}
+!23 = !{i32 2, ptr @UAV1, !"UAV1", i32 0, i32 2, i32 1, i32 10, i1 false, i1 false, i1 false, !22}
+!24 = !{i32 3, ptr @UAV, !"UAV", i32 0, i32 -1, i32 1, i32 10, i1 false, i1 false, i1 false, !22}
+!25 = !{!26}
+!26 = !{i32 0, ptr @CB, !"CB", i32 665, i32 3, i32 1, i32 4, null}
+!27 = !{ptr @CSMain, !"CSMain", null, !15, !28}
+!28 = !{i32 0, i64 16, i32 4, !29}
+!29 = !{i32 8, i32 8, i32 1}
diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation.ll
new file mode 100644
index 0000000000000..eaf8512c284a7
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/rootsignature-validation.ll
@@ -0,0 +1,149 @@
+; RUN: opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 
+; expected-no-diagnostics
+
+;
+; Resource Bindings:
+;
+; Name                                 Type  Format         Dim      ID      HLSL Bind     Count
+; ------------------------------ ---------- ------- ----------- ------- -------------- ---------
+; In                                texture  struct         r/o      T0             t0         1
+; Out                                   UAV  struct         r/w      U0             u0         1
+; UAV3                                  UAV  struct         r/w      U1             u1         1
+; UAV1                                  UAV  struct         r/w      U2             u2         1
+; UAV                                   UAV  struct         r/w      U3    u4294967294         1
+; CB                                cbuffer      NA          NA     CB0     cb3,space1         1
+;
+; ModuleID = '../clang/test/SemaHLSL/RootSignature-Validation.hlsl'
+target datalayout = "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:32-f64:64-n8:16:32:64"
+target triple = "dxilv1.5-unknown-shadermodel6.5-compute"
+
+%__cblayout_CB = type <{ float }>
+%"StructuredBuffer<int32_t>" = type { i32 }
+%"RWStructuredBuffer<int32_t>" = type { i32 }
+%"RWStructuredBuffer<float>" = type { float }
+%CBuffer.CB = type { float }
+
+ at CB.cb = local_unnamed_addr global target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 4, 0)) poison
+ at CB.str = private unnamed_addr constant [3 x i8] c"CB\00", align 1
+ at .str = private unnamed_addr constant [3 x i8] c"In\00", align 1
+ at .str.2 = private unnamed_addr constant [4 x i8] c"Out\00", align 1
+ at .str.4 = private unnamed_addr constant [4 x i8] c"UAV\00", align 1
+ at .str.6 = private unnamed_addr constant [5 x i8] c"UAV1\00", align 1
+ at .str.10 = private unnamed_addr constant [5 x i8] c"UAV3\00", align 1
+ at In = external constant %"StructuredBuffer<int32_t>"
+ at Out = external constant %"RWStructuredBuffer<int32_t>"
+ at UAV3 = external constant %"RWStructuredBuffer<float>"
+ at UAV1 = external constant %"RWStructuredBuffer<float>"
+ at UAV = external constant %"RWStructuredBuffer<float>"
+ at CB = external constant %CBuffer.CB
+
+; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(none)
+declare target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 4, 0)) @llvm.dx.resource.handlefrombinding.tdx.CBuffer_tdx.Layout_s___cblayout_CBs_4_0tt(i32, i32, i32, i32, i1, ptr) #0
+
+; Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(readwrite, inaccessiblemem: none)
+define void @CSMain() local_unnamed_addr #1 {
+entry:
+  %CB.cb_h.i.i = tail call target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 4, 0)) @llvm.dx.resource.handlefrombinding.tdx.CBuffer_tdx.Layout_s___cblayout_CBs_4_0tt(i32 1, i32 3, i32 1, i32 0, i1 false, ptr nonnull @CB.str)
+  store target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 4, 0)) %CB.cb_h.i.i, ptr @CB.cb, align 4
+  %0 = 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 @.str)
+  %1 = tail call target("dx.RawBuffer", i32, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i32_1_0t(i32 0, i32 0, i32 1, i32 0, i1 false, ptr nonnull @.str.2)
+  %2 = tail call target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_f32_1_0t(i32 0, i32 -2, i32 1, i32 0, i1 false, ptr nonnull @.str.4)
+  %3 = tail call target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_f32_1_0t(i32 0, i32 2, i32 1, i32 0, i1 false, ptr nonnull @.str.6)
+  %4 = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_f32_1_0t(i32 0, i32 1, i32 1, i32 0, i1 false, ptr @.str.10)
+  %5 = call { float, float, float, float } @llvm.dx.resource.load.cbufferrow.4.f32.f32.f32.f32.tdx.CBuffer_tdx.Layout_s___cblayout_CBs_4_0tt(target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 4, 0)) %CB.cb_h.i.i, i32 0)
+  %6 = extractvalue { float, float, float, float } %5, 0
+  %7 = call { i32, i1 } @llvm.dx.resource.load.rawbuffer.i32.tdx.RawBuffer_i32_0_0t(target("dx.RawBuffer", i32, 0, 0) %0, i32 0, i32 0)
+  %8 = extractvalue { i32, i1 } %7, 0
+  %conv.i = sitofp i32 %8 to float
+  %add.i = fadd reassoc nnan ninf nsz arcp afn float %6, %conv.i
+  %9 = call { float, i1 } @llvm.dx.resource.load.rawbuffer.f32.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %2, i32 0, i32 0)
+  %10 = extractvalue { float, i1 } %9, 0
+  %add2.i = fadd reassoc nnan ninf nsz arcp afn float %add.i, %10
+  %11 = call { float, i1 } @llvm.dx.resource.load.rawbuffer.f32.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %3, i32 0, i32 0)
+  %12 = extractvalue { float, i1 } %11, 0
+  %add4.i = fadd reassoc nnan ninf nsz arcp afn float %add2.i, %12
+  %13 = call { float, i1 } @llvm.dx.resource.load.rawbuffer.f32.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %4, i32 0, i32 0)
+  %14 = extractvalue { float, i1 } %13, 0
+  %add6.i = fadd reassoc nnan ninf nsz arcp afn float %add4.i, %14
+  %conv7.i = fptosi float %add6.i to i32
+  call void @llvm.dx.resource.store.rawbuffer.tdx.RawBuffer_i32_1_0t.i32(target("dx.RawBuffer", i32, 1, 0) %1, i32 0, i32 0, i32 %conv7.i)
+  ret void
+}
+
+; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(none)
+declare target("dx.RawBuffer", i32, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i32_0_0t(i32, i32, i32, i32, i1, ptr) #0
+
+; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(none)
+declare target("dx.RawBuffer", i32, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i32_1_0t(i32, i32, i32, i32, i1, ptr) #0
+
+; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(none)
+declare target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_f32_1_0t(i32, i32, i32, i32, i1, ptr) #0
+
+; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(none)
+declare ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_i32_1_0t(target("dx.RawBuffer", i32, 1, 0), i32) #0
+
+; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(none)
+declare ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_i32_0_0t(target("dx.RawBuffer", i32, 0, 0), i32) #0
+
+; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(none)
+declare ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0), i32) #0
+
+; Function Attrs: nocallback nofree nosync nounwind willreturn memory(read)
+declare { i32, i1 } @llvm.dx.resource.load.rawbuffer.i32.tdx.RawBuffer_i32_0_0t(target("dx.RawBuffer", i32, 0, 0), i32, i32) #2
+
+; Function Attrs: nocallback nofree nosync nounwind willreturn memory(read)
+declare { float, i1 } @llvm.dx.resource.load.rawbuffer.f32.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0), i32, i32) #2
+
+; Function Attrs: nocallback nofree nosync nounwind willreturn memory(write)
+declare void @llvm.dx.resource.store.rawbuffer.tdx.RawBuffer_i32_1_0t.i32(target("dx.RawBuffer", i32, 1, 0), i32, i32, i32) #3
+
+; Function Attrs: nocallback nofree nosync nounwind willreturn memory(read)
+declare { float, float, float, float } @llvm.dx.resource.load.cbufferrow.4.f32.f32.f32.f32.tdx.CBuffer_tdx.Layout_s___cblayout_CBs_4_0tt(target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 4, 0)), i32) #2
+
+; uselistorder directives
+uselistorder ptr @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_f32_1_0t, { 2, 1, 0 }
+uselistorder ptr @llvm.dx.resource.load.rawbuffer.f32.tdx.RawBuffer_f32_1_0t, { 2, 1, 0 }
+
+attributes #0 = { mustprogress nocallback nofree nosync nounwind willreturn memory(none) }
+attributes #1 = { mustprogress nofree noinline norecurse nosync nounwind willreturn memory(readwrite, inaccessiblemem: none) "approx-func-fp-math"="false" "frame-pointer"="all" "hlsl.numthreads"="8,8,1" "hlsl.shader"="compute" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
+attributes #2 = { nocallback nofree nosync nounwind willreturn memory(read) }
+attributes #3 = { nocallback nofree nosync nounwind willreturn memory(write) }
+
+!dx.rootsignatures = !{!0}
+!llvm.module.flags = !{!9, !10}
+!dx.valver = !{!11}
+!llvm.ident = !{!12}
+!dx.shaderModel = !{!13}
+!dx.version = !{!14}
+!dx.resources = !{!15}
+!dx.entryPoints = !{!26}
+
+!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 4}
+!5 = !{!"DescriptorTable", i32 1, !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}
+!9 = !{i32 1, !"wchar_size", i32 4}
+!10 = !{i32 7, !"frame-pointer", i32 2}
+!11 = !{i32 1, i32 8}
+!12 = !{!"clang version 21.0.0git (https://github.com/joaosaffran/llvm-project.git c16f15b4cd469a3f6efc2e4b0e098190d7fd0787)"}
+!13 = !{!"cs", i32 6, i32 5}
+!14 = !{i32 1, i32 5}
+!15 = !{!16, !19, !24, null}
+!16 = !{!17}
+!17 = !{i32 0, ptr @In, !"In", i32 0, i32 0, i32 1, i32 12, i32 0, !18}
+!18 = !{i32 1, i32 4}
+!19 = !{!20, !21, !22, !23}
+!20 = !{i32 0, ptr @Out, !"Out", i32 0, i32 0, i32 1, i32 12, i1 false, i1 false, i1 false, !18}
+!21 = !{i32 1, ptr @UAV3, !"UAV3", i32 0, i32 1, i32 1, i32 12, i1 false, i1 false, i1 false, !18}
+!22 = !{i32 2, ptr @UAV1, !"UAV1", i32 0, i32 2, i32 1, i32 12, i1 false, i1 false, i1 false, !18}
+!23 = !{i32 3, ptr @UAV, !"UAV", i32 0, i32 -2, i32 1, i32 12, i1 false, i1 false, i1 false, !18}
+!24 = !{!25}
+!25 = !{i32 0, ptr @CB, !"CB", i32 1, i32 3, i32 1, i32 4, null}
+!26 = !{ptr @CSMain, !"CSMain", null, !15, !27}
+!27 = !{i32 0, i64 16, i32 4, !28}
+!28 = !{i32 8, i32 8, i32 1}

>From e0bc8623dba624c1d3b01bd73102b258df5cc006 Mon Sep 17 00:00:00 2001
From: joaosaffran <joao.saffran at microsoft.com>
Date: Tue, 8 Jul 2025 21:18:45 +0000
Subject: [PATCH 22/29] add preserved

---
 llvm/lib/Target/DirectX/DXContainerGlobals.cpp | 2 +-
 llvm/test/CodeGen/DirectX/llc-pipeline.ll      | 1 -
 2 files changed, 1 insertion(+), 2 deletions(-)

diff --git a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp
index b6e8ce7d78b23..a6dfc11c9c44c 100644
--- a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp
+++ b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp
@@ -62,10 +62,10 @@ class DXContainerGlobals : public llvm::ModulePass {
   void getAnalysisUsage(AnalysisUsage &AU) const override {
     AU.setPreservesAll();
     AU.addRequired<ShaderFlagsAnalysisWrapper>();
-    AU.addRequired<RootSignatureAnalysisWrapper>();
     AU.addRequired<DXILMetadataAnalysisWrapperPass>();
     AU.addRequired<DXILResourceTypeWrapperPass>();
     AU.addRequired<DXILResourceWrapperPass>();
+    AU.addPreserved<RootSignatureAnalysisWrapper>();
   }
 };
 
diff --git a/llvm/test/CodeGen/DirectX/llc-pipeline.ll b/llvm/test/CodeGen/DirectX/llc-pipeline.ll
index 8d75249dc6ecb..e8612f4213539 100644
--- a/llvm/test/CodeGen/DirectX/llc-pipeline.ll
+++ b/llvm/test/CodeGen/DirectX/llc-pipeline.ll
@@ -40,7 +40,6 @@
 ; CHECK-ASM-NEXT: Print Module IR
 
 ; CHECK-OBJ-NEXT: DXIL Embedder
-; CHECK-OBJ-NEXT: DXIL Root Signature Analysis
 ; CHECK-OBJ-NEXT: DXContainer Global Emitter
 ; CHECK-OBJ-NEXT: FunctionPass Manager
 ; CHECK-OBJ-NEXT:   Lazy Machine Block Frequency Analysis

>From b5a0b32a43b04f9f20efb879a7b8644e937cfaf7 Mon Sep 17 00:00:00 2001
From: joaosaffran <joao.saffran at microsoft.com>
Date: Thu, 10 Jul 2025 17:46:07 +0000
Subject: [PATCH 23/29] addressing comments

---
 llvm/lib/Target/DirectX/DXILRootSignature.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.h b/llvm/lib/Target/DirectX/DXILRootSignature.h
index 07dbd51bed391..ccffa3fd0a3e2 100644
--- a/llvm/lib/Target/DirectX/DXILRootSignature.h
+++ b/llvm/lib/Target/DirectX/DXILRootSignature.h
@@ -106,4 +106,4 @@ class RootSignatureAnalysisPrinter
 
 } // namespace dxil
 } // namespace llvm
-#endif
+#endif // LLVM_LIB_TARGET_DIRECTX_DXILROOTSIGNATURE_H

>From 5ccb842c9ba0cf558a30361793f8c33996c5f526 Mon Sep 17 00:00:00 2001
From: joaosaffran <joao.saffran at microsoft.com>
Date: Fri, 11 Jul 2025 06:27:26 +0000
Subject: [PATCH 24/29] updating

---
 .../lib/Target/DirectX/DXContainerGlobals.cpp |   2 +-
 llvm/lib/Target/DirectX/DXILOpLowering.cpp    |   2 +
 .../DXILPostOptimizationValidation.cpp        | 160 +++++++++++-------
 .../DirectX/DXILPostOptimizationValidation.h  | 149 +++++-----------
 llvm/lib/Target/DirectX/DXILPrepare.cpp       |   1 -
 llvm/lib/Target/DirectX/DXILRootSignature.cpp |   3 +-
 llvm/test/CodeGen/DirectX/llc-pipeline.ll     |   1 -
 .../DirectX/rootsignature-validation-fail.ll  | 143 +---------------
 8 files changed, 147 insertions(+), 314 deletions(-)

diff --git a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp
index a6dfc11c9c44c..97cbb76da2a55 100644
--- a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp
+++ b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp
@@ -65,7 +65,7 @@ class DXContainerGlobals : public llvm::ModulePass {
     AU.addRequired<DXILMetadataAnalysisWrapperPass>();
     AU.addRequired<DXILResourceTypeWrapperPass>();
     AU.addRequired<DXILResourceWrapperPass>();
-    AU.addPreserved<RootSignatureAnalysisWrapper>();
+    AU.addRequired<RootSignatureAnalysisWrapper>();
   }
 };
 
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 a52a04323514c..30a4cc6070971 100644
--- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
+++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
@@ -10,9 +10,12 @@
 #include "DXILRootSignature.h"
 #include "DXILShaderFlags.h"
 #include "DirectX.h"
+#include "llvm/ADT/STLForwardCompat.h"
 #include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/iterator_range.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"
@@ -123,6 +126,70 @@ tripleToVisibility(llvm::Triple::EnvironmentType ET) {
   }
 }
 
+static uint32_t parameterToRangeType(uint32_t Type) {
+  switch (Type) {
+  case llvm::to_underlying(dxbc::RootParameterType::CBV):
+    return llvm::to_underlying(dxbc::DescriptorRangeType::CBV);
+  break;
+  case llvm::to_underlying(dxbc::RootParameterType::SRV):
+      return llvm::to_underlying(dxbc::DescriptorRangeType::SRV);
+  break;
+  case llvm::to_underlying(dxbc::RootParameterType::UAV):
+        return llvm::to_underlying(dxbc::DescriptorRangeType::UAV);
+  break;
+  default:
+    llvm_unreachable("Root Parameter Type has no Range Type equivalent");
+  }
+}
+
+static RootSignatureBindingValidation initRsBindingValdation(const mcdxbc::RootSignatureDesc &RSD, dxbc::ShaderVisibility Visibility) {
+
+  RootSignatureBindingValidation Validation;
+
+  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::SRV):
+    case llvm::to_underlying(dxbc::RootParameterType::UAV):
+    case llvm::to_underlying(dxbc::RootParameterType::CBV): {
+      dxbc::RTS0::v2::RootDescriptor Desc =
+          RSD.ParametersContainer.getRootDescriptor(Loc);
+
+      llvm::dxil::ResourceInfo::ResourceBinding Binding;
+      Binding.LowerBound = Desc.ShaderRegister;
+      Binding.Space = Desc.RegisterSpace;
+      Binding.Size = 1;
+  
+      Validation.addBinding(parameterToRangeType(Type), Binding);
+      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) {
+          llvm::dxil::ResourceInfo::ResourceBinding Binding;
+          Binding.LowerBound = Range.BaseShaderRegister;
+          Binding.Space = Range.RegisterSpace;
+          Binding.Size = Range.NumDescriptors;
+          Validation.addBinding(Range.RangeType, Binding);
+      }
+      break;
+    }
+    }
+  }
+
+  return Validation;
+}
+
 std::optional<mcdxbc::RootSignatureDesc>
 getRootSignature(RootSignatureBindingInfo &RSBI,
                  dxil::ModuleMetadataInfo &MMI) {
@@ -135,6 +202,27 @@ getRootSignature(RootSignatureBindingInfo &RSBI,
   return RootSigDesc;
 }
 
+static void reportUnboundRegisters(
+    Module &M,
+    const std::vector<llvm::dxil::ResourceInfo::ResourceBinding> &Bindings,
+    iterator_range<SmallVector<dxil::ResourceInfo>::iterator> &Resources) {
+  for (auto Res = Resources.begin(), End = Resources.end(); Res != End; Res++) {
+    bool Bound = false;
+    ResourceInfo::ResourceBinding ResBinding = Res->getBinding();
+    for (const auto &Binding : Bindings) {
+      if (ResBinding.Space == Binding.Space &&
+          ResBinding.LowerBound >= Binding.LowerBound &&
+          ResBinding.LowerBound < Binding.LowerBound + Binding.Size) {
+        Bound = true;
+        break;
+      }
+    }
+    if (!Bound) {
+      reportRegNotBound(M, Res->getName(), Res->getBinding());
+    }
+  }
+}
+
 static void reportErrors(Module &M, DXILResourceMap &DRM,
                          DXILResourceBindingInfo &DRBI,
                          RootSignatureBindingInfo &RSBI,
@@ -150,72 +238,21 @@ static void reportErrors(Module &M, DXILResourceMap &DRM,
 
   if (auto RSD = getRootSignature(RSBI, MMI)) {
 
-    RootSignatureBindingValidation Validation;
-    Validation.addRsBindingInfo(*RSD, tripleToVisibility(MMI.ShaderProfile));
-
-    for (const ResourceInfo &CBuf : DRM.cbuffers()) {
-      ResourceInfo::ResourceBinding Binding = CBuf.getBinding();
-      if (!Validation.checkCRegBinding(Binding))
-        reportRegNotBound(M, "cbuffer", Binding);
-    }
-
-    for (const ResourceInfo &SRV : DRM.srvs()) {
-      ResourceInfo::ResourceBinding Binding = SRV.getBinding();
-      if (!Validation.checkTRegBinding(Binding))
-        reportRegNotBound(M, "srv", Binding);
-    }
+    RootSignatureBindingValidation Validation = initRsBindingValdation(*RSD, tripleToVisibility(MMI.ShaderProfile));
 
-    for (const ResourceInfo &UAV : DRM.uavs()) {
-      ResourceInfo::ResourceBinding Binding = UAV.getBinding();
-      if (!Validation.checkURegBinding(Binding))
-        reportRegNotBound(M, "uav", Binding);
-    }
+    auto Cbufs = DRM.cbuffers();
+    auto SRVs = DRM.srvs();
+    auto UAVs = DRM.uavs();
+    auto Samplers = DRM.samplers();
 
-    for (const ResourceInfo &Sampler : DRM.samplers()) {
-      ResourceInfo::ResourceBinding Binding = Sampler.getBinding();
-      if (!Validation.checkSamplerBinding(Binding))
-        reportRegNotBound(M, "sampler", Binding);
-    }
+    reportUnboundRegisters(M, Validation.getBindingsOfType(dxbc::DescriptorRangeType::CBV), Cbufs);
+    reportUnboundRegisters(M, Validation.getBindingsOfType(dxbc::DescriptorRangeType::UAV), UAVs);
+    reportUnboundRegisters(M, Validation.getBindingsOfType(dxbc::DescriptorRangeType::Sampler), Samplers);
+    reportUnboundRegisters(M, Validation.getBindingsOfType(dxbc::DescriptorRangeType::SRV), SRVs);
   }
 }
 } // namespace
 
-void RootSignatureBindingValidation::addRsBindingInfo(
-    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);
-    switch (Type) {
-    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);
-
-      if (Header.ShaderVisibility ==
-              llvm::to_underlying(dxbc::ShaderVisibility::All) ||
-          Header.ShaderVisibility == llvm::to_underlying(Visibility))
-        addRange(Desc, Type);
-      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) {
-        if (Header.ShaderVisibility ==
-                llvm::to_underlying(dxbc::ShaderVisibility::All) ||
-            Header.ShaderVisibility == llvm::to_underlying(Visibility))
-          addRange(Range);
-      }
-      break;
-    }
-    }
-  }
-}
-
 PreservedAnalyses
 DXILPostOptimizationValidation::run(Module &M, ModuleAnalysisManager &MAM) {
   DXILResourceMap &DRM = MAM.getResult<DXILResourceAnalysis>(M);
@@ -252,8 +289,8 @@ class DXILPostOptimizationValidationLegacy : public ModulePass {
   void getAnalysisUsage(llvm::AnalysisUsage &AU) const override {
     AU.addRequired<DXILResourceWrapperPass>();
     AU.addRequired<DXILResourceBindingWrapperPass>();
-    AU.addRequired<RootSignatureAnalysisWrapper>();
     AU.addRequired<DXILMetadataAnalysisWrapperPass>();
+    AU.addRequired<RootSignatureAnalysisWrapper>();
     AU.addPreserved<DXILResourceWrapperPass>();
     AU.addPreserved<DXILResourceBindingWrapperPass>();
     AU.addPreserved<DXILMetadataAnalysisWrapperPass>();
@@ -269,6 +306,7 @@ INITIALIZE_PASS_BEGIN(DXILPostOptimizationValidationLegacy, DEBUG_TYPE,
 INITIALIZE_PASS_DEPENDENCY(DXILResourceBindingWrapperPass)
 INITIALIZE_PASS_DEPENDENCY(DXILResourceTypeWrapperPass)
 INITIALIZE_PASS_DEPENDENCY(DXILResourceWrapperPass)
+INITIALIZE_PASS_DEPENDENCY(RootSignatureAnalysisWrapper)
 INITIALIZE_PASS_END(DXILPostOptimizationValidationLegacy, DEBUG_TYPE,
                     "DXIL Post Optimization Validation", false, false)
 
diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h
index 0fa0285425d7e..9a6fe258b02c7 100644
--- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h
+++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h
@@ -15,126 +15,55 @@
 #define LLVM_LIB_TARGET_DIRECTX_DXILPOSTOPTIMIZATIONVALIDATION_H
 
 #include "DXILRootSignature.h"
-#include "llvm/ADT/IntervalMap.h"
+#include "llvm/ADT/STLForwardCompat.h"
+#include "llvm/ADT/SmallVector.h"
 #include "llvm/Analysis/DXILResource.h"
+#include "llvm/BinaryFormat/DXContainer.h"
 #include "llvm/IR/PassManager.h"
+#include <cstdint>
 
 namespace llvm {
 
-static uint64_t combineUint32ToUint64(uint32_t High, uint32_t Low) {
-  return (static_cast<uint64_t>(High) << 32) | Low;
-}
-
 class RootSignatureBindingValidation {
-  using MapT =
-      llvm::IntervalMap<uint64_t, dxil::ResourceInfo::ResourceBinding,
-                        sizeof(llvm::dxil::ResourceInfo::ResourceBinding),
-                        llvm::IntervalMapInfo<uint64_t>>;
-
 private:
-  MapT::Allocator Allocator;
-  MapT CRegBindingsMap;
-  MapT TRegBindingsMap;
-  MapT URegBindingsMap;
-  MapT SamplersBindingsMap;
-
-  void addRange(const dxbc::RTS0::v2::RootDescriptor &Desc, uint32_t Type) {
-    assert((Type == llvm::to_underlying(dxbc::RootParameterType::CBV) ||
-            Type == llvm::to_underlying(dxbc::RootParameterType::SRV) ||
-            Type == llvm::to_underlying(dxbc::RootParameterType::UAV)) &&
-           "Invalid Type in add Range Method");
-
-    llvm::dxil::ResourceInfo::ResourceBinding Binding;
-    Binding.LowerBound = Desc.ShaderRegister;
-    Binding.Space = Desc.RegisterSpace;
-    Binding.Size = 1;
-
-    uint64_t LowRange =
-        combineUint32ToUint64(Binding.Space, Binding.LowerBound);
-    uint64_t HighRange = combineUint32ToUint64(
-        Binding.Space, Binding.LowerBound + Binding.Size - 1);
+    llvm::SmallVector<dxil::ResourceInfo::ResourceBinding, 16> Bindings;    
+    struct TypeRange {
+        uint32_t Start;
+        uint32_t End; 
+    };
+    std::unordered_map<uint32_t, TypeRange> Ranges;
 
-    assert(LowRange <= HighRange && "Invalid range configuration");
-
-    switch (Type) {
-
-    case llvm::to_underlying(dxbc::RootParameterType::CBV):
-      CRegBindingsMap.insert(LowRange, HighRange, Binding);
-      break;
-    case llvm::to_underlying(dxbc::RootParameterType::SRV):
-      TRegBindingsMap.insert(LowRange, HighRange, Binding);
-      break;
-    case llvm::to_underlying(dxbc::RootParameterType::UAV):
-      URegBindingsMap.insert(LowRange, HighRange, Binding);
-      break;
+public:
+    void addBinding(const uint32_t& Type, const dxil::ResourceInfo::ResourceBinding& Binding) {
+        auto It = Ranges.find(Type);
+        
+        if (It == Ranges.end()) {
+            uint32_t InsertPos = Bindings.size();
+            Bindings.push_back(Binding);
+            Ranges[Type] = {InsertPos, InsertPos + 1};
+        } else {
+            uint32_t InsertPos = It->second.End;
+            Bindings.insert(Bindings.begin() + InsertPos, Binding);
+            
+            It->second.End++;
+            
+            for (auto& [type, range] : Ranges) {
+                if (range.Start > InsertPos) {
+                    range.Start++;
+                    range.End++;
+                }
+            }
+        }
     }
-  }
-
-  void addRange(const dxbc::RTS0::v2::DescriptorRange &Range) {
-
-    llvm::dxil::ResourceInfo::ResourceBinding Binding;
-    Binding.LowerBound = Range.BaseShaderRegister;
-    Binding.Space = Range.RegisterSpace;
-    Binding.Size = Range.NumDescriptors;
-
-    uint64_t LowRange =
-        combineUint32ToUint64(Binding.Space, Binding.LowerBound);
-    uint64_t HighRange = combineUint32ToUint64(
-        Binding.Space, Binding.LowerBound + Binding.Size - 1);
-
-    assert(LowRange <= HighRange && "Invalid range configuration");
-
-    switch (Range.RangeType) {
-    case llvm::to_underlying(dxbc::DescriptorRangeType::CBV):
-      CRegBindingsMap.insert(LowRange, HighRange, Binding);
-      break;
-    case llvm::to_underlying(dxbc::DescriptorRangeType::SRV):
-      TRegBindingsMap.insert(LowRange, HighRange, Binding);
-      break;
-    case llvm::to_underlying(dxbc::DescriptorRangeType::UAV):
-      URegBindingsMap.insert(LowRange, HighRange, Binding);
-      break;
-    case llvm::to_underlying(dxbc::DescriptorRangeType::Sampler):
-      SamplersBindingsMap.insert(LowRange, HighRange, Binding);
-      break;
+    
+    llvm::ArrayRef<dxil::ResourceInfo::ResourceBinding> getBindingsOfType(const dxbc::DescriptorRangeType& Type) const {
+        auto It = Ranges.find(llvm::to_underlying(Type));
+        if (It == Ranges.end()) {
+            return {};
+        }
+        return llvm::ArrayRef<dxil::ResourceInfo::ResourceBinding>(Bindings.data() + It->second.Start, 
+                                               It->second.End - It->second.Start);
     }
-  }
-
-public:
-  RootSignatureBindingValidation()
-      : Allocator(), CRegBindingsMap(Allocator), TRegBindingsMap(Allocator),
-        URegBindingsMap(Allocator), SamplersBindingsMap(Allocator) {}
-
-  void addRsBindingInfo(mcdxbc::RootSignatureDesc &RSD,
-                        dxbc::ShaderVisibility Visibility);
-
-  bool checkCRegBinding(dxil::ResourceInfo::ResourceBinding Binding) {
-    return CRegBindingsMap.overlaps(
-        combineUint32ToUint64(Binding.Space, Binding.LowerBound),
-        combineUint32ToUint64(Binding.Space,
-                              Binding.LowerBound + Binding.Size - 1));
-  }
-
-  bool checkTRegBinding(dxil::ResourceInfo::ResourceBinding Binding) {
-    return TRegBindingsMap.overlaps(
-        combineUint32ToUint64(Binding.Space, Binding.LowerBound),
-        combineUint32ToUint64(Binding.Space,
-                              Binding.LowerBound + Binding.Size - 1));
-  }
-
-  bool checkURegBinding(dxil::ResourceInfo::ResourceBinding Binding) {
-    return URegBindingsMap.overlaps(
-        combineUint32ToUint64(Binding.Space, Binding.LowerBound),
-        combineUint32ToUint64(Binding.Space,
-                              Binding.LowerBound + Binding.Size - 1));
-  }
-
-  bool checkSamplerBinding(dxil::ResourceInfo::ResourceBinding Binding) {
-    return SamplersBindingsMap.overlaps(
-        combineUint32ToUint64(Binding.Space, Binding.LowerBound),
-        combineUint32ToUint64(Binding.Space,
-                              Binding.LowerBound + Binding.Size - 1));
-  }
 };
 
 class DXILPostOptimizationValidation
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 dfc81626da01f..70cb8bc47e00c 100644
--- a/llvm/lib/Target/DirectX/DXILRootSignature.cpp
+++ b/llvm/lib/Target/DirectX/DXILRootSignature.cpp
@@ -684,7 +684,7 @@ bool RootSignatureAnalysisWrapper::runOnModule(Module &M) {
 
 void RootSignatureAnalysisWrapper::getAnalysisUsage(AnalysisUsage &AU) const {
   AU.setPreservesAll();
-  AU.addPreserved<DXILMetadataAnalysisWrapperPass>();
+  AU.addRequired<DXILMetadataAnalysisWrapperPass>();
 }
 
 char RootSignatureAnalysisWrapper::ID = 0;
@@ -692,6 +692,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/test/CodeGen/DirectX/llc-pipeline.ll b/llvm/test/CodeGen/DirectX/llc-pipeline.ll
index 6c5e9be63da58..e8612f4213539 100644
--- a/llvm/test/CodeGen/DirectX/llc-pipeline.ll
+++ b/llvm/test/CodeGen/DirectX/llc-pipeline.ll
@@ -34,7 +34,6 @@
 ; 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-fail.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail.ll
index 54802c9e7ed22..e52647fe888b1 100644
--- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail.ll
+++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail.ll
@@ -1,132 +1,18 @@
-; RUN: not opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 
+; 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) is not defined in Root Signature
-; CHECK: error: register srv (space=0, register=0) is not defined in Root Signature
-; CHECK: error: register uav (space=0, register=4294967295) is not defined in Root Signature
-
-;
-; Resource Bindings:
-;
-; Name                                 Type  Format         Dim      ID      HLSL Bind     Count
-; ------------------------------ ---------- ------- ----------- ------- -------------- ---------
-; In                                texture  struct         r/o      T0             t0         1
-; Out                                   UAV  struct         r/w      U0             u0         1
-; UAV3                                  UAV     f32         buf      U1             u1         1
-; UAV1                                  UAV     f32         buf      U2             u2         1
-; UAV                                   UAV     f32         buf      U3    u4294967295         1
-; CB                                cbuffer      NA          NA     CB0   cb3,space665         1
-;
-; ModuleID = '../clang/test/SemaHLSL/RootSignature-Validation-Fail.hlsl'
-target datalayout = "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:32-f64:64-n8:16:32:64"
-target triple = "dxilv1.5-unknown-shadermodel6.5-compute"
+; CHECK: error: register CB (space=665, register=3) is not defined in Root Signature
 
 %__cblayout_CB = type <{ float }>
-%"StructuredBuffer<int32_t>" = type { i32 }
-%"RWStructuredBuffer<int32_t>" = type { i32 }
-%"RWBuffer<float>" = type { float }
-%CBuffer.CB = type { float }
 
- at CB.cb = local_unnamed_addr global target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 4, 0)) poison
 @CB.str = private unnamed_addr constant [3 x i8] c"CB\00", align 1
- at .str = private unnamed_addr constant [3 x i8] c"In\00", align 1
- at .str.2 = private unnamed_addr constant [4 x i8] c"Out\00", align 1
- at .str.4 = private unnamed_addr constant [4 x i8] c"UAV\00", align 1
- at .str.6 = private unnamed_addr constant [5 x i8] c"UAV1\00", align 1
- at .str.10 = private unnamed_addr constant [5 x i8] c"UAV3\00", align 1
- at In = external constant %"StructuredBuffer<int32_t>"
- at Out = external constant %"RWStructuredBuffer<int32_t>"
- at UAV3 = external constant %"RWBuffer<float>"
- at UAV1 = external constant %"RWBuffer<float>"
- at UAV = external constant %"RWBuffer<float>"
- at CB = external constant %CBuffer.CB
-
-; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(none)
-declare target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 4, 0)) @llvm.dx.resource.handlefrombinding.tdx.CBuffer_tdx.Layout_s___cblayout_CBs_4_0tt(i32, i32, i32, i32, i1, ptr) #0
 
-; Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(readwrite, inaccessiblemem: none)
-define void @CSMain() local_unnamed_addr #1 {
+define void @CSMain() "hlsl.shader"="compute" {
 entry:
-  %CB.cb_h.i.i = tail call target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 4, 0)) @llvm.dx.resource.handlefrombinding.tdx.CBuffer_tdx.Layout_s___cblayout_CBs_4_0tt(i32 665, i32 3, i32 1, i32 0, i1 false, ptr nonnull @CB.str)
-  store target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 4, 0)) %CB.cb_h.i.i, ptr @CB.cb, align 4
-  %0 = 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 @.str)
-  %1 = tail call target("dx.RawBuffer", i32, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i32_1_0t(i32 0, i32 0, i32 1, i32 0, i1 false, ptr nonnull @.str.2)
-  %2 = tail call target("dx.TypedBuffer", float, 1, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0_0t(i32 0, i32 -1, i32 1, i32 0, i1 false, ptr nonnull @.str.4)
-  %3 = tail call target("dx.TypedBuffer", float, 1, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0_0t(i32 0, i32 2, i32 1, i32 0, i1 false, ptr nonnull @.str.6)
-  %4 = call target("dx.TypedBuffer", float, 1, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0_0t(i32 0, i32 1, i32 1, i32 0, i1 false, ptr @.str.10)
-  %5 = tail call i32 @llvm.dx.group.id(i32 0)
-  %6 = call { float, float, float, float } @llvm.dx.resource.load.cbufferrow.4.f32.f32.f32.f32.tdx.CBuffer_tdx.Layout_s___cblayout_CBs_4_0tt(target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 4, 0)) %CB.cb_h.i.i, i32 0)
-  %7 = extractvalue { float, float, float, float } %6, 0
-  %conv.i = uitofp i32 %5 to float
-  %add.i = fadd reassoc nnan ninf nsz arcp afn float %7, %conv.i
-  %8 = call { i32, i1 } @llvm.dx.resource.load.rawbuffer.i32.tdx.RawBuffer_i32_0_0t(target("dx.RawBuffer", i32, 0, 0) %0, i32 0, i32 0)
-  %9 = extractvalue { i32, i1 } %8, 0
-  %conv1.i = sitofp i32 %9 to float
-  %add2.i = fadd reassoc nnan ninf nsz arcp afn float %add.i, %conv1.i
-  %10 = call { float, i1 } @llvm.dx.resource.load.typedbuffer.f32.tdx.TypedBuffer_f32_1_0_0t(target("dx.TypedBuffer", float, 1, 0, 0) %2, i32 0)
-  %11 = extractvalue { float, i1 } %10, 0
-  %add4.i = fadd reassoc nnan ninf nsz arcp afn float %add2.i, %11
-  %12 = call { float, i1 } @llvm.dx.resource.load.typedbuffer.f32.tdx.TypedBuffer_f32_1_0_0t(target("dx.TypedBuffer", float, 1, 0, 0) %3, i32 0)
-  %13 = extractvalue { float, i1 } %12, 0
-  %add6.i = fadd reassoc nnan ninf nsz arcp afn float %add4.i, %13
-  %14 = call { float, i1 } @llvm.dx.resource.load.typedbuffer.f32.tdx.TypedBuffer_f32_1_0_0t(target("dx.TypedBuffer", float, 1, 0, 0) %4, i32 0)
-  %15 = extractvalue { float, i1 } %14, 0
-  %add8.i = fadd reassoc nnan ninf nsz arcp afn float %add6.i, %15
-  %conv9.i = fptosi float %add8.i to i32
-  call void @llvm.dx.resource.store.rawbuffer.tdx.RawBuffer_i32_1_0t.i32(target("dx.RawBuffer", i32, 1, 0) %1, i32 0, i32 0, i32 %conv9.i)
+  %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
 }
 
-; Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
-declare i32 @llvm.dx.group.id(i32) #2
-
-; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(none)
-declare target("dx.RawBuffer", i32, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i32_0_0t(i32, i32, i32, i32, i1, ptr) #0
-
-; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(none)
-declare target("dx.RawBuffer", i32, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i32_1_0t(i32, i32, i32, i32, i1, ptr) #0
-
-; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(none)
-declare target("dx.TypedBuffer", float, 1, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0_0t(i32, i32, i32, i32, i1, ptr) #0
-
-; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(none)
-declare ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_i32_1_0t(target("dx.RawBuffer", i32, 1, 0), i32) #0
-
-; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(none)
-declare ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_i32_0_0t(target("dx.RawBuffer", i32, 0, 0), i32) #0
-
-; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(none)
-declare ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_f32_1_0_0t(target("dx.TypedBuffer", float, 1, 0, 0), i32) #0
-
-; Function Attrs: nocallback nofree nosync nounwind willreturn memory(read)
-declare { i32, i1 } @llvm.dx.resource.load.rawbuffer.i32.tdx.RawBuffer_i32_0_0t(target("dx.RawBuffer", i32, 0, 0), i32, i32) #3
-
-; Function Attrs: nocallback nofree nosync nounwind willreturn memory(read)
-declare { float, i1 } @llvm.dx.resource.load.typedbuffer.f32.tdx.TypedBuffer_f32_1_0_0t(target("dx.TypedBuffer", float, 1, 0, 0), i32) #3
-
-; Function Attrs: nocallback nofree nosync nounwind willreturn memory(write)
-declare void @llvm.dx.resource.store.rawbuffer.tdx.RawBuffer_i32_1_0t.i32(target("dx.RawBuffer", i32, 1, 0), i32, i32, i32) #4
-
-; Function Attrs: nocallback nofree nosync nounwind willreturn memory(read)
-declare { float, float, float, float } @llvm.dx.resource.load.cbufferrow.4.f32.f32.f32.f32.tdx.CBuffer_tdx.Layout_s___cblayout_CBs_4_0tt(target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 4, 0)), i32) #3
-
-; uselistorder directives
-uselistorder ptr @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0_0t, { 2, 1, 0 }
-uselistorder ptr @llvm.dx.resource.load.typedbuffer.f32.tdx.TypedBuffer_f32_1_0_0t, { 2, 1, 0 }
-
-attributes #0 = { mustprogress nocallback nofree nosync nounwind willreturn memory(none) }
-attributes #1 = { mustprogress nofree noinline norecurse nosync nounwind willreturn memory(readwrite, inaccessiblemem: none) "approx-func-fp-math"="false" "frame-pointer"="all" "hlsl.numthreads"="8,8,1" "hlsl.shader"="compute" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
-attributes #2 = { mustprogress nofree nosync nounwind willreturn memory(none) }
-attributes #3 = { nocallback nofree nosync nounwind willreturn memory(read) }
-attributes #4 = { nocallback nofree nosync nounwind willreturn memory(write) }
-
 !dx.rootsignatures = !{!0}
-!llvm.module.flags = !{!9, !10}
-!dx.valver = !{!11}
-!llvm.ident = !{!12}
-!dx.shaderModel = !{!13}
-!dx.version = !{!14}
-!dx.resources = !{!15}
-!dx.entryPoints = !{!27}
 
 !0 = !{ptr @CSMain, !1, i32 2}
 !1 = !{!2, !3, !5, !7}
@@ -137,24 +23,3 @@ attributes #4 = { nocallback nofree nosync nounwind willreturn memory(write) }
 !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}
-!9 = !{i32 1, !"wchar_size", i32 4}
-!10 = !{i32 7, !"frame-pointer", i32 2}
-!11 = !{i32 1, i32 8}
-!12 = !{!"clang version 21.0.0git (https://github.com/joaosaffran/llvm-project.git c16f15b4cd469a3f6efc2e4b0e098190d7fd0787)"}
-!13 = !{!"cs", i32 6, i32 5}
-!14 = !{i32 1, i32 5}
-!15 = !{!16, !19, !25, null}
-!16 = !{!17}
-!17 = !{i32 0, ptr @In, !"In", i32 0, i32 0, i32 1, i32 12, i32 0, !18}
-!18 = !{i32 1, i32 4}
-!19 = !{!20, !21, !23, !24}
-!20 = !{i32 0, ptr @Out, !"Out", i32 0, i32 0, i32 1, i32 12, i1 false, i1 false, i1 false, !18}
-!21 = !{i32 1, ptr @UAV3, !"UAV3", i32 0, i32 1, i32 1, i32 10, i1 false, i1 false, i1 false, !22}
-!22 = !{i32 0, i32 9}
-!23 = !{i32 2, ptr @UAV1, !"UAV1", i32 0, i32 2, i32 1, i32 10, i1 false, i1 false, i1 false, !22}
-!24 = !{i32 3, ptr @UAV, !"UAV", i32 0, i32 -1, i32 1, i32 10, i1 false, i1 false, i1 false, !22}
-!25 = !{!26}
-!26 = !{i32 0, ptr @CB, !"CB", i32 665, i32 3, i32 1, i32 4, null}
-!27 = !{ptr @CSMain, !"CSMain", null, !15, !28}
-!28 = !{i32 0, i64 16, i32 4, !29}
-!29 = !{i32 8, i32 8, i32 1}

>From 5423aba8038731f6159266304fa8cad983b6af7c Mon Sep 17 00:00:00 2001
From: joaosaffran <joao.saffran at microsoft.com>
Date: Mon, 14 Jul 2025 18:40:30 +0000
Subject: [PATCH 25/29] format

---
 .../DXILPostOptimizationValidation.cpp        | 50 ++++++++------
 .../DirectX/DXILPostOptimizationValidation.h  | 68 ++++++++++---------
 2 files changed, 64 insertions(+), 54 deletions(-)

diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
index 30a4cc6070971..035a5bd225ac8 100644
--- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
+++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
@@ -130,19 +130,21 @@ static uint32_t parameterToRangeType(uint32_t Type) {
   switch (Type) {
   case llvm::to_underlying(dxbc::RootParameterType::CBV):
     return llvm::to_underlying(dxbc::DescriptorRangeType::CBV);
-  break;
+    break;
   case llvm::to_underlying(dxbc::RootParameterType::SRV):
-      return llvm::to_underlying(dxbc::DescriptorRangeType::SRV);
-  break;
+    return llvm::to_underlying(dxbc::DescriptorRangeType::SRV);
+    break;
   case llvm::to_underlying(dxbc::RootParameterType::UAV):
-        return llvm::to_underlying(dxbc::DescriptorRangeType::UAV);
-  break;
+    return llvm::to_underlying(dxbc::DescriptorRangeType::UAV);
+    break;
   default:
     llvm_unreachable("Root Parameter Type has no Range Type equivalent");
   }
 }
 
-static RootSignatureBindingValidation initRsBindingValdation(const mcdxbc::RootSignatureDesc &RSD, dxbc::ShaderVisibility Visibility) {
+static RootSignatureBindingValidation
+initRsBindingValdation(const mcdxbc::RootSignatureDesc &RSD,
+                       dxbc::ShaderVisibility Visibility) {
 
   RootSignatureBindingValidation Validation;
 
@@ -152,10 +154,10 @@ static RootSignatureBindingValidation initRsBindingValdation(const mcdxbc::RootS
 
     const auto &Header = RSD.ParametersContainer.getHeader(I);
     if (Header.ShaderVisibility !=
-          llvm::to_underlying(dxbc::ShaderVisibility::All) &&
-          Header.ShaderVisibility != llvm::to_underlying(Visibility))
-          continue;
-          
+            llvm::to_underlying(dxbc::ShaderVisibility::All) &&
+        Header.ShaderVisibility != llvm::to_underlying(Visibility))
+      continue;
+
     switch (Type) {
     case llvm::to_underlying(dxbc::RootParameterType::SRV):
     case llvm::to_underlying(dxbc::RootParameterType::UAV):
@@ -167,7 +169,7 @@ static RootSignatureBindingValidation initRsBindingValdation(const mcdxbc::RootS
       Binding.LowerBound = Desc.ShaderRegister;
       Binding.Space = Desc.RegisterSpace;
       Binding.Size = 1;
-  
+
       Validation.addBinding(parameterToRangeType(Type), Binding);
       break;
     }
@@ -176,11 +178,11 @@ static RootSignatureBindingValidation initRsBindingValdation(const mcdxbc::RootS
           RSD.ParametersContainer.getDescriptorTable(Loc);
 
       for (const dxbc::RTS0::v2::DescriptorRange &Range : Table.Ranges) {
-          llvm::dxil::ResourceInfo::ResourceBinding Binding;
-          Binding.LowerBound = Range.BaseShaderRegister;
-          Binding.Space = Range.RegisterSpace;
-          Binding.Size = Range.NumDescriptors;
-          Validation.addBinding(Range.RangeType, Binding);
+        llvm::dxil::ResourceInfo::ResourceBinding Binding;
+        Binding.LowerBound = Range.BaseShaderRegister;
+        Binding.Space = Range.RegisterSpace;
+        Binding.Size = Range.NumDescriptors;
+        Validation.addBinding(Range.RangeType, Binding);
       }
       break;
     }
@@ -238,17 +240,23 @@ static void reportErrors(Module &M, DXILResourceMap &DRM,
 
   if (auto RSD = getRootSignature(RSBI, MMI)) {
 
-    RootSignatureBindingValidation Validation = initRsBindingValdation(*RSD, tripleToVisibility(MMI.ShaderProfile));
+    RootSignatureBindingValidation Validation =
+        initRsBindingValdation(*RSD, tripleToVisibility(MMI.ShaderProfile));
 
     auto Cbufs = DRM.cbuffers();
     auto SRVs = DRM.srvs();
     auto UAVs = DRM.uavs();
     auto Samplers = DRM.samplers();
 
-    reportUnboundRegisters(M, Validation.getBindingsOfType(dxbc::DescriptorRangeType::CBV), Cbufs);
-    reportUnboundRegisters(M, Validation.getBindingsOfType(dxbc::DescriptorRangeType::UAV), UAVs);
-    reportUnboundRegisters(M, Validation.getBindingsOfType(dxbc::DescriptorRangeType::Sampler), Samplers);
-    reportUnboundRegisters(M, Validation.getBindingsOfType(dxbc::DescriptorRangeType::SRV), SRVs);
+    reportUnboundRegisters(
+        M, Validation.getBindingsOfType(dxbc::DescriptorRangeType::CBV), Cbufs);
+    reportUnboundRegisters(
+        M, Validation.getBindingsOfType(dxbc::DescriptorRangeType::UAV), UAVs);
+    reportUnboundRegisters(
+        M, Validation.getBindingsOfType(dxbc::DescriptorRangeType::Sampler),
+        Samplers);
+    reportUnboundRegisters(
+        M, Validation.getBindingsOfType(dxbc::DescriptorRangeType::SRV), SRVs);
   }
 }
 } // namespace
diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h
index 9a6fe258b02c7..f0e4c4d9d7164 100644
--- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h
+++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h
@@ -26,44 +26,46 @@ namespace llvm {
 
 class RootSignatureBindingValidation {
 private:
-    llvm::SmallVector<dxil::ResourceInfo::ResourceBinding, 16> Bindings;    
-    struct TypeRange {
-        uint32_t Start;
-        uint32_t End; 
-    };
-    std::unordered_map<uint32_t, TypeRange> Ranges;
+  llvm::SmallVector<dxil::ResourceInfo::ResourceBinding, 16> Bindings;
+  struct TypeRange {
+    uint32_t Start;
+    uint32_t End;
+  };
+  std::unordered_map<uint32_t, TypeRange> Ranges;
 
 public:
-    void addBinding(const uint32_t& Type, const dxil::ResourceInfo::ResourceBinding& Binding) {
-        auto It = Ranges.find(Type);
-        
-        if (It == Ranges.end()) {
-            uint32_t InsertPos = Bindings.size();
-            Bindings.push_back(Binding);
-            Ranges[Type] = {InsertPos, InsertPos + 1};
-        } else {
-            uint32_t InsertPos = It->second.End;
-            Bindings.insert(Bindings.begin() + InsertPos, Binding);
-            
-            It->second.End++;
-            
-            for (auto& [type, range] : Ranges) {
-                if (range.Start > InsertPos) {
-                    range.Start++;
-                    range.End++;
-                }
-            }
+  void addBinding(const uint32_t &Type,
+                  const dxil::ResourceInfo::ResourceBinding &Binding) {
+    auto It = Ranges.find(Type);
+
+    if (It == Ranges.end()) {
+      uint32_t InsertPos = Bindings.size();
+      Bindings.push_back(Binding);
+      Ranges[Type] = {InsertPos, InsertPos + 1};
+    } else {
+      uint32_t InsertPos = It->second.End;
+      Bindings.insert(Bindings.begin() + InsertPos, Binding);
+
+      It->second.End++;
+
+      for (auto &[type, range] : Ranges) {
+        if (range.Start > InsertPos) {
+          range.Start++;
+          range.End++;
         }
+      }
     }
-    
-    llvm::ArrayRef<dxil::ResourceInfo::ResourceBinding> getBindingsOfType(const dxbc::DescriptorRangeType& Type) const {
-        auto It = Ranges.find(llvm::to_underlying(Type));
-        if (It == Ranges.end()) {
-            return {};
-        }
-        return llvm::ArrayRef<dxil::ResourceInfo::ResourceBinding>(Bindings.data() + It->second.Start, 
-                                               It->second.End - It->second.Start);
+  }
+
+  llvm::ArrayRef<dxil::ResourceInfo::ResourceBinding>
+  getBindingsOfType(const dxbc::DescriptorRangeType &Type) const {
+    auto It = Ranges.find(llvm::to_underlying(Type));
+    if (It == Ranges.end()) {
+      return {};
     }
+    return llvm::ArrayRef<dxil::ResourceInfo::ResourceBinding>(
+        Bindings.data() + It->second.Start, It->second.End - It->second.Start);
+  }
 };
 
 class DXILPostOptimizationValidation

>From a7637a7848b6a3bfd60ab366568f6f708878287e Mon Sep 17 00:00:00 2001
From: joaosaffran <joao.saffran at microsoft.com>
Date: Mon, 14 Jul 2025 19:31:23 +0000
Subject: [PATCH 26/29] adding tests

---
 .../DXILPostOptimizationValidation.cpp        |   7 -
 ... rootsignature-validation-fail-cbuffer.ll} |   9 ++
 .../rootsignature-validation-fail-sampler.ll  |  31 ++++
 .../rootsignature-validation-fail-srv.ll      |  30 ++++
 .../rootsignature-validation-fail-uav.ll      |  30 ++++
 .../DirectX/rootsignature-validation.ll       | 148 +++---------------
 6 files changed, 119 insertions(+), 136 deletions(-)
 rename llvm/test/CodeGen/DirectX/{rootsignature-validation-fail.ll => rootsignature-validation-fail-cbuffer.ll} (70%)
 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

diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
index 035a5bd225ac8..f9218d571365c 100644
--- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
+++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
@@ -7,15 +7,11 @@
 //===----------------------------------------------------------------------===//
 
 #include "DXILPostOptimizationValidation.h"
-#include "DXILRootSignature.h"
 #include "DXILShaderFlags.h"
 #include "DirectX.h"
-#include "llvm/ADT/STLForwardCompat.h"
 #include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/iterator_range.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"
@@ -130,13 +126,10 @@ static uint32_t parameterToRangeType(uint32_t Type) {
   switch (Type) {
   case llvm::to_underlying(dxbc::RootParameterType::CBV):
     return llvm::to_underlying(dxbc::DescriptorRangeType::CBV);
-    break;
   case llvm::to_underlying(dxbc::RootParameterType::SRV):
     return llvm::to_underlying(dxbc::DescriptorRangeType::SRV);
-    break;
   case llvm::to_underlying(dxbc::RootParameterType::UAV):
     return llvm::to_underlying(dxbc::DescriptorRangeType::UAV);
-    break;
   default:
     llvm_unreachable("Root Parameter Type has no Range Type equivalent");
   }
diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbuffer.ll
similarity index 70%
rename from llvm/test/CodeGen/DirectX/rootsignature-validation-fail.ll
rename to llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbuffer.ll
index e52647fe888b1..cd8a87d04f31a 100644
--- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail.ll
+++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbuffer.ll
@@ -2,12 +2,21 @@
 
 ; CHECK: error: register CB (space=665, register=3) is not defined in 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 }>
 
 @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
 }
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..8e7e0de96ccff
--- /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 Smp (space=2, register=3) is not defined in 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..166ac51a7d0de
--- /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 SB (space=0, register=0) is not defined in 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..8a1daea8f7d24
--- /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 RWB (space=0, register=4294967295) is not defined in 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(u4294967295);
+  %RWB = tail call target("dx.TypedBuffer", float, 1, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0_0t(i32 0, i32 -1, 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 -1, 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
index eaf8512c284a7..750679bf743c5 100644
--- a/llvm/test/CodeGen/DirectX/rootsignature-validation.ll
+++ b/llvm/test/CodeGen/DirectX/rootsignature-validation.ll
@@ -1,149 +1,39 @@
 ; RUN: opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 
 ; expected-no-diagnostics
 
-;
-; Resource Bindings:
-;
-; Name                                 Type  Format         Dim      ID      HLSL Bind     Count
-; ------------------------------ ---------- ------- ----------- ------- -------------- ---------
-; In                                texture  struct         r/o      T0             t0         1
-; Out                                   UAV  struct         r/w      U0             u0         1
-; UAV3                                  UAV  struct         r/w      U1             u1         1
-; UAV1                                  UAV  struct         r/w      U2             u2         1
-; UAV                                   UAV  struct         r/w      U3    u4294967294         1
-; CB                                cbuffer      NA          NA     CB0     cb3,space1         1
-;
-; ModuleID = '../clang/test/SemaHLSL/RootSignature-Validation.hlsl'
-target datalayout = "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:32-f64:64-n8:16:32:64"
-target triple = "dxilv1.5-unknown-shadermodel6.5-compute"
+
+; 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 }>
-%"StructuredBuffer<int32_t>" = type { i32 }
-%"RWStructuredBuffer<int32_t>" = type { i32 }
-%"RWStructuredBuffer<float>" = type { float }
-%CBuffer.CB = type { float }
 
- at CB.cb = local_unnamed_addr global target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 4, 0)) poison
 @CB.str = private unnamed_addr constant [3 x i8] c"CB\00", align 1
- at .str = private unnamed_addr constant [3 x i8] c"In\00", align 1
- at .str.2 = private unnamed_addr constant [4 x i8] c"Out\00", align 1
- at .str.4 = private unnamed_addr constant [4 x i8] c"UAV\00", align 1
- at .str.6 = private unnamed_addr constant [5 x i8] c"UAV1\00", align 1
- at .str.10 = private unnamed_addr constant [5 x i8] c"UAV3\00", align 1
- at In = external constant %"StructuredBuffer<int32_t>"
- at Out = external constant %"RWStructuredBuffer<int32_t>"
- at UAV3 = external constant %"RWStructuredBuffer<float>"
- at UAV1 = external constant %"RWStructuredBuffer<float>"
- at UAV = external constant %"RWStructuredBuffer<float>"
- at CB = external constant %CBuffer.CB
-
-; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(none)
-declare target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 4, 0)) @llvm.dx.resource.handlefrombinding.tdx.CBuffer_tdx.Layout_s___cblayout_CBs_4_0tt(i32, i32, i32, i32, i1, ptr) #0
+ 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
 
-; Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(readwrite, inaccessiblemem: none)
-define void @CSMain() local_unnamed_addr #1 {
+define void @CSMain() "hlsl.shader"="compute" {
 entry:
-  %CB.cb_h.i.i = tail call target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 4, 0)) @llvm.dx.resource.handlefrombinding.tdx.CBuffer_tdx.Layout_s___cblayout_CBs_4_0tt(i32 1, i32 3, i32 1, i32 0, i1 false, ptr nonnull @CB.str)
-  store target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 4, 0)) %CB.cb_h.i.i, ptr @CB.cb, align 4
-  %0 = 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 @.str)
-  %1 = tail call target("dx.RawBuffer", i32, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i32_1_0t(i32 0, i32 0, i32 1, i32 0, i1 false, ptr nonnull @.str.2)
-  %2 = tail call target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_f32_1_0t(i32 0, i32 -2, i32 1, i32 0, i1 false, ptr nonnull @.str.4)
-  %3 = tail call target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_f32_1_0t(i32 0, i32 2, i32 1, i32 0, i1 false, ptr nonnull @.str.6)
-  %4 = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_f32_1_0t(i32 0, i32 1, i32 1, i32 0, i1 false, ptr @.str.10)
-  %5 = call { float, float, float, float } @llvm.dx.resource.load.cbufferrow.4.f32.f32.f32.f32.tdx.CBuffer_tdx.Layout_s___cblayout_CBs_4_0tt(target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 4, 0)) %CB.cb_h.i.i, i32 0)
-  %6 = extractvalue { float, float, float, float } %5, 0
-  %7 = call { i32, i1 } @llvm.dx.resource.load.rawbuffer.i32.tdx.RawBuffer_i32_0_0t(target("dx.RawBuffer", i32, 0, 0) %0, i32 0, i32 0)
-  %8 = extractvalue { i32, i1 } %7, 0
-  %conv.i = sitofp i32 %8 to float
-  %add.i = fadd reassoc nnan ninf nsz arcp afn float %6, %conv.i
-  %9 = call { float, i1 } @llvm.dx.resource.load.rawbuffer.f32.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %2, i32 0, i32 0)
-  %10 = extractvalue { float, i1 } %9, 0
-  %add2.i = fadd reassoc nnan ninf nsz arcp afn float %add.i, %10
-  %11 = call { float, i1 } @llvm.dx.resource.load.rawbuffer.f32.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %3, i32 0, i32 0)
-  %12 = extractvalue { float, i1 } %11, 0
-  %add4.i = fadd reassoc nnan ninf nsz arcp afn float %add2.i, %12
-  %13 = call { float, i1 } @llvm.dx.resource.load.rawbuffer.f32.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %4, i32 0, i32 0)
-  %14 = extractvalue { float, i1 } %13, 0
-  %add6.i = fadd reassoc nnan ninf nsz arcp afn float %add4.i, %14
-  %conv7.i = fptosi float %add6.i to i32
-  call void @llvm.dx.resource.store.rawbuffer.tdx.RawBuffer_i32_1_0t.i32(target("dx.RawBuffer", i32, 1, 0) %1, i32 0, i32 0, i32 %conv7.i)
-  ret void
-}
-
-; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(none)
-declare target("dx.RawBuffer", i32, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i32_0_0t(i32, i32, i32, i32, i1, ptr) #0
-
-; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(none)
-declare target("dx.RawBuffer", i32, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i32_1_0t(i32, i32, i32, i32, i1, ptr) #0
-
-; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(none)
-declare target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_f32_1_0t(i32, i32, i32, i32, i1, ptr) #0
-
-; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(none)
-declare ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_i32_1_0t(target("dx.RawBuffer", i32, 1, 0), i32) #0
 
-; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(none)
-declare ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_i32_0_0t(target("dx.RawBuffer", i32, 0, 0), i32) #0
+  %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)
 
-; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(none)
-declare ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0), i32) #0
-
-; Function Attrs: nocallback nofree nosync nounwind willreturn memory(read)
-declare { i32, i1 } @llvm.dx.resource.load.rawbuffer.i32.tdx.RawBuffer_i32_0_0t(target("dx.RawBuffer", i32, 0, 0), i32, i32) #2
-
-; Function Attrs: nocallback nofree nosync nounwind willreturn memory(read)
-declare { float, i1 } @llvm.dx.resource.load.rawbuffer.f32.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0), i32, i32) #2
-
-; Function Attrs: nocallback nofree nosync nounwind willreturn memory(write)
-declare void @llvm.dx.resource.store.rawbuffer.tdx.RawBuffer_i32_1_0t.i32(target("dx.RawBuffer", i32, 1, 0), i32, i32, i32) #3
-
-; Function Attrs: nocallback nofree nosync nounwind willreturn memory(read)
-declare { float, float, float, float } @llvm.dx.resource.load.cbufferrow.4.f32.f32.f32.f32.tdx.CBuffer_tdx.Layout_s___cblayout_CBs_4_0tt(target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 4, 0)), i32) #2
-
-; uselistorder directives
-uselistorder ptr @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_f32_1_0t, { 2, 1, 0 }
-uselistorder ptr @llvm.dx.resource.load.rawbuffer.f32.tdx.RawBuffer_f32_1_0t, { 2, 1, 0 }
-
-attributes #0 = { mustprogress nocallback nofree nosync nounwind willreturn memory(none) }
-attributes #1 = { mustprogress nofree noinline norecurse nosync nounwind willreturn memory(readwrite, inaccessiblemem: none) "approx-func-fp-math"="false" "frame-pointer"="all" "hlsl.numthreads"="8,8,1" "hlsl.shader"="compute" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
-attributes #2 = { nocallback nofree nosync nounwind willreturn memory(read) }
-attributes #3 = { nocallback nofree nosync nounwind willreturn memory(write) }
+  ret void
+}
 
 !dx.rootsignatures = !{!0}
-!llvm.module.flags = !{!9, !10}
-!dx.valver = !{!11}
-!llvm.ident = !{!12}
-!dx.shaderModel = !{!13}
-!dx.version = !{!14}
-!dx.resources = !{!15}
-!dx.entryPoints = !{!26}
 
 !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 4}
-!5 = !{!"DescriptorTable", i32 1, !6}
-!6 = !{!"Sampler", i32 2, i32 0, i32 0, i32 -1, i32 0}
+!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}
-!9 = !{i32 1, !"wchar_size", i32 4}
-!10 = !{i32 7, !"frame-pointer", i32 2}
-!11 = !{i32 1, i32 8}
-!12 = !{!"clang version 21.0.0git (https://github.com/joaosaffran/llvm-project.git c16f15b4cd469a3f6efc2e4b0e098190d7fd0787)"}
-!13 = !{!"cs", i32 6, i32 5}
-!14 = !{i32 1, i32 5}
-!15 = !{!16, !19, !24, null}
-!16 = !{!17}
-!17 = !{i32 0, ptr @In, !"In", i32 0, i32 0, i32 1, i32 12, i32 0, !18}
-!18 = !{i32 1, i32 4}
-!19 = !{!20, !21, !22, !23}
-!20 = !{i32 0, ptr @Out, !"Out", i32 0, i32 0, i32 1, i32 12, i1 false, i1 false, i1 false, !18}
-!21 = !{i32 1, ptr @UAV3, !"UAV3", i32 0, i32 1, i32 1, i32 12, i1 false, i1 false, i1 false, !18}
-!22 = !{i32 2, ptr @UAV1, !"UAV1", i32 0, i32 2, i32 1, i32 12, i1 false, i1 false, i1 false, !18}
-!23 = !{i32 3, ptr @UAV, !"UAV", i32 0, i32 -2, i32 1, i32 12, i1 false, i1 false, i1 false, !18}
-!24 = !{!25}
-!25 = !{i32 0, ptr @CB, !"CB", i32 1, i32 3, i32 1, i32 4, null}
-!26 = !{ptr @CSMain, !"CSMain", null, !15, !27}
-!27 = !{i32 0, i64 16, i32 4, !28}
-!28 = !{i32 8, i32 8, i32 1}

>From da42c0c2f6af1ee68f85779fe307bda2a7af597f Mon Sep 17 00:00:00 2001
From: joaosaffran <joao.saffran at microsoft.com>
Date: Mon, 14 Jul 2025 20:30:37 +0000
Subject: [PATCH 27/29] clean up

---
 llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h | 1 -
 1 file changed, 1 deletion(-)

diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h
index f0e4c4d9d7164..cabf3d95e66e9 100644
--- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h
+++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h
@@ -20,7 +20,6 @@
 #include "llvm/Analysis/DXILResource.h"
 #include "llvm/BinaryFormat/DXContainer.h"
 #include "llvm/IR/PassManager.h"
-#include <cstdint>
 
 namespace llvm {
 

>From edb015dcae3bfb5d3168321b288d0b8cd1451ff9 Mon Sep 17 00:00:00 2001
From: joaosaffran <joao.saffran at microsoft.com>
Date: Tue, 15 Jul 2025 00:37:40 +0000
Subject: [PATCH 28/29] address comments

---
 .../DXILPostOptimizationValidation.cpp        | 32 ++++++++++---------
 .../DirectX/DXILPostOptimizationValidation.h  |  8 ++---
 2 files changed, 21 insertions(+), 19 deletions(-)

diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
index f9218d571365c..c01f52e07d230 100644
--- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
+++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
@@ -10,6 +10,7 @@
 #include "DXILShaderFlags.h"
 #include "DirectX.h"
 #include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
 #include "llvm/Analysis/DXILMetadataAnalysis.h"
 #include "llvm/Analysis/DXILResource.h"
 #include "llvm/IR/DiagnosticInfo.h"
@@ -136,8 +137,8 @@ static uint32_t parameterToRangeType(uint32_t Type) {
 }
 
 static RootSignatureBindingValidation
-initRsBindingValdation(const mcdxbc::RootSignatureDesc &RSD,
-                       dxbc::ShaderVisibility Visibility) {
+initRSBindingValidation(const mcdxbc::RootSignatureDesc &RSD,
+                        dxbc::ShaderVisibility Visibility) {
 
   RootSignatureBindingValidation Validation;
 
@@ -199,15 +200,17 @@ getRootSignature(RootSignatureBindingInfo &RSBI,
 
 static void reportUnboundRegisters(
     Module &M,
-    const std::vector<llvm::dxil::ResourceInfo::ResourceBinding> &Bindings,
-    iterator_range<SmallVector<dxil::ResourceInfo>::iterator> &Resources) {
+    const llvm::ArrayRef<llvm::dxil::ResourceInfo::ResourceBinding> &Bindings,
+    const iterator_range<SmallVectorImpl<dxil::ResourceInfo>::iterator>
+        &Resources) {
   for (auto Res = Resources.begin(), End = Resources.end(); Res != End; Res++) {
     bool Bound = false;
     ResourceInfo::ResourceBinding ResBinding = Res->getBinding();
     for (const auto &Binding : Bindings) {
       if (ResBinding.Space == Binding.Space &&
           ResBinding.LowerBound >= Binding.LowerBound &&
-          ResBinding.LowerBound < Binding.LowerBound + Binding.Size) {
+          ResBinding.LowerBound + ResBinding.Size - 1 <
+              Binding.LowerBound + Binding.Size) {
         Bound = true;
         break;
       }
@@ -234,22 +237,20 @@ static void reportErrors(Module &M, DXILResourceMap &DRM,
   if (auto RSD = getRootSignature(RSBI, MMI)) {
 
     RootSignatureBindingValidation Validation =
-        initRsBindingValdation(*RSD, tripleToVisibility(MMI.ShaderProfile));
-
-    auto Cbufs = DRM.cbuffers();
-    auto SRVs = DRM.srvs();
-    auto UAVs = DRM.uavs();
-    auto Samplers = DRM.samplers();
+        initRSBindingValidation(*RSD, tripleToVisibility(MMI.ShaderProfile));
 
     reportUnboundRegisters(
-        M, Validation.getBindingsOfType(dxbc::DescriptorRangeType::CBV), Cbufs);
+        M, Validation.getBindingsOfType(dxbc::DescriptorRangeType::CBV),
+        DRM.cbuffers());
     reportUnboundRegisters(
-        M, Validation.getBindingsOfType(dxbc::DescriptorRangeType::UAV), UAVs);
+        M, Validation.getBindingsOfType(dxbc::DescriptorRangeType::UAV),
+        DRM.uavs());
     reportUnboundRegisters(
         M, Validation.getBindingsOfType(dxbc::DescriptorRangeType::Sampler),
-        Samplers);
+        DRM.samplers());
     reportUnboundRegisters(
-        M, Validation.getBindingsOfType(dxbc::DescriptorRangeType::SRV), SRVs);
+        M, Validation.getBindingsOfType(dxbc::DescriptorRangeType::SRV),
+        DRM.srvs());
   }
 }
 } // namespace
@@ -307,6 +308,7 @@ 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/DXILPostOptimizationValidation.h b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h
index cabf3d95e66e9..789bbe4573964 100644
--- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h
+++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h
@@ -47,10 +47,10 @@ class RootSignatureBindingValidation {
 
       It->second.End++;
 
-      for (auto &[type, range] : Ranges) {
-        if (range.Start > InsertPos) {
-          range.Start++;
-          range.End++;
+      for (auto &[Type, Range] : Ranges) {
+        if (Range.Start > InsertPos) {
+          Range.Start++;
+          Range.End++;
         }
       }
     }

>From 9f3888ead4ed2934400cbf4ef3b92bdccc56645b Mon Sep 17 00:00:00 2001
From: joaosaffran <joao.saffran at microsoft.com>
Date: Tue, 15 Jul 2025 18:17:45 +0000
Subject: [PATCH 29/29] adding root constants

---
 .../DXILPostOptimizationValidation.cpp        | 18 +++++++++++++++
 .../rootsignature-validation-constants.ll     | 22 +++++++++++++++++++
 ...rootsignature-validation-fail-constants.ll | 22 +++++++++++++++++++
 3 files changed, 62 insertions(+)
 create mode 100644 llvm/test/CodeGen/DirectX/rootsignature-validation-constants.ll
 create mode 100644 llvm/test/CodeGen/DirectX/rootsignature-validation-fail-constants.ll

diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
index c01f52e07d230..eb3ad6a6e56ee 100644
--- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
+++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
@@ -9,10 +9,12 @@
 #include "DXILPostOptimizationValidation.h"
 #include "DXILShaderFlags.h"
 #include "DirectX.h"
+#include "llvm/ADT/STLForwardCompat.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/SmallVector.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"
@@ -153,6 +155,22 @@ initRSBindingValidation(const mcdxbc::RootSignatureDesc &RSD,
       continue;
 
     switch (Type) {
+    case llvm::to_underlying(dxbc::RootParameterType::Constants32Bit): {
+      dxbc::RTS0::v1::RootConstants Const =
+          RSD.ParametersContainer.getConstant(Loc);
+
+      llvm::dxil::ResourceInfo::ResourceBinding Binding;
+      Binding.LowerBound = Const.ShaderRegister;
+      Binding.Space = Const.RegisterSpace;
+      Binding.Size = 1;
+
+      // Root Constants Bind to CBuffers
+      Validation.addBinding(llvm::to_underlying(dxbc::DescriptorRangeType::CBV),
+                            Binding);
+
+      break;
+    }
+
     case llvm::to_underlying(dxbc::RootParameterType::SRV):
     case llvm::to_underlying(dxbc::RootParameterType::UAV):
     case llvm::to_underlying(dxbc::RootParameterType::CBV): {
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-constants.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-constants.ll
new file mode 100644
index 0000000000000..b7e1172c7304a
--- /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 CB (space=666, register=2) is not defined in 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}



More information about the llvm-commits mailing list