CACAO
DeadCodeEliminationPass.cpp
Go to the documentation of this file.
1 /* src/vm/jit/compiler2/DeadCodeEliminationPass.cpp - DeadCodeEliminationPass
2 
3  Copyright (C) 2013
4  CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5 
6  This file is part of CACAO.
7 
8  This program is free software; you can redistribute it and/or
9  modify it under the terms of the GNU General Public License as
10  published by the Free Software Foundation; either version 2, or (at
11  your option) any later version.
12 
13  This program is distributed in the hope that it will be useful, but
14  WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with this program; if not, write to the Free Software
20  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21  02110-1301, USA.
22 
23 */
24 
30 #include "toolbox/logging.hpp"
36 
37 #define DEBUG_NAME "compiler2/DeadCodeEliminationPass"
38 
39 STAT_DECLARE_GROUP(compiler2_stat)
40 STAT_REGISTER_SUBGROUP(compiler2_deadcodeeliminationpass_stat,
41  "deadcodeeliminationpass","deadcodeeliminationpass",compiler2_stat)
42 STAT_REGISTER_GROUP_VAR(std::size_t,num_dead_nodes,0,"# dead nodes",
43  "number of removed dead nodes",compiler2_deadcodeeliminationpass_stat)
44 STAT_REGISTER_GROUP_VAR(std::size_t,num_remaining_nodes,0,"# remaining nodes",
45  "number of nodes not removed",compiler2_deadcodeeliminationpass_stat)
46 
47 namespace cacao {
48 namespace jit {
49 namespace compiler2 {
50 
51 // TODO: maybe we should make this a flag in the Instruction class
52 bool is_control_flow_inst(Instruction *inst) {
53  return inst->get_opcode() == Instruction::BeginInstID
54  || inst->to_EndInst();
55 }
56 
58  Method *M = JD.get_Method();
59 
60  // this work list is used by the algorithm to store the instructions which
61  // have to be reconsidered. at the beginning it therefore contains all
62  // instructions.
63  Method::InstructionListTy workList(M->begin(), M->end());
64 
65  // will be used to look up whether an instruction is currently contained in the
66  // worklist to avoid inserting an instruction which is already in the list.
67  InstBoolMapTy inWorkList;
68  for (Method::const_iterator i = workList.begin(), e = workList.end();
69  i != e; i++) {
70  inWorkList[*i] = true;
71  }
72 
73  // will be used to mark instructions as dead.
74  InstBoolMapTy dead;
75 
76  // used to track for each instruction the number of its users which are
77  // already dead
78  InstIntMapTy deadUsers;
79 
80  Method::InstructionListTy liveInstructions;
81  Method::InstructionListTy deadInstructions;
82 
83  while (!workList.empty()) {
84  Instruction *I = workList.front();
85  workList.pop_front();
86  inWorkList[I] = false;
87 
88  // here we inspect whether the node that has just been picked from
89  // the work list is dead
90  if (I->user_size() == deadUsers[I] && !I->has_side_effects()
91  && I->is_floating()
92  && !is_control_flow_inst(I) && !I->to_SourceStateInst()
94  && !I->to_AssumptionInst()
95  && I->rdep_size() == 0) {
96  dead[I] = true;
97  InstBoolMapTy visited;
98 
99  // insert the dead instructions in the order they should be deleted
100  deadInstructions.push_back(I);
101 
102  for (Instruction::OperandListTy::const_iterator
103  i = I->op_begin(), e = I->op_end(); i != e; i++) {
104  Instruction *Op = (*i)->to_Instruction();
105 
106  if (Op && !visited[Op]) {
107  visited[Op] = true;
108  deadUsers[Op]++;
109 
110  if (!inWorkList[Op]) {
111  workList.push_back(Op);
112  inWorkList[Op] = true;
113  }
114  }
115  }
116  }
117  }
118 
119  // collect the living instructions (i.e., the instructions which are not dead)
120  for (Method::const_iterator i = M->begin(), e = M->end(); i != e; i++) {
121  Instruction *I = *i;
122  if (dead[I]) {
123  LOG("Dead: " << I << nl);
124  } else {
125  liveInstructions.push_back(I);
126  LOG("Live: " << I << nl);
127  }
128  }
129 
130  STATISTICS(num_dead_nodes = deadInstructions.size());
131  STATISTICS(num_remaining_nodes = liveInstructions.size());
132 
133  M->replace_instruction_list(liveInstructions.begin(), liveInstructions.end());
134 
135  // delete the dead instructions
136  while (!deadInstructions.empty()) {
137  Instruction *I = deadInstructions.front();
138  deadInstructions.pop_front();
139  delete I;
140  }
141 
142  return true;
143 }
144 
145 // pass usage
150  return PU;
151 }
152 
153 Option<bool> DeadCodeEliminationPass::enabled("DeadCodeEliminationPass","compiler2: enable dead code elimination (default = true)",true,::cacao::option::xx_root());
154 
155 // register pass
156 static PassRegistry<DeadCodeEliminationPass> X("DeadCodeEliminationPass");
157 
158 } // end namespace compiler2
159 } // end namespace jit
160 } // end namespace cacao
161 
162 
163 /*
164  * These are local overrides for various environment variables in Emacs.
165  * Please do not remove this and leave it at the end of the file, where
166  * Emacs will automagically detect them.
167  * ---------------------------------------------------------------------
168  * Local variables:
169  * mode: c++
170  * indent-tabs-mode: t
171  * c-basic-offset: 4
172  * tab-width: 4
173  * End:
174  * vim:noexpandtab:sw=4:ts=4:
175  */
alloc::unordered_map< Instruction *, bool >::type InstBoolMapTy
#define STATISTICS(x)
Wrapper for statistics only code.
Definition: statistics.hpp:975
alloc::list< Instruction * >::type InstructionListTy
Definition: MethodC2.hpp:66
#define STAT_REGISTER_SUBGROUP(var, name, description, group)
Register a statistics group and add it to a group.
Definition: statistics.hpp:974
alloc::unordered_map< Instruction *, std::size_t >::type InstIntMapTy
virtual bool is_floating() const
True if the instruction has no fixed control dependencies.
virtual bool has_side_effects() const
True the instruction has side effects.
void replace_instruction_list(InputIterator first, InputIterator last)
Replaces the instructions of the method, with the instructions in the given range [first...
Definition: MethodC2.hpp:117
SSAPrinterPass TODO: more info.
virtual PassUsage & get_PassUsage(PassUsage &PA) const
Set the requirements for the pass.
void add_schedule_before()
Schedule before PassName.
Definition: PassUsage.hpp:127
virtual SourceStateInst * to_SourceStateInst()
Definition: Instruction.hpp:83
Stores the interdependencies of a pass.
Definition: PassUsage.hpp:55
#define STAT_REGISTER_GROUP_VAR(type, var, init, name, description, group)
Register an statistics variable and add it to a group.
Definition: statistics.hpp:967
virtual Instruction * to_Instruction()
Instruction super class.
Definition: Instruction.hpp:75
MIIterator i
InstructionListTy::const_iterator const_iterator
Definition: MethodC2.hpp:69
const_iterator end() const
Definition: MethodC2.hpp:147
const_op_iterator op_begin() const
virtual AssumptionInst * to_AssumptionInst()
Definition: Instruction.hpp:85
MIIterator e
#define LOG(STMT)
Analogous to DEBUG.
Definition: logging.hpp:91
#define I(value)
Definition: codegen.c:279
OptionPrefix & xx_root()
Definition: Option.cpp:39
#define STAT_DECLARE_GROUP(var)
Declare an external group (or subgroup).
Definition: statistics.hpp:970
const Method & M
const_iterator begin() const
Definition: MethodC2.hpp:143
size_t user_size() const
Get the number of (unique) users.
Definition: Value.hpp:81
virtual bool run(JITData &JD)
Run the Pass.
virtual ReplacementEntryInst * to_ReplacementEntryInst()
Definition: Instruction.hpp:84
static PassRegistry< BasicBlockSchedulingPass > X("BasicBlockSchedulingPass")
Nl nl
Definition: OStream.cpp:56
const_op_iterator op_end() const
void add_requires()
PassName is required.
Definition: PassUsage.hpp:78