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