[llvm] [MachineCopyPropagation][NFC] Refactor EliminateSpillageCopies (PR #192609)
Jack Styles via llvm-commits
llvm-commits at lists.llvm.org
Fri Apr 17 06:45:30 PDT 2026
https://github.com/Stylie777 updated https://github.com/llvm/llvm-project/pull/192609
>From 066a7d06408b024fc8ebe1987d053415d43aecea 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/5] [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 b03b61255499dd391a84d150e0aca49f3c961ee2 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/5] 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 6e6de88e7c25caf6b465f0d777360d2c674ffc5b 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/5] 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 f5a8f63ed6efba8b6681a35cdae74045f19e6134 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/5] 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;
};
>From 5311c0b125b872ef21176761c2aec90e8bbb4733 Mon Sep 17 00:00:00 2001
From: Jack Styles <jack.styles at arm.com>
Date: Fri, 17 Apr 2026 14:42:28 +0100
Subject: [PATCH 5/5] Rework processing of non-copy RegMasks to fix test
failure
---
llvm/lib/CodeGen/MachineCopyPropagation.cpp | 19 +++++++++++++++++--
1 file changed, 17 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/CodeGen/MachineCopyPropagation.cpp b/llvm/lib/CodeGen/MachineCopyPropagation.cpp
index 50ae2d87f5d04..0f1ff77f0ad8b 100644
--- a/llvm/lib/CodeGen/MachineCopyPropagation.cpp
+++ b/llvm/lib/CodeGen/MachineCopyPropagation.cpp
@@ -431,8 +431,23 @@ class CopyTracker {
for (auto &[Unit, _] : Copies)
if (!PreservedRegUnits.test(static_cast<unsigned>(Unit)))
UnitsToClobber.push_back(Unit);
- for (MCRegUnit Unit : UnitsToClobber)
- clobberRegUnit(Unit, TRI, TII, UseCopyInstr);
+
+ for (MCRegUnit Unit : UnitsToClobber) {
+ // If we clobber the RegUnit, it will mark all the DefReg Units
+ // as unavailable, which leads to issues if the Destination Reg Unit is
+ // preserved, and used later. As such, only mark them as unavailable if
+ // they are not preserved.
+ auto RegUnitInfo = Copies.find(Unit);
+ if (RegUnitInfo == Copies.end())
+ continue;
+
+ for (MCRegister DstReg : RegUnitInfo->second.DefRegs)
+ for (MCRegUnit DstUnit : TRI.regunits(DstReg))
+ if (!PreservedRegUnits.test(static_cast<unsigned>(DstUnit)))
+ if (auto CI = Copies.find(DstUnit); CI != Copies.end())
+ CI->second.Avail = false;
+ Copies.erase(RegUnitInfo);
+ }
}
// Find last COPY that uses Reg.
More information about the llvm-commits
mailing list