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; 91e8d8bef9SDimitry Andric SmallVector<MCRegister, 4> DefRegs; 920b57cec5SDimitry Andric bool Avail; 930b57cec5SDimitry Andric }; 940b57cec5SDimitry Andric 95e8d8bef9SDimitry 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. 100e8d8bef9SDimitry Andric void markRegsUnavailable(ArrayRef<MCRegister> Regs, 1010b57cec5SDimitry Andric const TargetRegisterInfo &TRI) { 102e8d8bef9SDimitry 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. 113e8d8bef9SDimitry 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. 117e8d8bef9SDimitry 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) { 123e8d8bef9SDimitry Andric RegsToInvalidate.insert(MI->getOperand(0).getReg().asMCReg()); 124e8d8bef9SDimitry 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 } 130e8d8bef9SDimitry 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. 136e8d8bef9SDimitry 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) 146e8d8bef9SDimitry 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. 1540b57cec5SDimitry Andric void trackCopy(MachineInstr *MI, const TargetRegisterInfo &TRI) { 1550b57cec5SDimitry Andric assert(MI->isCopy() && "Tracking non-copy?"); 1560b57cec5SDimitry Andric 157e8d8bef9SDimitry Andric MCRegister Def = MI->getOperand(0).getReg().asMCReg(); 158e8d8bef9SDimitry 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 1740b57cec5SDimitry Andric bool hasAnyCopies() { 1750b57cec5SDimitry Andric return !Copies.empty(); 1760b57cec5SDimitry Andric } 1770b57cec5SDimitry Andric 178e8d8bef9SDimitry Andric MachineInstr *findCopyForUnit(MCRegister RegUnit, 179e8d8bef9SDimitry 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 189e8d8bef9SDimitry 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 200e8d8bef9SDimitry 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 221e8d8bef9SDimitry 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 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 2590b57cec5SDimitry Andric MachineCopyPropagation() : MachineFunctionPass(ID) { 2600b57cec5SDimitry Andric initializeMachineCopyPropagationPass(*PassRegistry::getPassRegistry()); 2610b57cec5SDimitry Andric } 2620b57cec5SDimitry Andric 2630b57cec5SDimitry 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 2700b57cec5SDimitry 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 278e8d8bef9SDimitry Andric void ReadRegister(MCRegister Reg, MachineInstr &Reader, DebugType DT); 279480093f4SDimitry Andric void ForwardCopyPropagateBlock(MachineBasicBlock &MBB); 280480093f4SDimitry Andric void BackwardCopyPropagateBlock(MachineBasicBlock &MBB); 281e8d8bef9SDimitry 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); 290e8d8bef9SDimitry Andric bool hasOverlappingMultipleDef(const MachineInstr &MI, 291e8d8bef9SDimitry 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 297fe6060f1SDimitry 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 313e8d8bef9SDimitry 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 { 324fe6060f1SDimitry 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 336e8d8bef9SDimitry Andric static bool isNopCopy(const MachineInstr &PreviousCopy, MCRegister Src, 337e8d8bef9SDimitry Andric MCRegister Def, const TargetRegisterInfo *TRI) { 338e8d8bef9SDimitry Andric MCRegister PreviousSrc = PreviousCopy.getOperand(1).getReg().asMCReg(); 339e8d8bef9SDimitry 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. 351e8d8bef9SDimitry Andric bool MachineCopyPropagation::eraseIfRedundant(MachineInstr &Copy, 352e8d8bef9SDimitry 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 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. 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 417349cc55cSDimitry Andric const TargetRegisterClass *CopySrcRC = 418349cc55cSDimitry Andric TRI->getMinimalPhysRegClass(CopySrcReg); 419349cc55cSDimitry Andric const TargetRegisterClass *UseDstRC = 420349cc55cSDimitry Andric TRI->getMinimalPhysRegClass(UseI.getOperand(0).getReg()); 421349cc55cSDimitry Andric const TargetRegisterClass *CrossCopyRC = TRI->getCrossCopyRegClass(CopySrcRC); 422349cc55cSDimitry Andric 423349cc55cSDimitry Andric // If cross copy register class is not the same as copy source register class 424349cc55cSDimitry Andric // then it is not possible to copy the register directly and requires a cross 425349cc55cSDimitry Andric // register class copy. Fowarding this copy without checking register class of 426349cc55cSDimitry Andric // UseDst may create additional cross register copies when expanding the copy 427349cc55cSDimitry Andric // instruction in later passes. 428349cc55cSDimitry Andric if (CopySrcRC != CrossCopyRC) { 429349cc55cSDimitry Andric const TargetRegisterClass *CopyDstRC = 430349cc55cSDimitry Andric TRI->getMinimalPhysRegClass(Copy.getOperand(0).getReg()); 431349cc55cSDimitry Andric 432349cc55cSDimitry Andric // Check if UseDstRC matches the necessary register class to copy from 433349cc55cSDimitry Andric // CopySrc's register class. If so then forwarding the copy will not 434349cc55cSDimitry Andric // introduce any cross-class copys. Else if CopyDstRC matches then keep the 435349cc55cSDimitry Andric // copy and do not forward. If neither UseDstRC or CopyDstRC matches then 436349cc55cSDimitry Andric // we may need a cross register copy later but we do not worry about it 437349cc55cSDimitry Andric // here. 438349cc55cSDimitry Andric if (UseDstRC != CrossCopyRC && CopyDstRC == CrossCopyRC) 439349cc55cSDimitry Andric return false; 440349cc55cSDimitry Andric } 441349cc55cSDimitry Andric 4420b57cec5SDimitry Andric /// COPYs don't have register class constraints, so if the user instruction 4430b57cec5SDimitry Andric /// is a COPY, we just try to avoid introducing additional cross-class 4440b57cec5SDimitry Andric /// COPYs. For example: 4450b57cec5SDimitry Andric /// 4460b57cec5SDimitry Andric /// RegClassA = COPY RegClassB // Copy parameter 4470b57cec5SDimitry Andric /// ... 4480b57cec5SDimitry Andric /// RegClassB = COPY RegClassA // UseI parameter 4490b57cec5SDimitry Andric /// 4500b57cec5SDimitry Andric /// which after forwarding becomes 4510b57cec5SDimitry Andric /// 4520b57cec5SDimitry Andric /// RegClassA = COPY RegClassB 4530b57cec5SDimitry Andric /// ... 4540b57cec5SDimitry Andric /// RegClassB = COPY RegClassB 4550b57cec5SDimitry Andric /// 4560b57cec5SDimitry Andric /// so we have reduced the number of cross-class COPYs and potentially 4570b57cec5SDimitry Andric /// introduced a nop COPY that can be removed. 4580b57cec5SDimitry Andric const TargetRegisterClass *SuperRC = UseDstRC; 4590b57cec5SDimitry Andric for (TargetRegisterClass::sc_iterator SuperRCI = UseDstRC->getSuperClasses(); 4600b57cec5SDimitry Andric SuperRC; SuperRC = *SuperRCI++) 4610b57cec5SDimitry Andric if (SuperRC->contains(CopySrcReg)) 4620b57cec5SDimitry Andric return true; 4630b57cec5SDimitry Andric 4640b57cec5SDimitry Andric return false; 4650b57cec5SDimitry Andric } 4660b57cec5SDimitry Andric 4670b57cec5SDimitry Andric /// Check that \p MI does not have implicit uses that overlap with it's \p Use 4680b57cec5SDimitry Andric /// operand (the register being replaced), since these can sometimes be 4690b57cec5SDimitry Andric /// implicitly tied to other operands. For example, on AMDGPU: 4700b57cec5SDimitry Andric /// 4710b57cec5SDimitry Andric /// V_MOVRELS_B32_e32 %VGPR2, %M0<imp-use>, %EXEC<imp-use>, %VGPR2_VGPR3_VGPR4_VGPR5<imp-use> 4720b57cec5SDimitry Andric /// 4730b57cec5SDimitry Andric /// the %VGPR2 is implicitly tied to the larger reg operand, but we have no 4740b57cec5SDimitry Andric /// way of knowing we need to update the latter when updating the former. 4750b57cec5SDimitry Andric bool MachineCopyPropagation::hasImplicitOverlap(const MachineInstr &MI, 4760b57cec5SDimitry Andric const MachineOperand &Use) { 4770b57cec5SDimitry Andric for (const MachineOperand &MIUse : MI.uses()) 4780b57cec5SDimitry Andric if (&MIUse != &Use && MIUse.isReg() && MIUse.isImplicit() && 4790b57cec5SDimitry Andric MIUse.isUse() && TRI->regsOverlap(Use.getReg(), MIUse.getReg())) 4800b57cec5SDimitry Andric return true; 4810b57cec5SDimitry Andric 4820b57cec5SDimitry Andric return false; 4830b57cec5SDimitry Andric } 4840b57cec5SDimitry Andric 485e8d8bef9SDimitry Andric /// For an MI that has multiple definitions, check whether \p MI has 486e8d8bef9SDimitry Andric /// a definition that overlaps with another of its definitions. 487e8d8bef9SDimitry Andric /// For example, on ARM: umull r9, r9, lr, r0 488e8d8bef9SDimitry Andric /// The umull instruction is unpredictable unless RdHi and RdLo are different. 489e8d8bef9SDimitry Andric bool MachineCopyPropagation::hasOverlappingMultipleDef( 490e8d8bef9SDimitry Andric const MachineInstr &MI, const MachineOperand &MODef, Register Def) { 491e8d8bef9SDimitry Andric for (const MachineOperand &MIDef : MI.defs()) { 492e8d8bef9SDimitry Andric if ((&MIDef != &MODef) && MIDef.isReg() && 493e8d8bef9SDimitry Andric TRI->regsOverlap(Def, MIDef.getReg())) 494e8d8bef9SDimitry Andric return true; 495e8d8bef9SDimitry Andric } 496e8d8bef9SDimitry Andric 497e8d8bef9SDimitry Andric return false; 498e8d8bef9SDimitry Andric } 499e8d8bef9SDimitry Andric 5000b57cec5SDimitry Andric /// Look for available copies whose destination register is used by \p MI and 5010b57cec5SDimitry Andric /// replace the use in \p MI with the copy's source register. 5020b57cec5SDimitry Andric void MachineCopyPropagation::forwardUses(MachineInstr &MI) { 5030b57cec5SDimitry Andric if (!Tracker.hasAnyCopies()) 5040b57cec5SDimitry Andric return; 5050b57cec5SDimitry Andric 5060b57cec5SDimitry Andric // Look for non-tied explicit vreg uses that have an active COPY 5070b57cec5SDimitry Andric // instruction that defines the physical register allocated to them. 5080b57cec5SDimitry Andric // Replace the vreg with the source of the active COPY. 5090b57cec5SDimitry Andric for (unsigned OpIdx = 0, OpEnd = MI.getNumOperands(); OpIdx < OpEnd; 5100b57cec5SDimitry Andric ++OpIdx) { 5110b57cec5SDimitry Andric MachineOperand &MOUse = MI.getOperand(OpIdx); 5120b57cec5SDimitry Andric // Don't forward into undef use operands since doing so can cause problems 5130b57cec5SDimitry Andric // with the machine verifier, since it doesn't treat undef reads as reads, 5140b57cec5SDimitry Andric // so we can end up with a live range that ends on an undef read, leading to 5150b57cec5SDimitry Andric // an error that the live range doesn't end on a read of the live range 5160b57cec5SDimitry Andric // register. 5170b57cec5SDimitry Andric if (!MOUse.isReg() || MOUse.isTied() || MOUse.isUndef() || MOUse.isDef() || 5180b57cec5SDimitry Andric MOUse.isImplicit()) 5190b57cec5SDimitry Andric continue; 5200b57cec5SDimitry Andric 5210b57cec5SDimitry Andric if (!MOUse.getReg()) 5220b57cec5SDimitry Andric continue; 5230b57cec5SDimitry Andric 5240b57cec5SDimitry Andric // Check that the register is marked 'renamable' so we know it is safe to 5250b57cec5SDimitry Andric // rename it without violating any constraints that aren't expressed in the 5260b57cec5SDimitry Andric // IR (e.g. ABI or opcode requirements). 5270b57cec5SDimitry Andric if (!MOUse.isRenamable()) 5280b57cec5SDimitry Andric continue; 5290b57cec5SDimitry Andric 530e8d8bef9SDimitry Andric MachineInstr *Copy = 531e8d8bef9SDimitry Andric Tracker.findAvailCopy(MI, MOUse.getReg().asMCReg(), *TRI); 5320b57cec5SDimitry Andric if (!Copy) 5330b57cec5SDimitry Andric continue; 5340b57cec5SDimitry Andric 5358bcb0991SDimitry Andric Register CopyDstReg = Copy->getOperand(0).getReg(); 5360b57cec5SDimitry Andric const MachineOperand &CopySrc = Copy->getOperand(1); 5378bcb0991SDimitry Andric Register CopySrcReg = CopySrc.getReg(); 5380b57cec5SDimitry Andric 5390b57cec5SDimitry Andric // FIXME: Don't handle partial uses of wider COPYs yet. 5400b57cec5SDimitry Andric if (MOUse.getReg() != CopyDstReg) { 5410b57cec5SDimitry Andric LLVM_DEBUG( 5420b57cec5SDimitry Andric dbgs() << "MCP: FIXME! Not forwarding COPY to sub-register use:\n " 5430b57cec5SDimitry Andric << MI); 5440b57cec5SDimitry Andric continue; 5450b57cec5SDimitry Andric } 5460b57cec5SDimitry Andric 5470b57cec5SDimitry Andric // Don't forward COPYs of reserved regs unless they are constant. 5480b57cec5SDimitry Andric if (MRI->isReserved(CopySrcReg) && !MRI->isConstantPhysReg(CopySrcReg)) 5490b57cec5SDimitry Andric continue; 5500b57cec5SDimitry Andric 5510b57cec5SDimitry Andric if (!isForwardableRegClassCopy(*Copy, MI, OpIdx)) 5520b57cec5SDimitry Andric continue; 5530b57cec5SDimitry Andric 5540b57cec5SDimitry Andric if (hasImplicitOverlap(MI, MOUse)) 5550b57cec5SDimitry Andric continue; 5560b57cec5SDimitry Andric 557480093f4SDimitry Andric // Check that the instruction is not a copy that partially overwrites the 558480093f4SDimitry Andric // original copy source that we are about to use. The tracker mechanism 559480093f4SDimitry Andric // cannot cope with that. 560480093f4SDimitry Andric if (MI.isCopy() && MI.modifiesRegister(CopySrcReg, TRI) && 561480093f4SDimitry Andric !MI.definesRegister(CopySrcReg)) { 562480093f4SDimitry Andric LLVM_DEBUG(dbgs() << "MCP: Copy source overlap with dest in " << MI); 563480093f4SDimitry Andric continue; 564480093f4SDimitry Andric } 565480093f4SDimitry Andric 5660b57cec5SDimitry Andric if (!DebugCounter::shouldExecute(FwdCounter)) { 5670b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "MCP: Skipping forwarding due to debug counter:\n " 5680b57cec5SDimitry Andric << MI); 5690b57cec5SDimitry Andric continue; 5700b57cec5SDimitry Andric } 5710b57cec5SDimitry Andric 5720b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "MCP: Replacing " << printReg(MOUse.getReg(), TRI) 5730b57cec5SDimitry Andric << "\n with " << printReg(CopySrcReg, TRI) 5740b57cec5SDimitry Andric << "\n in " << MI << " from " << *Copy); 5750b57cec5SDimitry Andric 5760b57cec5SDimitry Andric MOUse.setReg(CopySrcReg); 5770b57cec5SDimitry Andric if (!CopySrc.isRenamable()) 5780b57cec5SDimitry Andric MOUse.setIsRenamable(false); 579349cc55cSDimitry Andric MOUse.setIsUndef(CopySrc.isUndef()); 5800b57cec5SDimitry Andric 5810b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "MCP: After replacement: " << MI << "\n"); 5820b57cec5SDimitry Andric 5830b57cec5SDimitry Andric // Clear kill markers that may have been invalidated. 5840b57cec5SDimitry Andric for (MachineInstr &KMI : 5850b57cec5SDimitry Andric make_range(Copy->getIterator(), std::next(MI.getIterator()))) 5860b57cec5SDimitry Andric KMI.clearRegisterKills(CopySrcReg, TRI); 5870b57cec5SDimitry Andric 5880b57cec5SDimitry Andric ++NumCopyForwards; 5890b57cec5SDimitry Andric Changed = true; 5900b57cec5SDimitry Andric } 5910b57cec5SDimitry Andric } 5920b57cec5SDimitry Andric 593480093f4SDimitry Andric void MachineCopyPropagation::ForwardCopyPropagateBlock(MachineBasicBlock &MBB) { 594480093f4SDimitry Andric LLVM_DEBUG(dbgs() << "MCP: ForwardCopyPropagateBlock " << MBB.getName() 595480093f4SDimitry Andric << "\n"); 5960b57cec5SDimitry Andric 597349cc55cSDimitry Andric for (MachineInstr &MI : llvm::make_early_inc_range(MBB)) { 5980b57cec5SDimitry Andric // Analyze copies (which don't overlap themselves). 599349cc55cSDimitry Andric if (MI.isCopy() && !TRI->regsOverlap(MI.getOperand(0).getReg(), 600349cc55cSDimitry Andric MI.getOperand(1).getReg())) { 601349cc55cSDimitry Andric assert(MI.getOperand(0).getReg().isPhysical() && 602349cc55cSDimitry Andric MI.getOperand(1).getReg().isPhysical() && 6030b57cec5SDimitry Andric "MachineCopyPropagation should be run after register allocation!"); 6040b57cec5SDimitry Andric 605349cc55cSDimitry Andric MCRegister Def = MI.getOperand(0).getReg().asMCReg(); 606349cc55cSDimitry Andric MCRegister Src = MI.getOperand(1).getReg().asMCReg(); 607e8d8bef9SDimitry Andric 6080b57cec5SDimitry Andric // The two copies cancel out and the source of the first copy 6090b57cec5SDimitry Andric // hasn't been overridden, eliminate the second one. e.g. 6100b57cec5SDimitry Andric // %ecx = COPY %eax 6110b57cec5SDimitry Andric // ... nothing clobbered eax. 6120b57cec5SDimitry Andric // %eax = COPY %ecx 6130b57cec5SDimitry Andric // => 6140b57cec5SDimitry Andric // %ecx = COPY %eax 6150b57cec5SDimitry Andric // 6160b57cec5SDimitry Andric // or 6170b57cec5SDimitry Andric // 6180b57cec5SDimitry Andric // %ecx = COPY %eax 6190b57cec5SDimitry Andric // ... nothing clobbered eax. 6200b57cec5SDimitry Andric // %ecx = COPY %eax 6210b57cec5SDimitry Andric // => 6220b57cec5SDimitry Andric // %ecx = COPY %eax 623349cc55cSDimitry Andric if (eraseIfRedundant(MI, Def, Src) || eraseIfRedundant(MI, Src, Def)) 6240b57cec5SDimitry Andric continue; 6250b57cec5SDimitry Andric 626349cc55cSDimitry Andric forwardUses(MI); 6270b57cec5SDimitry Andric 6280b57cec5SDimitry Andric // Src may have been changed by forwardUses() 629349cc55cSDimitry Andric Src = MI.getOperand(1).getReg().asMCReg(); 6300b57cec5SDimitry Andric 6310b57cec5SDimitry Andric // If Src is defined by a previous copy, the previous copy cannot be 6320b57cec5SDimitry Andric // eliminated. 633349cc55cSDimitry Andric ReadRegister(Src, MI, RegularUse); 634349cc55cSDimitry Andric for (const MachineOperand &MO : MI.implicit_operands()) { 6350b57cec5SDimitry Andric if (!MO.isReg() || !MO.readsReg()) 6360b57cec5SDimitry Andric continue; 637e8d8bef9SDimitry Andric MCRegister Reg = MO.getReg().asMCReg(); 6380b57cec5SDimitry Andric if (!Reg) 6390b57cec5SDimitry Andric continue; 640349cc55cSDimitry Andric ReadRegister(Reg, MI, RegularUse); 6410b57cec5SDimitry Andric } 6420b57cec5SDimitry Andric 643349cc55cSDimitry Andric LLVM_DEBUG(dbgs() << "MCP: Copy is a deletion candidate: "; MI.dump()); 6440b57cec5SDimitry Andric 6450b57cec5SDimitry Andric // Copy is now a candidate for deletion. 6460b57cec5SDimitry Andric if (!MRI->isReserved(Def)) 647349cc55cSDimitry Andric MaybeDeadCopies.insert(&MI); 6480b57cec5SDimitry Andric 6490b57cec5SDimitry Andric // If 'Def' is previously source of another copy, then this earlier copy's 6500b57cec5SDimitry Andric // source is no longer available. e.g. 6510b57cec5SDimitry Andric // %xmm9 = copy %xmm2 6520b57cec5SDimitry Andric // ... 6530b57cec5SDimitry Andric // %xmm2 = copy %xmm0 6540b57cec5SDimitry Andric // ... 6550b57cec5SDimitry Andric // %xmm2 = copy %xmm9 6560b57cec5SDimitry Andric Tracker.clobberRegister(Def, *TRI); 657349cc55cSDimitry Andric for (const MachineOperand &MO : MI.implicit_operands()) { 6580b57cec5SDimitry Andric if (!MO.isReg() || !MO.isDef()) 6590b57cec5SDimitry Andric continue; 660e8d8bef9SDimitry Andric MCRegister Reg = MO.getReg().asMCReg(); 6610b57cec5SDimitry Andric if (!Reg) 6620b57cec5SDimitry Andric continue; 6630b57cec5SDimitry Andric Tracker.clobberRegister(Reg, *TRI); 6640b57cec5SDimitry Andric } 6650b57cec5SDimitry Andric 666349cc55cSDimitry Andric Tracker.trackCopy(&MI, *TRI); 6670b57cec5SDimitry Andric 6680b57cec5SDimitry Andric continue; 6690b57cec5SDimitry Andric } 6700b57cec5SDimitry Andric 6710b57cec5SDimitry Andric // Clobber any earlyclobber regs first. 672349cc55cSDimitry Andric for (const MachineOperand &MO : MI.operands()) 6730b57cec5SDimitry Andric if (MO.isReg() && MO.isEarlyClobber()) { 674e8d8bef9SDimitry Andric MCRegister Reg = MO.getReg().asMCReg(); 6750b57cec5SDimitry Andric // If we have a tied earlyclobber, that means it is also read by this 6760b57cec5SDimitry Andric // instruction, so we need to make sure we don't remove it as dead 6770b57cec5SDimitry Andric // later. 6780b57cec5SDimitry Andric if (MO.isTied()) 679349cc55cSDimitry Andric ReadRegister(Reg, MI, RegularUse); 6800b57cec5SDimitry Andric Tracker.clobberRegister(Reg, *TRI); 6810b57cec5SDimitry Andric } 6820b57cec5SDimitry Andric 683349cc55cSDimitry Andric forwardUses(MI); 6840b57cec5SDimitry Andric 6850b57cec5SDimitry Andric // Not a copy. 686e8d8bef9SDimitry Andric SmallVector<Register, 2> Defs; 6870b57cec5SDimitry Andric const MachineOperand *RegMask = nullptr; 688349cc55cSDimitry Andric for (const MachineOperand &MO : MI.operands()) { 6890b57cec5SDimitry Andric if (MO.isRegMask()) 6900b57cec5SDimitry Andric RegMask = &MO; 6910b57cec5SDimitry Andric if (!MO.isReg()) 6920b57cec5SDimitry Andric continue; 6938bcb0991SDimitry Andric Register Reg = MO.getReg(); 6940b57cec5SDimitry Andric if (!Reg) 6950b57cec5SDimitry Andric continue; 6960b57cec5SDimitry Andric 697e8d8bef9SDimitry Andric assert(!Reg.isVirtual() && 6980b57cec5SDimitry Andric "MachineCopyPropagation should be run after register allocation!"); 6990b57cec5SDimitry Andric 7000b57cec5SDimitry Andric if (MO.isDef() && !MO.isEarlyClobber()) { 701e8d8bef9SDimitry Andric Defs.push_back(Reg.asMCReg()); 7020b57cec5SDimitry Andric continue; 7038bcb0991SDimitry Andric } else if (MO.readsReg()) 704349cc55cSDimitry Andric ReadRegister(Reg.asMCReg(), MI, MO.isDebug() ? DebugUse : RegularUse); 7050b57cec5SDimitry Andric } 7060b57cec5SDimitry Andric 7070b57cec5SDimitry Andric // The instruction has a register mask operand which means that it clobbers 7080b57cec5SDimitry Andric // a large set of registers. Treat clobbered registers the same way as 7090b57cec5SDimitry Andric // defined registers. 7100b57cec5SDimitry Andric if (RegMask) { 7110b57cec5SDimitry Andric // Erase any MaybeDeadCopies whose destination register is clobbered. 7120b57cec5SDimitry Andric for (SmallSetVector<MachineInstr *, 8>::iterator DI = 7130b57cec5SDimitry Andric MaybeDeadCopies.begin(); 7140b57cec5SDimitry Andric DI != MaybeDeadCopies.end();) { 7150b57cec5SDimitry Andric MachineInstr *MaybeDead = *DI; 716e8d8bef9SDimitry Andric MCRegister Reg = MaybeDead->getOperand(0).getReg().asMCReg(); 7170b57cec5SDimitry Andric assert(!MRI->isReserved(Reg)); 7180b57cec5SDimitry Andric 7190b57cec5SDimitry Andric if (!RegMask->clobbersPhysReg(Reg)) { 7200b57cec5SDimitry Andric ++DI; 7210b57cec5SDimitry Andric continue; 7220b57cec5SDimitry Andric } 7230b57cec5SDimitry Andric 7240b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "MCP: Removing copy due to regmask clobbering: "; 7250b57cec5SDimitry Andric MaybeDead->dump()); 7260b57cec5SDimitry Andric 7270b57cec5SDimitry Andric // Make sure we invalidate any entries in the copy maps before erasing 7280b57cec5SDimitry Andric // the instruction. 7290b57cec5SDimitry Andric Tracker.clobberRegister(Reg, *TRI); 7300b57cec5SDimitry Andric 7310b57cec5SDimitry Andric // erase() will return the next valid iterator pointing to the next 7320b57cec5SDimitry Andric // element after the erased one. 7330b57cec5SDimitry Andric DI = MaybeDeadCopies.erase(DI); 7340b57cec5SDimitry Andric MaybeDead->eraseFromParent(); 7350b57cec5SDimitry Andric Changed = true; 7360b57cec5SDimitry Andric ++NumDeletes; 7370b57cec5SDimitry Andric } 7380b57cec5SDimitry Andric } 7390b57cec5SDimitry Andric 7400b57cec5SDimitry Andric // Any previous copy definition or reading the Defs is no longer available. 741e8d8bef9SDimitry Andric for (MCRegister Reg : Defs) 7420b57cec5SDimitry Andric Tracker.clobberRegister(Reg, *TRI); 7430b57cec5SDimitry Andric } 7440b57cec5SDimitry Andric 7450b57cec5SDimitry Andric // If MBB doesn't have successors, delete the copies whose defs are not used. 7460b57cec5SDimitry Andric // If MBB does have successors, then conservative assume the defs are live-out 7470b57cec5SDimitry Andric // since we don't want to trust live-in lists. 7480b57cec5SDimitry Andric if (MBB.succ_empty()) { 7490b57cec5SDimitry Andric for (MachineInstr *MaybeDead : MaybeDeadCopies) { 7500b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "MCP: Removing copy due to no live-out succ: "; 7510b57cec5SDimitry Andric MaybeDead->dump()); 7520b57cec5SDimitry Andric assert(!MRI->isReserved(MaybeDead->getOperand(0).getReg())); 7530b57cec5SDimitry Andric 7548bcb0991SDimitry Andric // Update matching debug values, if any. 7550b57cec5SDimitry Andric assert(MaybeDead->isCopy()); 756e8d8bef9SDimitry Andric Register SrcReg = MaybeDead->getOperand(1).getReg(); 757fe6060f1SDimitry Andric Register DestReg = MaybeDead->getOperand(0).getReg(); 758fe6060f1SDimitry Andric SmallVector<MachineInstr *> MaybeDeadDbgUsers( 759fe6060f1SDimitry Andric CopyDbgUsers[MaybeDead].begin(), CopyDbgUsers[MaybeDead].end()); 760fe6060f1SDimitry Andric MRI->updateDbgUsersToReg(DestReg.asMCReg(), SrcReg.asMCReg(), 761fe6060f1SDimitry Andric MaybeDeadDbgUsers); 7620b57cec5SDimitry Andric 7630b57cec5SDimitry Andric MaybeDead->eraseFromParent(); 7640b57cec5SDimitry Andric Changed = true; 7650b57cec5SDimitry Andric ++NumDeletes; 7660b57cec5SDimitry Andric } 7670b57cec5SDimitry Andric } 7680b57cec5SDimitry Andric 7690b57cec5SDimitry Andric MaybeDeadCopies.clear(); 7708bcb0991SDimitry Andric CopyDbgUsers.clear(); 7710b57cec5SDimitry Andric Tracker.clear(); 7720b57cec5SDimitry Andric } 7730b57cec5SDimitry Andric 774480093f4SDimitry Andric static bool isBackwardPropagatableCopy(MachineInstr &MI, 775480093f4SDimitry Andric const MachineRegisterInfo &MRI) { 776480093f4SDimitry Andric assert(MI.isCopy() && "MI is expected to be a COPY"); 777480093f4SDimitry Andric Register Def = MI.getOperand(0).getReg(); 778480093f4SDimitry Andric Register Src = MI.getOperand(1).getReg(); 779480093f4SDimitry Andric 780480093f4SDimitry Andric if (!Def || !Src) 781480093f4SDimitry Andric return false; 782480093f4SDimitry Andric 783480093f4SDimitry Andric if (MRI.isReserved(Def) || MRI.isReserved(Src)) 784480093f4SDimitry Andric return false; 785480093f4SDimitry Andric 786480093f4SDimitry Andric return MI.getOperand(1).isRenamable() && MI.getOperand(1).isKill(); 787480093f4SDimitry Andric } 788480093f4SDimitry Andric 789480093f4SDimitry Andric void MachineCopyPropagation::propagateDefs(MachineInstr &MI) { 790480093f4SDimitry Andric if (!Tracker.hasAnyCopies()) 791480093f4SDimitry Andric return; 792480093f4SDimitry Andric 793480093f4SDimitry Andric for (unsigned OpIdx = 0, OpEnd = MI.getNumOperands(); OpIdx != OpEnd; 794480093f4SDimitry Andric ++OpIdx) { 795480093f4SDimitry Andric MachineOperand &MODef = MI.getOperand(OpIdx); 796480093f4SDimitry Andric 797480093f4SDimitry Andric if (!MODef.isReg() || MODef.isUse()) 798480093f4SDimitry Andric continue; 799480093f4SDimitry Andric 800480093f4SDimitry Andric // Ignore non-trivial cases. 801480093f4SDimitry Andric if (MODef.isTied() || MODef.isUndef() || MODef.isImplicit()) 802480093f4SDimitry Andric continue; 803480093f4SDimitry Andric 804480093f4SDimitry Andric if (!MODef.getReg()) 805480093f4SDimitry Andric continue; 806480093f4SDimitry Andric 807480093f4SDimitry Andric // We only handle if the register comes from a vreg. 808480093f4SDimitry Andric if (!MODef.isRenamable()) 809480093f4SDimitry Andric continue; 810480093f4SDimitry Andric 811480093f4SDimitry Andric MachineInstr *Copy = 812e8d8bef9SDimitry Andric Tracker.findAvailBackwardCopy(MI, MODef.getReg().asMCReg(), *TRI); 813480093f4SDimitry Andric if (!Copy) 814480093f4SDimitry Andric continue; 815480093f4SDimitry Andric 816480093f4SDimitry Andric Register Def = Copy->getOperand(0).getReg(); 817480093f4SDimitry Andric Register Src = Copy->getOperand(1).getReg(); 818480093f4SDimitry Andric 819480093f4SDimitry Andric if (MODef.getReg() != Src) 820480093f4SDimitry Andric continue; 821480093f4SDimitry Andric 822480093f4SDimitry Andric if (!isBackwardPropagatableRegClassCopy(*Copy, MI, OpIdx)) 823480093f4SDimitry Andric continue; 824480093f4SDimitry Andric 825480093f4SDimitry Andric if (hasImplicitOverlap(MI, MODef)) 826480093f4SDimitry Andric continue; 827480093f4SDimitry Andric 828e8d8bef9SDimitry Andric if (hasOverlappingMultipleDef(MI, MODef, Def)) 829e8d8bef9SDimitry Andric continue; 830e8d8bef9SDimitry Andric 831480093f4SDimitry Andric LLVM_DEBUG(dbgs() << "MCP: Replacing " << printReg(MODef.getReg(), TRI) 832480093f4SDimitry Andric << "\n with " << printReg(Def, TRI) << "\n in " 833480093f4SDimitry Andric << MI << " from " << *Copy); 834480093f4SDimitry Andric 835480093f4SDimitry Andric MODef.setReg(Def); 836480093f4SDimitry Andric MODef.setIsRenamable(Copy->getOperand(0).isRenamable()); 837480093f4SDimitry Andric 838480093f4SDimitry Andric LLVM_DEBUG(dbgs() << "MCP: After replacement: " << MI << "\n"); 839480093f4SDimitry Andric MaybeDeadCopies.insert(Copy); 840480093f4SDimitry Andric Changed = true; 841480093f4SDimitry Andric ++NumCopyBackwardPropagated; 842480093f4SDimitry Andric } 843480093f4SDimitry Andric } 844480093f4SDimitry Andric 845480093f4SDimitry Andric void MachineCopyPropagation::BackwardCopyPropagateBlock( 846480093f4SDimitry Andric MachineBasicBlock &MBB) { 847480093f4SDimitry Andric LLVM_DEBUG(dbgs() << "MCP: BackwardCopyPropagateBlock " << MBB.getName() 848480093f4SDimitry Andric << "\n"); 849480093f4SDimitry Andric 850*0eae32dcSDimitry Andric for (MachineInstr &MI : llvm::make_early_inc_range(llvm::reverse(MBB))) { 851480093f4SDimitry Andric // Ignore non-trivial COPYs. 852*0eae32dcSDimitry Andric if (MI.isCopy() && MI.getNumOperands() == 2 && 853*0eae32dcSDimitry Andric !TRI->regsOverlap(MI.getOperand(0).getReg(), 854*0eae32dcSDimitry Andric MI.getOperand(1).getReg())) { 855480093f4SDimitry Andric 856*0eae32dcSDimitry Andric MCRegister Def = MI.getOperand(0).getReg().asMCReg(); 857*0eae32dcSDimitry Andric MCRegister Src = MI.getOperand(1).getReg().asMCReg(); 858480093f4SDimitry Andric 859480093f4SDimitry Andric // Unlike forward cp, we don't invoke propagateDefs here, 860480093f4SDimitry Andric // just let forward cp do COPY-to-COPY propagation. 861*0eae32dcSDimitry Andric if (isBackwardPropagatableCopy(MI, *MRI)) { 862480093f4SDimitry Andric Tracker.invalidateRegister(Src, *TRI); 863480093f4SDimitry Andric Tracker.invalidateRegister(Def, *TRI); 864*0eae32dcSDimitry Andric Tracker.trackCopy(&MI, *TRI); 865480093f4SDimitry Andric continue; 866480093f4SDimitry Andric } 867480093f4SDimitry Andric } 868480093f4SDimitry Andric 869480093f4SDimitry Andric // Invalidate any earlyclobber regs first. 870*0eae32dcSDimitry Andric for (const MachineOperand &MO : MI.operands()) 871480093f4SDimitry Andric if (MO.isReg() && MO.isEarlyClobber()) { 872e8d8bef9SDimitry Andric MCRegister Reg = MO.getReg().asMCReg(); 873480093f4SDimitry Andric if (!Reg) 874480093f4SDimitry Andric continue; 875480093f4SDimitry Andric Tracker.invalidateRegister(Reg, *TRI); 876480093f4SDimitry Andric } 877480093f4SDimitry Andric 878*0eae32dcSDimitry Andric propagateDefs(MI); 879*0eae32dcSDimitry Andric for (const MachineOperand &MO : MI.operands()) { 880480093f4SDimitry Andric if (!MO.isReg()) 881480093f4SDimitry Andric continue; 882480093f4SDimitry Andric 883480093f4SDimitry Andric if (!MO.getReg()) 884480093f4SDimitry Andric continue; 885480093f4SDimitry Andric 886480093f4SDimitry Andric if (MO.isDef()) 887e8d8bef9SDimitry Andric Tracker.invalidateRegister(MO.getReg().asMCReg(), *TRI); 888480093f4SDimitry Andric 889fe6060f1SDimitry Andric if (MO.readsReg()) { 890fe6060f1SDimitry Andric if (MO.isDebug()) { 891fe6060f1SDimitry Andric // Check if the register in the debug instruction is utilized 892fe6060f1SDimitry Andric // in a copy instruction, so we can update the debug info if the 893fe6060f1SDimitry Andric // register is changed. 894fe6060f1SDimitry Andric for (MCRegUnitIterator RUI(MO.getReg().asMCReg(), TRI); RUI.isValid(); 895fe6060f1SDimitry Andric ++RUI) { 896fe6060f1SDimitry Andric if (auto *Copy = Tracker.findCopyDefViaUnit(*RUI, *TRI)) { 897*0eae32dcSDimitry Andric CopyDbgUsers[Copy].insert(&MI); 898fe6060f1SDimitry Andric } 899fe6060f1SDimitry Andric } 900fe6060f1SDimitry Andric } else { 901e8d8bef9SDimitry Andric Tracker.invalidateRegister(MO.getReg().asMCReg(), *TRI); 902480093f4SDimitry Andric } 903480093f4SDimitry Andric } 904fe6060f1SDimitry Andric } 905fe6060f1SDimitry Andric } 906480093f4SDimitry Andric 907480093f4SDimitry Andric for (auto *Copy : MaybeDeadCopies) { 908fe6060f1SDimitry Andric 909fe6060f1SDimitry Andric Register Src = Copy->getOperand(1).getReg(); 910fe6060f1SDimitry Andric Register Def = Copy->getOperand(0).getReg(); 911fe6060f1SDimitry Andric SmallVector<MachineInstr *> MaybeDeadDbgUsers(CopyDbgUsers[Copy].begin(), 912fe6060f1SDimitry Andric CopyDbgUsers[Copy].end()); 913fe6060f1SDimitry Andric 914fe6060f1SDimitry Andric MRI->updateDbgUsersToReg(Src.asMCReg(), Def.asMCReg(), MaybeDeadDbgUsers); 915480093f4SDimitry Andric Copy->eraseFromParent(); 916480093f4SDimitry Andric ++NumDeletes; 917480093f4SDimitry Andric } 918480093f4SDimitry Andric 919480093f4SDimitry Andric MaybeDeadCopies.clear(); 920480093f4SDimitry Andric CopyDbgUsers.clear(); 921480093f4SDimitry Andric Tracker.clear(); 922480093f4SDimitry Andric } 923480093f4SDimitry Andric 9240b57cec5SDimitry Andric bool MachineCopyPropagation::runOnMachineFunction(MachineFunction &MF) { 9250b57cec5SDimitry Andric if (skipFunction(MF.getFunction())) 9260b57cec5SDimitry Andric return false; 9270b57cec5SDimitry Andric 9280b57cec5SDimitry Andric Changed = false; 9290b57cec5SDimitry Andric 9300b57cec5SDimitry Andric TRI = MF.getSubtarget().getRegisterInfo(); 9310b57cec5SDimitry Andric TII = MF.getSubtarget().getInstrInfo(); 9320b57cec5SDimitry Andric MRI = &MF.getRegInfo(); 9330b57cec5SDimitry Andric 934480093f4SDimitry Andric for (MachineBasicBlock &MBB : MF) { 935480093f4SDimitry Andric BackwardCopyPropagateBlock(MBB); 936480093f4SDimitry Andric ForwardCopyPropagateBlock(MBB); 937480093f4SDimitry Andric } 9380b57cec5SDimitry Andric 9390b57cec5SDimitry Andric return Changed; 9400b57cec5SDimitry Andric } 941