15ecd3632SJonas Paulsson //==--- MachineLateInstrsCleanup.cpp - Late Instructions Cleanup Pass -----===// 25ecd3632SJonas Paulsson // 35ecd3632SJonas Paulsson // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 45ecd3632SJonas Paulsson // See https://llvm.org/LICENSE.txt for license information. 55ecd3632SJonas Paulsson // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 65ecd3632SJonas Paulsson // 75ecd3632SJonas Paulsson //===----------------------------------------------------------------------===// 85ecd3632SJonas Paulsson // 95ecd3632SJonas Paulsson // This simple pass removes any identical and redundant immediate or address 105ecd3632SJonas Paulsson // loads to the same register. The immediate loads removed can originally be 115ecd3632SJonas Paulsson // the result of rematerialization, while the addresses are redundant frame 125ecd3632SJonas Paulsson // addressing anchor points created during Frame Indices elimination. 135ecd3632SJonas Paulsson // 145ecd3632SJonas Paulsson //===----------------------------------------------------------------------===// 155ecd3632SJonas Paulsson 165ecd3632SJonas Paulsson #include "llvm/ADT/BitVector.h" 175ecd3632SJonas Paulsson #include "llvm/ADT/PostOrderIterator.h" 185ecd3632SJonas Paulsson #include "llvm/ADT/Statistic.h" 195ecd3632SJonas Paulsson #include "llvm/CodeGen/MachineBasicBlock.h" 205ecd3632SJonas Paulsson #include "llvm/CodeGen/MachineFunction.h" 215ecd3632SJonas Paulsson #include "llvm/CodeGen/MachineFunctionPass.h" 225ecd3632SJonas Paulsson #include "llvm/CodeGen/MachineInstr.h" 235ecd3632SJonas Paulsson #include "llvm/CodeGen/MachineOperand.h" 245ecd3632SJonas Paulsson #include "llvm/CodeGen/TargetInstrInfo.h" 255ecd3632SJonas Paulsson #include "llvm/CodeGen/TargetRegisterInfo.h" 265ecd3632SJonas Paulsson #include "llvm/CodeGen/TargetSubtargetInfo.h" 275ecd3632SJonas Paulsson #include "llvm/InitializePasses.h" 285ecd3632SJonas Paulsson #include "llvm/Pass.h" 295ecd3632SJonas Paulsson #include "llvm/Support/Debug.h" 305ecd3632SJonas Paulsson 315ecd3632SJonas Paulsson using namespace llvm; 325ecd3632SJonas Paulsson 335ecd3632SJonas Paulsson #define DEBUG_TYPE "machine-latecleanup" 345ecd3632SJonas Paulsson 355ecd3632SJonas Paulsson STATISTIC(NumRemoved, "Number of redundant instructions removed."); 365ecd3632SJonas Paulsson 375ecd3632SJonas Paulsson namespace { 385ecd3632SJonas Paulsson 395ecd3632SJonas Paulsson class MachineLateInstrsCleanup : public MachineFunctionPass { 409db75b23SLuo, Yuanke const TargetRegisterInfo *TRI = nullptr; 419db75b23SLuo, Yuanke const TargetInstrInfo *TII = nullptr; 425ecd3632SJonas Paulsson 43cb57b7a7SJonas Paulsson // Data structures to map regs to their definitions and kills per MBB. 44cb57b7a7SJonas Paulsson struct Reg2MIMap : public SmallDenseMap<Register, MachineInstr *> { 45cb57b7a7SJonas Paulsson bool hasIdentical(Register Reg, MachineInstr *ArgMI) { 46fb7f50a0SKazu Hirata MachineInstr *MI = lookup(Reg); 47cb57b7a7SJonas Paulsson return MI && MI->isIdenticalTo(*ArgMI); 48cb57b7a7SJonas Paulsson } 49cb57b7a7SJonas Paulsson }; 50cb57b7a7SJonas Paulsson 51cb57b7a7SJonas Paulsson std::vector<Reg2MIMap> RegDefs; 52cb57b7a7SJonas Paulsson std::vector<Reg2MIMap> RegKills; 535ecd3632SJonas Paulsson 545ecd3632SJonas Paulsson // Walk through the instructions in MBB and remove any redundant 555ecd3632SJonas Paulsson // instructions. 565ecd3632SJonas Paulsson bool processBlock(MachineBasicBlock *MBB); 575ecd3632SJonas Paulsson 58cb57b7a7SJonas Paulsson void removeRedundantDef(MachineInstr *MI); 59cb57b7a7SJonas Paulsson void clearKillsForDef(Register Reg, MachineBasicBlock *MBB, 60cb57b7a7SJonas Paulsson BitVector &VisitedPreds); 61cb57b7a7SJonas Paulsson 625ecd3632SJonas Paulsson public: 635ecd3632SJonas Paulsson static char ID; // Pass identification, replacement for typeid 645ecd3632SJonas Paulsson 655ecd3632SJonas Paulsson MachineLateInstrsCleanup() : MachineFunctionPass(ID) { 665ecd3632SJonas Paulsson initializeMachineLateInstrsCleanupPass(*PassRegistry::getPassRegistry()); 675ecd3632SJonas Paulsson } 685ecd3632SJonas Paulsson 695ecd3632SJonas Paulsson void getAnalysisUsage(AnalysisUsage &AU) const override { 705ecd3632SJonas Paulsson AU.setPreservesCFG(); 715ecd3632SJonas Paulsson MachineFunctionPass::getAnalysisUsage(AU); 725ecd3632SJonas Paulsson } 735ecd3632SJonas Paulsson 745ecd3632SJonas Paulsson bool runOnMachineFunction(MachineFunction &MF) override; 755ecd3632SJonas Paulsson 765ecd3632SJonas Paulsson MachineFunctionProperties getRequiredProperties() const override { 775ecd3632SJonas Paulsson return MachineFunctionProperties().set( 785ecd3632SJonas Paulsson MachineFunctionProperties::Property::NoVRegs); 795ecd3632SJonas Paulsson } 805ecd3632SJonas Paulsson }; 815ecd3632SJonas Paulsson 825ecd3632SJonas Paulsson } // end anonymous namespace 835ecd3632SJonas Paulsson 845ecd3632SJonas Paulsson char MachineLateInstrsCleanup::ID = 0; 855ecd3632SJonas Paulsson 865ecd3632SJonas Paulsson char &llvm::MachineLateInstrsCleanupID = MachineLateInstrsCleanup::ID; 875ecd3632SJonas Paulsson 885ecd3632SJonas Paulsson INITIALIZE_PASS(MachineLateInstrsCleanup, DEBUG_TYPE, 895ecd3632SJonas Paulsson "Machine Late Instructions Cleanup Pass", false, false) 905ecd3632SJonas Paulsson 915ecd3632SJonas Paulsson bool MachineLateInstrsCleanup::runOnMachineFunction(MachineFunction &MF) { 925ecd3632SJonas Paulsson if (skipFunction(MF.getFunction())) 935ecd3632SJonas Paulsson return false; 945ecd3632SJonas Paulsson 955ecd3632SJonas Paulsson TRI = MF.getSubtarget().getRegisterInfo(); 965ecd3632SJonas Paulsson TII = MF.getSubtarget().getInstrInfo(); 975ecd3632SJonas Paulsson 985ecd3632SJonas Paulsson RegDefs.clear(); 995ecd3632SJonas Paulsson RegDefs.resize(MF.getNumBlockIDs()); 100cb57b7a7SJonas Paulsson RegKills.clear(); 101cb57b7a7SJonas Paulsson RegKills.resize(MF.getNumBlockIDs()); 1025ecd3632SJonas Paulsson 1035ecd3632SJonas Paulsson // Visit all MBBs in an order that maximises the reuse from predecessors. 1045ecd3632SJonas Paulsson bool Changed = false; 1055ecd3632SJonas Paulsson ReversePostOrderTraversal<MachineFunction *> RPOT(&MF); 1065ecd3632SJonas Paulsson for (MachineBasicBlock *MBB : RPOT) 1075ecd3632SJonas Paulsson Changed |= processBlock(MBB); 1085ecd3632SJonas Paulsson 1095ecd3632SJonas Paulsson return Changed; 1105ecd3632SJonas Paulsson } 1115ecd3632SJonas Paulsson 112175e0dd4SJonas Paulsson // Clear any preceding kill flag on Reg after removing a redundant 113175e0dd4SJonas Paulsson // definition. 114175e0dd4SJonas Paulsson void MachineLateInstrsCleanup::clearKillsForDef(Register Reg, 115175e0dd4SJonas Paulsson MachineBasicBlock *MBB, 116cb57b7a7SJonas Paulsson BitVector &VisitedPreds) { 1175ecd3632SJonas Paulsson VisitedPreds.set(MBB->getNumber()); 118cb57b7a7SJonas Paulsson 119cb57b7a7SJonas Paulsson // Kill flag in MBB 120fb7f50a0SKazu Hirata if (MachineInstr *KillMI = RegKills[MBB->getNumber()].lookup(Reg)) { 121cb57b7a7SJonas Paulsson KillMI->clearRegisterKills(Reg, TRI); 1225ecd3632SJonas Paulsson return; 1235ecd3632SJonas Paulsson } 1245ecd3632SJonas Paulsson 125cb57b7a7SJonas Paulsson // Def in MBB (missing kill flag) 126fb7f50a0SKazu Hirata if (MachineInstr *DefMI = RegDefs[MBB->getNumber()].lookup(Reg)) 127cb57b7a7SJonas Paulsson if (DefMI->getParent() == MBB) 128cb57b7a7SJonas Paulsson return; 129cb57b7a7SJonas Paulsson 1305ecd3632SJonas Paulsson // If an earlier def is not in MBB, continue in predecessors. 1315ecd3632SJonas Paulsson if (!MBB->isLiveIn(Reg)) 1325ecd3632SJonas Paulsson MBB->addLiveIn(Reg); 1335ecd3632SJonas Paulsson assert(!MBB->pred_empty() && "Predecessor def not found!"); 1345ecd3632SJonas Paulsson for (MachineBasicBlock *Pred : MBB->predecessors()) 1355ecd3632SJonas Paulsson if (!VisitedPreds.test(Pred->getNumber())) 136175e0dd4SJonas Paulsson clearKillsForDef(Reg, Pred, VisitedPreds); 1375ecd3632SJonas Paulsson } 1385ecd3632SJonas Paulsson 139cb57b7a7SJonas Paulsson void MachineLateInstrsCleanup::removeRedundantDef(MachineInstr *MI) { 1405ecd3632SJonas Paulsson Register Reg = MI->getOperand(0).getReg(); 1415ecd3632SJonas Paulsson BitVector VisitedPreds(MI->getMF()->getNumBlockIDs()); 142175e0dd4SJonas Paulsson clearKillsForDef(Reg, MI->getParent(), VisitedPreds); 1435ecd3632SJonas Paulsson MI->eraseFromParent(); 1445ecd3632SJonas Paulsson ++NumRemoved; 1455ecd3632SJonas Paulsson } 1465ecd3632SJonas Paulsson 1475ecd3632SJonas Paulsson // Return true if MI is a potential candidate for reuse/removal and if so 1485ecd3632SJonas Paulsson // also the register it defines in DefedReg. A candidate is a simple 1495ecd3632SJonas Paulsson // instruction that does not touch memory, has only one register definition 1505ecd3632SJonas Paulsson // and the only reg it may use is FrameReg. Typically this is an immediate 1515ecd3632SJonas Paulsson // load or a load-address instruction. 1525ecd3632SJonas Paulsson static bool isCandidate(const MachineInstr *MI, Register &DefedReg, 1535ecd3632SJonas Paulsson Register FrameReg) { 1545ecd3632SJonas Paulsson DefedReg = MCRegister::NoRegister; 1555ecd3632SJonas Paulsson bool SawStore = true; 156ed4e75d5SPengcheng Wang if (!MI->isSafeToMove(SawStore) || MI->isImplicitDef() || MI->isInlineAsm()) 1575ecd3632SJonas Paulsson return false; 1585ecd3632SJonas Paulsson for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { 1595ecd3632SJonas Paulsson const MachineOperand &MO = MI->getOperand(i); 1605ecd3632SJonas Paulsson if (MO.isReg()) { 1615ecd3632SJonas Paulsson if (MO.isDef()) { 1625ecd3632SJonas Paulsson if (i == 0 && !MO.isImplicit() && !MO.isDead()) 1635ecd3632SJonas Paulsson DefedReg = MO.getReg(); 1645ecd3632SJonas Paulsson else 1655ecd3632SJonas Paulsson return false; 1665ecd3632SJonas Paulsson } else if (MO.getReg() && MO.getReg() != FrameReg) 1675ecd3632SJonas Paulsson return false; 1685ecd3632SJonas Paulsson } else if (!(MO.isImm() || MO.isCImm() || MO.isFPImm() || MO.isCPI() || 1695ecd3632SJonas Paulsson MO.isGlobal() || MO.isSymbol())) 1705ecd3632SJonas Paulsson return false; 1715ecd3632SJonas Paulsson } 1725ecd3632SJonas Paulsson return DefedReg.isValid(); 1735ecd3632SJonas Paulsson } 1745ecd3632SJonas Paulsson 1755ecd3632SJonas Paulsson bool MachineLateInstrsCleanup::processBlock(MachineBasicBlock *MBB) { 1765ecd3632SJonas Paulsson bool Changed = false; 177cb57b7a7SJonas Paulsson Reg2MIMap &MBBDefs = RegDefs[MBB->getNumber()]; 178cb57b7a7SJonas Paulsson Reg2MIMap &MBBKills = RegKills[MBB->getNumber()]; 1795ecd3632SJonas Paulsson 1805ecd3632SJonas Paulsson // Find reusable definitions in the predecessor(s). 181012ea747SNick Desaulniers if (!MBB->pred_empty() && !MBB->isEHPad() && 182012ea747SNick Desaulniers !MBB->isInlineAsmBrIndirectTarget()) { 1835ecd3632SJonas Paulsson MachineBasicBlock *FirstPred = *MBB->pred_begin(); 1845ecd3632SJonas Paulsson for (auto [Reg, DefMI] : RegDefs[FirstPred->getNumber()]) 1855ecd3632SJonas Paulsson if (llvm::all_of( 1865ecd3632SJonas Paulsson drop_begin(MBB->predecessors()), 1875ecd3632SJonas Paulsson [&, &Reg = Reg, &DefMI = DefMI](const MachineBasicBlock *Pred) { 188cb57b7a7SJonas Paulsson return RegDefs[Pred->getNumber()].hasIdentical(Reg, DefMI); 1895ecd3632SJonas Paulsson })) { 1905ecd3632SJonas Paulsson MBBDefs[Reg] = DefMI; 1915ecd3632SJonas Paulsson LLVM_DEBUG(dbgs() << "Reusable instruction from pred(s): in " 192*a35db288SDavid Green << printMBBReference(*MBB) << ": " << *DefMI); 1935ecd3632SJonas Paulsson } 1945ecd3632SJonas Paulsson } 1955ecd3632SJonas Paulsson 1965ecd3632SJonas Paulsson // Process MBB. 1975ecd3632SJonas Paulsson MachineFunction *MF = MBB->getParent(); 1985ecd3632SJonas Paulsson const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo(); 1995ecd3632SJonas Paulsson Register FrameReg = TRI->getFrameRegister(*MF); 2005ecd3632SJonas Paulsson for (MachineInstr &MI : llvm::make_early_inc_range(*MBB)) { 2015ecd3632SJonas Paulsson // If FrameReg is modified, no previous load-address instructions (using 2025ecd3632SJonas Paulsson // it) are valid. 2035ecd3632SJonas Paulsson if (MI.modifiesRegister(FrameReg, TRI)) { 2045ecd3632SJonas Paulsson MBBDefs.clear(); 205cb57b7a7SJonas Paulsson MBBKills.clear(); 2065ecd3632SJonas Paulsson continue; 2075ecd3632SJonas Paulsson } 2085ecd3632SJonas Paulsson 2095ecd3632SJonas Paulsson Register DefedReg; 2105ecd3632SJonas Paulsson bool IsCandidate = isCandidate(&MI, DefedReg, FrameReg); 2115ecd3632SJonas Paulsson 2125ecd3632SJonas Paulsson // Check for an earlier identical and reusable instruction. 213cb57b7a7SJonas Paulsson if (IsCandidate && MBBDefs.hasIdentical(DefedReg, &MI)) { 2145ecd3632SJonas Paulsson LLVM_DEBUG(dbgs() << "Removing redundant instruction in " 215*a35db288SDavid Green << printMBBReference(*MBB) << ": " << MI); 216cb57b7a7SJonas Paulsson removeRedundantDef(&MI); 2175ecd3632SJonas Paulsson Changed = true; 2185ecd3632SJonas Paulsson continue; 2195ecd3632SJonas Paulsson } 2205ecd3632SJonas Paulsson 2215ecd3632SJonas Paulsson // Clear any entries in map that MI clobbers. 222cb57b7a7SJonas Paulsson for (auto DefI : llvm::make_early_inc_range(MBBDefs)) { 223cb57b7a7SJonas Paulsson Register Reg = DefI.first; 224cb57b7a7SJonas Paulsson if (MI.modifiesRegister(Reg, TRI)) { 225cb57b7a7SJonas Paulsson MBBDefs.erase(Reg); 226cb57b7a7SJonas Paulsson MBBKills.erase(Reg); 227f6d431f2SXu Zhang } else if (MI.findRegisterUseOperandIdx(Reg, TRI, true /*isKill*/) != -1) 22810f0158fSJonas Paulsson // Keep track of register kills. 229cb57b7a7SJonas Paulsson MBBKills[Reg] = &MI; 2305ecd3632SJonas Paulsson } 2315ecd3632SJonas Paulsson 2325ecd3632SJonas Paulsson // Record this MI for potential later reuse. 2335ecd3632SJonas Paulsson if (IsCandidate) { 2345ecd3632SJonas Paulsson LLVM_DEBUG(dbgs() << "Found interesting instruction in " 235*a35db288SDavid Green << printMBBReference(*MBB) << ": " << MI); 2365ecd3632SJonas Paulsson MBBDefs[DefedReg] = &MI; 237cb57b7a7SJonas Paulsson assert(!MBBKills.count(DefedReg) && "Should already have been removed."); 2385ecd3632SJonas Paulsson } 2395ecd3632SJonas Paulsson } 2405ecd3632SJonas Paulsson 2415ecd3632SJonas Paulsson return Changed; 2425ecd3632SJonas Paulsson } 243