[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