xref: /aosp_15_r20/external/llvm/lib/CodeGen/MachineCopyPropagation.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===- MachineCopyPropagation.cpp - Machine Copy Propagation Pass ---------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // This is an extremely simple MachineInstr-level copy propagation pass.
11*9880d681SAndroid Build Coastguard Worker //
12*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
13*9880d681SAndroid Build Coastguard Worker 
14*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/Passes.h"
15*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/DenseMap.h"
16*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/SetVector.h"
17*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/SmallVector.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/Statistic.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineFunction.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineFunctionPass.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineRegisterInfo.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/Pass.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Debug.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
25*9880d681SAndroid Build Coastguard Worker #include "llvm/Target/TargetInstrInfo.h"
26*9880d681SAndroid Build Coastguard Worker #include "llvm/Target/TargetRegisterInfo.h"
27*9880d681SAndroid Build Coastguard Worker #include "llvm/Target/TargetSubtargetInfo.h"
28*9880d681SAndroid Build Coastguard Worker using namespace llvm;
29*9880d681SAndroid Build Coastguard Worker 
30*9880d681SAndroid Build Coastguard Worker #define DEBUG_TYPE "codegen-cp"
31*9880d681SAndroid Build Coastguard Worker 
32*9880d681SAndroid Build Coastguard Worker STATISTIC(NumDeletes, "Number of dead copies deleted");
33*9880d681SAndroid Build Coastguard Worker 
34*9880d681SAndroid Build Coastguard Worker namespace {
35*9880d681SAndroid Build Coastguard Worker   typedef SmallVector<unsigned, 4> RegList;
36*9880d681SAndroid Build Coastguard Worker   typedef DenseMap<unsigned, RegList> SourceMap;
37*9880d681SAndroid Build Coastguard Worker   typedef DenseMap<unsigned, MachineInstr*> Reg2MIMap;
38*9880d681SAndroid Build Coastguard Worker 
39*9880d681SAndroid Build Coastguard Worker   class MachineCopyPropagation : public MachineFunctionPass {
40*9880d681SAndroid Build Coastguard Worker     const TargetRegisterInfo *TRI;
41*9880d681SAndroid Build Coastguard Worker     const TargetInstrInfo *TII;
42*9880d681SAndroid Build Coastguard Worker     const MachineRegisterInfo *MRI;
43*9880d681SAndroid Build Coastguard Worker 
44*9880d681SAndroid Build Coastguard Worker   public:
45*9880d681SAndroid Build Coastguard Worker     static char ID; // Pass identification, replacement for typeid
MachineCopyPropagation()46*9880d681SAndroid Build Coastguard Worker     MachineCopyPropagation() : MachineFunctionPass(ID) {
47*9880d681SAndroid Build Coastguard Worker       initializeMachineCopyPropagationPass(*PassRegistry::getPassRegistry());
48*9880d681SAndroid Build Coastguard Worker     }
49*9880d681SAndroid Build Coastguard Worker 
getAnalysisUsage(AnalysisUsage & AU) const50*9880d681SAndroid Build Coastguard Worker     void getAnalysisUsage(AnalysisUsage &AU) const override {
51*9880d681SAndroid Build Coastguard Worker       AU.setPreservesCFG();
52*9880d681SAndroid Build Coastguard Worker       MachineFunctionPass::getAnalysisUsage(AU);
53*9880d681SAndroid Build Coastguard Worker     }
54*9880d681SAndroid Build Coastguard Worker 
55*9880d681SAndroid Build Coastguard Worker     bool runOnMachineFunction(MachineFunction &MF) override;
56*9880d681SAndroid Build Coastguard Worker 
getRequiredProperties() const57*9880d681SAndroid Build Coastguard Worker     MachineFunctionProperties getRequiredProperties() const override {
58*9880d681SAndroid Build Coastguard Worker       return MachineFunctionProperties().set(
59*9880d681SAndroid Build Coastguard Worker           MachineFunctionProperties::Property::AllVRegsAllocated);
60*9880d681SAndroid Build Coastguard Worker     }
61*9880d681SAndroid Build Coastguard Worker 
62*9880d681SAndroid Build Coastguard Worker   private:
63*9880d681SAndroid Build Coastguard Worker     void ClobberRegister(unsigned Reg);
64*9880d681SAndroid Build Coastguard Worker     void CopyPropagateBlock(MachineBasicBlock &MBB);
65*9880d681SAndroid Build Coastguard Worker     bool eraseIfRedundant(MachineInstr &Copy, unsigned Src, unsigned Def);
66*9880d681SAndroid Build Coastguard Worker 
67*9880d681SAndroid Build Coastguard Worker     /// Candidates for deletion.
68*9880d681SAndroid Build Coastguard Worker     SmallSetVector<MachineInstr*, 8> MaybeDeadCopies;
69*9880d681SAndroid Build Coastguard Worker     /// Def -> available copies map.
70*9880d681SAndroid Build Coastguard Worker     Reg2MIMap AvailCopyMap;
71*9880d681SAndroid Build Coastguard Worker     /// Def -> copies map.
72*9880d681SAndroid Build Coastguard Worker     Reg2MIMap CopyMap;
73*9880d681SAndroid Build Coastguard Worker     /// Src -> Def map
74*9880d681SAndroid Build Coastguard Worker     SourceMap SrcMap;
75*9880d681SAndroid Build Coastguard Worker     bool Changed;
76*9880d681SAndroid Build Coastguard Worker   };
77*9880d681SAndroid Build Coastguard Worker }
78*9880d681SAndroid Build Coastguard Worker char MachineCopyPropagation::ID = 0;
79*9880d681SAndroid Build Coastguard Worker char &llvm::MachineCopyPropagationID = MachineCopyPropagation::ID;
80*9880d681SAndroid Build Coastguard Worker 
81*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS(MachineCopyPropagation, "machine-cp",
82*9880d681SAndroid Build Coastguard Worker                 "Machine Copy Propagation Pass", false, false)
83*9880d681SAndroid Build Coastguard Worker 
84*9880d681SAndroid Build Coastguard Worker /// Remove any entry in \p Map where the register is a subregister or equal to
85*9880d681SAndroid Build Coastguard Worker /// a register contained in \p Regs.
removeRegsFromMap(Reg2MIMap & Map,const RegList & Regs,const TargetRegisterInfo & TRI)86*9880d681SAndroid Build Coastguard Worker static void removeRegsFromMap(Reg2MIMap &Map, const RegList &Regs,
87*9880d681SAndroid Build Coastguard Worker                               const TargetRegisterInfo &TRI) {
88*9880d681SAndroid Build Coastguard Worker   for (unsigned Reg : Regs) {
89*9880d681SAndroid Build Coastguard Worker     // Source of copy is no longer available for propagation.
90*9880d681SAndroid Build Coastguard Worker     for (MCSubRegIterator SR(Reg, &TRI, true); SR.isValid(); ++SR)
91*9880d681SAndroid Build Coastguard Worker       Map.erase(*SR);
92*9880d681SAndroid Build Coastguard Worker   }
93*9880d681SAndroid Build Coastguard Worker }
94*9880d681SAndroid Build Coastguard Worker 
95*9880d681SAndroid Build Coastguard Worker /// Remove any entry in \p Map that is marked clobbered in \p RegMask.
96*9880d681SAndroid Build Coastguard Worker /// The map will typically have a lot fewer entries than the regmask clobbers,
97*9880d681SAndroid Build Coastguard Worker /// so this is more efficient than iterating the clobbered registers and calling
98*9880d681SAndroid Build Coastguard Worker /// ClobberRegister() on them.
removeClobberedRegsFromMap(Reg2MIMap & Map,const MachineOperand & RegMask)99*9880d681SAndroid Build Coastguard Worker static void removeClobberedRegsFromMap(Reg2MIMap &Map,
100*9880d681SAndroid Build Coastguard Worker                                        const MachineOperand &RegMask) {
101*9880d681SAndroid Build Coastguard Worker   for (Reg2MIMap::iterator I = Map.begin(), E = Map.end(), Next; I != E;
102*9880d681SAndroid Build Coastguard Worker        I = Next) {
103*9880d681SAndroid Build Coastguard Worker     Next = std::next(I);
104*9880d681SAndroid Build Coastguard Worker     unsigned Reg = I->first;
105*9880d681SAndroid Build Coastguard Worker     if (RegMask.clobbersPhysReg(Reg))
106*9880d681SAndroid Build Coastguard Worker       Map.erase(I);
107*9880d681SAndroid Build Coastguard Worker   }
108*9880d681SAndroid Build Coastguard Worker }
109*9880d681SAndroid Build Coastguard Worker 
ClobberRegister(unsigned Reg)110*9880d681SAndroid Build Coastguard Worker void MachineCopyPropagation::ClobberRegister(unsigned Reg) {
111*9880d681SAndroid Build Coastguard Worker   for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI) {
112*9880d681SAndroid Build Coastguard Worker     CopyMap.erase(*AI);
113*9880d681SAndroid Build Coastguard Worker     AvailCopyMap.erase(*AI);
114*9880d681SAndroid Build Coastguard Worker 
115*9880d681SAndroid Build Coastguard Worker     SourceMap::iterator SI = SrcMap.find(*AI);
116*9880d681SAndroid Build Coastguard Worker     if (SI != SrcMap.end()) {
117*9880d681SAndroid Build Coastguard Worker       removeRegsFromMap(AvailCopyMap, SI->second, *TRI);
118*9880d681SAndroid Build Coastguard Worker       SrcMap.erase(SI);
119*9880d681SAndroid Build Coastguard Worker     }
120*9880d681SAndroid Build Coastguard Worker   }
121*9880d681SAndroid Build Coastguard Worker }
122*9880d681SAndroid Build Coastguard Worker 
123*9880d681SAndroid Build Coastguard Worker /// Return true if \p PreviousCopy did copy register \p Src to register \p Def.
124*9880d681SAndroid Build Coastguard Worker /// This fact may have been obscured by sub register usage or may not be true at
125*9880d681SAndroid Build Coastguard Worker /// all even though Src and Def are subregisters of the registers used in
126*9880d681SAndroid Build Coastguard Worker /// PreviousCopy. e.g.
127*9880d681SAndroid Build Coastguard Worker /// isNopCopy("ecx = COPY eax", AX, CX) == true
128*9880d681SAndroid Build Coastguard Worker /// isNopCopy("ecx = COPY eax", AH, CL) == false
isNopCopy(const MachineInstr & PreviousCopy,unsigned Src,unsigned Def,const TargetRegisterInfo * TRI)129*9880d681SAndroid Build Coastguard Worker static bool isNopCopy(const MachineInstr &PreviousCopy, unsigned Src,
130*9880d681SAndroid Build Coastguard Worker                       unsigned Def, const TargetRegisterInfo *TRI) {
131*9880d681SAndroid Build Coastguard Worker   unsigned PreviousSrc = PreviousCopy.getOperand(1).getReg();
132*9880d681SAndroid Build Coastguard Worker   unsigned PreviousDef = PreviousCopy.getOperand(0).getReg();
133*9880d681SAndroid Build Coastguard Worker   if (Src == PreviousSrc) {
134*9880d681SAndroid Build Coastguard Worker     assert(Def == PreviousDef);
135*9880d681SAndroid Build Coastguard Worker     return true;
136*9880d681SAndroid Build Coastguard Worker   }
137*9880d681SAndroid Build Coastguard Worker   if (!TRI->isSubRegister(PreviousSrc, Src))
138*9880d681SAndroid Build Coastguard Worker     return false;
139*9880d681SAndroid Build Coastguard Worker   unsigned SubIdx = TRI->getSubRegIndex(PreviousSrc, Src);
140*9880d681SAndroid Build Coastguard Worker   return SubIdx == TRI->getSubRegIndex(PreviousDef, Def);
141*9880d681SAndroid Build Coastguard Worker }
142*9880d681SAndroid Build Coastguard Worker 
143*9880d681SAndroid Build Coastguard Worker /// Remove instruction \p Copy if there exists a previous copy that copies the
144*9880d681SAndroid Build Coastguard Worker /// register \p Src to the register \p Def; This may happen indirectly by
145*9880d681SAndroid Build Coastguard Worker /// copying the super registers.
eraseIfRedundant(MachineInstr & Copy,unsigned Src,unsigned Def)146*9880d681SAndroid Build Coastguard Worker bool MachineCopyPropagation::eraseIfRedundant(MachineInstr &Copy, unsigned Src,
147*9880d681SAndroid Build Coastguard Worker                                               unsigned Def) {
148*9880d681SAndroid Build Coastguard Worker   // Avoid eliminating a copy from/to a reserved registers as we cannot predict
149*9880d681SAndroid Build Coastguard Worker   // the value (Example: The sparc zero register is writable but stays zero).
150*9880d681SAndroid Build Coastguard Worker   if (MRI->isReserved(Src) || MRI->isReserved(Def))
151*9880d681SAndroid Build Coastguard Worker     return false;
152*9880d681SAndroid Build Coastguard Worker 
153*9880d681SAndroid Build Coastguard Worker   // Search for an existing copy.
154*9880d681SAndroid Build Coastguard Worker   Reg2MIMap::iterator CI = AvailCopyMap.find(Def);
155*9880d681SAndroid Build Coastguard Worker   if (CI == AvailCopyMap.end())
156*9880d681SAndroid Build Coastguard Worker     return false;
157*9880d681SAndroid Build Coastguard Worker 
158*9880d681SAndroid Build Coastguard Worker   // Check that the existing copy uses the correct sub registers.
159*9880d681SAndroid Build Coastguard Worker   MachineInstr &PrevCopy = *CI->second;
160*9880d681SAndroid Build Coastguard Worker   if (!isNopCopy(PrevCopy, Src, Def, TRI))
161*9880d681SAndroid Build Coastguard Worker     return false;
162*9880d681SAndroid Build Coastguard Worker 
163*9880d681SAndroid Build Coastguard Worker   DEBUG(dbgs() << "MCP: copy is a NOP, removing: "; Copy.dump());
164*9880d681SAndroid Build Coastguard Worker 
165*9880d681SAndroid Build Coastguard Worker   // Copy was redundantly redefining either Src or Def. Remove earlier kill
166*9880d681SAndroid Build Coastguard Worker   // flags between Copy and PrevCopy because the value will be reused now.
167*9880d681SAndroid Build Coastguard Worker   assert(Copy.isCopy());
168*9880d681SAndroid Build Coastguard Worker   unsigned CopyDef = Copy.getOperand(0).getReg();
169*9880d681SAndroid Build Coastguard Worker   assert(CopyDef == Src || CopyDef == Def);
170*9880d681SAndroid Build Coastguard Worker   for (MachineInstr &MI :
171*9880d681SAndroid Build Coastguard Worker        make_range(PrevCopy.getIterator(), Copy.getIterator()))
172*9880d681SAndroid Build Coastguard Worker     MI.clearRegisterKills(CopyDef, TRI);
173*9880d681SAndroid Build Coastguard Worker 
174*9880d681SAndroid Build Coastguard Worker   Copy.eraseFromParent();
175*9880d681SAndroid Build Coastguard Worker   Changed = true;
176*9880d681SAndroid Build Coastguard Worker   ++NumDeletes;
177*9880d681SAndroid Build Coastguard Worker   return true;
178*9880d681SAndroid Build Coastguard Worker }
179*9880d681SAndroid Build Coastguard Worker 
CopyPropagateBlock(MachineBasicBlock & MBB)180*9880d681SAndroid Build Coastguard Worker void MachineCopyPropagation::CopyPropagateBlock(MachineBasicBlock &MBB) {
181*9880d681SAndroid Build Coastguard Worker   DEBUG(dbgs() << "MCP: CopyPropagateBlock " << MBB.getName() << "\n");
182*9880d681SAndroid Build Coastguard Worker 
183*9880d681SAndroid Build Coastguard Worker   for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end(); I != E; ) {
184*9880d681SAndroid Build Coastguard Worker     MachineInstr *MI = &*I;
185*9880d681SAndroid Build Coastguard Worker     ++I;
186*9880d681SAndroid Build Coastguard Worker 
187*9880d681SAndroid Build Coastguard Worker     if (MI->isCopy()) {
188*9880d681SAndroid Build Coastguard Worker       unsigned Def = MI->getOperand(0).getReg();
189*9880d681SAndroid Build Coastguard Worker       unsigned Src = MI->getOperand(1).getReg();
190*9880d681SAndroid Build Coastguard Worker 
191*9880d681SAndroid Build Coastguard Worker       assert(!TargetRegisterInfo::isVirtualRegister(Def) &&
192*9880d681SAndroid Build Coastguard Worker              !TargetRegisterInfo::isVirtualRegister(Src) &&
193*9880d681SAndroid Build Coastguard Worker              "MachineCopyPropagation should be run after register allocation!");
194*9880d681SAndroid Build Coastguard Worker 
195*9880d681SAndroid Build Coastguard Worker       // The two copies cancel out and the source of the first copy
196*9880d681SAndroid Build Coastguard Worker       // hasn't been overridden, eliminate the second one. e.g.
197*9880d681SAndroid Build Coastguard Worker       //  %ECX<def> = COPY %EAX
198*9880d681SAndroid Build Coastguard Worker       //  ... nothing clobbered EAX.
199*9880d681SAndroid Build Coastguard Worker       //  %EAX<def> = COPY %ECX
200*9880d681SAndroid Build Coastguard Worker       // =>
201*9880d681SAndroid Build Coastguard Worker       //  %ECX<def> = COPY %EAX
202*9880d681SAndroid Build Coastguard Worker       //
203*9880d681SAndroid Build Coastguard Worker       // or
204*9880d681SAndroid Build Coastguard Worker       //
205*9880d681SAndroid Build Coastguard Worker       //  %ECX<def> = COPY %EAX
206*9880d681SAndroid Build Coastguard Worker       //  ... nothing clobbered EAX.
207*9880d681SAndroid Build Coastguard Worker       //  %ECX<def> = COPY %EAX
208*9880d681SAndroid Build Coastguard Worker       // =>
209*9880d681SAndroid Build Coastguard Worker       //  %ECX<def> = COPY %EAX
210*9880d681SAndroid Build Coastguard Worker       if (eraseIfRedundant(*MI, Def, Src) || eraseIfRedundant(*MI, Src, Def))
211*9880d681SAndroid Build Coastguard Worker         continue;
212*9880d681SAndroid Build Coastguard Worker 
213*9880d681SAndroid Build Coastguard Worker       // If Src is defined by a previous copy, the previous copy cannot be
214*9880d681SAndroid Build Coastguard Worker       // eliminated.
215*9880d681SAndroid Build Coastguard Worker       for (MCRegAliasIterator AI(Src, TRI, true); AI.isValid(); ++AI) {
216*9880d681SAndroid Build Coastguard Worker         Reg2MIMap::iterator CI = CopyMap.find(*AI);
217*9880d681SAndroid Build Coastguard Worker         if (CI != CopyMap.end()) {
218*9880d681SAndroid Build Coastguard Worker           DEBUG(dbgs() << "MCP: Copy is no longer dead: "; CI->second->dump());
219*9880d681SAndroid Build Coastguard Worker           MaybeDeadCopies.remove(CI->second);
220*9880d681SAndroid Build Coastguard Worker         }
221*9880d681SAndroid Build Coastguard Worker       }
222*9880d681SAndroid Build Coastguard Worker 
223*9880d681SAndroid Build Coastguard Worker       DEBUG(dbgs() << "MCP: Copy is a deletion candidate: "; MI->dump());
224*9880d681SAndroid Build Coastguard Worker 
225*9880d681SAndroid Build Coastguard Worker       // Copy is now a candidate for deletion.
226*9880d681SAndroid Build Coastguard Worker       if (!MRI->isReserved(Def))
227*9880d681SAndroid Build Coastguard Worker         MaybeDeadCopies.insert(MI);
228*9880d681SAndroid Build Coastguard Worker 
229*9880d681SAndroid Build Coastguard Worker       // If 'Def' is previously source of another copy, then this earlier copy's
230*9880d681SAndroid Build Coastguard Worker       // source is no longer available. e.g.
231*9880d681SAndroid Build Coastguard Worker       // %xmm9<def> = copy %xmm2
232*9880d681SAndroid Build Coastguard Worker       // ...
233*9880d681SAndroid Build Coastguard Worker       // %xmm2<def> = copy %xmm0
234*9880d681SAndroid Build Coastguard Worker       // ...
235*9880d681SAndroid Build Coastguard Worker       // %xmm2<def> = copy %xmm9
236*9880d681SAndroid Build Coastguard Worker       ClobberRegister(Def);
237*9880d681SAndroid Build Coastguard Worker 
238*9880d681SAndroid Build Coastguard Worker       // Remember Def is defined by the copy.
239*9880d681SAndroid Build Coastguard Worker       for (MCSubRegIterator SR(Def, TRI, /*IncludeSelf=*/true); SR.isValid();
240*9880d681SAndroid Build Coastguard Worker            ++SR) {
241*9880d681SAndroid Build Coastguard Worker         CopyMap[*SR] = MI;
242*9880d681SAndroid Build Coastguard Worker         AvailCopyMap[*SR] = MI;
243*9880d681SAndroid Build Coastguard Worker       }
244*9880d681SAndroid Build Coastguard Worker 
245*9880d681SAndroid Build Coastguard Worker       // Remember source that's copied to Def. Once it's clobbered, then
246*9880d681SAndroid Build Coastguard Worker       // it's no longer available for copy propagation.
247*9880d681SAndroid Build Coastguard Worker       RegList &DestList = SrcMap[Src];
248*9880d681SAndroid Build Coastguard Worker       if (std::find(DestList.begin(), DestList.end(), Def) == DestList.end())
249*9880d681SAndroid Build Coastguard Worker         DestList.push_back(Def);
250*9880d681SAndroid Build Coastguard Worker 
251*9880d681SAndroid Build Coastguard Worker       continue;
252*9880d681SAndroid Build Coastguard Worker     }
253*9880d681SAndroid Build Coastguard Worker 
254*9880d681SAndroid Build Coastguard Worker     // Not a copy.
255*9880d681SAndroid Build Coastguard Worker     SmallVector<unsigned, 2> Defs;
256*9880d681SAndroid Build Coastguard Worker     const MachineOperand *RegMask = nullptr;
257*9880d681SAndroid Build Coastguard Worker     for (const MachineOperand &MO : MI->operands()) {
258*9880d681SAndroid Build Coastguard Worker       if (MO.isRegMask())
259*9880d681SAndroid Build Coastguard Worker         RegMask = &MO;
260*9880d681SAndroid Build Coastguard Worker       if (!MO.isReg())
261*9880d681SAndroid Build Coastguard Worker         continue;
262*9880d681SAndroid Build Coastguard Worker       unsigned Reg = MO.getReg();
263*9880d681SAndroid Build Coastguard Worker       if (!Reg)
264*9880d681SAndroid Build Coastguard Worker         continue;
265*9880d681SAndroid Build Coastguard Worker 
266*9880d681SAndroid Build Coastguard Worker       assert(!TargetRegisterInfo::isVirtualRegister(Reg) &&
267*9880d681SAndroid Build Coastguard Worker              "MachineCopyPropagation should be run after register allocation!");
268*9880d681SAndroid Build Coastguard Worker 
269*9880d681SAndroid Build Coastguard Worker       if (MO.isDef()) {
270*9880d681SAndroid Build Coastguard Worker         Defs.push_back(Reg);
271*9880d681SAndroid Build Coastguard Worker         continue;
272*9880d681SAndroid Build Coastguard Worker       }
273*9880d681SAndroid Build Coastguard Worker 
274*9880d681SAndroid Build Coastguard Worker       // If 'Reg' is defined by a copy, the copy is no longer a candidate
275*9880d681SAndroid Build Coastguard Worker       // for elimination.
276*9880d681SAndroid Build Coastguard Worker       for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI) {
277*9880d681SAndroid Build Coastguard Worker         Reg2MIMap::iterator CI = CopyMap.find(*AI);
278*9880d681SAndroid Build Coastguard Worker         if (CI != CopyMap.end()) {
279*9880d681SAndroid Build Coastguard Worker           DEBUG(dbgs() << "MCP: Copy is used - not dead: "; CI->second->dump());
280*9880d681SAndroid Build Coastguard Worker           MaybeDeadCopies.remove(CI->second);
281*9880d681SAndroid Build Coastguard Worker         }
282*9880d681SAndroid Build Coastguard Worker       }
283*9880d681SAndroid Build Coastguard Worker       // Treat undef use like defs for copy propagation but not for
284*9880d681SAndroid Build Coastguard Worker       // dead copy. We would need to do a liveness check to be sure the copy
285*9880d681SAndroid Build Coastguard Worker       // is dead for undef uses.
286*9880d681SAndroid Build Coastguard Worker       // The backends are allowed to do whatever they want with undef value
287*9880d681SAndroid Build Coastguard Worker       // and we cannot be sure this register will not be rewritten to break
288*9880d681SAndroid Build Coastguard Worker       // some false dependencies for the hardware for instance.
289*9880d681SAndroid Build Coastguard Worker       if (MO.isUndef())
290*9880d681SAndroid Build Coastguard Worker         Defs.push_back(Reg);
291*9880d681SAndroid Build Coastguard Worker     }
292*9880d681SAndroid Build Coastguard Worker 
293*9880d681SAndroid Build Coastguard Worker     // The instruction has a register mask operand which means that it clobbers
294*9880d681SAndroid Build Coastguard Worker     // a large set of registers.  Treat clobbered registers the same way as
295*9880d681SAndroid Build Coastguard Worker     // defined registers.
296*9880d681SAndroid Build Coastguard Worker     if (RegMask) {
297*9880d681SAndroid Build Coastguard Worker       // Erase any MaybeDeadCopies whose destination register is clobbered.
298*9880d681SAndroid Build Coastguard Worker       for (SmallSetVector<MachineInstr *, 8>::iterator DI =
299*9880d681SAndroid Build Coastguard Worker                MaybeDeadCopies.begin();
300*9880d681SAndroid Build Coastguard Worker            DI != MaybeDeadCopies.end();) {
301*9880d681SAndroid Build Coastguard Worker         MachineInstr *MaybeDead = *DI;
302*9880d681SAndroid Build Coastguard Worker         unsigned Reg = MaybeDead->getOperand(0).getReg();
303*9880d681SAndroid Build Coastguard Worker         assert(!MRI->isReserved(Reg));
304*9880d681SAndroid Build Coastguard Worker 
305*9880d681SAndroid Build Coastguard Worker         if (!RegMask->clobbersPhysReg(Reg)) {
306*9880d681SAndroid Build Coastguard Worker           ++DI;
307*9880d681SAndroid Build Coastguard Worker           continue;
308*9880d681SAndroid Build Coastguard Worker         }
309*9880d681SAndroid Build Coastguard Worker 
310*9880d681SAndroid Build Coastguard Worker         DEBUG(dbgs() << "MCP: Removing copy due to regmask clobbering: ";
311*9880d681SAndroid Build Coastguard Worker               MaybeDead->dump());
312*9880d681SAndroid Build Coastguard Worker 
313*9880d681SAndroid Build Coastguard Worker         // erase() will return the next valid iterator pointing to the next
314*9880d681SAndroid Build Coastguard Worker         // element after the erased one.
315*9880d681SAndroid Build Coastguard Worker         DI = MaybeDeadCopies.erase(DI);
316*9880d681SAndroid Build Coastguard Worker         MaybeDead->eraseFromParent();
317*9880d681SAndroid Build Coastguard Worker         Changed = true;
318*9880d681SAndroid Build Coastguard Worker         ++NumDeletes;
319*9880d681SAndroid Build Coastguard Worker       }
320*9880d681SAndroid Build Coastguard Worker 
321*9880d681SAndroid Build Coastguard Worker       removeClobberedRegsFromMap(AvailCopyMap, *RegMask);
322*9880d681SAndroid Build Coastguard Worker       removeClobberedRegsFromMap(CopyMap, *RegMask);
323*9880d681SAndroid Build Coastguard Worker       for (SourceMap::iterator I = SrcMap.begin(), E = SrcMap.end(), Next;
324*9880d681SAndroid Build Coastguard Worker            I != E; I = Next) {
325*9880d681SAndroid Build Coastguard Worker         Next = std::next(I);
326*9880d681SAndroid Build Coastguard Worker         if (RegMask->clobbersPhysReg(I->first)) {
327*9880d681SAndroid Build Coastguard Worker           removeRegsFromMap(AvailCopyMap, I->second, *TRI);
328*9880d681SAndroid Build Coastguard Worker           SrcMap.erase(I);
329*9880d681SAndroid Build Coastguard Worker         }
330*9880d681SAndroid Build Coastguard Worker       }
331*9880d681SAndroid Build Coastguard Worker     }
332*9880d681SAndroid Build Coastguard Worker 
333*9880d681SAndroid Build Coastguard Worker     // Any previous copy definition or reading the Defs is no longer available.
334*9880d681SAndroid Build Coastguard Worker     for (unsigned Reg : Defs)
335*9880d681SAndroid Build Coastguard Worker       ClobberRegister(Reg);
336*9880d681SAndroid Build Coastguard Worker   }
337*9880d681SAndroid Build Coastguard Worker 
338*9880d681SAndroid Build Coastguard Worker   // If MBB doesn't have successors, delete the copies whose defs are not used.
339*9880d681SAndroid Build Coastguard Worker   // If MBB does have successors, then conservative assume the defs are live-out
340*9880d681SAndroid Build Coastguard Worker   // since we don't want to trust live-in lists.
341*9880d681SAndroid Build Coastguard Worker   if (MBB.succ_empty()) {
342*9880d681SAndroid Build Coastguard Worker     for (MachineInstr *MaybeDead : MaybeDeadCopies) {
343*9880d681SAndroid Build Coastguard Worker       assert(!MRI->isReserved(MaybeDead->getOperand(0).getReg()));
344*9880d681SAndroid Build Coastguard Worker       MaybeDead->eraseFromParent();
345*9880d681SAndroid Build Coastguard Worker       Changed = true;
346*9880d681SAndroid Build Coastguard Worker       ++NumDeletes;
347*9880d681SAndroid Build Coastguard Worker     }
348*9880d681SAndroid Build Coastguard Worker   }
349*9880d681SAndroid Build Coastguard Worker 
350*9880d681SAndroid Build Coastguard Worker   MaybeDeadCopies.clear();
351*9880d681SAndroid Build Coastguard Worker   AvailCopyMap.clear();
352*9880d681SAndroid Build Coastguard Worker   CopyMap.clear();
353*9880d681SAndroid Build Coastguard Worker   SrcMap.clear();
354*9880d681SAndroid Build Coastguard Worker }
355*9880d681SAndroid Build Coastguard Worker 
runOnMachineFunction(MachineFunction & MF)356*9880d681SAndroid Build Coastguard Worker bool MachineCopyPropagation::runOnMachineFunction(MachineFunction &MF) {
357*9880d681SAndroid Build Coastguard Worker   if (skipFunction(*MF.getFunction()))
358*9880d681SAndroid Build Coastguard Worker     return false;
359*9880d681SAndroid Build Coastguard Worker 
360*9880d681SAndroid Build Coastguard Worker   Changed = false;
361*9880d681SAndroid Build Coastguard Worker 
362*9880d681SAndroid Build Coastguard Worker   TRI = MF.getSubtarget().getRegisterInfo();
363*9880d681SAndroid Build Coastguard Worker   TII = MF.getSubtarget().getInstrInfo();
364*9880d681SAndroid Build Coastguard Worker   MRI = &MF.getRegInfo();
365*9880d681SAndroid Build Coastguard Worker 
366*9880d681SAndroid Build Coastguard Worker   for (MachineBasicBlock &MBB : MF)
367*9880d681SAndroid Build Coastguard Worker     CopyPropagateBlock(MBB);
368*9880d681SAndroid Build Coastguard Worker 
369*9880d681SAndroid Build Coastguard Worker   return Changed;
370*9880d681SAndroid Build Coastguard Worker }
371*9880d681SAndroid Build Coastguard Worker 
372