[llvm] [HLSL] Analyze update counter usage (PR #130356)
Ashley Coleman via llvm-commits
llvm-commits at lists.llvm.org
Mon Mar 17 13:04:16 PDT 2025
https://github.com/V-FEXrt updated https://github.com/llvm/llvm-project/pull/130356
>From ee05b44bb7ff79ea77927d94724aba2657d0134a Mon Sep 17 00:00:00 2001
From: Ashley Coleman <ascoleman at microsoft.com>
Date: Wed, 5 Mar 2025 17:23:12 -0700
Subject: [PATCH 01/11] [HLSL] Analyze update counter usage
---
llvm/include/llvm/Analysis/DXILResource.h | 67 +++++++++++++
llvm/include/llvm/InitializePasses.h | 1 +
llvm/lib/Analysis/DXILResource.cpp | 93 +++++++++++++++++++
.../DirectX/UniqueResourceFromUseTests.cpp | 44 +++++++++
4 files changed, 205 insertions(+)
diff --git a/llvm/include/llvm/Analysis/DXILResource.h b/llvm/include/llvm/Analysis/DXILResource.h
index d399457e16916..3f11b07cd75eb 100644
--- a/llvm/include/llvm/Analysis/DXILResource.h
+++ b/llvm/include/llvm/Analysis/DXILResource.h
@@ -18,6 +18,10 @@
#include "llvm/Support/Alignment.h"
#include "llvm/Support/DXILABI.h"
+#include <algorithm>
+#include <cstdint>
+#include <unordered_map>
+
namespace llvm {
class CallInst;
class DataLayout;
@@ -407,6 +411,69 @@ class DXILResourceTypeMap {
}
};
+enum ResourceCounterDirection {
+ Increment,
+ Decrement,
+ Unknown,
+};
+
+class DXILResourceCounterDirectionMap {
+ std::vector<std::pair<dxil::ResourceBindingInfo, ResourceCounterDirection>> CounterDirections;
+
+public:
+ bool invalidate(Module &M, const PreservedAnalyses &PA,
+ ModuleAnalysisManager::Invalidator &Inv);
+
+ void populate(Module &M, ModuleAnalysisManager &AM);
+
+ ResourceCounterDirection operator[](const dxil::ResourceBindingInfo &Info) const {
+ auto Lower = std::lower_bound(CounterDirections.begin(), CounterDirections.end(), std::pair{Info, ResourceCounterDirection::Unknown}, [](auto lhs, auto rhs){
+ return lhs.first < rhs.first;
+ });
+
+ if (Lower == CounterDirections.end()) {
+ return ResourceCounterDirection::Unknown;
+ }
+
+ if (Lower->first != Info) {
+ return ResourceCounterDirection::Unknown;
+ }
+
+ return Lower->second;
+ }
+};
+
+class DXILResourceCounterDirectionAnalysis
+ : public AnalysisInfoMixin<DXILResourceCounterDirectionAnalysis> {
+ friend AnalysisInfoMixin<DXILResourceCounterDirectionAnalysis>;
+
+ static AnalysisKey Key;
+
+public:
+ using Result = DXILResourceCounterDirectionMap;
+
+ DXILResourceCounterDirectionMap run(Module &M, ModuleAnalysisManager &AM) {
+ DXILResourceCounterDirectionMap DRCDM{};
+ DRCDM.populate(M, AM);
+ return DRCDM;
+ }
+};
+
+class DXILResourceCounterDirectionWrapperPass : public ImmutablePass {
+ DXILResourceCounterDirectionMap DRCDM;
+
+ virtual void anchor();
+
+public:
+ static char ID;
+ DXILResourceCounterDirectionWrapperPass();
+
+ DXILResourceCounterDirectionMap &getResourceCounterDirectionMap() { return DRCDM; }
+ const DXILResourceCounterDirectionMap &getResourceCounterDirectionMap() const { return DRCDM; }
+};
+
+ModulePass *createDXILResourceCounterDirectionWrapperPassPass();
+
class DXILResourceTypeAnalysis
: public AnalysisInfoMixin<DXILResourceTypeAnalysis> {
friend AnalysisInfoMixin<DXILResourceTypeAnalysis>;
diff --git a/llvm/include/llvm/InitializePasses.h b/llvm/include/llvm/InitializePasses.h
index 0dfb46a210c7e..3848f0dd6fe03 100644
--- a/llvm/include/llvm/InitializePasses.h
+++ b/llvm/include/llvm/InitializePasses.h
@@ -85,6 +85,7 @@ void initializeDCELegacyPassPass(PassRegistry &);
void initializeDXILMetadataAnalysisWrapperPassPass(PassRegistry &);
void initializeDXILMetadataAnalysisWrapperPrinterPass(PassRegistry &);
void initializeDXILResourceBindingWrapperPassPass(PassRegistry &);
+void initializeDXILResourceCounterDirectionWrapperPassPass(PassRegistry &);
void initializeDXILResourceTypeWrapperPassPass(PassRegistry &);
void initializeDeadMachineInstructionElimPass(PassRegistry &);
void initializeDebugifyMachineModulePass(PassRegistry &);
diff --git a/llvm/lib/Analysis/DXILResource.cpp b/llvm/lib/Analysis/DXILResource.cpp
index c0319c9a354a6..59e432075db17 100644
--- a/llvm/lib/Analysis/DXILResource.cpp
+++ b/llvm/lib/Analysis/DXILResource.cpp
@@ -19,6 +19,7 @@
#include "llvm/IR/Module.h"
#include "llvm/InitializePasses.h"
#include "llvm/Support/FormatVariadic.h"
+#include <algorithm>
#define DEBUG_TYPE "dxil-resource"
@@ -818,8 +819,88 @@ DXILBindingMap::findByUse(const Value *Key) const {
//===----------------------------------------------------------------------===//
+static bool isUpdateCounterIntrinsic(Function &F) {
+ return F.getIntrinsicID() == Intrinsic::dx_resource_updatecounter;
+}
+
+void DXILResourceCounterDirectionMap::populate(Module &M, ModuleAnalysisManager &AM) {
+ DXILBindingMap &DBM = AM.getResult<DXILResourceBindingAnalysis>(M);
+ CounterDirections.clear();
+
+ for (Function &F : M.functions()) {
+ if (!isUpdateCounterIntrinsic(F))
+ continue;
+
+ for (const User *U : F.users()) {
+ const CallInst *CI = dyn_cast<CallInst>(U);
+ assert(CI && "Users of dx_resource_updateCounter must be call instrs");
+
+ // Determine if the use is an increment or decrement
+ Value *CountArg = CI->getArgOperand(1);
+ ConstantInt *CountValue = dyn_cast<ConstantInt>(CountArg);
+ int64_t CountLiteral = CountValue->getSExtValue();
+
+ ResourceCounterDirection Direction = ResourceCounterDirection::Unknown;
+ if (CountLiteral > 0) {
+ Direction = ResourceCounterDirection::Increment;
+ }
+ if (CountLiteral < 0) {
+ Direction = ResourceCounterDirection::Decrement;
+ }
+
+
+ // Collect all potential creation points for the handle arg
+ Value *HandleArg = CI->getArgOperand(0);
+ SmallVector<dxil::ResourceBindingInfo> RBInfos = DBM.findByUse(HandleArg);
+ for(const dxil::ResourceBindingInfo RBInfo : RBInfos) {
+ CounterDirections.emplace_back(RBInfo, Direction);
+ }
+ }
+ }
+
+ // An entry that is not in the map is considered unknown so its wasted
+ // overhead and increased complexity to keep it so it should be removed.
+ const auto RemoveEnd = std::remove_if(CounterDirections.begin(), CounterDirections.end(), [](const auto& Item) {
+ return Item.second == ResourceCounterDirection::Unknown;
+ });
+
+ // Order for fast lookup
+ std::sort(CounterDirections.begin(), RemoveEnd);
+
+ // Remove the duplicate entries. Since direction is considered for equality
+ // a unique resource with more than one direction will not be deduped.
+ const auto UniqueEnd = std::unique(CounterDirections.begin(), RemoveEnd);
+
+ // Actually erase the items invalidated by remove_if + unique
+ CounterDirections.erase(UniqueEnd, CounterDirections.end());
+
+ // If any duplicate entries still exist at this point then it must be a
+ // resource that was both incremented and decremented which is not allowed.
+ const auto DuplicateEntry = std::adjacent_find(CounterDirections.begin(), CounterDirections.end(), [](const auto& LHS, const auto& RHS){
+ return LHS.first == RHS.first;
+ });
+ if (DuplicateEntry == CounterDirections.end())
+ return;
+
+ // TODO: Emit an error message
+ assert(CounterDirections.size() == 1 && "dups found");
+}
+
+bool DXILResourceCounterDirectionMap::invalidate(Module &M, const PreservedAnalyses &PA,
+ ModuleAnalysisManager::Invalidator &Inv) {
+ // Passes that introduce resource types must explicitly invalidate this pass.
+ // auto PAC = PA.getChecker<DXILResourceTypeAnalysis>();
+ // return !PAC.preservedWhenStateless();
+ return false;
+}
+
+void DXILResourceCounterDirectionWrapperPass::anchor() {}
+
+//===----------------------------------------------------------------------===//
+
AnalysisKey DXILResourceTypeAnalysis::Key;
AnalysisKey DXILResourceBindingAnalysis::Key;
+AnalysisKey DXILResourceCounterDirectionAnalysis::Key;
DXILBindingMap DXILResourceBindingAnalysis::run(Module &M,
ModuleAnalysisManager &AM) {
@@ -838,6 +919,13 @@ DXILResourceBindingPrinterPass::run(Module &M, ModuleAnalysisManager &AM) {
return PreservedAnalyses::all();
}
+INITIALIZE_PASS(DXILResourceCounterDirectionWrapperPass, "dxil-resource-counter",
+ "DXIL Resource Counter Analysis", false, true)
+
+DXILResourceCounterDirectionWrapperPass::DXILResourceCounterDirectionWrapperPass() : ImmutablePass(ID) {
+ initializeDXILResourceTypeWrapperPassPass(*PassRegistry::getPassRegistry());
+}
+
void DXILResourceTypeWrapperPass::anchor() {}
DXILResourceTypeWrapperPass::DXILResourceTypeWrapperPass() : ImmutablePass(ID) {
@@ -847,11 +935,16 @@ DXILResourceTypeWrapperPass::DXILResourceTypeWrapperPass() : ImmutablePass(ID) {
INITIALIZE_PASS(DXILResourceTypeWrapperPass, "dxil-resource-type",
"DXIL Resource Type Analysis", false, true)
char DXILResourceTypeWrapperPass::ID = 0;
+char DXILResourceCounterDirectionWrapperPass::ID = 0;
ModulePass *llvm::createDXILResourceTypeWrapperPassPass() {
return new DXILResourceTypeWrapperPass();
}
+ModulePass *llvm::createDXILResourceCounterDirectionWrapperPassPass() {
+ return new DXILResourceCounterDirectionWrapperPass();
+}
+
DXILResourceBindingWrapperPass::DXILResourceBindingWrapperPass()
: ModulePass(ID) {
initializeDXILResourceBindingWrapperPassPass(
diff --git a/llvm/unittests/Target/DirectX/UniqueResourceFromUseTests.cpp b/llvm/unittests/Target/DirectX/UniqueResourceFromUseTests.cpp
index f272381c0c250..a991cf230d930 100644
--- a/llvm/unittests/Target/DirectX/UniqueResourceFromUseTests.cpp
+++ b/llvm/unittests/Target/DirectX/UniqueResourceFromUseTests.cpp
@@ -35,6 +35,7 @@ class UniqueResourceFromUseTest : public testing::Test {
PB->registerModuleAnalyses(*MAM);
MAM->registerPass([&] { return DXILResourceTypeAnalysis(); });
MAM->registerPass([&] { return DXILResourceBindingAnalysis(); });
+ MAM->registerPass([&] { return DXILResourceCounterDirectionAnalysis(); });
}
virtual void TearDown() {
@@ -280,4 +281,47 @@ declare target("dx.RawBuffer", float, 1, 0) @ind.func(target("dx.RawBuffer", flo
}
}
+TEST_F(UniqueResourceFromUseTest, TestResourceCounter) {
+ StringRef Assembly = R"(
+define void @main() {
+entry:
+ %handle = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_f32_1_0t(i32 1, i32 2, i32 3, i32 4, i1 false)
+ call i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %handle, i8 -1)
+ call i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %handle, i8 -1)
+ call i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %handle, i8 -1)
+ call i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %handle, i8 -1)
+ call i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %handle, i8 -1)
+ call i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %handle, i8 -1)
+ call void @a.func(target("dx.RawBuffer", float, 1, 0) %handle)
+ ret void
+}
+
+declare target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_f32_1_0t(i32, i32, i32, i32, i1)
+declare i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0), i8)
+declare void @a.func(target("dx.RawBuffer", float, 1, 0) %handle)
+ )";
+
+ LLVMContext Context;
+ SMDiagnostic Error;
+ auto M = parseAssemblyString(Assembly, Error, Context);
+ ASSERT_TRUE(M) << "Bad assembly?";
+
+ const DXILBindingMap &DBM = MAM->getResult<DXILResourceBindingAnalysis>(*M);
+ const DXILResourceCounterDirectionMap &DCDM = MAM->getResult<DXILResourceCounterDirectionAnalysis>(*M);
+
+ for (const Function &F : M->functions()) {
+ if (F.getName() != "a.func") {
+ continue;
+ }
+
+ for (const User *U : F.users()) {
+ const CallInst *CI = cast<CallInst>(U);
+ const Value *Handle = CI->getArgOperand(0);
+ const auto Bindings = DBM.findByUse(Handle);
+ ASSERT_EQ(Bindings.size(), 1u);
+ ASSERT_EQ(DCDM[Bindings.front()], ResourceCounterDirection::Decrement);
+ }
+ }
+}
+
} // namespace
>From 28e7369e462a7b2b7bac3c0e01351b8cb7dfb6c0 Mon Sep 17 00:00:00 2001
From: Ashley Coleman <ascoleman at microsoft.com>
Date: Wed, 5 Mar 2025 17:23:36 -0700
Subject: [PATCH 02/11] format
---
llvm/include/llvm/Analysis/DXILResource.h | 26 ++--
llvm/lib/Analysis/DXILResource.cpp | 117 +++++++++---------
.../DirectX/UniqueResourceFromUseTests.cpp | 3 +-
3 files changed, 80 insertions(+), 66 deletions(-)
diff --git a/llvm/include/llvm/Analysis/DXILResource.h b/llvm/include/llvm/Analysis/DXILResource.h
index 3f11b07cd75eb..61ee3b99d250f 100644
--- a/llvm/include/llvm/Analysis/DXILResource.h
+++ b/llvm/include/llvm/Analysis/DXILResource.h
@@ -418,18 +418,21 @@ enum ResourceCounterDirection {
};
class DXILResourceCounterDirectionMap {
- std::vector<std::pair<dxil::ResourceBindingInfo, ResourceCounterDirection>> CounterDirections;
+ std::vector<std::pair<dxil::ResourceBindingInfo, ResourceCounterDirection>>
+ CounterDirections;
public:
bool invalidate(Module &M, const PreservedAnalyses &PA,
ModuleAnalysisManager::Invalidator &Inv);
- void populate(Module &M, ModuleAnalysisManager &AM);
+ void populate(Module &M, ModuleAnalysisManager &AM);
- ResourceCounterDirection operator[](const dxil::ResourceBindingInfo &Info) const {
- auto Lower = std::lower_bound(CounterDirections.begin(), CounterDirections.end(), std::pair{Info, ResourceCounterDirection::Unknown}, [](auto lhs, auto rhs){
- return lhs.first < rhs.first;
- });
+ ResourceCounterDirection
+ operator[](const dxil::ResourceBindingInfo &Info) const {
+ auto Lower = std::lower_bound(
+ CounterDirections.begin(), CounterDirections.end(),
+ std::pair{Info, ResourceCounterDirection::Unknown},
+ [](auto lhs, auto rhs) { return lhs.first < rhs.first; });
if (Lower == CounterDirections.end()) {
return ResourceCounterDirection::Unknown;
@@ -440,7 +443,7 @@ class DXILResourceCounterDirectionMap {
}
return Lower->second;
- }
+ }
};
class DXILResourceCounterDirectionAnalysis
@@ -468,8 +471,13 @@ class DXILResourceCounterDirectionWrapperPass : public ImmutablePass {
static char ID;
DXILResourceCounterDirectionWrapperPass();
- DXILResourceCounterDirectionMap &getResourceCounterDirectionMap() { return DRCDM; }
- const DXILResourceCounterDirectionMap &getResourceCounterDirectionMap() const { return DRCDM; }
+ DXILResourceCounterDirectionMap &getResourceCounterDirectionMap() {
+ return DRCDM;
+ }
+ const DXILResourceCounterDirectionMap &
+ getResourceCounterDirectionMap() const {
+ return DRCDM;
+ }
};
ModulePass *createDXILResourceCounterDirectionWrapperPassPass();
diff --git a/llvm/lib/Analysis/DXILResource.cpp b/llvm/lib/Analysis/DXILResource.cpp
index 59e432075db17..d274de11d9bc0 100644
--- a/llvm/lib/Analysis/DXILResource.cpp
+++ b/llvm/lib/Analysis/DXILResource.cpp
@@ -823,71 +823,73 @@ static bool isUpdateCounterIntrinsic(Function &F) {
return F.getIntrinsicID() == Intrinsic::dx_resource_updatecounter;
}
-void DXILResourceCounterDirectionMap::populate(Module &M, ModuleAnalysisManager &AM) {
- DXILBindingMap &DBM = AM.getResult<DXILResourceBindingAnalysis>(M);
- CounterDirections.clear();
-
- for (Function &F : M.functions()) {
- if (!isUpdateCounterIntrinsic(F))
- continue;
-
- for (const User *U : F.users()) {
- const CallInst *CI = dyn_cast<CallInst>(U);
- assert(CI && "Users of dx_resource_updateCounter must be call instrs");
-
- // Determine if the use is an increment or decrement
- Value *CountArg = CI->getArgOperand(1);
- ConstantInt *CountValue = dyn_cast<ConstantInt>(CountArg);
- int64_t CountLiteral = CountValue->getSExtValue();
-
- ResourceCounterDirection Direction = ResourceCounterDirection::Unknown;
- if (CountLiteral > 0) {
- Direction = ResourceCounterDirection::Increment;
- }
- if (CountLiteral < 0) {
- Direction = ResourceCounterDirection::Decrement;
- }
+void DXILResourceCounterDirectionMap::populate(Module &M,
+ ModuleAnalysisManager &AM) {
+ DXILBindingMap &DBM = AM.getResult<DXILResourceBindingAnalysis>(M);
+ CounterDirections.clear();
+ for (Function &F : M.functions()) {
+ if (!isUpdateCounterIntrinsic(F))
+ continue;
- // Collect all potential creation points for the handle arg
- Value *HandleArg = CI->getArgOperand(0);
- SmallVector<dxil::ResourceBindingInfo> RBInfos = DBM.findByUse(HandleArg);
- for(const dxil::ResourceBindingInfo RBInfo : RBInfos) {
- CounterDirections.emplace_back(RBInfo, Direction);
- }
+ for (const User *U : F.users()) {
+ const CallInst *CI = dyn_cast<CallInst>(U);
+ assert(CI && "Users of dx_resource_updateCounter must be call instrs");
+
+ // Determine if the use is an increment or decrement
+ Value *CountArg = CI->getArgOperand(1);
+ ConstantInt *CountValue = dyn_cast<ConstantInt>(CountArg);
+ int64_t CountLiteral = CountValue->getSExtValue();
+
+ ResourceCounterDirection Direction = ResourceCounterDirection::Unknown;
+ if (CountLiteral > 0) {
+ Direction = ResourceCounterDirection::Increment;
+ }
+ if (CountLiteral < 0) {
+ Direction = ResourceCounterDirection::Decrement;
+ }
+
+ // Collect all potential creation points for the handle arg
+ Value *HandleArg = CI->getArgOperand(0);
+ SmallVector<dxil::ResourceBindingInfo> RBInfos = DBM.findByUse(HandleArg);
+ for (const dxil::ResourceBindingInfo RBInfo : RBInfos) {
+ CounterDirections.emplace_back(RBInfo, Direction);
}
}
+ }
- // An entry that is not in the map is considered unknown so its wasted
- // overhead and increased complexity to keep it so it should be removed.
- const auto RemoveEnd = std::remove_if(CounterDirections.begin(), CounterDirections.end(), [](const auto& Item) {
- return Item.second == ResourceCounterDirection::Unknown;
- });
+ // An entry that is not in the map is considered unknown so its wasted
+ // overhead and increased complexity to keep it so it should be removed.
+ const auto RemoveEnd = std::remove_if(
+ CounterDirections.begin(), CounterDirections.end(), [](const auto &Item) {
+ return Item.second == ResourceCounterDirection::Unknown;
+ });
- // Order for fast lookup
- std::sort(CounterDirections.begin(), RemoveEnd);
+ // Order for fast lookup
+ std::sort(CounterDirections.begin(), RemoveEnd);
- // Remove the duplicate entries. Since direction is considered for equality
- // a unique resource with more than one direction will not be deduped.
- const auto UniqueEnd = std::unique(CounterDirections.begin(), RemoveEnd);
+ // Remove the duplicate entries. Since direction is considered for equality
+ // a unique resource with more than one direction will not be deduped.
+ const auto UniqueEnd = std::unique(CounterDirections.begin(), RemoveEnd);
- // Actually erase the items invalidated by remove_if + unique
- CounterDirections.erase(UniqueEnd, CounterDirections.end());
+ // Actually erase the items invalidated by remove_if + unique
+ CounterDirections.erase(UniqueEnd, CounterDirections.end());
- // If any duplicate entries still exist at this point then it must be a
- // resource that was both incremented and decremented which is not allowed.
- const auto DuplicateEntry = std::adjacent_find(CounterDirections.begin(), CounterDirections.end(), [](const auto& LHS, const auto& RHS){
- return LHS.first == RHS.first;
- });
- if (DuplicateEntry == CounterDirections.end())
- return;
+ // If any duplicate entries still exist at this point then it must be a
+ // resource that was both incremented and decremented which is not allowed.
+ const auto DuplicateEntry = std::adjacent_find(
+ CounterDirections.begin(), CounterDirections.end(),
+ [](const auto &LHS, const auto &RHS) { return LHS.first == RHS.first; });
+ if (DuplicateEntry == CounterDirections.end())
+ return;
- // TODO: Emit an error message
- assert(CounterDirections.size() == 1 && "dups found");
+ // TODO: Emit an error message
+ assert(CounterDirections.size() == 1 && "dups found");
}
-bool DXILResourceCounterDirectionMap::invalidate(Module &M, const PreservedAnalyses &PA,
- ModuleAnalysisManager::Invalidator &Inv) {
+bool DXILResourceCounterDirectionMap::invalidate(
+ Module &M, const PreservedAnalyses &PA,
+ ModuleAnalysisManager::Invalidator &Inv) {
// Passes that introduce resource types must explicitly invalidate this pass.
// auto PAC = PA.getChecker<DXILResourceTypeAnalysis>();
// return !PAC.preservedWhenStateless();
@@ -919,10 +921,13 @@ DXILResourceBindingPrinterPass::run(Module &M, ModuleAnalysisManager &AM) {
return PreservedAnalyses::all();
}
-INITIALIZE_PASS(DXILResourceCounterDirectionWrapperPass, "dxil-resource-counter",
- "DXIL Resource Counter Analysis", false, true)
+INITIALIZE_PASS(DXILResourceCounterDirectionWrapperPass,
+ "dxil-resource-counter", "DXIL Resource Counter Analysis",
+ false, true)
-DXILResourceCounterDirectionWrapperPass::DXILResourceCounterDirectionWrapperPass() : ImmutablePass(ID) {
+DXILResourceCounterDirectionWrapperPass::
+ DXILResourceCounterDirectionWrapperPass()
+ : ImmutablePass(ID) {
initializeDXILResourceTypeWrapperPassPass(*PassRegistry::getPassRegistry());
}
diff --git a/llvm/unittests/Target/DirectX/UniqueResourceFromUseTests.cpp b/llvm/unittests/Target/DirectX/UniqueResourceFromUseTests.cpp
index a991cf230d930..9cacd005f6b14 100644
--- a/llvm/unittests/Target/DirectX/UniqueResourceFromUseTests.cpp
+++ b/llvm/unittests/Target/DirectX/UniqueResourceFromUseTests.cpp
@@ -307,7 +307,8 @@ declare void @a.func(target("dx.RawBuffer", float, 1, 0) %handle)
ASSERT_TRUE(M) << "Bad assembly?";
const DXILBindingMap &DBM = MAM->getResult<DXILResourceBindingAnalysis>(*M);
- const DXILResourceCounterDirectionMap &DCDM = MAM->getResult<DXILResourceCounterDirectionAnalysis>(*M);
+ const DXILResourceCounterDirectionMap &DCDM =
+ MAM->getResult<DXILResourceCounterDirectionAnalysis>(*M);
for (const Function &F : M->functions()) {
if (F.getName() != "a.func") {
>From 90621829cb71e6a2fcd465728f2b1e586dd03f1c Mon Sep 17 00:00:00 2001
From: Ashley Coleman <ascoleman at microsoft.com>
Date: Fri, 7 Mar 2025 14:57:00 -0700
Subject: [PATCH 03/11] Add Diag and tests
---
llvm/lib/Analysis/DXILResource.cpp | 10 +-
llvm/lib/Passes/PassRegistry.def | 1 +
llvm/lib/Target/DirectX/DXILOpLowering.cpp | 1 +
.../CodeGen/DirectX/resource_counter_error.ll | 13 ++
.../DirectX/UniqueResourceFromUseTests.cpp | 130 +++++++++++++++++-
5 files changed, 147 insertions(+), 8 deletions(-)
create mode 100644 llvm/test/CodeGen/DirectX/resource_counter_error.ll
diff --git a/llvm/lib/Analysis/DXILResource.cpp b/llvm/lib/Analysis/DXILResource.cpp
index d274de11d9bc0..82a42e5c44359 100644
--- a/llvm/lib/Analysis/DXILResource.cpp
+++ b/llvm/lib/Analysis/DXILResource.cpp
@@ -9,6 +9,7 @@
#include "llvm/Analysis/DXILResource.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/DiagnosticInfo.h"
@@ -20,6 +21,7 @@
#include "llvm/InitializePasses.h"
#include "llvm/Support/FormatVariadic.h"
#include <algorithm>
+#include "llvm/IR/DiagnosticInfo.h"
#define DEBUG_TYPE "dxil-resource"
@@ -858,8 +860,8 @@ void DXILResourceCounterDirectionMap::populate(Module &M,
}
}
- // An entry that is not in the map is considered unknown so its wasted
- // overhead and increased complexity to keep it so it should be removed.
+ // An entry that is not in the map is considered unknown so its wasted overhead
+ // and increased complexity to keep an entry explicitly marked unknown
const auto RemoveEnd = std::remove_if(
CounterDirections.begin(), CounterDirections.end(), [](const auto &Item) {
return Item.second == ResourceCounterDirection::Unknown;
@@ -883,8 +885,8 @@ void DXILResourceCounterDirectionMap::populate(Module &M,
if (DuplicateEntry == CounterDirections.end())
return;
- // TODO: Emit an error message
- assert(CounterDirections.size() == 1 && "dups found");
+ StringRef Message = "RWStructuredBuffers may increment or decrement their counters, but not both.";
+ M.getContext().diagnose(DiagnosticInfoGeneric(Message));
}
bool DXILResourceCounterDirectionMap::invalidate(
diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def
index a664d6fd7085f..5812add8c701a 100644
--- a/llvm/lib/Passes/PassRegistry.def
+++ b/llvm/lib/Passes/PassRegistry.def
@@ -24,6 +24,7 @@ MODULE_ANALYSIS("ctx-prof-analysis", CtxProfAnalysis())
MODULE_ANALYSIS("dxil-metadata", DXILMetadataAnalysis())
MODULE_ANALYSIS("dxil-resource-binding", DXILResourceBindingAnalysis())
MODULE_ANALYSIS("dxil-resource-type", DXILResourceTypeAnalysis())
+MODULE_ANALYSIS("dxil-resource-counter-direction", DXILResourceCounterDirectionAnalysis())
MODULE_ANALYSIS("inline-advisor", InlineAdvisorAnalysis())
MODULE_ANALYSIS("ir-similarity", IRSimilarityAnalysis())
MODULE_ANALYSIS("last-run-tracking", LastRunTrackingAnalysis())
diff --git a/llvm/lib/Target/DirectX/DXILOpLowering.cpp b/llvm/lib/Target/DirectX/DXILOpLowering.cpp
index 83cc4b18824c7..b4bf40d26489f 100644
--- a/llvm/lib/Target/DirectX/DXILOpLowering.cpp
+++ b/llvm/lib/Target/DirectX/DXILOpLowering.cpp
@@ -816,6 +816,7 @@ class OpLowerer {
PreservedAnalyses DXILOpLowering::run(Module &M, ModuleAnalysisManager &MAM) {
DXILBindingMap &DBM = MAM.getResult<DXILResourceBindingAnalysis>(M);
DXILResourceTypeMap &DRTM = MAM.getResult<DXILResourceTypeAnalysis>(M);
+ DXILResourceCounterDirectionMap &DRCDM = MAM.getResult<DXILResourceCounterDirectionAnalysis>(M);
bool MadeChanges = OpLowerer(M, DBM, DRTM).lowerIntrinsics();
if (!MadeChanges)
diff --git a/llvm/test/CodeGen/DirectX/resource_counter_error.ll b/llvm/test/CodeGen/DirectX/resource_counter_error.ll
new file mode 100644
index 0000000000000..48ce32031ef00
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/resource_counter_error.ll
@@ -0,0 +1,13 @@
+; RUN: not opt -S -passes='dxil-op-lower' -mtriple=dxil-pc-shadermodel6.3-library %s 2>&1 | FileCheck %s
+; CHECK: RWStructuredBuffers may increment or decrement their counters, but not both.
+
+define void @inc_and_dec() {
+entry:
+ %handle = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_f32_1_0t(i32 1, i32 2, i32 3, i32 4, i1 false)
+ call i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %handle, i8 -1)
+ call i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %handle, i8 1)
+ ret void
+}
+
+declare target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_f32_1_0t(i32, i32, i32, i32, i1)
+declare i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0), i8)
diff --git a/llvm/unittests/Target/DirectX/UniqueResourceFromUseTests.cpp b/llvm/unittests/Target/DirectX/UniqueResourceFromUseTests.cpp
index 9cacd005f6b14..c9c526ef058ea 100644
--- a/llvm/unittests/Target/DirectX/UniqueResourceFromUseTests.cpp
+++ b/llvm/unittests/Target/DirectX/UniqueResourceFromUseTests.cpp
@@ -281,7 +281,7 @@ declare target("dx.RawBuffer", float, 1, 0) @ind.func(target("dx.RawBuffer", flo
}
}
-TEST_F(UniqueResourceFromUseTest, TestResourceCounter) {
+TEST_F(UniqueResourceFromUseTest, TestResourceCounterDecrement) {
StringRef Assembly = R"(
define void @main() {
entry:
@@ -289,9 +289,6 @@ define void @main() {
call i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %handle, i8 -1)
call i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %handle, i8 -1)
call i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %handle, i8 -1)
- call i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %handle, i8 -1)
- call i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %handle, i8 -1)
- call i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %handle, i8 -1)
call void @a.func(target("dx.RawBuffer", float, 1, 0) %handle)
ret void
}
@@ -325,4 +322,129 @@ declare void @a.func(target("dx.RawBuffer", float, 1, 0) %handle)
}
}
+TEST_F(UniqueResourceFromUseTest, TestResourceCounterIncrement) {
+ StringRef Assembly = R"(
+define void @main() {
+entry:
+ %handle = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_f32_1_0t(i32 1, i32 2, i32 3, i32 4, i1 false)
+ call i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %handle, i8 1)
+ call i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %handle, i8 1)
+ call i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %handle, i8 1)
+ call void @a.func(target("dx.RawBuffer", float, 1, 0) %handle)
+ ret void
+}
+
+declare target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_f32_1_0t(i32, i32, i32, i32, i1)
+declare i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0), i8)
+declare void @a.func(target("dx.RawBuffer", float, 1, 0) %handle)
+ )";
+
+ LLVMContext Context;
+ SMDiagnostic Error;
+ auto M = parseAssemblyString(Assembly, Error, Context);
+ ASSERT_TRUE(M) << "Bad assembly?";
+
+ const DXILBindingMap &DBM = MAM->getResult<DXILResourceBindingAnalysis>(*M);
+ const DXILResourceCounterDirectionMap &DCDM =
+ MAM->getResult<DXILResourceCounterDirectionAnalysis>(*M);
+
+ for (const Function &F : M->functions()) {
+ if (F.getName() != "a.func") {
+ continue;
+ }
+
+ for (const User *U : F.users()) {
+ const CallInst *CI = cast<CallInst>(U);
+ const Value *Handle = CI->getArgOperand(0);
+ const auto Bindings = DBM.findByUse(Handle);
+ ASSERT_EQ(Bindings.size(), 1u);
+ ASSERT_EQ(DCDM[Bindings.front()], ResourceCounterDirection::Increment);
+ }
+ }
+}
+
+TEST_F(UniqueResourceFromUseTest, TestResourceCounterUnknown) {
+ StringRef Assembly = R"(
+define void @main() {
+entry:
+ %handle = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_f32_1_0t(i32 1, i32 2, i32 3, i32 4, i1 false)
+ call void @a.func(target("dx.RawBuffer", float, 1, 0) %handle)
+ ret void
+}
+
+declare target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_f32_1_0t(i32, i32, i32, i32, i1)
+declare i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0), i8)
+declare void @a.func(target("dx.RawBuffer", float, 1, 0) %handle)
+ )";
+
+ LLVMContext Context;
+ SMDiagnostic Error;
+ auto M = parseAssemblyString(Assembly, Error, Context);
+ ASSERT_TRUE(M) << "Bad assembly?";
+
+ const DXILBindingMap &DBM = MAM->getResult<DXILResourceBindingAnalysis>(*M);
+ const DXILResourceCounterDirectionMap &DCDM =
+ MAM->getResult<DXILResourceCounterDirectionAnalysis>(*M);
+
+ for (const Function &F : M->functions()) {
+ if (F.getName() != "a.func") {
+ continue;
+ }
+
+ for (const User *U : F.users()) {
+ const CallInst *CI = cast<CallInst>(U);
+ const Value *Handle = CI->getArgOperand(0);
+ const auto Bindings = DBM.findByUse(Handle);
+ ASSERT_EQ(Bindings.size(), 1u);
+ ASSERT_EQ(DCDM[Bindings.front()], ResourceCounterDirection::Unknown);
+ }
+ }
+}
+
+TEST_F(UniqueResourceFromUseTest, TestResourceCounterMultiple) {
+ StringRef Assembly = R"(
+define void @main() {
+entry:
+ %handle1 = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_f32_1_0t(i32 1, i32 2, i32 3, i32 4, i1 false)
+ %handle2 = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_f32_1_0t(i32 4, i32 3, i32 2, i32 1, i1 false)
+ call i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %handle1, i8 -1)
+ call i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %handle2, i8 1)
+ call void @a.func(target("dx.RawBuffer", float, 1, 0) %handle1)
+ call void @b.func(target("dx.RawBuffer", float, 1, 0) %handle2)
+ ret void
+}
+
+declare target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_f32_1_0t(i32, i32, i32, i32, i1)
+declare i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0), i8)
+declare void @a.func(target("dx.RawBuffer", float, 1, 0) %handle)
+declare void @b.func(target("dx.RawBuffer", float, 1, 0) %handle)
+ )";
+
+ LLVMContext Context;
+ SMDiagnostic Error;
+ auto M = parseAssemblyString(Assembly, Error, Context);
+ ASSERT_TRUE(M) << "Bad assembly?";
+
+ const DXILBindingMap &DBM = MAM->getResult<DXILResourceBindingAnalysis>(*M);
+ const DXILResourceCounterDirectionMap &DCDM =
+ MAM->getResult<DXILResourceCounterDirectionAnalysis>(*M);
+
+ for (const Function &F : M->functions()) {
+ StringRef FName = F.getName();
+ if (FName != "a.func" && FName != "b.func") {
+ continue;
+ }
+
+ auto Dir = FName == "a.func" ? ResourceCounterDirection::Decrement : ResourceCounterDirection::Increment;
+
+ for (const User *U : F.users()) {
+ const CallInst *CI = cast<CallInst>(U);
+ const Value *Handle = CI->getArgOperand(0);
+ const auto Bindings = DBM.findByUse(Handle);
+ ASSERT_EQ(Bindings.size(), 1u);
+ ASSERT_EQ(DCDM[Bindings.front()], Dir);
+ }
+ }
+}
+
} // namespace
>From 7c777715cc05d0d0c8b88bd7221d4d424db3c26c Mon Sep 17 00:00:00 2001
From: Ashley Coleman <ascoleman at microsoft.com>
Date: Fri, 7 Mar 2025 14:57:37 -0700
Subject: [PATCH 04/11] format
---
llvm/lib/Analysis/DXILResource.cpp | 9 +++++----
llvm/lib/Target/DirectX/DXILOpLowering.cpp | 3 ++-
.../Target/DirectX/UniqueResourceFromUseTests.cpp | 3 ++-
3 files changed, 9 insertions(+), 6 deletions(-)
diff --git a/llvm/lib/Analysis/DXILResource.cpp b/llvm/lib/Analysis/DXILResource.cpp
index 82a42e5c44359..b5e28199593a4 100644
--- a/llvm/lib/Analysis/DXILResource.cpp
+++ b/llvm/lib/Analysis/DXILResource.cpp
@@ -21,7 +21,6 @@
#include "llvm/InitializePasses.h"
#include "llvm/Support/FormatVariadic.h"
#include <algorithm>
-#include "llvm/IR/DiagnosticInfo.h"
#define DEBUG_TYPE "dxil-resource"
@@ -860,8 +859,9 @@ void DXILResourceCounterDirectionMap::populate(Module &M,
}
}
- // An entry that is not in the map is considered unknown so its wasted overhead
- // and increased complexity to keep an entry explicitly marked unknown
+ // An entry that is not in the map is considered unknown so its wasted
+ // overhead and increased complexity to keep an entry explicitly marked
+ // unknown
const auto RemoveEnd = std::remove_if(
CounterDirections.begin(), CounterDirections.end(), [](const auto &Item) {
return Item.second == ResourceCounterDirection::Unknown;
@@ -885,7 +885,8 @@ void DXILResourceCounterDirectionMap::populate(Module &M,
if (DuplicateEntry == CounterDirections.end())
return;
- StringRef Message = "RWStructuredBuffers may increment or decrement their counters, but not both.";
+ StringRef Message = "RWStructuredBuffers may increment or decrement their "
+ "counters, but not both.";
M.getContext().diagnose(DiagnosticInfoGeneric(Message));
}
diff --git a/llvm/lib/Target/DirectX/DXILOpLowering.cpp b/llvm/lib/Target/DirectX/DXILOpLowering.cpp
index b4bf40d26489f..ba2f2d9096d03 100644
--- a/llvm/lib/Target/DirectX/DXILOpLowering.cpp
+++ b/llvm/lib/Target/DirectX/DXILOpLowering.cpp
@@ -816,7 +816,8 @@ class OpLowerer {
PreservedAnalyses DXILOpLowering::run(Module &M, ModuleAnalysisManager &MAM) {
DXILBindingMap &DBM = MAM.getResult<DXILResourceBindingAnalysis>(M);
DXILResourceTypeMap &DRTM = MAM.getResult<DXILResourceTypeAnalysis>(M);
- DXILResourceCounterDirectionMap &DRCDM = MAM.getResult<DXILResourceCounterDirectionAnalysis>(M);
+ DXILResourceCounterDirectionMap &DRCDM =
+ MAM.getResult<DXILResourceCounterDirectionAnalysis>(M);
bool MadeChanges = OpLowerer(M, DBM, DRTM).lowerIntrinsics();
if (!MadeChanges)
diff --git a/llvm/unittests/Target/DirectX/UniqueResourceFromUseTests.cpp b/llvm/unittests/Target/DirectX/UniqueResourceFromUseTests.cpp
index c9c526ef058ea..b653bc3127ffc 100644
--- a/llvm/unittests/Target/DirectX/UniqueResourceFromUseTests.cpp
+++ b/llvm/unittests/Target/DirectX/UniqueResourceFromUseTests.cpp
@@ -435,7 +435,8 @@ declare void @b.func(target("dx.RawBuffer", float, 1, 0) %handle)
continue;
}
- auto Dir = FName == "a.func" ? ResourceCounterDirection::Decrement : ResourceCounterDirection::Increment;
+ auto Dir = FName == "a.func" ? ResourceCounterDirection::Decrement
+ : ResourceCounterDirection::Increment;
for (const User *U : F.users()) {
const CallInst *CI = cast<CallInst>(U);
>From 11c731e5a89150a6e2a30a90b8f5591d13ea1571 Mon Sep 17 00:00:00 2001
From: Ashley Coleman <ascoleman at microsoft.com>
Date: Mon, 10 Mar 2025 17:21:29 -0600
Subject: [PATCH 05/11] Use Module Pass
---
llvm/include/llvm/Analysis/DXILResource.h | 147 +++++++++++-----------
llvm/lib/Analysis/DXILResource.cpp | 40 ++++--
2 files changed, 104 insertions(+), 83 deletions(-)
diff --git a/llvm/include/llvm/Analysis/DXILResource.h b/llvm/include/llvm/Analysis/DXILResource.h
index 61ee3b99d250f..749d7739ee2b1 100644
--- a/llvm/include/llvm/Analysis/DXILResource.h
+++ b/llvm/include/llvm/Analysis/DXILResource.h
@@ -20,7 +20,6 @@
#include <algorithm>
#include <cstdint>
-#include <unordered_map>
namespace llvm {
class CallInst;
@@ -411,77 +410,6 @@ class DXILResourceTypeMap {
}
};
-enum ResourceCounterDirection {
- Increment,
- Decrement,
- Unknown,
-};
-
-class DXILResourceCounterDirectionMap {
- std::vector<std::pair<dxil::ResourceBindingInfo, ResourceCounterDirection>>
- CounterDirections;
-
-public:
- bool invalidate(Module &M, const PreservedAnalyses &PA,
- ModuleAnalysisManager::Invalidator &Inv);
-
- void populate(Module &M, ModuleAnalysisManager &AM);
-
- ResourceCounterDirection
- operator[](const dxil::ResourceBindingInfo &Info) const {
- auto Lower = std::lower_bound(
- CounterDirections.begin(), CounterDirections.end(),
- std::pair{Info, ResourceCounterDirection::Unknown},
- [](auto lhs, auto rhs) { return lhs.first < rhs.first; });
-
- if (Lower == CounterDirections.end()) {
- return ResourceCounterDirection::Unknown;
- }
-
- if (Lower->first != Info) {
- return ResourceCounterDirection::Unknown;
- }
-
- return Lower->second;
- }
-};
-
-class DXILResourceCounterDirectionAnalysis
- : public AnalysisInfoMixin<DXILResourceCounterDirectionAnalysis> {
- friend AnalysisInfoMixin<DXILResourceCounterDirectionAnalysis>;
-
- static AnalysisKey Key;
-
-public:
- using Result = DXILResourceCounterDirectionMap;
-
- DXILResourceCounterDirectionMap run(Module &M, ModuleAnalysisManager &AM) {
- DXILResourceCounterDirectionMap DRCDM{};
- DRCDM.populate(M, AM);
- return DRCDM;
- }
-};
-
-class DXILResourceCounterDirectionWrapperPass : public ImmutablePass {
- DXILResourceCounterDirectionMap DRCDM;
-
- virtual void anchor();
-
-public:
- static char ID;
- DXILResourceCounterDirectionWrapperPass();
-
- DXILResourceCounterDirectionMap &getResourceCounterDirectionMap() {
- return DRCDM;
- }
- const DXILResourceCounterDirectionMap &
- getResourceCounterDirectionMap() const {
- return DRCDM;
- }
-};
-
-ModulePass *createDXILResourceCounterDirectionWrapperPassPass();
-
class DXILResourceTypeAnalysis
: public AnalysisInfoMixin<DXILResourceTypeAnalysis> {
friend AnalysisInfoMixin<DXILResourceTypeAnalysis>;
@@ -649,6 +577,81 @@ class DXILResourceBindingWrapperPass : public ModulePass {
ModulePass *createDXILResourceBindingWrapperPassPass();
+enum ResourceCounterDirection {
+ Increment,
+ Decrement,
+ Unknown,
+};
+
+class DXILResourceCounterDirectionMap {
+ std::vector<std::pair<dxil::ResourceBindingInfo, ResourceCounterDirection>>
+ CounterDirections;
+
+public:
+ void populate(Module &M, DXILBindingMap &DBM);
+
+ ResourceCounterDirection
+ operator[](const dxil::ResourceBindingInfo &Info) const {
+ auto Lower = std::lower_bound(
+ CounterDirections.begin(), CounterDirections.end(),
+ std::pair{Info, ResourceCounterDirection::Unknown},
+ [](auto LHS, auto RHS) { return LHS.first < RHS.first; });
+
+ if (Lower == CounterDirections.end()) {
+ return ResourceCounterDirection::Unknown;
+ }
+
+ if (Lower->first != Info) {
+ return ResourceCounterDirection::Unknown;
+ }
+
+ return Lower->second;
+ }
+};
+
+class DXILResourceCounterDirectionAnalysis
+ : public AnalysisInfoMixin<DXILResourceCounterDirectionAnalysis> {
+ friend AnalysisInfoMixin<DXILResourceCounterDirectionAnalysis>;
+
+ static AnalysisKey Key;
+
+public:
+ using Result = DXILResourceCounterDirectionMap;
+
+ DXILResourceCounterDirectionMap run(Module &M, ModuleAnalysisManager &AM) {
+ DXILResourceCounterDirectionMap DRCDM{};
+ DXILBindingMap &DBM = AM.getResult<DXILResourceBindingAnalysis>(M);
+ DRCDM.populate(M, DBM);
+ return DRCDM;
+ }
+};
+
+class DXILResourceCounterDirectionWrapperPass : public ModulePass {
+ std::unique_ptr<DXILResourceCounterDirectionMap> Map;
+
+public:
+ static char ID;
+ DXILResourceCounterDirectionWrapperPass();
+ ~DXILResourceCounterDirectionWrapperPass() override = default;
+
+ DXILResourceCounterDirectionMap &getResourceCounterDirectionMap() {
+ return *Map;
+ }
+ const DXILResourceCounterDirectionMap &
+ getResourceCounterDirectionMap() const {
+ return *Map;
+ }
+
+ void getAnalysisUsage(AnalysisUsage &AU) const override;
+ bool runOnModule(Module &M) override;
+ void releaseMemory() override;
+
+ void print(raw_ostream &OS, const Module *M) const override;
+};
+
+ModulePass *createDXILResourceCounterDirectionWrapperPassPass();
+
+
} // namespace llvm
#endif // LLVM_ANALYSIS_DXILRESOURCE_H
diff --git a/llvm/lib/Analysis/DXILResource.cpp b/llvm/lib/Analysis/DXILResource.cpp
index 82e8af46ec0c1..80d4595efdec7 100644
--- a/llvm/lib/Analysis/DXILResource.cpp
+++ b/llvm/lib/Analysis/DXILResource.cpp
@@ -830,8 +830,7 @@ static bool isUpdateCounterIntrinsic(Function &F) {
}
void DXILResourceCounterDirectionMap::populate(Module &M,
- ModuleAnalysisManager &AM) {
- DXILBindingMap &DBM = AM.getResult<DXILResourceBindingAnalysis>(M);
+ DXILBindingMap &DBM) {
CounterDirections.clear();
for (Function &F : M.functions()) {
@@ -895,17 +894,36 @@ void DXILResourceCounterDirectionMap::populate(Module &M,
M.getContext().diagnose(DiagnosticInfoGeneric(Message));
}
-bool DXILResourceCounterDirectionMap::invalidate(
- Module &M, const PreservedAnalyses &PA,
- ModuleAnalysisManager::Invalidator &Inv) {
- // Passes that introduce resource types must explicitly invalidate this pass.
- // auto PAC = PA.getChecker<DXILResourceTypeAnalysis>();
- // return !PAC.preservedWhenStateless();
+void DXILResourceCounterDirectionWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.addRequiredTransitive<DXILResourceBindingWrapperPass>();
+ AU.setPreservesAll();
+}
+
+bool DXILResourceCounterDirectionWrapperPass::runOnModule(Module &M) {
+ Map.reset(new DXILResourceCounterDirectionMap());
+
+ auto DBM = getAnalysis<DXILResourceBindingWrapperPass>().getBindingMap();
+ Map->populate(M, DBM);
+
return false;
}
-void DXILResourceCounterDirectionWrapperPass::anchor() {}
+void DXILResourceCounterDirectionWrapperPass::releaseMemory() { Map.reset(); }
+
+void DXILResourceCounterDirectionWrapperPass::print(raw_ostream &OS,
+ const Module *M) const {
+ if (!Map) {
+ OS << "No resource directions have been built!\n";
+ return;
+ }
+ //Map->print(OS, *DRTM, M->getDataLayout());
+}
+
+//#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+//LLVM_DUMP_METHOD
+//void DXILResourceCounterDirectionWrapperPass::dump() const { print(dbgs(), nullptr); }
+//#endif
//===----------------------------------------------------------------------===//
AnalysisKey DXILResourceTypeAnalysis::Key;
@@ -935,8 +953,8 @@ INITIALIZE_PASS(DXILResourceCounterDirectionWrapperPass,
DXILResourceCounterDirectionWrapperPass::
DXILResourceCounterDirectionWrapperPass()
- : ImmutablePass(ID) {
- initializeDXILResourceTypeWrapperPassPass(*PassRegistry::getPassRegistry());
+ : ModulePass(ID) {
+ initializeDXILResourceCounterDirectionWrapperPassPass(*PassRegistry::getPassRegistry());
}
void DXILResourceTypeWrapperPass::anchor() {}
>From 955ce1b03413b484a44b50ed670310103ec933c4 Mon Sep 17 00:00:00 2001
From: Ashley Coleman <ascoleman at microsoft.com>
Date: Tue, 11 Mar 2025 10:37:51 -0600
Subject: [PATCH 06/11] comments
---
llvm/lib/Analysis/DXILResource.cpp | 9 +++------
1 file changed, 3 insertions(+), 6 deletions(-)
diff --git a/llvm/lib/Analysis/DXILResource.cpp b/llvm/lib/Analysis/DXILResource.cpp
index 80d4595efdec7..847508fcf4518 100644
--- a/llvm/lib/Analysis/DXILResource.cpp
+++ b/llvm/lib/Analysis/DXILResource.cpp
@@ -847,19 +847,16 @@ void DXILResourceCounterDirectionMap::populate(Module &M,
int64_t CountLiteral = CountValue->getSExtValue();
ResourceCounterDirection Direction = ResourceCounterDirection::Unknown;
- if (CountLiteral > 0) {
+ if (CountLiteral > 0)
Direction = ResourceCounterDirection::Increment;
- }
- if (CountLiteral < 0) {
+ if (CountLiteral < 0)
Direction = ResourceCounterDirection::Decrement;
- }
// Collect all potential creation points for the handle arg
Value *HandleArg = CI->getArgOperand(0);
SmallVector<dxil::ResourceBindingInfo> RBInfos = DBM.findByUse(HandleArg);
- for (const dxil::ResourceBindingInfo RBInfo : RBInfos) {
+ for (const dxil::ResourceBindingInfo RBInfo : RBInfos)
CounterDirections.emplace_back(RBInfo, Direction);
- }
}
}
>From 92f2a467b8a046fb0a16757ed786ba6541127c2b Mon Sep 17 00:00:00 2001
From: Ashley Coleman <ascoleman at microsoft.com>
Date: Tue, 11 Mar 2025 10:44:41 -0600
Subject: [PATCH 07/11] format
---
llvm/include/llvm/Analysis/DXILResource.h | 1 -
llvm/lib/Analysis/DXILResource.cpp | 22 +++++++++++-----------
2 files changed, 11 insertions(+), 12 deletions(-)
diff --git a/llvm/include/llvm/Analysis/DXILResource.h b/llvm/include/llvm/Analysis/DXILResource.h
index 749d7739ee2b1..f4ba17f8e396b 100644
--- a/llvm/include/llvm/Analysis/DXILResource.h
+++ b/llvm/include/llvm/Analysis/DXILResource.h
@@ -651,7 +651,6 @@ class DXILResourceCounterDirectionWrapperPass : public ModulePass {
ModulePass *createDXILResourceCounterDirectionWrapperPassPass();
-
} // namespace llvm
#endif // LLVM_ANALYSIS_DXILRESOURCE_H
diff --git a/llvm/lib/Analysis/DXILResource.cpp b/llvm/lib/Analysis/DXILResource.cpp
index 847508fcf4518..7ba277d0c3c0a 100644
--- a/llvm/lib/Analysis/DXILResource.cpp
+++ b/llvm/lib/Analysis/DXILResource.cpp
@@ -829,8 +829,7 @@ static bool isUpdateCounterIntrinsic(Function &F) {
return F.getIntrinsicID() == Intrinsic::dx_resource_updatecounter;
}
-void DXILResourceCounterDirectionMap::populate(Module &M,
- DXILBindingMap &DBM) {
+void DXILResourceCounterDirectionMap::populate(Module &M, DXILBindingMap &DBM) {
CounterDirections.clear();
for (Function &F : M.functions()) {
@@ -891,7 +890,8 @@ void DXILResourceCounterDirectionMap::populate(Module &M,
M.getContext().diagnose(DiagnosticInfoGeneric(Message));
}
-void DXILResourceCounterDirectionWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
+void DXILResourceCounterDirectionWrapperPass::getAnalysisUsage(
+ AnalysisUsage &AU) const {
AU.addRequiredTransitive<DXILResourceBindingWrapperPass>();
AU.setPreservesAll();
}
@@ -908,19 +908,18 @@ bool DXILResourceCounterDirectionWrapperPass::runOnModule(Module &M) {
void DXILResourceCounterDirectionWrapperPass::releaseMemory() { Map.reset(); }
void DXILResourceCounterDirectionWrapperPass::print(raw_ostream &OS,
- const Module *M) const {
+ const Module *M) const {
if (!Map) {
OS << "No resource directions have been built!\n";
return;
}
- //Map->print(OS, *DRTM, M->getDataLayout());
+ // Map->print(OS, *DRTM, M->getDataLayout());
}
-
-//#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
-//LLVM_DUMP_METHOD
-//void DXILResourceCounterDirectionWrapperPass::dump() const { print(dbgs(), nullptr); }
-//#endif
+// #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+// LLVM_DUMP_METHOD
+// void DXILResourceCounterDirectionWrapperPass::dump() const { print(dbgs(),
+// nullptr); } #endif
//===----------------------------------------------------------------------===//
AnalysisKey DXILResourceTypeAnalysis::Key;
@@ -951,7 +950,8 @@ INITIALIZE_PASS(DXILResourceCounterDirectionWrapperPass,
DXILResourceCounterDirectionWrapperPass::
DXILResourceCounterDirectionWrapperPass()
: ModulePass(ID) {
- initializeDXILResourceCounterDirectionWrapperPassPass(*PassRegistry::getPassRegistry());
+ initializeDXILResourceCounterDirectionWrapperPassPass(
+ *PassRegistry::getPassRegistry());
}
void DXILResourceTypeWrapperPass::anchor() {}
>From 176b8626de121f4270b01d825f85b38592d451ee Mon Sep 17 00:00:00 2001
From: Ashley Coleman <ascoleman at microsoft.com>
Date: Wed, 12 Mar 2025 15:47:43 -0600
Subject: [PATCH 08/11] Add location to error message
---
llvm/lib/Analysis/DXILResource.cpp | 47 ++++++++++++++-----
.../CodeGen/DirectX/resource_counter_error.ll | 2 +-
.../DirectX/UniqueResourceFromUseTests.cpp | 8 ++++
3 files changed, 44 insertions(+), 13 deletions(-)
diff --git a/llvm/lib/Analysis/DXILResource.cpp b/llvm/lib/Analysis/DXILResource.cpp
index 7ba277d0c3c0a..4cb20d9f1ea34 100644
--- a/llvm/lib/Analysis/DXILResource.cpp
+++ b/llvm/lib/Analysis/DXILResource.cpp
@@ -11,6 +11,7 @@
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/IR/Constants.h"
+#include "llvm/IR/DebugLoc.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/Instructions.h"
@@ -21,6 +22,7 @@
#include "llvm/InitializePasses.h"
#include "llvm/Support/FormatVariadic.h"
#include <algorithm>
+#include <iterator>
#define DEBUG_TYPE "dxil-resource"
@@ -830,7 +832,8 @@ static bool isUpdateCounterIntrinsic(Function &F) {
}
void DXILResourceCounterDirectionMap::populate(Module &M, DXILBindingMap &DBM) {
- CounterDirections.clear();
+ std::vector<std::tuple<dxil::ResourceBindingInfo, ResourceCounterDirection, const Function*, const CallInst*>>
+ DiagCounterDirs;
for (Function &F : M.functions()) {
if (!isUpdateCounterIntrinsic(F))
@@ -855,7 +858,7 @@ void DXILResourceCounterDirectionMap::populate(Module &M, DXILBindingMap &DBM) {
Value *HandleArg = CI->getArgOperand(0);
SmallVector<dxil::ResourceBindingInfo> RBInfos = DBM.findByUse(HandleArg);
for (const dxil::ResourceBindingInfo RBInfo : RBInfos)
- CounterDirections.emplace_back(RBInfo, Direction);
+ DiagCounterDirs.emplace_back(RBInfo, Direction, &F, CI);
}
}
@@ -863,31 +866,51 @@ void DXILResourceCounterDirectionMap::populate(Module &M, DXILBindingMap &DBM) {
// overhead and increased complexity to keep an entry explicitly marked
// unknown
const auto RemoveEnd = std::remove_if(
- CounterDirections.begin(), CounterDirections.end(), [](const auto &Item) {
- return Item.second == ResourceCounterDirection::Unknown;
+ DiagCounterDirs.begin(), DiagCounterDirs.end(), [](const auto &Item) {
+ return std::get<ResourceCounterDirection>(Item) == ResourceCounterDirection::Unknown;
});
- // Order for fast lookup
- std::sort(CounterDirections.begin(), RemoveEnd);
+ // Sort by the Binding and Direction for fast lookup
+ std::sort(DiagCounterDirs.begin(), RemoveEnd, [](const auto &LHS, const auto &RHS) {
+ const auto L = std::pair{std::get<dxil::ResourceBindingInfo>(LHS), std::get<ResourceCounterDirection>(LHS)};
+ const auto R = std::pair{std::get<dxil::ResourceBindingInfo>(RHS), std::get<ResourceCounterDirection>(RHS)};
+ return L < R;
+ });
// Remove the duplicate entries. Since direction is considered for equality
// a unique resource with more than one direction will not be deduped.
- const auto UniqueEnd = std::unique(CounterDirections.begin(), RemoveEnd);
+ const auto UniqueEnd = std::unique(DiagCounterDirs.begin(), RemoveEnd, [](const auto &LHS, const auto &RHS) {
+ const auto L = std::pair{std::get<dxil::ResourceBindingInfo>(LHS), std::get<ResourceCounterDirection>(LHS)};
+ const auto R = std::pair{std::get<dxil::ResourceBindingInfo>(RHS), std::get<ResourceCounterDirection>(RHS)};
+ return L == R;
+ });
// Actually erase the items invalidated by remove_if + unique
- CounterDirections.erase(UniqueEnd, CounterDirections.end());
+ DiagCounterDirs.erase(UniqueEnd, DiagCounterDirs.end());
// If any duplicate entries still exist at this point then it must be a
// resource that was both incremented and decremented which is not allowed.
const auto DuplicateEntry = std::adjacent_find(
- CounterDirections.begin(), CounterDirections.end(),
- [](const auto &LHS, const auto &RHS) { return LHS.first == RHS.first; });
- if (DuplicateEntry == CounterDirections.end())
+ DiagCounterDirs.begin(), DiagCounterDirs.end(),
+ [](const auto &LHS, const auto &RHS) {
+ return std::get<dxil::ResourceBindingInfo>(LHS) == std::get<dxil::ResourceBindingInfo>(RHS);
+ });
+
+ // Copy the results into the final vec
+ CounterDirections.clear();
+ CounterDirections.reserve(DiagCounterDirs.size());
+ std::transform(DiagCounterDirs.begin(), DiagCounterDirs.end(), std::back_inserter(CounterDirections), [](const auto &Item){
+ return std::pair{std::get<dxil::ResourceBindingInfo>(Item), std::get<ResourceCounterDirection>(Item)};
+ });
+
+ if (DuplicateEntry == DiagCounterDirs.end())
return;
+ const Function* F = std::get<const Function*>(*DuplicateEntry);
+ const CallInst* CI = std::get<const CallInst*>(*DuplicateEntry);
StringRef Message = "RWStructuredBuffers may increment or decrement their "
"counters, but not both.";
- M.getContext().diagnose(DiagnosticInfoGeneric(Message));
+ M.getContext().diagnose(DiagnosticInfoGenericWithLoc(Message, *F, CI->getDebugLoc()));
}
void DXILResourceCounterDirectionWrapperPass::getAnalysisUsage(
diff --git a/llvm/test/CodeGen/DirectX/resource_counter_error.ll b/llvm/test/CodeGen/DirectX/resource_counter_error.ll
index 48ce32031ef00..bea8dcac572e5 100644
--- a/llvm/test/CodeGen/DirectX/resource_counter_error.ll
+++ b/llvm/test/CodeGen/DirectX/resource_counter_error.ll
@@ -1,5 +1,5 @@
; RUN: not opt -S -passes='dxil-op-lower' -mtriple=dxil-pc-shadermodel6.3-library %s 2>&1 | FileCheck %s
-; CHECK: RWStructuredBuffers may increment or decrement their counters, but not both.
+; CHECK: <unknown>:0:0: RWStructuredBuffers may increment or decrement their counters, but not both.
define void @inc_and_dec() {
entry:
diff --git a/llvm/unittests/Target/DirectX/UniqueResourceFromUseTests.cpp b/llvm/unittests/Target/DirectX/UniqueResourceFromUseTests.cpp
index b653bc3127ffc..76de33e061a3d 100644
--- a/llvm/unittests/Target/DirectX/UniqueResourceFromUseTests.cpp
+++ b/llvm/unittests/Target/DirectX/UniqueResourceFromUseTests.cpp
@@ -281,6 +281,8 @@ declare target("dx.RawBuffer", float, 1, 0) @ind.func(target("dx.RawBuffer", flo
}
}
+// Test that several calls to decrement on the same resource don't raise a
+// Diagnositic and resolves to a single decrement entry
TEST_F(UniqueResourceFromUseTest, TestResourceCounterDecrement) {
StringRef Assembly = R"(
define void @main() {
@@ -322,6 +324,8 @@ declare void @a.func(target("dx.RawBuffer", float, 1, 0) %handle)
}
}
+// Test that several calls to increment on the same resource don't raise a
+// Diagnositic and resolves to a single increment entry
TEST_F(UniqueResourceFromUseTest, TestResourceCounterIncrement) {
StringRef Assembly = R"(
define void @main() {
@@ -363,6 +367,8 @@ declare void @a.func(target("dx.RawBuffer", float, 1, 0) %handle)
}
}
+// Test that looking up a resource that doesn't have the counter updated
+// resoves to unknown
TEST_F(UniqueResourceFromUseTest, TestResourceCounterUnknown) {
StringRef Assembly = R"(
define void @main() {
@@ -401,6 +407,8 @@ declare void @a.func(target("dx.RawBuffer", float, 1, 0) %handle)
}
}
+// Test that multiple different resources with unique incs/decs don't
+// raise a Diagnostic and can be individually checked for direction
TEST_F(UniqueResourceFromUseTest, TestResourceCounterMultiple) {
StringRef Assembly = R"(
define void @main() {
>From 5d1648ae259443c038e9a0c675a8f42db3452eac Mon Sep 17 00:00:00 2001
From: Ashley Coleman <ascoleman at microsoft.com>
Date: Wed, 12 Mar 2025 15:48:19 -0600
Subject: [PATCH 09/11] format
---
llvm/lib/Analysis/DXILResource.cpp | 58 ++++++++++++++++++------------
1 file changed, 35 insertions(+), 23 deletions(-)
diff --git a/llvm/lib/Analysis/DXILResource.cpp b/llvm/lib/Analysis/DXILResource.cpp
index 4cb20d9f1ea34..a06b77b1ac8be 100644
--- a/llvm/lib/Analysis/DXILResource.cpp
+++ b/llvm/lib/Analysis/DXILResource.cpp
@@ -832,7 +832,8 @@ static bool isUpdateCounterIntrinsic(Function &F) {
}
void DXILResourceCounterDirectionMap::populate(Module &M, DXILBindingMap &DBM) {
- std::vector<std::tuple<dxil::ResourceBindingInfo, ResourceCounterDirection, const Function*, const CallInst*>>
+ std::vector<std::tuple<dxil::ResourceBindingInfo, ResourceCounterDirection,
+ const Function *, const CallInst *>>
DiagCounterDirs;
for (Function &F : M.functions()) {
@@ -867,50 +868,61 @@ void DXILResourceCounterDirectionMap::populate(Module &M, DXILBindingMap &DBM) {
// unknown
const auto RemoveEnd = std::remove_if(
DiagCounterDirs.begin(), DiagCounterDirs.end(), [](const auto &Item) {
- return std::get<ResourceCounterDirection>(Item) == ResourceCounterDirection::Unknown;
+ return std::get<ResourceCounterDirection>(Item) ==
+ ResourceCounterDirection::Unknown;
});
// Sort by the Binding and Direction for fast lookup
- std::sort(DiagCounterDirs.begin(), RemoveEnd, [](const auto &LHS, const auto &RHS) {
- const auto L = std::pair{std::get<dxil::ResourceBindingInfo>(LHS), std::get<ResourceCounterDirection>(LHS)};
- const auto R = std::pair{std::get<dxil::ResourceBindingInfo>(RHS), std::get<ResourceCounterDirection>(RHS)};
- return L < R;
- });
+ std::sort(DiagCounterDirs.begin(), RemoveEnd,
+ [](const auto &LHS, const auto &RHS) {
+ const auto L = std::pair{std::get<dxil::ResourceBindingInfo>(LHS),
+ std::get<ResourceCounterDirection>(LHS)};
+ const auto R = std::pair{std::get<dxil::ResourceBindingInfo>(RHS),
+ std::get<ResourceCounterDirection>(RHS)};
+ return L < R;
+ });
// Remove the duplicate entries. Since direction is considered for equality
// a unique resource with more than one direction will not be deduped.
- const auto UniqueEnd = std::unique(DiagCounterDirs.begin(), RemoveEnd, [](const auto &LHS, const auto &RHS) {
- const auto L = std::pair{std::get<dxil::ResourceBindingInfo>(LHS), std::get<ResourceCounterDirection>(LHS)};
- const auto R = std::pair{std::get<dxil::ResourceBindingInfo>(RHS), std::get<ResourceCounterDirection>(RHS)};
- return L == R;
- });
+ const auto UniqueEnd = std::unique(
+ DiagCounterDirs.begin(), RemoveEnd, [](const auto &LHS, const auto &RHS) {
+ const auto L = std::pair{std::get<dxil::ResourceBindingInfo>(LHS),
+ std::get<ResourceCounterDirection>(LHS)};
+ const auto R = std::pair{std::get<dxil::ResourceBindingInfo>(RHS),
+ std::get<ResourceCounterDirection>(RHS)};
+ return L == R;
+ });
// Actually erase the items invalidated by remove_if + unique
DiagCounterDirs.erase(UniqueEnd, DiagCounterDirs.end());
// If any duplicate entries still exist at this point then it must be a
// resource that was both incremented and decremented which is not allowed.
- const auto DuplicateEntry = std::adjacent_find(
- DiagCounterDirs.begin(), DiagCounterDirs.end(),
- [](const auto &LHS, const auto &RHS) {
- return std::get<dxil::ResourceBindingInfo>(LHS) == std::get<dxil::ResourceBindingInfo>(RHS);
- });
+ const auto DuplicateEntry =
+ std::adjacent_find(DiagCounterDirs.begin(), DiagCounterDirs.end(),
+ [](const auto &LHS, const auto &RHS) {
+ return std::get<dxil::ResourceBindingInfo>(LHS) ==
+ std::get<dxil::ResourceBindingInfo>(RHS);
+ });
// Copy the results into the final vec
CounterDirections.clear();
CounterDirections.reserve(DiagCounterDirs.size());
- std::transform(DiagCounterDirs.begin(), DiagCounterDirs.end(), std::back_inserter(CounterDirections), [](const auto &Item){
- return std::pair{std::get<dxil::ResourceBindingInfo>(Item), std::get<ResourceCounterDirection>(Item)};
- });
+ std::transform(DiagCounterDirs.begin(), DiagCounterDirs.end(),
+ std::back_inserter(CounterDirections), [](const auto &Item) {
+ return std::pair{std::get<dxil::ResourceBindingInfo>(Item),
+ std::get<ResourceCounterDirection>(Item)};
+ });
if (DuplicateEntry == DiagCounterDirs.end())
return;
- const Function* F = std::get<const Function*>(*DuplicateEntry);
- const CallInst* CI = std::get<const CallInst*>(*DuplicateEntry);
+ const Function *F = std::get<const Function *>(*DuplicateEntry);
+ const CallInst *CI = std::get<const CallInst *>(*DuplicateEntry);
StringRef Message = "RWStructuredBuffers may increment or decrement their "
"counters, but not both.";
- M.getContext().diagnose(DiagnosticInfoGenericWithLoc(Message, *F, CI->getDebugLoc()));
+ M.getContext().diagnose(
+ DiagnosticInfoGenericWithLoc(Message, *F, CI->getDebugLoc()));
}
void DXILResourceCounterDirectionWrapperPass::getAnalysisUsage(
>From 67c76a0f338a3d774fbb3ac02ccdcacf3445690a Mon Sep 17 00:00:00 2001
From: Ashley Coleman <ascoleman at microsoft.com>
Date: Wed, 12 Mar 2025 17:30:22 -0600
Subject: [PATCH 10/11] Mark resources with invalid use in map
---
llvm/include/llvm/Analysis/DXILResource.h | 1 +
llvm/lib/Analysis/DXILResource.cpp | 43 ++++++++++++++---------
2 files changed, 28 insertions(+), 16 deletions(-)
diff --git a/llvm/include/llvm/Analysis/DXILResource.h b/llvm/include/llvm/Analysis/DXILResource.h
index f4ba17f8e396b..6552357b156b4 100644
--- a/llvm/include/llvm/Analysis/DXILResource.h
+++ b/llvm/include/llvm/Analysis/DXILResource.h
@@ -581,6 +581,7 @@ enum ResourceCounterDirection {
Increment,
Decrement,
Unknown,
+ MyInvalid,
};
class DXILResourceCounterDirectionMap {
diff --git a/llvm/lib/Analysis/DXILResource.cpp b/llvm/lib/Analysis/DXILResource.cpp
index a06b77b1ac8be..1080d460fd1d9 100644
--- a/llvm/lib/Analysis/DXILResource.cpp
+++ b/llvm/lib/Analysis/DXILResource.cpp
@@ -898,12 +898,33 @@ void DXILResourceCounterDirectionMap::populate(Module &M, DXILBindingMap &DBM) {
// If any duplicate entries still exist at this point then it must be a
// resource that was both incremented and decremented which is not allowed.
- const auto DuplicateEntry =
- std::adjacent_find(DiagCounterDirs.begin(), DiagCounterDirs.end(),
- [](const auto &LHS, const auto &RHS) {
- return std::get<dxil::ResourceBindingInfo>(LHS) ==
- std::get<dxil::ResourceBindingInfo>(RHS);
- });
+ // Mark all those entries as invalid.
+ {
+ auto DupFirst = DiagCounterDirs.begin();
+ auto DupNext = DupFirst + 1;
+ auto DupLast = DiagCounterDirs.end();
+ for (; DupFirst < DupLast && DupNext < DupLast; ++DupFirst, ++DupNext) {
+ if (std::get<dxil::ResourceBindingInfo>(*DupFirst) == std::get<dxil::ResourceBindingInfo>(*DupNext)) {
+ std::get<ResourceCounterDirection>(*DupFirst) = ResourceCounterDirection::MyInvalid;
+ std::get<ResourceCounterDirection>(*DupNext) = ResourceCounterDirection::MyInvalid;
+ }
+ }
+ }
+
+ // Raise an error for every invalid entry
+ for (const auto Entry : DiagCounterDirs) {
+ ResourceCounterDirection Dir = std::get<ResourceCounterDirection>(Entry);
+ const Function *F = std::get<const Function *>(Entry);
+ const CallInst *CI = std::get<const CallInst *>(Entry);
+
+ if (Dir != ResourceCounterDirection::MyInvalid)
+ continue;
+
+ StringRef Message = "RWStructuredBuffers may increment or decrement their "
+ "counters, but not both.";
+ M.getContext().diagnose(
+ DiagnosticInfoGenericWithLoc(Message, *F, CI->getDebugLoc()));
+ }
// Copy the results into the final vec
CounterDirections.clear();
@@ -913,16 +934,6 @@ void DXILResourceCounterDirectionMap::populate(Module &M, DXILBindingMap &DBM) {
return std::pair{std::get<dxil::ResourceBindingInfo>(Item),
std::get<ResourceCounterDirection>(Item)};
});
-
- if (DuplicateEntry == DiagCounterDirs.end())
- return;
-
- const Function *F = std::get<const Function *>(*DuplicateEntry);
- const CallInst *CI = std::get<const CallInst *>(*DuplicateEntry);
- StringRef Message = "RWStructuredBuffers may increment or decrement their "
- "counters, but not both.";
- M.getContext().diagnose(
- DiagnosticInfoGenericWithLoc(Message, *F, CI->getDebugLoc()));
}
void DXILResourceCounterDirectionWrapperPass::getAnalysisUsage(
>From ef30e9a4a1b42bdc1e128d126b75b4a104ff4f3f Mon Sep 17 00:00:00 2001
From: Ashley Coleman <ascoleman at microsoft.com>
Date: Wed, 12 Mar 2025 17:30:41 -0600
Subject: [PATCH 11/11] format
---
llvm/lib/Analysis/DXILResource.cpp | 19 +++++++++++--------
1 file changed, 11 insertions(+), 8 deletions(-)
diff --git a/llvm/lib/Analysis/DXILResource.cpp b/llvm/lib/Analysis/DXILResource.cpp
index 1080d460fd1d9..0cbfb45083abf 100644
--- a/llvm/lib/Analysis/DXILResource.cpp
+++ b/llvm/lib/Analysis/DXILResource.cpp
@@ -900,16 +900,19 @@ void DXILResourceCounterDirectionMap::populate(Module &M, DXILBindingMap &DBM) {
// resource that was both incremented and decremented which is not allowed.
// Mark all those entries as invalid.
{
- auto DupFirst = DiagCounterDirs.begin();
- auto DupNext = DupFirst + 1;
- auto DupLast = DiagCounterDirs.end();
- for (; DupFirst < DupLast && DupNext < DupLast; ++DupFirst, ++DupNext) {
- if (std::get<dxil::ResourceBindingInfo>(*DupFirst) == std::get<dxil::ResourceBindingInfo>(*DupNext)) {
- std::get<ResourceCounterDirection>(*DupFirst) = ResourceCounterDirection::MyInvalid;
- std::get<ResourceCounterDirection>(*DupNext) = ResourceCounterDirection::MyInvalid;
+ auto DupFirst = DiagCounterDirs.begin();
+ auto DupNext = DupFirst + 1;
+ auto DupLast = DiagCounterDirs.end();
+ for (; DupFirst < DupLast && DupNext < DupLast; ++DupFirst, ++DupNext) {
+ if (std::get<dxil::ResourceBindingInfo>(*DupFirst) ==
+ std::get<dxil::ResourceBindingInfo>(*DupNext)) {
+ std::get<ResourceCounterDirection>(*DupFirst) =
+ ResourceCounterDirection::MyInvalid;
+ std::get<ResourceCounterDirection>(*DupNext) =
+ ResourceCounterDirection::MyInvalid;
+ }
}
}
- }
// Raise an error for every invalid entry
for (const auto Entry : DiagCounterDirs) {
More information about the llvm-commits
mailing list