[llvm] [HLSL] Analyze updateCounter usage (PR #135669)
Helena Kotas via llvm-commits
llvm-commits at lists.llvm.org
Tue Apr 22 11:15:44 PDT 2025
================
@@ -280,4 +274,159 @@ 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() {
+entry:
+ %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)
+ ret void
+}
+ )";
+
+ auto M = parseAsm(Assembly);
+
+ DXILResourceMap &DRM = MAM->getResult<DXILResourceAnalysis>(*M);
+
+ for (const Function &F : M->functions()) {
+ if (F.getIntrinsicID() != Intrinsic::dx_resource_handlefrombinding) {
+ continue;
+ }
+
+ for (const User *U : F.users()) {
+ const CallInst *CI = cast<CallInst>(U);
+ const auto *const Binding = DRM.find(CI);
+ ASSERT_EQ(Binding->CounterDirection, ResourceCounterDirection::Decrement);
+ }
+ }
+}
+
+// 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() {
+entry:
+ %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)
+ ret void
+}
+ )";
+
+ auto M = parseAsm(Assembly);
+
+ DXILResourceMap &DRM = MAM->getResult<DXILResourceAnalysis>(*M);
+
+ for (const Function &F : M->functions()) {
+ if (F.getIntrinsicID() != Intrinsic::dx_resource_handlefrombinding) {
+ continue;
+ }
+
+ for (const User *U : F.users()) {
+ const CallInst *CI = cast<CallInst>(U);
+ const auto *const Binding = DRM.find(CI);
+ ASSERT_EQ(Binding->CounterDirection, ResourceCounterDirection::Increment);
+ }
+ }
+}
+
+// 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() {
+entry:
+ %handle = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding(i32 1, i32 2, i32 3, i32 4, i1 false)
+ ret void
+}
+ )";
+
+ auto M = parseAsm(Assembly);
+
+ DXILResourceMap &DRM = MAM->getResult<DXILResourceAnalysis>(*M);
+
+ for (const Function &F : M->functions()) {
+ if (F.getIntrinsicID() != Intrinsic::dx_resource_handlefrombinding) {
+ continue;
+ }
+
+ for (const User *U : F.users()) {
+ const CallInst *CI = cast<CallInst>(U);
+ const auto *const Binding = DRM.find(CI);
+ ASSERT_EQ(Binding->CounterDirection, ResourceCounterDirection::Unknown);
+ }
+ }
+}
+
+// Test that multiple different resources with unique incs/decs aren't
+// marked invalid
+TEST_F(UniqueResourceFromUseTest, TestResourceCounterMultiple) {
+ StringRef Assembly = R"(
+define void @main() {
+entry:
+ %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)
+ ret void
+}
+ )";
+
+ auto M = parseAsm(Assembly);
+
+ DXILResourceMap &DRM = MAM->getResult<DXILResourceAnalysis>(*M);
+
+ ResourceCounterDirection Dirs[2] = {ResourceCounterDirection::Decrement,
+ ResourceCounterDirection::Increment};
+ ResourceCounterDirection *Dir = Dirs;
+
+ for (const Function &F : M->functions()) {
+ if (F.getIntrinsicID() != Intrinsic::dx_resource_handlefrombinding) {
+ continue;
+ }
+
+ for (const User *U : F.users()) {
+ const CallInst *CI = cast<CallInst>(U);
+ const auto *const Binding = DRM.find(CI);
+ ASSERT_EQ(Binding->CounterDirection, *Dir);
----------------
hekota wrote:
If by some convoluted bug there happen to be 3 instances of `handlefrombinding` or `updatecounter` intrinsics, this will crash. Consider replacing `Dir` with something like `ExpectedDirectionIndex` and check the value is not OOB before accessing `Dirs`.
https://github.com/llvm/llvm-project/pull/135669
More information about the llvm-commits
mailing list