[llvm] [SLSR] Adding a cost model considering register pressure (PR #213808)

Igor Wodiany via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 13 03:13:31 PDT 2026


================
@@ -1362,11 +1376,124 @@ bool StraightLineStrengthReduceLegacyPass::runOnFunction(Function &F) {
   return StraightLineStrengthReduce(DL, DT, SE, TTI).runOnFunction(F);
 }
 
+// Go through all operands of instruction, and check if any operand is used in
+// another block different from the instruction's block and the other use is
+// not rewritable. return true if such operand is found, otherwise return false.
+bool StraightLineStrengthReduce::
+    hasOperandsUsedInNonRewritableUsersInAnotherBlock(
+        llvm::Instruction *Inst) const {
+  llvm::BasicBlock *InstBB = Inst->getParent();
+
+  for (Value *OpVal : Inst->operand_values()) {
+    auto *OpInst = dyn_cast<Instruction>(OpVal);
+    if (!OpInst)
+      continue;
+
+    for (const User *U : OpInst->users())
+      if (auto *UI = dyn_cast<Instruction>(U)) {
+        if (UI->isDebugOrPseudoInst())
+          continue;
+        if (UI->getParent() != InstBB && !hasRewritableCandidates(UI)) {
+          LLVM_DEBUG(dbgs()
+                     << "Inst's operand is used in another block "
+                     << "("
+                     << (InstBB->hasName() ? InstBB->getName() : "unnamed")
+                     << " -> "
+                     << (UI->getParent() && UI->getParent()->hasName()
+                             ? UI->getParent()->getName()
+                             : "unnamed")
+                     << ") " << *UI << "\n");
+          return true;
+        }
+      }
+  }
+  return false;
+}
+
+bool StraightLineStrengthReduce::hasRewritableCandidates(
+    const Instruction *Inst) const {
+  if (!RewriteCandidates.count(Inst))
+    return false;
+
+  for (const Candidate *C : RewriteCandidates.at(Inst))
+    if (C->Basis)
+      return true;
+
+  return false;
+}
+
+// Assign a monotonically increasing index to each (non-debug/pseudo)
+// instruction in BB so in-block distances can be queried in O(1) once built.
+static DenseMap<const Instruction *, int>
+buildBlockIndexMap(const BasicBlock &BB) {
+  DenseMap<const Instruction *, int> IndexMap;
+  int Index = 0;
+  for (const Instruction &I : BB) {
+    // Skip debug/pseudo instructions so the distance math is identical
+    // between debug and release builds.
+    if (I.isDebugOrPseudoInst())
+      continue;
+    IndexMap[&I] = Index++;
+  }
+  return IndexMap;
+}
+
+// Return true
+// 1. if C.Basis used only in C.Ins's block before C.Ins
+// AND
+// 2. if any use of C.Basis before C.Ins and C.Ins exceeds
+// SLSRBasisDistanceThreshold.
+bool StraightLineStrengthReduce::basisTooFarInSameBlock(
+    const Candidate &C,
+    DenseMap<const BasicBlock *, DenseMap<const Instruction *, int>>
+        &IndexCache,
+    const Instruction *I) const {
+  Instruction *Inst = C.Ins;
+  assert(Inst == I);
+  Instruction *BasisInst = C.Basis ? C.Basis->Ins : nullptr;
+  if (!BasisInst)
+    return false;
+
+  const BasicBlock *BB = Inst->getParent();
+  auto [It, Inserted] = IndexCache.try_emplace(BB);
+  if (Inserted)
+    It->second = buildBlockIndexMap(*BB);
+  const DenseMap<const Instruction *, int> &IndexMap = It->second;
+
+  auto InstIt = IndexMap.find(Inst);
+  if (InstIt == IndexMap.end())
+    return false;
+  int InstIdx = InstIt->second;
+
+  int LastUseIdx = 0;
+
+  bool FoundSameBlockUse = false;
+  for (const User *U : BasisInst->users()) {
+    const auto *UI = dyn_cast<Instruction>(U);
+    if (!UI)
+      continue;
+    // If one of the uses is not in the same block, return false.
+    if (UI->getParent() != BB)
+      return false;
+    auto UseIt = IndexMap.find(UI);
+    // If any same block use is later than Inst, return false.
+    if (UseIt == IndexMap.end() || UseIt->second >= InstIdx)
+      return false;
+    FoundSameBlockUse = true;
+    LastUseIdx = std::max(LastUseIdx, UseIt->second);
+  }
+
+  if (!FoundSameBlockUse)
+    return false;
+
+  return (InstIdx - LastUseIdx) > SLSRBasisDistanceThreshold;
+}
+
 bool StraightLineStrengthReduce::runOnFunction(Function &F) {
   LLVM_DEBUG(dbgs() << "SLSR on Function: " << F.getName() << "\n");
   // Traverse the dominator tree in the depth-first order. This order makes sure
   // all bases of a candidate are in Candidates when we process it.
-  for (const auto Node : depth_first(DT))
+  for (auto *const Node : depth_first(DT))
----------------
IgWod wrote:

nit: Unrelated change, probably shouldn't land in this PR

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


More information about the llvm-commits mailing list