xref: /freebsd/contrib/llvm-project/llvm/lib/CodeGen/DeadMachineInstructionElim.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
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 
13e8d8bef9SDimitry Andric #include "llvm/ADT/PostOrderIterator.h"
140b57cec5SDimitry Andric #include "llvm/ADT/Statistic.h"
15bdd1243dSDimitry Andric #include "llvm/CodeGen/LiveRegUnits.h"
160b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
170b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
180b57cec5SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h"
19480093f4SDimitry Andric #include "llvm/InitializePasses.h"
200b57cec5SDimitry Andric #include "llvm/Pass.h"
210b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
220b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
230b57cec5SDimitry Andric 
240b57cec5SDimitry Andric using namespace llvm;
250b57cec5SDimitry Andric 
260b57cec5SDimitry Andric #define DEBUG_TYPE "dead-mi-elimination"
270b57cec5SDimitry Andric 
280b57cec5SDimitry Andric STATISTIC(NumDeletes,          "Number of dead instructions deleted");
290b57cec5SDimitry Andric 
300b57cec5SDimitry Andric namespace {
310b57cec5SDimitry Andric   class DeadMachineInstructionElim : public MachineFunctionPass {
320b57cec5SDimitry Andric     bool runOnMachineFunction(MachineFunction &MF) override;
330b57cec5SDimitry Andric 
34*06c3fb27SDimitry Andric     const MachineRegisterInfo *MRI = nullptr;
35*06c3fb27SDimitry Andric     const TargetInstrInfo *TII = nullptr;
36bdd1243dSDimitry Andric     LiveRegUnits LivePhysRegs;
370b57cec5SDimitry Andric 
380b57cec5SDimitry Andric   public:
390b57cec5SDimitry Andric     static char ID; // Pass identification, replacement for typeid
400b57cec5SDimitry Andric     DeadMachineInstructionElim() : MachineFunctionPass(ID) {
410b57cec5SDimitry Andric      initializeDeadMachineInstructionElimPass(*PassRegistry::getPassRegistry());
420b57cec5SDimitry Andric     }
430b57cec5SDimitry Andric 
440b57cec5SDimitry Andric     void getAnalysisUsage(AnalysisUsage &AU) const override {
450b57cec5SDimitry Andric       AU.setPreservesCFG();
460b57cec5SDimitry Andric       MachineFunctionPass::getAnalysisUsage(AU);
470b57cec5SDimitry Andric     }
480b57cec5SDimitry Andric 
490b57cec5SDimitry Andric   private:
500b57cec5SDimitry Andric     bool isDead(const MachineInstr *MI) const;
51e8d8bef9SDimitry Andric 
52e8d8bef9SDimitry Andric     bool eliminateDeadMI(MachineFunction &MF);
530b57cec5SDimitry Andric   };
540b57cec5SDimitry Andric }
550b57cec5SDimitry Andric char DeadMachineInstructionElim::ID = 0;
560b57cec5SDimitry Andric char &llvm::DeadMachineInstructionElimID = DeadMachineInstructionElim::ID;
570b57cec5SDimitry Andric 
580b57cec5SDimitry Andric INITIALIZE_PASS(DeadMachineInstructionElim, DEBUG_TYPE,
590b57cec5SDimitry Andric                 "Remove dead machine instructions", false, false)
600b57cec5SDimitry Andric 
610b57cec5SDimitry Andric bool DeadMachineInstructionElim::isDead(const MachineInstr *MI) const {
620b57cec5SDimitry Andric   // Technically speaking inline asm without side effects and no defs can still
630b57cec5SDimitry Andric   // be deleted. But there is so much bad inline asm code out there, we should
640b57cec5SDimitry Andric   // let them be.
650b57cec5SDimitry Andric   if (MI->isInlineAsm())
660b57cec5SDimitry Andric     return false;
670b57cec5SDimitry Andric 
680b57cec5SDimitry Andric   // Don't delete frame allocation labels.
690b57cec5SDimitry Andric   if (MI->getOpcode() == TargetOpcode::LOCAL_ESCAPE)
700b57cec5SDimitry Andric     return false;
710b57cec5SDimitry Andric 
720b57cec5SDimitry Andric   // Don't delete instructions with side effects.
730b57cec5SDimitry Andric   bool SawStore = false;
740b57cec5SDimitry Andric   if (!MI->isSafeToMove(nullptr, SawStore) && !MI->isPHI())
750b57cec5SDimitry Andric     return false;
760b57cec5SDimitry Andric 
770b57cec5SDimitry Andric   // Examine each operand.
78*06c3fb27SDimitry Andric   for (const MachineOperand &MO : MI->all_defs()) {
798bcb0991SDimitry Andric     Register Reg = MO.getReg();
80bdd1243dSDimitry Andric     if (Reg.isPhysical()) {
810b57cec5SDimitry Andric       // Don't delete live physreg defs, or any reserved register defs.
82bdd1243dSDimitry Andric       if (!LivePhysRegs.available(Reg) || MRI->isReserved(Reg))
830b57cec5SDimitry Andric         return false;
840b57cec5SDimitry Andric     } else {
85480093f4SDimitry Andric       if (MO.isDead()) {
86480093f4SDimitry Andric #ifndef NDEBUG
87bdd1243dSDimitry Andric         // Basic check on the register. All of them should be 'undef'.
88480093f4SDimitry Andric         for (auto &U : MRI->use_nodbg_operands(Reg))
89480093f4SDimitry Andric           assert(U.isUndef() && "'Undef' use on a 'dead' register is found!");
90480093f4SDimitry Andric #endif
91480093f4SDimitry Andric         continue;
92480093f4SDimitry Andric       }
930b57cec5SDimitry Andric       for (const MachineInstr &Use : MRI->use_nodbg_instructions(Reg)) {
940b57cec5SDimitry Andric         if (&Use != MI)
950b57cec5SDimitry Andric           // This def has a non-debug use. Don't delete the instruction!
960b57cec5SDimitry Andric           return false;
970b57cec5SDimitry Andric       }
980b57cec5SDimitry Andric     }
990b57cec5SDimitry Andric   }
1000b57cec5SDimitry Andric 
1010b57cec5SDimitry Andric   // If there are no defs with uses, the instruction is dead.
1020b57cec5SDimitry Andric   return true;
1030b57cec5SDimitry Andric }
1040b57cec5SDimitry Andric 
1050b57cec5SDimitry Andric bool DeadMachineInstructionElim::runOnMachineFunction(MachineFunction &MF) {
1060b57cec5SDimitry Andric   if (skipFunction(MF.getFunction()))
1070b57cec5SDimitry Andric     return false;
108bdd1243dSDimitry Andric 
109bdd1243dSDimitry Andric   MRI = &MF.getRegInfo();
110bdd1243dSDimitry Andric 
111bdd1243dSDimitry Andric   const TargetSubtargetInfo &ST = MF.getSubtarget();
112bdd1243dSDimitry Andric   TII = ST.getInstrInfo();
113bdd1243dSDimitry Andric   LivePhysRegs.init(*ST.getRegisterInfo());
114bdd1243dSDimitry Andric 
115e8d8bef9SDimitry Andric   bool AnyChanges = eliminateDeadMI(MF);
116e8d8bef9SDimitry Andric   while (AnyChanges && eliminateDeadMI(MF))
117e8d8bef9SDimitry Andric     ;
118e8d8bef9SDimitry Andric   return AnyChanges;
119e8d8bef9SDimitry Andric }
1200b57cec5SDimitry Andric 
121e8d8bef9SDimitry Andric bool DeadMachineInstructionElim::eliminateDeadMI(MachineFunction &MF) {
1220b57cec5SDimitry Andric   bool AnyChanges = false;
1230b57cec5SDimitry Andric 
1240b57cec5SDimitry Andric   // Loop over all instructions in all blocks, from bottom to top, so that it's
1250b57cec5SDimitry Andric   // more likely that chains of dependent but ultimately dead instructions will
1260b57cec5SDimitry Andric   // be cleaned up.
127e8d8bef9SDimitry Andric   for (MachineBasicBlock *MBB : post_order(&MF)) {
128bdd1243dSDimitry Andric     LivePhysRegs.addLiveOuts(*MBB);
1290b57cec5SDimitry Andric 
1300b57cec5SDimitry Andric     // Now scan the instructions and delete dead ones, tracking physreg
1310b57cec5SDimitry Andric     // liveness as we go.
132bdd1243dSDimitry Andric     for (MachineInstr &MI : make_early_inc_range(reverse(*MBB))) {
1330b57cec5SDimitry Andric       // If the instruction is dead, delete it!
134349cc55cSDimitry Andric       if (isDead(&MI)) {
135349cc55cSDimitry Andric         LLVM_DEBUG(dbgs() << "DeadMachineInstructionElim: DELETING: " << MI);
1360b57cec5SDimitry Andric         // It is possible that some DBG_VALUE instructions refer to this
1370eae32dcSDimitry Andric         // instruction. They will be deleted in the live debug variable
1380eae32dcSDimitry Andric         // analysis.
1390eae32dcSDimitry Andric         MI.eraseFromParent();
1400b57cec5SDimitry Andric         AnyChanges = true;
1410b57cec5SDimitry Andric         ++NumDeletes;
1420b57cec5SDimitry Andric         continue;
1430b57cec5SDimitry Andric       }
1440b57cec5SDimitry Andric 
145bdd1243dSDimitry Andric       LivePhysRegs.stepBackward(MI);
1460b57cec5SDimitry Andric     }
1470b57cec5SDimitry Andric   }
1480b57cec5SDimitry Andric 
1490b57cec5SDimitry Andric   LivePhysRegs.clear();
1500b57cec5SDimitry Andric   return AnyChanges;
1510b57cec5SDimitry Andric }
152