diff options
Diffstat (limited to 'llvm/lib/CodeGen/MachineCopyPropagation.cpp')
-rw-r--r-- | llvm/lib/CodeGen/MachineCopyPropagation.cpp | 79 |
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); } |