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
860b57cec5SDimitry Andric namespace {
870b57cec5SDimitry Andric
880b57cec5SDimitry Andric class CopyTracker {
890b57cec5SDimitry Andric struct CopyInfo {
900b57cec5SDimitry Andric MachineInstr *MI;
91af732203SDimitry Andric SmallVector<MCRegister, 4> DefRegs;
920b57cec5SDimitry Andric bool Avail;
930b57cec5SDimitry Andric };
940b57cec5SDimitry Andric
95af732203SDimitry Andric DenseMap<MCRegister, CopyInfo> Copies;
960b57cec5SDimitry Andric
970b57cec5SDimitry Andric public:
980b57cec5SDimitry Andric /// Mark all of the given registers and their subregisters as unavailable for
990b57cec5SDimitry Andric /// copying.
markRegsUnavailable(ArrayRef<MCRegister> Regs,const TargetRegisterInfo & TRI)100af732203SDimitry Andric void markRegsUnavailable(ArrayRef<MCRegister> Regs,
1010b57cec5SDimitry Andric const TargetRegisterInfo &TRI) {
102af732203SDimitry Andric for (MCRegister Reg : Regs) {
1030b57cec5SDimitry Andric // Source of copy is no longer available for propagation.
1040b57cec5SDimitry Andric for (MCRegUnitIterator RUI(Reg, &TRI); RUI.isValid(); ++RUI) {
1050b57cec5SDimitry Andric auto CI = Copies.find(*RUI);
1060b57cec5SDimitry Andric if (CI != Copies.end())
1070b57cec5SDimitry Andric CI->second.Avail = false;
1080b57cec5SDimitry Andric }
1090b57cec5SDimitry Andric }
1100b57cec5SDimitry Andric }
1110b57cec5SDimitry Andric
112480093f4SDimitry Andric /// Remove register from copy maps.
invalidateRegister(MCRegister Reg,const TargetRegisterInfo & TRI)113af732203SDimitry Andric void invalidateRegister(MCRegister Reg, const TargetRegisterInfo &TRI) {
114480093f4SDimitry Andric // Since Reg might be a subreg of some registers, only invalidate Reg is not
115480093f4SDimitry Andric // enough. We have to find the COPY defines Reg or registers defined by Reg
116480093f4SDimitry Andric // and invalidate all of them.
117af732203SDimitry Andric SmallSet<MCRegister, 8> RegsToInvalidate;
1185ffd83dbSDimitry Andric RegsToInvalidate.insert(Reg);
119480093f4SDimitry Andric for (MCRegUnitIterator RUI(Reg, &TRI); RUI.isValid(); ++RUI) {
120480093f4SDimitry Andric auto I = Copies.find(*RUI);
121480093f4SDimitry Andric if (I != Copies.end()) {
122480093f4SDimitry Andric if (MachineInstr *MI = I->second.MI) {
123af732203SDimitry Andric RegsToInvalidate.insert(MI->getOperand(0).getReg().asMCReg());
124af732203SDimitry Andric RegsToInvalidate.insert(MI->getOperand(1).getReg().asMCReg());
125480093f4SDimitry Andric }
126480093f4SDimitry Andric RegsToInvalidate.insert(I->second.DefRegs.begin(),
127480093f4SDimitry Andric I->second.DefRegs.end());
128480093f4SDimitry Andric }
129480093f4SDimitry Andric }
130af732203SDimitry Andric for (MCRegister InvalidReg : RegsToInvalidate)
131480093f4SDimitry Andric for (MCRegUnitIterator RUI(InvalidReg, &TRI); RUI.isValid(); ++RUI)
132480093f4SDimitry Andric Copies.erase(*RUI);
133480093f4SDimitry Andric }
134480093f4SDimitry Andric
1350b57cec5SDimitry Andric /// Clobber a single register, removing it from the tracker's copy maps.
clobberRegister(MCRegister Reg,const TargetRegisterInfo & TRI)136af732203SDimitry Andric void clobberRegister(MCRegister Reg, const TargetRegisterInfo &TRI) {
1370b57cec5SDimitry Andric for (MCRegUnitIterator RUI(Reg, &TRI); RUI.isValid(); ++RUI) {
1380b57cec5SDimitry Andric auto I = Copies.find(*RUI);
1390b57cec5SDimitry Andric if (I != Copies.end()) {
1400b57cec5SDimitry Andric // When we clobber the source of a copy, we need to clobber everything
1410b57cec5SDimitry Andric // it defined.
1420b57cec5SDimitry Andric markRegsUnavailable(I->second.DefRegs, TRI);
1430b57cec5SDimitry Andric // When we clobber the destination of a copy, we need to clobber the
1440b57cec5SDimitry Andric // whole register it defined.
1450b57cec5SDimitry Andric if (MachineInstr *MI = I->second.MI)
146af732203SDimitry Andric markRegsUnavailable({MI->getOperand(0).getReg().asMCReg()}, TRI);
1470b57cec5SDimitry Andric // Now we can erase the copy.
1480b57cec5SDimitry Andric Copies.erase(I);
1490b57cec5SDimitry Andric }
1500b57cec5SDimitry Andric }
1510b57cec5SDimitry Andric }
1520b57cec5SDimitry Andric
1530b57cec5SDimitry Andric /// Add this copy's registers into the tracker's copy maps.
trackCopy(MachineInstr * MI,const TargetRegisterInfo & TRI)1540b57cec5SDimitry Andric void trackCopy(MachineInstr *MI, const TargetRegisterInfo &TRI) {
1550b57cec5SDimitry Andric assert(MI->isCopy() && "Tracking non-copy?");
1560b57cec5SDimitry Andric
157af732203SDimitry Andric MCRegister Def = MI->getOperand(0).getReg().asMCReg();
158af732203SDimitry Andric MCRegister Src = MI->getOperand(1).getReg().asMCReg();
1590b57cec5SDimitry Andric
1600b57cec5SDimitry Andric // Remember Def is defined by the copy.
1610b57cec5SDimitry Andric for (MCRegUnitIterator RUI(Def, &TRI); RUI.isValid(); ++RUI)
1620b57cec5SDimitry Andric Copies[*RUI] = {MI, {}, true};
1630b57cec5SDimitry Andric
1640b57cec5SDimitry Andric // Remember source that's copied to Def. Once it's clobbered, then
1650b57cec5SDimitry Andric // it's no longer available for copy propagation.
1660b57cec5SDimitry Andric for (MCRegUnitIterator RUI(Src, &TRI); RUI.isValid(); ++RUI) {
1670b57cec5SDimitry Andric auto I = Copies.insert({*RUI, {nullptr, {}, false}});
1680b57cec5SDimitry Andric auto &Copy = I.first->second;
1690b57cec5SDimitry Andric if (!is_contained(Copy.DefRegs, Def))
1700b57cec5SDimitry Andric Copy.DefRegs.push_back(Def);
1710b57cec5SDimitry Andric }
1720b57cec5SDimitry Andric }
1730b57cec5SDimitry Andric
hasAnyCopies()1740b57cec5SDimitry Andric bool hasAnyCopies() {
1750b57cec5SDimitry Andric return !Copies.empty();
1760b57cec5SDimitry Andric }
1770b57cec5SDimitry Andric
findCopyForUnit(MCRegister RegUnit,const TargetRegisterInfo & TRI,bool MustBeAvailable=false)178af732203SDimitry Andric MachineInstr *findCopyForUnit(MCRegister RegUnit,
179af732203SDimitry Andric const TargetRegisterInfo &TRI,
1800b57cec5SDimitry Andric bool MustBeAvailable = false) {
1810b57cec5SDimitry Andric auto CI = Copies.find(RegUnit);
1820b57cec5SDimitry Andric if (CI == Copies.end())
1830b57cec5SDimitry Andric return nullptr;
1840b57cec5SDimitry Andric if (MustBeAvailable && !CI->second.Avail)
1850b57cec5SDimitry Andric return nullptr;
1860b57cec5SDimitry Andric return CI->second.MI;
1870b57cec5SDimitry Andric }
1880b57cec5SDimitry Andric
findCopyDefViaUnit(MCRegister RegUnit,const TargetRegisterInfo & TRI)189af732203SDimitry Andric MachineInstr *findCopyDefViaUnit(MCRegister RegUnit,
190480093f4SDimitry Andric const TargetRegisterInfo &TRI) {
191480093f4SDimitry Andric auto CI = Copies.find(RegUnit);
192480093f4SDimitry Andric if (CI == Copies.end())
193480093f4SDimitry Andric return nullptr;
194480093f4SDimitry Andric if (CI->second.DefRegs.size() != 1)
195480093f4SDimitry Andric return nullptr;
196480093f4SDimitry Andric MCRegUnitIterator RUI(CI->second.DefRegs[0], &TRI);
197480093f4SDimitry Andric return findCopyForUnit(*RUI, TRI, true);
198480093f4SDimitry Andric }
199480093f4SDimitry Andric
findAvailBackwardCopy(MachineInstr & I,MCRegister Reg,const TargetRegisterInfo & TRI)200af732203SDimitry Andric MachineInstr *findAvailBackwardCopy(MachineInstr &I, MCRegister Reg,
201480093f4SDimitry Andric const TargetRegisterInfo &TRI) {
202480093f4SDimitry Andric MCRegUnitIterator RUI(Reg, &TRI);
203480093f4SDimitry Andric MachineInstr *AvailCopy = findCopyDefViaUnit(*RUI, TRI);
204480093f4SDimitry Andric if (!AvailCopy ||
205480093f4SDimitry Andric !TRI.isSubRegisterEq(AvailCopy->getOperand(1).getReg(), Reg))
206480093f4SDimitry Andric return nullptr;
207480093f4SDimitry Andric
208480093f4SDimitry Andric Register AvailSrc = AvailCopy->getOperand(1).getReg();
209480093f4SDimitry Andric Register AvailDef = AvailCopy->getOperand(0).getReg();
210480093f4SDimitry Andric for (const MachineInstr &MI :
211480093f4SDimitry Andric make_range(AvailCopy->getReverseIterator(), I.getReverseIterator()))
212480093f4SDimitry Andric for (const MachineOperand &MO : MI.operands())
213480093f4SDimitry Andric if (MO.isRegMask())
214480093f4SDimitry Andric // FIXME: Shall we simultaneously invalidate AvailSrc or AvailDef?
215480093f4SDimitry Andric if (MO.clobbersPhysReg(AvailSrc) || MO.clobbersPhysReg(AvailDef))
216480093f4SDimitry Andric return nullptr;
217480093f4SDimitry Andric
218480093f4SDimitry Andric return AvailCopy;
219480093f4SDimitry Andric }
220480093f4SDimitry Andric
findAvailCopy(MachineInstr & DestCopy,MCRegister Reg,const TargetRegisterInfo & TRI)221af732203SDimitry Andric MachineInstr *findAvailCopy(MachineInstr &DestCopy, MCRegister Reg,
2220b57cec5SDimitry Andric const TargetRegisterInfo &TRI) {
2230b57cec5SDimitry Andric // We check the first RegUnit here, since we'll only be interested in the
2240b57cec5SDimitry Andric // copy if it copies the entire register anyway.
2250b57cec5SDimitry Andric MCRegUnitIterator RUI(Reg, &TRI);
2260b57cec5SDimitry Andric MachineInstr *AvailCopy =
2270b57cec5SDimitry Andric findCopyForUnit(*RUI, TRI, /*MustBeAvailable=*/true);
2280b57cec5SDimitry Andric if (!AvailCopy ||
2290b57cec5SDimitry Andric !TRI.isSubRegisterEq(AvailCopy->getOperand(0).getReg(), Reg))
2300b57cec5SDimitry Andric return nullptr;
2310b57cec5SDimitry Andric
2320b57cec5SDimitry Andric // Check that the available copy isn't clobbered by any regmasks between
2330b57cec5SDimitry Andric // itself and the destination.
2348bcb0991SDimitry Andric Register AvailSrc = AvailCopy->getOperand(1).getReg();
2358bcb0991SDimitry Andric Register AvailDef = AvailCopy->getOperand(0).getReg();
2360b57cec5SDimitry Andric for (const MachineInstr &MI :
2370b57cec5SDimitry Andric make_range(AvailCopy->getIterator(), DestCopy.getIterator()))
2380b57cec5SDimitry Andric for (const MachineOperand &MO : MI.operands())
2390b57cec5SDimitry Andric if (MO.isRegMask())
2400b57cec5SDimitry Andric if (MO.clobbersPhysReg(AvailSrc) || MO.clobbersPhysReg(AvailDef))
2410b57cec5SDimitry Andric return nullptr;
2420b57cec5SDimitry Andric
2430b57cec5SDimitry Andric return AvailCopy;
2440b57cec5SDimitry Andric }
2450b57cec5SDimitry Andric
clear()2460b57cec5SDimitry Andric void clear() {
2470b57cec5SDimitry Andric Copies.clear();
2480b57cec5SDimitry Andric }
2490b57cec5SDimitry Andric };
2500b57cec5SDimitry Andric
2510b57cec5SDimitry Andric class MachineCopyPropagation : public MachineFunctionPass {
2520b57cec5SDimitry Andric const TargetRegisterInfo *TRI;
2530b57cec5SDimitry Andric const TargetInstrInfo *TII;
2540b57cec5SDimitry Andric const MachineRegisterInfo *MRI;
2550b57cec5SDimitry Andric
2560b57cec5SDimitry Andric public:
2570b57cec5SDimitry Andric static char ID; // Pass identification, replacement for typeid
2580b57cec5SDimitry Andric
MachineCopyPropagation()2590b57cec5SDimitry Andric MachineCopyPropagation() : MachineFunctionPass(ID) {
2600b57cec5SDimitry Andric initializeMachineCopyPropagationPass(*PassRegistry::getPassRegistry());
2610b57cec5SDimitry Andric }
2620b57cec5SDimitry Andric
getAnalysisUsage(AnalysisUsage & AU) const2630b57cec5SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override {
2640b57cec5SDimitry Andric AU.setPreservesCFG();
2650b57cec5SDimitry Andric MachineFunctionPass::getAnalysisUsage(AU);
2660b57cec5SDimitry Andric }
2670b57cec5SDimitry Andric
2680b57cec5SDimitry Andric bool runOnMachineFunction(MachineFunction &MF) override;
2690b57cec5SDimitry Andric
getRequiredProperties() const2700b57cec5SDimitry Andric MachineFunctionProperties getRequiredProperties() const override {
2710b57cec5SDimitry Andric return MachineFunctionProperties().set(
2720b57cec5SDimitry Andric MachineFunctionProperties::Property::NoVRegs);
2730b57cec5SDimitry Andric }
2740b57cec5SDimitry Andric
2750b57cec5SDimitry Andric private:
2768bcb0991SDimitry Andric typedef enum { DebugUse = false, RegularUse = true } DebugType;
2778bcb0991SDimitry Andric
278af732203SDimitry Andric void ReadRegister(MCRegister Reg, MachineInstr &Reader, DebugType DT);
279480093f4SDimitry Andric void ForwardCopyPropagateBlock(MachineBasicBlock &MBB);
280480093f4SDimitry Andric void BackwardCopyPropagateBlock(MachineBasicBlock &MBB);
281af732203SDimitry Andric bool eraseIfRedundant(MachineInstr &Copy, MCRegister Src, MCRegister Def);
2820b57cec5SDimitry Andric void forwardUses(MachineInstr &MI);
283480093f4SDimitry Andric void propagateDefs(MachineInstr &MI);
2840b57cec5SDimitry Andric bool isForwardableRegClassCopy(const MachineInstr &Copy,
2850b57cec5SDimitry Andric const MachineInstr &UseI, unsigned UseIdx);
286480093f4SDimitry Andric bool isBackwardPropagatableRegClassCopy(const MachineInstr &Copy,
287480093f4SDimitry Andric const MachineInstr &UseI,
288480093f4SDimitry Andric unsigned UseIdx);
2890b57cec5SDimitry Andric bool hasImplicitOverlap(const MachineInstr &MI, const MachineOperand &Use);
290af732203SDimitry Andric bool hasOverlappingMultipleDef(const MachineInstr &MI,
291af732203SDimitry Andric const MachineOperand &MODef, Register Def);
2920b57cec5SDimitry Andric
2930b57cec5SDimitry Andric /// Candidates for deletion.
2940b57cec5SDimitry Andric SmallSetVector<MachineInstr *, 8> MaybeDeadCopies;
2950b57cec5SDimitry Andric
2968bcb0991SDimitry Andric /// Multimap tracking debug users in current BB
297*5f7ddb14SDimitry Andric DenseMap<MachineInstr *, SmallSet<MachineInstr *, 2>> CopyDbgUsers;
2988bcb0991SDimitry Andric
2990b57cec5SDimitry Andric CopyTracker Tracker;
3000b57cec5SDimitry Andric
3010b57cec5SDimitry Andric bool Changed;
3020b57cec5SDimitry Andric };
3030b57cec5SDimitry Andric
3040b57cec5SDimitry Andric } // end anonymous namespace
3050b57cec5SDimitry Andric
3060b57cec5SDimitry Andric char MachineCopyPropagation::ID = 0;
3070b57cec5SDimitry Andric
3080b57cec5SDimitry Andric char &llvm::MachineCopyPropagationID = MachineCopyPropagation::ID;
3090b57cec5SDimitry Andric
3100b57cec5SDimitry Andric INITIALIZE_PASS(MachineCopyPropagation, DEBUG_TYPE,
3110b57cec5SDimitry Andric "Machine Copy Propagation Pass", false, false)
3120b57cec5SDimitry Andric
ReadRegister(MCRegister Reg,MachineInstr & Reader,DebugType DT)313af732203SDimitry Andric void MachineCopyPropagation::ReadRegister(MCRegister Reg, MachineInstr &Reader,
3148bcb0991SDimitry Andric DebugType DT) {
3150b57cec5SDimitry Andric // If 'Reg' is defined by a copy, the copy is no longer a candidate
3168bcb0991SDimitry Andric // for elimination. If a copy is "read" by a debug user, record the user
3178bcb0991SDimitry Andric // for propagation.
3180b57cec5SDimitry Andric for (MCRegUnitIterator RUI(Reg, TRI); RUI.isValid(); ++RUI) {
3190b57cec5SDimitry Andric if (MachineInstr *Copy = Tracker.findCopyForUnit(*RUI, *TRI)) {
3208bcb0991SDimitry Andric if (DT == RegularUse) {
3210b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "MCP: Copy is used - not dead: "; Copy->dump());
3220b57cec5SDimitry Andric MaybeDeadCopies.remove(Copy);
3238bcb0991SDimitry Andric } else {
324*5f7ddb14SDimitry Andric CopyDbgUsers[Copy].insert(&Reader);
3258bcb0991SDimitry Andric }
3260b57cec5SDimitry Andric }
3270b57cec5SDimitry Andric }
3280b57cec5SDimitry Andric }
3290b57cec5SDimitry Andric
3300b57cec5SDimitry Andric /// Return true if \p PreviousCopy did copy register \p Src to register \p Def.
3310b57cec5SDimitry Andric /// This fact may have been obscured by sub register usage or may not be true at
3320b57cec5SDimitry Andric /// all even though Src and Def are subregisters of the registers used in
3330b57cec5SDimitry Andric /// PreviousCopy. e.g.
3340b57cec5SDimitry Andric /// isNopCopy("ecx = COPY eax", AX, CX) == true
3350b57cec5SDimitry Andric /// isNopCopy("ecx = COPY eax", AH, CL) == false
isNopCopy(const MachineInstr & PreviousCopy,MCRegister Src,MCRegister Def,const TargetRegisterInfo * TRI)336af732203SDimitry Andric static bool isNopCopy(const MachineInstr &PreviousCopy, MCRegister Src,
337af732203SDimitry Andric MCRegister Def, const TargetRegisterInfo *TRI) {
338af732203SDimitry Andric MCRegister PreviousSrc = PreviousCopy.getOperand(1).getReg().asMCReg();
339af732203SDimitry Andric MCRegister PreviousDef = PreviousCopy.getOperand(0).getReg().asMCReg();
34016d6b3b3SDimitry Andric if (Src == PreviousSrc && Def == PreviousDef)
3410b57cec5SDimitry Andric return true;
3420b57cec5SDimitry Andric if (!TRI->isSubRegister(PreviousSrc, Src))
3430b57cec5SDimitry Andric return false;
3440b57cec5SDimitry Andric unsigned SubIdx = TRI->getSubRegIndex(PreviousSrc, Src);
3450b57cec5SDimitry Andric return SubIdx == TRI->getSubRegIndex(PreviousDef, Def);
3460b57cec5SDimitry Andric }
3470b57cec5SDimitry Andric
3480b57cec5SDimitry Andric /// Remove instruction \p Copy if there exists a previous copy that copies the
3490b57cec5SDimitry Andric /// register \p Src to the register \p Def; This may happen indirectly by
3500b57cec5SDimitry Andric /// copying the super registers.
eraseIfRedundant(MachineInstr & Copy,MCRegister Src,MCRegister Def)351af732203SDimitry Andric bool MachineCopyPropagation::eraseIfRedundant(MachineInstr &Copy,
352af732203SDimitry Andric MCRegister Src, MCRegister Def) {
3530b57cec5SDimitry Andric // Avoid eliminating a copy from/to a reserved registers as we cannot predict
3540b57cec5SDimitry Andric // the value (Example: The sparc zero register is writable but stays zero).
3550b57cec5SDimitry Andric if (MRI->isReserved(Src) || MRI->isReserved(Def))
3560b57cec5SDimitry Andric return false;
3570b57cec5SDimitry Andric
3580b57cec5SDimitry Andric // Search for an existing copy.
3590b57cec5SDimitry Andric MachineInstr *PrevCopy = Tracker.findAvailCopy(Copy, Def, *TRI);
3600b57cec5SDimitry Andric if (!PrevCopy)
3610b57cec5SDimitry Andric return false;
3620b57cec5SDimitry Andric
3630b57cec5SDimitry Andric // Check that the existing copy uses the correct sub registers.
3640b57cec5SDimitry Andric if (PrevCopy->getOperand(0).isDead())
3650b57cec5SDimitry Andric return false;
3660b57cec5SDimitry Andric if (!isNopCopy(*PrevCopy, Src, Def, TRI))
3670b57cec5SDimitry Andric return false;
3680b57cec5SDimitry Andric
3690b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "MCP: copy is a NOP, removing: "; Copy.dump());
3700b57cec5SDimitry Andric
3710b57cec5SDimitry Andric // Copy was redundantly redefining either Src or Def. Remove earlier kill
3720b57cec5SDimitry Andric // flags between Copy and PrevCopy because the value will be reused now.
3730b57cec5SDimitry Andric assert(Copy.isCopy());
3748bcb0991SDimitry Andric Register CopyDef = Copy.getOperand(0).getReg();
3750b57cec5SDimitry Andric assert(CopyDef == Src || CopyDef == Def);
3760b57cec5SDimitry Andric for (MachineInstr &MI :
3770b57cec5SDimitry Andric make_range(PrevCopy->getIterator(), Copy.getIterator()))
3780b57cec5SDimitry Andric MI.clearRegisterKills(CopyDef, TRI);
3790b57cec5SDimitry Andric
3800b57cec5SDimitry Andric Copy.eraseFromParent();
3810b57cec5SDimitry Andric Changed = true;
3820b57cec5SDimitry Andric ++NumDeletes;
3830b57cec5SDimitry Andric return true;
3840b57cec5SDimitry Andric }
3850b57cec5SDimitry Andric
isBackwardPropagatableRegClassCopy(const MachineInstr & Copy,const MachineInstr & UseI,unsigned UseIdx)386480093f4SDimitry Andric bool MachineCopyPropagation::isBackwardPropagatableRegClassCopy(
387480093f4SDimitry Andric const MachineInstr &Copy, const MachineInstr &UseI, unsigned UseIdx) {
388480093f4SDimitry Andric Register Def = Copy.getOperand(0).getReg();
389480093f4SDimitry Andric
390480093f4SDimitry Andric if (const TargetRegisterClass *URC =
391480093f4SDimitry Andric UseI.getRegClassConstraint(UseIdx, TII, TRI))
392480093f4SDimitry Andric return URC->contains(Def);
393480093f4SDimitry Andric
394480093f4SDimitry Andric // We don't process further if UseI is a COPY, since forward copy propagation
395480093f4SDimitry Andric // should handle that.
396480093f4SDimitry Andric return false;
397480093f4SDimitry Andric }
398480093f4SDimitry Andric
3990b57cec5SDimitry Andric /// Decide whether we should forward the source of \param Copy to its use in
4000b57cec5SDimitry Andric /// \param UseI based on the physical register class constraints of the opcode
4010b57cec5SDimitry Andric /// and avoiding introducing more cross-class COPYs.
isForwardableRegClassCopy(const MachineInstr & Copy,const MachineInstr & UseI,unsigned UseIdx)4020b57cec5SDimitry Andric bool MachineCopyPropagation::isForwardableRegClassCopy(const MachineInstr &Copy,
4030b57cec5SDimitry Andric const MachineInstr &UseI,
4040b57cec5SDimitry Andric unsigned UseIdx) {
4050b57cec5SDimitry Andric
4068bcb0991SDimitry Andric Register CopySrcReg = Copy.getOperand(1).getReg();
4070b57cec5SDimitry Andric
4080b57cec5SDimitry Andric // If the new register meets the opcode register constraints, then allow
4090b57cec5SDimitry Andric // forwarding.
4100b57cec5SDimitry Andric if (const TargetRegisterClass *URC =
4110b57cec5SDimitry Andric UseI.getRegClassConstraint(UseIdx, TII, TRI))
4120b57cec5SDimitry Andric return URC->contains(CopySrcReg);
4130b57cec5SDimitry Andric
4140b57cec5SDimitry Andric if (!UseI.isCopy())
4150b57cec5SDimitry Andric return false;
4160b57cec5SDimitry Andric
4170b57cec5SDimitry Andric /// COPYs don't have register class constraints, so if the user instruction
4180b57cec5SDimitry Andric /// is a COPY, we just try to avoid introducing additional cross-class
4190b57cec5SDimitry Andric /// COPYs. For example:
4200b57cec5SDimitry Andric ///
4210b57cec5SDimitry Andric /// RegClassA = COPY RegClassB // Copy parameter
4220b57cec5SDimitry Andric /// ...
4230b57cec5SDimitry Andric /// RegClassB = COPY RegClassA // UseI parameter
4240b57cec5SDimitry Andric ///
4250b57cec5SDimitry Andric /// which after forwarding becomes
4260b57cec5SDimitry Andric ///
4270b57cec5SDimitry Andric /// RegClassA = COPY RegClassB
4280b57cec5SDimitry Andric /// ...
4290b57cec5SDimitry Andric /// RegClassB = COPY RegClassB
4300b57cec5SDimitry Andric ///
4310b57cec5SDimitry Andric /// so we have reduced the number of cross-class COPYs and potentially
4320b57cec5SDimitry Andric /// introduced a nop COPY that can be removed.
4330b57cec5SDimitry Andric const TargetRegisterClass *UseDstRC =
4340b57cec5SDimitry Andric TRI->getMinimalPhysRegClass(UseI.getOperand(0).getReg());
4350b57cec5SDimitry Andric
4360b57cec5SDimitry Andric const TargetRegisterClass *SuperRC = UseDstRC;
4370b57cec5SDimitry Andric for (TargetRegisterClass::sc_iterator SuperRCI = UseDstRC->getSuperClasses();
4380b57cec5SDimitry Andric SuperRC; SuperRC = *SuperRCI++)
4390b57cec5SDimitry Andric if (SuperRC->contains(CopySrcReg))
4400b57cec5SDimitry Andric return true;
4410b57cec5SDimitry Andric
4420b57cec5SDimitry Andric return false;
4430b57cec5SDimitry Andric }
4440b57cec5SDimitry Andric
4450b57cec5SDimitry Andric /// Check that \p MI does not have implicit uses that overlap with it's \p Use
4460b57cec5SDimitry Andric /// operand (the register being replaced), since these can sometimes be
4470b57cec5SDimitry Andric /// implicitly tied to other operands. For example, on AMDGPU:
4480b57cec5SDimitry Andric ///
4490b57cec5SDimitry Andric /// V_MOVRELS_B32_e32 %VGPR2, %M0<imp-use>, %EXEC<imp-use>, %VGPR2_VGPR3_VGPR4_VGPR5<imp-use>
4500b57cec5SDimitry Andric ///
4510b57cec5SDimitry Andric /// the %VGPR2 is implicitly tied to the larger reg operand, but we have no
4520b57cec5SDimitry Andric /// way of knowing we need to update the latter when updating the former.
hasImplicitOverlap(const MachineInstr & MI,const MachineOperand & Use)4530b57cec5SDimitry Andric bool MachineCopyPropagation::hasImplicitOverlap(const MachineInstr &MI,
4540b57cec5SDimitry Andric const MachineOperand &Use) {
4550b57cec5SDimitry Andric for (const MachineOperand &MIUse : MI.uses())
4560b57cec5SDimitry Andric if (&MIUse != &Use && MIUse.isReg() && MIUse.isImplicit() &&
4570b57cec5SDimitry Andric MIUse.isUse() && TRI->regsOverlap(Use.getReg(), MIUse.getReg()))
4580b57cec5SDimitry Andric return true;
4590b57cec5SDimitry Andric
4600b57cec5SDimitry Andric return false;
4610b57cec5SDimitry Andric }
4620b57cec5SDimitry Andric
463af732203SDimitry Andric /// For an MI that has multiple definitions, check whether \p MI has
464af732203SDimitry Andric /// a definition that overlaps with another of its definitions.
465af732203SDimitry Andric /// For example, on ARM: umull r9, r9, lr, r0
466af732203SDimitry Andric /// The umull instruction is unpredictable unless RdHi and RdLo are different.
hasOverlappingMultipleDef(const MachineInstr & MI,const MachineOperand & MODef,Register Def)467af732203SDimitry Andric bool MachineCopyPropagation::hasOverlappingMultipleDef(
468af732203SDimitry Andric const MachineInstr &MI, const MachineOperand &MODef, Register Def) {
469af732203SDimitry Andric for (const MachineOperand &MIDef : MI.defs()) {
470af732203SDimitry Andric if ((&MIDef != &MODef) && MIDef.isReg() &&
471af732203SDimitry Andric TRI->regsOverlap(Def, MIDef.getReg()))
472af732203SDimitry Andric return true;
473af732203SDimitry Andric }
474af732203SDimitry Andric
475af732203SDimitry Andric return false;
476af732203SDimitry Andric }
477af732203SDimitry Andric
4780b57cec5SDimitry Andric /// Look for available copies whose destination register is used by \p MI and
4790b57cec5SDimitry Andric /// replace the use in \p MI with the copy's source register.
forwardUses(MachineInstr & MI)4800b57cec5SDimitry Andric void MachineCopyPropagation::forwardUses(MachineInstr &MI) {
4810b57cec5SDimitry Andric if (!Tracker.hasAnyCopies())
4820b57cec5SDimitry Andric return;
4830b57cec5SDimitry Andric
4840b57cec5SDimitry Andric // Look for non-tied explicit vreg uses that have an active COPY
4850b57cec5SDimitry Andric // instruction that defines the physical register allocated to them.
4860b57cec5SDimitry Andric // Replace the vreg with the source of the active COPY.
4870b57cec5SDimitry Andric for (unsigned OpIdx = 0, OpEnd = MI.getNumOperands(); OpIdx < OpEnd;
4880b57cec5SDimitry Andric ++OpIdx) {
4890b57cec5SDimitry Andric MachineOperand &MOUse = MI.getOperand(OpIdx);
4900b57cec5SDimitry Andric // Don't forward into undef use operands since doing so can cause problems
4910b57cec5SDimitry Andric // with the machine verifier, since it doesn't treat undef reads as reads,
4920b57cec5SDimitry Andric // so we can end up with a live range that ends on an undef read, leading to
4930b57cec5SDimitry Andric // an error that the live range doesn't end on a read of the live range
4940b57cec5SDimitry Andric // register.
4950b57cec5SDimitry Andric if (!MOUse.isReg() || MOUse.isTied() || MOUse.isUndef() || MOUse.isDef() ||
4960b57cec5SDimitry Andric MOUse.isImplicit())
4970b57cec5SDimitry Andric continue;
4980b57cec5SDimitry Andric
4990b57cec5SDimitry Andric if (!MOUse.getReg())
5000b57cec5SDimitry Andric continue;
5010b57cec5SDimitry Andric
5020b57cec5SDimitry Andric // Check that the register is marked 'renamable' so we know it is safe to
5030b57cec5SDimitry Andric // rename it without violating any constraints that aren't expressed in the
5040b57cec5SDimitry Andric // IR (e.g. ABI or opcode requirements).
5050b57cec5SDimitry Andric if (!MOUse.isRenamable())
5060b57cec5SDimitry Andric continue;
5070b57cec5SDimitry Andric
508af732203SDimitry Andric MachineInstr *Copy =
509af732203SDimitry Andric Tracker.findAvailCopy(MI, MOUse.getReg().asMCReg(), *TRI);
5100b57cec5SDimitry Andric if (!Copy)
5110b57cec5SDimitry Andric continue;
5120b57cec5SDimitry Andric
5138bcb0991SDimitry Andric Register CopyDstReg = Copy->getOperand(0).getReg();
5140b57cec5SDimitry Andric const MachineOperand &CopySrc = Copy->getOperand(1);
5158bcb0991SDimitry Andric Register CopySrcReg = CopySrc.getReg();
5160b57cec5SDimitry Andric
5170b57cec5SDimitry Andric // FIXME: Don't handle partial uses of wider COPYs yet.
5180b57cec5SDimitry Andric if (MOUse.getReg() != CopyDstReg) {
5190b57cec5SDimitry Andric LLVM_DEBUG(
5200b57cec5SDimitry Andric dbgs() << "MCP: FIXME! Not forwarding COPY to sub-register use:\n "
5210b57cec5SDimitry Andric << MI);
5220b57cec5SDimitry Andric continue;
5230b57cec5SDimitry Andric }
5240b57cec5SDimitry Andric
5250b57cec5SDimitry Andric // Don't forward COPYs of reserved regs unless they are constant.
5260b57cec5SDimitry Andric if (MRI->isReserved(CopySrcReg) && !MRI->isConstantPhysReg(CopySrcReg))
5270b57cec5SDimitry Andric continue;
5280b57cec5SDimitry Andric
5290b57cec5SDimitry Andric if (!isForwardableRegClassCopy(*Copy, MI, OpIdx))
5300b57cec5SDimitry Andric continue;
5310b57cec5SDimitry Andric
5320b57cec5SDimitry Andric if (hasImplicitOverlap(MI, MOUse))
5330b57cec5SDimitry Andric continue;
5340b57cec5SDimitry Andric
535480093f4SDimitry Andric // Check that the instruction is not a copy that partially overwrites the
536480093f4SDimitry Andric // original copy source that we are about to use. The tracker mechanism
537480093f4SDimitry Andric // cannot cope with that.
538480093f4SDimitry Andric if (MI.isCopy() && MI.modifiesRegister(CopySrcReg, TRI) &&
539480093f4SDimitry Andric !MI.definesRegister(CopySrcReg)) {
540480093f4SDimitry Andric LLVM_DEBUG(dbgs() << "MCP: Copy source overlap with dest in " << MI);
541480093f4SDimitry Andric continue;
542480093f4SDimitry Andric }
543480093f4SDimitry Andric
5440b57cec5SDimitry Andric if (!DebugCounter::shouldExecute(FwdCounter)) {
5450b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "MCP: Skipping forwarding due to debug counter:\n "
5460b57cec5SDimitry Andric << MI);
5470b57cec5SDimitry Andric continue;
5480b57cec5SDimitry Andric }
5490b57cec5SDimitry Andric
5500b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "MCP: Replacing " << printReg(MOUse.getReg(), TRI)
5510b57cec5SDimitry Andric << "\n with " << printReg(CopySrcReg, TRI)
5520b57cec5SDimitry Andric << "\n in " << MI << " from " << *Copy);
5530b57cec5SDimitry Andric
5540b57cec5SDimitry Andric MOUse.setReg(CopySrcReg);
5550b57cec5SDimitry Andric if (!CopySrc.isRenamable())
5560b57cec5SDimitry Andric MOUse.setIsRenamable(false);
5570b57cec5SDimitry Andric
5580b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "MCP: After replacement: " << MI << "\n");
5590b57cec5SDimitry Andric
5600b57cec5SDimitry Andric // Clear kill markers that may have been invalidated.
5610b57cec5SDimitry Andric for (MachineInstr &KMI :
5620b57cec5SDimitry Andric make_range(Copy->getIterator(), std::next(MI.getIterator())))
5630b57cec5SDimitry Andric KMI.clearRegisterKills(CopySrcReg, TRI);
5640b57cec5SDimitry Andric
5650b57cec5SDimitry Andric ++NumCopyForwards;
5660b57cec5SDimitry Andric Changed = true;
5670b57cec5SDimitry Andric }
5680b57cec5SDimitry Andric }
5690b57cec5SDimitry Andric
ForwardCopyPropagateBlock(MachineBasicBlock & MBB)570480093f4SDimitry Andric void MachineCopyPropagation::ForwardCopyPropagateBlock(MachineBasicBlock &MBB) {
571480093f4SDimitry Andric LLVM_DEBUG(dbgs() << "MCP: ForwardCopyPropagateBlock " << MBB.getName()
572480093f4SDimitry Andric << "\n");
5730b57cec5SDimitry Andric
5740b57cec5SDimitry Andric for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end(); I != E; ) {
5750b57cec5SDimitry Andric MachineInstr *MI = &*I;
5760b57cec5SDimitry Andric ++I;
5770b57cec5SDimitry Andric
5780b57cec5SDimitry Andric // Analyze copies (which don't overlap themselves).
5790b57cec5SDimitry Andric if (MI->isCopy() && !TRI->regsOverlap(MI->getOperand(0).getReg(),
5800b57cec5SDimitry Andric MI->getOperand(1).getReg())) {
581af732203SDimitry Andric assert(MI->getOperand(0).getReg().isPhysical() &&
582af732203SDimitry Andric MI->getOperand(1).getReg().isPhysical() &&
5830b57cec5SDimitry Andric "MachineCopyPropagation should be run after register allocation!");
5840b57cec5SDimitry Andric
585af732203SDimitry Andric MCRegister Def = MI->getOperand(0).getReg().asMCReg();
586af732203SDimitry Andric MCRegister Src = MI->getOperand(1).getReg().asMCReg();
587af732203SDimitry Andric
5880b57cec5SDimitry Andric // The two copies cancel out and the source of the first copy
5890b57cec5SDimitry Andric // hasn't been overridden, eliminate the second one. e.g.
5900b57cec5SDimitry Andric // %ecx = COPY %eax
5910b57cec5SDimitry Andric // ... nothing clobbered eax.
5920b57cec5SDimitry Andric // %eax = COPY %ecx
5930b57cec5SDimitry Andric // =>
5940b57cec5SDimitry Andric // %ecx = COPY %eax
5950b57cec5SDimitry Andric //
5960b57cec5SDimitry Andric // or
5970b57cec5SDimitry Andric //
5980b57cec5SDimitry Andric // %ecx = COPY %eax
5990b57cec5SDimitry Andric // ... nothing clobbered eax.
6000b57cec5SDimitry Andric // %ecx = COPY %eax
6010b57cec5SDimitry Andric // =>
6020b57cec5SDimitry Andric // %ecx = COPY %eax
6030b57cec5SDimitry Andric if (eraseIfRedundant(*MI, Def, Src) || eraseIfRedundant(*MI, Src, Def))
6040b57cec5SDimitry Andric continue;
6050b57cec5SDimitry Andric
6060b57cec5SDimitry Andric forwardUses(*MI);
6070b57cec5SDimitry Andric
6080b57cec5SDimitry Andric // Src may have been changed by forwardUses()
609af732203SDimitry Andric Src = MI->getOperand(1).getReg().asMCReg();
6100b57cec5SDimitry Andric
6110b57cec5SDimitry Andric // If Src is defined by a previous copy, the previous copy cannot be
6120b57cec5SDimitry Andric // eliminated.
6138bcb0991SDimitry Andric ReadRegister(Src, *MI, RegularUse);
6140b57cec5SDimitry Andric for (const MachineOperand &MO : MI->implicit_operands()) {
6150b57cec5SDimitry Andric if (!MO.isReg() || !MO.readsReg())
6160b57cec5SDimitry Andric continue;
617af732203SDimitry Andric MCRegister Reg = MO.getReg().asMCReg();
6180b57cec5SDimitry Andric if (!Reg)
6190b57cec5SDimitry Andric continue;
6208bcb0991SDimitry Andric ReadRegister(Reg, *MI, RegularUse);
6210b57cec5SDimitry Andric }
6220b57cec5SDimitry Andric
6230b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "MCP: Copy is a deletion candidate: "; MI->dump());
6240b57cec5SDimitry Andric
6250b57cec5SDimitry Andric // Copy is now a candidate for deletion.
6260b57cec5SDimitry Andric if (!MRI->isReserved(Def))
6270b57cec5SDimitry Andric MaybeDeadCopies.insert(MI);
6280b57cec5SDimitry Andric
6290b57cec5SDimitry Andric // If 'Def' is previously source of another copy, then this earlier copy's
6300b57cec5SDimitry Andric // source is no longer available. e.g.
6310b57cec5SDimitry Andric // %xmm9 = copy %xmm2
6320b57cec5SDimitry Andric // ...
6330b57cec5SDimitry Andric // %xmm2 = copy %xmm0
6340b57cec5SDimitry Andric // ...
6350b57cec5SDimitry Andric // %xmm2 = copy %xmm9
6360b57cec5SDimitry Andric Tracker.clobberRegister(Def, *TRI);
6370b57cec5SDimitry Andric for (const MachineOperand &MO : MI->implicit_operands()) {
6380b57cec5SDimitry Andric if (!MO.isReg() || !MO.isDef())
6390b57cec5SDimitry Andric continue;
640af732203SDimitry Andric MCRegister Reg = MO.getReg().asMCReg();
6410b57cec5SDimitry Andric if (!Reg)
6420b57cec5SDimitry Andric continue;
6430b57cec5SDimitry Andric Tracker.clobberRegister(Reg, *TRI);
6440b57cec5SDimitry Andric }
6450b57cec5SDimitry Andric
6460b57cec5SDimitry Andric Tracker.trackCopy(MI, *TRI);
6470b57cec5SDimitry Andric
6480b57cec5SDimitry Andric continue;
6490b57cec5SDimitry Andric }
6500b57cec5SDimitry Andric
6510b57cec5SDimitry Andric // Clobber any earlyclobber regs first.
6520b57cec5SDimitry Andric for (const MachineOperand &MO : MI->operands())
6530b57cec5SDimitry Andric if (MO.isReg() && MO.isEarlyClobber()) {
654af732203SDimitry Andric MCRegister Reg = MO.getReg().asMCReg();
6550b57cec5SDimitry Andric // If we have a tied earlyclobber, that means it is also read by this
6560b57cec5SDimitry Andric // instruction, so we need to make sure we don't remove it as dead
6570b57cec5SDimitry Andric // later.
6580b57cec5SDimitry Andric if (MO.isTied())
6598bcb0991SDimitry Andric ReadRegister(Reg, *MI, RegularUse);
6600b57cec5SDimitry Andric Tracker.clobberRegister(Reg, *TRI);
6610b57cec5SDimitry Andric }
6620b57cec5SDimitry Andric
6630b57cec5SDimitry Andric forwardUses(*MI);
6640b57cec5SDimitry Andric
6650b57cec5SDimitry Andric // Not a copy.
666af732203SDimitry Andric SmallVector<Register, 2> Defs;
6670b57cec5SDimitry Andric const MachineOperand *RegMask = nullptr;
6680b57cec5SDimitry Andric for (const MachineOperand &MO : MI->operands()) {
6690b57cec5SDimitry Andric if (MO.isRegMask())
6700b57cec5SDimitry Andric RegMask = &MO;
6710b57cec5SDimitry Andric if (!MO.isReg())
6720b57cec5SDimitry Andric continue;
6738bcb0991SDimitry Andric Register Reg = MO.getReg();
6740b57cec5SDimitry Andric if (!Reg)
6750b57cec5SDimitry Andric continue;
6760b57cec5SDimitry Andric
677af732203SDimitry Andric assert(!Reg.isVirtual() &&
6780b57cec5SDimitry Andric "MachineCopyPropagation should be run after register allocation!");
6790b57cec5SDimitry Andric
6800b57cec5SDimitry Andric if (MO.isDef() && !MO.isEarlyClobber()) {
681af732203SDimitry Andric Defs.push_back(Reg.asMCReg());
6820b57cec5SDimitry Andric continue;
6838bcb0991SDimitry Andric } else if (MO.readsReg())
684af732203SDimitry Andric ReadRegister(Reg.asMCReg(), *MI, MO.isDebug() ? DebugUse : RegularUse);
6850b57cec5SDimitry Andric }
6860b57cec5SDimitry Andric
6870b57cec5SDimitry Andric // The instruction has a register mask operand which means that it clobbers
6880b57cec5SDimitry Andric // a large set of registers. Treat clobbered registers the same way as
6890b57cec5SDimitry Andric // defined registers.
6900b57cec5SDimitry Andric if (RegMask) {
6910b57cec5SDimitry Andric // Erase any MaybeDeadCopies whose destination register is clobbered.
6920b57cec5SDimitry Andric for (SmallSetVector<MachineInstr *, 8>::iterator DI =
6930b57cec5SDimitry Andric MaybeDeadCopies.begin();
6940b57cec5SDimitry Andric DI != MaybeDeadCopies.end();) {
6950b57cec5SDimitry Andric MachineInstr *MaybeDead = *DI;
696af732203SDimitry Andric MCRegister Reg = MaybeDead->getOperand(0).getReg().asMCReg();
6970b57cec5SDimitry Andric assert(!MRI->isReserved(Reg));
6980b57cec5SDimitry Andric
6990b57cec5SDimitry Andric if (!RegMask->clobbersPhysReg(Reg)) {
7000b57cec5SDimitry Andric ++DI;
7010b57cec5SDimitry Andric continue;
7020b57cec5SDimitry Andric }
7030b57cec5SDimitry Andric
7040b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "MCP: Removing copy due to regmask clobbering: ";
7050b57cec5SDimitry Andric MaybeDead->dump());
7060b57cec5SDimitry Andric
7070b57cec5SDimitry Andric // Make sure we invalidate any entries in the copy maps before erasing
7080b57cec5SDimitry Andric // the instruction.
7090b57cec5SDimitry Andric Tracker.clobberRegister(Reg, *TRI);
7100b57cec5SDimitry Andric
7110b57cec5SDimitry Andric // erase() will return the next valid iterator pointing to the next
7120b57cec5SDimitry Andric // element after the erased one.
7130b57cec5SDimitry Andric DI = MaybeDeadCopies.erase(DI);
7140b57cec5SDimitry Andric MaybeDead->eraseFromParent();
7150b57cec5SDimitry Andric Changed = true;
7160b57cec5SDimitry Andric ++NumDeletes;
7170b57cec5SDimitry Andric }
7180b57cec5SDimitry Andric }
7190b57cec5SDimitry Andric
7200b57cec5SDimitry Andric // Any previous copy definition or reading the Defs is no longer available.
721af732203SDimitry Andric for (MCRegister Reg : Defs)
7220b57cec5SDimitry Andric Tracker.clobberRegister(Reg, *TRI);
7230b57cec5SDimitry Andric }
7240b57cec5SDimitry Andric
7250b57cec5SDimitry Andric // If MBB doesn't have successors, delete the copies whose defs are not used.
7260b57cec5SDimitry Andric // If MBB does have successors, then conservative assume the defs are live-out
7270b57cec5SDimitry Andric // since we don't want to trust live-in lists.
7280b57cec5SDimitry Andric if (MBB.succ_empty()) {
7290b57cec5SDimitry Andric for (MachineInstr *MaybeDead : MaybeDeadCopies) {
7300b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "MCP: Removing copy due to no live-out succ: ";
7310b57cec5SDimitry Andric MaybeDead->dump());
7320b57cec5SDimitry Andric assert(!MRI->isReserved(MaybeDead->getOperand(0).getReg()));
7330b57cec5SDimitry Andric
7348bcb0991SDimitry Andric // Update matching debug values, if any.
7350b57cec5SDimitry Andric assert(MaybeDead->isCopy());
736af732203SDimitry Andric Register SrcReg = MaybeDead->getOperand(1).getReg();
737*5f7ddb14SDimitry Andric Register DestReg = MaybeDead->getOperand(0).getReg();
738*5f7ddb14SDimitry Andric SmallVector<MachineInstr *> MaybeDeadDbgUsers(
739*5f7ddb14SDimitry Andric CopyDbgUsers[MaybeDead].begin(), CopyDbgUsers[MaybeDead].end());
740*5f7ddb14SDimitry Andric MRI->updateDbgUsersToReg(DestReg.asMCReg(), SrcReg.asMCReg(),
741*5f7ddb14SDimitry Andric MaybeDeadDbgUsers);
7420b57cec5SDimitry Andric
7430b57cec5SDimitry Andric MaybeDead->eraseFromParent();
7440b57cec5SDimitry Andric Changed = true;
7450b57cec5SDimitry Andric ++NumDeletes;
7460b57cec5SDimitry Andric }
7470b57cec5SDimitry Andric }
7480b57cec5SDimitry Andric
7490b57cec5SDimitry Andric MaybeDeadCopies.clear();
7508bcb0991SDimitry Andric CopyDbgUsers.clear();
7510b57cec5SDimitry Andric Tracker.clear();
7520b57cec5SDimitry Andric }
7530b57cec5SDimitry Andric
isBackwardPropagatableCopy(MachineInstr & MI,const MachineRegisterInfo & MRI)754480093f4SDimitry Andric static bool isBackwardPropagatableCopy(MachineInstr &MI,
755480093f4SDimitry Andric const MachineRegisterInfo &MRI) {
756480093f4SDimitry Andric assert(MI.isCopy() && "MI is expected to be a COPY");
757480093f4SDimitry Andric Register Def = MI.getOperand(0).getReg();
758480093f4SDimitry Andric Register Src = MI.getOperand(1).getReg();
759480093f4SDimitry Andric
760480093f4SDimitry Andric if (!Def || !Src)
761480093f4SDimitry Andric return false;
762480093f4SDimitry Andric
763480093f4SDimitry Andric if (MRI.isReserved(Def) || MRI.isReserved(Src))
764480093f4SDimitry Andric return false;
765480093f4SDimitry Andric
766480093f4SDimitry Andric return MI.getOperand(1).isRenamable() && MI.getOperand(1).isKill();
767480093f4SDimitry Andric }
768480093f4SDimitry Andric
propagateDefs(MachineInstr & MI)769480093f4SDimitry Andric void MachineCopyPropagation::propagateDefs(MachineInstr &MI) {
770480093f4SDimitry Andric if (!Tracker.hasAnyCopies())
771480093f4SDimitry Andric return;
772480093f4SDimitry Andric
773480093f4SDimitry Andric for (unsigned OpIdx = 0, OpEnd = MI.getNumOperands(); OpIdx != OpEnd;
774480093f4SDimitry Andric ++OpIdx) {
775480093f4SDimitry Andric MachineOperand &MODef = MI.getOperand(OpIdx);
776480093f4SDimitry Andric
777480093f4SDimitry Andric if (!MODef.isReg() || MODef.isUse())
778480093f4SDimitry Andric continue;
779480093f4SDimitry Andric
780480093f4SDimitry Andric // Ignore non-trivial cases.
781480093f4SDimitry Andric if (MODef.isTied() || MODef.isUndef() || MODef.isImplicit())
782480093f4SDimitry Andric continue;
783480093f4SDimitry Andric
784480093f4SDimitry Andric if (!MODef.getReg())
785480093f4SDimitry Andric continue;
786480093f4SDimitry Andric
787480093f4SDimitry Andric // We only handle if the register comes from a vreg.
788480093f4SDimitry Andric if (!MODef.isRenamable())
789480093f4SDimitry Andric continue;
790480093f4SDimitry Andric
791480093f4SDimitry Andric MachineInstr *Copy =
792af732203SDimitry Andric Tracker.findAvailBackwardCopy(MI, MODef.getReg().asMCReg(), *TRI);
793480093f4SDimitry Andric if (!Copy)
794480093f4SDimitry Andric continue;
795480093f4SDimitry Andric
796480093f4SDimitry Andric Register Def = Copy->getOperand(0).getReg();
797480093f4SDimitry Andric Register Src = Copy->getOperand(1).getReg();
798480093f4SDimitry Andric
799480093f4SDimitry Andric if (MODef.getReg() != Src)
800480093f4SDimitry Andric continue;
801480093f4SDimitry Andric
802480093f4SDimitry Andric if (!isBackwardPropagatableRegClassCopy(*Copy, MI, OpIdx))
803480093f4SDimitry Andric continue;
804480093f4SDimitry Andric
805480093f4SDimitry Andric if (hasImplicitOverlap(MI, MODef))
806480093f4SDimitry Andric continue;
807480093f4SDimitry Andric
808af732203SDimitry Andric if (hasOverlappingMultipleDef(MI, MODef, Def))
809af732203SDimitry Andric continue;
810af732203SDimitry Andric
811480093f4SDimitry Andric LLVM_DEBUG(dbgs() << "MCP: Replacing " << printReg(MODef.getReg(), TRI)
812480093f4SDimitry Andric << "\n with " << printReg(Def, TRI) << "\n in "
813480093f4SDimitry Andric << MI << " from " << *Copy);
814480093f4SDimitry Andric
815480093f4SDimitry Andric MODef.setReg(Def);
816480093f4SDimitry Andric MODef.setIsRenamable(Copy->getOperand(0).isRenamable());
817480093f4SDimitry Andric
818480093f4SDimitry Andric LLVM_DEBUG(dbgs() << "MCP: After replacement: " << MI << "\n");
819480093f4SDimitry Andric MaybeDeadCopies.insert(Copy);
820480093f4SDimitry Andric Changed = true;
821480093f4SDimitry Andric ++NumCopyBackwardPropagated;
822480093f4SDimitry Andric }
823480093f4SDimitry Andric }
824480093f4SDimitry Andric
BackwardCopyPropagateBlock(MachineBasicBlock & MBB)825480093f4SDimitry Andric void MachineCopyPropagation::BackwardCopyPropagateBlock(
826480093f4SDimitry Andric MachineBasicBlock &MBB) {
827480093f4SDimitry Andric LLVM_DEBUG(dbgs() << "MCP: BackwardCopyPropagateBlock " << MBB.getName()
828480093f4SDimitry Andric << "\n");
829480093f4SDimitry Andric
830480093f4SDimitry Andric for (MachineBasicBlock::reverse_iterator I = MBB.rbegin(), E = MBB.rend();
831480093f4SDimitry Andric I != E;) {
832480093f4SDimitry Andric MachineInstr *MI = &*I;
833480093f4SDimitry Andric ++I;
834480093f4SDimitry Andric
835480093f4SDimitry Andric // Ignore non-trivial COPYs.
836480093f4SDimitry Andric if (MI->isCopy() && MI->getNumOperands() == 2 &&
837480093f4SDimitry Andric !TRI->regsOverlap(MI->getOperand(0).getReg(),
838480093f4SDimitry Andric MI->getOperand(1).getReg())) {
839480093f4SDimitry Andric
840af732203SDimitry Andric MCRegister Def = MI->getOperand(0).getReg().asMCReg();
841af732203SDimitry Andric MCRegister Src = MI->getOperand(1).getReg().asMCReg();
842480093f4SDimitry Andric
843480093f4SDimitry Andric // Unlike forward cp, we don't invoke propagateDefs here,
844480093f4SDimitry Andric // just let forward cp do COPY-to-COPY propagation.
845480093f4SDimitry Andric if (isBackwardPropagatableCopy(*MI, *MRI)) {
846480093f4SDimitry Andric Tracker.invalidateRegister(Src, *TRI);
847480093f4SDimitry Andric Tracker.invalidateRegister(Def, *TRI);
848480093f4SDimitry Andric Tracker.trackCopy(MI, *TRI);
849480093f4SDimitry Andric continue;
850480093f4SDimitry Andric }
851480093f4SDimitry Andric }
852480093f4SDimitry Andric
853480093f4SDimitry Andric // Invalidate any earlyclobber regs first.
854480093f4SDimitry Andric for (const MachineOperand &MO : MI->operands())
855480093f4SDimitry Andric if (MO.isReg() && MO.isEarlyClobber()) {
856af732203SDimitry Andric MCRegister Reg = MO.getReg().asMCReg();
857480093f4SDimitry Andric if (!Reg)
858480093f4SDimitry Andric continue;
859480093f4SDimitry Andric Tracker.invalidateRegister(Reg, *TRI);
860480093f4SDimitry Andric }
861480093f4SDimitry Andric
862480093f4SDimitry Andric propagateDefs(*MI);
863480093f4SDimitry Andric for (const MachineOperand &MO : MI->operands()) {
864480093f4SDimitry Andric if (!MO.isReg())
865480093f4SDimitry Andric continue;
866480093f4SDimitry Andric
867480093f4SDimitry Andric if (!MO.getReg())
868480093f4SDimitry Andric continue;
869480093f4SDimitry Andric
870480093f4SDimitry Andric if (MO.isDef())
871af732203SDimitry Andric Tracker.invalidateRegister(MO.getReg().asMCReg(), *TRI);
872480093f4SDimitry Andric
873*5f7ddb14SDimitry Andric if (MO.readsReg()) {
874*5f7ddb14SDimitry Andric if (MO.isDebug()) {
875*5f7ddb14SDimitry Andric // Check if the register in the debug instruction is utilized
876*5f7ddb14SDimitry Andric // in a copy instruction, so we can update the debug info if the
877*5f7ddb14SDimitry Andric // register is changed.
878*5f7ddb14SDimitry Andric for (MCRegUnitIterator RUI(MO.getReg().asMCReg(), TRI); RUI.isValid();
879*5f7ddb14SDimitry Andric ++RUI) {
880*5f7ddb14SDimitry Andric if (auto *Copy = Tracker.findCopyDefViaUnit(*RUI, *TRI)) {
881*5f7ddb14SDimitry Andric CopyDbgUsers[Copy].insert(MI);
882*5f7ddb14SDimitry Andric }
883*5f7ddb14SDimitry Andric }
884*5f7ddb14SDimitry Andric } else {
885af732203SDimitry Andric Tracker.invalidateRegister(MO.getReg().asMCReg(), *TRI);
886480093f4SDimitry Andric }
887480093f4SDimitry Andric }
888*5f7ddb14SDimitry Andric }
889*5f7ddb14SDimitry Andric }
890480093f4SDimitry Andric
891480093f4SDimitry Andric for (auto *Copy : MaybeDeadCopies) {
892*5f7ddb14SDimitry Andric
893*5f7ddb14SDimitry Andric Register Src = Copy->getOperand(1).getReg();
894*5f7ddb14SDimitry Andric Register Def = Copy->getOperand(0).getReg();
895*5f7ddb14SDimitry Andric SmallVector<MachineInstr *> MaybeDeadDbgUsers(CopyDbgUsers[Copy].begin(),
896*5f7ddb14SDimitry Andric CopyDbgUsers[Copy].end());
897*5f7ddb14SDimitry Andric
898*5f7ddb14SDimitry Andric MRI->updateDbgUsersToReg(Src.asMCReg(), Def.asMCReg(), MaybeDeadDbgUsers);
899480093f4SDimitry Andric Copy->eraseFromParent();
900480093f4SDimitry Andric ++NumDeletes;
901480093f4SDimitry Andric }
902480093f4SDimitry Andric
903480093f4SDimitry Andric MaybeDeadCopies.clear();
904480093f4SDimitry Andric CopyDbgUsers.clear();
905480093f4SDimitry Andric Tracker.clear();
906480093f4SDimitry Andric }
907480093f4SDimitry Andric
runOnMachineFunction(MachineFunction & MF)9080b57cec5SDimitry Andric bool MachineCopyPropagation::runOnMachineFunction(MachineFunction &MF) {
9090b57cec5SDimitry Andric if (skipFunction(MF.getFunction()))
9100b57cec5SDimitry Andric return false;
9110b57cec5SDimitry Andric
9120b57cec5SDimitry Andric Changed = false;
9130b57cec5SDimitry Andric
9140b57cec5SDimitry Andric TRI = MF.getSubtarget().getRegisterInfo();
9150b57cec5SDimitry Andric TII = MF.getSubtarget().getInstrInfo();
9160b57cec5SDimitry Andric MRI = &MF.getRegInfo();
9170b57cec5SDimitry Andric
918480093f4SDimitry Andric for (MachineBasicBlock &MBB : MF) {
919480093f4SDimitry Andric BackwardCopyPropagateBlock(MBB);
920480093f4SDimitry Andric ForwardCopyPropagateBlock(MBB);
921480093f4SDimitry Andric }
9220b57cec5SDimitry Andric
9230b57cec5SDimitry Andric return Changed;
9240b57cec5SDimitry Andric }
925