[llvm] [AMDGPU] Preserve resource requirements through call-graph cycles (PR #221625)

Matt Arsenault via llvm-commits llvm-commits at lists.llvm.org
Sun Sep 13 11:33:27 PDT 2026


================
@@ -247,33 +252,167 @@ bool AMDGPUMCExpr::evaluateInstPrefSize(MCValue &Res,
 
 bool AMDGPUMCExpr::isSymbolUsedInExpression(const MCSymbol *Sym,
                                             const MCExpr *E) {
-  switch (E->getKind()) {
-  case MCExpr::Constant:
-    return false;
-  case MCExpr::Unary:
-    return isSymbolUsedInExpression(
-        Sym, static_cast<const MCUnaryExpr *>(E)->getSubExpr());
-  case MCExpr::Binary: {
-    const MCBinaryExpr *BE = static_cast<const MCBinaryExpr *>(E);
-    return isSymbolUsedInExpression(Sym, BE->getLHS()) ||
-           isSymbolUsedInExpression(Sym, BE->getRHS());
-  }
-  case MCExpr::SymbolRef: {
-    const MCSymbol &S = static_cast<const MCSymbolRefExpr *>(E)->getSymbol();
-    if (S.isVariable())
-      return isSymbolUsedInExpression(Sym, S.getVariableValue());
-    return &S == Sym;
-  }
-  case MCExpr::Specifier:
-  case MCExpr::Target: {
-    auto *TE = static_cast<const AMDGPUMCExpr *>(E);
-    for (const MCExpr *E : TE->getArgs())
-      if (isSymbolUsedInExpression(Sym, E))
+  SmallVector<const MCExpr *, 16> WorkList{E};
+  SmallPtrSet<const MCExpr *, 16> Seen;
+  while (!WorkList.empty()) {
+    const MCExpr *Expr = WorkList.pop_back_val();
+    if (!Seen.insert(Expr).second)
+      continue;
+    switch (Expr->getKind()) {
+    case MCExpr::Constant:
+      break;
+    case MCExpr::Unary:
+      WorkList.push_back(cast<MCUnaryExpr>(Expr)->getSubExpr());
+      break;
+    case MCExpr::Binary: {
+      const auto *BE = cast<MCBinaryExpr>(Expr);
+      WorkList.push_back(BE->getRHS());
+      WorkList.push_back(BE->getLHS());
+      break;
+    }
+    case MCExpr::SymbolRef: {
+      const MCSymbol &S = cast<MCSymbolRefExpr>(Expr)->getSymbol();
+      if (&S == Sym)
         return true;
-    return false;
+      if (S.isVariable())
+        WorkList.push_back(S.getVariableValue());
+      break;
+    }
+    case MCExpr::Specifier:
+      WorkList.push_back(cast<MCSpecifierExpr>(Expr)->getSubExpr());
+      break;
+    case MCExpr::Target:
+      append_range(WorkList, reverse(cast<AMDGPUMCExpr>(Expr)->getArgs()));
+      break;
+    }
   }
+  return false;
+}
+
+// Resource expressions form a DAG of maxima, boolean unions, and frame-size
+// additions. Evaluate shared subexpressions once per query, including additions
+// between maxima, instead of recursively expanding every path through the DAG.
+static bool evaluateResourceExpr(const AMDGPUMCExpr *Root, MCValue &Res,
+                                 const MCAssembler *Asm) {
+  enum class Phase { Visit, Complete, CheckAbsolute };
+  struct WorkItem {
+    const MCExpr *Expr;
+    Phase Step = Phase::Visit;
+    MCSymbol *ResolvingSymbol = nullptr;
+  };
+  SmallVector<WorkItem, 16> WorkList{{Root}};
----------------
arsenm wrote:

```suggestion
  SmallVector<WorkItem, 16> WorkList = {Root};
```

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


More information about the llvm-commits mailing list