aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/CodeGen/MachineCopyPropagation.cpp
diff options
context:
space:
mode:
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);
}