[llvm] [HLSL] Implement DXILResourceBindingAnalysis (PR #137258)

Helena Kotas via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 30 12:05:06 PDT 2025


================
@@ -879,8 +883,121 @@ SmallVector<dxil::ResourceInfo *> DXILResourceMap::findByUse(const Value *Key) {
 
 //===----------------------------------------------------------------------===//
 
+void DXILResourceBindingInfo::populate(Module &M, DXILResourceTypeMap &DRTM) {
+  struct Binding {
+    ResourceClass ResClass;
+    uint32_t Space;
+    uint32_t LowerBound;
+    uint32_t UpperBound;
+    Binding(ResourceClass RC, uint32_t Sp, uint32_t LB, uint32_t UB)
+        : ResClass(RC), Space(Sp), LowerBound(LB), UpperBound(UB) {}
+  };
+  SmallVector<Binding> Bindings;
+
+  // collect all of the llvm.dx.resource.handlefrombinding calls;
+  // make a note if there is llvm.dx.resource.handlefromimplicitbinding
+  for (Function &F : M.functions()) {
+    if (!F.isDeclaration())
+      continue;
+
+    switch (F.getIntrinsicID()) {
+    default:
+      continue;
+    case Intrinsic::dx_resource_handlefrombinding: {
+      auto *HandleTy = cast<TargetExtType>(F.getReturnType());
+      ResourceTypeInfo &RTI = DRTM[HandleTy];
+
+      for (User *U : F.users())
+        if (CallInst *CI = dyn_cast<CallInst>(U)) {
+          uint32_t Space =
+              cast<ConstantInt>(CI->getArgOperand(0))->getZExtValue();
+          uint32_t LowerBound =
+              cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue();
+          int32_t Size =
+              cast<ConstantInt>(CI->getArgOperand(2))->getZExtValue();
+
+          // negative size means unbounded resource array;
+          // upper bound register overflow should be detected in Sema
+          assert((Size < 0 || (unsigned)LowerBound + Size - 1 <= UINT32_MAX) &&
+                 "upper bound register overflow");
+          uint32_t UpperBound = Size < 0 ? UINT32_MAX : LowerBound + Size - 1;
+          Bindings.emplace_back(RTI.getResourceClass(), Space, LowerBound,
+                                UpperBound);
+        }
+      break;
+    }
+    case Intrinsic::dx_resource_handlefromimplicitbinding: {
+      if (!F.user_empty())
+        ImplicitBinding = true;
+      break;
+    }
+    }
+  }
+
+  // sort all the collected bindings
+  llvm::stable_sort(Bindings, [](auto &LHS, auto &RHS) {
+    return std::tie(LHS.ResClass, LHS.Space, LHS.LowerBound) <
+           std::tie(RHS.ResClass, RHS.Space, RHS.LowerBound);
+  });
+
+  // remove duplicates
----------------
hekota wrote:

Correct. If 2 resources have identical binding this will not catch it. The problem is that since the global resource variables are marked internal by Clang, they get optimized away before this analysis runs, and we have no way of distinguishing between two 2 resources instances that are initialized with identical `llvm.dx.resource.handlefrombinding` calls.

We need to re-open the conversation about having the global resource variables present in the module until we are done with the resource processing and diagnostics passes. In the meantime, I will add a FIXME to this PR that this case is not covered.

Tracking issue:
Diagnose overlapping bindings: https://github.com/llvm/llvm-project/issues/110723



https://github.com/llvm/llvm-project/pull/137258


More information about the llvm-commits mailing list