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/Statistic.h" 19bdd1243dSDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h" 20bdd1243dSDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 21bdd1243dSDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h" 22bdd1243dSDimitry Andric #include "llvm/CodeGen/MachineInstr.h" 23bdd1243dSDimitry Andric #include "llvm/CodeGen/MachineOperand.h" 24bdd1243dSDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h" 25bdd1243dSDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h" 26bdd1243dSDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h" 27bdd1243dSDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h" 28bdd1243dSDimitry Andric #include "llvm/InitializePasses.h" 29bdd1243dSDimitry Andric #include "llvm/Pass.h" 30bdd1243dSDimitry Andric #include "llvm/Support/Debug.h" 31bdd1243dSDimitry Andric 32bdd1243dSDimitry Andric using namespace llvm; 33bdd1243dSDimitry Andric 34bdd1243dSDimitry Andric #define DEBUG_TYPE "machine-latecleanup" 35bdd1243dSDimitry Andric 36bdd1243dSDimitry Andric STATISTIC(NumRemoved, "Number of redundant instructions removed."); 37bdd1243dSDimitry Andric 38bdd1243dSDimitry Andric namespace { 39bdd1243dSDimitry Andric 40bdd1243dSDimitry Andric class MachineLateInstrsCleanup : public MachineFunctionPass { 4106c3fb27SDimitry Andric const TargetRegisterInfo *TRI = nullptr; 4206c3fb27SDimitry Andric const TargetInstrInfo *TII = nullptr; 43bdd1243dSDimitry Andric 4406c3fb27SDimitry Andric // Data structures to map regs to their definitions and kills per MBB. 4506c3fb27SDimitry Andric struct Reg2MIMap : public SmallDenseMap<Register, MachineInstr *> { 4606c3fb27SDimitry Andric bool hasIdentical(Register Reg, MachineInstr *ArgMI) { 4706c3fb27SDimitry Andric MachineInstr *MI = lookup(Reg); 4806c3fb27SDimitry Andric return MI && MI->isIdenticalTo(*ArgMI); 4906c3fb27SDimitry Andric } 5006c3fb27SDimitry Andric }; 5106c3fb27SDimitry Andric 5206c3fb27SDimitry Andric std::vector<Reg2MIMap> RegDefs; 5306c3fb27SDimitry Andric std::vector<Reg2MIMap> RegKills; 54bdd1243dSDimitry Andric 55bdd1243dSDimitry Andric // Walk through the instructions in MBB and remove any redundant 56bdd1243dSDimitry Andric // instructions. 57bdd1243dSDimitry Andric bool processBlock(MachineBasicBlock *MBB); 58bdd1243dSDimitry Andric 5906c3fb27SDimitry Andric void removeRedundantDef(MachineInstr *MI); 6006c3fb27SDimitry Andric void clearKillsForDef(Register Reg, MachineBasicBlock *MBB, 6106c3fb27SDimitry Andric MachineBasicBlock::iterator I, 6206c3fb27SDimitry Andric BitVector &VisitedPreds); 6306c3fb27SDimitry Andric 64bdd1243dSDimitry Andric public: 65bdd1243dSDimitry Andric static char ID; // Pass identification, replacement for typeid 66bdd1243dSDimitry Andric 67bdd1243dSDimitry Andric MachineLateInstrsCleanup() : MachineFunctionPass(ID) { 68bdd1243dSDimitry Andric initializeMachineLateInstrsCleanupPass(*PassRegistry::getPassRegistry()); 69bdd1243dSDimitry Andric } 70bdd1243dSDimitry Andric 71bdd1243dSDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override { 72bdd1243dSDimitry Andric AU.setPreservesCFG(); 73bdd1243dSDimitry Andric MachineFunctionPass::getAnalysisUsage(AU); 74bdd1243dSDimitry Andric } 75bdd1243dSDimitry Andric 76bdd1243dSDimitry Andric bool runOnMachineFunction(MachineFunction &MF) override; 77bdd1243dSDimitry Andric 78bdd1243dSDimitry Andric MachineFunctionProperties getRequiredProperties() const override { 79bdd1243dSDimitry Andric return MachineFunctionProperties().set( 80bdd1243dSDimitry Andric MachineFunctionProperties::Property::NoVRegs); 81bdd1243dSDimitry Andric } 82bdd1243dSDimitry Andric }; 83bdd1243dSDimitry Andric 84bdd1243dSDimitry Andric } // end anonymous namespace 85bdd1243dSDimitry Andric 86bdd1243dSDimitry Andric char MachineLateInstrsCleanup::ID = 0; 87bdd1243dSDimitry Andric 88bdd1243dSDimitry Andric char &llvm::MachineLateInstrsCleanupID = MachineLateInstrsCleanup::ID; 89bdd1243dSDimitry Andric 90bdd1243dSDimitry Andric INITIALIZE_PASS(MachineLateInstrsCleanup, DEBUG_TYPE, 91bdd1243dSDimitry Andric "Machine Late Instructions Cleanup Pass", false, false) 92bdd1243dSDimitry Andric 93bdd1243dSDimitry Andric bool MachineLateInstrsCleanup::runOnMachineFunction(MachineFunction &MF) { 94bdd1243dSDimitry Andric if (skipFunction(MF.getFunction())) 95bdd1243dSDimitry Andric return false; 96bdd1243dSDimitry Andric 97bdd1243dSDimitry Andric TRI = MF.getSubtarget().getRegisterInfo(); 98bdd1243dSDimitry Andric TII = MF.getSubtarget().getInstrInfo(); 99bdd1243dSDimitry Andric 100bdd1243dSDimitry Andric RegDefs.clear(); 101bdd1243dSDimitry Andric RegDefs.resize(MF.getNumBlockIDs()); 10206c3fb27SDimitry Andric RegKills.clear(); 10306c3fb27SDimitry Andric RegKills.resize(MF.getNumBlockIDs()); 104bdd1243dSDimitry Andric 105bdd1243dSDimitry Andric // Visit all MBBs in an order that maximises the reuse from predecessors. 106bdd1243dSDimitry Andric bool Changed = false; 107bdd1243dSDimitry Andric ReversePostOrderTraversal<MachineFunction *> RPOT(&MF); 108bdd1243dSDimitry Andric for (MachineBasicBlock *MBB : RPOT) 109bdd1243dSDimitry Andric Changed |= processBlock(MBB); 110bdd1243dSDimitry Andric 111bdd1243dSDimitry Andric return Changed; 112bdd1243dSDimitry Andric } 113bdd1243dSDimitry Andric 114bdd1243dSDimitry Andric // Clear any previous kill flag on Reg found before I in MBB. Walk backwards 115bdd1243dSDimitry Andric // in MBB and if needed continue in predecessors until a use/def of Reg is 116bdd1243dSDimitry Andric // encountered. This seems to be faster in practice than tracking kill flags 117bdd1243dSDimitry Andric // in a map. 11806c3fb27SDimitry Andric void MachineLateInstrsCleanup:: 11906c3fb27SDimitry Andric clearKillsForDef(Register Reg, MachineBasicBlock *MBB, 120bdd1243dSDimitry Andric MachineBasicBlock::iterator I, 12106c3fb27SDimitry Andric BitVector &VisitedPreds) { 122bdd1243dSDimitry Andric VisitedPreds.set(MBB->getNumber()); 12306c3fb27SDimitry Andric 12406c3fb27SDimitry Andric // Kill flag in MBB 12506c3fb27SDimitry Andric if (MachineInstr *KillMI = RegKills[MBB->getNumber()].lookup(Reg)) { 12606c3fb27SDimitry Andric KillMI->clearRegisterKills(Reg, TRI); 127bdd1243dSDimitry Andric return; 128bdd1243dSDimitry Andric } 129bdd1243dSDimitry Andric 13006c3fb27SDimitry Andric // Def in MBB (missing kill flag) 13106c3fb27SDimitry Andric if (MachineInstr *DefMI = RegDefs[MBB->getNumber()].lookup(Reg)) 13206c3fb27SDimitry Andric if (DefMI->getParent() == MBB) 13306c3fb27SDimitry Andric return; 13406c3fb27SDimitry Andric 135bdd1243dSDimitry Andric // If an earlier def is not in MBB, continue in predecessors. 136bdd1243dSDimitry Andric if (!MBB->isLiveIn(Reg)) 137bdd1243dSDimitry Andric MBB->addLiveIn(Reg); 138bdd1243dSDimitry Andric assert(!MBB->pred_empty() && "Predecessor def not found!"); 139bdd1243dSDimitry Andric for (MachineBasicBlock *Pred : MBB->predecessors()) 140bdd1243dSDimitry Andric if (!VisitedPreds.test(Pred->getNumber())) 14106c3fb27SDimitry Andric clearKillsForDef(Reg, Pred, Pred->end(), VisitedPreds); 142bdd1243dSDimitry Andric } 143bdd1243dSDimitry Andric 14406c3fb27SDimitry Andric void MachineLateInstrsCleanup::removeRedundantDef(MachineInstr *MI) { 145bdd1243dSDimitry Andric Register Reg = MI->getOperand(0).getReg(); 146bdd1243dSDimitry Andric BitVector VisitedPreds(MI->getMF()->getNumBlockIDs()); 14706c3fb27SDimitry Andric clearKillsForDef(Reg, MI->getParent(), MI->getIterator(), VisitedPreds); 148bdd1243dSDimitry Andric MI->eraseFromParent(); 149bdd1243dSDimitry Andric ++NumRemoved; 150bdd1243dSDimitry Andric } 151bdd1243dSDimitry Andric 152bdd1243dSDimitry Andric // Return true if MI is a potential candidate for reuse/removal and if so 153bdd1243dSDimitry Andric // also the register it defines in DefedReg. A candidate is a simple 154bdd1243dSDimitry Andric // instruction that does not touch memory, has only one register definition 155bdd1243dSDimitry Andric // and the only reg it may use is FrameReg. Typically this is an immediate 156bdd1243dSDimitry Andric // load or a load-address instruction. 157bdd1243dSDimitry Andric static bool isCandidate(const MachineInstr *MI, Register &DefedReg, 158bdd1243dSDimitry Andric Register FrameReg) { 159bdd1243dSDimitry Andric DefedReg = MCRegister::NoRegister; 160bdd1243dSDimitry Andric bool SawStore = true; 161bdd1243dSDimitry Andric if (!MI->isSafeToMove(nullptr, SawStore) || MI->isImplicitDef() || 162bdd1243dSDimitry Andric MI->isInlineAsm()) 163bdd1243dSDimitry Andric return false; 164bdd1243dSDimitry Andric for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { 165bdd1243dSDimitry Andric const MachineOperand &MO = MI->getOperand(i); 166bdd1243dSDimitry Andric if (MO.isReg()) { 167bdd1243dSDimitry Andric if (MO.isDef()) { 168bdd1243dSDimitry Andric if (i == 0 && !MO.isImplicit() && !MO.isDead()) 169bdd1243dSDimitry Andric DefedReg = MO.getReg(); 170bdd1243dSDimitry Andric else 171bdd1243dSDimitry Andric return false; 172bdd1243dSDimitry Andric } else if (MO.getReg() && MO.getReg() != FrameReg) 173bdd1243dSDimitry Andric return false; 174bdd1243dSDimitry Andric } else if (!(MO.isImm() || MO.isCImm() || MO.isFPImm() || MO.isCPI() || 175bdd1243dSDimitry Andric MO.isGlobal() || MO.isSymbol())) 176bdd1243dSDimitry Andric return false; 177bdd1243dSDimitry Andric } 178bdd1243dSDimitry Andric return DefedReg.isValid(); 179bdd1243dSDimitry Andric } 180bdd1243dSDimitry Andric 181bdd1243dSDimitry Andric bool MachineLateInstrsCleanup::processBlock(MachineBasicBlock *MBB) { 182bdd1243dSDimitry Andric bool Changed = false; 18306c3fb27SDimitry Andric Reg2MIMap &MBBDefs = RegDefs[MBB->getNumber()]; 18406c3fb27SDimitry Andric Reg2MIMap &MBBKills = RegKills[MBB->getNumber()]; 185bdd1243dSDimitry Andric 186bdd1243dSDimitry Andric // Find reusable definitions in the predecessor(s). 187cbe9438cSDimitry Andric if (!MBB->pred_empty() && !MBB->isEHPad() && 188cbe9438cSDimitry Andric !MBB->isInlineAsmBrIndirectTarget()) { 189bdd1243dSDimitry Andric MachineBasicBlock *FirstPred = *MBB->pred_begin(); 190bdd1243dSDimitry Andric for (auto [Reg, DefMI] : RegDefs[FirstPred->getNumber()]) 191bdd1243dSDimitry Andric if (llvm::all_of( 192bdd1243dSDimitry Andric drop_begin(MBB->predecessors()), 193bdd1243dSDimitry Andric [&, &Reg = Reg, &DefMI = DefMI](const MachineBasicBlock *Pred) { 19406c3fb27SDimitry Andric return RegDefs[Pred->getNumber()].hasIdentical(Reg, DefMI); 195bdd1243dSDimitry Andric })) { 196bdd1243dSDimitry Andric MBBDefs[Reg] = DefMI; 197bdd1243dSDimitry Andric LLVM_DEBUG(dbgs() << "Reusable instruction from pred(s): in " 198bdd1243dSDimitry Andric << printMBBReference(*MBB) << ": " << *DefMI;); 199bdd1243dSDimitry Andric } 200bdd1243dSDimitry Andric } 201bdd1243dSDimitry Andric 202bdd1243dSDimitry Andric // Process MBB. 203bdd1243dSDimitry Andric MachineFunction *MF = MBB->getParent(); 204bdd1243dSDimitry Andric const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo(); 205bdd1243dSDimitry Andric Register FrameReg = TRI->getFrameRegister(*MF); 206bdd1243dSDimitry Andric for (MachineInstr &MI : llvm::make_early_inc_range(*MBB)) { 207bdd1243dSDimitry Andric // If FrameReg is modified, no previous load-address instructions (using 208bdd1243dSDimitry Andric // it) are valid. 209bdd1243dSDimitry Andric if (MI.modifiesRegister(FrameReg, TRI)) { 210bdd1243dSDimitry Andric MBBDefs.clear(); 21106c3fb27SDimitry Andric MBBKills.clear(); 212bdd1243dSDimitry Andric continue; 213bdd1243dSDimitry Andric } 214bdd1243dSDimitry Andric 215bdd1243dSDimitry Andric Register DefedReg; 216bdd1243dSDimitry Andric bool IsCandidate = isCandidate(&MI, DefedReg, FrameReg); 217bdd1243dSDimitry Andric 218bdd1243dSDimitry Andric // Check for an earlier identical and reusable instruction. 21906c3fb27SDimitry Andric if (IsCandidate && MBBDefs.hasIdentical(DefedReg, &MI)) { 220bdd1243dSDimitry Andric LLVM_DEBUG(dbgs() << "Removing redundant instruction in " 221bdd1243dSDimitry Andric << printMBBReference(*MBB) << ": " << MI;); 22206c3fb27SDimitry Andric removeRedundantDef(&MI); 223bdd1243dSDimitry Andric Changed = true; 224bdd1243dSDimitry Andric continue; 225bdd1243dSDimitry Andric } 226bdd1243dSDimitry Andric 227bdd1243dSDimitry Andric // Clear any entries in map that MI clobbers. 22806c3fb27SDimitry Andric for (auto DefI : llvm::make_early_inc_range(MBBDefs)) { 22906c3fb27SDimitry Andric Register Reg = DefI.first; 23006c3fb27SDimitry Andric if (MI.modifiesRegister(Reg, TRI)) { 23106c3fb27SDimitry Andric MBBDefs.erase(Reg); 23206c3fb27SDimitry Andric MBBKills.erase(Reg); 233*0fca6ea1SDimitry Andric } else if (MI.findRegisterUseOperandIdx(Reg, TRI, true /*isKill*/) != -1) 23406c3fb27SDimitry Andric // Keep track of register kills. 23506c3fb27SDimitry Andric MBBKills[Reg] = &MI; 236bdd1243dSDimitry Andric } 237bdd1243dSDimitry Andric 238bdd1243dSDimitry Andric // Record this MI for potential later reuse. 239bdd1243dSDimitry Andric if (IsCandidate) { 240bdd1243dSDimitry Andric LLVM_DEBUG(dbgs() << "Found interesting instruction in " 241bdd1243dSDimitry Andric << printMBBReference(*MBB) << ": " << MI;); 242bdd1243dSDimitry Andric MBBDefs[DefedReg] = &MI; 24306c3fb27SDimitry Andric assert(!MBBKills.count(DefedReg) && "Should already have been removed."); 244bdd1243dSDimitry Andric } 245bdd1243dSDimitry Andric } 246bdd1243dSDimitry Andric 247bdd1243dSDimitry Andric return Changed; 248bdd1243dSDimitry Andric } 249