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