1*bdd1243dSDimitry Andric //==--- MachineLateInstrsCleanup.cpp - Late Instructions Cleanup Pass -----===// 2*bdd1243dSDimitry Andric // 3*bdd1243dSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*bdd1243dSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*bdd1243dSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*bdd1243dSDimitry Andric // 7*bdd1243dSDimitry Andric //===----------------------------------------------------------------------===// 8*bdd1243dSDimitry Andric // 9*bdd1243dSDimitry Andric // This simple pass removes any identical and redundant immediate or address 10*bdd1243dSDimitry Andric // loads to the same register. The immediate loads removed can originally be 11*bdd1243dSDimitry Andric // the result of rematerialization, while the addresses are redundant frame 12*bdd1243dSDimitry Andric // addressing anchor points created during Frame Indices elimination. 13*bdd1243dSDimitry Andric // 14*bdd1243dSDimitry Andric //===----------------------------------------------------------------------===// 15*bdd1243dSDimitry Andric 16*bdd1243dSDimitry Andric #include "llvm/ADT/BitVector.h" 17*bdd1243dSDimitry Andric #include "llvm/ADT/PostOrderIterator.h" 18*bdd1243dSDimitry Andric #include "llvm/ADT/SmallPtrSet.h" 19*bdd1243dSDimitry Andric #include "llvm/ADT/Statistic.h" 20*bdd1243dSDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h" 21*bdd1243dSDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 22*bdd1243dSDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h" 23*bdd1243dSDimitry Andric #include "llvm/CodeGen/MachineInstr.h" 24*bdd1243dSDimitry Andric #include "llvm/CodeGen/MachineOperand.h" 25*bdd1243dSDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h" 26*bdd1243dSDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h" 27*bdd1243dSDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h" 28*bdd1243dSDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h" 29*bdd1243dSDimitry Andric #include "llvm/InitializePasses.h" 30*bdd1243dSDimitry Andric #include "llvm/Pass.h" 31*bdd1243dSDimitry Andric #include "llvm/Support/Debug.h" 32*bdd1243dSDimitry Andric 33*bdd1243dSDimitry Andric using namespace llvm; 34*bdd1243dSDimitry Andric 35*bdd1243dSDimitry Andric #define DEBUG_TYPE "machine-latecleanup" 36*bdd1243dSDimitry Andric 37*bdd1243dSDimitry Andric STATISTIC(NumRemoved, "Number of redundant instructions removed."); 38*bdd1243dSDimitry Andric 39*bdd1243dSDimitry Andric namespace { 40*bdd1243dSDimitry Andric 41*bdd1243dSDimitry Andric class MachineLateInstrsCleanup : public MachineFunctionPass { 42*bdd1243dSDimitry Andric const TargetRegisterInfo *TRI; 43*bdd1243dSDimitry Andric const TargetInstrInfo *TII; 44*bdd1243dSDimitry Andric 45*bdd1243dSDimitry Andric // Data structures to map regs to their definitions per MBB. 46*bdd1243dSDimitry Andric using Reg2DefMap = std::map<Register, MachineInstr*>; 47*bdd1243dSDimitry Andric std::vector<Reg2DefMap> RegDefs; 48*bdd1243dSDimitry Andric 49*bdd1243dSDimitry Andric // Walk through the instructions in MBB and remove any redundant 50*bdd1243dSDimitry Andric // instructions. 51*bdd1243dSDimitry Andric bool processBlock(MachineBasicBlock *MBB); 52*bdd1243dSDimitry Andric 53*bdd1243dSDimitry Andric public: 54*bdd1243dSDimitry Andric static char ID; // Pass identification, replacement for typeid 55*bdd1243dSDimitry Andric 56*bdd1243dSDimitry Andric MachineLateInstrsCleanup() : MachineFunctionPass(ID) { 57*bdd1243dSDimitry Andric initializeMachineLateInstrsCleanupPass(*PassRegistry::getPassRegistry()); 58*bdd1243dSDimitry Andric } 59*bdd1243dSDimitry Andric 60*bdd1243dSDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override { 61*bdd1243dSDimitry Andric AU.setPreservesCFG(); 62*bdd1243dSDimitry Andric MachineFunctionPass::getAnalysisUsage(AU); 63*bdd1243dSDimitry Andric } 64*bdd1243dSDimitry Andric 65*bdd1243dSDimitry Andric bool runOnMachineFunction(MachineFunction &MF) override; 66*bdd1243dSDimitry Andric 67*bdd1243dSDimitry Andric MachineFunctionProperties getRequiredProperties() const override { 68*bdd1243dSDimitry Andric return MachineFunctionProperties().set( 69*bdd1243dSDimitry Andric MachineFunctionProperties::Property::NoVRegs); 70*bdd1243dSDimitry Andric } 71*bdd1243dSDimitry Andric }; 72*bdd1243dSDimitry Andric 73*bdd1243dSDimitry Andric } // end anonymous namespace 74*bdd1243dSDimitry Andric 75*bdd1243dSDimitry Andric char MachineLateInstrsCleanup::ID = 0; 76*bdd1243dSDimitry Andric 77*bdd1243dSDimitry Andric char &llvm::MachineLateInstrsCleanupID = MachineLateInstrsCleanup::ID; 78*bdd1243dSDimitry Andric 79*bdd1243dSDimitry Andric INITIALIZE_PASS(MachineLateInstrsCleanup, DEBUG_TYPE, 80*bdd1243dSDimitry Andric "Machine Late Instructions Cleanup Pass", false, false) 81*bdd1243dSDimitry Andric 82*bdd1243dSDimitry Andric bool MachineLateInstrsCleanup::runOnMachineFunction(MachineFunction &MF) { 83*bdd1243dSDimitry Andric if (skipFunction(MF.getFunction())) 84*bdd1243dSDimitry Andric return false; 85*bdd1243dSDimitry Andric 86*bdd1243dSDimitry Andric TRI = MF.getSubtarget().getRegisterInfo(); 87*bdd1243dSDimitry Andric TII = MF.getSubtarget().getInstrInfo(); 88*bdd1243dSDimitry Andric 89*bdd1243dSDimitry Andric RegDefs.clear(); 90*bdd1243dSDimitry Andric RegDefs.resize(MF.getNumBlockIDs()); 91*bdd1243dSDimitry Andric 92*bdd1243dSDimitry Andric // Visit all MBBs in an order that maximises the reuse from predecessors. 93*bdd1243dSDimitry Andric bool Changed = false; 94*bdd1243dSDimitry Andric ReversePostOrderTraversal<MachineFunction *> RPOT(&MF); 95*bdd1243dSDimitry Andric for (MachineBasicBlock *MBB : RPOT) 96*bdd1243dSDimitry Andric Changed |= processBlock(MBB); 97*bdd1243dSDimitry Andric 98*bdd1243dSDimitry Andric return Changed; 99*bdd1243dSDimitry Andric } 100*bdd1243dSDimitry Andric 101*bdd1243dSDimitry Andric // Clear any previous kill flag on Reg found before I in MBB. Walk backwards 102*bdd1243dSDimitry Andric // in MBB and if needed continue in predecessors until a use/def of Reg is 103*bdd1243dSDimitry Andric // encountered. This seems to be faster in practice than tracking kill flags 104*bdd1243dSDimitry Andric // in a map. 105*bdd1243dSDimitry Andric static void clearKillsForDef(Register Reg, MachineBasicBlock *MBB, 106*bdd1243dSDimitry Andric MachineBasicBlock::iterator I, 107*bdd1243dSDimitry Andric BitVector &VisitedPreds, 108*bdd1243dSDimitry Andric const TargetRegisterInfo *TRI) { 109*bdd1243dSDimitry Andric VisitedPreds.set(MBB->getNumber()); 110*bdd1243dSDimitry Andric while (I != MBB->begin()) { 111*bdd1243dSDimitry Andric --I; 112*bdd1243dSDimitry Andric bool Found = false; 113*bdd1243dSDimitry Andric for (auto &MO : I->operands()) 114*bdd1243dSDimitry Andric if (MO.isReg() && TRI->regsOverlap(MO.getReg(), Reg)) { 115*bdd1243dSDimitry Andric if (MO.isDef()) 116*bdd1243dSDimitry Andric return; 117*bdd1243dSDimitry Andric if (MO.readsReg()) { 118*bdd1243dSDimitry Andric MO.setIsKill(false); 119*bdd1243dSDimitry Andric Found = true; // Keep going for an implicit kill of the super-reg. 120*bdd1243dSDimitry Andric } 121*bdd1243dSDimitry Andric } 122*bdd1243dSDimitry Andric if (Found) 123*bdd1243dSDimitry Andric return; 124*bdd1243dSDimitry Andric } 125*bdd1243dSDimitry Andric 126*bdd1243dSDimitry Andric // If an earlier def is not in MBB, continue in predecessors. 127*bdd1243dSDimitry Andric if (!MBB->isLiveIn(Reg)) 128*bdd1243dSDimitry Andric MBB->addLiveIn(Reg); 129*bdd1243dSDimitry Andric assert(!MBB->pred_empty() && "Predecessor def not found!"); 130*bdd1243dSDimitry Andric for (MachineBasicBlock *Pred : MBB->predecessors()) 131*bdd1243dSDimitry Andric if (!VisitedPreds.test(Pred->getNumber())) 132*bdd1243dSDimitry Andric clearKillsForDef(Reg, Pred, Pred->end(), VisitedPreds, TRI); 133*bdd1243dSDimitry Andric } 134*bdd1243dSDimitry Andric 135*bdd1243dSDimitry Andric static void removeRedundantDef(MachineInstr *MI, 136*bdd1243dSDimitry Andric const TargetRegisterInfo *TRI) { 137*bdd1243dSDimitry Andric Register Reg = MI->getOperand(0).getReg(); 138*bdd1243dSDimitry Andric BitVector VisitedPreds(MI->getMF()->getNumBlockIDs()); 139*bdd1243dSDimitry Andric clearKillsForDef(Reg, MI->getParent(), MI->getIterator(), VisitedPreds, TRI); 140*bdd1243dSDimitry Andric MI->eraseFromParent(); 141*bdd1243dSDimitry Andric ++NumRemoved; 142*bdd1243dSDimitry Andric } 143*bdd1243dSDimitry Andric 144*bdd1243dSDimitry Andric // Return true if MI is a potential candidate for reuse/removal and if so 145*bdd1243dSDimitry Andric // also the register it defines in DefedReg. A candidate is a simple 146*bdd1243dSDimitry Andric // instruction that does not touch memory, has only one register definition 147*bdd1243dSDimitry Andric // and the only reg it may use is FrameReg. Typically this is an immediate 148*bdd1243dSDimitry Andric // load or a load-address instruction. 149*bdd1243dSDimitry Andric static bool isCandidate(const MachineInstr *MI, Register &DefedReg, 150*bdd1243dSDimitry Andric Register FrameReg) { 151*bdd1243dSDimitry Andric DefedReg = MCRegister::NoRegister; 152*bdd1243dSDimitry Andric bool SawStore = true; 153*bdd1243dSDimitry Andric if (!MI->isSafeToMove(nullptr, SawStore) || MI->isImplicitDef() || 154*bdd1243dSDimitry Andric MI->isInlineAsm()) 155*bdd1243dSDimitry Andric return false; 156*bdd1243dSDimitry Andric for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { 157*bdd1243dSDimitry Andric const MachineOperand &MO = MI->getOperand(i); 158*bdd1243dSDimitry Andric if (MO.isReg()) { 159*bdd1243dSDimitry Andric if (MO.isDef()) { 160*bdd1243dSDimitry Andric if (i == 0 && !MO.isImplicit() && !MO.isDead()) 161*bdd1243dSDimitry Andric DefedReg = MO.getReg(); 162*bdd1243dSDimitry Andric else 163*bdd1243dSDimitry Andric return false; 164*bdd1243dSDimitry Andric } else if (MO.getReg() && MO.getReg() != FrameReg) 165*bdd1243dSDimitry Andric return false; 166*bdd1243dSDimitry Andric } else if (!(MO.isImm() || MO.isCImm() || MO.isFPImm() || MO.isCPI() || 167*bdd1243dSDimitry Andric MO.isGlobal() || MO.isSymbol())) 168*bdd1243dSDimitry Andric return false; 169*bdd1243dSDimitry Andric } 170*bdd1243dSDimitry Andric return DefedReg.isValid(); 171*bdd1243dSDimitry Andric } 172*bdd1243dSDimitry Andric 173*bdd1243dSDimitry Andric bool MachineLateInstrsCleanup::processBlock(MachineBasicBlock *MBB) { 174*bdd1243dSDimitry Andric bool Changed = false; 175*bdd1243dSDimitry Andric Reg2DefMap &MBBDefs = RegDefs[MBB->getNumber()]; 176*bdd1243dSDimitry Andric 177*bdd1243dSDimitry Andric // Find reusable definitions in the predecessor(s). 178*bdd1243dSDimitry Andric if (!MBB->pred_empty() && !MBB->isEHPad()) { 179*bdd1243dSDimitry Andric MachineBasicBlock *FirstPred = *MBB->pred_begin(); 180*bdd1243dSDimitry Andric for (auto [Reg, DefMI] : RegDefs[FirstPred->getNumber()]) 181*bdd1243dSDimitry Andric if (llvm::all_of( 182*bdd1243dSDimitry Andric drop_begin(MBB->predecessors()), 183*bdd1243dSDimitry Andric [&, &Reg = Reg, &DefMI = DefMI](const MachineBasicBlock *Pred) { 184*bdd1243dSDimitry Andric auto PredDefI = RegDefs[Pred->getNumber()].find(Reg); 185*bdd1243dSDimitry Andric return PredDefI != RegDefs[Pred->getNumber()].end() && 186*bdd1243dSDimitry Andric DefMI->isIdenticalTo(*PredDefI->second); 187*bdd1243dSDimitry Andric })) { 188*bdd1243dSDimitry Andric MBBDefs[Reg] = DefMI; 189*bdd1243dSDimitry Andric LLVM_DEBUG(dbgs() << "Reusable instruction from pred(s): in " 190*bdd1243dSDimitry Andric << printMBBReference(*MBB) << ": " << *DefMI;); 191*bdd1243dSDimitry Andric } 192*bdd1243dSDimitry Andric } 193*bdd1243dSDimitry Andric 194*bdd1243dSDimitry Andric // Process MBB. 195*bdd1243dSDimitry Andric MachineFunction *MF = MBB->getParent(); 196*bdd1243dSDimitry Andric const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo(); 197*bdd1243dSDimitry Andric Register FrameReg = TRI->getFrameRegister(*MF); 198*bdd1243dSDimitry Andric for (MachineInstr &MI : llvm::make_early_inc_range(*MBB)) { 199*bdd1243dSDimitry Andric // If FrameReg is modified, no previous load-address instructions (using 200*bdd1243dSDimitry Andric // it) are valid. 201*bdd1243dSDimitry Andric if (MI.modifiesRegister(FrameReg, TRI)) { 202*bdd1243dSDimitry Andric MBBDefs.clear(); 203*bdd1243dSDimitry Andric continue; 204*bdd1243dSDimitry Andric } 205*bdd1243dSDimitry Andric 206*bdd1243dSDimitry Andric Register DefedReg; 207*bdd1243dSDimitry Andric bool IsCandidate = isCandidate(&MI, DefedReg, FrameReg); 208*bdd1243dSDimitry Andric 209*bdd1243dSDimitry Andric // Check for an earlier identical and reusable instruction. 210*bdd1243dSDimitry Andric if (IsCandidate) { 211*bdd1243dSDimitry Andric auto DefI = MBBDefs.find(DefedReg); 212*bdd1243dSDimitry Andric if (DefI != MBBDefs.end() && MI.isIdenticalTo(*DefI->second)) { 213*bdd1243dSDimitry Andric LLVM_DEBUG(dbgs() << "Removing redundant instruction in " 214*bdd1243dSDimitry Andric << printMBBReference(*MBB) << ": " << MI;); 215*bdd1243dSDimitry Andric removeRedundantDef(&MI, TRI); 216*bdd1243dSDimitry Andric Changed = true; 217*bdd1243dSDimitry Andric continue; 218*bdd1243dSDimitry Andric } 219*bdd1243dSDimitry Andric } 220*bdd1243dSDimitry Andric 221*bdd1243dSDimitry Andric // Clear any entries in map that MI clobbers. 222*bdd1243dSDimitry Andric for (auto DefI = MBBDefs.begin(); DefI != MBBDefs.end();) { 223*bdd1243dSDimitry Andric Register Reg = DefI->first; 224*bdd1243dSDimitry Andric if (MI.modifiesRegister(Reg, TRI)) 225*bdd1243dSDimitry Andric DefI = MBBDefs.erase(DefI); 226*bdd1243dSDimitry Andric else 227*bdd1243dSDimitry Andric ++DefI; 228*bdd1243dSDimitry Andric } 229*bdd1243dSDimitry Andric 230*bdd1243dSDimitry Andric // Record this MI for potential later reuse. 231*bdd1243dSDimitry Andric if (IsCandidate) { 232*bdd1243dSDimitry Andric LLVM_DEBUG(dbgs() << "Found interesting instruction in " 233*bdd1243dSDimitry Andric << printMBBReference(*MBB) << ": " << MI;); 234*bdd1243dSDimitry Andric MBBDefs[DefedReg] = &MI; 235*bdd1243dSDimitry Andric } 236*bdd1243dSDimitry Andric } 237*bdd1243dSDimitry Andric 238*bdd1243dSDimitry Andric return Changed; 239*bdd1243dSDimitry Andric } 240