[llvm] [HLSL] Add support to lookup a ResourceBindingInfo from its use (PR #126556)
Ashley Coleman via llvm-commits
llvm-commits at lists.llvm.org
Mon Feb 10 10:05:35 PST 2025
https://github.com/V-FEXrt updated https://github.com/llvm/llvm-project/pull/126556
>From ab1e78dd414c3d2c816451f2310082c1a1827e2f Mon Sep 17 00:00:00 2001
From: Ashley Coleman <ascoleman at microsoft.com>
Date: Fri, 7 Feb 2025 16:30:44 -0700
Subject: [PATCH 1/3] Implement trivial resource lookup with test
---
llvm/include/llvm/Analysis/DXILResource.h | 4 +
llvm/lib/Analysis/DXILResource.cpp | 20 ++++-
llvm/unittests/Target/DirectX/CMakeLists.txt | 1 +
.../DirectX/UniqueResourceFromUseTests.cpp | 87 +++++++++++++++++++
4 files changed, 111 insertions(+), 1 deletion(-)
create mode 100644 llvm/unittests/Target/DirectX/UniqueResourceFromUseTests.cpp
diff --git a/llvm/include/llvm/Analysis/DXILResource.h b/llvm/include/llvm/Analysis/DXILResource.h
index 87c5615c28ee0c5..8a861c510c0011b 100644
--- a/llvm/include/llvm/Analysis/DXILResource.h
+++ b/llvm/include/llvm/Analysis/DXILResource.h
@@ -446,6 +446,10 @@ class DXILBindingMap {
return Pos == CallMap.end() ? Infos.end() : (Infos.begin() + Pos->second);
}
+ // Resoloves the use of a resource handle into the unique description of that
+ // resource by deduping calls to create.
+ const_iterator findByUse(const Value *Key) const;
+
const_iterator find(const CallInst *Key) const {
auto Pos = CallMap.find(Key);
return Pos == CallMap.end() ? Infos.end() : (Infos.begin() + Pos->second);
diff --git a/llvm/lib/Analysis/DXILResource.cpp b/llvm/lib/Analysis/DXILResource.cpp
index 7f28e63cc117d4c..56957a7ea09b60f 100644
--- a/llvm/lib/Analysis/DXILResource.cpp
+++ b/llvm/lib/Analysis/DXILResource.cpp
@@ -770,6 +770,23 @@ void DXILBindingMap::print(raw_ostream &OS, DXILResourceTypeMap &DRTM,
}
}
+SmallVector<dxil::ResourceBindingInfo>::const_iterator DXILBindingMap::findByUse(const Value *Key) const {
+ const CallInst *CI = dyn_cast<CallInst>(Key);
+ if (!CI) {
+ // TODO: Any other cases to follow up the tree?
+ return Infos.end();
+ }
+
+ switch (CI->getIntrinsicID()) {
+ case Intrinsic::not_intrinsic:
+ return Infos.end();
+ case Intrinsic::dx_resource_handlefrombinding:
+ return find(CI);
+ }
+
+ return Infos.end();
+}
+
//===----------------------------------------------------------------------===//
AnalysisKey DXILResourceTypeAnalysis::Key;
@@ -828,7 +845,8 @@ bool DXILResourceBindingWrapperPass::runOnModule(Module &M) {
return false;
}
-void DXILResourceBindingWrapperPass::releaseMemory() { Map.reset(); }
+void DXILResourceBindingWrapperPass::releaseMemory() {
+ /*Map.reset();*/ }
void DXILResourceBindingWrapperPass::print(raw_ostream &OS,
const Module *M) const {
diff --git a/llvm/unittests/Target/DirectX/CMakeLists.txt b/llvm/unittests/Target/DirectX/CMakeLists.txt
index 626c0d6384268da..4aed48c0b9a2ac5 100644
--- a/llvm/unittests/Target/DirectX/CMakeLists.txt
+++ b/llvm/unittests/Target/DirectX/CMakeLists.txt
@@ -14,4 +14,5 @@ set(LLVM_LINK_COMPONENTS
add_llvm_target_unittest(DirectXTests
CBufferDataLayoutTests.cpp
PointerTypeAnalysisTests.cpp
+ UniqueResourceFromUseTests.cpp
)
diff --git a/llvm/unittests/Target/DirectX/UniqueResourceFromUseTests.cpp b/llvm/unittests/Target/DirectX/UniqueResourceFromUseTests.cpp
new file mode 100644
index 000000000000000..08e9cc77d166aba
--- /dev/null
+++ b/llvm/unittests/Target/DirectX/UniqueResourceFromUseTests.cpp
@@ -0,0 +1,87 @@
+//===- llvm/unittests/Target/DirectX/PointerTypeAnalysisTests.cpp ---------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "DirectXIRPasses/PointerTypeAnalysis.h"
+#include "llvm/Analysis/DXILResource.h"
+#include "llvm/AsmParser/Parser.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/Type.h"
+#include "llvm/IR/TypedPointerType.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/SourceMgr.h"
+#include "llvm/Transforms/Utils/Debugify.h"
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+using ::testing::Contains;
+using ::testing::Pair;
+
+using namespace llvm;
+using namespace llvm::dxil;
+
+template <typename T> struct IsA {
+ friend bool operator==(const Value *V, const IsA &) { return isa<T>(V); }
+};
+
+TEST(UniqueResourceFromUse, 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)
+ 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)
+ )";
+
+ LLVMContext Context;
+ SMDiagnostic Error;
+ auto M = parseAssemblyString(Assembly, Error, Context);
+ ASSERT_TRUE(M) << "Bad assembly?";
+ DebugifyCustomPassManager Passes;
+ Passes.add(createDXILResourceTypeWrapperPassPass());
+ DXILResourceBindingWrapperPass* RBPass = new DXILResourceBindingWrapperPass();
+ Passes.add(RBPass);
+ Passes.run(*M);
+
+ const DXILBindingMap &DBM = RBPass->getBindingMap();
+ for (const Function& F : M->functions()) {
+ if (F.getName() != "a.func") {
+ continue;
+ }
+
+ unsigned CalledResources = 0;
+
+ for (const User* U : F.users()) {
+ const CallInst* CI = dyn_cast<CallInst>(U);
+ ASSERT_TRUE(CI) << "All users of @a.func must be CallInst";
+
+ const Value* Handle = CI->getArgOperand(0);
+
+ const auto* It = DBM.findByUse(Handle);
+ ASSERT_TRUE(It != DBM.end()) << "Handle should resolve into resource";
+
+ const llvm::dxil::ResourceBindingInfo::ResourceBinding& Binding = It->getBinding();
+ EXPECT_EQ(0u, Binding.RecordID);
+ EXPECT_EQ(1u, Binding.Space);
+ EXPECT_EQ(2u, Binding.LowerBound);
+ EXPECT_EQ(3u, Binding.Size);
+
+ CalledResources++;
+ }
+
+ EXPECT_EQ(1u, CalledResources) << "Expected exactly 1 resolved call to create resource";
+ }
+
+}
>From e7d1042457256b5580125f6a72789ad191f05b3f Mon Sep 17 00:00:00 2001
From: Ashley Coleman <ascoleman at microsoft.com>
Date: Mon, 10 Feb 2025 10:39:36 -0700
Subject: [PATCH 2/3] format
---
llvm/lib/Analysis/DXILResource.cpp | 29 ++++++++++---------
.../DirectX/UniqueResourceFromUseTests.cpp | 19 ++++++------
2 files changed, 25 insertions(+), 23 deletions(-)
diff --git a/llvm/lib/Analysis/DXILResource.cpp b/llvm/lib/Analysis/DXILResource.cpp
index 56957a7ea09b60f..bcf8fed90bcad3e 100644
--- a/llvm/lib/Analysis/DXILResource.cpp
+++ b/llvm/lib/Analysis/DXILResource.cpp
@@ -770,21 +770,22 @@ void DXILBindingMap::print(raw_ostream &OS, DXILResourceTypeMap &DRTM,
}
}
-SmallVector<dxil::ResourceBindingInfo>::const_iterator DXILBindingMap::findByUse(const Value *Key) const {
- const CallInst *CI = dyn_cast<CallInst>(Key);
- if (!CI) {
- // TODO: Any other cases to follow up the tree?
- return Infos.end();
- }
-
- switch (CI->getIntrinsicID()) {
- case Intrinsic::not_intrinsic:
- return Infos.end();
- case Intrinsic::dx_resource_handlefrombinding:
- return find(CI);
- }
+SmallVector<dxil::ResourceBindingInfo>::const_iterator
+DXILBindingMap::findByUse(const Value *Key) const {
+ const CallInst *CI = dyn_cast<CallInst>(Key);
+ if (!CI) {
+ // TODO: Any other cases to follow up the tree?
+ return Infos.end();
+ }
+ switch (CI->getIntrinsicID()) {
+ case Intrinsic::not_intrinsic:
return Infos.end();
+ case Intrinsic::dx_resource_handlefrombinding:
+ return find(CI);
+ }
+
+ return Infos.end();
}
//===----------------------------------------------------------------------===//
@@ -845,7 +846,7 @@ bool DXILResourceBindingWrapperPass::runOnModule(Module &M) {
return false;
}
-void DXILResourceBindingWrapperPass::releaseMemory() {
+void DXILResourceBindingWrapperPass::releaseMemory() {
/*Map.reset();*/ }
void DXILResourceBindingWrapperPass::print(raw_ostream &OS,
diff --git a/llvm/unittests/Target/DirectX/UniqueResourceFromUseTests.cpp b/llvm/unittests/Target/DirectX/UniqueResourceFromUseTests.cpp
index 08e9cc77d166aba..1f40ccebd4a3ca3 100644
--- a/llvm/unittests/Target/DirectX/UniqueResourceFromUseTests.cpp
+++ b/llvm/unittests/Target/DirectX/UniqueResourceFromUseTests.cpp
@@ -51,28 +51,29 @@ declare void @a.func(target("dx.RawBuffer", float, 1, 0) %handle)
ASSERT_TRUE(M) << "Bad assembly?";
DebugifyCustomPassManager Passes;
Passes.add(createDXILResourceTypeWrapperPassPass());
- DXILResourceBindingWrapperPass* RBPass = new DXILResourceBindingWrapperPass();
+ DXILResourceBindingWrapperPass *RBPass = new DXILResourceBindingWrapperPass();
Passes.add(RBPass);
Passes.run(*M);
const DXILBindingMap &DBM = RBPass->getBindingMap();
- for (const Function& F : M->functions()) {
+ for (const Function &F : M->functions()) {
if (F.getName() != "a.func") {
continue;
}
unsigned CalledResources = 0;
- for (const User* U : F.users()) {
- const CallInst* CI = dyn_cast<CallInst>(U);
+ for (const User *U : F.users()) {
+ const CallInst *CI = dyn_cast<CallInst>(U);
ASSERT_TRUE(CI) << "All users of @a.func must be CallInst";
- const Value* Handle = CI->getArgOperand(0);
+ const Value *Handle = CI->getArgOperand(0);
- const auto* It = DBM.findByUse(Handle);
+ const auto *It = DBM.findByUse(Handle);
ASSERT_TRUE(It != DBM.end()) << "Handle should resolve into resource";
- const llvm::dxil::ResourceBindingInfo::ResourceBinding& Binding = It->getBinding();
+ const llvm::dxil::ResourceBindingInfo::ResourceBinding &Binding =
+ It->getBinding();
EXPECT_EQ(0u, Binding.RecordID);
EXPECT_EQ(1u, Binding.Space);
EXPECT_EQ(2u, Binding.LowerBound);
@@ -81,7 +82,7 @@ declare void @a.func(target("dx.RawBuffer", float, 1, 0) %handle)
CalledResources++;
}
- EXPECT_EQ(1u, CalledResources) << "Expected exactly 1 resolved call to create resource";
+ EXPECT_EQ(1u, CalledResources)
+ << "Expected exactly 1 resolved call to create resource";
}
-
}
>From 09b63733c9edadf42fbebe7e8a8376770cd016cb Mon Sep 17 00:00:00 2001
From: Ashley Coleman <ascoleman at microsoft.com>
Date: Mon, 10 Feb 2025 11:05:00 -0700
Subject: [PATCH 3/3] Add TODOs
---
llvm/lib/Analysis/DXILResource.cpp | 2 ++
1 file changed, 2 insertions(+)
diff --git a/llvm/lib/Analysis/DXILResource.cpp b/llvm/lib/Analysis/DXILResource.cpp
index bcf8fed90bcad3e..1c34850caa707d7 100644
--- a/llvm/lib/Analysis/DXILResource.cpp
+++ b/llvm/lib/Analysis/DXILResource.cpp
@@ -780,6 +780,7 @@ DXILBindingMap::findByUse(const Value *Key) const {
switch (CI->getIntrinsicID()) {
case Intrinsic::not_intrinsic:
+ // TODO: Walk the call tree
return Infos.end();
case Intrinsic::dx_resource_handlefrombinding:
return find(CI);
@@ -847,6 +848,7 @@ bool DXILResourceBindingWrapperPass::runOnModule(Module &M) {
}
void DXILResourceBindingWrapperPass::releaseMemory() {
+ // TODO: Can't comment out this code
/*Map.reset();*/ }
void DXILResourceBindingWrapperPass::print(raw_ostream &OS,
More information about the llvm-commits
mailing list