xref: /openbsd-src/gnu/llvm/llvm/lib/CodeGen/MachineCopyPropagation.cpp (revision d415bd752c734aee168c4ee86ff32e8cc249eb16)
109467b48Spatrick //===- MachineCopyPropagation.cpp - Machine Copy Propagation Pass ---------===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick //
909467b48Spatrick // This is an extremely simple MachineInstr-level copy propagation pass.
1009467b48Spatrick //
1109467b48Spatrick // This pass forwards the source of COPYs to the users of their destinations
1209467b48Spatrick // when doing so is legal.  For example:
1309467b48Spatrick //
1409467b48Spatrick //   %reg1 = COPY %reg0
1509467b48Spatrick //   ...
1609467b48Spatrick //   ... = OP %reg1
1709467b48Spatrick //
1809467b48Spatrick // If
1909467b48Spatrick //   - %reg0 has not been clobbered by the time of the use of %reg1
2009467b48Spatrick //   - the register class constraints are satisfied
2109467b48Spatrick //   - the COPY def is the only value that reaches OP
2209467b48Spatrick // then this pass replaces the above with:
2309467b48Spatrick //
2409467b48Spatrick //   %reg1 = COPY %reg0
2509467b48Spatrick //   ...
2609467b48Spatrick //   ... = OP %reg0
2709467b48Spatrick //
2809467b48Spatrick // This pass also removes some redundant COPYs.  For example:
2909467b48Spatrick //
3009467b48Spatrick //    %R1 = COPY %R0
3109467b48Spatrick //    ... // No clobber of %R1
3209467b48Spatrick //    %R0 = COPY %R1 <<< Removed
3309467b48Spatrick //
3409467b48Spatrick // or
3509467b48Spatrick //
3609467b48Spatrick //    %R1 = COPY %R0
3709467b48Spatrick //    ... // No clobber of %R0
3809467b48Spatrick //    %R1 = COPY %R0 <<< Removed
3909467b48Spatrick //
4009467b48Spatrick // or
4109467b48Spatrick //
4209467b48Spatrick //    $R0 = OP ...
4309467b48Spatrick //    ... // No read/clobber of $R0 and $R1
4409467b48Spatrick //    $R1 = COPY $R0 // $R0 is killed
4509467b48Spatrick // Replace $R0 with $R1 and remove the COPY
4609467b48Spatrick //    $R1 = OP ...
4709467b48Spatrick //    ...
4809467b48Spatrick //
4909467b48Spatrick //===----------------------------------------------------------------------===//
5009467b48Spatrick 
5109467b48Spatrick #include "llvm/ADT/DenseMap.h"
5209467b48Spatrick #include "llvm/ADT/STLExtras.h"
5309467b48Spatrick #include "llvm/ADT/SetVector.h"
54097a140dSpatrick #include "llvm/ADT/SmallSet.h"
5509467b48Spatrick #include "llvm/ADT/SmallVector.h"
5609467b48Spatrick #include "llvm/ADT/Statistic.h"
5709467b48Spatrick #include "llvm/ADT/iterator_range.h"
5809467b48Spatrick #include "llvm/CodeGen/MachineBasicBlock.h"
5909467b48Spatrick #include "llvm/CodeGen/MachineFunction.h"
6009467b48Spatrick #include "llvm/CodeGen/MachineFunctionPass.h"
6109467b48Spatrick #include "llvm/CodeGen/MachineInstr.h"
6209467b48Spatrick #include "llvm/CodeGen/MachineOperand.h"
6309467b48Spatrick #include "llvm/CodeGen/MachineRegisterInfo.h"
6409467b48Spatrick #include "llvm/CodeGen/TargetInstrInfo.h"
6509467b48Spatrick #include "llvm/CodeGen/TargetRegisterInfo.h"
6609467b48Spatrick #include "llvm/CodeGen/TargetSubtargetInfo.h"
6709467b48Spatrick #include "llvm/InitializePasses.h"
6809467b48Spatrick #include "llvm/MC/MCRegisterInfo.h"
6909467b48Spatrick #include "llvm/Pass.h"
7009467b48Spatrick #include "llvm/Support/Debug.h"
7109467b48Spatrick #include "llvm/Support/DebugCounter.h"
7209467b48Spatrick #include "llvm/Support/raw_ostream.h"
7309467b48Spatrick #include <cassert>
7409467b48Spatrick #include <iterator>
7509467b48Spatrick 
7609467b48Spatrick using namespace llvm;
7709467b48Spatrick 
7809467b48Spatrick #define DEBUG_TYPE "machine-cp"
7909467b48Spatrick 
8009467b48Spatrick STATISTIC(NumDeletes, "Number of dead copies deleted");
8109467b48Spatrick STATISTIC(NumCopyForwards, "Number of copy uses forwarded");
8209467b48Spatrick STATISTIC(NumCopyBackwardPropagated, "Number of copy defs backward propagated");
8309467b48Spatrick DEBUG_COUNTER(FwdCounter, "machine-cp-fwd",
8409467b48Spatrick               "Controls which register COPYs are forwarded");
8509467b48Spatrick 
86*d415bd75Srobert static cl::opt<bool> MCPUseCopyInstr("mcp-use-is-copy-instr", cl::init(false),
87*d415bd75Srobert                                      cl::Hidden);
88*d415bd75Srobert 
8909467b48Spatrick namespace {
9009467b48Spatrick 
isCopyInstr(const MachineInstr & MI,const TargetInstrInfo & TII,bool UseCopyInstr)91*d415bd75Srobert static std::optional<DestSourcePair> isCopyInstr(const MachineInstr &MI,
92*d415bd75Srobert                                                  const TargetInstrInfo &TII,
93*d415bd75Srobert                                                  bool UseCopyInstr) {
94*d415bd75Srobert   if (UseCopyInstr)
95*d415bd75Srobert     return TII.isCopyInstr(MI);
96*d415bd75Srobert 
97*d415bd75Srobert   if (MI.isCopy())
98*d415bd75Srobert     return std::optional<DestSourcePair>(
99*d415bd75Srobert         DestSourcePair{MI.getOperand(0), MI.getOperand(1)});
100*d415bd75Srobert 
101*d415bd75Srobert   return std::nullopt;
102*d415bd75Srobert }
103*d415bd75Srobert 
10409467b48Spatrick class CopyTracker {
10509467b48Spatrick   struct CopyInfo {
10609467b48Spatrick     MachineInstr *MI;
10773471bf0Spatrick     SmallVector<MCRegister, 4> DefRegs;
10809467b48Spatrick     bool Avail;
10909467b48Spatrick   };
11009467b48Spatrick 
11173471bf0Spatrick   DenseMap<MCRegister, CopyInfo> Copies;
11209467b48Spatrick 
11309467b48Spatrick public:
11409467b48Spatrick   /// Mark all of the given registers and their subregisters as unavailable for
11509467b48Spatrick   /// copying.
markRegsUnavailable(ArrayRef<MCRegister> Regs,const TargetRegisterInfo & TRI)11673471bf0Spatrick   void markRegsUnavailable(ArrayRef<MCRegister> Regs,
11709467b48Spatrick                            const TargetRegisterInfo &TRI) {
11873471bf0Spatrick     for (MCRegister Reg : Regs) {
11909467b48Spatrick       // Source of copy is no longer available for propagation.
12009467b48Spatrick       for (MCRegUnitIterator RUI(Reg, &TRI); RUI.isValid(); ++RUI) {
12109467b48Spatrick         auto CI = Copies.find(*RUI);
12209467b48Spatrick         if (CI != Copies.end())
12309467b48Spatrick           CI->second.Avail = false;
12409467b48Spatrick       }
12509467b48Spatrick     }
12609467b48Spatrick   }
12709467b48Spatrick 
12809467b48Spatrick   /// Remove register from copy maps.
invalidateRegister(MCRegister Reg,const TargetRegisterInfo & TRI,const TargetInstrInfo & TII,bool UseCopyInstr)129*d415bd75Srobert   void invalidateRegister(MCRegister Reg, const TargetRegisterInfo &TRI,
130*d415bd75Srobert                           const TargetInstrInfo &TII, bool UseCopyInstr) {
13109467b48Spatrick     // Since Reg might be a subreg of some registers, only invalidate Reg is not
13209467b48Spatrick     // enough. We have to find the COPY defines Reg or registers defined by Reg
13309467b48Spatrick     // and invalidate all of them.
13473471bf0Spatrick     SmallSet<MCRegister, 8> RegsToInvalidate;
135097a140dSpatrick     RegsToInvalidate.insert(Reg);
13609467b48Spatrick     for (MCRegUnitIterator RUI(Reg, &TRI); RUI.isValid(); ++RUI) {
13709467b48Spatrick       auto I = Copies.find(*RUI);
13809467b48Spatrick       if (I != Copies.end()) {
13909467b48Spatrick         if (MachineInstr *MI = I->second.MI) {
140*d415bd75Srobert           std::optional<DestSourcePair> CopyOperands =
141*d415bd75Srobert               isCopyInstr(*MI, TII, UseCopyInstr);
142*d415bd75Srobert           assert(CopyOperands && "Expect copy");
143*d415bd75Srobert 
144*d415bd75Srobert           RegsToInvalidate.insert(
145*d415bd75Srobert               CopyOperands->Destination->getReg().asMCReg());
146*d415bd75Srobert           RegsToInvalidate.insert(CopyOperands->Source->getReg().asMCReg());
14709467b48Spatrick         }
14809467b48Spatrick         RegsToInvalidate.insert(I->second.DefRegs.begin(),
14909467b48Spatrick                                 I->second.DefRegs.end());
15009467b48Spatrick       }
15109467b48Spatrick     }
15273471bf0Spatrick     for (MCRegister InvalidReg : RegsToInvalidate)
15309467b48Spatrick       for (MCRegUnitIterator RUI(InvalidReg, &TRI); RUI.isValid(); ++RUI)
15409467b48Spatrick         Copies.erase(*RUI);
15509467b48Spatrick   }
15609467b48Spatrick 
15709467b48Spatrick   /// Clobber a single register, removing it from the tracker's copy maps.
clobberRegister(MCRegister Reg,const TargetRegisterInfo & TRI,const TargetInstrInfo & TII,bool UseCopyInstr)158*d415bd75Srobert   void clobberRegister(MCRegister Reg, const TargetRegisterInfo &TRI,
159*d415bd75Srobert                        const TargetInstrInfo &TII, bool UseCopyInstr) {
16009467b48Spatrick     for (MCRegUnitIterator RUI(Reg, &TRI); RUI.isValid(); ++RUI) {
16109467b48Spatrick       auto I = Copies.find(*RUI);
16209467b48Spatrick       if (I != Copies.end()) {
16309467b48Spatrick         // When we clobber the source of a copy, we need to clobber everything
16409467b48Spatrick         // it defined.
16509467b48Spatrick         markRegsUnavailable(I->second.DefRegs, TRI);
16609467b48Spatrick         // When we clobber the destination of a copy, we need to clobber the
16709467b48Spatrick         // whole register it defined.
168*d415bd75Srobert         if (MachineInstr *MI = I->second.MI) {
169*d415bd75Srobert           std::optional<DestSourcePair> CopyOperands =
170*d415bd75Srobert               isCopyInstr(*MI, TII, UseCopyInstr);
171*d415bd75Srobert           markRegsUnavailable({CopyOperands->Destination->getReg().asMCReg()},
172*d415bd75Srobert                               TRI);
173*d415bd75Srobert         }
17409467b48Spatrick         // Now we can erase the copy.
17509467b48Spatrick         Copies.erase(I);
17609467b48Spatrick       }
17709467b48Spatrick     }
17809467b48Spatrick   }
17909467b48Spatrick 
18009467b48Spatrick   /// Add this copy's registers into the tracker's copy maps.
trackCopy(MachineInstr * MI,const TargetRegisterInfo & TRI,const TargetInstrInfo & TII,bool UseCopyInstr)181*d415bd75Srobert   void trackCopy(MachineInstr *MI, const TargetRegisterInfo &TRI,
182*d415bd75Srobert                  const TargetInstrInfo &TII, bool UseCopyInstr) {
183*d415bd75Srobert     std::optional<DestSourcePair> CopyOperands =
184*d415bd75Srobert         isCopyInstr(*MI, TII, UseCopyInstr);
185*d415bd75Srobert     assert(CopyOperands && "Tracking non-copy?");
18609467b48Spatrick 
187*d415bd75Srobert     MCRegister Src = CopyOperands->Source->getReg().asMCReg();
188*d415bd75Srobert     MCRegister Def = CopyOperands->Destination->getReg().asMCReg();
18909467b48Spatrick 
19009467b48Spatrick     // Remember Def is defined by the copy.
19109467b48Spatrick     for (MCRegUnitIterator RUI(Def, &TRI); RUI.isValid(); ++RUI)
19209467b48Spatrick       Copies[*RUI] = {MI, {}, true};
19309467b48Spatrick 
19409467b48Spatrick     // Remember source that's copied to Def. Once it's clobbered, then
19509467b48Spatrick     // it's no longer available for copy propagation.
19609467b48Spatrick     for (MCRegUnitIterator RUI(Src, &TRI); RUI.isValid(); ++RUI) {
19709467b48Spatrick       auto I = Copies.insert({*RUI, {nullptr, {}, false}});
19809467b48Spatrick       auto &Copy = I.first->second;
19909467b48Spatrick       if (!is_contained(Copy.DefRegs, Def))
20009467b48Spatrick         Copy.DefRegs.push_back(Def);
20109467b48Spatrick     }
20209467b48Spatrick   }
20309467b48Spatrick 
hasAnyCopies()20409467b48Spatrick   bool hasAnyCopies() {
20509467b48Spatrick     return !Copies.empty();
20609467b48Spatrick   }
20709467b48Spatrick 
findCopyForUnit(MCRegister RegUnit,const TargetRegisterInfo & TRI,bool MustBeAvailable=false)20873471bf0Spatrick   MachineInstr *findCopyForUnit(MCRegister RegUnit,
20973471bf0Spatrick                                 const TargetRegisterInfo &TRI,
21009467b48Spatrick                                 bool MustBeAvailable = false) {
21109467b48Spatrick     auto CI = Copies.find(RegUnit);
21209467b48Spatrick     if (CI == Copies.end())
21309467b48Spatrick       return nullptr;
21409467b48Spatrick     if (MustBeAvailable && !CI->second.Avail)
21509467b48Spatrick       return nullptr;
21609467b48Spatrick     return CI->second.MI;
21709467b48Spatrick   }
21809467b48Spatrick 
findCopyDefViaUnit(MCRegister RegUnit,const TargetRegisterInfo & TRI)21973471bf0Spatrick   MachineInstr *findCopyDefViaUnit(MCRegister RegUnit,
22009467b48Spatrick                                    const TargetRegisterInfo &TRI) {
22109467b48Spatrick     auto CI = Copies.find(RegUnit);
22209467b48Spatrick     if (CI == Copies.end())
22309467b48Spatrick       return nullptr;
22409467b48Spatrick     if (CI->second.DefRegs.size() != 1)
22509467b48Spatrick       return nullptr;
22609467b48Spatrick     MCRegUnitIterator RUI(CI->second.DefRegs[0], &TRI);
22709467b48Spatrick     return findCopyForUnit(*RUI, TRI, true);
22809467b48Spatrick   }
22909467b48Spatrick 
findAvailBackwardCopy(MachineInstr & I,MCRegister Reg,const TargetRegisterInfo & TRI,const TargetInstrInfo & TII,bool UseCopyInstr)23073471bf0Spatrick   MachineInstr *findAvailBackwardCopy(MachineInstr &I, MCRegister Reg,
231*d415bd75Srobert                                       const TargetRegisterInfo &TRI,
232*d415bd75Srobert                                       const TargetInstrInfo &TII,
233*d415bd75Srobert                                       bool UseCopyInstr) {
23409467b48Spatrick     MCRegUnitIterator RUI(Reg, &TRI);
23509467b48Spatrick     MachineInstr *AvailCopy = findCopyDefViaUnit(*RUI, TRI);
236*d415bd75Srobert 
237*d415bd75Srobert     if (!AvailCopy)
23809467b48Spatrick       return nullptr;
23909467b48Spatrick 
240*d415bd75Srobert     std::optional<DestSourcePair> CopyOperands =
241*d415bd75Srobert         isCopyInstr(*AvailCopy, TII, UseCopyInstr);
242*d415bd75Srobert     Register AvailSrc = CopyOperands->Source->getReg();
243*d415bd75Srobert     Register AvailDef = CopyOperands->Destination->getReg();
244*d415bd75Srobert     if (!TRI.isSubRegisterEq(AvailSrc, Reg))
245*d415bd75Srobert       return nullptr;
246*d415bd75Srobert 
24709467b48Spatrick     for (const MachineInstr &MI :
24809467b48Spatrick          make_range(AvailCopy->getReverseIterator(), I.getReverseIterator()))
24909467b48Spatrick       for (const MachineOperand &MO : MI.operands())
25009467b48Spatrick         if (MO.isRegMask())
25109467b48Spatrick           // FIXME: Shall we simultaneously invalidate AvailSrc or AvailDef?
25209467b48Spatrick           if (MO.clobbersPhysReg(AvailSrc) || MO.clobbersPhysReg(AvailDef))
25309467b48Spatrick             return nullptr;
25409467b48Spatrick 
25509467b48Spatrick     return AvailCopy;
25609467b48Spatrick   }
25709467b48Spatrick 
findAvailCopy(MachineInstr & DestCopy,MCRegister Reg,const TargetRegisterInfo & TRI,const TargetInstrInfo & TII,bool UseCopyInstr)25873471bf0Spatrick   MachineInstr *findAvailCopy(MachineInstr &DestCopy, MCRegister Reg,
259*d415bd75Srobert                               const TargetRegisterInfo &TRI,
260*d415bd75Srobert                               const TargetInstrInfo &TII, bool UseCopyInstr) {
26109467b48Spatrick     // We check the first RegUnit here, since we'll only be interested in the
26209467b48Spatrick     // copy if it copies the entire register anyway.
26309467b48Spatrick     MCRegUnitIterator RUI(Reg, &TRI);
26409467b48Spatrick     MachineInstr *AvailCopy =
26509467b48Spatrick         findCopyForUnit(*RUI, TRI, /*MustBeAvailable=*/true);
266*d415bd75Srobert 
267*d415bd75Srobert     if (!AvailCopy)
268*d415bd75Srobert       return nullptr;
269*d415bd75Srobert 
270*d415bd75Srobert     std::optional<DestSourcePair> CopyOperands =
271*d415bd75Srobert         isCopyInstr(*AvailCopy, TII, UseCopyInstr);
272*d415bd75Srobert     Register AvailSrc = CopyOperands->Source->getReg();
273*d415bd75Srobert     Register AvailDef = CopyOperands->Destination->getReg();
274*d415bd75Srobert     if (!TRI.isSubRegisterEq(AvailDef, Reg))
27509467b48Spatrick       return nullptr;
27609467b48Spatrick 
27709467b48Spatrick     // Check that the available copy isn't clobbered by any regmasks between
27809467b48Spatrick     // itself and the destination.
27909467b48Spatrick     for (const MachineInstr &MI :
28009467b48Spatrick          make_range(AvailCopy->getIterator(), DestCopy.getIterator()))
28109467b48Spatrick       for (const MachineOperand &MO : MI.operands())
28209467b48Spatrick         if (MO.isRegMask())
28309467b48Spatrick           if (MO.clobbersPhysReg(AvailSrc) || MO.clobbersPhysReg(AvailDef))
28409467b48Spatrick             return nullptr;
28509467b48Spatrick 
28609467b48Spatrick     return AvailCopy;
28709467b48Spatrick   }
28809467b48Spatrick 
clear()28909467b48Spatrick   void clear() {
29009467b48Spatrick     Copies.clear();
29109467b48Spatrick   }
29209467b48Spatrick };
29309467b48Spatrick 
29409467b48Spatrick class MachineCopyPropagation : public MachineFunctionPass {
29509467b48Spatrick   const TargetRegisterInfo *TRI;
29609467b48Spatrick   const TargetInstrInfo *TII;
29709467b48Spatrick   const MachineRegisterInfo *MRI;
29809467b48Spatrick 
299*d415bd75Srobert   // Return true if this is a copy instruction and false otherwise.
300*d415bd75Srobert   bool UseCopyInstr;
301*d415bd75Srobert 
30209467b48Spatrick public:
30309467b48Spatrick   static char ID; // Pass identification, replacement for typeid
30409467b48Spatrick 
MachineCopyPropagation(bool CopyInstr=false)305*d415bd75Srobert   MachineCopyPropagation(bool CopyInstr = false)
306*d415bd75Srobert       : MachineFunctionPass(ID), UseCopyInstr(CopyInstr || MCPUseCopyInstr) {
30709467b48Spatrick     initializeMachineCopyPropagationPass(*PassRegistry::getPassRegistry());
30809467b48Spatrick   }
30909467b48Spatrick 
getAnalysisUsage(AnalysisUsage & AU) const31009467b48Spatrick   void getAnalysisUsage(AnalysisUsage &AU) const override {
31109467b48Spatrick     AU.setPreservesCFG();
31209467b48Spatrick     MachineFunctionPass::getAnalysisUsage(AU);
31309467b48Spatrick   }
31409467b48Spatrick 
31509467b48Spatrick   bool runOnMachineFunction(MachineFunction &MF) override;
31609467b48Spatrick 
getRequiredProperties() const31709467b48Spatrick   MachineFunctionProperties getRequiredProperties() const override {
31809467b48Spatrick     return MachineFunctionProperties().set(
31909467b48Spatrick         MachineFunctionProperties::Property::NoVRegs);
32009467b48Spatrick   }
32109467b48Spatrick 
32209467b48Spatrick private:
32309467b48Spatrick   typedef enum { DebugUse = false, RegularUse = true } DebugType;
32409467b48Spatrick 
32573471bf0Spatrick   void ReadRegister(MCRegister Reg, MachineInstr &Reader, DebugType DT);
32609467b48Spatrick   void ForwardCopyPropagateBlock(MachineBasicBlock &MBB);
32709467b48Spatrick   void BackwardCopyPropagateBlock(MachineBasicBlock &MBB);
32873471bf0Spatrick   bool eraseIfRedundant(MachineInstr &Copy, MCRegister Src, MCRegister Def);
32909467b48Spatrick   void forwardUses(MachineInstr &MI);
33009467b48Spatrick   void propagateDefs(MachineInstr &MI);
33109467b48Spatrick   bool isForwardableRegClassCopy(const MachineInstr &Copy,
33209467b48Spatrick                                  const MachineInstr &UseI, unsigned UseIdx);
33309467b48Spatrick   bool isBackwardPropagatableRegClassCopy(const MachineInstr &Copy,
33409467b48Spatrick                                           const MachineInstr &UseI,
33509467b48Spatrick                                           unsigned UseIdx);
33609467b48Spatrick   bool hasImplicitOverlap(const MachineInstr &MI, const MachineOperand &Use);
33773471bf0Spatrick   bool hasOverlappingMultipleDef(const MachineInstr &MI,
33873471bf0Spatrick                                  const MachineOperand &MODef, Register Def);
33909467b48Spatrick 
34009467b48Spatrick   /// Candidates for deletion.
34109467b48Spatrick   SmallSetVector<MachineInstr *, 8> MaybeDeadCopies;
34209467b48Spatrick 
34309467b48Spatrick   /// Multimap tracking debug users in current BB
34473471bf0Spatrick   DenseMap<MachineInstr *, SmallSet<MachineInstr *, 2>> CopyDbgUsers;
34509467b48Spatrick 
34609467b48Spatrick   CopyTracker Tracker;
34709467b48Spatrick 
34809467b48Spatrick   bool Changed;
34909467b48Spatrick };
35009467b48Spatrick 
35109467b48Spatrick } // end anonymous namespace
35209467b48Spatrick 
35309467b48Spatrick char MachineCopyPropagation::ID = 0;
35409467b48Spatrick 
35509467b48Spatrick char &llvm::MachineCopyPropagationID = MachineCopyPropagation::ID;
35609467b48Spatrick 
35709467b48Spatrick INITIALIZE_PASS(MachineCopyPropagation, DEBUG_TYPE,
35809467b48Spatrick                 "Machine Copy Propagation Pass", false, false)
35909467b48Spatrick 
ReadRegister(MCRegister Reg,MachineInstr & Reader,DebugType DT)36073471bf0Spatrick void MachineCopyPropagation::ReadRegister(MCRegister Reg, MachineInstr &Reader,
36109467b48Spatrick                                           DebugType DT) {
36209467b48Spatrick   // If 'Reg' is defined by a copy, the copy is no longer a candidate
36309467b48Spatrick   // for elimination. If a copy is "read" by a debug user, record the user
36409467b48Spatrick   // for propagation.
36509467b48Spatrick   for (MCRegUnitIterator RUI(Reg, TRI); RUI.isValid(); ++RUI) {
36609467b48Spatrick     if (MachineInstr *Copy = Tracker.findCopyForUnit(*RUI, *TRI)) {
36709467b48Spatrick       if (DT == RegularUse) {
36809467b48Spatrick         LLVM_DEBUG(dbgs() << "MCP: Copy is used - not dead: "; Copy->dump());
36909467b48Spatrick         MaybeDeadCopies.remove(Copy);
37009467b48Spatrick       } else {
37173471bf0Spatrick         CopyDbgUsers[Copy].insert(&Reader);
37209467b48Spatrick       }
37309467b48Spatrick     }
37409467b48Spatrick   }
37509467b48Spatrick }
37609467b48Spatrick 
37709467b48Spatrick /// Return true if \p PreviousCopy did copy register \p Src to register \p Def.
37809467b48Spatrick /// This fact may have been obscured by sub register usage or may not be true at
37909467b48Spatrick /// all even though Src and Def are subregisters of the registers used in
38009467b48Spatrick /// PreviousCopy. e.g.
38109467b48Spatrick /// isNopCopy("ecx = COPY eax", AX, CX) == true
38209467b48Spatrick /// isNopCopy("ecx = COPY eax", AH, CL) == false
isNopCopy(const MachineInstr & PreviousCopy,MCRegister Src,MCRegister Def,const TargetRegisterInfo * TRI,const TargetInstrInfo * TII,bool UseCopyInstr)38373471bf0Spatrick static bool isNopCopy(const MachineInstr &PreviousCopy, MCRegister Src,
384*d415bd75Srobert                       MCRegister Def, const TargetRegisterInfo *TRI,
385*d415bd75Srobert                       const TargetInstrInfo *TII, bool UseCopyInstr) {
386*d415bd75Srobert 
387*d415bd75Srobert   std::optional<DestSourcePair> CopyOperands =
388*d415bd75Srobert       isCopyInstr(PreviousCopy, *TII, UseCopyInstr);
389*d415bd75Srobert   MCRegister PreviousSrc = CopyOperands->Source->getReg().asMCReg();
390*d415bd75Srobert   MCRegister PreviousDef = CopyOperands->Destination->getReg().asMCReg();
391097a140dSpatrick   if (Src == PreviousSrc && Def == PreviousDef)
39209467b48Spatrick     return true;
39309467b48Spatrick   if (!TRI->isSubRegister(PreviousSrc, Src))
39409467b48Spatrick     return false;
39509467b48Spatrick   unsigned SubIdx = TRI->getSubRegIndex(PreviousSrc, Src);
39609467b48Spatrick   return SubIdx == TRI->getSubRegIndex(PreviousDef, Def);
39709467b48Spatrick }
39809467b48Spatrick 
39909467b48Spatrick /// Remove instruction \p Copy if there exists a previous copy that copies the
40009467b48Spatrick /// register \p Src to the register \p Def; This may happen indirectly by
40109467b48Spatrick /// copying the super registers.
eraseIfRedundant(MachineInstr & Copy,MCRegister Src,MCRegister Def)40273471bf0Spatrick bool MachineCopyPropagation::eraseIfRedundant(MachineInstr &Copy,
40373471bf0Spatrick                                               MCRegister Src, MCRegister Def) {
40409467b48Spatrick   // Avoid eliminating a copy from/to a reserved registers as we cannot predict
40509467b48Spatrick   // the value (Example: The sparc zero register is writable but stays zero).
40609467b48Spatrick   if (MRI->isReserved(Src) || MRI->isReserved(Def))
40709467b48Spatrick     return false;
40809467b48Spatrick 
40909467b48Spatrick   // Search for an existing copy.
410*d415bd75Srobert   MachineInstr *PrevCopy =
411*d415bd75Srobert       Tracker.findAvailCopy(Copy, Def, *TRI, *TII, UseCopyInstr);
41209467b48Spatrick   if (!PrevCopy)
41309467b48Spatrick     return false;
41409467b48Spatrick 
415*d415bd75Srobert   auto PrevCopyOperands = isCopyInstr(*PrevCopy, *TII, UseCopyInstr);
41609467b48Spatrick   // Check that the existing copy uses the correct sub registers.
417*d415bd75Srobert   if (PrevCopyOperands->Destination->isDead())
41809467b48Spatrick     return false;
419*d415bd75Srobert   if (!isNopCopy(*PrevCopy, Src, Def, TRI, TII, UseCopyInstr))
42009467b48Spatrick     return false;
42109467b48Spatrick 
42209467b48Spatrick   LLVM_DEBUG(dbgs() << "MCP: copy is a NOP, removing: "; Copy.dump());
42309467b48Spatrick 
42409467b48Spatrick   // Copy was redundantly redefining either Src or Def. Remove earlier kill
42509467b48Spatrick   // flags between Copy and PrevCopy because the value will be reused now.
426*d415bd75Srobert   std::optional<DestSourcePair> CopyOperands =
427*d415bd75Srobert       isCopyInstr(Copy, *TII, UseCopyInstr);
428*d415bd75Srobert   assert(CopyOperands);
429*d415bd75Srobert 
430*d415bd75Srobert   Register CopyDef = CopyOperands->Destination->getReg();
43109467b48Spatrick   assert(CopyDef == Src || CopyDef == Def);
43209467b48Spatrick   for (MachineInstr &MI :
43309467b48Spatrick        make_range(PrevCopy->getIterator(), Copy.getIterator()))
43409467b48Spatrick     MI.clearRegisterKills(CopyDef, TRI);
43509467b48Spatrick 
43609467b48Spatrick   Copy.eraseFromParent();
43709467b48Spatrick   Changed = true;
43809467b48Spatrick   ++NumDeletes;
43909467b48Spatrick   return true;
44009467b48Spatrick }
44109467b48Spatrick 
isBackwardPropagatableRegClassCopy(const MachineInstr & Copy,const MachineInstr & UseI,unsigned UseIdx)44209467b48Spatrick bool MachineCopyPropagation::isBackwardPropagatableRegClassCopy(
44309467b48Spatrick     const MachineInstr &Copy, const MachineInstr &UseI, unsigned UseIdx) {
444*d415bd75Srobert   std::optional<DestSourcePair> CopyOperands =
445*d415bd75Srobert       isCopyInstr(Copy, *TII, UseCopyInstr);
446*d415bd75Srobert   Register Def = CopyOperands->Destination->getReg();
44709467b48Spatrick 
44809467b48Spatrick   if (const TargetRegisterClass *URC =
44909467b48Spatrick           UseI.getRegClassConstraint(UseIdx, TII, TRI))
45009467b48Spatrick     return URC->contains(Def);
45109467b48Spatrick 
45209467b48Spatrick   // We don't process further if UseI is a COPY, since forward copy propagation
45309467b48Spatrick   // should handle that.
45409467b48Spatrick   return false;
45509467b48Spatrick }
45609467b48Spatrick 
45709467b48Spatrick /// Decide whether we should forward the source of \param Copy to its use in
45809467b48Spatrick /// \param UseI based on the physical register class constraints of the opcode
45909467b48Spatrick /// and avoiding introducing more cross-class COPYs.
isForwardableRegClassCopy(const MachineInstr & Copy,const MachineInstr & UseI,unsigned UseIdx)46009467b48Spatrick bool MachineCopyPropagation::isForwardableRegClassCopy(const MachineInstr &Copy,
46109467b48Spatrick                                                        const MachineInstr &UseI,
46209467b48Spatrick                                                        unsigned UseIdx) {
463*d415bd75Srobert   std::optional<DestSourcePair> CopyOperands =
464*d415bd75Srobert       isCopyInstr(Copy, *TII, UseCopyInstr);
465*d415bd75Srobert   Register CopySrcReg = CopyOperands->Source->getReg();
46609467b48Spatrick 
46709467b48Spatrick   // If the new register meets the opcode register constraints, then allow
46809467b48Spatrick   // forwarding.
46909467b48Spatrick   if (const TargetRegisterClass *URC =
47009467b48Spatrick           UseI.getRegClassConstraint(UseIdx, TII, TRI))
47109467b48Spatrick     return URC->contains(CopySrcReg);
47209467b48Spatrick 
473*d415bd75Srobert   auto UseICopyOperands = isCopyInstr(UseI, *TII, UseCopyInstr);
474*d415bd75Srobert   if (!UseICopyOperands)
47509467b48Spatrick     return false;
47609467b48Spatrick 
47709467b48Spatrick   /// COPYs don't have register class constraints, so if the user instruction
47809467b48Spatrick   /// is a COPY, we just try to avoid introducing additional cross-class
47909467b48Spatrick   /// COPYs.  For example:
48009467b48Spatrick   ///
48109467b48Spatrick   ///   RegClassA = COPY RegClassB  // Copy parameter
48209467b48Spatrick   ///   ...
48309467b48Spatrick   ///   RegClassB = COPY RegClassA  // UseI parameter
48409467b48Spatrick   ///
48509467b48Spatrick   /// which after forwarding becomes
48609467b48Spatrick   ///
48709467b48Spatrick   ///   RegClassA = COPY RegClassB
48809467b48Spatrick   ///   ...
48909467b48Spatrick   ///   RegClassB = COPY RegClassB
49009467b48Spatrick   ///
49109467b48Spatrick   /// so we have reduced the number of cross-class COPYs and potentially
49209467b48Spatrick   /// introduced a nop COPY that can be removed.
49309467b48Spatrick 
494*d415bd75Srobert   // Allow forwarding if src and dst belong to any common class, so long as they
495*d415bd75Srobert   // don't belong to any (possibly smaller) common class that requires copies to
496*d415bd75Srobert   // go via a different class.
497*d415bd75Srobert   Register UseDstReg = UseICopyOperands->Destination->getReg();
498*d415bd75Srobert   bool Found = false;
499*d415bd75Srobert   bool IsCrossClass = false;
500*d415bd75Srobert   for (const TargetRegisterClass *RC : TRI->regclasses()) {
501*d415bd75Srobert     if (RC->contains(CopySrcReg) && RC->contains(UseDstReg)) {
502*d415bd75Srobert       Found = true;
503*d415bd75Srobert       if (TRI->getCrossCopyRegClass(RC) != RC) {
504*d415bd75Srobert         IsCrossClass = true;
505*d415bd75Srobert         break;
506*d415bd75Srobert       }
507*d415bd75Srobert     }
508*d415bd75Srobert   }
509*d415bd75Srobert   if (!Found)
510*d415bd75Srobert     return false;
511*d415bd75Srobert   if (!IsCrossClass)
51209467b48Spatrick     return true;
513*d415bd75Srobert   // The forwarded copy would be cross-class. Only do this if the original copy
514*d415bd75Srobert   // was also cross-class.
515*d415bd75Srobert   Register CopyDstReg = CopyOperands->Destination->getReg();
516*d415bd75Srobert   for (const TargetRegisterClass *RC : TRI->regclasses()) {
517*d415bd75Srobert     if (RC->contains(CopySrcReg) && RC->contains(CopyDstReg) &&
518*d415bd75Srobert         TRI->getCrossCopyRegClass(RC) != RC)
519*d415bd75Srobert       return true;
520*d415bd75Srobert   }
52109467b48Spatrick   return false;
52209467b48Spatrick }
52309467b48Spatrick 
52409467b48Spatrick /// Check that \p MI does not have implicit uses that overlap with it's \p Use
52509467b48Spatrick /// operand (the register being replaced), since these can sometimes be
52609467b48Spatrick /// implicitly tied to other operands.  For example, on AMDGPU:
52709467b48Spatrick ///
52809467b48Spatrick /// V_MOVRELS_B32_e32 %VGPR2, %M0<imp-use>, %EXEC<imp-use>, %VGPR2_VGPR3_VGPR4_VGPR5<imp-use>
52909467b48Spatrick ///
53009467b48Spatrick /// the %VGPR2 is implicitly tied to the larger reg operand, but we have no
53109467b48Spatrick /// way of knowing we need to update the latter when updating the former.
hasImplicitOverlap(const MachineInstr & MI,const MachineOperand & Use)53209467b48Spatrick bool MachineCopyPropagation::hasImplicitOverlap(const MachineInstr &MI,
53309467b48Spatrick                                                 const MachineOperand &Use) {
53409467b48Spatrick   for (const MachineOperand &MIUse : MI.uses())
53509467b48Spatrick     if (&MIUse != &Use && MIUse.isReg() && MIUse.isImplicit() &&
53609467b48Spatrick         MIUse.isUse() && TRI->regsOverlap(Use.getReg(), MIUse.getReg()))
53709467b48Spatrick       return true;
53809467b48Spatrick 
53909467b48Spatrick   return false;
54009467b48Spatrick }
54109467b48Spatrick 
54273471bf0Spatrick /// For an MI that has multiple definitions, check whether \p MI has
54373471bf0Spatrick /// a definition that overlaps with another of its definitions.
54473471bf0Spatrick /// For example, on ARM: umull   r9, r9, lr, r0
54573471bf0Spatrick /// The umull instruction is unpredictable unless RdHi and RdLo are different.
hasOverlappingMultipleDef(const MachineInstr & MI,const MachineOperand & MODef,Register Def)54673471bf0Spatrick bool MachineCopyPropagation::hasOverlappingMultipleDef(
54773471bf0Spatrick     const MachineInstr &MI, const MachineOperand &MODef, Register Def) {
54873471bf0Spatrick   for (const MachineOperand &MIDef : MI.defs()) {
54973471bf0Spatrick     if ((&MIDef != &MODef) && MIDef.isReg() &&
55073471bf0Spatrick         TRI->regsOverlap(Def, MIDef.getReg()))
55173471bf0Spatrick       return true;
55273471bf0Spatrick   }
55373471bf0Spatrick 
55473471bf0Spatrick   return false;
55573471bf0Spatrick }
55673471bf0Spatrick 
55709467b48Spatrick /// Look for available copies whose destination register is used by \p MI and
55809467b48Spatrick /// replace the use in \p MI with the copy's source register.
forwardUses(MachineInstr & MI)55909467b48Spatrick void MachineCopyPropagation::forwardUses(MachineInstr &MI) {
56009467b48Spatrick   if (!Tracker.hasAnyCopies())
56109467b48Spatrick     return;
56209467b48Spatrick 
56309467b48Spatrick   // Look for non-tied explicit vreg uses that have an active COPY
56409467b48Spatrick   // instruction that defines the physical register allocated to them.
56509467b48Spatrick   // Replace the vreg with the source of the active COPY.
56609467b48Spatrick   for (unsigned OpIdx = 0, OpEnd = MI.getNumOperands(); OpIdx < OpEnd;
56709467b48Spatrick        ++OpIdx) {
56809467b48Spatrick     MachineOperand &MOUse = MI.getOperand(OpIdx);
56909467b48Spatrick     // Don't forward into undef use operands since doing so can cause problems
57009467b48Spatrick     // with the machine verifier, since it doesn't treat undef reads as reads,
57109467b48Spatrick     // so we can end up with a live range that ends on an undef read, leading to
57209467b48Spatrick     // an error that the live range doesn't end on a read of the live range
57309467b48Spatrick     // register.
57409467b48Spatrick     if (!MOUse.isReg() || MOUse.isTied() || MOUse.isUndef() || MOUse.isDef() ||
57509467b48Spatrick         MOUse.isImplicit())
57609467b48Spatrick       continue;
57709467b48Spatrick 
57809467b48Spatrick     if (!MOUse.getReg())
57909467b48Spatrick       continue;
58009467b48Spatrick 
58109467b48Spatrick     // Check that the register is marked 'renamable' so we know it is safe to
58209467b48Spatrick     // rename it without violating any constraints that aren't expressed in the
58309467b48Spatrick     // IR (e.g. ABI or opcode requirements).
58409467b48Spatrick     if (!MOUse.isRenamable())
58509467b48Spatrick       continue;
58609467b48Spatrick 
587*d415bd75Srobert     MachineInstr *Copy = Tracker.findAvailCopy(MI, MOUse.getReg().asMCReg(),
588*d415bd75Srobert                                                *TRI, *TII, UseCopyInstr);
58909467b48Spatrick     if (!Copy)
59009467b48Spatrick       continue;
59109467b48Spatrick 
592*d415bd75Srobert     std::optional<DestSourcePair> CopyOperands =
593*d415bd75Srobert         isCopyInstr(*Copy, *TII, UseCopyInstr);
594*d415bd75Srobert     Register CopyDstReg = CopyOperands->Destination->getReg();
595*d415bd75Srobert     const MachineOperand &CopySrc = *CopyOperands->Source;
59609467b48Spatrick     Register CopySrcReg = CopySrc.getReg();
59709467b48Spatrick 
59809467b48Spatrick     // FIXME: Don't handle partial uses of wider COPYs yet.
59909467b48Spatrick     if (MOUse.getReg() != CopyDstReg) {
60009467b48Spatrick       LLVM_DEBUG(
60109467b48Spatrick           dbgs() << "MCP: FIXME! Not forwarding COPY to sub-register use:\n  "
60209467b48Spatrick                  << MI);
60309467b48Spatrick       continue;
60409467b48Spatrick     }
60509467b48Spatrick 
60609467b48Spatrick     // Don't forward COPYs of reserved regs unless they are constant.
60709467b48Spatrick     if (MRI->isReserved(CopySrcReg) && !MRI->isConstantPhysReg(CopySrcReg))
60809467b48Spatrick       continue;
60909467b48Spatrick 
61009467b48Spatrick     if (!isForwardableRegClassCopy(*Copy, MI, OpIdx))
61109467b48Spatrick       continue;
61209467b48Spatrick 
61309467b48Spatrick     if (hasImplicitOverlap(MI, MOUse))
61409467b48Spatrick       continue;
61509467b48Spatrick 
61609467b48Spatrick     // Check that the instruction is not a copy that partially overwrites the
61709467b48Spatrick     // original copy source that we are about to use. The tracker mechanism
61809467b48Spatrick     // cannot cope with that.
619*d415bd75Srobert     if (isCopyInstr(MI, *TII, UseCopyInstr) &&
620*d415bd75Srobert         MI.modifiesRegister(CopySrcReg, TRI) &&
62109467b48Spatrick         !MI.definesRegister(CopySrcReg)) {
62209467b48Spatrick       LLVM_DEBUG(dbgs() << "MCP: Copy source overlap with dest in " << MI);
62309467b48Spatrick       continue;
62409467b48Spatrick     }
62509467b48Spatrick 
62609467b48Spatrick     if (!DebugCounter::shouldExecute(FwdCounter)) {
62709467b48Spatrick       LLVM_DEBUG(dbgs() << "MCP: Skipping forwarding due to debug counter:\n  "
62809467b48Spatrick                         << MI);
62909467b48Spatrick       continue;
63009467b48Spatrick     }
63109467b48Spatrick 
63209467b48Spatrick     LLVM_DEBUG(dbgs() << "MCP: Replacing " << printReg(MOUse.getReg(), TRI)
63309467b48Spatrick                       << "\n     with " << printReg(CopySrcReg, TRI)
63409467b48Spatrick                       << "\n     in " << MI << "     from " << *Copy);
63509467b48Spatrick 
63609467b48Spatrick     MOUse.setReg(CopySrcReg);
63709467b48Spatrick     if (!CopySrc.isRenamable())
63809467b48Spatrick       MOUse.setIsRenamable(false);
639*d415bd75Srobert     MOUse.setIsUndef(CopySrc.isUndef());
64009467b48Spatrick 
64109467b48Spatrick     LLVM_DEBUG(dbgs() << "MCP: After replacement: " << MI << "\n");
64209467b48Spatrick 
64309467b48Spatrick     // Clear kill markers that may have been invalidated.
64409467b48Spatrick     for (MachineInstr &KMI :
64509467b48Spatrick          make_range(Copy->getIterator(), std::next(MI.getIterator())))
64609467b48Spatrick       KMI.clearRegisterKills(CopySrcReg, TRI);
64709467b48Spatrick 
64809467b48Spatrick     ++NumCopyForwards;
64909467b48Spatrick     Changed = true;
65009467b48Spatrick   }
65109467b48Spatrick }
65209467b48Spatrick 
ForwardCopyPropagateBlock(MachineBasicBlock & MBB)65309467b48Spatrick void MachineCopyPropagation::ForwardCopyPropagateBlock(MachineBasicBlock &MBB) {
65409467b48Spatrick   LLVM_DEBUG(dbgs() << "MCP: ForwardCopyPropagateBlock " << MBB.getName()
65509467b48Spatrick                     << "\n");
65609467b48Spatrick 
657*d415bd75Srobert   for (MachineInstr &MI : llvm::make_early_inc_range(MBB)) {
65809467b48Spatrick     // Analyze copies (which don't overlap themselves).
659*d415bd75Srobert     std::optional<DestSourcePair> CopyOperands =
660*d415bd75Srobert         isCopyInstr(MI, *TII, UseCopyInstr);
661*d415bd75Srobert     if (CopyOperands) {
662*d415bd75Srobert 
663*d415bd75Srobert       Register RegSrc = CopyOperands->Source->getReg();
664*d415bd75Srobert       Register RegDef = CopyOperands->Destination->getReg();
665*d415bd75Srobert 
666*d415bd75Srobert       if (!TRI->regsOverlap(RegDef, RegSrc)) {
667*d415bd75Srobert         assert(RegDef.isPhysical() && RegSrc.isPhysical() &&
66809467b48Spatrick               "MachineCopyPropagation should be run after register allocation!");
66909467b48Spatrick 
670*d415bd75Srobert         MCRegister Def = RegDef.asMCReg();
671*d415bd75Srobert         MCRegister Src = RegSrc.asMCReg();
67273471bf0Spatrick 
67309467b48Spatrick         // The two copies cancel out and the source of the first copy
67409467b48Spatrick         // hasn't been overridden, eliminate the second one. e.g.
67509467b48Spatrick         //  %ecx = COPY %eax
67609467b48Spatrick         //  ... nothing clobbered eax.
67709467b48Spatrick         //  %eax = COPY %ecx
67809467b48Spatrick         // =>
67909467b48Spatrick         //  %ecx = COPY %eax
68009467b48Spatrick         //
68109467b48Spatrick         // or
68209467b48Spatrick         //
68309467b48Spatrick         //  %ecx = COPY %eax
68409467b48Spatrick         //  ... nothing clobbered eax.
68509467b48Spatrick         //  %ecx = COPY %eax
68609467b48Spatrick         // =>
68709467b48Spatrick         //  %ecx = COPY %eax
688*d415bd75Srobert         if (eraseIfRedundant(MI, Def, Src) || eraseIfRedundant(MI, Src, Def))
68909467b48Spatrick           continue;
69009467b48Spatrick 
691*d415bd75Srobert         forwardUses(MI);
69209467b48Spatrick 
69309467b48Spatrick         // Src may have been changed by forwardUses()
694*d415bd75Srobert         CopyOperands = isCopyInstr(MI, *TII, UseCopyInstr);
695*d415bd75Srobert         Src = CopyOperands->Source->getReg().asMCReg();
69609467b48Spatrick 
69709467b48Spatrick         // If Src is defined by a previous copy, the previous copy cannot be
69809467b48Spatrick         // eliminated.
699*d415bd75Srobert         ReadRegister(Src, MI, RegularUse);
700*d415bd75Srobert         for (const MachineOperand &MO : MI.implicit_operands()) {
70109467b48Spatrick           if (!MO.isReg() || !MO.readsReg())
70209467b48Spatrick             continue;
70373471bf0Spatrick           MCRegister Reg = MO.getReg().asMCReg();
70409467b48Spatrick           if (!Reg)
70509467b48Spatrick             continue;
706*d415bd75Srobert           ReadRegister(Reg, MI, RegularUse);
70709467b48Spatrick         }
70809467b48Spatrick 
709*d415bd75Srobert         LLVM_DEBUG(dbgs() << "MCP: Copy is a deletion candidate: "; MI.dump());
71009467b48Spatrick 
71109467b48Spatrick         // Copy is now a candidate for deletion.
71209467b48Spatrick         if (!MRI->isReserved(Def))
713*d415bd75Srobert           MaybeDeadCopies.insert(&MI);
71409467b48Spatrick 
71509467b48Spatrick         // If 'Def' is previously source of another copy, then this earlier copy's
71609467b48Spatrick         // source is no longer available. e.g.
71709467b48Spatrick         // %xmm9 = copy %xmm2
71809467b48Spatrick         // ...
71909467b48Spatrick         // %xmm2 = copy %xmm0
72009467b48Spatrick         // ...
72109467b48Spatrick         // %xmm2 = copy %xmm9
722*d415bd75Srobert         Tracker.clobberRegister(Def, *TRI, *TII, UseCopyInstr);
723*d415bd75Srobert         for (const MachineOperand &MO : MI.implicit_operands()) {
72409467b48Spatrick           if (!MO.isReg() || !MO.isDef())
72509467b48Spatrick             continue;
72673471bf0Spatrick           MCRegister Reg = MO.getReg().asMCReg();
72709467b48Spatrick           if (!Reg)
72809467b48Spatrick             continue;
729*d415bd75Srobert           Tracker.clobberRegister(Reg, *TRI, *TII, UseCopyInstr);
73009467b48Spatrick         }
73109467b48Spatrick 
732*d415bd75Srobert         Tracker.trackCopy(&MI, *TRI, *TII, UseCopyInstr);
73309467b48Spatrick 
73409467b48Spatrick         continue;
73509467b48Spatrick       }
736*d415bd75Srobert     }
73709467b48Spatrick 
73809467b48Spatrick     // Clobber any earlyclobber regs first.
739*d415bd75Srobert     for (const MachineOperand &MO : MI.operands())
74009467b48Spatrick       if (MO.isReg() && MO.isEarlyClobber()) {
74173471bf0Spatrick         MCRegister Reg = MO.getReg().asMCReg();
74209467b48Spatrick         // If we have a tied earlyclobber, that means it is also read by this
74309467b48Spatrick         // instruction, so we need to make sure we don't remove it as dead
74409467b48Spatrick         // later.
74509467b48Spatrick         if (MO.isTied())
746*d415bd75Srobert           ReadRegister(Reg, MI, RegularUse);
747*d415bd75Srobert         Tracker.clobberRegister(Reg, *TRI, *TII, UseCopyInstr);
74809467b48Spatrick       }
74909467b48Spatrick 
750*d415bd75Srobert     forwardUses(MI);
75109467b48Spatrick 
75209467b48Spatrick     // Not a copy.
75373471bf0Spatrick     SmallVector<Register, 2> Defs;
75409467b48Spatrick     const MachineOperand *RegMask = nullptr;
755*d415bd75Srobert     for (const MachineOperand &MO : MI.operands()) {
75609467b48Spatrick       if (MO.isRegMask())
75709467b48Spatrick         RegMask = &MO;
75809467b48Spatrick       if (!MO.isReg())
75909467b48Spatrick         continue;
76009467b48Spatrick       Register Reg = MO.getReg();
76109467b48Spatrick       if (!Reg)
76209467b48Spatrick         continue;
76309467b48Spatrick 
76473471bf0Spatrick       assert(!Reg.isVirtual() &&
76509467b48Spatrick              "MachineCopyPropagation should be run after register allocation!");
76609467b48Spatrick 
76709467b48Spatrick       if (MO.isDef() && !MO.isEarlyClobber()) {
76873471bf0Spatrick         Defs.push_back(Reg.asMCReg());
76909467b48Spatrick         continue;
77009467b48Spatrick       } else if (MO.readsReg())
771*d415bd75Srobert         ReadRegister(Reg.asMCReg(), MI, MO.isDebug() ? DebugUse : RegularUse);
77209467b48Spatrick     }
77309467b48Spatrick 
77409467b48Spatrick     // The instruction has a register mask operand which means that it clobbers
77509467b48Spatrick     // a large set of registers.  Treat clobbered registers the same way as
77609467b48Spatrick     // defined registers.
77709467b48Spatrick     if (RegMask) {
77809467b48Spatrick       // Erase any MaybeDeadCopies whose destination register is clobbered.
77909467b48Spatrick       for (SmallSetVector<MachineInstr *, 8>::iterator DI =
78009467b48Spatrick                MaybeDeadCopies.begin();
78109467b48Spatrick            DI != MaybeDeadCopies.end();) {
78209467b48Spatrick         MachineInstr *MaybeDead = *DI;
783*d415bd75Srobert         std::optional<DestSourcePair> CopyOperands =
784*d415bd75Srobert             isCopyInstr(*MaybeDead, *TII, UseCopyInstr);
785*d415bd75Srobert         MCRegister Reg = CopyOperands->Destination->getReg().asMCReg();
78609467b48Spatrick         assert(!MRI->isReserved(Reg));
78709467b48Spatrick 
78809467b48Spatrick         if (!RegMask->clobbersPhysReg(Reg)) {
78909467b48Spatrick           ++DI;
79009467b48Spatrick           continue;
79109467b48Spatrick         }
79209467b48Spatrick 
79309467b48Spatrick         LLVM_DEBUG(dbgs() << "MCP: Removing copy due to regmask clobbering: ";
79409467b48Spatrick                    MaybeDead->dump());
79509467b48Spatrick 
79609467b48Spatrick         // Make sure we invalidate any entries in the copy maps before erasing
79709467b48Spatrick         // the instruction.
798*d415bd75Srobert         Tracker.clobberRegister(Reg, *TRI, *TII, UseCopyInstr);
79909467b48Spatrick 
80009467b48Spatrick         // erase() will return the next valid iterator pointing to the next
80109467b48Spatrick         // element after the erased one.
80209467b48Spatrick         DI = MaybeDeadCopies.erase(DI);
80309467b48Spatrick         MaybeDead->eraseFromParent();
80409467b48Spatrick         Changed = true;
80509467b48Spatrick         ++NumDeletes;
80609467b48Spatrick       }
80709467b48Spatrick     }
80809467b48Spatrick 
80909467b48Spatrick     // Any previous copy definition or reading the Defs is no longer available.
81073471bf0Spatrick     for (MCRegister Reg : Defs)
811*d415bd75Srobert       Tracker.clobberRegister(Reg, *TRI, *TII, UseCopyInstr);
81209467b48Spatrick   }
81309467b48Spatrick 
81409467b48Spatrick   // If MBB doesn't have successors, delete the copies whose defs are not used.
81509467b48Spatrick   // If MBB does have successors, then conservative assume the defs are live-out
81609467b48Spatrick   // since we don't want to trust live-in lists.
81709467b48Spatrick   if (MBB.succ_empty()) {
81809467b48Spatrick     for (MachineInstr *MaybeDead : MaybeDeadCopies) {
81909467b48Spatrick       LLVM_DEBUG(dbgs() << "MCP: Removing copy due to no live-out succ: ";
82009467b48Spatrick                  MaybeDead->dump());
821*d415bd75Srobert 
822*d415bd75Srobert       std::optional<DestSourcePair> CopyOperands =
823*d415bd75Srobert           isCopyInstr(*MaybeDead, *TII, UseCopyInstr);
824*d415bd75Srobert       assert(CopyOperands);
825*d415bd75Srobert 
826*d415bd75Srobert       Register SrcReg = CopyOperands->Source->getReg();
827*d415bd75Srobert       Register DestReg = CopyOperands->Destination->getReg();
828*d415bd75Srobert       assert(!MRI->isReserved(DestReg));
82909467b48Spatrick 
83009467b48Spatrick       // Update matching debug values, if any.
83173471bf0Spatrick       SmallVector<MachineInstr *> MaybeDeadDbgUsers(
83273471bf0Spatrick           CopyDbgUsers[MaybeDead].begin(), CopyDbgUsers[MaybeDead].end());
83373471bf0Spatrick       MRI->updateDbgUsersToReg(DestReg.asMCReg(), SrcReg.asMCReg(),
83473471bf0Spatrick                                MaybeDeadDbgUsers);
83509467b48Spatrick 
83609467b48Spatrick       MaybeDead->eraseFromParent();
83709467b48Spatrick       Changed = true;
83809467b48Spatrick       ++NumDeletes;
83909467b48Spatrick     }
84009467b48Spatrick   }
84109467b48Spatrick 
84209467b48Spatrick   MaybeDeadCopies.clear();
84309467b48Spatrick   CopyDbgUsers.clear();
84409467b48Spatrick   Tracker.clear();
84509467b48Spatrick }
84609467b48Spatrick 
isBackwardPropagatableCopy(MachineInstr & MI,const MachineRegisterInfo & MRI,const TargetInstrInfo & TII,bool UseCopyInstr)84709467b48Spatrick static bool isBackwardPropagatableCopy(MachineInstr &MI,
848*d415bd75Srobert                                        const MachineRegisterInfo &MRI,
849*d415bd75Srobert                                        const TargetInstrInfo &TII,
850*d415bd75Srobert                                        bool UseCopyInstr) {
851*d415bd75Srobert   std::optional<DestSourcePair> CopyOperands =
852*d415bd75Srobert       isCopyInstr(MI, TII, UseCopyInstr);
853*d415bd75Srobert   assert(CopyOperands && "MI is expected to be a COPY");
854*d415bd75Srobert 
855*d415bd75Srobert   Register Def = CopyOperands->Destination->getReg();
856*d415bd75Srobert   Register Src = CopyOperands->Source->getReg();
85709467b48Spatrick 
85809467b48Spatrick   if (!Def || !Src)
85909467b48Spatrick     return false;
86009467b48Spatrick 
86109467b48Spatrick   if (MRI.isReserved(Def) || MRI.isReserved(Src))
86209467b48Spatrick     return false;
86309467b48Spatrick 
864*d415bd75Srobert   return CopyOperands->Source->isRenamable() && CopyOperands->Source->isKill();
86509467b48Spatrick }
86609467b48Spatrick 
propagateDefs(MachineInstr & MI)86709467b48Spatrick void MachineCopyPropagation::propagateDefs(MachineInstr &MI) {
86809467b48Spatrick   if (!Tracker.hasAnyCopies())
86909467b48Spatrick     return;
87009467b48Spatrick 
87109467b48Spatrick   for (unsigned OpIdx = 0, OpEnd = MI.getNumOperands(); OpIdx != OpEnd;
87209467b48Spatrick        ++OpIdx) {
87309467b48Spatrick     MachineOperand &MODef = MI.getOperand(OpIdx);
87409467b48Spatrick 
87509467b48Spatrick     if (!MODef.isReg() || MODef.isUse())
87609467b48Spatrick       continue;
87709467b48Spatrick 
87809467b48Spatrick     // Ignore non-trivial cases.
87909467b48Spatrick     if (MODef.isTied() || MODef.isUndef() || MODef.isImplicit())
88009467b48Spatrick       continue;
88109467b48Spatrick 
88209467b48Spatrick     if (!MODef.getReg())
88309467b48Spatrick       continue;
88409467b48Spatrick 
88509467b48Spatrick     // We only handle if the register comes from a vreg.
88609467b48Spatrick     if (!MODef.isRenamable())
88709467b48Spatrick       continue;
88809467b48Spatrick 
889*d415bd75Srobert     MachineInstr *Copy = Tracker.findAvailBackwardCopy(
890*d415bd75Srobert         MI, MODef.getReg().asMCReg(), *TRI, *TII, UseCopyInstr);
89109467b48Spatrick     if (!Copy)
89209467b48Spatrick       continue;
89309467b48Spatrick 
894*d415bd75Srobert     std::optional<DestSourcePair> CopyOperands =
895*d415bd75Srobert         isCopyInstr(*Copy, *TII, UseCopyInstr);
896*d415bd75Srobert     Register Def = CopyOperands->Destination->getReg();
897*d415bd75Srobert     Register Src = CopyOperands->Source->getReg();
89809467b48Spatrick 
89909467b48Spatrick     if (MODef.getReg() != Src)
90009467b48Spatrick       continue;
90109467b48Spatrick 
90209467b48Spatrick     if (!isBackwardPropagatableRegClassCopy(*Copy, MI, OpIdx))
90309467b48Spatrick       continue;
90409467b48Spatrick 
90509467b48Spatrick     if (hasImplicitOverlap(MI, MODef))
90609467b48Spatrick       continue;
90709467b48Spatrick 
90873471bf0Spatrick     if (hasOverlappingMultipleDef(MI, MODef, Def))
90973471bf0Spatrick       continue;
91073471bf0Spatrick 
91109467b48Spatrick     LLVM_DEBUG(dbgs() << "MCP: Replacing " << printReg(MODef.getReg(), TRI)
91209467b48Spatrick                       << "\n     with " << printReg(Def, TRI) << "\n     in "
91309467b48Spatrick                       << MI << "     from " << *Copy);
91409467b48Spatrick 
91509467b48Spatrick     MODef.setReg(Def);
916*d415bd75Srobert     MODef.setIsRenamable(CopyOperands->Destination->isRenamable());
91709467b48Spatrick 
91809467b48Spatrick     LLVM_DEBUG(dbgs() << "MCP: After replacement: " << MI << "\n");
91909467b48Spatrick     MaybeDeadCopies.insert(Copy);
92009467b48Spatrick     Changed = true;
92109467b48Spatrick     ++NumCopyBackwardPropagated;
92209467b48Spatrick   }
92309467b48Spatrick }
92409467b48Spatrick 
BackwardCopyPropagateBlock(MachineBasicBlock & MBB)92509467b48Spatrick void MachineCopyPropagation::BackwardCopyPropagateBlock(
92609467b48Spatrick     MachineBasicBlock &MBB) {
92709467b48Spatrick   LLVM_DEBUG(dbgs() << "MCP: BackwardCopyPropagateBlock " << MBB.getName()
92809467b48Spatrick                     << "\n");
92909467b48Spatrick 
930*d415bd75Srobert   for (MachineInstr &MI : llvm::make_early_inc_range(llvm::reverse(MBB))) {
93109467b48Spatrick     // Ignore non-trivial COPYs.
932*d415bd75Srobert     std::optional<DestSourcePair> CopyOperands =
933*d415bd75Srobert         isCopyInstr(MI, *TII, UseCopyInstr);
934*d415bd75Srobert     if (CopyOperands && MI.getNumOperands() == 2) {
935*d415bd75Srobert       Register DefReg = CopyOperands->Destination->getReg();
936*d415bd75Srobert       Register SrcReg = CopyOperands->Source->getReg();
93709467b48Spatrick 
938*d415bd75Srobert       if (!TRI->regsOverlap(DefReg, SrcReg)) {
939*d415bd75Srobert         MCRegister Def = DefReg.asMCReg();
940*d415bd75Srobert         MCRegister Src = SrcReg.asMCReg();
94109467b48Spatrick 
94209467b48Spatrick         // Unlike forward cp, we don't invoke propagateDefs here,
94309467b48Spatrick         // just let forward cp do COPY-to-COPY propagation.
944*d415bd75Srobert         if (isBackwardPropagatableCopy(MI, *MRI, *TII, UseCopyInstr)) {
945*d415bd75Srobert           Tracker.invalidateRegister(Src, *TRI, *TII, UseCopyInstr);
946*d415bd75Srobert           Tracker.invalidateRegister(Def, *TRI, *TII, UseCopyInstr);
947*d415bd75Srobert           Tracker.trackCopy(&MI, *TRI, *TII, UseCopyInstr);
94809467b48Spatrick           continue;
94909467b48Spatrick         }
95009467b48Spatrick       }
951*d415bd75Srobert     }
95209467b48Spatrick 
95309467b48Spatrick     // Invalidate any earlyclobber regs first.
954*d415bd75Srobert     for (const MachineOperand &MO : MI.operands())
95509467b48Spatrick       if (MO.isReg() && MO.isEarlyClobber()) {
95673471bf0Spatrick         MCRegister Reg = MO.getReg().asMCReg();
95709467b48Spatrick         if (!Reg)
95809467b48Spatrick           continue;
959*d415bd75Srobert         Tracker.invalidateRegister(Reg, *TRI, *TII, UseCopyInstr);
96009467b48Spatrick       }
96109467b48Spatrick 
962*d415bd75Srobert     propagateDefs(MI);
963*d415bd75Srobert     for (const MachineOperand &MO : MI.operands()) {
96409467b48Spatrick       if (!MO.isReg())
96509467b48Spatrick         continue;
96609467b48Spatrick 
96709467b48Spatrick       if (!MO.getReg())
96809467b48Spatrick         continue;
96909467b48Spatrick 
97009467b48Spatrick       if (MO.isDef())
971*d415bd75Srobert         Tracker.invalidateRegister(MO.getReg().asMCReg(), *TRI, *TII,
972*d415bd75Srobert                                    UseCopyInstr);
97309467b48Spatrick 
97473471bf0Spatrick       if (MO.readsReg()) {
97573471bf0Spatrick         if (MO.isDebug()) {
97673471bf0Spatrick           //  Check if the register in the debug instruction is utilized
97773471bf0Spatrick           // in a copy instruction, so we can update the debug info if the
97873471bf0Spatrick           // register is changed.
97973471bf0Spatrick           for (MCRegUnitIterator RUI(MO.getReg().asMCReg(), TRI); RUI.isValid();
98073471bf0Spatrick                ++RUI) {
98173471bf0Spatrick             if (auto *Copy = Tracker.findCopyDefViaUnit(*RUI, *TRI)) {
982*d415bd75Srobert               CopyDbgUsers[Copy].insert(&MI);
98373471bf0Spatrick             }
98473471bf0Spatrick           }
98573471bf0Spatrick         } else {
986*d415bd75Srobert           Tracker.invalidateRegister(MO.getReg().asMCReg(), *TRI, *TII,
987*d415bd75Srobert                                      UseCopyInstr);
98873471bf0Spatrick         }
98973471bf0Spatrick       }
99009467b48Spatrick     }
99109467b48Spatrick   }
99209467b48Spatrick 
99309467b48Spatrick   for (auto *Copy : MaybeDeadCopies) {
994*d415bd75Srobert     std::optional<DestSourcePair> CopyOperands =
995*d415bd75Srobert         isCopyInstr(*Copy, *TII, UseCopyInstr);
996*d415bd75Srobert     Register Src = CopyOperands->Source->getReg();
997*d415bd75Srobert     Register Def = CopyOperands->Destination->getReg();
99873471bf0Spatrick     SmallVector<MachineInstr *> MaybeDeadDbgUsers(CopyDbgUsers[Copy].begin(),
99973471bf0Spatrick                                                   CopyDbgUsers[Copy].end());
100073471bf0Spatrick 
100173471bf0Spatrick     MRI->updateDbgUsersToReg(Src.asMCReg(), Def.asMCReg(), MaybeDeadDbgUsers);
100209467b48Spatrick     Copy->eraseFromParent();
100309467b48Spatrick     ++NumDeletes;
100409467b48Spatrick   }
100509467b48Spatrick 
100609467b48Spatrick   MaybeDeadCopies.clear();
100709467b48Spatrick   CopyDbgUsers.clear();
100809467b48Spatrick   Tracker.clear();
100909467b48Spatrick }
101009467b48Spatrick 
runOnMachineFunction(MachineFunction & MF)101109467b48Spatrick bool MachineCopyPropagation::runOnMachineFunction(MachineFunction &MF) {
101209467b48Spatrick   if (skipFunction(MF.getFunction()))
101309467b48Spatrick     return false;
101409467b48Spatrick 
101509467b48Spatrick   Changed = false;
101609467b48Spatrick 
101709467b48Spatrick   TRI = MF.getSubtarget().getRegisterInfo();
101809467b48Spatrick   TII = MF.getSubtarget().getInstrInfo();
101909467b48Spatrick   MRI = &MF.getRegInfo();
102009467b48Spatrick 
102109467b48Spatrick   for (MachineBasicBlock &MBB : MF) {
102209467b48Spatrick     BackwardCopyPropagateBlock(MBB);
102309467b48Spatrick     ForwardCopyPropagateBlock(MBB);
102409467b48Spatrick   }
102509467b48Spatrick 
102609467b48Spatrick   return Changed;
102709467b48Spatrick }
1028*d415bd75Srobert 
1029*d415bd75Srobert MachineFunctionPass *
createMachineCopyPropagationPass(bool UseCopyInstr=false)1030*d415bd75Srobert llvm::createMachineCopyPropagationPass(bool UseCopyInstr = false) {
1031*d415bd75Srobert   return new MachineCopyPropagation(UseCopyInstr);
1032*d415bd75Srobert }
1033