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  && !is_control_flow_inst(I) && I->rdep_size() == 0) {
92  dead[I] = true;
93  InstBoolMapTy visited;
94 
95  // insert the dead instructions in the order they should be deleted
96  deadInstructions.push_back(I);
97 
98  for (Instruction::OperandListTy::const_iterator
99  i = I->op_begin(), e = I->op_end(); i != e; i++) {
100  Instruction *Op = (*i)->to_Instruction();
101 
102  if (Op && !visited[Op]) {
103  visited[Op] = true;
104  deadUsers[Op]++;
105 
106  if (!inWorkList[Op]) {
107  workList.push_back(Op);
108  inWorkList[Op] = true;
109  }
110  }
111  }
112  }
113  }
114 
115  // collect the living instructions (i.e., the instructions which are not dead)
116  for (Method::const_iterator i = M->begin(), e = M->end(); i != e; i++) {
117  Instruction *I = *i;
118  if (dead[I]) {
119  LOG("Dead: " << I << nl);
120  } else {
121  liveInstructions.push_back(I);
122  LOG("Live: " << I << nl);
123  }
124  }
125 
126  STATISTICS(num_dead_nodes = deadInstructions.size());
127  STATISTICS(num_remaining_nodes = liveInstructions.size());
128 
129  M->replace_instruction_list(liveInstructions.begin(), liveInstructions.end());
130 
131  // delete the dead instructions
132  while (!deadInstructions.empty()) {
133  Instruction *I = deadInstructions.front();
134  deadInstructions.pop_front();
135  delete I;
136  }
137 
138  return true;
139 }
140 
141 // pass usage
146  return PU;
147 }
148 
149 // the address of this variable is used to identify the pass
151 
152 // register pass
153 static PassRegistry<DeadCodeEliminationPass> X("DeadCodeEliminationPass");
154 
155 } // end namespace compiler2
156 } // end namespace jit
157 } // end namespace cacao
158 
159 
160 /*
161  * These are local overrides for various environment variables in Emacs.
162  * Please do not remove this and leave it at the end of the file, where
163  * Emacs will automagically detect them.
164  * ---------------------------------------------------------------------
165  * Local variables:
166  * mode: c++
167  * indent-tabs-mode: t
168  * c-basic-offset: 4
169  * tab-width: 4
170  * End:
171  * vim:noexpandtab:sw=4:ts=4:
172  */
#define STATISTICS(x)
Wrapper for statistics only code.
Definition: statistics.hpp:975
alloc::list< Instruction * >::type InstructionListTy
Definition: MethodC2.hpp:64
#define STAT_REGISTER_SUBGROUP(var, name, description, group)
Register a statistics group and add it to a group.
Definition: statistics.hpp:974
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:111
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
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:73
MIIterator i
InstructionListTy::const_iterator const_iterator
Definition: MethodC2.hpp:67
const_iterator end() const
Definition: MethodC2.hpp:141
const_op_iterator op_begin() const
MIIterator e
#define LOG(STMT)
Analogous to DEBUG.
Definition: logging.hpp:91
#define I(value)
Definition: codegen.c:279
#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:137
size_t user_size() const
Get the number of (unique) users.
Definition: Value.hpp:81
virtual bool run(JITData &JD)
Run the Pass.
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