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