[llvm] [MachineCopyPropagation][NFC] Refactor EliminateSpillageCopies (PR #192609)

Jack Styles via llvm-commits llvm-commits at lists.llvm.org
Fri Apr 17 02:27:42 PDT 2026


https://github.com/Stylie777 updated https://github.com/llvm/llvm-project/pull/192609

>From e12dcff81c3a6718f67d069badff91c6a27c78c1 Mon Sep 17 00:00:00 2001
From: Jack Styles <jack.styles at arm.com>
Date: Tue, 14 Apr 2026 14:38:38 +0100
Subject: [PATCH 1/4] [MachineCopyPropagation][NFC] Refactor
 EliminateSpillageCopies

This patch builds on the original implementation to address areas that
may impact compile time regression if enabled. The aim of the patch is
to streamline and improve the implementation for better compile time
impact. A summary of the changes is as follows:
- Cost modelling that does an initial scan of the block, any blocks with
less than 6 copies are immediately skipped.
- RegMask scan in `findLastSeenDefInCopy` removed. This now only checks
the recorded copies to ensure that RegMasks are clobbered when they are
seen if they clobber a Reg
- Streamlining of `IsSpillReloadPair` and `IsChainedCopy` to reduce the
need for a second call to isCopyInstr to get the DestSourcePair, these
are now returned from the lamdba function
- Use of TRI API to get the CommonRegClass, rather than scanning all
RegClasses

Assisted-by: Claude Sonnet 4.6 (Co-Pilot)
---
 llvm/lib/CodeGen/MachineCopyPropagation.cpp | 65 ++++++++++++---------
 1 file changed, 38 insertions(+), 27 deletions(-)

diff --git a/llvm/lib/CodeGen/MachineCopyPropagation.cpp b/llvm/lib/CodeGen/MachineCopyPropagation.cpp
index 4d2a66f41df93..22fdedcd5465f 100644
--- a/llvm/lib/CodeGen/MachineCopyPropagation.cpp
+++ b/llvm/lib/CodeGen/MachineCopyPropagation.cpp
@@ -421,20 +421,20 @@ class CopyTracker {
     if (!TRI.isSubRegisterEq(Dst, Reg))
       return nullptr;
 
-    for (const MachineInstr &MI :
-         make_range(static_cast<const MachineInstr *>(DefCopy)->getIterator(),
-                    Current.getIterator()))
-      for (const MachineOperand &MO : MI.operands())
-        if (MO.isRegMask())
-          if (MO.clobbersPhysReg(Dst)) {
-            LLVM_DEBUG(dbgs() << "MCP: Removed tracking of "
-                              << printReg(Dst, &TRI) << "\n");
-            return nullptr;
-          }
-
     return DefCopy;
   }
 
+  void clobberNonPreservedRegs(const BitVector &PreservedRegUnits,
+                              const TargetRegisterInfo &TRI,
+                              const TargetInstrInfo &TII, bool UseCopyInstr) {
+    SmallVector<MCRegUnit, 8> UnitsToClobber;
+    for (auto &[Unit, _] : Copies)
+      if (!PreservedRegUnits.test(static_cast<unsigned>(Unit)))
+        UnitsToClobber.push_back(Unit);
+    for (MCRegUnit Unit : UnitsToClobber)
+      clobberRegUnit(Unit, TRI, TII, UseCopyInstr);
+  }
+
   // Find last COPY that uses Reg.
   MachineInstr *findLastSeenUseInCopy(MCRegister Reg,
                                       const TargetRegisterInfo &TRI) {
@@ -1284,7 +1284,7 @@ void MachineCopyPropagation::backwardCopyPropagateBlock(
 // 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) {
+void MachineCopyPropagation::EliminateSpillageCopies(MachineBasicBlock &MBB) {
   // ChainLeader maps MI inside a spill-reload chain to its innermost reload COPY.
   // Thus we can track if a MI belongs to an existing spill-reload chain.
   DenseMap<MachineInstr *, MachineInstr *> ChainLeader;
@@ -1323,9 +1323,9 @@ void MachineCopyPropagation::eliminateSpillageCopies(MachineBasicBlock &MBB) {
           if (CopySourceInvalid.count(Reload))
             return;
 
-        auto CheckCopyConstraint = [this](Register Dst, Register Src) {
+        auto CheckCopyConstraint = [this](Register Def, Register Src) {
           for (const TargetRegisterClass *RC : TRI->regclasses()) {
-            if (RC->contains(Dst) && RC->contains(Src))
+            if (RC->contains(Def) && RC->contains(Src))
               return true;
           }
           return false;
@@ -1367,22 +1367,26 @@ void MachineCopyPropagation::eliminateSpillageCopies(MachineBasicBlock &MBB) {
         }
       };
 
-  auto IsFoldableCopy = [this](const MachineInstr &MaybeCopy) {
+  auto GetFoldableCopy =
+      [this](const MachineInstr &MaybeCopy) -> std::optional<DestSourcePair> {
     if (MaybeCopy.getNumImplicitOperands() > 0)
-      return false;
+      return std::nullopt;
     std::optional<DestSourcePair> CopyOperands =
         isCopyInstr(MaybeCopy, *TII, UseCopyInstr);
     if (!CopyOperands)
       return false;
-    auto [Dst, Src] = getDstSrcMCRegs(*CopyOperands);
-    return Src && Dst && !TRI->regsOverlap(Src, Dst) &&
+    Register Src = CopyOperands->Source->getReg();
+    Register Def = CopyOperands->Destination->getReg();
+    return Src && Def && !TRI->regsOverlap(Src, Def) &&
            CopyOperands->Source->isRenamable() &&
            CopyOperands->Destination->isRenamable();
   };
 
-  auto IsSpillReloadPair = [&, this](const MachineInstr &Spill,
-                                     const MachineInstr &Reload) {
-    if (!IsFoldableCopy(Spill) || !IsFoldableCopy(Reload))
+  auto IsSpillReloadPair = [&](const MachineInstr &Spill,
+                               const MachineInstr &Reload) {
+    std::optional<DestSourcePair> FoldableSpillCopy = GetFoldableCopy(Spill);
+    std::optional<DestSourcePair> FoldableReloadCopy = GetFoldableCopy(Reload);
+    if (!FoldableReloadCopy || !FoldableSpillCopy)
       return false;
     std::optional<DestSourcePair> SpillCopy =
         isCopyInstr(Spill, *TII, UseCopyInstr);
@@ -1390,13 +1394,16 @@ void MachineCopyPropagation::eliminateSpillageCopies(MachineBasicBlock &MBB) {
         isCopyInstr(Reload, *TII, UseCopyInstr);
     if (!SpillCopy || !ReloadCopy)
       return false;
-    return getSrcMCReg(*SpillCopy) == getDstMCReg(*ReloadCopy) &&
-           getDstMCReg(*SpillCopy) == getSrcMCReg(*ReloadCopy);
+    return SpillCopy->Source->getReg() == ReloadCopy->Destination->getReg() &&
+           SpillCopy->Destination->getReg() == ReloadCopy->Source->getReg();
   };
 
-  auto IsChainedCopy = [&, this](const MachineInstr &Prev,
-                                 const MachineInstr &Current) {
-    if (!IsFoldableCopy(Prev) || !IsFoldableCopy(Current))
+  auto IsChainedCopy = [&](const MachineInstr &Prev,
+                           const MachineInstr &Current) {
+    std::optional<DestSourcePair> FoldablePrevCopy = GetFoldableCopy(Prev);
+    std::optional<DestSourcePair> FoldableCurrentCopy =
+        GetFoldableCopy(Current);
+    if (!FoldablePrevCopy || !FoldableCurrentCopy)
       return false;
     std::optional<DestSourcePair> PrevCopy =
         isCopyInstr(Prev, *TII, UseCopyInstr);
@@ -1404,7 +1411,7 @@ void MachineCopyPropagation::eliminateSpillageCopies(MachineBasicBlock &MBB) {
         isCopyInstr(Current, *TII, UseCopyInstr);
     if (!PrevCopy || !CurrentCopy)
       return false;
-    return getSrcMCReg(*PrevCopy) == getDstMCReg(*CurrentCopy);
+    return PrevCopy->Source->getReg() == CurrentCopy->Destination->getReg();
   };
 
   for (MachineInstr &MI : llvm::make_early_inc_range(MBB)) {
@@ -1415,6 +1422,10 @@ void MachineCopyPropagation::eliminateSpillageCopies(MachineBasicBlock &MBB) {
     SmallSet<Register, 8> RegsToClobber;
     if (!CopyOperands) {
       for (const MachineOperand &MO : MI.operands()) {
+        if (MO.isRegMask()) {
+          BitVector &PreservedRegUnits = Tracker.getPreservedRegUnits(MO, *TRI);
+          Tracker.clobberNonPreservedRegs(PreservedRegUnits, *TRI, *TII, UseCopyInstr);
+        }
         if (!MO.isReg())
           continue;
         Register Reg = MO.getReg();

>From 5a2848b1347acf6c718096f70e9d3e9836a7f4c0 Mon Sep 17 00:00:00 2001
From: Jack Styles <jack.styles at arm.com>
Date: Fri, 17 Apr 2026 10:11:45 +0100
Subject: [PATCH 2/4] Fix formatting, build error and some missed elements of
 rebase

---
 llvm/lib/CodeGen/MachineCopyPropagation.cpp | 44 +++++++++------------
 1 file changed, 19 insertions(+), 25 deletions(-)

diff --git a/llvm/lib/CodeGen/MachineCopyPropagation.cpp b/llvm/lib/CodeGen/MachineCopyPropagation.cpp
index 22fdedcd5465f..abcd6ecbd3389 100644
--- a/llvm/lib/CodeGen/MachineCopyPropagation.cpp
+++ b/llvm/lib/CodeGen/MachineCopyPropagation.cpp
@@ -425,8 +425,8 @@ class CopyTracker {
   }
 
   void clobberNonPreservedRegs(const BitVector &PreservedRegUnits,
-                              const TargetRegisterInfo &TRI,
-                              const TargetInstrInfo &TII, bool UseCopyInstr) {
+                               const TargetRegisterInfo &TRI,
+                               const TargetInstrInfo &TII, bool UseCopyInstr) {
     SmallVector<MCRegUnit, 8> UnitsToClobber;
     for (auto &[Unit, _] : Copies)
       if (!PreservedRegUnits.test(static_cast<unsigned>(Unit)))
@@ -1284,7 +1284,7 @@ void MachineCopyPropagation::backwardCopyPropagateBlock(
 // 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) {
+void MachineCopyPropagation::eliminateSpillageCopies(MachineBasicBlock &MBB) {
   // ChainLeader maps MI inside a spill-reload chain to its innermost reload COPY.
   // Thus we can track if a MI belongs to an existing spill-reload chain.
   DenseMap<MachineInstr *, MachineInstr *> ChainLeader;
@@ -1374,12 +1374,14 @@ void MachineCopyPropagation::EliminateSpillageCopies(MachineBasicBlock &MBB) {
     std::optional<DestSourcePair> CopyOperands =
         isCopyInstr(MaybeCopy, *TII, UseCopyInstr);
     if (!CopyOperands)
-      return false;
-    Register Src = CopyOperands->Source->getReg();
-    Register Def = CopyOperands->Destination->getReg();
-    return Src && Def && !TRI->regsOverlap(Src, Def) &&
-           CopyOperands->Source->isRenamable() &&
-           CopyOperands->Destination->isRenamable();
+      return std::nullopt;
+    auto [Dst, Src] = getDstSrcMCRegs(*CopyOperands);
+    if (Src && Dst && !TRI->regsOverlap(Src, Dst) &&
+        CopyOperands->Source->isRenamable() &&
+        CopyOperands->Destination->isRenamable())
+      return CopyOperands;
+
+    return std::nullopt;
   };
 
   auto IsSpillReloadPair = [&](const MachineInstr &Spill,
@@ -1388,14 +1390,10 @@ void MachineCopyPropagation::EliminateSpillageCopies(MachineBasicBlock &MBB) {
     std::optional<DestSourcePair> FoldableReloadCopy = GetFoldableCopy(Reload);
     if (!FoldableReloadCopy || !FoldableSpillCopy)
       return false;
-    std::optional<DestSourcePair> SpillCopy =
-        isCopyInstr(Spill, *TII, UseCopyInstr);
-    std::optional<DestSourcePair> ReloadCopy =
-        isCopyInstr(Reload, *TII, UseCopyInstr);
-    if (!SpillCopy || !ReloadCopy)
-      return false;
-    return SpillCopy->Source->getReg() == ReloadCopy->Destination->getReg() &&
-           SpillCopy->Destination->getReg() == ReloadCopy->Source->getReg();
+    return FoldableSpillCopy->Source->getReg() ==
+               FoldableReloadCopy->Destination->getReg() &&
+           FoldableSpillCopy->Destination->getReg() ==
+               FoldableReloadCopy->Source->getReg();
   };
 
   auto IsChainedCopy = [&](const MachineInstr &Prev,
@@ -1405,13 +1403,8 @@ void MachineCopyPropagation::EliminateSpillageCopies(MachineBasicBlock &MBB) {
         GetFoldableCopy(Current);
     if (!FoldablePrevCopy || !FoldableCurrentCopy)
       return false;
-    std::optional<DestSourcePair> PrevCopy =
-        isCopyInstr(Prev, *TII, UseCopyInstr);
-    std::optional<DestSourcePair> CurrentCopy =
-        isCopyInstr(Current, *TII, UseCopyInstr);
-    if (!PrevCopy || !CurrentCopy)
-      return false;
-    return PrevCopy->Source->getReg() == CurrentCopy->Destination->getReg();
+    return FoldablePrevCopy->Source->getReg() ==
+           FoldableCurrentCopy->Destination->getReg();
   };
 
   for (MachineInstr &MI : llvm::make_early_inc_range(MBB)) {
@@ -1424,7 +1417,8 @@ void MachineCopyPropagation::EliminateSpillageCopies(MachineBasicBlock &MBB) {
       for (const MachineOperand &MO : MI.operands()) {
         if (MO.isRegMask()) {
           BitVector &PreservedRegUnits = Tracker.getPreservedRegUnits(MO, *TRI);
-          Tracker.clobberNonPreservedRegs(PreservedRegUnits, *TRI, *TII, UseCopyInstr);
+          Tracker.clobberNonPreservedRegs(PreservedRegUnits, *TRI, *TII,
+                                          UseCopyInstr);
         }
         if (!MO.isReg())
           continue;

>From d6d1bc2ac92fc76566298483d40209da48cb13da Mon Sep 17 00:00:00 2001
From: Jack Styles <jack.styles at arm.com>
Date: Fri, 17 Apr 2026 10:22:51 +0100
Subject: [PATCH 3/4] fix another missed addition from rebase

---
 llvm/lib/CodeGen/MachineCopyPropagation.cpp | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/CodeGen/MachineCopyPropagation.cpp b/llvm/lib/CodeGen/MachineCopyPropagation.cpp
index abcd6ecbd3389..a5bd820ef99af 100644
--- a/llvm/lib/CodeGen/MachineCopyPropagation.cpp
+++ b/llvm/lib/CodeGen/MachineCopyPropagation.cpp
@@ -1323,11 +1323,9 @@ void MachineCopyPropagation::eliminateSpillageCopies(MachineBasicBlock &MBB) {
           if (CopySourceInvalid.count(Reload))
             return;
 
-        auto CheckCopyConstraint = [this](Register Def, Register Src) {
-          for (const TargetRegisterClass *RC : TRI->regclasses()) {
-            if (RC->contains(Def) && RC->contains(Src))
+        auto CheckCopyConstraint = [this](Register Dst, Register Src) {
+          if (TRI->getCommonMinimalPhysRegClass(Dst, Src))
               return true;
-          }
           return false;
         };
 

>From cda80af4cbfb077af985ef06ae3405c7a56967ab Mon Sep 17 00:00:00 2001
From: Jack Styles <jack.styles at arm.com>
Date: Fri, 17 Apr 2026 10:26:45 +0100
Subject: [PATCH 4/4] format

---
 llvm/lib/CodeGen/MachineCopyPropagation.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/CodeGen/MachineCopyPropagation.cpp b/llvm/lib/CodeGen/MachineCopyPropagation.cpp
index a5bd820ef99af..50ae2d87f5d04 100644
--- a/llvm/lib/CodeGen/MachineCopyPropagation.cpp
+++ b/llvm/lib/CodeGen/MachineCopyPropagation.cpp
@@ -1325,7 +1325,7 @@ void MachineCopyPropagation::eliminateSpillageCopies(MachineBasicBlock &MBB) {
 
         auto CheckCopyConstraint = [this](Register Dst, Register Src) {
           if (TRI->getCommonMinimalPhysRegClass(Dst, Src))
-              return true;
+            return true;
           return false;
         };
 



More information about the llvm-commits mailing list