[llvm] [MCP][NFC] Refactor eliminateSpillageCopies (PR #208210)

Gaƫtan Bossu via llvm-commits llvm-commits at lists.llvm.org
Mon Jul 13 06:48:21 PDT 2026


================
@@ -1578,20 +1545,88 @@ void MachineCopyPropagation::eliminateSpillageCopies(MachineBasicBlock &MBB) {
       LLVM_DEBUG(dbgs() << "MCP: Not paired spill-reload:\n");
       LLVM_DEBUG(MaybeSpill->dump());
       LLVM_DEBUG(MI.dump());
-      Tracker.clobberRegister(Src, *TRI, *TII, UseCopyInstr);
-      LLVM_DEBUG(dbgs() << "MCP: Removed tracking of " << printReg(Src, TRI)
+      Tracker.clobberRegister(Src, TRI, TII, UseCopyInstr);
+      LLVM_DEBUG(dbgs() << "MCP: Removed tracking of " << printReg(Src, &TRI)
                         << "\n");
     }
-    Tracker.trackCopy(&MI, *TRI, *TII, UseCopyInstr);
   }
 
-  for (auto I = SpillChain.begin(), E = SpillChain.end(); I != E; ++I) {
-    auto &SC = I->second;
-    assert(ReloadChain.count(I->first) &&
-           "Reload chain of the same leader should exist");
-    auto &RC = ReloadChain[I->first];
-    TryFoldSpillageCopies(SC, RC);
+public:
+  SpillageCopyEliminator(const TargetRegisterInfo &TRI,
+                         const TargetInstrInfo &TII, CopyTracker &Tracker,
+                         bool UseCopyInstr)
+      : TRI(TRI), TII(TII), Tracker(Tracker), UseCopyInstr(UseCopyInstr) {}
+
+  void run(MachineBasicBlock &MBB) {
+    for (MachineInstr &MI : llvm::make_early_inc_range(MBB)) {
+      std::optional<DestSourcePair> CopyOperands =
+          isCopyInstr(MI, TII, UseCopyInstr);
+      if (!CopyOperands) {
+        processNonCopy(MI);
+        continue;
+      }
+
+      processCopy(MI, *CopyOperands);
+      Tracker.trackCopy(&MI, TRI, TII, UseCopyInstr);
+    }
+
+    for (auto &Chain : Chains)
+      tryFoldChain(Chain.Pairs);
+  }
+};
+
+// Remove spill-reload like copy chains. For example
+// r0 = COPY r1
+// r1 = COPY r2
+// r2 = COPY r3
+// r3 = COPY r4
+// <def-use r4>
+// r4 = COPY r3
+// r3 = COPY r2
+// r2 = COPY r1
+// r1 = COPY r0
+// will be folded into
+// r0 = COPY r1
+// r1 = COPY r4
+// <def-use r4>
+// r4 = COPY r1
+// r1 = COPY r0
+// TODO: Currently we don't track usage of r0 outside the chain, so we
+// conservatively keep its value as it was before the rewrite.
+//
+// The algorithm is trying to keep
+// property#1: No Dst of spill COPY in the chain is used or defined until the
+// paired reload COPY in the chain uses the Dst.
+//
+// property#2: NO Source of COPY in the chain is used or defined until the next
+// COPY in the chain defines the Source, except the innermost spill-reload
+// pair.
+//
+// The algorithm is conducted by checking every COPY inside the MBB, assuming
+// the COPY is a reload COPY, then try to find paired spill COPY by searching
+// the COPY defines the Src of the reload COPY backward. If such pair is found,
+// it either belongs to an existing chain or a new chain depends on
+// last available COPY uses the Dst of the reload COPY.
+// Implementation notes, we use CopyTracker::findLastDefCopy(Reg, ...) to find
+// out last COPY that defines Reg; we use CopyTracker::findLastUseCopy(Reg, ...)
+// to find out last COPY that uses Reg. When we are encountered with a Non-COPY
+// instruction, we check registers in the operands of this instruction. If this
+// Reg is defined by a COPY, we untrack this Reg via
+// CopyTracker::clobberRegister(Reg, ...).
+void MachineCopyPropagation::eliminateSpillageCopies(MachineBasicBlock &MBB) {
+
+  // Perform some cost modelling to ensure that only MBB's with more
+  // than 6 copies are checked. To create a chain that can be optimised,
+  // 6 copies are needed.
+  unsigned CopyCount = 0;
+  for (const MachineInstr &MI : MBB) {
+    if (isCopyInstr(MI, *TII, UseCopyInstr) && ++CopyCount > 6)
+      break;
   }
+  if (CopyCount < 6)
----------------
gbossu wrote:

Is it worth at least creating a `cl::opt` for that magic `6`? At least this exposes the number as somewhat magic and makes it tweakable.

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


More information about the llvm-commits mailing list