xref: /src/contrib/llvm-project/llvm/lib/CodeGen/DeadMachineInstructionElim.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1009b1c42SEd Schouten //===- DeadMachineInstructionElim.cpp - Remove dead machine instructions --===//
2009b1c42SEd Schouten //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6009b1c42SEd Schouten //
7009b1c42SEd Schouten //===----------------------------------------------------------------------===//
8009b1c42SEd Schouten //
9009b1c42SEd Schouten // This is an extremely simple MachineInstr-level dead-code-elimination pass.
10009b1c42SEd Schouten //
11009b1c42SEd Schouten //===----------------------------------------------------------------------===//
12009b1c42SEd Schouten 
13ac9a064cSDimitry Andric #include "llvm/CodeGen/DeadMachineInstructionElim.h"
14b60736ecSDimitry Andric #include "llvm/ADT/PostOrderIterator.h"
154a16efa3SDimitry Andric #include "llvm/ADT/Statistic.h"
16e3b55780SDimitry Andric #include "llvm/CodeGen/LiveRegUnits.h"
17009b1c42SEd Schouten #include "llvm/CodeGen/MachineFunctionPass.h"
18009b1c42SEd Schouten #include "llvm/CodeGen/MachineRegisterInfo.h"
19044eb2f6SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h"
20706b4fc4SDimitry Andric #include "llvm/InitializePasses.h"
214a16efa3SDimitry Andric #include "llvm/Pass.h"
22009b1c42SEd Schouten #include "llvm/Support/Debug.h"
2359850d08SRoman Divacky #include "llvm/Support/raw_ostream.h"
2467c32a98SDimitry Andric 
25009b1c42SEd Schouten using namespace llvm;
26009b1c42SEd Schouten 
27ab44ce3dSDimitry Andric #define DEBUG_TYPE "dead-mi-elimination"
285ca98fd9SDimitry Andric 
296fe5c7aaSRoman Divacky STATISTIC(NumDeletes,          "Number of dead instructions deleted");
306fe5c7aaSRoman Divacky 
31009b1c42SEd Schouten namespace {
32ac9a064cSDimitry Andric class DeadMachineInstructionElimImpl {
337fa27ce4SDimitry Andric   const MachineRegisterInfo *MRI = nullptr;
347fa27ce4SDimitry Andric   const TargetInstrInfo *TII = nullptr;
35e3b55780SDimitry Andric   LiveRegUnits LivePhysRegs;
36009b1c42SEd Schouten 
37009b1c42SEd Schouten public:
38ac9a064cSDimitry Andric   bool runImpl(MachineFunction &MF);
39ac9a064cSDimitry Andric 
40ac9a064cSDimitry Andric private:
41ac9a064cSDimitry Andric   bool isDead(const MachineInstr *MI) const;
42ac9a064cSDimitry Andric   bool eliminateDeadMI(MachineFunction &MF);
43ac9a064cSDimitry Andric };
44ac9a064cSDimitry Andric 
45ac9a064cSDimitry Andric class DeadMachineInstructionElim : public MachineFunctionPass {
46ac9a064cSDimitry Andric public:
47009b1c42SEd Schouten   static char ID; // Pass identification, replacement for typeid
48ac9a064cSDimitry Andric 
DeadMachineInstructionElim()49cf099d11SDimitry Andric   DeadMachineInstructionElim() : MachineFunctionPass(ID) {
50cf099d11SDimitry Andric     initializeDeadMachineInstructionElimPass(*PassRegistry::getPassRegistry());
51cf099d11SDimitry Andric   }
52009b1c42SEd Schouten 
runOnMachineFunction(MachineFunction & MF)53ac9a064cSDimitry Andric   bool runOnMachineFunction(MachineFunction &MF) override {
54ac9a064cSDimitry Andric     if (skipFunction(MF.getFunction()))
55ac9a064cSDimitry Andric       return false;
56ac9a064cSDimitry Andric     return DeadMachineInstructionElimImpl().runImpl(MF);
57ac9a064cSDimitry Andric   }
58ac9a064cSDimitry Andric 
getAnalysisUsage(AnalysisUsage & AU) const5901095a5dSDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override {
6001095a5dSDimitry Andric     AU.setPreservesCFG();
6101095a5dSDimitry Andric     MachineFunctionPass::getAnalysisUsage(AU);
6201095a5dSDimitry Andric   }
63009b1c42SEd Schouten };
64ac9a064cSDimitry Andric } // namespace
65ac9a064cSDimitry Andric 
66ac9a064cSDimitry Andric PreservedAnalyses
run(MachineFunction & MF,MachineFunctionAnalysisManager &)67ac9a064cSDimitry Andric DeadMachineInstructionElimPass::run(MachineFunction &MF,
68ac9a064cSDimitry Andric                                     MachineFunctionAnalysisManager &) {
69ac9a064cSDimitry Andric   if (!DeadMachineInstructionElimImpl().runImpl(MF))
70ac9a064cSDimitry Andric     return PreservedAnalyses::all();
71ac9a064cSDimitry Andric   PreservedAnalyses PA = getMachineFunctionPassPreservedAnalyses();
72ac9a064cSDimitry Andric   PA.preserveSet<CFGAnalyses>();
73ac9a064cSDimitry Andric   return PA;
741a82d4c0SDimitry Andric }
75ac9a064cSDimitry Andric 
76009b1c42SEd Schouten char DeadMachineInstructionElim::ID = 0;
7763faed5bSDimitry Andric char &llvm::DeadMachineInstructionElimID = DeadMachineInstructionElim::ID;
78009b1c42SEd Schouten 
79ab44ce3dSDimitry Andric INITIALIZE_PASS(DeadMachineInstructionElim, DEBUG_TYPE,
80cf099d11SDimitry Andric                 "Remove dead machine instructions", false, false)
81009b1c42SEd Schouten 
isDead(const MachineInstr * MI) const82ac9a064cSDimitry Andric bool DeadMachineInstructionElimImpl::isDead(const MachineInstr *MI) const {
83cf099d11SDimitry Andric   // Technically speaking inline asm without side effects and no defs can still
84cf099d11SDimitry Andric   // be deleted. But there is so much bad inline asm code out there, we should
85cf099d11SDimitry Andric   // let them be.
86cf099d11SDimitry Andric   if (MI->isInlineAsm())
87cf099d11SDimitry Andric     return false;
88cf099d11SDimitry Andric 
8967c32a98SDimitry Andric   // Don't delete frame allocation labels.
90ee8648bdSDimitry Andric   if (MI->getOpcode() == TargetOpcode::LOCAL_ESCAPE)
9167c32a98SDimitry Andric     return false;
9267c32a98SDimitry Andric 
93009b1c42SEd Schouten   // Don't delete instructions with side effects.
94009b1c42SEd Schouten   bool SawStore = false;
955a5ac124SDimitry Andric   if (!MI->isSafeToMove(nullptr, SawStore) && !MI->isPHI())
96009b1c42SEd Schouten     return false;
97009b1c42SEd Schouten 
98009b1c42SEd Schouten   // Examine each operand.
997fa27ce4SDimitry Andric   for (const MachineOperand &MO : MI->all_defs()) {
1001d5ae102SDimitry Andric     Register Reg = MO.getReg();
101e3b55780SDimitry Andric     if (Reg.isPhysical()) {
10263faed5bSDimitry Andric       // Don't delete live physreg defs, or any reserved register defs.
103e3b55780SDimitry Andric       if (!LivePhysRegs.available(Reg) || MRI->isReserved(Reg))
10463faed5bSDimitry Andric         return false;
10563faed5bSDimitry Andric     } else {
106706b4fc4SDimitry Andric       if (MO.isDead()) {
107706b4fc4SDimitry Andric #ifndef NDEBUG
108e3b55780SDimitry Andric         // Basic check on the register. All of them should be 'undef'.
109706b4fc4SDimitry Andric         for (auto &U : MRI->use_nodbg_operands(Reg))
110706b4fc4SDimitry Andric           assert(U.isUndef() && "'Undef' use on a 'dead' register is found!");
111706b4fc4SDimitry Andric #endif
112706b4fc4SDimitry Andric         continue;
113706b4fc4SDimitry Andric       }
114e6d15924SDimitry Andric       for (const MachineInstr &Use : MRI->use_nodbg_instructions(Reg)) {
115e6d15924SDimitry Andric         if (&Use != MI)
1166fe5c7aaSRoman Divacky           // This def has a non-debug use. Don't delete the instruction!
117009b1c42SEd Schouten           return false;
118009b1c42SEd Schouten       }
119009b1c42SEd Schouten     }
120009b1c42SEd Schouten   }
121009b1c42SEd Schouten 
122009b1c42SEd Schouten   // If there are no defs with uses, the instruction is dead.
123009b1c42SEd Schouten   return true;
124009b1c42SEd Schouten }
125009b1c42SEd Schouten 
runImpl(MachineFunction & MF)126ac9a064cSDimitry Andric bool DeadMachineInstructionElimImpl::runImpl(MachineFunction &MF) {
127e3b55780SDimitry Andric   MRI = &MF.getRegInfo();
128e3b55780SDimitry Andric 
129e3b55780SDimitry Andric   const TargetSubtargetInfo &ST = MF.getSubtarget();
130e3b55780SDimitry Andric   TII = ST.getInstrInfo();
131e3b55780SDimitry Andric   LivePhysRegs.init(*ST.getRegisterInfo());
132e3b55780SDimitry Andric 
133b60736ecSDimitry Andric   bool AnyChanges = eliminateDeadMI(MF);
134b60736ecSDimitry Andric   while (AnyChanges && eliminateDeadMI(MF))
135b60736ecSDimitry Andric     ;
136b60736ecSDimitry Andric   return AnyChanges;
137b60736ecSDimitry Andric }
1385ca98fd9SDimitry Andric 
eliminateDeadMI(MachineFunction & MF)139ac9a064cSDimitry Andric bool DeadMachineInstructionElimImpl::eliminateDeadMI(MachineFunction &MF) {
140009b1c42SEd Schouten   bool AnyChanges = false;
141009b1c42SEd Schouten 
142009b1c42SEd Schouten   // Loop over all instructions in all blocks, from bottom to top, so that it's
143009b1c42SEd Schouten   // more likely that chains of dependent but ultimately dead instructions will
144009b1c42SEd Schouten   // be cleaned up.
145b60736ecSDimitry Andric   for (MachineBasicBlock *MBB : post_order(&MF)) {
146e3b55780SDimitry Andric     LivePhysRegs.addLiveOuts(*MBB);
147d39c594dSDimitry Andric 
148009b1c42SEd Schouten     // Now scan the instructions and delete dead ones, tracking physreg
149009b1c42SEd Schouten     // liveness as we go.
150e3b55780SDimitry Andric     for (MachineInstr &MI : make_early_inc_range(reverse(*MBB))) {
151009b1c42SEd Schouten       // If the instruction is dead, delete it!
152c0981da4SDimitry Andric       if (isDead(&MI)) {
153c0981da4SDimitry Andric         LLVM_DEBUG(dbgs() << "DeadMachineInstructionElim: DELETING: " << MI);
1546fe5c7aaSRoman Divacky         // It is possible that some DBG_VALUE instructions refer to this
15577fc4c14SDimitry Andric         // instruction. They will be deleted in the live debug variable
15677fc4c14SDimitry Andric         // analysis.
15777fc4c14SDimitry Andric         MI.eraseFromParent();
158009b1c42SEd Schouten         AnyChanges = true;
1596fe5c7aaSRoman Divacky         ++NumDeletes;
160009b1c42SEd Schouten         continue;
161009b1c42SEd Schouten       }
162009b1c42SEd Schouten 
163e3b55780SDimitry Andric       LivePhysRegs.stepBackward(MI);
164009b1c42SEd Schouten     }
165009b1c42SEd Schouten   }
166009b1c42SEd Schouten 
167009b1c42SEd Schouten   LivePhysRegs.clear();
168009b1c42SEd Schouten   return AnyChanges;
169009b1c42SEd Schouten }
170