1*0b57cec5SDimitry Andric //===- MachineCopyPropagation.cpp - Machine Copy Propagation Pass ---------===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric // 9*0b57cec5SDimitry Andric // This is an extremely simple MachineInstr-level copy propagation pass. 10*0b57cec5SDimitry Andric // 11*0b57cec5SDimitry Andric // This pass forwards the source of COPYs to the users of their destinations 12*0b57cec5SDimitry Andric // when doing so is legal. For example: 13*0b57cec5SDimitry Andric // 14*0b57cec5SDimitry Andric // %reg1 = COPY %reg0 15*0b57cec5SDimitry Andric // ... 16*0b57cec5SDimitry Andric // ... = OP %reg1 17*0b57cec5SDimitry Andric // 18*0b57cec5SDimitry Andric // If 19*0b57cec5SDimitry Andric // - %reg0 has not been clobbered by the time of the use of %reg1 20*0b57cec5SDimitry Andric // - the register class constraints are satisfied 21*0b57cec5SDimitry Andric // - the COPY def is the only value that reaches OP 22*0b57cec5SDimitry Andric // then this pass replaces the above with: 23*0b57cec5SDimitry Andric // 24*0b57cec5SDimitry Andric // %reg1 = COPY %reg0 25*0b57cec5SDimitry Andric // ... 26*0b57cec5SDimitry Andric // ... = OP %reg0 27*0b57cec5SDimitry Andric // 28*0b57cec5SDimitry Andric // This pass also removes some redundant COPYs. For example: 29*0b57cec5SDimitry Andric // 30*0b57cec5SDimitry Andric // %R1 = COPY %R0 31*0b57cec5SDimitry Andric // ... // No clobber of %R1 32*0b57cec5SDimitry Andric // %R0 = COPY %R1 <<< Removed 33*0b57cec5SDimitry Andric // 34*0b57cec5SDimitry Andric // or 35*0b57cec5SDimitry Andric // 36*0b57cec5SDimitry Andric // %R1 = COPY %R0 37*0b57cec5SDimitry Andric // ... // No clobber of %R0 38*0b57cec5SDimitry Andric // %R1 = COPY %R0 <<< Removed 39*0b57cec5SDimitry Andric // 40*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 41*0b57cec5SDimitry Andric 42*0b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h" 43*0b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h" 44*0b57cec5SDimitry Andric #include "llvm/ADT/SetVector.h" 45*0b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 46*0b57cec5SDimitry Andric #include "llvm/ADT/Statistic.h" 47*0b57cec5SDimitry Andric #include "llvm/ADT/iterator_range.h" 48*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h" 49*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 50*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h" 51*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstr.h" 52*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineOperand.h" 53*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h" 54*0b57cec5SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h" 55*0b57cec5SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h" 56*0b57cec5SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h" 57*0b57cec5SDimitry Andric #include "llvm/MC/MCRegisterInfo.h" 58*0b57cec5SDimitry Andric #include "llvm/Pass.h" 59*0b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 60*0b57cec5SDimitry Andric #include "llvm/Support/DebugCounter.h" 61*0b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 62*0b57cec5SDimitry Andric #include <cassert> 63*0b57cec5SDimitry Andric #include <iterator> 64*0b57cec5SDimitry Andric 65*0b57cec5SDimitry Andric using namespace llvm; 66*0b57cec5SDimitry Andric 67*0b57cec5SDimitry Andric #define DEBUG_TYPE "machine-cp" 68*0b57cec5SDimitry Andric 69*0b57cec5SDimitry Andric STATISTIC(NumDeletes, "Number of dead copies deleted"); 70*0b57cec5SDimitry Andric STATISTIC(NumCopyForwards, "Number of copy uses forwarded"); 71*0b57cec5SDimitry Andric DEBUG_COUNTER(FwdCounter, "machine-cp-fwd", 72*0b57cec5SDimitry Andric "Controls which register COPYs are forwarded"); 73*0b57cec5SDimitry Andric 74*0b57cec5SDimitry Andric namespace { 75*0b57cec5SDimitry Andric 76*0b57cec5SDimitry Andric class CopyTracker { 77*0b57cec5SDimitry Andric struct CopyInfo { 78*0b57cec5SDimitry Andric MachineInstr *MI; 79*0b57cec5SDimitry Andric SmallVector<unsigned, 4> DefRegs; 80*0b57cec5SDimitry Andric bool Avail; 81*0b57cec5SDimitry Andric }; 82*0b57cec5SDimitry Andric 83*0b57cec5SDimitry Andric DenseMap<unsigned, CopyInfo> Copies; 84*0b57cec5SDimitry Andric 85*0b57cec5SDimitry Andric public: 86*0b57cec5SDimitry Andric /// Mark all of the given registers and their subregisters as unavailable for 87*0b57cec5SDimitry Andric /// copying. 88*0b57cec5SDimitry Andric void markRegsUnavailable(ArrayRef<unsigned> Regs, 89*0b57cec5SDimitry Andric const TargetRegisterInfo &TRI) { 90*0b57cec5SDimitry Andric for (unsigned Reg : Regs) { 91*0b57cec5SDimitry Andric // Source of copy is no longer available for propagation. 92*0b57cec5SDimitry Andric for (MCRegUnitIterator RUI(Reg, &TRI); RUI.isValid(); ++RUI) { 93*0b57cec5SDimitry Andric auto CI = Copies.find(*RUI); 94*0b57cec5SDimitry Andric if (CI != Copies.end()) 95*0b57cec5SDimitry Andric CI->second.Avail = false; 96*0b57cec5SDimitry Andric } 97*0b57cec5SDimitry Andric } 98*0b57cec5SDimitry Andric } 99*0b57cec5SDimitry Andric 100*0b57cec5SDimitry Andric /// Clobber a single register, removing it from the tracker's copy maps. 101*0b57cec5SDimitry Andric void clobberRegister(unsigned Reg, const TargetRegisterInfo &TRI) { 102*0b57cec5SDimitry Andric for (MCRegUnitIterator RUI(Reg, &TRI); RUI.isValid(); ++RUI) { 103*0b57cec5SDimitry Andric auto I = Copies.find(*RUI); 104*0b57cec5SDimitry Andric if (I != Copies.end()) { 105*0b57cec5SDimitry Andric // When we clobber the source of a copy, we need to clobber everything 106*0b57cec5SDimitry Andric // it defined. 107*0b57cec5SDimitry Andric markRegsUnavailable(I->second.DefRegs, TRI); 108*0b57cec5SDimitry Andric // When we clobber the destination of a copy, we need to clobber the 109*0b57cec5SDimitry Andric // whole register it defined. 110*0b57cec5SDimitry Andric if (MachineInstr *MI = I->second.MI) 111*0b57cec5SDimitry Andric markRegsUnavailable({MI->getOperand(0).getReg()}, TRI); 112*0b57cec5SDimitry Andric // Now we can erase the copy. 113*0b57cec5SDimitry Andric Copies.erase(I); 114*0b57cec5SDimitry Andric } 115*0b57cec5SDimitry Andric } 116*0b57cec5SDimitry Andric } 117*0b57cec5SDimitry Andric 118*0b57cec5SDimitry Andric /// Add this copy's registers into the tracker's copy maps. 119*0b57cec5SDimitry Andric void trackCopy(MachineInstr *MI, const TargetRegisterInfo &TRI) { 120*0b57cec5SDimitry Andric assert(MI->isCopy() && "Tracking non-copy?"); 121*0b57cec5SDimitry Andric 122*0b57cec5SDimitry Andric unsigned Def = MI->getOperand(0).getReg(); 123*0b57cec5SDimitry Andric unsigned Src = MI->getOperand(1).getReg(); 124*0b57cec5SDimitry Andric 125*0b57cec5SDimitry Andric // Remember Def is defined by the copy. 126*0b57cec5SDimitry Andric for (MCRegUnitIterator RUI(Def, &TRI); RUI.isValid(); ++RUI) 127*0b57cec5SDimitry Andric Copies[*RUI] = {MI, {}, true}; 128*0b57cec5SDimitry Andric 129*0b57cec5SDimitry Andric // Remember source that's copied to Def. Once it's clobbered, then 130*0b57cec5SDimitry Andric // it's no longer available for copy propagation. 131*0b57cec5SDimitry Andric for (MCRegUnitIterator RUI(Src, &TRI); RUI.isValid(); ++RUI) { 132*0b57cec5SDimitry Andric auto I = Copies.insert({*RUI, {nullptr, {}, false}}); 133*0b57cec5SDimitry Andric auto &Copy = I.first->second; 134*0b57cec5SDimitry Andric if (!is_contained(Copy.DefRegs, Def)) 135*0b57cec5SDimitry Andric Copy.DefRegs.push_back(Def); 136*0b57cec5SDimitry Andric } 137*0b57cec5SDimitry Andric } 138*0b57cec5SDimitry Andric 139*0b57cec5SDimitry Andric bool hasAnyCopies() { 140*0b57cec5SDimitry Andric return !Copies.empty(); 141*0b57cec5SDimitry Andric } 142*0b57cec5SDimitry Andric 143*0b57cec5SDimitry Andric MachineInstr *findCopyForUnit(unsigned RegUnit, const TargetRegisterInfo &TRI, 144*0b57cec5SDimitry Andric bool MustBeAvailable = false) { 145*0b57cec5SDimitry Andric auto CI = Copies.find(RegUnit); 146*0b57cec5SDimitry Andric if (CI == Copies.end()) 147*0b57cec5SDimitry Andric return nullptr; 148*0b57cec5SDimitry Andric if (MustBeAvailable && !CI->second.Avail) 149*0b57cec5SDimitry Andric return nullptr; 150*0b57cec5SDimitry Andric return CI->second.MI; 151*0b57cec5SDimitry Andric } 152*0b57cec5SDimitry Andric 153*0b57cec5SDimitry Andric MachineInstr *findAvailCopy(MachineInstr &DestCopy, unsigned Reg, 154*0b57cec5SDimitry Andric const TargetRegisterInfo &TRI) { 155*0b57cec5SDimitry Andric // We check the first RegUnit here, since we'll only be interested in the 156*0b57cec5SDimitry Andric // copy if it copies the entire register anyway. 157*0b57cec5SDimitry Andric MCRegUnitIterator RUI(Reg, &TRI); 158*0b57cec5SDimitry Andric MachineInstr *AvailCopy = 159*0b57cec5SDimitry Andric findCopyForUnit(*RUI, TRI, /*MustBeAvailable=*/true); 160*0b57cec5SDimitry Andric if (!AvailCopy || 161*0b57cec5SDimitry Andric !TRI.isSubRegisterEq(AvailCopy->getOperand(0).getReg(), Reg)) 162*0b57cec5SDimitry Andric return nullptr; 163*0b57cec5SDimitry Andric 164*0b57cec5SDimitry Andric // Check that the available copy isn't clobbered by any regmasks between 165*0b57cec5SDimitry Andric // itself and the destination. 166*0b57cec5SDimitry Andric unsigned AvailSrc = AvailCopy->getOperand(1).getReg(); 167*0b57cec5SDimitry Andric unsigned AvailDef = AvailCopy->getOperand(0).getReg(); 168*0b57cec5SDimitry Andric for (const MachineInstr &MI : 169*0b57cec5SDimitry Andric make_range(AvailCopy->getIterator(), DestCopy.getIterator())) 170*0b57cec5SDimitry Andric for (const MachineOperand &MO : MI.operands()) 171*0b57cec5SDimitry Andric if (MO.isRegMask()) 172*0b57cec5SDimitry Andric if (MO.clobbersPhysReg(AvailSrc) || MO.clobbersPhysReg(AvailDef)) 173*0b57cec5SDimitry Andric return nullptr; 174*0b57cec5SDimitry Andric 175*0b57cec5SDimitry Andric return AvailCopy; 176*0b57cec5SDimitry Andric } 177*0b57cec5SDimitry Andric 178*0b57cec5SDimitry Andric void clear() { 179*0b57cec5SDimitry Andric Copies.clear(); 180*0b57cec5SDimitry Andric } 181*0b57cec5SDimitry Andric }; 182*0b57cec5SDimitry Andric 183*0b57cec5SDimitry Andric class MachineCopyPropagation : public MachineFunctionPass { 184*0b57cec5SDimitry Andric const TargetRegisterInfo *TRI; 185*0b57cec5SDimitry Andric const TargetInstrInfo *TII; 186*0b57cec5SDimitry Andric const MachineRegisterInfo *MRI; 187*0b57cec5SDimitry Andric 188*0b57cec5SDimitry Andric public: 189*0b57cec5SDimitry Andric static char ID; // Pass identification, replacement for typeid 190*0b57cec5SDimitry Andric 191*0b57cec5SDimitry Andric MachineCopyPropagation() : MachineFunctionPass(ID) { 192*0b57cec5SDimitry Andric initializeMachineCopyPropagationPass(*PassRegistry::getPassRegistry()); 193*0b57cec5SDimitry Andric } 194*0b57cec5SDimitry Andric 195*0b57cec5SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override { 196*0b57cec5SDimitry Andric AU.setPreservesCFG(); 197*0b57cec5SDimitry Andric MachineFunctionPass::getAnalysisUsage(AU); 198*0b57cec5SDimitry Andric } 199*0b57cec5SDimitry Andric 200*0b57cec5SDimitry Andric bool runOnMachineFunction(MachineFunction &MF) override; 201*0b57cec5SDimitry Andric 202*0b57cec5SDimitry Andric MachineFunctionProperties getRequiredProperties() const override { 203*0b57cec5SDimitry Andric return MachineFunctionProperties().set( 204*0b57cec5SDimitry Andric MachineFunctionProperties::Property::NoVRegs); 205*0b57cec5SDimitry Andric } 206*0b57cec5SDimitry Andric 207*0b57cec5SDimitry Andric private: 208*0b57cec5SDimitry Andric void ClobberRegister(unsigned Reg); 209*0b57cec5SDimitry Andric void ReadRegister(unsigned Reg); 210*0b57cec5SDimitry Andric void CopyPropagateBlock(MachineBasicBlock &MBB); 211*0b57cec5SDimitry Andric bool eraseIfRedundant(MachineInstr &Copy, unsigned Src, unsigned Def); 212*0b57cec5SDimitry Andric void forwardUses(MachineInstr &MI); 213*0b57cec5SDimitry Andric bool isForwardableRegClassCopy(const MachineInstr &Copy, 214*0b57cec5SDimitry Andric const MachineInstr &UseI, unsigned UseIdx); 215*0b57cec5SDimitry Andric bool hasImplicitOverlap(const MachineInstr &MI, const MachineOperand &Use); 216*0b57cec5SDimitry Andric 217*0b57cec5SDimitry Andric /// Candidates for deletion. 218*0b57cec5SDimitry Andric SmallSetVector<MachineInstr *, 8> MaybeDeadCopies; 219*0b57cec5SDimitry Andric 220*0b57cec5SDimitry Andric CopyTracker Tracker; 221*0b57cec5SDimitry Andric 222*0b57cec5SDimitry Andric bool Changed; 223*0b57cec5SDimitry Andric }; 224*0b57cec5SDimitry Andric 225*0b57cec5SDimitry Andric } // end anonymous namespace 226*0b57cec5SDimitry Andric 227*0b57cec5SDimitry Andric char MachineCopyPropagation::ID = 0; 228*0b57cec5SDimitry Andric 229*0b57cec5SDimitry Andric char &llvm::MachineCopyPropagationID = MachineCopyPropagation::ID; 230*0b57cec5SDimitry Andric 231*0b57cec5SDimitry Andric INITIALIZE_PASS(MachineCopyPropagation, DEBUG_TYPE, 232*0b57cec5SDimitry Andric "Machine Copy Propagation Pass", false, false) 233*0b57cec5SDimitry Andric 234*0b57cec5SDimitry Andric void MachineCopyPropagation::ReadRegister(unsigned Reg) { 235*0b57cec5SDimitry Andric // If 'Reg' is defined by a copy, the copy is no longer a candidate 236*0b57cec5SDimitry Andric // for elimination. 237*0b57cec5SDimitry Andric for (MCRegUnitIterator RUI(Reg, TRI); RUI.isValid(); ++RUI) { 238*0b57cec5SDimitry Andric if (MachineInstr *Copy = Tracker.findCopyForUnit(*RUI, *TRI)) { 239*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "MCP: Copy is used - not dead: "; Copy->dump()); 240*0b57cec5SDimitry Andric MaybeDeadCopies.remove(Copy); 241*0b57cec5SDimitry Andric } 242*0b57cec5SDimitry Andric } 243*0b57cec5SDimitry Andric } 244*0b57cec5SDimitry Andric 245*0b57cec5SDimitry Andric /// Return true if \p PreviousCopy did copy register \p Src to register \p Def. 246*0b57cec5SDimitry Andric /// This fact may have been obscured by sub register usage or may not be true at 247*0b57cec5SDimitry Andric /// all even though Src and Def are subregisters of the registers used in 248*0b57cec5SDimitry Andric /// PreviousCopy. e.g. 249*0b57cec5SDimitry Andric /// isNopCopy("ecx = COPY eax", AX, CX) == true 250*0b57cec5SDimitry Andric /// isNopCopy("ecx = COPY eax", AH, CL) == false 251*0b57cec5SDimitry Andric static bool isNopCopy(const MachineInstr &PreviousCopy, unsigned Src, 252*0b57cec5SDimitry Andric unsigned Def, const TargetRegisterInfo *TRI) { 253*0b57cec5SDimitry Andric unsigned PreviousSrc = PreviousCopy.getOperand(1).getReg(); 254*0b57cec5SDimitry Andric unsigned PreviousDef = PreviousCopy.getOperand(0).getReg(); 255*0b57cec5SDimitry Andric if (Src == PreviousSrc) { 256*0b57cec5SDimitry Andric assert(Def == PreviousDef); 257*0b57cec5SDimitry Andric return true; 258*0b57cec5SDimitry Andric } 259*0b57cec5SDimitry Andric if (!TRI->isSubRegister(PreviousSrc, Src)) 260*0b57cec5SDimitry Andric return false; 261*0b57cec5SDimitry Andric unsigned SubIdx = TRI->getSubRegIndex(PreviousSrc, Src); 262*0b57cec5SDimitry Andric return SubIdx == TRI->getSubRegIndex(PreviousDef, Def); 263*0b57cec5SDimitry Andric } 264*0b57cec5SDimitry Andric 265*0b57cec5SDimitry Andric /// Remove instruction \p Copy if there exists a previous copy that copies the 266*0b57cec5SDimitry Andric /// register \p Src to the register \p Def; This may happen indirectly by 267*0b57cec5SDimitry Andric /// copying the super registers. 268*0b57cec5SDimitry Andric bool MachineCopyPropagation::eraseIfRedundant(MachineInstr &Copy, unsigned Src, 269*0b57cec5SDimitry Andric unsigned Def) { 270*0b57cec5SDimitry Andric // Avoid eliminating a copy from/to a reserved registers as we cannot predict 271*0b57cec5SDimitry Andric // the value (Example: The sparc zero register is writable but stays zero). 272*0b57cec5SDimitry Andric if (MRI->isReserved(Src) || MRI->isReserved(Def)) 273*0b57cec5SDimitry Andric return false; 274*0b57cec5SDimitry Andric 275*0b57cec5SDimitry Andric // Search for an existing copy. 276*0b57cec5SDimitry Andric MachineInstr *PrevCopy = Tracker.findAvailCopy(Copy, Def, *TRI); 277*0b57cec5SDimitry Andric if (!PrevCopy) 278*0b57cec5SDimitry Andric return false; 279*0b57cec5SDimitry Andric 280*0b57cec5SDimitry Andric // Check that the existing copy uses the correct sub registers. 281*0b57cec5SDimitry Andric if (PrevCopy->getOperand(0).isDead()) 282*0b57cec5SDimitry Andric return false; 283*0b57cec5SDimitry Andric if (!isNopCopy(*PrevCopy, Src, Def, TRI)) 284*0b57cec5SDimitry Andric return false; 285*0b57cec5SDimitry Andric 286*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "MCP: copy is a NOP, removing: "; Copy.dump()); 287*0b57cec5SDimitry Andric 288*0b57cec5SDimitry Andric // Copy was redundantly redefining either Src or Def. Remove earlier kill 289*0b57cec5SDimitry Andric // flags between Copy and PrevCopy because the value will be reused now. 290*0b57cec5SDimitry Andric assert(Copy.isCopy()); 291*0b57cec5SDimitry Andric unsigned CopyDef = Copy.getOperand(0).getReg(); 292*0b57cec5SDimitry Andric assert(CopyDef == Src || CopyDef == Def); 293*0b57cec5SDimitry Andric for (MachineInstr &MI : 294*0b57cec5SDimitry Andric make_range(PrevCopy->getIterator(), Copy.getIterator())) 295*0b57cec5SDimitry Andric MI.clearRegisterKills(CopyDef, TRI); 296*0b57cec5SDimitry Andric 297*0b57cec5SDimitry Andric Copy.eraseFromParent(); 298*0b57cec5SDimitry Andric Changed = true; 299*0b57cec5SDimitry Andric ++NumDeletes; 300*0b57cec5SDimitry Andric return true; 301*0b57cec5SDimitry Andric } 302*0b57cec5SDimitry Andric 303*0b57cec5SDimitry Andric /// Decide whether we should forward the source of \param Copy to its use in 304*0b57cec5SDimitry Andric /// \param UseI based on the physical register class constraints of the opcode 305*0b57cec5SDimitry Andric /// and avoiding introducing more cross-class COPYs. 306*0b57cec5SDimitry Andric bool MachineCopyPropagation::isForwardableRegClassCopy(const MachineInstr &Copy, 307*0b57cec5SDimitry Andric const MachineInstr &UseI, 308*0b57cec5SDimitry Andric unsigned UseIdx) { 309*0b57cec5SDimitry Andric 310*0b57cec5SDimitry Andric unsigned CopySrcReg = Copy.getOperand(1).getReg(); 311*0b57cec5SDimitry Andric 312*0b57cec5SDimitry Andric // If the new register meets the opcode register constraints, then allow 313*0b57cec5SDimitry Andric // forwarding. 314*0b57cec5SDimitry Andric if (const TargetRegisterClass *URC = 315*0b57cec5SDimitry Andric UseI.getRegClassConstraint(UseIdx, TII, TRI)) 316*0b57cec5SDimitry Andric return URC->contains(CopySrcReg); 317*0b57cec5SDimitry Andric 318*0b57cec5SDimitry Andric if (!UseI.isCopy()) 319*0b57cec5SDimitry Andric return false; 320*0b57cec5SDimitry Andric 321*0b57cec5SDimitry Andric /// COPYs don't have register class constraints, so if the user instruction 322*0b57cec5SDimitry Andric /// is a COPY, we just try to avoid introducing additional cross-class 323*0b57cec5SDimitry Andric /// COPYs. For example: 324*0b57cec5SDimitry Andric /// 325*0b57cec5SDimitry Andric /// RegClassA = COPY RegClassB // Copy parameter 326*0b57cec5SDimitry Andric /// ... 327*0b57cec5SDimitry Andric /// RegClassB = COPY RegClassA // UseI parameter 328*0b57cec5SDimitry Andric /// 329*0b57cec5SDimitry Andric /// which after forwarding becomes 330*0b57cec5SDimitry Andric /// 331*0b57cec5SDimitry Andric /// RegClassA = COPY RegClassB 332*0b57cec5SDimitry Andric /// ... 333*0b57cec5SDimitry Andric /// RegClassB = COPY RegClassB 334*0b57cec5SDimitry Andric /// 335*0b57cec5SDimitry Andric /// so we have reduced the number of cross-class COPYs and potentially 336*0b57cec5SDimitry Andric /// introduced a nop COPY that can be removed. 337*0b57cec5SDimitry Andric const TargetRegisterClass *UseDstRC = 338*0b57cec5SDimitry Andric TRI->getMinimalPhysRegClass(UseI.getOperand(0).getReg()); 339*0b57cec5SDimitry Andric 340*0b57cec5SDimitry Andric const TargetRegisterClass *SuperRC = UseDstRC; 341*0b57cec5SDimitry Andric for (TargetRegisterClass::sc_iterator SuperRCI = UseDstRC->getSuperClasses(); 342*0b57cec5SDimitry Andric SuperRC; SuperRC = *SuperRCI++) 343*0b57cec5SDimitry Andric if (SuperRC->contains(CopySrcReg)) 344*0b57cec5SDimitry Andric return true; 345*0b57cec5SDimitry Andric 346*0b57cec5SDimitry Andric return false; 347*0b57cec5SDimitry Andric } 348*0b57cec5SDimitry Andric 349*0b57cec5SDimitry Andric /// Check that \p MI does not have implicit uses that overlap with it's \p Use 350*0b57cec5SDimitry Andric /// operand (the register being replaced), since these can sometimes be 351*0b57cec5SDimitry Andric /// implicitly tied to other operands. For example, on AMDGPU: 352*0b57cec5SDimitry Andric /// 353*0b57cec5SDimitry Andric /// V_MOVRELS_B32_e32 %VGPR2, %M0<imp-use>, %EXEC<imp-use>, %VGPR2_VGPR3_VGPR4_VGPR5<imp-use> 354*0b57cec5SDimitry Andric /// 355*0b57cec5SDimitry Andric /// the %VGPR2 is implicitly tied to the larger reg operand, but we have no 356*0b57cec5SDimitry Andric /// way of knowing we need to update the latter when updating the former. 357*0b57cec5SDimitry Andric bool MachineCopyPropagation::hasImplicitOverlap(const MachineInstr &MI, 358*0b57cec5SDimitry Andric const MachineOperand &Use) { 359*0b57cec5SDimitry Andric for (const MachineOperand &MIUse : MI.uses()) 360*0b57cec5SDimitry Andric if (&MIUse != &Use && MIUse.isReg() && MIUse.isImplicit() && 361*0b57cec5SDimitry Andric MIUse.isUse() && TRI->regsOverlap(Use.getReg(), MIUse.getReg())) 362*0b57cec5SDimitry Andric return true; 363*0b57cec5SDimitry Andric 364*0b57cec5SDimitry Andric return false; 365*0b57cec5SDimitry Andric } 366*0b57cec5SDimitry Andric 367*0b57cec5SDimitry Andric /// Look for available copies whose destination register is used by \p MI and 368*0b57cec5SDimitry Andric /// replace the use in \p MI with the copy's source register. 369*0b57cec5SDimitry Andric void MachineCopyPropagation::forwardUses(MachineInstr &MI) { 370*0b57cec5SDimitry Andric if (!Tracker.hasAnyCopies()) 371*0b57cec5SDimitry Andric return; 372*0b57cec5SDimitry Andric 373*0b57cec5SDimitry Andric // Look for non-tied explicit vreg uses that have an active COPY 374*0b57cec5SDimitry Andric // instruction that defines the physical register allocated to them. 375*0b57cec5SDimitry Andric // Replace the vreg with the source of the active COPY. 376*0b57cec5SDimitry Andric for (unsigned OpIdx = 0, OpEnd = MI.getNumOperands(); OpIdx < OpEnd; 377*0b57cec5SDimitry Andric ++OpIdx) { 378*0b57cec5SDimitry Andric MachineOperand &MOUse = MI.getOperand(OpIdx); 379*0b57cec5SDimitry Andric // Don't forward into undef use operands since doing so can cause problems 380*0b57cec5SDimitry Andric // with the machine verifier, since it doesn't treat undef reads as reads, 381*0b57cec5SDimitry Andric // so we can end up with a live range that ends on an undef read, leading to 382*0b57cec5SDimitry Andric // an error that the live range doesn't end on a read of the live range 383*0b57cec5SDimitry Andric // register. 384*0b57cec5SDimitry Andric if (!MOUse.isReg() || MOUse.isTied() || MOUse.isUndef() || MOUse.isDef() || 385*0b57cec5SDimitry Andric MOUse.isImplicit()) 386*0b57cec5SDimitry Andric continue; 387*0b57cec5SDimitry Andric 388*0b57cec5SDimitry Andric if (!MOUse.getReg()) 389*0b57cec5SDimitry Andric continue; 390*0b57cec5SDimitry Andric 391*0b57cec5SDimitry Andric // Check that the register is marked 'renamable' so we know it is safe to 392*0b57cec5SDimitry Andric // rename it without violating any constraints that aren't expressed in the 393*0b57cec5SDimitry Andric // IR (e.g. ABI or opcode requirements). 394*0b57cec5SDimitry Andric if (!MOUse.isRenamable()) 395*0b57cec5SDimitry Andric continue; 396*0b57cec5SDimitry Andric 397*0b57cec5SDimitry Andric MachineInstr *Copy = Tracker.findAvailCopy(MI, MOUse.getReg(), *TRI); 398*0b57cec5SDimitry Andric if (!Copy) 399*0b57cec5SDimitry Andric continue; 400*0b57cec5SDimitry Andric 401*0b57cec5SDimitry Andric unsigned CopyDstReg = Copy->getOperand(0).getReg(); 402*0b57cec5SDimitry Andric const MachineOperand &CopySrc = Copy->getOperand(1); 403*0b57cec5SDimitry Andric unsigned CopySrcReg = CopySrc.getReg(); 404*0b57cec5SDimitry Andric 405*0b57cec5SDimitry Andric // FIXME: Don't handle partial uses of wider COPYs yet. 406*0b57cec5SDimitry Andric if (MOUse.getReg() != CopyDstReg) { 407*0b57cec5SDimitry Andric LLVM_DEBUG( 408*0b57cec5SDimitry Andric dbgs() << "MCP: FIXME! Not forwarding COPY to sub-register use:\n " 409*0b57cec5SDimitry Andric << MI); 410*0b57cec5SDimitry Andric continue; 411*0b57cec5SDimitry Andric } 412*0b57cec5SDimitry Andric 413*0b57cec5SDimitry Andric // Don't forward COPYs of reserved regs unless they are constant. 414*0b57cec5SDimitry Andric if (MRI->isReserved(CopySrcReg) && !MRI->isConstantPhysReg(CopySrcReg)) 415*0b57cec5SDimitry Andric continue; 416*0b57cec5SDimitry Andric 417*0b57cec5SDimitry Andric if (!isForwardableRegClassCopy(*Copy, MI, OpIdx)) 418*0b57cec5SDimitry Andric continue; 419*0b57cec5SDimitry Andric 420*0b57cec5SDimitry Andric if (hasImplicitOverlap(MI, MOUse)) 421*0b57cec5SDimitry Andric continue; 422*0b57cec5SDimitry Andric 423*0b57cec5SDimitry Andric if (!DebugCounter::shouldExecute(FwdCounter)) { 424*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "MCP: Skipping forwarding due to debug counter:\n " 425*0b57cec5SDimitry Andric << MI); 426*0b57cec5SDimitry Andric continue; 427*0b57cec5SDimitry Andric } 428*0b57cec5SDimitry Andric 429*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "MCP: Replacing " << printReg(MOUse.getReg(), TRI) 430*0b57cec5SDimitry Andric << "\n with " << printReg(CopySrcReg, TRI) 431*0b57cec5SDimitry Andric << "\n in " << MI << " from " << *Copy); 432*0b57cec5SDimitry Andric 433*0b57cec5SDimitry Andric MOUse.setReg(CopySrcReg); 434*0b57cec5SDimitry Andric if (!CopySrc.isRenamable()) 435*0b57cec5SDimitry Andric MOUse.setIsRenamable(false); 436*0b57cec5SDimitry Andric 437*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "MCP: After replacement: " << MI << "\n"); 438*0b57cec5SDimitry Andric 439*0b57cec5SDimitry Andric // Clear kill markers that may have been invalidated. 440*0b57cec5SDimitry Andric for (MachineInstr &KMI : 441*0b57cec5SDimitry Andric make_range(Copy->getIterator(), std::next(MI.getIterator()))) 442*0b57cec5SDimitry Andric KMI.clearRegisterKills(CopySrcReg, TRI); 443*0b57cec5SDimitry Andric 444*0b57cec5SDimitry Andric ++NumCopyForwards; 445*0b57cec5SDimitry Andric Changed = true; 446*0b57cec5SDimitry Andric } 447*0b57cec5SDimitry Andric } 448*0b57cec5SDimitry Andric 449*0b57cec5SDimitry Andric void MachineCopyPropagation::CopyPropagateBlock(MachineBasicBlock &MBB) { 450*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "MCP: CopyPropagateBlock " << MBB.getName() << "\n"); 451*0b57cec5SDimitry Andric 452*0b57cec5SDimitry Andric for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end(); I != E; ) { 453*0b57cec5SDimitry Andric MachineInstr *MI = &*I; 454*0b57cec5SDimitry Andric ++I; 455*0b57cec5SDimitry Andric 456*0b57cec5SDimitry Andric // Analyze copies (which don't overlap themselves). 457*0b57cec5SDimitry Andric if (MI->isCopy() && !TRI->regsOverlap(MI->getOperand(0).getReg(), 458*0b57cec5SDimitry Andric MI->getOperand(1).getReg())) { 459*0b57cec5SDimitry Andric unsigned Def = MI->getOperand(0).getReg(); 460*0b57cec5SDimitry Andric unsigned Src = MI->getOperand(1).getReg(); 461*0b57cec5SDimitry Andric 462*0b57cec5SDimitry Andric assert(!TargetRegisterInfo::isVirtualRegister(Def) && 463*0b57cec5SDimitry Andric !TargetRegisterInfo::isVirtualRegister(Src) && 464*0b57cec5SDimitry Andric "MachineCopyPropagation should be run after register allocation!"); 465*0b57cec5SDimitry Andric 466*0b57cec5SDimitry Andric // The two copies cancel out and the source of the first copy 467*0b57cec5SDimitry Andric // hasn't been overridden, eliminate the second one. e.g. 468*0b57cec5SDimitry Andric // %ecx = COPY %eax 469*0b57cec5SDimitry Andric // ... nothing clobbered eax. 470*0b57cec5SDimitry Andric // %eax = COPY %ecx 471*0b57cec5SDimitry Andric // => 472*0b57cec5SDimitry Andric // %ecx = COPY %eax 473*0b57cec5SDimitry Andric // 474*0b57cec5SDimitry Andric // or 475*0b57cec5SDimitry Andric // 476*0b57cec5SDimitry Andric // %ecx = COPY %eax 477*0b57cec5SDimitry Andric // ... nothing clobbered eax. 478*0b57cec5SDimitry Andric // %ecx = COPY %eax 479*0b57cec5SDimitry Andric // => 480*0b57cec5SDimitry Andric // %ecx = COPY %eax 481*0b57cec5SDimitry Andric if (eraseIfRedundant(*MI, Def, Src) || eraseIfRedundant(*MI, Src, Def)) 482*0b57cec5SDimitry Andric continue; 483*0b57cec5SDimitry Andric 484*0b57cec5SDimitry Andric forwardUses(*MI); 485*0b57cec5SDimitry Andric 486*0b57cec5SDimitry Andric // Src may have been changed by forwardUses() 487*0b57cec5SDimitry Andric Src = MI->getOperand(1).getReg(); 488*0b57cec5SDimitry Andric 489*0b57cec5SDimitry Andric // If Src is defined by a previous copy, the previous copy cannot be 490*0b57cec5SDimitry Andric // eliminated. 491*0b57cec5SDimitry Andric ReadRegister(Src); 492*0b57cec5SDimitry Andric for (const MachineOperand &MO : MI->implicit_operands()) { 493*0b57cec5SDimitry Andric if (!MO.isReg() || !MO.readsReg()) 494*0b57cec5SDimitry Andric continue; 495*0b57cec5SDimitry Andric unsigned Reg = MO.getReg(); 496*0b57cec5SDimitry Andric if (!Reg) 497*0b57cec5SDimitry Andric continue; 498*0b57cec5SDimitry Andric ReadRegister(Reg); 499*0b57cec5SDimitry Andric } 500*0b57cec5SDimitry Andric 501*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "MCP: Copy is a deletion candidate: "; MI->dump()); 502*0b57cec5SDimitry Andric 503*0b57cec5SDimitry Andric // Copy is now a candidate for deletion. 504*0b57cec5SDimitry Andric if (!MRI->isReserved(Def)) 505*0b57cec5SDimitry Andric MaybeDeadCopies.insert(MI); 506*0b57cec5SDimitry Andric 507*0b57cec5SDimitry Andric // If 'Def' is previously source of another copy, then this earlier copy's 508*0b57cec5SDimitry Andric // source is no longer available. e.g. 509*0b57cec5SDimitry Andric // %xmm9 = copy %xmm2 510*0b57cec5SDimitry Andric // ... 511*0b57cec5SDimitry Andric // %xmm2 = copy %xmm0 512*0b57cec5SDimitry Andric // ... 513*0b57cec5SDimitry Andric // %xmm2 = copy %xmm9 514*0b57cec5SDimitry Andric Tracker.clobberRegister(Def, *TRI); 515*0b57cec5SDimitry Andric for (const MachineOperand &MO : MI->implicit_operands()) { 516*0b57cec5SDimitry Andric if (!MO.isReg() || !MO.isDef()) 517*0b57cec5SDimitry Andric continue; 518*0b57cec5SDimitry Andric unsigned Reg = MO.getReg(); 519*0b57cec5SDimitry Andric if (!Reg) 520*0b57cec5SDimitry Andric continue; 521*0b57cec5SDimitry Andric Tracker.clobberRegister(Reg, *TRI); 522*0b57cec5SDimitry Andric } 523*0b57cec5SDimitry Andric 524*0b57cec5SDimitry Andric Tracker.trackCopy(MI, *TRI); 525*0b57cec5SDimitry Andric 526*0b57cec5SDimitry Andric continue; 527*0b57cec5SDimitry Andric } 528*0b57cec5SDimitry Andric 529*0b57cec5SDimitry Andric // Clobber any earlyclobber regs first. 530*0b57cec5SDimitry Andric for (const MachineOperand &MO : MI->operands()) 531*0b57cec5SDimitry Andric if (MO.isReg() && MO.isEarlyClobber()) { 532*0b57cec5SDimitry Andric unsigned Reg = MO.getReg(); 533*0b57cec5SDimitry Andric // If we have a tied earlyclobber, that means it is also read by this 534*0b57cec5SDimitry Andric // instruction, so we need to make sure we don't remove it as dead 535*0b57cec5SDimitry Andric // later. 536*0b57cec5SDimitry Andric if (MO.isTied()) 537*0b57cec5SDimitry Andric ReadRegister(Reg); 538*0b57cec5SDimitry Andric Tracker.clobberRegister(Reg, *TRI); 539*0b57cec5SDimitry Andric } 540*0b57cec5SDimitry Andric 541*0b57cec5SDimitry Andric forwardUses(*MI); 542*0b57cec5SDimitry Andric 543*0b57cec5SDimitry Andric // Not a copy. 544*0b57cec5SDimitry Andric SmallVector<unsigned, 2> Defs; 545*0b57cec5SDimitry Andric const MachineOperand *RegMask = nullptr; 546*0b57cec5SDimitry Andric for (const MachineOperand &MO : MI->operands()) { 547*0b57cec5SDimitry Andric if (MO.isRegMask()) 548*0b57cec5SDimitry Andric RegMask = &MO; 549*0b57cec5SDimitry Andric if (!MO.isReg()) 550*0b57cec5SDimitry Andric continue; 551*0b57cec5SDimitry Andric unsigned Reg = MO.getReg(); 552*0b57cec5SDimitry Andric if (!Reg) 553*0b57cec5SDimitry Andric continue; 554*0b57cec5SDimitry Andric 555*0b57cec5SDimitry Andric assert(!TargetRegisterInfo::isVirtualRegister(Reg) && 556*0b57cec5SDimitry Andric "MachineCopyPropagation should be run after register allocation!"); 557*0b57cec5SDimitry Andric 558*0b57cec5SDimitry Andric if (MO.isDef() && !MO.isEarlyClobber()) { 559*0b57cec5SDimitry Andric Defs.push_back(Reg); 560*0b57cec5SDimitry Andric continue; 561*0b57cec5SDimitry Andric } else if (!MO.isDebug() && MO.readsReg()) 562*0b57cec5SDimitry Andric ReadRegister(Reg); 563*0b57cec5SDimitry Andric } 564*0b57cec5SDimitry Andric 565*0b57cec5SDimitry Andric // The instruction has a register mask operand which means that it clobbers 566*0b57cec5SDimitry Andric // a large set of registers. Treat clobbered registers the same way as 567*0b57cec5SDimitry Andric // defined registers. 568*0b57cec5SDimitry Andric if (RegMask) { 569*0b57cec5SDimitry Andric // Erase any MaybeDeadCopies whose destination register is clobbered. 570*0b57cec5SDimitry Andric for (SmallSetVector<MachineInstr *, 8>::iterator DI = 571*0b57cec5SDimitry Andric MaybeDeadCopies.begin(); 572*0b57cec5SDimitry Andric DI != MaybeDeadCopies.end();) { 573*0b57cec5SDimitry Andric MachineInstr *MaybeDead = *DI; 574*0b57cec5SDimitry Andric unsigned Reg = MaybeDead->getOperand(0).getReg(); 575*0b57cec5SDimitry Andric assert(!MRI->isReserved(Reg)); 576*0b57cec5SDimitry Andric 577*0b57cec5SDimitry Andric if (!RegMask->clobbersPhysReg(Reg)) { 578*0b57cec5SDimitry Andric ++DI; 579*0b57cec5SDimitry Andric continue; 580*0b57cec5SDimitry Andric } 581*0b57cec5SDimitry Andric 582*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "MCP: Removing copy due to regmask clobbering: "; 583*0b57cec5SDimitry Andric MaybeDead->dump()); 584*0b57cec5SDimitry Andric 585*0b57cec5SDimitry Andric // Make sure we invalidate any entries in the copy maps before erasing 586*0b57cec5SDimitry Andric // the instruction. 587*0b57cec5SDimitry Andric Tracker.clobberRegister(Reg, *TRI); 588*0b57cec5SDimitry Andric 589*0b57cec5SDimitry Andric // erase() will return the next valid iterator pointing to the next 590*0b57cec5SDimitry Andric // element after the erased one. 591*0b57cec5SDimitry Andric DI = MaybeDeadCopies.erase(DI); 592*0b57cec5SDimitry Andric MaybeDead->eraseFromParent(); 593*0b57cec5SDimitry Andric Changed = true; 594*0b57cec5SDimitry Andric ++NumDeletes; 595*0b57cec5SDimitry Andric } 596*0b57cec5SDimitry Andric } 597*0b57cec5SDimitry Andric 598*0b57cec5SDimitry Andric // Any previous copy definition or reading the Defs is no longer available. 599*0b57cec5SDimitry Andric for (unsigned Reg : Defs) 600*0b57cec5SDimitry Andric Tracker.clobberRegister(Reg, *TRI); 601*0b57cec5SDimitry Andric } 602*0b57cec5SDimitry Andric 603*0b57cec5SDimitry Andric // If MBB doesn't have successors, delete the copies whose defs are not used. 604*0b57cec5SDimitry Andric // If MBB does have successors, then conservative assume the defs are live-out 605*0b57cec5SDimitry Andric // since we don't want to trust live-in lists. 606*0b57cec5SDimitry Andric if (MBB.succ_empty()) { 607*0b57cec5SDimitry Andric for (MachineInstr *MaybeDead : MaybeDeadCopies) { 608*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "MCP: Removing copy due to no live-out succ: "; 609*0b57cec5SDimitry Andric MaybeDead->dump()); 610*0b57cec5SDimitry Andric assert(!MRI->isReserved(MaybeDead->getOperand(0).getReg())); 611*0b57cec5SDimitry Andric 612*0b57cec5SDimitry Andric // Update matching debug values. 613*0b57cec5SDimitry Andric assert(MaybeDead->isCopy()); 614*0b57cec5SDimitry Andric MaybeDead->changeDebugValuesDefReg(MaybeDead->getOperand(1).getReg()); 615*0b57cec5SDimitry Andric 616*0b57cec5SDimitry Andric MaybeDead->eraseFromParent(); 617*0b57cec5SDimitry Andric Changed = true; 618*0b57cec5SDimitry Andric ++NumDeletes; 619*0b57cec5SDimitry Andric } 620*0b57cec5SDimitry Andric } 621*0b57cec5SDimitry Andric 622*0b57cec5SDimitry Andric MaybeDeadCopies.clear(); 623*0b57cec5SDimitry Andric Tracker.clear(); 624*0b57cec5SDimitry Andric } 625*0b57cec5SDimitry Andric 626*0b57cec5SDimitry Andric bool MachineCopyPropagation::runOnMachineFunction(MachineFunction &MF) { 627*0b57cec5SDimitry Andric if (skipFunction(MF.getFunction())) 628*0b57cec5SDimitry Andric return false; 629*0b57cec5SDimitry Andric 630*0b57cec5SDimitry Andric Changed = false; 631*0b57cec5SDimitry Andric 632*0b57cec5SDimitry Andric TRI = MF.getSubtarget().getRegisterInfo(); 633*0b57cec5SDimitry Andric TII = MF.getSubtarget().getInstrInfo(); 634*0b57cec5SDimitry Andric MRI = &MF.getRegInfo(); 635*0b57cec5SDimitry Andric 636*0b57cec5SDimitry Andric for (MachineBasicBlock &MBB : MF) 637*0b57cec5SDimitry Andric CopyPropagateBlock(MBB); 638*0b57cec5SDimitry Andric 639*0b57cec5SDimitry Andric return Changed; 640*0b57cec5SDimitry Andric } 641