[llvm] [HLSL] Analyze update counter usage (PR #130356)

Ashley Coleman via llvm-commits llvm-commits at lists.llvm.org
Fri Mar 7 14:16:50 PST 2025


================
@@ -818,8 +820,92 @@ 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 an entry explicitly marked
+  // unknown
+  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;
+
+  StringRef Message = "RWStructuredBuffers may increment or decrement their "
+                      "counters, but not both.";
+  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.
----------------
V-FEXrt wrote:

I'm not really sure how invalidate works, when/why I'd want to. 

Any pointers or info here would be greatly appreciated

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


More information about the llvm-commits mailing list