xref: /freebsd/contrib/llvm-project/llvm/lib/CodeGen/DeadMachineInstructionElim.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
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"
15*bdd1243dSDimitry 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 
340b57cec5SDimitry Andric     const MachineRegisterInfo *MRI;
350b57cec5SDimitry Andric     const TargetInstrInfo *TII;
36*bdd1243dSDimitry 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.
784824e7fdSDimitry Andric   for (const MachineOperand &MO : MI->operands()) {
790b57cec5SDimitry Andric     if (MO.isReg() && MO.isDef()) {
808bcb0991SDimitry Andric       Register Reg = MO.getReg();
81*bdd1243dSDimitry Andric       if (Reg.isPhysical()) {
820b57cec5SDimitry Andric         // Don't delete live physreg defs, or any reserved register defs.
83*bdd1243dSDimitry Andric         if (!LivePhysRegs.available(Reg) || MRI->isReserved(Reg))
840b57cec5SDimitry Andric           return false;
850b57cec5SDimitry Andric       } else {
86480093f4SDimitry Andric         if (MO.isDead()) {
87480093f4SDimitry Andric #ifndef NDEBUG
88*bdd1243dSDimitry Andric           // Basic check on the register. All of them should be 'undef'.
89480093f4SDimitry Andric           for (auto &U : MRI->use_nodbg_operands(Reg))
90480093f4SDimitry Andric             assert(U.isUndef() && "'Undef' use on a 'dead' register is found!");
91480093f4SDimitry Andric #endif
92480093f4SDimitry Andric           continue;
93480093f4SDimitry Andric         }
940b57cec5SDimitry Andric         for (const MachineInstr &Use : MRI->use_nodbg_instructions(Reg)) {
950b57cec5SDimitry Andric           if (&Use != MI)
960b57cec5SDimitry Andric             // This def has a non-debug use. Don't delete the instruction!
970b57cec5SDimitry Andric             return false;
980b57cec5SDimitry Andric         }
990b57cec5SDimitry Andric       }
1000b57cec5SDimitry Andric     }
1010b57cec5SDimitry Andric   }
1020b57cec5SDimitry Andric 
1030b57cec5SDimitry Andric   // If there are no defs with uses, the instruction is dead.
1040b57cec5SDimitry Andric   return true;
1050b57cec5SDimitry Andric }
1060b57cec5SDimitry Andric 
1070b57cec5SDimitry Andric bool DeadMachineInstructionElim::runOnMachineFunction(MachineFunction &MF) {
1080b57cec5SDimitry Andric   if (skipFunction(MF.getFunction()))
1090b57cec5SDimitry Andric     return false;
110*bdd1243dSDimitry Andric 
111*bdd1243dSDimitry Andric   MRI = &MF.getRegInfo();
112*bdd1243dSDimitry Andric 
113*bdd1243dSDimitry Andric   const TargetSubtargetInfo &ST = MF.getSubtarget();
114*bdd1243dSDimitry Andric   TII = ST.getInstrInfo();
115*bdd1243dSDimitry Andric   LivePhysRegs.init(*ST.getRegisterInfo());
116*bdd1243dSDimitry Andric 
117e8d8bef9SDimitry Andric   bool AnyChanges = eliminateDeadMI(MF);
118e8d8bef9SDimitry Andric   while (AnyChanges && eliminateDeadMI(MF))
119e8d8bef9SDimitry Andric     ;
120e8d8bef9SDimitry Andric   return AnyChanges;
121e8d8bef9SDimitry Andric }
1220b57cec5SDimitry Andric 
123e8d8bef9SDimitry Andric bool DeadMachineInstructionElim::eliminateDeadMI(MachineFunction &MF) {
1240b57cec5SDimitry Andric   bool AnyChanges = false;
1250b57cec5SDimitry Andric 
1260b57cec5SDimitry Andric   // Loop over all instructions in all blocks, from bottom to top, so that it's
1270b57cec5SDimitry Andric   // more likely that chains of dependent but ultimately dead instructions will
1280b57cec5SDimitry Andric   // be cleaned up.
129e8d8bef9SDimitry Andric   for (MachineBasicBlock *MBB : post_order(&MF)) {
130*bdd1243dSDimitry Andric     LivePhysRegs.addLiveOuts(*MBB);
1310b57cec5SDimitry Andric 
1320b57cec5SDimitry Andric     // Now scan the instructions and delete dead ones, tracking physreg
1330b57cec5SDimitry Andric     // liveness as we go.
134*bdd1243dSDimitry Andric     for (MachineInstr &MI : make_early_inc_range(reverse(*MBB))) {
1350b57cec5SDimitry Andric       // If the instruction is dead, delete it!
136349cc55cSDimitry Andric       if (isDead(&MI)) {
137349cc55cSDimitry Andric         LLVM_DEBUG(dbgs() << "DeadMachineInstructionElim: DELETING: " << MI);
1380b57cec5SDimitry Andric         // It is possible that some DBG_VALUE instructions refer to this
1390eae32dcSDimitry Andric         // instruction. They will be deleted in the live debug variable
1400eae32dcSDimitry Andric         // analysis.
1410eae32dcSDimitry Andric         MI.eraseFromParent();
1420b57cec5SDimitry Andric         AnyChanges = true;
1430b57cec5SDimitry Andric         ++NumDeletes;
1440b57cec5SDimitry Andric         continue;
1450b57cec5SDimitry Andric       }
1460b57cec5SDimitry Andric 
147*bdd1243dSDimitry Andric       LivePhysRegs.stepBackward(MI);
1480b57cec5SDimitry Andric     }
1490b57cec5SDimitry Andric   }
1500b57cec5SDimitry Andric 
1510b57cec5SDimitry Andric   LivePhysRegs.clear();
1520b57cec5SDimitry Andric   return AnyChanges;
1530b57cec5SDimitry Andric }
154