xref: /freebsd/contrib/llvm-project/llvm/lib/CodeGen/MachineCopyPropagation.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
10b57cec5SDimitry Andric //===- MachineCopyPropagation.cpp - Machine Copy Propagation Pass ---------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This is an extremely simple MachineInstr-level copy propagation pass.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric // This pass forwards the source of COPYs to the users of their destinations
120b57cec5SDimitry Andric // when doing so is legal.  For example:
130b57cec5SDimitry Andric //
140b57cec5SDimitry Andric //   %reg1 = COPY %reg0
150b57cec5SDimitry Andric //   ...
160b57cec5SDimitry Andric //   ... = OP %reg1
170b57cec5SDimitry Andric //
180b57cec5SDimitry Andric // If
190b57cec5SDimitry Andric //   - %reg0 has not been clobbered by the time of the use of %reg1
200b57cec5SDimitry Andric //   - the register class constraints are satisfied
210b57cec5SDimitry Andric //   - the COPY def is the only value that reaches OP
220b57cec5SDimitry Andric // then this pass replaces the above with:
230b57cec5SDimitry Andric //
240b57cec5SDimitry Andric //   %reg1 = COPY %reg0
250b57cec5SDimitry Andric //   ...
260b57cec5SDimitry Andric //   ... = OP %reg0
270b57cec5SDimitry Andric //
280b57cec5SDimitry Andric // This pass also removes some redundant COPYs.  For example:
290b57cec5SDimitry Andric //
300b57cec5SDimitry Andric //    %R1 = COPY %R0
310b57cec5SDimitry Andric //    ... // No clobber of %R1
320b57cec5SDimitry Andric //    %R0 = COPY %R1 <<< Removed
330b57cec5SDimitry Andric //
340b57cec5SDimitry Andric // or
350b57cec5SDimitry Andric //
360b57cec5SDimitry Andric //    %R1 = COPY %R0
370b57cec5SDimitry Andric //    ... // No clobber of %R0
380b57cec5SDimitry Andric //    %R1 = COPY %R0 <<< Removed
390b57cec5SDimitry Andric //
40480093f4SDimitry Andric // or
41480093f4SDimitry Andric //
42480093f4SDimitry Andric //    $R0 = OP ...
43480093f4SDimitry Andric //    ... // No read/clobber of $R0 and $R1
44480093f4SDimitry Andric //    $R1 = COPY $R0 // $R0 is killed
45480093f4SDimitry Andric // Replace $R0 with $R1 and remove the COPY
46480093f4SDimitry Andric //    $R1 = OP ...
47480093f4SDimitry Andric //    ...
48480093f4SDimitry Andric //
490b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
500b57cec5SDimitry Andric 
510b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h"
520b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
530b57cec5SDimitry Andric #include "llvm/ADT/SetVector.h"
545ffd83dbSDimitry Andric #include "llvm/ADT/SmallSet.h"
550b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
560b57cec5SDimitry Andric #include "llvm/ADT/Statistic.h"
570b57cec5SDimitry Andric #include "llvm/ADT/iterator_range.h"
580b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h"
590b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
600b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
610b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstr.h"
620b57cec5SDimitry Andric #include "llvm/CodeGen/MachineOperand.h"
630b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
640b57cec5SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h"
650b57cec5SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h"
660b57cec5SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h"
67480093f4SDimitry Andric #include "llvm/InitializePasses.h"
680b57cec5SDimitry Andric #include "llvm/MC/MCRegisterInfo.h"
690b57cec5SDimitry Andric #include "llvm/Pass.h"
700b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
710b57cec5SDimitry Andric #include "llvm/Support/DebugCounter.h"
720b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
730b57cec5SDimitry Andric #include <cassert>
740b57cec5SDimitry Andric #include <iterator>
750b57cec5SDimitry Andric 
760b57cec5SDimitry Andric using namespace llvm;
770b57cec5SDimitry Andric 
780b57cec5SDimitry Andric #define DEBUG_TYPE "machine-cp"
790b57cec5SDimitry Andric 
800b57cec5SDimitry Andric STATISTIC(NumDeletes, "Number of dead copies deleted");
810b57cec5SDimitry Andric STATISTIC(NumCopyForwards, "Number of copy uses forwarded");
82480093f4SDimitry Andric STATISTIC(NumCopyBackwardPropagated, "Number of copy defs backward propagated");
830b57cec5SDimitry Andric DEBUG_COUNTER(FwdCounter, "machine-cp-fwd",
840b57cec5SDimitry Andric               "Controls which register COPYs are forwarded");
850b57cec5SDimitry Andric 
8681ad6265SDimitry Andric static cl::opt<bool> MCPUseCopyInstr("mcp-use-is-copy-instr", cl::init(false),
8781ad6265SDimitry Andric                                      cl::Hidden);
8881ad6265SDimitry Andric 
890b57cec5SDimitry Andric namespace {
900b57cec5SDimitry Andric 
91*bdd1243dSDimitry Andric static std::optional<DestSourcePair> isCopyInstr(const MachineInstr &MI,
9281ad6265SDimitry Andric                                                  const TargetInstrInfo &TII,
9381ad6265SDimitry Andric                                                  bool UseCopyInstr) {
9481ad6265SDimitry Andric   if (UseCopyInstr)
9581ad6265SDimitry Andric     return TII.isCopyInstr(MI);
9681ad6265SDimitry Andric 
9781ad6265SDimitry Andric   if (MI.isCopy())
98*bdd1243dSDimitry Andric     return std::optional<DestSourcePair>(
9981ad6265SDimitry Andric         DestSourcePair{MI.getOperand(0), MI.getOperand(1)});
10081ad6265SDimitry Andric 
101*bdd1243dSDimitry Andric   return std::nullopt;
10281ad6265SDimitry Andric }
10381ad6265SDimitry Andric 
1040b57cec5SDimitry Andric class CopyTracker {
1050b57cec5SDimitry Andric   struct CopyInfo {
1060b57cec5SDimitry Andric     MachineInstr *MI;
107e8d8bef9SDimitry Andric     SmallVector<MCRegister, 4> DefRegs;
1080b57cec5SDimitry Andric     bool Avail;
1090b57cec5SDimitry Andric   };
1100b57cec5SDimitry Andric 
111e8d8bef9SDimitry Andric   DenseMap<MCRegister, CopyInfo> Copies;
1120b57cec5SDimitry Andric 
1130b57cec5SDimitry Andric public:
1140b57cec5SDimitry Andric   /// Mark all of the given registers and their subregisters as unavailable for
1150b57cec5SDimitry Andric   /// copying.
116e8d8bef9SDimitry Andric   void markRegsUnavailable(ArrayRef<MCRegister> Regs,
1170b57cec5SDimitry Andric                            const TargetRegisterInfo &TRI) {
118e8d8bef9SDimitry Andric     for (MCRegister Reg : Regs) {
1190b57cec5SDimitry Andric       // Source of copy is no longer available for propagation.
1200b57cec5SDimitry Andric       for (MCRegUnitIterator RUI(Reg, &TRI); RUI.isValid(); ++RUI) {
1210b57cec5SDimitry Andric         auto CI = Copies.find(*RUI);
1220b57cec5SDimitry Andric         if (CI != Copies.end())
1230b57cec5SDimitry Andric           CI->second.Avail = false;
1240b57cec5SDimitry Andric       }
1250b57cec5SDimitry Andric     }
1260b57cec5SDimitry Andric   }
1270b57cec5SDimitry Andric 
128480093f4SDimitry Andric   /// Remove register from copy maps.
12981ad6265SDimitry Andric   void invalidateRegister(MCRegister Reg, const TargetRegisterInfo &TRI,
13081ad6265SDimitry Andric                           const TargetInstrInfo &TII, bool UseCopyInstr) {
131480093f4SDimitry Andric     // Since Reg might be a subreg of some registers, only invalidate Reg is not
132480093f4SDimitry Andric     // enough. We have to find the COPY defines Reg or registers defined by Reg
133480093f4SDimitry Andric     // and invalidate all of them.
134e8d8bef9SDimitry Andric     SmallSet<MCRegister, 8> RegsToInvalidate;
1355ffd83dbSDimitry Andric     RegsToInvalidate.insert(Reg);
136480093f4SDimitry Andric     for (MCRegUnitIterator RUI(Reg, &TRI); RUI.isValid(); ++RUI) {
137480093f4SDimitry Andric       auto I = Copies.find(*RUI);
138480093f4SDimitry Andric       if (I != Copies.end()) {
139480093f4SDimitry Andric         if (MachineInstr *MI = I->second.MI) {
140*bdd1243dSDimitry Andric           std::optional<DestSourcePair> CopyOperands =
14181ad6265SDimitry Andric               isCopyInstr(*MI, TII, UseCopyInstr);
14281ad6265SDimitry Andric           assert(CopyOperands && "Expect copy");
14381ad6265SDimitry Andric 
14481ad6265SDimitry Andric           RegsToInvalidate.insert(
14581ad6265SDimitry Andric               CopyOperands->Destination->getReg().asMCReg());
14681ad6265SDimitry Andric           RegsToInvalidate.insert(CopyOperands->Source->getReg().asMCReg());
147480093f4SDimitry Andric         }
148480093f4SDimitry Andric         RegsToInvalidate.insert(I->second.DefRegs.begin(),
149480093f4SDimitry Andric                                 I->second.DefRegs.end());
150480093f4SDimitry Andric       }
151480093f4SDimitry Andric     }
152e8d8bef9SDimitry Andric     for (MCRegister InvalidReg : RegsToInvalidate)
153480093f4SDimitry Andric       for (MCRegUnitIterator RUI(InvalidReg, &TRI); RUI.isValid(); ++RUI)
154480093f4SDimitry Andric         Copies.erase(*RUI);
155480093f4SDimitry Andric   }
156480093f4SDimitry Andric 
1570b57cec5SDimitry Andric   /// Clobber a single register, removing it from the tracker's copy maps.
15881ad6265SDimitry Andric   void clobberRegister(MCRegister Reg, const TargetRegisterInfo &TRI,
15981ad6265SDimitry Andric                        const TargetInstrInfo &TII, bool UseCopyInstr) {
1600b57cec5SDimitry Andric     for (MCRegUnitIterator RUI(Reg, &TRI); RUI.isValid(); ++RUI) {
1610b57cec5SDimitry Andric       auto I = Copies.find(*RUI);
1620b57cec5SDimitry Andric       if (I != Copies.end()) {
1630b57cec5SDimitry Andric         // When we clobber the source of a copy, we need to clobber everything
1640b57cec5SDimitry Andric         // it defined.
1650b57cec5SDimitry Andric         markRegsUnavailable(I->second.DefRegs, TRI);
1660b57cec5SDimitry Andric         // When we clobber the destination of a copy, we need to clobber the
1670b57cec5SDimitry Andric         // whole register it defined.
16881ad6265SDimitry Andric         if (MachineInstr *MI = I->second.MI) {
169*bdd1243dSDimitry Andric           std::optional<DestSourcePair> CopyOperands =
17081ad6265SDimitry Andric               isCopyInstr(*MI, TII, UseCopyInstr);
17181ad6265SDimitry Andric           markRegsUnavailable({CopyOperands->Destination->getReg().asMCReg()},
17281ad6265SDimitry Andric                               TRI);
17381ad6265SDimitry Andric         }
1740b57cec5SDimitry Andric         // Now we can erase the copy.
1750b57cec5SDimitry Andric         Copies.erase(I);
1760b57cec5SDimitry Andric       }
1770b57cec5SDimitry Andric     }
1780b57cec5SDimitry Andric   }
1790b57cec5SDimitry Andric 
1800b57cec5SDimitry Andric   /// Add this copy's registers into the tracker's copy maps.
18181ad6265SDimitry Andric   void trackCopy(MachineInstr *MI, const TargetRegisterInfo &TRI,
18281ad6265SDimitry Andric                  const TargetInstrInfo &TII, bool UseCopyInstr) {
183*bdd1243dSDimitry Andric     std::optional<DestSourcePair> CopyOperands =
184*bdd1243dSDimitry Andric         isCopyInstr(*MI, TII, UseCopyInstr);
18581ad6265SDimitry Andric     assert(CopyOperands && "Tracking non-copy?");
1860b57cec5SDimitry Andric 
18781ad6265SDimitry Andric     MCRegister Src = CopyOperands->Source->getReg().asMCReg();
18881ad6265SDimitry Andric     MCRegister Def = CopyOperands->Destination->getReg().asMCReg();
1890b57cec5SDimitry Andric 
1900b57cec5SDimitry Andric     // Remember Def is defined by the copy.
1910b57cec5SDimitry Andric     for (MCRegUnitIterator RUI(Def, &TRI); RUI.isValid(); ++RUI)
1920b57cec5SDimitry Andric       Copies[*RUI] = {MI, {}, true};
1930b57cec5SDimitry Andric 
1940b57cec5SDimitry Andric     // Remember source that's copied to Def. Once it's clobbered, then
1950b57cec5SDimitry Andric     // it's no longer available for copy propagation.
1960b57cec5SDimitry Andric     for (MCRegUnitIterator RUI(Src, &TRI); RUI.isValid(); ++RUI) {
1970b57cec5SDimitry Andric       auto I = Copies.insert({*RUI, {nullptr, {}, false}});
1980b57cec5SDimitry Andric       auto &Copy = I.first->second;
1990b57cec5SDimitry Andric       if (!is_contained(Copy.DefRegs, Def))
2000b57cec5SDimitry Andric         Copy.DefRegs.push_back(Def);
2010b57cec5SDimitry Andric     }
2020b57cec5SDimitry Andric   }
2030b57cec5SDimitry Andric 
2040b57cec5SDimitry Andric   bool hasAnyCopies() {
2050b57cec5SDimitry Andric     return !Copies.empty();
2060b57cec5SDimitry Andric   }
2070b57cec5SDimitry Andric 
208e8d8bef9SDimitry Andric   MachineInstr *findCopyForUnit(MCRegister RegUnit,
209e8d8bef9SDimitry Andric                                 const TargetRegisterInfo &TRI,
2100b57cec5SDimitry Andric                                 bool MustBeAvailable = false) {
2110b57cec5SDimitry Andric     auto CI = Copies.find(RegUnit);
2120b57cec5SDimitry Andric     if (CI == Copies.end())
2130b57cec5SDimitry Andric       return nullptr;
2140b57cec5SDimitry Andric     if (MustBeAvailable && !CI->second.Avail)
2150b57cec5SDimitry Andric       return nullptr;
2160b57cec5SDimitry Andric     return CI->second.MI;
2170b57cec5SDimitry Andric   }
2180b57cec5SDimitry Andric 
219e8d8bef9SDimitry Andric   MachineInstr *findCopyDefViaUnit(MCRegister RegUnit,
220480093f4SDimitry Andric                                    const TargetRegisterInfo &TRI) {
221480093f4SDimitry Andric     auto CI = Copies.find(RegUnit);
222480093f4SDimitry Andric     if (CI == Copies.end())
223480093f4SDimitry Andric       return nullptr;
224480093f4SDimitry Andric     if (CI->second.DefRegs.size() != 1)
225480093f4SDimitry Andric       return nullptr;
226480093f4SDimitry Andric     MCRegUnitIterator RUI(CI->second.DefRegs[0], &TRI);
227480093f4SDimitry Andric     return findCopyForUnit(*RUI, TRI, true);
228480093f4SDimitry Andric   }
229480093f4SDimitry Andric 
230e8d8bef9SDimitry Andric   MachineInstr *findAvailBackwardCopy(MachineInstr &I, MCRegister Reg,
23181ad6265SDimitry Andric                                       const TargetRegisterInfo &TRI,
23281ad6265SDimitry Andric                                       const TargetInstrInfo &TII,
23381ad6265SDimitry Andric                                       bool UseCopyInstr) {
234480093f4SDimitry Andric     MCRegUnitIterator RUI(Reg, &TRI);
235480093f4SDimitry Andric     MachineInstr *AvailCopy = findCopyDefViaUnit(*RUI, TRI);
23681ad6265SDimitry Andric 
23781ad6265SDimitry Andric     if (!AvailCopy)
238480093f4SDimitry Andric       return nullptr;
239480093f4SDimitry Andric 
240*bdd1243dSDimitry Andric     std::optional<DestSourcePair> CopyOperands =
24181ad6265SDimitry Andric         isCopyInstr(*AvailCopy, TII, UseCopyInstr);
24281ad6265SDimitry Andric     Register AvailSrc = CopyOperands->Source->getReg();
24381ad6265SDimitry Andric     Register AvailDef = CopyOperands->Destination->getReg();
24481ad6265SDimitry Andric     if (!TRI.isSubRegisterEq(AvailSrc, Reg))
24581ad6265SDimitry Andric       return nullptr;
24681ad6265SDimitry Andric 
247480093f4SDimitry Andric     for (const MachineInstr &MI :
248480093f4SDimitry Andric          make_range(AvailCopy->getReverseIterator(), I.getReverseIterator()))
249480093f4SDimitry Andric       for (const MachineOperand &MO : MI.operands())
250480093f4SDimitry Andric         if (MO.isRegMask())
251480093f4SDimitry Andric           // FIXME: Shall we simultaneously invalidate AvailSrc or AvailDef?
252480093f4SDimitry Andric           if (MO.clobbersPhysReg(AvailSrc) || MO.clobbersPhysReg(AvailDef))
253480093f4SDimitry Andric             return nullptr;
254480093f4SDimitry Andric 
255480093f4SDimitry Andric     return AvailCopy;
256480093f4SDimitry Andric   }
257480093f4SDimitry Andric 
258e8d8bef9SDimitry Andric   MachineInstr *findAvailCopy(MachineInstr &DestCopy, MCRegister Reg,
25981ad6265SDimitry Andric                               const TargetRegisterInfo &TRI,
26081ad6265SDimitry Andric                               const TargetInstrInfo &TII, bool UseCopyInstr) {
2610b57cec5SDimitry Andric     // We check the first RegUnit here, since we'll only be interested in the
2620b57cec5SDimitry Andric     // copy if it copies the entire register anyway.
2630b57cec5SDimitry Andric     MCRegUnitIterator RUI(Reg, &TRI);
2640b57cec5SDimitry Andric     MachineInstr *AvailCopy =
2650b57cec5SDimitry Andric         findCopyForUnit(*RUI, TRI, /*MustBeAvailable=*/true);
26681ad6265SDimitry Andric 
26781ad6265SDimitry Andric     if (!AvailCopy)
26881ad6265SDimitry Andric       return nullptr;
26981ad6265SDimitry Andric 
270*bdd1243dSDimitry Andric     std::optional<DestSourcePair> CopyOperands =
27181ad6265SDimitry Andric         isCopyInstr(*AvailCopy, TII, UseCopyInstr);
27281ad6265SDimitry Andric     Register AvailSrc = CopyOperands->Source->getReg();
27381ad6265SDimitry Andric     Register AvailDef = CopyOperands->Destination->getReg();
27481ad6265SDimitry Andric     if (!TRI.isSubRegisterEq(AvailDef, Reg))
2750b57cec5SDimitry Andric       return nullptr;
2760b57cec5SDimitry Andric 
2770b57cec5SDimitry Andric     // Check that the available copy isn't clobbered by any regmasks between
2780b57cec5SDimitry Andric     // itself and the destination.
2790b57cec5SDimitry Andric     for (const MachineInstr &MI :
2800b57cec5SDimitry Andric          make_range(AvailCopy->getIterator(), DestCopy.getIterator()))
2810b57cec5SDimitry Andric       for (const MachineOperand &MO : MI.operands())
2820b57cec5SDimitry Andric         if (MO.isRegMask())
2830b57cec5SDimitry Andric           if (MO.clobbersPhysReg(AvailSrc) || MO.clobbersPhysReg(AvailDef))
2840b57cec5SDimitry Andric             return nullptr;
2850b57cec5SDimitry Andric 
2860b57cec5SDimitry Andric     return AvailCopy;
2870b57cec5SDimitry Andric   }
2880b57cec5SDimitry Andric 
2890b57cec5SDimitry Andric   void clear() {
2900b57cec5SDimitry Andric     Copies.clear();
2910b57cec5SDimitry Andric   }
2920b57cec5SDimitry Andric };
2930b57cec5SDimitry Andric 
2940b57cec5SDimitry Andric class MachineCopyPropagation : public MachineFunctionPass {
2950b57cec5SDimitry Andric   const TargetRegisterInfo *TRI;
2960b57cec5SDimitry Andric   const TargetInstrInfo *TII;
2970b57cec5SDimitry Andric   const MachineRegisterInfo *MRI;
2980b57cec5SDimitry Andric 
29981ad6265SDimitry Andric   // Return true if this is a copy instruction and false otherwise.
30081ad6265SDimitry Andric   bool UseCopyInstr;
30181ad6265SDimitry Andric 
3020b57cec5SDimitry Andric public:
3030b57cec5SDimitry Andric   static char ID; // Pass identification, replacement for typeid
3040b57cec5SDimitry Andric 
30581ad6265SDimitry Andric   MachineCopyPropagation(bool CopyInstr = false)
30681ad6265SDimitry Andric       : MachineFunctionPass(ID), UseCopyInstr(CopyInstr || MCPUseCopyInstr) {
3070b57cec5SDimitry Andric     initializeMachineCopyPropagationPass(*PassRegistry::getPassRegistry());
3080b57cec5SDimitry Andric   }
3090b57cec5SDimitry Andric 
3100b57cec5SDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override {
3110b57cec5SDimitry Andric     AU.setPreservesCFG();
3120b57cec5SDimitry Andric     MachineFunctionPass::getAnalysisUsage(AU);
3130b57cec5SDimitry Andric   }
3140b57cec5SDimitry Andric 
3150b57cec5SDimitry Andric   bool runOnMachineFunction(MachineFunction &MF) override;
3160b57cec5SDimitry Andric 
3170b57cec5SDimitry Andric   MachineFunctionProperties getRequiredProperties() const override {
3180b57cec5SDimitry Andric     return MachineFunctionProperties().set(
3190b57cec5SDimitry Andric         MachineFunctionProperties::Property::NoVRegs);
3200b57cec5SDimitry Andric   }
3210b57cec5SDimitry Andric 
3220b57cec5SDimitry Andric private:
3238bcb0991SDimitry Andric   typedef enum { DebugUse = false, RegularUse = true } DebugType;
3248bcb0991SDimitry Andric 
325e8d8bef9SDimitry Andric   void ReadRegister(MCRegister Reg, MachineInstr &Reader, DebugType DT);
326480093f4SDimitry Andric   void ForwardCopyPropagateBlock(MachineBasicBlock &MBB);
327480093f4SDimitry Andric   void BackwardCopyPropagateBlock(MachineBasicBlock &MBB);
328e8d8bef9SDimitry Andric   bool eraseIfRedundant(MachineInstr &Copy, MCRegister Src, MCRegister Def);
3290b57cec5SDimitry Andric   void forwardUses(MachineInstr &MI);
330480093f4SDimitry Andric   void propagateDefs(MachineInstr &MI);
3310b57cec5SDimitry Andric   bool isForwardableRegClassCopy(const MachineInstr &Copy,
3320b57cec5SDimitry Andric                                  const MachineInstr &UseI, unsigned UseIdx);
333480093f4SDimitry Andric   bool isBackwardPropagatableRegClassCopy(const MachineInstr &Copy,
334480093f4SDimitry Andric                                           const MachineInstr &UseI,
335480093f4SDimitry Andric                                           unsigned UseIdx);
3360b57cec5SDimitry Andric   bool hasImplicitOverlap(const MachineInstr &MI, const MachineOperand &Use);
337e8d8bef9SDimitry Andric   bool hasOverlappingMultipleDef(const MachineInstr &MI,
338e8d8bef9SDimitry Andric                                  const MachineOperand &MODef, Register Def);
3390b57cec5SDimitry Andric 
3400b57cec5SDimitry Andric   /// Candidates for deletion.
3410b57cec5SDimitry Andric   SmallSetVector<MachineInstr *, 8> MaybeDeadCopies;
3420b57cec5SDimitry Andric 
3438bcb0991SDimitry Andric   /// Multimap tracking debug users in current BB
344fe6060f1SDimitry Andric   DenseMap<MachineInstr *, SmallSet<MachineInstr *, 2>> CopyDbgUsers;
3458bcb0991SDimitry Andric 
3460b57cec5SDimitry Andric   CopyTracker Tracker;
3470b57cec5SDimitry Andric 
3480b57cec5SDimitry Andric   bool Changed;
3490b57cec5SDimitry Andric };
3500b57cec5SDimitry Andric 
3510b57cec5SDimitry Andric } // end anonymous namespace
3520b57cec5SDimitry Andric 
3530b57cec5SDimitry Andric char MachineCopyPropagation::ID = 0;
3540b57cec5SDimitry Andric 
3550b57cec5SDimitry Andric char &llvm::MachineCopyPropagationID = MachineCopyPropagation::ID;
3560b57cec5SDimitry Andric 
3570b57cec5SDimitry Andric INITIALIZE_PASS(MachineCopyPropagation, DEBUG_TYPE,
3580b57cec5SDimitry Andric                 "Machine Copy Propagation Pass", false, false)
3590b57cec5SDimitry Andric 
360e8d8bef9SDimitry Andric void MachineCopyPropagation::ReadRegister(MCRegister Reg, MachineInstr &Reader,
3618bcb0991SDimitry Andric                                           DebugType DT) {
3620b57cec5SDimitry Andric   // If 'Reg' is defined by a copy, the copy is no longer a candidate
3638bcb0991SDimitry Andric   // for elimination. If a copy is "read" by a debug user, record the user
3648bcb0991SDimitry Andric   // for propagation.
3650b57cec5SDimitry Andric   for (MCRegUnitIterator RUI(Reg, TRI); RUI.isValid(); ++RUI) {
3660b57cec5SDimitry Andric     if (MachineInstr *Copy = Tracker.findCopyForUnit(*RUI, *TRI)) {
3678bcb0991SDimitry Andric       if (DT == RegularUse) {
3680b57cec5SDimitry Andric         LLVM_DEBUG(dbgs() << "MCP: Copy is used - not dead: "; Copy->dump());
3690b57cec5SDimitry Andric         MaybeDeadCopies.remove(Copy);
3708bcb0991SDimitry Andric       } else {
371fe6060f1SDimitry Andric         CopyDbgUsers[Copy].insert(&Reader);
3728bcb0991SDimitry Andric       }
3730b57cec5SDimitry Andric     }
3740b57cec5SDimitry Andric   }
3750b57cec5SDimitry Andric }
3760b57cec5SDimitry Andric 
3770b57cec5SDimitry Andric /// Return true if \p PreviousCopy did copy register \p Src to register \p Def.
3780b57cec5SDimitry Andric /// This fact may have been obscured by sub register usage or may not be true at
3790b57cec5SDimitry Andric /// all even though Src and Def are subregisters of the registers used in
3800b57cec5SDimitry Andric /// PreviousCopy. e.g.
3810b57cec5SDimitry Andric /// isNopCopy("ecx = COPY eax", AX, CX) == true
3820b57cec5SDimitry Andric /// isNopCopy("ecx = COPY eax", AH, CL) == false
383e8d8bef9SDimitry Andric static bool isNopCopy(const MachineInstr &PreviousCopy, MCRegister Src,
38481ad6265SDimitry Andric                       MCRegister Def, const TargetRegisterInfo *TRI,
38581ad6265SDimitry Andric                       const TargetInstrInfo *TII, bool UseCopyInstr) {
38681ad6265SDimitry Andric 
387*bdd1243dSDimitry Andric   std::optional<DestSourcePair> CopyOperands =
38881ad6265SDimitry Andric       isCopyInstr(PreviousCopy, *TII, UseCopyInstr);
38981ad6265SDimitry Andric   MCRegister PreviousSrc = CopyOperands->Source->getReg().asMCReg();
39081ad6265SDimitry Andric   MCRegister PreviousDef = CopyOperands->Destination->getReg().asMCReg();
39116d6b3b3SDimitry Andric   if (Src == PreviousSrc && Def == PreviousDef)
3920b57cec5SDimitry Andric     return true;
3930b57cec5SDimitry Andric   if (!TRI->isSubRegister(PreviousSrc, Src))
3940b57cec5SDimitry Andric     return false;
3950b57cec5SDimitry Andric   unsigned SubIdx = TRI->getSubRegIndex(PreviousSrc, Src);
3960b57cec5SDimitry Andric   return SubIdx == TRI->getSubRegIndex(PreviousDef, Def);
3970b57cec5SDimitry Andric }
3980b57cec5SDimitry Andric 
3990b57cec5SDimitry Andric /// Remove instruction \p Copy if there exists a previous copy that copies the
4000b57cec5SDimitry Andric /// register \p Src to the register \p Def; This may happen indirectly by
4010b57cec5SDimitry Andric /// copying the super registers.
402e8d8bef9SDimitry Andric bool MachineCopyPropagation::eraseIfRedundant(MachineInstr &Copy,
403e8d8bef9SDimitry Andric                                               MCRegister Src, MCRegister Def) {
4040b57cec5SDimitry Andric   // Avoid eliminating a copy from/to a reserved registers as we cannot predict
4050b57cec5SDimitry Andric   // the value (Example: The sparc zero register is writable but stays zero).
4060b57cec5SDimitry Andric   if (MRI->isReserved(Src) || MRI->isReserved(Def))
4070b57cec5SDimitry Andric     return false;
4080b57cec5SDimitry Andric 
4090b57cec5SDimitry Andric   // Search for an existing copy.
41081ad6265SDimitry Andric   MachineInstr *PrevCopy =
41181ad6265SDimitry Andric       Tracker.findAvailCopy(Copy, Def, *TRI, *TII, UseCopyInstr);
4120b57cec5SDimitry Andric   if (!PrevCopy)
4130b57cec5SDimitry Andric     return false;
4140b57cec5SDimitry Andric 
41581ad6265SDimitry Andric   auto PrevCopyOperands = isCopyInstr(*PrevCopy, *TII, UseCopyInstr);
4160b57cec5SDimitry Andric   // Check that the existing copy uses the correct sub registers.
41781ad6265SDimitry Andric   if (PrevCopyOperands->Destination->isDead())
4180b57cec5SDimitry Andric     return false;
41981ad6265SDimitry Andric   if (!isNopCopy(*PrevCopy, Src, Def, TRI, TII, UseCopyInstr))
4200b57cec5SDimitry Andric     return false;
4210b57cec5SDimitry Andric 
4220b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "MCP: copy is a NOP, removing: "; Copy.dump());
4230b57cec5SDimitry Andric 
4240b57cec5SDimitry Andric   // Copy was redundantly redefining either Src or Def. Remove earlier kill
4250b57cec5SDimitry Andric   // flags between Copy and PrevCopy because the value will be reused now.
426*bdd1243dSDimitry Andric   std::optional<DestSourcePair> CopyOperands =
427*bdd1243dSDimitry Andric       isCopyInstr(Copy, *TII, UseCopyInstr);
42881ad6265SDimitry Andric   assert(CopyOperands);
42981ad6265SDimitry Andric 
43081ad6265SDimitry Andric   Register CopyDef = CopyOperands->Destination->getReg();
4310b57cec5SDimitry Andric   assert(CopyDef == Src || CopyDef == Def);
4320b57cec5SDimitry Andric   for (MachineInstr &MI :
4330b57cec5SDimitry Andric        make_range(PrevCopy->getIterator(), Copy.getIterator()))
4340b57cec5SDimitry Andric     MI.clearRegisterKills(CopyDef, TRI);
4350b57cec5SDimitry Andric 
4360b57cec5SDimitry Andric   Copy.eraseFromParent();
4370b57cec5SDimitry Andric   Changed = true;
4380b57cec5SDimitry Andric   ++NumDeletes;
4390b57cec5SDimitry Andric   return true;
4400b57cec5SDimitry Andric }
4410b57cec5SDimitry Andric 
442480093f4SDimitry Andric bool MachineCopyPropagation::isBackwardPropagatableRegClassCopy(
443480093f4SDimitry Andric     const MachineInstr &Copy, const MachineInstr &UseI, unsigned UseIdx) {
444*bdd1243dSDimitry Andric   std::optional<DestSourcePair> CopyOperands =
445*bdd1243dSDimitry Andric       isCopyInstr(Copy, *TII, UseCopyInstr);
44681ad6265SDimitry Andric   Register Def = CopyOperands->Destination->getReg();
447480093f4SDimitry Andric 
448480093f4SDimitry Andric   if (const TargetRegisterClass *URC =
449480093f4SDimitry Andric           UseI.getRegClassConstraint(UseIdx, TII, TRI))
450480093f4SDimitry Andric     return URC->contains(Def);
451480093f4SDimitry Andric 
452480093f4SDimitry Andric   // We don't process further if UseI is a COPY, since forward copy propagation
453480093f4SDimitry Andric   // should handle that.
454480093f4SDimitry Andric   return false;
455480093f4SDimitry Andric }
456480093f4SDimitry Andric 
4570b57cec5SDimitry Andric /// Decide whether we should forward the source of \param Copy to its use in
4580b57cec5SDimitry Andric /// \param UseI based on the physical register class constraints of the opcode
4590b57cec5SDimitry Andric /// and avoiding introducing more cross-class COPYs.
4600b57cec5SDimitry Andric bool MachineCopyPropagation::isForwardableRegClassCopy(const MachineInstr &Copy,
4610b57cec5SDimitry Andric                                                        const MachineInstr &UseI,
4620b57cec5SDimitry Andric                                                        unsigned UseIdx) {
463*bdd1243dSDimitry Andric   std::optional<DestSourcePair> CopyOperands =
464*bdd1243dSDimitry Andric       isCopyInstr(Copy, *TII, UseCopyInstr);
46581ad6265SDimitry Andric   Register CopySrcReg = CopyOperands->Source->getReg();
4660b57cec5SDimitry Andric 
4670b57cec5SDimitry Andric   // If the new register meets the opcode register constraints, then allow
4680b57cec5SDimitry Andric   // forwarding.
4690b57cec5SDimitry Andric   if (const TargetRegisterClass *URC =
4700b57cec5SDimitry Andric           UseI.getRegClassConstraint(UseIdx, TII, TRI))
4710b57cec5SDimitry Andric     return URC->contains(CopySrcReg);
4720b57cec5SDimitry Andric 
47381ad6265SDimitry Andric   auto UseICopyOperands = isCopyInstr(UseI, *TII, UseCopyInstr);
47481ad6265SDimitry Andric   if (!UseICopyOperands)
4750b57cec5SDimitry Andric     return false;
4760b57cec5SDimitry Andric 
4770b57cec5SDimitry Andric   /// COPYs don't have register class constraints, so if the user instruction
4780b57cec5SDimitry Andric   /// is a COPY, we just try to avoid introducing additional cross-class
4790b57cec5SDimitry Andric   /// COPYs.  For example:
4800b57cec5SDimitry Andric   ///
4810b57cec5SDimitry Andric   ///   RegClassA = COPY RegClassB  // Copy parameter
4820b57cec5SDimitry Andric   ///   ...
4830b57cec5SDimitry Andric   ///   RegClassB = COPY RegClassA  // UseI parameter
4840b57cec5SDimitry Andric   ///
4850b57cec5SDimitry Andric   /// which after forwarding becomes
4860b57cec5SDimitry Andric   ///
4870b57cec5SDimitry Andric   ///   RegClassA = COPY RegClassB
4880b57cec5SDimitry Andric   ///   ...
4890b57cec5SDimitry Andric   ///   RegClassB = COPY RegClassB
4900b57cec5SDimitry Andric   ///
4910b57cec5SDimitry Andric   /// so we have reduced the number of cross-class COPYs and potentially
4920b57cec5SDimitry Andric   /// introduced a nop COPY that can be removed.
4930b57cec5SDimitry Andric 
49481ad6265SDimitry Andric   // Allow forwarding if src and dst belong to any common class, so long as they
49581ad6265SDimitry Andric   // don't belong to any (possibly smaller) common class that requires copies to
49681ad6265SDimitry Andric   // go via a different class.
49781ad6265SDimitry Andric   Register UseDstReg = UseICopyOperands->Destination->getReg();
49881ad6265SDimitry Andric   bool Found = false;
49981ad6265SDimitry Andric   bool IsCrossClass = false;
50081ad6265SDimitry Andric   for (const TargetRegisterClass *RC : TRI->regclasses()) {
50181ad6265SDimitry Andric     if (RC->contains(CopySrcReg) && RC->contains(UseDstReg)) {
50281ad6265SDimitry Andric       Found = true;
50381ad6265SDimitry Andric       if (TRI->getCrossCopyRegClass(RC) != RC) {
50481ad6265SDimitry Andric         IsCrossClass = true;
50581ad6265SDimitry Andric         break;
50681ad6265SDimitry Andric       }
50781ad6265SDimitry Andric     }
50881ad6265SDimitry Andric   }
50981ad6265SDimitry Andric   if (!Found)
51081ad6265SDimitry Andric     return false;
51181ad6265SDimitry Andric   if (!IsCrossClass)
51281ad6265SDimitry Andric     return true;
51381ad6265SDimitry Andric   // The forwarded copy would be cross-class. Only do this if the original copy
51481ad6265SDimitry Andric   // was also cross-class.
51581ad6265SDimitry Andric   Register CopyDstReg = CopyOperands->Destination->getReg();
51681ad6265SDimitry Andric   for (const TargetRegisterClass *RC : TRI->regclasses()) {
51781ad6265SDimitry Andric     if (RC->contains(CopySrcReg) && RC->contains(CopyDstReg) &&
51881ad6265SDimitry Andric         TRI->getCrossCopyRegClass(RC) != RC)
51981ad6265SDimitry Andric       return true;
52081ad6265SDimitry Andric   }
5210b57cec5SDimitry Andric   return false;
5220b57cec5SDimitry Andric }
5230b57cec5SDimitry Andric 
5240b57cec5SDimitry Andric /// Check that \p MI does not have implicit uses that overlap with it's \p Use
5250b57cec5SDimitry Andric /// operand (the register being replaced), since these can sometimes be
5260b57cec5SDimitry Andric /// implicitly tied to other operands.  For example, on AMDGPU:
5270b57cec5SDimitry Andric ///
5280b57cec5SDimitry Andric /// V_MOVRELS_B32_e32 %VGPR2, %M0<imp-use>, %EXEC<imp-use>, %VGPR2_VGPR3_VGPR4_VGPR5<imp-use>
5290b57cec5SDimitry Andric ///
5300b57cec5SDimitry Andric /// the %VGPR2 is implicitly tied to the larger reg operand, but we have no
5310b57cec5SDimitry Andric /// way of knowing we need to update the latter when updating the former.
5320b57cec5SDimitry Andric bool MachineCopyPropagation::hasImplicitOverlap(const MachineInstr &MI,
5330b57cec5SDimitry Andric                                                 const MachineOperand &Use) {
5340b57cec5SDimitry Andric   for (const MachineOperand &MIUse : MI.uses())
5350b57cec5SDimitry Andric     if (&MIUse != &Use && MIUse.isReg() && MIUse.isImplicit() &&
5360b57cec5SDimitry Andric         MIUse.isUse() && TRI->regsOverlap(Use.getReg(), MIUse.getReg()))
5370b57cec5SDimitry Andric       return true;
5380b57cec5SDimitry Andric 
5390b57cec5SDimitry Andric   return false;
5400b57cec5SDimitry Andric }
5410b57cec5SDimitry Andric 
542e8d8bef9SDimitry Andric /// For an MI that has multiple definitions, check whether \p MI has
543e8d8bef9SDimitry Andric /// a definition that overlaps with another of its definitions.
544e8d8bef9SDimitry Andric /// For example, on ARM: umull   r9, r9, lr, r0
545e8d8bef9SDimitry Andric /// The umull instruction is unpredictable unless RdHi and RdLo are different.
546e8d8bef9SDimitry Andric bool MachineCopyPropagation::hasOverlappingMultipleDef(
547e8d8bef9SDimitry Andric     const MachineInstr &MI, const MachineOperand &MODef, Register Def) {
548e8d8bef9SDimitry Andric   for (const MachineOperand &MIDef : MI.defs()) {
549e8d8bef9SDimitry Andric     if ((&MIDef != &MODef) && MIDef.isReg() &&
550e8d8bef9SDimitry Andric         TRI->regsOverlap(Def, MIDef.getReg()))
551e8d8bef9SDimitry Andric       return true;
552e8d8bef9SDimitry Andric   }
553e8d8bef9SDimitry Andric 
554e8d8bef9SDimitry Andric   return false;
555e8d8bef9SDimitry Andric }
556e8d8bef9SDimitry Andric 
5570b57cec5SDimitry Andric /// Look for available copies whose destination register is used by \p MI and
5580b57cec5SDimitry Andric /// replace the use in \p MI with the copy's source register.
5590b57cec5SDimitry Andric void MachineCopyPropagation::forwardUses(MachineInstr &MI) {
5600b57cec5SDimitry Andric   if (!Tracker.hasAnyCopies())
5610b57cec5SDimitry Andric     return;
5620b57cec5SDimitry Andric 
5630b57cec5SDimitry Andric   // Look for non-tied explicit vreg uses that have an active COPY
5640b57cec5SDimitry Andric   // instruction that defines the physical register allocated to them.
5650b57cec5SDimitry Andric   // Replace the vreg with the source of the active COPY.
5660b57cec5SDimitry Andric   for (unsigned OpIdx = 0, OpEnd = MI.getNumOperands(); OpIdx < OpEnd;
5670b57cec5SDimitry Andric        ++OpIdx) {
5680b57cec5SDimitry Andric     MachineOperand &MOUse = MI.getOperand(OpIdx);
5690b57cec5SDimitry Andric     // Don't forward into undef use operands since doing so can cause problems
5700b57cec5SDimitry Andric     // with the machine verifier, since it doesn't treat undef reads as reads,
5710b57cec5SDimitry Andric     // so we can end up with a live range that ends on an undef read, leading to
5720b57cec5SDimitry Andric     // an error that the live range doesn't end on a read of the live range
5730b57cec5SDimitry Andric     // register.
5740b57cec5SDimitry Andric     if (!MOUse.isReg() || MOUse.isTied() || MOUse.isUndef() || MOUse.isDef() ||
5750b57cec5SDimitry Andric         MOUse.isImplicit())
5760b57cec5SDimitry Andric       continue;
5770b57cec5SDimitry Andric 
5780b57cec5SDimitry Andric     if (!MOUse.getReg())
5790b57cec5SDimitry Andric       continue;
5800b57cec5SDimitry Andric 
5810b57cec5SDimitry Andric     // Check that the register is marked 'renamable' so we know it is safe to
5820b57cec5SDimitry Andric     // rename it without violating any constraints that aren't expressed in the
5830b57cec5SDimitry Andric     // IR (e.g. ABI or opcode requirements).
5840b57cec5SDimitry Andric     if (!MOUse.isRenamable())
5850b57cec5SDimitry Andric       continue;
5860b57cec5SDimitry Andric 
58781ad6265SDimitry Andric     MachineInstr *Copy = Tracker.findAvailCopy(MI, MOUse.getReg().asMCReg(),
58881ad6265SDimitry Andric                                                *TRI, *TII, UseCopyInstr);
5890b57cec5SDimitry Andric     if (!Copy)
5900b57cec5SDimitry Andric       continue;
5910b57cec5SDimitry Andric 
592*bdd1243dSDimitry Andric     std::optional<DestSourcePair> CopyOperands =
59381ad6265SDimitry Andric         isCopyInstr(*Copy, *TII, UseCopyInstr);
59481ad6265SDimitry Andric     Register CopyDstReg = CopyOperands->Destination->getReg();
59581ad6265SDimitry Andric     const MachineOperand &CopySrc = *CopyOperands->Source;
5968bcb0991SDimitry Andric     Register CopySrcReg = CopySrc.getReg();
5970b57cec5SDimitry Andric 
5980b57cec5SDimitry Andric     // FIXME: Don't handle partial uses of wider COPYs yet.
5990b57cec5SDimitry Andric     if (MOUse.getReg() != CopyDstReg) {
6000b57cec5SDimitry Andric       LLVM_DEBUG(
6010b57cec5SDimitry Andric           dbgs() << "MCP: FIXME! Not forwarding COPY to sub-register use:\n  "
6020b57cec5SDimitry Andric                  << MI);
6030b57cec5SDimitry Andric       continue;
6040b57cec5SDimitry Andric     }
6050b57cec5SDimitry Andric 
6060b57cec5SDimitry Andric     // Don't forward COPYs of reserved regs unless they are constant.
6070b57cec5SDimitry Andric     if (MRI->isReserved(CopySrcReg) && !MRI->isConstantPhysReg(CopySrcReg))
6080b57cec5SDimitry Andric       continue;
6090b57cec5SDimitry Andric 
6100b57cec5SDimitry Andric     if (!isForwardableRegClassCopy(*Copy, MI, OpIdx))
6110b57cec5SDimitry Andric       continue;
6120b57cec5SDimitry Andric 
6130b57cec5SDimitry Andric     if (hasImplicitOverlap(MI, MOUse))
6140b57cec5SDimitry Andric       continue;
6150b57cec5SDimitry Andric 
616480093f4SDimitry Andric     // Check that the instruction is not a copy that partially overwrites the
617480093f4SDimitry Andric     // original copy source that we are about to use. The tracker mechanism
618480093f4SDimitry Andric     // cannot cope with that.
61981ad6265SDimitry Andric     if (isCopyInstr(MI, *TII, UseCopyInstr) &&
62081ad6265SDimitry Andric         MI.modifiesRegister(CopySrcReg, TRI) &&
621480093f4SDimitry Andric         !MI.definesRegister(CopySrcReg)) {
622480093f4SDimitry Andric       LLVM_DEBUG(dbgs() << "MCP: Copy source overlap with dest in " << MI);
623480093f4SDimitry Andric       continue;
624480093f4SDimitry Andric     }
625480093f4SDimitry Andric 
6260b57cec5SDimitry Andric     if (!DebugCounter::shouldExecute(FwdCounter)) {
6270b57cec5SDimitry Andric       LLVM_DEBUG(dbgs() << "MCP: Skipping forwarding due to debug counter:\n  "
6280b57cec5SDimitry Andric                         << MI);
6290b57cec5SDimitry Andric       continue;
6300b57cec5SDimitry Andric     }
6310b57cec5SDimitry Andric 
6320b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "MCP: Replacing " << printReg(MOUse.getReg(), TRI)
6330b57cec5SDimitry Andric                       << "\n     with " << printReg(CopySrcReg, TRI)
6340b57cec5SDimitry Andric                       << "\n     in " << MI << "     from " << *Copy);
6350b57cec5SDimitry Andric 
6360b57cec5SDimitry Andric     MOUse.setReg(CopySrcReg);
6370b57cec5SDimitry Andric     if (!CopySrc.isRenamable())
6380b57cec5SDimitry Andric       MOUse.setIsRenamable(false);
639349cc55cSDimitry Andric     MOUse.setIsUndef(CopySrc.isUndef());
6400b57cec5SDimitry Andric 
6410b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "MCP: After replacement: " << MI << "\n");
6420b57cec5SDimitry Andric 
6430b57cec5SDimitry Andric     // Clear kill markers that may have been invalidated.
6440b57cec5SDimitry Andric     for (MachineInstr &KMI :
6450b57cec5SDimitry Andric          make_range(Copy->getIterator(), std::next(MI.getIterator())))
6460b57cec5SDimitry Andric       KMI.clearRegisterKills(CopySrcReg, TRI);
6470b57cec5SDimitry Andric 
6480b57cec5SDimitry Andric     ++NumCopyForwards;
6490b57cec5SDimitry Andric     Changed = true;
6500b57cec5SDimitry Andric   }
6510b57cec5SDimitry Andric }
6520b57cec5SDimitry Andric 
653480093f4SDimitry Andric void MachineCopyPropagation::ForwardCopyPropagateBlock(MachineBasicBlock &MBB) {
654480093f4SDimitry Andric   LLVM_DEBUG(dbgs() << "MCP: ForwardCopyPropagateBlock " << MBB.getName()
655480093f4SDimitry Andric                     << "\n");
6560b57cec5SDimitry Andric 
657349cc55cSDimitry Andric   for (MachineInstr &MI : llvm::make_early_inc_range(MBB)) {
6580b57cec5SDimitry Andric     // Analyze copies (which don't overlap themselves).
659*bdd1243dSDimitry Andric     std::optional<DestSourcePair> CopyOperands =
660*bdd1243dSDimitry Andric         isCopyInstr(MI, *TII, UseCopyInstr);
66181ad6265SDimitry Andric     if (CopyOperands) {
66281ad6265SDimitry Andric 
66381ad6265SDimitry Andric       Register RegSrc = CopyOperands->Source->getReg();
66481ad6265SDimitry Andric       Register RegDef = CopyOperands->Destination->getReg();
66581ad6265SDimitry Andric 
66681ad6265SDimitry Andric       if (!TRI->regsOverlap(RegDef, RegSrc)) {
66781ad6265SDimitry Andric         assert(RegDef.isPhysical() && RegSrc.isPhysical() &&
6680b57cec5SDimitry Andric               "MachineCopyPropagation should be run after register allocation!");
6690b57cec5SDimitry Andric 
67081ad6265SDimitry Andric         MCRegister Def = RegDef.asMCReg();
67181ad6265SDimitry Andric         MCRegister Src = RegSrc.asMCReg();
672e8d8bef9SDimitry Andric 
6730b57cec5SDimitry Andric         // The two copies cancel out and the source of the first copy
6740b57cec5SDimitry Andric         // hasn't been overridden, eliminate the second one. e.g.
6750b57cec5SDimitry Andric         //  %ecx = COPY %eax
6760b57cec5SDimitry Andric         //  ... nothing clobbered eax.
6770b57cec5SDimitry Andric         //  %eax = COPY %ecx
6780b57cec5SDimitry Andric         // =>
6790b57cec5SDimitry Andric         //  %ecx = COPY %eax
6800b57cec5SDimitry Andric         //
6810b57cec5SDimitry Andric         // or
6820b57cec5SDimitry Andric         //
6830b57cec5SDimitry Andric         //  %ecx = COPY %eax
6840b57cec5SDimitry Andric         //  ... nothing clobbered eax.
6850b57cec5SDimitry Andric         //  %ecx = COPY %eax
6860b57cec5SDimitry Andric         // =>
6870b57cec5SDimitry Andric         //  %ecx = COPY %eax
688349cc55cSDimitry Andric         if (eraseIfRedundant(MI, Def, Src) || eraseIfRedundant(MI, Src, Def))
6890b57cec5SDimitry Andric           continue;
6900b57cec5SDimitry Andric 
691349cc55cSDimitry Andric         forwardUses(MI);
6920b57cec5SDimitry Andric 
6930b57cec5SDimitry Andric         // Src may have been changed by forwardUses()
69481ad6265SDimitry Andric         CopyOperands = isCopyInstr(MI, *TII, UseCopyInstr);
69581ad6265SDimitry Andric         Src = CopyOperands->Source->getReg().asMCReg();
6960b57cec5SDimitry Andric 
6970b57cec5SDimitry Andric         // If Src is defined by a previous copy, the previous copy cannot be
6980b57cec5SDimitry Andric         // eliminated.
699349cc55cSDimitry Andric         ReadRegister(Src, MI, RegularUse);
700349cc55cSDimitry Andric         for (const MachineOperand &MO : MI.implicit_operands()) {
7010b57cec5SDimitry Andric           if (!MO.isReg() || !MO.readsReg())
7020b57cec5SDimitry Andric             continue;
703e8d8bef9SDimitry Andric           MCRegister Reg = MO.getReg().asMCReg();
7040b57cec5SDimitry Andric           if (!Reg)
7050b57cec5SDimitry Andric             continue;
706349cc55cSDimitry Andric           ReadRegister(Reg, MI, RegularUse);
7070b57cec5SDimitry Andric         }
7080b57cec5SDimitry Andric 
709349cc55cSDimitry Andric         LLVM_DEBUG(dbgs() << "MCP: Copy is a deletion candidate: "; MI.dump());
7100b57cec5SDimitry Andric 
7110b57cec5SDimitry Andric         // Copy is now a candidate for deletion.
7120b57cec5SDimitry Andric         if (!MRI->isReserved(Def))
713349cc55cSDimitry Andric           MaybeDeadCopies.insert(&MI);
7140b57cec5SDimitry Andric 
7150b57cec5SDimitry Andric         // If 'Def' is previously source of another copy, then this earlier copy's
7160b57cec5SDimitry Andric         // source is no longer available. e.g.
7170b57cec5SDimitry Andric         // %xmm9 = copy %xmm2
7180b57cec5SDimitry Andric         // ...
7190b57cec5SDimitry Andric         // %xmm2 = copy %xmm0
7200b57cec5SDimitry Andric         // ...
7210b57cec5SDimitry Andric         // %xmm2 = copy %xmm9
72281ad6265SDimitry Andric         Tracker.clobberRegister(Def, *TRI, *TII, UseCopyInstr);
723349cc55cSDimitry Andric         for (const MachineOperand &MO : MI.implicit_operands()) {
7240b57cec5SDimitry Andric           if (!MO.isReg() || !MO.isDef())
7250b57cec5SDimitry Andric             continue;
726e8d8bef9SDimitry Andric           MCRegister Reg = MO.getReg().asMCReg();
7270b57cec5SDimitry Andric           if (!Reg)
7280b57cec5SDimitry Andric             continue;
72981ad6265SDimitry Andric           Tracker.clobberRegister(Reg, *TRI, *TII, UseCopyInstr);
7300b57cec5SDimitry Andric         }
7310b57cec5SDimitry Andric 
73281ad6265SDimitry Andric         Tracker.trackCopy(&MI, *TRI, *TII, UseCopyInstr);
7330b57cec5SDimitry Andric 
7340b57cec5SDimitry Andric         continue;
7350b57cec5SDimitry Andric       }
73681ad6265SDimitry Andric     }
7370b57cec5SDimitry Andric 
7380b57cec5SDimitry Andric     // Clobber any earlyclobber regs first.
739349cc55cSDimitry Andric     for (const MachineOperand &MO : MI.operands())
7400b57cec5SDimitry Andric       if (MO.isReg() && MO.isEarlyClobber()) {
741e8d8bef9SDimitry Andric         MCRegister Reg = MO.getReg().asMCReg();
7420b57cec5SDimitry Andric         // If we have a tied earlyclobber, that means it is also read by this
7430b57cec5SDimitry Andric         // instruction, so we need to make sure we don't remove it as dead
7440b57cec5SDimitry Andric         // later.
7450b57cec5SDimitry Andric         if (MO.isTied())
746349cc55cSDimitry Andric           ReadRegister(Reg, MI, RegularUse);
74781ad6265SDimitry Andric         Tracker.clobberRegister(Reg, *TRI, *TII, UseCopyInstr);
7480b57cec5SDimitry Andric       }
7490b57cec5SDimitry Andric 
750349cc55cSDimitry Andric     forwardUses(MI);
7510b57cec5SDimitry Andric 
7520b57cec5SDimitry Andric     // Not a copy.
753e8d8bef9SDimitry Andric     SmallVector<Register, 2> Defs;
7540b57cec5SDimitry Andric     const MachineOperand *RegMask = nullptr;
755349cc55cSDimitry Andric     for (const MachineOperand &MO : MI.operands()) {
7560b57cec5SDimitry Andric       if (MO.isRegMask())
7570b57cec5SDimitry Andric         RegMask = &MO;
7580b57cec5SDimitry Andric       if (!MO.isReg())
7590b57cec5SDimitry Andric         continue;
7608bcb0991SDimitry Andric       Register Reg = MO.getReg();
7610b57cec5SDimitry Andric       if (!Reg)
7620b57cec5SDimitry Andric         continue;
7630b57cec5SDimitry Andric 
764e8d8bef9SDimitry Andric       assert(!Reg.isVirtual() &&
7650b57cec5SDimitry Andric              "MachineCopyPropagation should be run after register allocation!");
7660b57cec5SDimitry Andric 
7670b57cec5SDimitry Andric       if (MO.isDef() && !MO.isEarlyClobber()) {
768e8d8bef9SDimitry Andric         Defs.push_back(Reg.asMCReg());
7690b57cec5SDimitry Andric         continue;
7708bcb0991SDimitry Andric       } else if (MO.readsReg())
771349cc55cSDimitry Andric         ReadRegister(Reg.asMCReg(), MI, MO.isDebug() ? DebugUse : RegularUse);
7720b57cec5SDimitry Andric     }
7730b57cec5SDimitry Andric 
7740b57cec5SDimitry Andric     // The instruction has a register mask operand which means that it clobbers
7750b57cec5SDimitry Andric     // a large set of registers.  Treat clobbered registers the same way as
7760b57cec5SDimitry Andric     // defined registers.
7770b57cec5SDimitry Andric     if (RegMask) {
7780b57cec5SDimitry Andric       // Erase any MaybeDeadCopies whose destination register is clobbered.
7790b57cec5SDimitry Andric       for (SmallSetVector<MachineInstr *, 8>::iterator DI =
7800b57cec5SDimitry Andric                MaybeDeadCopies.begin();
7810b57cec5SDimitry Andric            DI != MaybeDeadCopies.end();) {
7820b57cec5SDimitry Andric         MachineInstr *MaybeDead = *DI;
783*bdd1243dSDimitry Andric         std::optional<DestSourcePair> CopyOperands =
78481ad6265SDimitry Andric             isCopyInstr(*MaybeDead, *TII, UseCopyInstr);
78581ad6265SDimitry Andric         MCRegister Reg = CopyOperands->Destination->getReg().asMCReg();
7860b57cec5SDimitry Andric         assert(!MRI->isReserved(Reg));
7870b57cec5SDimitry Andric 
7880b57cec5SDimitry Andric         if (!RegMask->clobbersPhysReg(Reg)) {
7890b57cec5SDimitry Andric           ++DI;
7900b57cec5SDimitry Andric           continue;
7910b57cec5SDimitry Andric         }
7920b57cec5SDimitry Andric 
7930b57cec5SDimitry Andric         LLVM_DEBUG(dbgs() << "MCP: Removing copy due to regmask clobbering: ";
7940b57cec5SDimitry Andric                    MaybeDead->dump());
7950b57cec5SDimitry Andric 
7960b57cec5SDimitry Andric         // Make sure we invalidate any entries in the copy maps before erasing
7970b57cec5SDimitry Andric         // the instruction.
79881ad6265SDimitry Andric         Tracker.clobberRegister(Reg, *TRI, *TII, UseCopyInstr);
7990b57cec5SDimitry Andric 
8000b57cec5SDimitry Andric         // erase() will return the next valid iterator pointing to the next
8010b57cec5SDimitry Andric         // element after the erased one.
8020b57cec5SDimitry Andric         DI = MaybeDeadCopies.erase(DI);
8030b57cec5SDimitry Andric         MaybeDead->eraseFromParent();
8040b57cec5SDimitry Andric         Changed = true;
8050b57cec5SDimitry Andric         ++NumDeletes;
8060b57cec5SDimitry Andric       }
8070b57cec5SDimitry Andric     }
8080b57cec5SDimitry Andric 
8090b57cec5SDimitry Andric     // Any previous copy definition or reading the Defs is no longer available.
810e8d8bef9SDimitry Andric     for (MCRegister Reg : Defs)
81181ad6265SDimitry Andric       Tracker.clobberRegister(Reg, *TRI, *TII, UseCopyInstr);
8120b57cec5SDimitry Andric   }
8130b57cec5SDimitry Andric 
8140b57cec5SDimitry Andric   // If MBB doesn't have successors, delete the copies whose defs are not used.
8150b57cec5SDimitry Andric   // If MBB does have successors, then conservative assume the defs are live-out
8160b57cec5SDimitry Andric   // since we don't want to trust live-in lists.
8170b57cec5SDimitry Andric   if (MBB.succ_empty()) {
8180b57cec5SDimitry Andric     for (MachineInstr *MaybeDead : MaybeDeadCopies) {
8190b57cec5SDimitry Andric       LLVM_DEBUG(dbgs() << "MCP: Removing copy due to no live-out succ: ";
8200b57cec5SDimitry Andric                  MaybeDead->dump());
82181ad6265SDimitry Andric 
822*bdd1243dSDimitry Andric       std::optional<DestSourcePair> CopyOperands =
82381ad6265SDimitry Andric           isCopyInstr(*MaybeDead, *TII, UseCopyInstr);
82481ad6265SDimitry Andric       assert(CopyOperands);
82581ad6265SDimitry Andric 
82681ad6265SDimitry Andric       Register SrcReg = CopyOperands->Source->getReg();
82781ad6265SDimitry Andric       Register DestReg = CopyOperands->Destination->getReg();
82881ad6265SDimitry Andric       assert(!MRI->isReserved(DestReg));
8290b57cec5SDimitry Andric 
8308bcb0991SDimitry Andric       // Update matching debug values, if any.
831fe6060f1SDimitry Andric       SmallVector<MachineInstr *> MaybeDeadDbgUsers(
832fe6060f1SDimitry Andric           CopyDbgUsers[MaybeDead].begin(), CopyDbgUsers[MaybeDead].end());
833fe6060f1SDimitry Andric       MRI->updateDbgUsersToReg(DestReg.asMCReg(), SrcReg.asMCReg(),
834fe6060f1SDimitry Andric                                MaybeDeadDbgUsers);
8350b57cec5SDimitry Andric 
8360b57cec5SDimitry Andric       MaybeDead->eraseFromParent();
8370b57cec5SDimitry Andric       Changed = true;
8380b57cec5SDimitry Andric       ++NumDeletes;
8390b57cec5SDimitry Andric     }
8400b57cec5SDimitry Andric   }
8410b57cec5SDimitry Andric 
8420b57cec5SDimitry Andric   MaybeDeadCopies.clear();
8438bcb0991SDimitry Andric   CopyDbgUsers.clear();
8440b57cec5SDimitry Andric   Tracker.clear();
8450b57cec5SDimitry Andric }
8460b57cec5SDimitry Andric 
847480093f4SDimitry Andric static bool isBackwardPropagatableCopy(MachineInstr &MI,
84881ad6265SDimitry Andric                                        const MachineRegisterInfo &MRI,
84981ad6265SDimitry Andric                                        const TargetInstrInfo &TII,
85081ad6265SDimitry Andric                                        bool UseCopyInstr) {
851*bdd1243dSDimitry Andric   std::optional<DestSourcePair> CopyOperands =
852*bdd1243dSDimitry Andric       isCopyInstr(MI, TII, UseCopyInstr);
85381ad6265SDimitry Andric   assert(CopyOperands && "MI is expected to be a COPY");
85481ad6265SDimitry Andric 
85581ad6265SDimitry Andric   Register Def = CopyOperands->Destination->getReg();
85681ad6265SDimitry Andric   Register Src = CopyOperands->Source->getReg();
857480093f4SDimitry Andric 
858480093f4SDimitry Andric   if (!Def || !Src)
859480093f4SDimitry Andric     return false;
860480093f4SDimitry Andric 
861480093f4SDimitry Andric   if (MRI.isReserved(Def) || MRI.isReserved(Src))
862480093f4SDimitry Andric     return false;
863480093f4SDimitry Andric 
86481ad6265SDimitry Andric   return CopyOperands->Source->isRenamable() && CopyOperands->Source->isKill();
865480093f4SDimitry Andric }
866480093f4SDimitry Andric 
867480093f4SDimitry Andric void MachineCopyPropagation::propagateDefs(MachineInstr &MI) {
868480093f4SDimitry Andric   if (!Tracker.hasAnyCopies())
869480093f4SDimitry Andric     return;
870480093f4SDimitry Andric 
871480093f4SDimitry Andric   for (unsigned OpIdx = 0, OpEnd = MI.getNumOperands(); OpIdx != OpEnd;
872480093f4SDimitry Andric        ++OpIdx) {
873480093f4SDimitry Andric     MachineOperand &MODef = MI.getOperand(OpIdx);
874480093f4SDimitry Andric 
875480093f4SDimitry Andric     if (!MODef.isReg() || MODef.isUse())
876480093f4SDimitry Andric       continue;
877480093f4SDimitry Andric 
878480093f4SDimitry Andric     // Ignore non-trivial cases.
879480093f4SDimitry Andric     if (MODef.isTied() || MODef.isUndef() || MODef.isImplicit())
880480093f4SDimitry Andric       continue;
881480093f4SDimitry Andric 
882480093f4SDimitry Andric     if (!MODef.getReg())
883480093f4SDimitry Andric       continue;
884480093f4SDimitry Andric 
885480093f4SDimitry Andric     // We only handle if the register comes from a vreg.
886480093f4SDimitry Andric     if (!MODef.isRenamable())
887480093f4SDimitry Andric       continue;
888480093f4SDimitry Andric 
88981ad6265SDimitry Andric     MachineInstr *Copy = Tracker.findAvailBackwardCopy(
89081ad6265SDimitry Andric         MI, MODef.getReg().asMCReg(), *TRI, *TII, UseCopyInstr);
891480093f4SDimitry Andric     if (!Copy)
892480093f4SDimitry Andric       continue;
893480093f4SDimitry Andric 
894*bdd1243dSDimitry Andric     std::optional<DestSourcePair> CopyOperands =
89581ad6265SDimitry Andric         isCopyInstr(*Copy, *TII, UseCopyInstr);
89681ad6265SDimitry Andric     Register Def = CopyOperands->Destination->getReg();
89781ad6265SDimitry Andric     Register Src = CopyOperands->Source->getReg();
898480093f4SDimitry Andric 
899480093f4SDimitry Andric     if (MODef.getReg() != Src)
900480093f4SDimitry Andric       continue;
901480093f4SDimitry Andric 
902480093f4SDimitry Andric     if (!isBackwardPropagatableRegClassCopy(*Copy, MI, OpIdx))
903480093f4SDimitry Andric       continue;
904480093f4SDimitry Andric 
905480093f4SDimitry Andric     if (hasImplicitOverlap(MI, MODef))
906480093f4SDimitry Andric       continue;
907480093f4SDimitry Andric 
908e8d8bef9SDimitry Andric     if (hasOverlappingMultipleDef(MI, MODef, Def))
909e8d8bef9SDimitry Andric       continue;
910e8d8bef9SDimitry Andric 
911480093f4SDimitry Andric     LLVM_DEBUG(dbgs() << "MCP: Replacing " << printReg(MODef.getReg(), TRI)
912480093f4SDimitry Andric                       << "\n     with " << printReg(Def, TRI) << "\n     in "
913480093f4SDimitry Andric                       << MI << "     from " << *Copy);
914480093f4SDimitry Andric 
915480093f4SDimitry Andric     MODef.setReg(Def);
91681ad6265SDimitry Andric     MODef.setIsRenamable(CopyOperands->Destination->isRenamable());
917480093f4SDimitry Andric 
918480093f4SDimitry Andric     LLVM_DEBUG(dbgs() << "MCP: After replacement: " << MI << "\n");
919480093f4SDimitry Andric     MaybeDeadCopies.insert(Copy);
920480093f4SDimitry Andric     Changed = true;
921480093f4SDimitry Andric     ++NumCopyBackwardPropagated;
922480093f4SDimitry Andric   }
923480093f4SDimitry Andric }
924480093f4SDimitry Andric 
925480093f4SDimitry Andric void MachineCopyPropagation::BackwardCopyPropagateBlock(
926480093f4SDimitry Andric     MachineBasicBlock &MBB) {
927480093f4SDimitry Andric   LLVM_DEBUG(dbgs() << "MCP: BackwardCopyPropagateBlock " << MBB.getName()
928480093f4SDimitry Andric                     << "\n");
929480093f4SDimitry Andric 
9300eae32dcSDimitry Andric   for (MachineInstr &MI : llvm::make_early_inc_range(llvm::reverse(MBB))) {
931480093f4SDimitry Andric     // Ignore non-trivial COPYs.
932*bdd1243dSDimitry Andric     std::optional<DestSourcePair> CopyOperands =
933*bdd1243dSDimitry Andric         isCopyInstr(MI, *TII, UseCopyInstr);
93481ad6265SDimitry Andric     if (CopyOperands && MI.getNumOperands() == 2) {
93581ad6265SDimitry Andric       Register DefReg = CopyOperands->Destination->getReg();
93681ad6265SDimitry Andric       Register SrcReg = CopyOperands->Source->getReg();
937480093f4SDimitry Andric 
93881ad6265SDimitry Andric       if (!TRI->regsOverlap(DefReg, SrcReg)) {
93981ad6265SDimitry Andric         MCRegister Def = DefReg.asMCReg();
94081ad6265SDimitry Andric         MCRegister Src = SrcReg.asMCReg();
941480093f4SDimitry Andric 
942480093f4SDimitry Andric         // Unlike forward cp, we don't invoke propagateDefs here,
943480093f4SDimitry Andric         // just let forward cp do COPY-to-COPY propagation.
94481ad6265SDimitry Andric         if (isBackwardPropagatableCopy(MI, *MRI, *TII, UseCopyInstr)) {
94581ad6265SDimitry Andric           Tracker.invalidateRegister(Src, *TRI, *TII, UseCopyInstr);
94681ad6265SDimitry Andric           Tracker.invalidateRegister(Def, *TRI, *TII, UseCopyInstr);
94781ad6265SDimitry Andric           Tracker.trackCopy(&MI, *TRI, *TII, UseCopyInstr);
948480093f4SDimitry Andric           continue;
949480093f4SDimitry Andric         }
950480093f4SDimitry Andric       }
95181ad6265SDimitry Andric     }
952480093f4SDimitry Andric 
953480093f4SDimitry Andric     // Invalidate any earlyclobber regs first.
9540eae32dcSDimitry Andric     for (const MachineOperand &MO : MI.operands())
955480093f4SDimitry Andric       if (MO.isReg() && MO.isEarlyClobber()) {
956e8d8bef9SDimitry Andric         MCRegister Reg = MO.getReg().asMCReg();
957480093f4SDimitry Andric         if (!Reg)
958480093f4SDimitry Andric           continue;
95981ad6265SDimitry Andric         Tracker.invalidateRegister(Reg, *TRI, *TII, UseCopyInstr);
960480093f4SDimitry Andric       }
961480093f4SDimitry Andric 
9620eae32dcSDimitry Andric     propagateDefs(MI);
9630eae32dcSDimitry Andric     for (const MachineOperand &MO : MI.operands()) {
964480093f4SDimitry Andric       if (!MO.isReg())
965480093f4SDimitry Andric         continue;
966480093f4SDimitry Andric 
967480093f4SDimitry Andric       if (!MO.getReg())
968480093f4SDimitry Andric         continue;
969480093f4SDimitry Andric 
970480093f4SDimitry Andric       if (MO.isDef())
97181ad6265SDimitry Andric         Tracker.invalidateRegister(MO.getReg().asMCReg(), *TRI, *TII,
97281ad6265SDimitry Andric                                    UseCopyInstr);
973480093f4SDimitry Andric 
974fe6060f1SDimitry Andric       if (MO.readsReg()) {
975fe6060f1SDimitry Andric         if (MO.isDebug()) {
976fe6060f1SDimitry Andric           //  Check if the register in the debug instruction is utilized
977fe6060f1SDimitry Andric           // in a copy instruction, so we can update the debug info if the
978fe6060f1SDimitry Andric           // register is changed.
979fe6060f1SDimitry Andric           for (MCRegUnitIterator RUI(MO.getReg().asMCReg(), TRI); RUI.isValid();
980fe6060f1SDimitry Andric                ++RUI) {
981fe6060f1SDimitry Andric             if (auto *Copy = Tracker.findCopyDefViaUnit(*RUI, *TRI)) {
9820eae32dcSDimitry Andric               CopyDbgUsers[Copy].insert(&MI);
983fe6060f1SDimitry Andric             }
984fe6060f1SDimitry Andric           }
985fe6060f1SDimitry Andric         } else {
98681ad6265SDimitry Andric           Tracker.invalidateRegister(MO.getReg().asMCReg(), *TRI, *TII,
98781ad6265SDimitry Andric                                      UseCopyInstr);
988480093f4SDimitry Andric         }
989480093f4SDimitry Andric       }
990fe6060f1SDimitry Andric     }
991fe6060f1SDimitry Andric   }
992480093f4SDimitry Andric 
993480093f4SDimitry Andric   for (auto *Copy : MaybeDeadCopies) {
994*bdd1243dSDimitry Andric     std::optional<DestSourcePair> CopyOperands =
99581ad6265SDimitry Andric         isCopyInstr(*Copy, *TII, UseCopyInstr);
99681ad6265SDimitry Andric     Register Src = CopyOperands->Source->getReg();
99781ad6265SDimitry Andric     Register Def = CopyOperands->Destination->getReg();
998fe6060f1SDimitry Andric     SmallVector<MachineInstr *> MaybeDeadDbgUsers(CopyDbgUsers[Copy].begin(),
999fe6060f1SDimitry Andric                                                   CopyDbgUsers[Copy].end());
1000fe6060f1SDimitry Andric 
1001fe6060f1SDimitry Andric     MRI->updateDbgUsersToReg(Src.asMCReg(), Def.asMCReg(), MaybeDeadDbgUsers);
1002480093f4SDimitry Andric     Copy->eraseFromParent();
1003480093f4SDimitry Andric     ++NumDeletes;
1004480093f4SDimitry Andric   }
1005480093f4SDimitry Andric 
1006480093f4SDimitry Andric   MaybeDeadCopies.clear();
1007480093f4SDimitry Andric   CopyDbgUsers.clear();
1008480093f4SDimitry Andric   Tracker.clear();
1009480093f4SDimitry Andric }
1010480093f4SDimitry Andric 
10110b57cec5SDimitry Andric bool MachineCopyPropagation::runOnMachineFunction(MachineFunction &MF) {
10120b57cec5SDimitry Andric   if (skipFunction(MF.getFunction()))
10130b57cec5SDimitry Andric     return false;
10140b57cec5SDimitry Andric 
10150b57cec5SDimitry Andric   Changed = false;
10160b57cec5SDimitry Andric 
10170b57cec5SDimitry Andric   TRI = MF.getSubtarget().getRegisterInfo();
10180b57cec5SDimitry Andric   TII = MF.getSubtarget().getInstrInfo();
10190b57cec5SDimitry Andric   MRI = &MF.getRegInfo();
10200b57cec5SDimitry Andric 
1021480093f4SDimitry Andric   for (MachineBasicBlock &MBB : MF) {
1022480093f4SDimitry Andric     BackwardCopyPropagateBlock(MBB);
1023480093f4SDimitry Andric     ForwardCopyPropagateBlock(MBB);
1024480093f4SDimitry Andric   }
10250b57cec5SDimitry Andric 
10260b57cec5SDimitry Andric   return Changed;
10270b57cec5SDimitry Andric }
102881ad6265SDimitry Andric 
102981ad6265SDimitry Andric MachineFunctionPass *
103081ad6265SDimitry Andric llvm::createMachineCopyPropagationPass(bool UseCopyInstr = false) {
103181ad6265SDimitry Andric   return new MachineCopyPropagation(UseCopyInstr);
103281ad6265SDimitry Andric }
1033