xref: /freebsd-src/contrib/llvm-project/llvm/lib/CodeGen/DeadMachineInstructionElim.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- DeadMachineInstructionElim.cpp - Remove dead machine instructions --===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This is an extremely simple MachineInstr-level dead-code-elimination pass.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
13*0fca6ea1SDimitry Andric #include "llvm/CodeGen/DeadMachineInstructionElim.h"
14e8d8bef9SDimitry Andric #include "llvm/ADT/PostOrderIterator.h"
150b57cec5SDimitry Andric #include "llvm/ADT/Statistic.h"
16bdd1243dSDimitry Andric #include "llvm/CodeGen/LiveRegUnits.h"
170b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
180b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
190b57cec5SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h"
20480093f4SDimitry Andric #include "llvm/InitializePasses.h"
210b57cec5SDimitry Andric #include "llvm/Pass.h"
220b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
230b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
240b57cec5SDimitry Andric 
250b57cec5SDimitry Andric using namespace llvm;
260b57cec5SDimitry Andric 
270b57cec5SDimitry Andric #define DEBUG_TYPE "dead-mi-elimination"
280b57cec5SDimitry Andric 
290b57cec5SDimitry Andric STATISTIC(NumDeletes,          "Number of dead instructions deleted");
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric namespace {
32*0fca6ea1SDimitry Andric class DeadMachineInstructionElimImpl {
3306c3fb27SDimitry Andric   const MachineRegisterInfo *MRI = nullptr;
3406c3fb27SDimitry Andric   const TargetInstrInfo *TII = nullptr;
35bdd1243dSDimitry Andric   LiveRegUnits LivePhysRegs;
360b57cec5SDimitry Andric 
370b57cec5SDimitry Andric public:
38*0fca6ea1SDimitry Andric   bool runImpl(MachineFunction &MF);
39*0fca6ea1SDimitry Andric 
40*0fca6ea1SDimitry Andric private:
41*0fca6ea1SDimitry Andric   bool isDead(const MachineInstr *MI) const;
42*0fca6ea1SDimitry Andric   bool eliminateDeadMI(MachineFunction &MF);
43*0fca6ea1SDimitry Andric };
44*0fca6ea1SDimitry Andric 
45*0fca6ea1SDimitry Andric class DeadMachineInstructionElim : public MachineFunctionPass {
46*0fca6ea1SDimitry Andric public:
470b57cec5SDimitry Andric   static char ID; // Pass identification, replacement for typeid
48*0fca6ea1SDimitry Andric 
490b57cec5SDimitry Andric   DeadMachineInstructionElim() : MachineFunctionPass(ID) {
500b57cec5SDimitry Andric     initializeDeadMachineInstructionElimPass(*PassRegistry::getPassRegistry());
510b57cec5SDimitry Andric   }
520b57cec5SDimitry Andric 
53*0fca6ea1SDimitry Andric   bool runOnMachineFunction(MachineFunction &MF) override {
54*0fca6ea1SDimitry Andric     if (skipFunction(MF.getFunction()))
55*0fca6ea1SDimitry Andric       return false;
56*0fca6ea1SDimitry Andric     return DeadMachineInstructionElimImpl().runImpl(MF);
57*0fca6ea1SDimitry Andric   }
58*0fca6ea1SDimitry Andric 
590b57cec5SDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override {
600b57cec5SDimitry Andric     AU.setPreservesCFG();
610b57cec5SDimitry Andric     MachineFunctionPass::getAnalysisUsage(AU);
620b57cec5SDimitry Andric   }
630b57cec5SDimitry Andric };
64*0fca6ea1SDimitry Andric } // namespace
65*0fca6ea1SDimitry Andric 
66*0fca6ea1SDimitry Andric PreservedAnalyses
67*0fca6ea1SDimitry Andric DeadMachineInstructionElimPass::run(MachineFunction &MF,
68*0fca6ea1SDimitry Andric                                     MachineFunctionAnalysisManager &) {
69*0fca6ea1SDimitry Andric   if (!DeadMachineInstructionElimImpl().runImpl(MF))
70*0fca6ea1SDimitry Andric     return PreservedAnalyses::all();
71*0fca6ea1SDimitry Andric   PreservedAnalyses PA = getMachineFunctionPassPreservedAnalyses();
72*0fca6ea1SDimitry Andric   PA.preserveSet<CFGAnalyses>();
73*0fca6ea1SDimitry Andric   return PA;
740b57cec5SDimitry Andric }
75*0fca6ea1SDimitry Andric 
760b57cec5SDimitry Andric char DeadMachineInstructionElim::ID = 0;
770b57cec5SDimitry Andric char &llvm::DeadMachineInstructionElimID = DeadMachineInstructionElim::ID;
780b57cec5SDimitry Andric 
790b57cec5SDimitry Andric INITIALIZE_PASS(DeadMachineInstructionElim, DEBUG_TYPE,
800b57cec5SDimitry Andric                 "Remove dead machine instructions", false, false)
810b57cec5SDimitry Andric 
82*0fca6ea1SDimitry Andric bool DeadMachineInstructionElimImpl::isDead(const MachineInstr *MI) const {
830b57cec5SDimitry Andric   // Technically speaking inline asm without side effects and no defs can still
840b57cec5SDimitry Andric   // be deleted. But there is so much bad inline asm code out there, we should
850b57cec5SDimitry Andric   // let them be.
860b57cec5SDimitry Andric   if (MI->isInlineAsm())
870b57cec5SDimitry Andric     return false;
880b57cec5SDimitry Andric 
890b57cec5SDimitry Andric   // Don't delete frame allocation labels.
900b57cec5SDimitry Andric   if (MI->getOpcode() == TargetOpcode::LOCAL_ESCAPE)
910b57cec5SDimitry Andric     return false;
920b57cec5SDimitry Andric 
930b57cec5SDimitry Andric   // Don't delete instructions with side effects.
940b57cec5SDimitry Andric   bool SawStore = false;
950b57cec5SDimitry Andric   if (!MI->isSafeToMove(nullptr, SawStore) && !MI->isPHI())
960b57cec5SDimitry Andric     return false;
970b57cec5SDimitry Andric 
980b57cec5SDimitry Andric   // Examine each operand.
9906c3fb27SDimitry Andric   for (const MachineOperand &MO : MI->all_defs()) {
1008bcb0991SDimitry Andric     Register Reg = MO.getReg();
101bdd1243dSDimitry Andric     if (Reg.isPhysical()) {
1020b57cec5SDimitry Andric       // Don't delete live physreg defs, or any reserved register defs.
103bdd1243dSDimitry Andric       if (!LivePhysRegs.available(Reg) || MRI->isReserved(Reg))
1040b57cec5SDimitry Andric         return false;
1050b57cec5SDimitry Andric     } else {
106480093f4SDimitry Andric       if (MO.isDead()) {
107480093f4SDimitry Andric #ifndef NDEBUG
108bdd1243dSDimitry Andric         // Basic check on the register. All of them should be 'undef'.
109480093f4SDimitry Andric         for (auto &U : MRI->use_nodbg_operands(Reg))
110480093f4SDimitry Andric           assert(U.isUndef() && "'Undef' use on a 'dead' register is found!");
111480093f4SDimitry Andric #endif
112480093f4SDimitry Andric         continue;
113480093f4SDimitry Andric       }
1140b57cec5SDimitry Andric       for (const MachineInstr &Use : MRI->use_nodbg_instructions(Reg)) {
1150b57cec5SDimitry Andric         if (&Use != MI)
1160b57cec5SDimitry Andric           // This def has a non-debug use. Don't delete the instruction!
1170b57cec5SDimitry Andric           return false;
1180b57cec5SDimitry Andric       }
1190b57cec5SDimitry Andric     }
1200b57cec5SDimitry Andric   }
1210b57cec5SDimitry Andric 
1220b57cec5SDimitry Andric   // If there are no defs with uses, the instruction is dead.
1230b57cec5SDimitry Andric   return true;
1240b57cec5SDimitry Andric }
1250b57cec5SDimitry Andric 
126*0fca6ea1SDimitry Andric bool DeadMachineInstructionElimImpl::runImpl(MachineFunction &MF) {
127bdd1243dSDimitry Andric   MRI = &MF.getRegInfo();
128bdd1243dSDimitry Andric 
129bdd1243dSDimitry Andric   const TargetSubtargetInfo &ST = MF.getSubtarget();
130bdd1243dSDimitry Andric   TII = ST.getInstrInfo();
131bdd1243dSDimitry Andric   LivePhysRegs.init(*ST.getRegisterInfo());
132bdd1243dSDimitry Andric 
133e8d8bef9SDimitry Andric   bool AnyChanges = eliminateDeadMI(MF);
134e8d8bef9SDimitry Andric   while (AnyChanges && eliminateDeadMI(MF))
135e8d8bef9SDimitry Andric     ;
136e8d8bef9SDimitry Andric   return AnyChanges;
137e8d8bef9SDimitry Andric }
1380b57cec5SDimitry Andric 
139*0fca6ea1SDimitry Andric bool DeadMachineInstructionElimImpl::eliminateDeadMI(MachineFunction &MF) {
1400b57cec5SDimitry Andric   bool AnyChanges = false;
1410b57cec5SDimitry Andric 
1420b57cec5SDimitry Andric   // Loop over all instructions in all blocks, from bottom to top, so that it's
1430b57cec5SDimitry Andric   // more likely that chains of dependent but ultimately dead instructions will
1440b57cec5SDimitry Andric   // be cleaned up.
145e8d8bef9SDimitry Andric   for (MachineBasicBlock *MBB : post_order(&MF)) {
146bdd1243dSDimitry Andric     LivePhysRegs.addLiveOuts(*MBB);
1470b57cec5SDimitry Andric 
1480b57cec5SDimitry Andric     // Now scan the instructions and delete dead ones, tracking physreg
1490b57cec5SDimitry Andric     // liveness as we go.
150bdd1243dSDimitry Andric     for (MachineInstr &MI : make_early_inc_range(reverse(*MBB))) {
1510b57cec5SDimitry Andric       // If the instruction is dead, delete it!
152349cc55cSDimitry Andric       if (isDead(&MI)) {
153349cc55cSDimitry Andric         LLVM_DEBUG(dbgs() << "DeadMachineInstructionElim: DELETING: " << MI);
1540b57cec5SDimitry Andric         // It is possible that some DBG_VALUE instructions refer to this
1550eae32dcSDimitry Andric         // instruction. They will be deleted in the live debug variable
1560eae32dcSDimitry Andric         // analysis.
1570eae32dcSDimitry Andric         MI.eraseFromParent();
1580b57cec5SDimitry Andric         AnyChanges = true;
1590b57cec5SDimitry Andric         ++NumDeletes;
1600b57cec5SDimitry Andric         continue;
1610b57cec5SDimitry Andric       }
1620b57cec5SDimitry Andric 
163bdd1243dSDimitry Andric       LivePhysRegs.stepBackward(MI);
1640b57cec5SDimitry Andric     }
1650b57cec5SDimitry Andric   }
1660b57cec5SDimitry Andric 
1670b57cec5SDimitry Andric   LivePhysRegs.clear();
1680b57cec5SDimitry Andric   return AnyChanges;
1690b57cec5SDimitry Andric }
170