aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/CodeGen/MachineCopyPropagation.cpp
diff options
context:
space:
mode:
authorVladimir Radosavljevic <129192835+vladimirradosavljevic@users.noreply.github.com>2024-10-23 13:37:02 +0200
committerGitHub <noreply@github.com>2024-10-23 13:37:02 +0200
commit401d123a1fdcbbf4ae7a20178957b7e3a625c044 (patch)
tree177bd4601d5e21a4264cb5884946f252606174f0 /llvm/lib/CodeGen/MachineCopyPropagation.cpp
parentc4c60c0db98dc9139d540963470c5dbdd6d45b9f (diff)
downloadllvm-401d123a1fdcbbf4ae7a20178957b7e3a625c044.zip
llvm-401d123a1fdcbbf4ae7a20178957b7e3a625c044.tar.gz
llvm-401d123a1fdcbbf4ae7a20178957b7e3a625c044.tar.bz2
[MCP] Optimize copies when src is used during backward propagation (#111130)
Before this patch, redundant COPY couldn't be removed for the following case: ``` $R0 = OP ... ... // Read of %R0 $R1 = COPY killed $R0 ``` This patch adds support for tracking the users of the source register during backward propagation, so that we can remove the redundant COPY in the above case and optimize it to: ``` $R1 = OP ... ... // Replace all uses of %R0 with $R1 ```
Diffstat (limited to 'llvm/lib/CodeGen/MachineCopyPropagation.cpp')
-rw-r--r--llvm/lib/CodeGen/MachineCopyPropagation.cpp79
1 files changed, 77 insertions, 2 deletions
diff --git a/llvm/lib/CodeGen/MachineCopyPropagation.cpp b/llvm/lib/CodeGen/MachineCopyPropagation.cpp
index fb4da2c..49ce4b6 100644
--- a/llvm/lib/CodeGen/MachineCopyPropagation.cpp
+++ b/llvm/lib/CodeGen/MachineCopyPropagation.cpp
@@ -110,6 +110,7 @@ class CopyTracker {
struct CopyInfo {
MachineInstr *MI = nullptr;
MachineInstr *LastSeenUseInCopy = nullptr;
+ SmallPtrSet<MachineInstr *, 4> SrcUsers;
SmallVector<MCRegister, 4> DefRegs;
bool Avail = false;
};
@@ -224,6 +225,43 @@ public:
}
}
+ /// Track copy's src users, and return false if that can't be done.
+ /// We can only track if we have a COPY instruction which source is
+ /// the same as the Reg.
+ bool trackSrcUsers(MCRegister Reg, MachineInstr &MI,
+ const TargetRegisterInfo &TRI, const TargetInstrInfo &TII,
+ bool UseCopyInstr) {
+ MCRegUnit RU = *TRI.regunits(Reg).begin();
+ MachineInstr *AvailCopy = findCopyDefViaUnit(RU, TRI);
+ if (!AvailCopy)
+ return false;
+
+ std::optional<DestSourcePair> CopyOperands =
+ isCopyInstr(*AvailCopy, TII, UseCopyInstr);
+ Register Src = CopyOperands->Source->getReg();
+
+ // Bail out, if the source of the copy is not the same as the Reg.
+ if (Src != Reg)
+ return false;
+
+ auto I = Copies.find(RU);
+ if (I == Copies.end())
+ return false;
+
+ I->second.SrcUsers.insert(&MI);
+ return true;
+ }
+
+ /// Return the users for a given register.
+ SmallPtrSet<MachineInstr *, 4> getSrcUsers(MCRegister Reg,
+ const TargetRegisterInfo &TRI) {
+ MCRegUnit RU = *TRI.regunits(Reg).begin();
+ auto I = Copies.find(RU);
+ if (I == Copies.end())
+ return {};
+ return I->second.SrcUsers;
+ }
+
/// Add this copy's registers into the tracker's copy maps.
void trackCopy(MachineInstr *MI, const TargetRegisterInfo &TRI,
const TargetInstrInfo &TII, bool UseCopyInstr) {
@@ -236,7 +274,7 @@ public:
// Remember Def is defined by the copy.
for (MCRegUnit Unit : TRI.regunits(Def))
- Copies[Unit] = {MI, nullptr, {}, true};
+ Copies[Unit] = {MI, nullptr, {}, {}, true};
// Remember source that's copied to Def. Once it's clobbered, then
// it's no longer available for copy propagation.
@@ -427,6 +465,8 @@ private:
bool hasImplicitOverlap(const MachineInstr &MI, const MachineOperand &Use);
bool hasOverlappingMultipleDef(const MachineInstr &MI,
const MachineOperand &MODef, Register Def);
+ bool canUpdateSrcUsers(const MachineInstr &Copy,
+ const MachineOperand &CopySrc);
/// Candidates for deletion.
SmallSetVector<MachineInstr *, 8> MaybeDeadCopies;
@@ -667,6 +707,27 @@ bool MachineCopyPropagation::hasOverlappingMultipleDef(
return false;
}
+/// Return true if it is safe to update all users of the \p CopySrc register
+/// in the given \p Copy instruction.
+bool MachineCopyPropagation::canUpdateSrcUsers(const MachineInstr &Copy,
+ const MachineOperand &CopySrc) {
+ assert(CopySrc.isReg() && "Expected a register operand");
+ for (auto *SrcUser : Tracker.getSrcUsers(CopySrc.getReg(), *TRI)) {
+ if (hasImplicitOverlap(*SrcUser, CopySrc))
+ return false;
+
+ for (MachineOperand &MO : SrcUser->uses()) {
+ if (!MO.isReg() || !MO.isUse() || MO.getReg() != CopySrc.getReg())
+ continue;
+ if (MO.isTied() || !MO.isRenamable() ||
+ !isBackwardPropagatableRegClassCopy(Copy, *SrcUser,
+ MO.getOperandNo()))
+ return false;
+ }
+ }
+ return true;
+}
+
/// Look for available copies whose destination register is used by \p MI and
/// replace the use in \p MI with the copy's source register.
void MachineCopyPropagation::forwardUses(MachineInstr &MI) {
@@ -1033,6 +1094,9 @@ void MachineCopyPropagation::propagateDefs(MachineInstr &MI) {
if (hasOverlappingMultipleDef(MI, MODef, Def))
continue;
+ if (!canUpdateSrcUsers(*Copy, *CopyOperands->Source))
+ continue;
+
LLVM_DEBUG(dbgs() << "MCP: Replacing " << printReg(MODef.getReg(), TRI)
<< "\n with " << printReg(Def, TRI) << "\n in "
<< MI << " from " << *Copy);
@@ -1040,6 +1104,15 @@ void MachineCopyPropagation::propagateDefs(MachineInstr &MI) {
MODef.setReg(Def);
MODef.setIsRenamable(CopyOperands->Destination->isRenamable());
+ for (auto *SrcUser : Tracker.getSrcUsers(Src, *TRI)) {
+ for (MachineOperand &MO : SrcUser->uses()) {
+ if (!MO.isReg() || !MO.isUse() || MO.getReg() != Src)
+ continue;
+ MO.setReg(Def);
+ MO.setIsRenamable(CopyOperands->Destination->isRenamable());
+ }
+ }
+
LLVM_DEBUG(dbgs() << "MCP: After replacement: " << MI << "\n");
MaybeDeadCopies.insert(Copy);
Changed = true;
@@ -1105,7 +1178,9 @@ void MachineCopyPropagation::BackwardCopyPropagateBlock(
CopyDbgUsers[Copy].insert(&MI);
}
}
- } else {
+ } else if (!Tracker.trackSrcUsers(MO.getReg().asMCReg(), MI, *TRI, *TII,
+ UseCopyInstr)) {
+ // If we can't track the source users, invalidate the register.
Tracker.invalidateRegister(MO.getReg().asMCReg(), *TRI, *TII,
UseCopyInstr);
}