xref: /llvm-project/llvm/lib/CodeGen/MachineLateInstrsCleanup.cpp (revision a35db2880a488b62a16f269972ad885fd58033f7)
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