[llvm] [HLSL] Analyze update counter usage (PR #130356)
Ashley Coleman via llvm-commits
llvm-commits at lists.llvm.org
Wed Mar 26 16:04:36 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/22] [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/22] 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/22] 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/22] 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/22] 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/22] 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/22] 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/22] 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/22] 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/22] 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/22] 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) {
>From b1a4f4ddba7c82ae9c48ffbe1e65b48dd1231923 Mon Sep 17 00:00:00 2001
From: Ashley Coleman <ascoleman at microsoft.com>
Date: Mon, 17 Mar 2025 15:15:12 -0600
Subject: [PATCH 12/22] Fix enum name
---
llvm/include/llvm/Analysis/DXILResource.h | 4 ++--
llvm/lib/Analysis/DXILResource.cpp | 6 +++---
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/llvm/include/llvm/Analysis/DXILResource.h b/llvm/include/llvm/Analysis/DXILResource.h
index 6552357b156b4..aa7dfffa399b2 100644
--- a/llvm/include/llvm/Analysis/DXILResource.h
+++ b/llvm/include/llvm/Analysis/DXILResource.h
@@ -577,11 +577,11 @@ class DXILResourceBindingWrapperPass : public ModulePass {
ModulePass *createDXILResourceBindingWrapperPassPass();
-enum ResourceCounterDirection {
+enum class ResourceCounterDirection {
Increment,
Decrement,
Unknown,
- MyInvalid,
+ Invalid,
};
class DXILResourceCounterDirectionMap {
diff --git a/llvm/lib/Analysis/DXILResource.cpp b/llvm/lib/Analysis/DXILResource.cpp
index 0cbfb45083abf..278c219c58f3f 100644
--- a/llvm/lib/Analysis/DXILResource.cpp
+++ b/llvm/lib/Analysis/DXILResource.cpp
@@ -907,9 +907,9 @@ void DXILResourceCounterDirectionMap::populate(Module &M, DXILBindingMap &DBM) {
if (std::get<dxil::ResourceBindingInfo>(*DupFirst) ==
std::get<dxil::ResourceBindingInfo>(*DupNext)) {
std::get<ResourceCounterDirection>(*DupFirst) =
- ResourceCounterDirection::MyInvalid;
+ ResourceCounterDirection::Invalid;
std::get<ResourceCounterDirection>(*DupNext) =
- ResourceCounterDirection::MyInvalid;
+ ResourceCounterDirection::Invalid;
}
}
}
@@ -920,7 +920,7 @@ void DXILResourceCounterDirectionMap::populate(Module &M, DXILBindingMap &DBM) {
const Function *F = std::get<const Function *>(Entry);
const CallInst *CI = std::get<const CallInst *>(Entry);
- if (Dir != ResourceCounterDirection::MyInvalid)
+ if (Dir != ResourceCounterDirection::Invalid)
continue;
StringRef Message = "RWStructuredBuffers may increment or decrement their "
>From 1f011b70e30e3121b133e22cfaf9e0dfcc807d69 Mon Sep 17 00:00:00 2001
From: Ashley Coleman <ascoleman at microsoft.com>
Date: Mon, 24 Mar 2025 10:10:08 -0600
Subject: [PATCH 13/22] address comments
---
.../DirectX/UniqueResourceFromUseTests.cpp | 54 ++++++++-----------
1 file changed, 21 insertions(+), 33 deletions(-)
diff --git a/llvm/unittests/Target/DirectX/UniqueResourceFromUseTests.cpp b/llvm/unittests/Target/DirectX/UniqueResourceFromUseTests.cpp
index 76de33e061a3d..e2f913816bcc7 100644
--- a/llvm/unittests/Target/DirectX/UniqueResourceFromUseTests.cpp
+++ b/llvm/unittests/Target/DirectX/UniqueResourceFromUseTests.cpp
@@ -48,13 +48,12 @@ TEST_F(UniqueResourceFromUseTest, TestTrivialUse) {
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)
+ %handle = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding(i32 1, i32 2, i32 3, i32 4, i1 false)
call void @a.func(target("dx.RawBuffer", float, 1, 0) %handle)
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 void @a.func(target("dx.RawBuffer", float, 1, 0) %handle)
)";
@@ -95,7 +94,7 @@ declare void @a.func(target("dx.RawBuffer", float, 1, 0) %handle)
TEST_F(UniqueResourceFromUseTest, TestIndirectUse) {
StringRef Assembly = R"(
define void @foo() {
- %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)
+ %handle = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding(i32 1, i32 2, i32 3, i32 4, i1 false)
%handle2 = call target("dx.RawBuffer", float, 1, 0) @ind.func(target("dx.RawBuffer", float, 1, 0) %handle)
%handle3 = call target("dx.RawBuffer", float, 1, 0) @ind.func(target("dx.RawBuffer", float, 1, 0) %handle2)
%handle4 = call target("dx.RawBuffer", float, 1, 0) @ind.func(target("dx.RawBuffer", float, 1, 0) %handle3)
@@ -103,7 +102,6 @@ define void @foo() {
ret void
}
-declare target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_f32_1_0t(i32, i32, i32, i32, i1)
declare void @a.func(target("dx.RawBuffer", float, 1, 0) %handle)
declare target("dx.RawBuffer", float, 1, 0) @ind.func(target("dx.RawBuffer", float, 1, 0) %handle)
)";
@@ -145,10 +143,10 @@ declare target("dx.RawBuffer", float, 1, 0) @ind.func(target("dx.RawBuffer", flo
TEST_F(UniqueResourceFromUseTest, TestAmbigousIndirectUse) {
StringRef Assembly = R"(
define void @foo() {
- %foo = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_f32_1_0t(i32 1, i32 1, i32 1, i32 1, i1 false)
- %bar = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_f32_1_0t(i32 2, i32 2, i32 2, i32 2, i1 false)
- %baz = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_f32_1_0t(i32 3, i32 3, i32 3, i32 3, i1 false)
- %bat = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_f32_1_0t(i32 4, i32 4, i32 4, i32 4, i1 false)
+ %foo = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding(i32 1, i32 1, i32 1, i32 1, i1 false)
+ %bar = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding(i32 2, i32 2, i32 2, i32 2, i1 false)
+ %baz = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding(i32 3, i32 3, i32 3, i32 3, i1 false)
+ %bat = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding(i32 4, i32 4, i32 4, i32 4, i1 false)
%a = call target("dx.RawBuffer", float, 1, 0) @ind.func(target("dx.RawBuffer", float, 1, 0) %foo, target("dx.RawBuffer", float, 1, 0) %bar)
%b = call target("dx.RawBuffer", float, 1, 0) @ind.func(target("dx.RawBuffer", float, 1, 0) %baz, target("dx.RawBuffer", float, 1, 0) %bat)
%handle = call target("dx.RawBuffer", float, 1, 0) @ind.func(target("dx.RawBuffer", float, 1, 0) %a, target("dx.RawBuffer", float, 1, 0) %b)
@@ -156,7 +154,6 @@ define void @foo() {
ret void
}
-declare target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_f32_1_0t(i32, i32, i32, i32, i1)
declare void @a.func(target("dx.RawBuffer", float, 1, 0) %handle)
declare target("dx.RawBuffer", float, 1, 0) @ind.func(target("dx.RawBuffer", float, 1, 0) %x, target("dx.RawBuffer", float, 1, 0) %y)
)";
@@ -217,8 +214,8 @@ TEST_F(UniqueResourceFromUseTest, TestConditionalUse) {
StringRef Assembly = R"(
define void @foo(i32 %n) {
entry:
- %x = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_f32_1_0t(i32 1, i32 1, i32 1, i32 1, i1 false)
- %y = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_f32_1_0t(i32 4, i32 4, i32 4, i32 4, i1 false)
+ %x = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding(i32 1, i32 1, i32 1, i32 1, i1 false)
+ %y = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding(i32 4, i32 4, i32 4, i32 4, i1 false)
%cond = icmp eq i32 %n, 0
br i1 %cond, label %bb.true, label %bb.false
@@ -236,7 +233,6 @@ bb.exit:
ret void
}
-declare target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_f32_1_0t(i32, i32, i32, i32, i1)
declare void @a.func(target("dx.RawBuffer", float, 1, 0) %handle)
declare target("dx.RawBuffer", float, 1, 0) @ind.func(target("dx.RawBuffer", float, 1, 0) %x)
)";
@@ -287,16 +283,14 @@ TEST_F(UniqueResourceFromUseTest, TestResourceCounterDecrement) {
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)
+ %handle = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding(i32 1, i32 2, i32 3, i32 4, i1 false)
+ call i32 @llvm.dx.resource.updatecounter(target("dx.RawBuffer", float, 1, 0) %handle, i8 -1)
+ call i32 @llvm.dx.resource.updatecounter(target("dx.RawBuffer", float, 1, 0) %handle, i8 -1)
+ call i32 @llvm.dx.resource.updatecounter(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)
)";
@@ -330,16 +324,14 @@ 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)
+ %handle = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding(i32 1, i32 2, i32 3, i32 4, i1 false)
+ call i32 @llvm.dx.resource.updatecounter(target("dx.RawBuffer", float, 1, 0) %handle, i8 1)
+ call i32 @llvm.dx.resource.updatecounter(target("dx.RawBuffer", float, 1, 0) %handle, i8 1)
+ call i32 @llvm.dx.resource.updatecounter(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)
)";
@@ -373,13 +365,11 @@ 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)
+ %handle = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding(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)
)";
@@ -413,17 +403,15 @@ 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)
+ %handle1 = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding(i32 1, i32 2, i32 3, i32 4, i1 false)
+ %handle2 = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding(i32 4, i32 3, i32 2, i32 1, i1 false)
+ call i32 @llvm.dx.resource.updatecounter(target("dx.RawBuffer", float, 1, 0) %handle1, i8 -1)
+ call i32 @llvm.dx.resource.updatecounter(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)
)";
>From f7b82c03264480bec8954be625d571b0a8f80c15 Mon Sep 17 00:00:00 2001
From: Ashley Coleman <ascoleman at microsoft.com>
Date: Mon, 24 Mar 2025 10:50:14 -0600
Subject: [PATCH 14/22] address comments
---
.../DirectX/UniqueResourceFromUseTests.cpp | 46 ++++++-------------
1 file changed, 15 insertions(+), 31 deletions(-)
diff --git a/llvm/unittests/Target/DirectX/UniqueResourceFromUseTests.cpp b/llvm/unittests/Target/DirectX/UniqueResourceFromUseTests.cpp
index e2f913816bcc7..c065648c852a1 100644
--- a/llvm/unittests/Target/DirectX/UniqueResourceFromUseTests.cpp
+++ b/llvm/unittests/Target/DirectX/UniqueResourceFromUseTests.cpp
@@ -11,6 +11,7 @@
#include "llvm/AsmParser/Parser.h"
#include "llvm/CodeGen/CommandFlags.h"
#include "llvm/IR/Instructions.h"
+#include "llvm/IR/IntrinsicsDirectX.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Type.h"
@@ -287,11 +288,8 @@ define void @main() {
call i32 @llvm.dx.resource.updatecounter(target("dx.RawBuffer", float, 1, 0) %handle, i8 -1)
call i32 @llvm.dx.resource.updatecounter(target("dx.RawBuffer", float, 1, 0) %handle, i8 -1)
call i32 @llvm.dx.resource.updatecounter(target("dx.RawBuffer", float, 1, 0) %handle, i8 -1)
- call void @a.func(target("dx.RawBuffer", float, 1, 0) %handle)
ret void
}
-
-declare void @a.func(target("dx.RawBuffer", float, 1, 0) %handle)
)";
LLVMContext Context;
@@ -304,14 +302,13 @@ declare void @a.func(target("dx.RawBuffer", float, 1, 0) %handle)
MAM->getResult<DXILResourceCounterDirectionAnalysis>(*M);
for (const Function &F : M->functions()) {
- if (F.getName() != "a.func") {
+ if (F.getIntrinsicID() != Intrinsic::dx_resource_handlefrombinding) {
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);
+ const auto Bindings = DBM.findByUse(CI);
ASSERT_EQ(Bindings.size(), 1u);
ASSERT_EQ(DCDM[Bindings.front()], ResourceCounterDirection::Decrement);
}
@@ -328,11 +325,8 @@ define void @main() {
call i32 @llvm.dx.resource.updatecounter(target("dx.RawBuffer", float, 1, 0) %handle, i8 1)
call i32 @llvm.dx.resource.updatecounter(target("dx.RawBuffer", float, 1, 0) %handle, i8 1)
call i32 @llvm.dx.resource.updatecounter(target("dx.RawBuffer", float, 1, 0) %handle, i8 1)
- call void @a.func(target("dx.RawBuffer", float, 1, 0) %handle)
ret void
}
-
-declare void @a.func(target("dx.RawBuffer", float, 1, 0) %handle)
)";
LLVMContext Context;
@@ -345,14 +339,13 @@ declare void @a.func(target("dx.RawBuffer", float, 1, 0) %handle)
MAM->getResult<DXILResourceCounterDirectionAnalysis>(*M);
for (const Function &F : M->functions()) {
- if (F.getName() != "a.func") {
+ if (F.getIntrinsicID() != Intrinsic::dx_resource_handlefrombinding) {
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);
+ const auto Bindings = DBM.findByUse(CI);
ASSERT_EQ(Bindings.size(), 1u);
ASSERT_EQ(DCDM[Bindings.front()], ResourceCounterDirection::Increment);
}
@@ -366,11 +359,8 @@ TEST_F(UniqueResourceFromUseTest, TestResourceCounterUnknown) {
define void @main() {
entry:
%handle = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding(i32 1, i32 2, i32 3, i32 4, i1 false)
- call void @a.func(target("dx.RawBuffer", float, 1, 0) %handle)
ret void
}
-
-declare void @a.func(target("dx.RawBuffer", float, 1, 0) %handle)
)";
LLVMContext Context;
@@ -383,14 +373,13 @@ declare void @a.func(target("dx.RawBuffer", float, 1, 0) %handle)
MAM->getResult<DXILResourceCounterDirectionAnalysis>(*M);
for (const Function &F : M->functions()) {
- if (F.getName() != "a.func") {
+ if (F.getIntrinsicID() != Intrinsic::dx_resource_handlefrombinding) {
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);
+ const auto Bindings = DBM.findByUse(CI);
ASSERT_EQ(Bindings.size(), 1u);
ASSERT_EQ(DCDM[Bindings.front()], ResourceCounterDirection::Unknown);
}
@@ -407,13 +396,8 @@ define void @main() {
%handle2 = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding(i32 4, i32 3, i32 2, i32 1, i1 false)
call i32 @llvm.dx.resource.updatecounter(target("dx.RawBuffer", float, 1, 0) %handle1, i8 -1)
call i32 @llvm.dx.resource.updatecounter(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 void @a.func(target("dx.RawBuffer", float, 1, 0) %handle)
-declare void @b.func(target("dx.RawBuffer", float, 1, 0) %handle)
)";
LLVMContext Context;
@@ -425,21 +409,21 @@ declare void @b.func(target("dx.RawBuffer", float, 1, 0) %handle)
const DXILResourceCounterDirectionMap &DCDM =
MAM->getResult<DXILResourceCounterDirectionAnalysis>(*M);
+ ResourceCounterDirection Dirs[2] = {ResourceCounterDirection::Decrement,
+ ResourceCounterDirection::Increment};
+ ResourceCounterDirection *Dir = Dirs;
+
for (const Function &F : M->functions()) {
- StringRef FName = F.getName();
- if (FName != "a.func" && FName != "b.func") {
+ if (F.getIntrinsicID() != Intrinsic::dx_resource_handlefrombinding) {
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);
+ const auto Bindings = DBM.findByUse(CI);
ASSERT_EQ(Bindings.size(), 1u);
- ASSERT_EQ(DCDM[Bindings.front()], Dir);
+ ASSERT_EQ(DCDM[Bindings.front()], *Dir);
+ Dir++;
}
}
}
>From c82249db23dd32b9d4ca24224ba4cee458318ac4 Mon Sep 17 00:00:00 2001
From: Ashley Coleman <ascoleman at microsoft.com>
Date: Mon, 24 Mar 2025 14:14:56 -0600
Subject: [PATCH 15/22] address comments
---
.../DirectX/UniqueResourceFromUseTests.cpp | 20 ++++++++-----------
1 file changed, 8 insertions(+), 12 deletions(-)
diff --git a/llvm/unittests/Target/DirectX/UniqueResourceFromUseTests.cpp b/llvm/unittests/Target/DirectX/UniqueResourceFromUseTests.cpp
index c065648c852a1..fdec0df4a7f89 100644
--- a/llvm/unittests/Target/DirectX/UniqueResourceFromUseTests.cpp
+++ b/llvm/unittests/Target/DirectX/UniqueResourceFromUseTests.cpp
@@ -308,9 +308,8 @@ define void @main() {
for (const User *U : F.users()) {
const CallInst *CI = cast<CallInst>(U);
- const auto Bindings = DBM.findByUse(CI);
- ASSERT_EQ(Bindings.size(), 1u);
- ASSERT_EQ(DCDM[Bindings.front()], ResourceCounterDirection::Decrement);
+ const auto *const Binding = DBM.find(CI);
+ ASSERT_EQ(DCDM[*Binding], ResourceCounterDirection::Decrement);
}
}
}
@@ -345,9 +344,8 @@ define void @main() {
for (const User *U : F.users()) {
const CallInst *CI = cast<CallInst>(U);
- const auto Bindings = DBM.findByUse(CI);
- ASSERT_EQ(Bindings.size(), 1u);
- ASSERT_EQ(DCDM[Bindings.front()], ResourceCounterDirection::Increment);
+ const auto *const Binding = DBM.find(CI);
+ ASSERT_EQ(DCDM[*Binding], ResourceCounterDirection::Increment);
}
}
}
@@ -379,9 +377,8 @@ define void @main() {
for (const User *U : F.users()) {
const CallInst *CI = cast<CallInst>(U);
- const auto Bindings = DBM.findByUse(CI);
- ASSERT_EQ(Bindings.size(), 1u);
- ASSERT_EQ(DCDM[Bindings.front()], ResourceCounterDirection::Unknown);
+ const auto *const Binding = DBM.find(CI);
+ ASSERT_EQ(DCDM[*Binding], ResourceCounterDirection::Unknown);
}
}
}
@@ -420,9 +417,8 @@ define void @main() {
for (const User *U : F.users()) {
const CallInst *CI = cast<CallInst>(U);
- const auto Bindings = DBM.findByUse(CI);
- ASSERT_EQ(Bindings.size(), 1u);
- ASSERT_EQ(DCDM[Bindings.front()], *Dir);
+ const auto *const Binding = DBM.find(CI);
+ ASSERT_EQ(DCDM[*Binding], *Dir);
Dir++;
}
}
>From 61d371feb8a106fa15748c89536fd75b72b06bee Mon Sep 17 00:00:00 2001
From: Ashley Coleman <ascoleman at microsoft.com>
Date: Mon, 24 Mar 2025 16:44:14 -0600
Subject: [PATCH 16/22] address comments
---
llvm/include/llvm/Analysis/DXILResource.h | 7 ++--
llvm/lib/Analysis/DXILResource.cpp | 38 +++++++++-------------
llvm/lib/Target/DirectX/DXILOpLowering.cpp | 6 ++++
3 files changed, 25 insertions(+), 26 deletions(-)
diff --git a/llvm/include/llvm/Analysis/DXILResource.h b/llvm/include/llvm/Analysis/DXILResource.h
index aa7dfffa399b2..1647d37ef8353 100644
--- a/llvm/include/llvm/Analysis/DXILResource.h
+++ b/llvm/include/llvm/Analysis/DXILResource.h
@@ -593,10 +593,9 @@ class DXILResourceCounterDirectionMap {
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; });
+ auto Lower = llvm::lower_bound(
+ CounterDirections, Info,
+ [](const auto &LHS, const auto &RHS) { return LHS.first < RHS; });
if (Lower == CounterDirections.end()) {
return ResourceCounterDirection::Unknown;
diff --git a/llvm/lib/Analysis/DXILResource.cpp b/llvm/lib/Analysis/DXILResource.cpp
index 278c219c58f3f..c09ce8400b98d 100644
--- a/llvm/lib/Analysis/DXILResource.cpp
+++ b/llvm/lib/Analysis/DXILResource.cpp
@@ -832,7 +832,7 @@ static bool isUpdateCounterIntrinsic(Function &F) {
}
void DXILResourceCounterDirectionMap::populate(Module &M, DXILBindingMap &DBM) {
- std::vector<std::tuple<dxil::ResourceBindingInfo, ResourceCounterDirection,
+ SmallVector<std::tuple<dxil::ResourceBindingInfo, ResourceCounterDirection,
const Function *, const CallInst *>>
DiagCounterDirs;
@@ -846,14 +846,16 @@ void DXILResourceCounterDirectionMap::populate(Module &M, DXILBindingMap &DBM) {
// Determine if the use is an increment or decrement
Value *CountArg = CI->getArgOperand(1);
- ConstantInt *CountValue = dyn_cast<ConstantInt>(CountArg);
+ ConstantInt *CountValue = cast<ConstantInt>(CountArg);
int64_t CountLiteral = CountValue->getSExtValue();
- ResourceCounterDirection Direction = ResourceCounterDirection::Unknown;
+ // 0 is an unknown direction and shouldn't result in an insert
+ if (CountLiteral == 0)
+ continue;
+
+ ResourceCounterDirection Direction = ResourceCounterDirection::Decrement;
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);
@@ -863,17 +865,8 @@ void DXILResourceCounterDirectionMap::populate(Module &M, DXILBindingMap &DBM) {
}
}
- // 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(
- DiagCounterDirs.begin(), DiagCounterDirs.end(), [](const auto &Item) {
- return std::get<ResourceCounterDirection>(Item) ==
- ResourceCounterDirection::Unknown;
- });
-
// Sort by the Binding and Direction for fast lookup
- std::sort(DiagCounterDirs.begin(), RemoveEnd,
+ std::sort(DiagCounterDirs.begin(), DiagCounterDirs.end(),
[](const auto &LHS, const auto &RHS) {
const auto L = std::pair{std::get<dxil::ResourceBindingInfo>(LHS),
std::get<ResourceCounterDirection>(LHS)};
@@ -884,8 +877,9 @@ void DXILResourceCounterDirectionMap::populate(Module &M, DXILBindingMap &DBM) {
// 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) {
+ auto *const UniqueEnd = std::unique(
+ DiagCounterDirs.begin(), DiagCounterDirs.end(),
+ [](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),
@@ -893,16 +887,16 @@ void DXILResourceCounterDirectionMap::populate(Module &M, DXILBindingMap &DBM) {
return L == R;
});
- // Actually erase the items invalidated by remove_if + unique
+ // Actually erase the invalidated items
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.
// Mark all those entries as invalid.
{
- auto DupFirst = DiagCounterDirs.begin();
- auto DupNext = DupFirst + 1;
- auto DupLast = DiagCounterDirs.end();
+ 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)) {
@@ -915,7 +909,7 @@ void DXILResourceCounterDirectionMap::populate(Module &M, DXILBindingMap &DBM) {
}
// Raise an error for every invalid entry
- for (const auto Entry : DiagCounterDirs) {
+ 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);
diff --git a/llvm/lib/Target/DirectX/DXILOpLowering.cpp b/llvm/lib/Target/DirectX/DXILOpLowering.cpp
index cfa65e69ea0bb..c5ce3fc4167b0 100644
--- a/llvm/lib/Target/DirectX/DXILOpLowering.cpp
+++ b/llvm/lib/Target/DirectX/DXILOpLowering.cpp
@@ -858,8 +858,14 @@ class OpLowerer {
PreservedAnalyses DXILOpLowering::run(Module &M, ModuleAnalysisManager &MAM) {
DXILBindingMap &DBM = MAM.getResult<DXILResourceBindingAnalysis>(M);
DXILResourceTypeMap &DRTM = MAM.getResult<DXILResourceTypeAnalysis>(M);
+
+ // TODO: This needs to be called even though its not currently being used in
+ // order for tests to pass. It will eventually need to be used as part of
+ // https://github.com/llvm/llvm-project/issues/125126 which will have the same
+ // effect. Until then discard the result.
DXILResourceCounterDirectionMap &DRCDM =
MAM.getResult<DXILResourceCounterDirectionAnalysis>(M);
+ (void)DRCDM;
bool MadeChanges = OpLowerer(M, DBM, DRTM).lowerIntrinsics();
if (!MadeChanges)
>From 1202e86dc9a88cc4392a93c2e349bfe30d754571 Mon Sep 17 00:00:00 2001
From: Ashley Coleman <ascoleman at microsoft.com>
Date: Mon, 24 Mar 2025 17:25:19 -0600
Subject: [PATCH 17/22] address comments
---
llvm/lib/Analysis/DXILResource.cpp | 18 ++++++++++--------
1 file changed, 10 insertions(+), 8 deletions(-)
diff --git a/llvm/lib/Analysis/DXILResource.cpp b/llvm/lib/Analysis/DXILResource.cpp
index c09ce8400b98d..ea0083bc13b82 100644
--- a/llvm/lib/Analysis/DXILResource.cpp
+++ b/llvm/lib/Analysis/DXILResource.cpp
@@ -866,14 +866,16 @@ void DXILResourceCounterDirectionMap::populate(Module &M, DXILBindingMap &DBM) {
}
// Sort by the Binding and Direction for fast lookup
- std::sort(DiagCounterDirs.begin(), DiagCounterDirs.end(),
- [](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::stable_sort(DiagCounterDirs.begin(), DiagCounterDirs.end(),
+ [](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.
>From 940b928245ba67eb670d3cfc9c88d71bb8140098 Mon Sep 17 00:00:00 2001
From: Ashley Coleman <me at ashleycoleman.me>
Date: Tue, 25 Mar 2025 10:01:00 -0600
Subject: [PATCH 18/22] Update llvm/include/llvm/Analysis/DXILResource.h
Co-authored-by: Helena Kotas <hekotas at microsoft.com>
---
llvm/include/llvm/Analysis/DXILResource.h | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/llvm/include/llvm/Analysis/DXILResource.h b/llvm/include/llvm/Analysis/DXILResource.h
index 1647d37ef8353..99e53126d897e 100644
--- a/llvm/include/llvm/Analysis/DXILResource.h
+++ b/llvm/include/llvm/Analysis/DXILResource.h
@@ -597,13 +597,10 @@ class DXILResourceCounterDirectionMap {
CounterDirections, Info,
[](const auto &LHS, const auto &RHS) { return LHS.first < RHS; });
- if (Lower == CounterDirections.end()) {
+ if (Lower == CounterDirections.end())
return ResourceCounterDirection::Unknown;
- }
-
- if (Lower->first != Info) {
+ if (Lower->first != Info)
return ResourceCounterDirection::Unknown;
- }
return Lower->second;
}
>From 336689770832c51d71bd8f7b33f4a8613b0d83f3 Mon Sep 17 00:00:00 2001
From: Ashley Coleman <ascoleman at microsoft.com>
Date: Tue, 25 Mar 2025 15:08:09 -0600
Subject: [PATCH 19/22] address comments
---
llvm/include/llvm/Analysis/DXILResource.h | 10 ++--
llvm/lib/Analysis/DXILResource.cpp | 49 ++++++++++---------
.../DirectX/UniqueResourceFromUseTests.cpp | 16 +++---
3 files changed, 41 insertions(+), 34 deletions(-)
diff --git a/llvm/include/llvm/Analysis/DXILResource.h b/llvm/include/llvm/Analysis/DXILResource.h
index 99e53126d897e..a5acca6ec32bb 100644
--- a/llvm/include/llvm/Analysis/DXILResource.h
+++ b/llvm/include/llvm/Analysis/DXILResource.h
@@ -474,7 +474,8 @@ class DXILBindingMap {
/// ambiguous so multiple creation instructions may be returned. The resulting
/// ResourceBindingInfo can be used to depuplicate unique handles that
/// reference the same resource
- SmallVector<dxil::ResourceBindingInfo> findByUse(const Value *Key) const;
+ SmallVector<const dxil::ResourceBindingInfo *>
+ findByUse(const Value *Key) const;
const_iterator find(const CallInst *Key) const {
auto Pos = CallMap.find(Key);
@@ -585,7 +586,8 @@ enum class ResourceCounterDirection {
};
class DXILResourceCounterDirectionMap {
- std::vector<std::pair<dxil::ResourceBindingInfo, ResourceCounterDirection>>
+ std::vector<
+ std::pair<const dxil::ResourceBindingInfo *, ResourceCounterDirection>>
CounterDirections;
public:
@@ -595,11 +597,11 @@ class DXILResourceCounterDirectionMap {
operator[](const dxil::ResourceBindingInfo &Info) const {
auto Lower = llvm::lower_bound(
CounterDirections, Info,
- [](const auto &LHS, const auto &RHS) { return LHS.first < RHS; });
+ [](const auto &LHS, const auto &RHS) { return *LHS.first < RHS; });
if (Lower == CounterDirections.end())
return ResourceCounterDirection::Unknown;
- if (Lower->first != Info)
+ if (*Lower->first != Info)
return ResourceCounterDirection::Unknown;
return Lower->second;
diff --git a/llvm/lib/Analysis/DXILResource.cpp b/llvm/lib/Analysis/DXILResource.cpp
index ea0083bc13b82..668480153c723 100644
--- a/llvm/lib/Analysis/DXILResource.cpp
+++ b/llvm/lib/Analysis/DXILResource.cpp
@@ -786,10 +786,10 @@ void DXILBindingMap::print(raw_ostream &OS, DXILResourceTypeMap &DRTM,
}
}
-SmallVector<dxil::ResourceBindingInfo>
+SmallVector<const dxil::ResourceBindingInfo *>
DXILBindingMap::findByUse(const Value *Key) const {
if (const PHINode *Phi = dyn_cast<PHINode>(Key)) {
- SmallVector<dxil::ResourceBindingInfo> Children;
+ SmallVector<const dxil::ResourceBindingInfo *> Children;
for (const Value *V : Phi->operands()) {
Children.append(findByUse(V));
}
@@ -805,7 +805,7 @@ DXILBindingMap::findByUse(const Value *Key) const {
case Intrinsic::dx_resource_handlefrombinding: {
const auto *It = find(CI);
assert(It != Infos.end() && "HandleFromBinding must be in resource map");
- return {*It};
+ return {It};
}
default:
break;
@@ -814,7 +814,7 @@ DXILBindingMap::findByUse(const Value *Key) const {
// Check if any of the parameters are the resource we are following. If so
// keep searching. If none of them are return an empty list
const Type *UseType = CI->getType();
- SmallVector<dxil::ResourceBindingInfo> Children;
+ SmallVector<const dxil::ResourceBindingInfo *> Children;
for (const Value *V : CI->args()) {
if (V->getType() != UseType)
continue;
@@ -832,8 +832,9 @@ static bool isUpdateCounterIntrinsic(Function &F) {
}
void DXILResourceCounterDirectionMap::populate(Module &M, DXILBindingMap &DBM) {
- SmallVector<std::tuple<dxil::ResourceBindingInfo, ResourceCounterDirection,
- const Function *, const CallInst *>>
+ SmallVector<
+ std::tuple<const dxil::ResourceBindingInfo *, ResourceCounterDirection,
+ const Function *, const CallInst *>>
DiagCounterDirs;
for (Function &F : M.functions()) {
@@ -859,8 +860,9 @@ void DXILResourceCounterDirectionMap::populate(Module &M, DXILBindingMap &DBM) {
// 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)
+ SmallVector<const dxil::ResourceBindingInfo *> RBInfos =
+ DBM.findByUse(HandleArg);
+ for (const dxil::ResourceBindingInfo *RBInfo : RBInfos)
DiagCounterDirs.emplace_back(RBInfo, Direction, &F, CI);
}
}
@@ -868,12 +870,12 @@ void DXILResourceCounterDirectionMap::populate(Module &M, DXILBindingMap &DBM) {
// Sort by the Binding and Direction for fast lookup
std::stable_sort(DiagCounterDirs.begin(), DiagCounterDirs.end(),
[](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)};
+ const auto L = std::pair{
+ std::get<const dxil::ResourceBindingInfo *>(LHS),
+ std::get<ResourceCounterDirection>(LHS)};
+ const auto R = std::pair{
+ std::get<const dxil::ResourceBindingInfo *>(RHS),
+ std::get<ResourceCounterDirection>(RHS)};
return L < R;
});
@@ -882,10 +884,12 @@ void DXILResourceCounterDirectionMap::populate(Module &M, DXILBindingMap &DBM) {
auto *const UniqueEnd = std::unique(
DiagCounterDirs.begin(), DiagCounterDirs.end(),
[](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)};
+ const auto L =
+ std::pair{std::get<const dxil::ResourceBindingInfo *>(LHS),
+ std::get<ResourceCounterDirection>(LHS)};
+ const auto R =
+ std::pair{std::get<const dxil::ResourceBindingInfo *>(RHS),
+ std::get<ResourceCounterDirection>(RHS)};
return L == R;
});
@@ -900,8 +904,8 @@ void DXILResourceCounterDirectionMap::populate(Module &M, DXILBindingMap &DBM) {
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)) {
+ if (std::get<const dxil::ResourceBindingInfo *>(*DupFirst) ==
+ std::get<const dxil::ResourceBindingInfo *>(*DupNext)) {
std::get<ResourceCounterDirection>(*DupFirst) =
ResourceCounterDirection::Invalid;
std::get<ResourceCounterDirection>(*DupNext) =
@@ -930,8 +934,9 @@ void DXILResourceCounterDirectionMap::populate(Module &M, DXILBindingMap &DBM) {
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)};
+ return std::pair{
+ std::get<const dxil::ResourceBindingInfo *>(Item),
+ std::get<ResourceCounterDirection>(Item)};
});
}
diff --git a/llvm/unittests/Target/DirectX/UniqueResourceFromUseTests.cpp b/llvm/unittests/Target/DirectX/UniqueResourceFromUseTests.cpp
index fdec0df4a7f89..fcb609a7576b1 100644
--- a/llvm/unittests/Target/DirectX/UniqueResourceFromUseTests.cpp
+++ b/llvm/unittests/Target/DirectX/UniqueResourceFromUseTests.cpp
@@ -78,7 +78,7 @@ declare void @a.func(target("dx.RawBuffer", float, 1, 0) %handle)
ASSERT_EQ(Bindings.size(), 1u)
<< "Handle should resolve into one resource";
- auto Binding = Bindings[0].getBinding();
+ auto Binding = Bindings[0]->getBinding();
EXPECT_EQ(0u, Binding.RecordID);
EXPECT_EQ(1u, Binding.Space);
EXPECT_EQ(2u, Binding.LowerBound);
@@ -127,7 +127,7 @@ declare target("dx.RawBuffer", float, 1, 0) @ind.func(target("dx.RawBuffer", flo
ASSERT_EQ(Bindings.size(), 1u)
<< "Handle should resolve into one resource";
- auto Binding = Bindings[0].getBinding();
+ auto Binding = Bindings[0]->getBinding();
EXPECT_EQ(0u, Binding.RecordID);
EXPECT_EQ(1u, Binding.Space);
EXPECT_EQ(2u, Binding.LowerBound);
@@ -179,25 +179,25 @@ declare target("dx.RawBuffer", float, 1, 0) @ind.func(target("dx.RawBuffer", flo
ASSERT_EQ(Bindings.size(), 4u)
<< "Handle should resolve into four resources";
- auto Binding = Bindings[0].getBinding();
+ auto Binding = Bindings[0]->getBinding();
EXPECT_EQ(0u, Binding.RecordID);
EXPECT_EQ(1u, Binding.Space);
EXPECT_EQ(1u, Binding.LowerBound);
EXPECT_EQ(1u, Binding.Size);
- Binding = Bindings[1].getBinding();
+ Binding = Bindings[1]->getBinding();
EXPECT_EQ(1u, Binding.RecordID);
EXPECT_EQ(2u, Binding.Space);
EXPECT_EQ(2u, Binding.LowerBound);
EXPECT_EQ(2u, Binding.Size);
- Binding = Bindings[2].getBinding();
+ Binding = Bindings[2]->getBinding();
EXPECT_EQ(2u, Binding.RecordID);
EXPECT_EQ(3u, Binding.Space);
EXPECT_EQ(3u, Binding.LowerBound);
EXPECT_EQ(3u, Binding.Size);
- Binding = Bindings[3].getBinding();
+ Binding = Bindings[3]->getBinding();
EXPECT_EQ(3u, Binding.RecordID);
EXPECT_EQ(4u, Binding.Space);
EXPECT_EQ(4u, Binding.LowerBound);
@@ -258,13 +258,13 @@ declare target("dx.RawBuffer", float, 1, 0) @ind.func(target("dx.RawBuffer", flo
ASSERT_EQ(Bindings.size(), 2u)
<< "Handle should resolve into four resources";
- auto Binding = Bindings[0].getBinding();
+ auto Binding = Bindings[0]->getBinding();
EXPECT_EQ(0u, Binding.RecordID);
EXPECT_EQ(1u, Binding.Space);
EXPECT_EQ(1u, Binding.LowerBound);
EXPECT_EQ(1u, Binding.Size);
- Binding = Bindings[1].getBinding();
+ Binding = Bindings[1]->getBinding();
EXPECT_EQ(1u, Binding.RecordID);
EXPECT_EQ(4u, Binding.Space);
EXPECT_EQ(4u, Binding.LowerBound);
>From 6de3c49b2df1afb89d237fc16f22783c539dace5 Mon Sep 17 00:00:00 2001
From: Ashley Coleman <ascoleman at microsoft.com>
Date: Tue, 25 Mar 2025 18:02:43 -0600
Subject: [PATCH 20/22] address comments
---
llvm/include/llvm/Analysis/DXILResource.h | 14 ++----
llvm/lib/Analysis/DXILResource.cpp | 54 ++++++++++++++++++++---
2 files changed, 52 insertions(+), 16 deletions(-)
diff --git a/llvm/include/llvm/Analysis/DXILResource.h b/llvm/include/llvm/Analysis/DXILResource.h
index a5acca6ec32bb..d7f619e18fe73 100644
--- a/llvm/include/llvm/Analysis/DXILResource.h
+++ b/llvm/include/llvm/Analysis/DXILResource.h
@@ -594,18 +594,9 @@ class DXILResourceCounterDirectionMap {
void populate(Module &M, DXILBindingMap &DBM);
ResourceCounterDirection
- operator[](const dxil::ResourceBindingInfo &Info) const {
- auto Lower = llvm::lower_bound(
- CounterDirections, Info,
- [](const auto &LHS, const auto &RHS) { return *LHS.first < RHS; });
+ operator[](const dxil::ResourceBindingInfo &Info) const;
- if (Lower == CounterDirections.end())
- return ResourceCounterDirection::Unknown;
- if (*Lower->first != Info)
- return ResourceCounterDirection::Unknown;
-
- return Lower->second;
- }
+ void print(raw_ostream &OS) const;
};
class DXILResourceCounterDirectionAnalysis
@@ -646,6 +637,7 @@ class DXILResourceCounterDirectionWrapperPass : public ModulePass {
void releaseMemory() override;
void print(raw_ostream &OS, const Module *M) const override;
+ void dump() const;
};
ModulePass *createDXILResourceCounterDirectionWrapperPassPass();
diff --git a/llvm/lib/Analysis/DXILResource.cpp b/llvm/lib/Analysis/DXILResource.cpp
index 668480153c723..8a7197397739f 100644
--- a/llvm/lib/Analysis/DXILResource.cpp
+++ b/llvm/lib/Analysis/DXILResource.cpp
@@ -940,6 +940,46 @@ void DXILResourceCounterDirectionMap::populate(Module &M, DXILBindingMap &DBM) {
});
}
+ResourceCounterDirection DXILResourceCounterDirectionMap::operator[](
+ const dxil::ResourceBindingInfo &Info) const {
+ auto Lower = llvm::lower_bound(
+ CounterDirections, Info,
+ [](const auto &LHS, const auto &RHS) { return *LHS.first < RHS; });
+
+ if (Lower == CounterDirections.end())
+ return ResourceCounterDirection::Unknown;
+ if (*Lower->first != Info)
+ return ResourceCounterDirection::Unknown;
+
+ return Lower->second;
+}
+
+void DXILResourceCounterDirectionMap::print(raw_ostream &OS) const {
+ OS << "Counter Directions:\n";
+ for (const auto &Dir : CounterDirections) {
+ const dxil::ResourceBindingInfo::ResourceBinding &RB =
+ Dir.first->getBinding();
+
+ OS << " Binding(" << RB.RecordID << ", " << RB.Size << ", "
+ << RB.LowerBound << ", " << RB.Size << ", " << ")'s counter is ";
+
+ switch (Dir.second) {
+ case ResourceCounterDirection::Increment:
+ OS << "incremented\n";
+ break;
+ case ResourceCounterDirection::Decrement:
+ OS << "decremented\n";
+ break;
+ case ResourceCounterDirection::Unknown:
+ OS << "unknown\n";
+ break;
+ case ResourceCounterDirection::Invalid:
+ OS << "invalid\n";
+ break;
+ }
+ }
+}
+
void DXILResourceCounterDirectionWrapperPass::getAnalysisUsage(
AnalysisUsage &AU) const {
AU.addRequiredTransitive<DXILResourceBindingWrapperPass>();
@@ -963,13 +1003,17 @@ void DXILResourceCounterDirectionWrapperPass::print(raw_ostream &OS,
OS << "No resource directions have been built!\n";
return;
}
- // Map->print(OS, *DRTM, M->getDataLayout());
+
+ Map->print(OS);
}
-// #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;
>From f6a39c7a9bf250c898404c5f8a65d35ca74c67db Mon Sep 17 00:00:00 2001
From: Ashley Coleman <ascoleman at microsoft.com>
Date: Wed, 26 Mar 2025 12:38:00 -0600
Subject: [PATCH 21/22] address comments
---
llvm/lib/Analysis/DXILResource.cpp | 28 +++++++++++++---------------
1 file changed, 13 insertions(+), 15 deletions(-)
diff --git a/llvm/lib/Analysis/DXILResource.cpp b/llvm/lib/Analysis/DXILResource.cpp
index 8a7197397739f..28844d6eb0c64 100644
--- a/llvm/lib/Analysis/DXILResource.cpp
+++ b/llvm/lib/Analysis/DXILResource.cpp
@@ -910,25 +910,23 @@ void DXILResourceCounterDirectionMap::populate(Module &M, DXILBindingMap &DBM) {
ResourceCounterDirection::Invalid;
std::get<ResourceCounterDirection>(*DupNext) =
ResourceCounterDirection::Invalid;
+
+ // Raise an error for every invalid entry
+ StringRef Message =
+ "RWStructuredBuffers may increment or decrement their "
+ "counters, but not both.";
+ const Function *FFirst = std::get<const Function *>(*DupFirst);
+ const CallInst *CIFirst = std::get<const CallInst *>(*DupFirst);
+ const Function *FNext = std::get<const Function *>(*DupNext);
+ const CallInst *CINext = std::get<const CallInst *>(*DupNext);
+ M.getContext().diagnose(DiagnosticInfoGenericWithLoc(
+ Message, *FFirst, CIFirst->getDebugLoc()));
+ M.getContext().diagnose(DiagnosticInfoGenericWithLoc(
+ Message, *FNext, CINext->getDebugLoc()));
}
}
}
- // 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::Invalid)
- 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();
CounterDirections.reserve(DiagCounterDirs.size());
>From 6ae40ec151331a9e640f5981435481b4a9095f45 Mon Sep 17 00:00:00 2001
From: Ashley Coleman <ascoleman at microsoft.com>
Date: Wed, 26 Mar 2025 17:03:59 -0600
Subject: [PATCH 22/22] Remove unnecessary functions
---
llvm/include/llvm/Analysis/DXILResource.h | 5 ---
llvm/lib/Analysis/DXILResource.cpp | 43 -----------------------
2 files changed, 48 deletions(-)
diff --git a/llvm/include/llvm/Analysis/DXILResource.h b/llvm/include/llvm/Analysis/DXILResource.h
index d7f619e18fe73..05937ac6b00ae 100644
--- a/llvm/include/llvm/Analysis/DXILResource.h
+++ b/llvm/include/llvm/Analysis/DXILResource.h
@@ -595,8 +595,6 @@ class DXILResourceCounterDirectionMap {
ResourceCounterDirection
operator[](const dxil::ResourceBindingInfo &Info) const;
-
- void print(raw_ostream &OS) const;
};
class DXILResourceCounterDirectionAnalysis
@@ -635,9 +633,6 @@ class DXILResourceCounterDirectionWrapperPass : public ModulePass {
void getAnalysisUsage(AnalysisUsage &AU) const override;
bool runOnModule(Module &M) override;
void releaseMemory() override;
-
- void print(raw_ostream &OS, const Module *M) const override;
- void dump() const;
};
ModulePass *createDXILResourceCounterDirectionWrapperPassPass();
diff --git a/llvm/lib/Analysis/DXILResource.cpp b/llvm/lib/Analysis/DXILResource.cpp
index 28844d6eb0c64..b8d4afa5e3f96 100644
--- a/llvm/lib/Analysis/DXILResource.cpp
+++ b/llvm/lib/Analysis/DXILResource.cpp
@@ -952,32 +952,6 @@ ResourceCounterDirection DXILResourceCounterDirectionMap::operator[](
return Lower->second;
}
-void DXILResourceCounterDirectionMap::print(raw_ostream &OS) const {
- OS << "Counter Directions:\n";
- for (const auto &Dir : CounterDirections) {
- const dxil::ResourceBindingInfo::ResourceBinding &RB =
- Dir.first->getBinding();
-
- OS << " Binding(" << RB.RecordID << ", " << RB.Size << ", "
- << RB.LowerBound << ", " << RB.Size << ", " << ")'s counter is ";
-
- switch (Dir.second) {
- case ResourceCounterDirection::Increment:
- OS << "incremented\n";
- break;
- case ResourceCounterDirection::Decrement:
- OS << "decremented\n";
- break;
- case ResourceCounterDirection::Unknown:
- OS << "unknown\n";
- break;
- case ResourceCounterDirection::Invalid:
- OS << "invalid\n";
- break;
- }
- }
-}
-
void DXILResourceCounterDirectionWrapperPass::getAnalysisUsage(
AnalysisUsage &AU) const {
AU.addRequiredTransitive<DXILResourceBindingWrapperPass>();
@@ -995,23 +969,6 @@ bool DXILResourceCounterDirectionWrapperPass::runOnModule(Module &M) {
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);
-}
-
-#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
-LLVM_DUMP_METHOD
-void DXILResourceCounterDirectionWrapperPass::dump() const {
- print(dbgs(), nullptr);
-}
-#endif
-
//===----------------------------------------------------------------------===//
AnalysisKey DXILResourceTypeAnalysis::Key;
More information about the llvm-commits
mailing list