CACAO
DominatorPass.cpp
Go to the documentation of this file.
1 /* src/vm/jit/compiler2/DominatorPass.cpp - DominatorPass
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 
31 #include "toolbox/logging.hpp"
32 
33 #define DEBUG_NAME "compiler2/DominatorPass"
34 
35 namespace cacao {
36 namespace jit {
37 namespace compiler2 {
38 
39 ///////////////////////////////////////////////////////////////////////////////
40 // DominatorTree
41 ///////////////////////////////////////////////////////////////////////////////
43  for ( ; b != NULL ; b = get_idominator(b) ) {
44  if (a == b)
45  return true;
46  }
47  return false;
48 }
49 
51  // trivial cases
52  if (!a)
53  return b;
54  if (!b)
55  return a;
56  if (dominates(a,b))
57  return a;
58  if (dominates(b,a))
59  return b;
60  // collect a's dominators
62  while ( (a = get_idominator(a)) ) {
63  dom_a.insert(a);
64  }
65 
66  // search nearest common dominator
67  for(alloc::set<NodeTy*>::type::const_iterator e = dom_a.end(); b != NULL ; b = get_idominator(b) ) {
68  if (dom_a.find(b) != e) {
69  return b;
70  }
71  }
72  return NULL;
73 }
74 
75 ///////////////////////////////////////////////////////////////////////////////
76 // DominatorPass
77 ///////////////////////////////////////////////////////////////////////////////
78 
80  EndInst *ve = v->get_EndInst();
81  assert(ve);
82  for (EndInst::SuccessorListTy::const_iterator i = ve->succ_begin(),
83  e = ve->succ_end(); i != e; ++i) {
84  list.insert(i->get());
85  }
86  return list;
87 }
88 
90  assert(v);
91  semi[v] = ++n;
92  vertex[n] = v;
93  // TODO this can be done better
94  NodeListTy succ_v;
95  succ_v = succ(v, succ_v);
96  LOG("number of succ for " << (long)v << " (" << n << ") " << " = " << succ_v.size() << nl);
97  for(NodeListTy::const_iterator i = succ_v.begin() , e = succ_v.end();
98  i != e; ++i) {
99  NodeTy *w = *i;
100  if (semi[w] == 0) {
101  parent[w] = v;
102  DFS(w);
103  }
104  pred[w].insert(v);
105  }
106 }
107 
108 // simple versions
110  ancestor[w] = v;
111 }
112 
114  if (ancestor[v] == 0) {
115  return v;
116  } else {
117  return label[v];
118  }
119 }
120 
122  // this preocedure assumes ancestor[v] != 0
123  assert(ancestor[v]);
124  if (ancestor[ancestor[v]] != 0) {
125  Compress(ancestor[v]);
126  if (semi[label[ancestor[v]]] < semi[label[v]]) {
127  label[v] = label[ancestor[v]];
128  }
129  ancestor[v] = ancestor[ancestor[v]];
130  }
131 }
132 
134  Method *M = JD.get_Method();
135  // initialize
136  n = 0;
137  vertex.resize(M->bb_size() + 1); // +1 because we start at 1 not at 0
138  for(Method::BBListTy::const_iterator i = M->bb_begin(), e = M->bb_end() ;
139  i != e; ++i) {
140  NodeTy *v = *i;
141  // pred[v] = NodeListTy(); // maps are auto initialized at first access
142  semi[v] = 0;
143  // init label and ancestor array
144  ancestor[v] = 0;
145  label[v] = v;
146  }
147  DFS(M->get_init_bb());
148 
149  LOG("DFS:" << nl);
150  for (int i = 1 ; i <= n; ++i) {
151  LOG("index" << setw(3) << i << " " << (long)vertex[i] << nl);
152  }
153 
154  // from n to 2
155  for (int i = n; i >= 2; --i) {
156  NodeTy *w = vertex[i];
157  // step 2
158  NodeListTy &pred_w = pred[w];
159  for (NodeListTy::const_iterator it = pred_w.begin(), et = pred_w.end();
160  it != et; ++it) {
161  NodeTy *v = *it;
162  NodeTy *u = Eval(v);
163  if (semi[u] < semi[w]) {
164  semi[w] = semi[u];
165  }
166  }
167  bucket[vertex[semi[w]]].insert(w);
168  Link(parent[w],w);
169  // step 3
170  NodeListTy &bucket_p_w = bucket[parent[w]];
171  for (NodeListTy::const_iterator it = bucket_p_w.begin(), et = bucket_p_w.end();
172  it != et; ) {
173  NodeListTy::const_iterator ittmp = it;
174  it++;
175  NodeTy *v = *ittmp;
176  bucket_p_w.erase(ittmp);
177  NodeTy *u = Eval(v);
178  dom[v] = semi[u] < semi[v] ? u : parent[w] ;
179  }
180 
181  }
182 
183  // step 4
184  for (int i = 2; i <= n ; ++i) {
185  NodeTy *w = vertex[i];
186  if (dom[w] != vertex[semi[w]]) {
187  dom[w] = dom[dom[w]];
188  }
189  }
190  dom[M->get_init_bb()];
191 
192  LOG("Dominators:" << nl);
193  #if defined(ENABLE_LOGGING)
194  if (DEBUG_COND_N(0)) {
195  for (int i = 1 ; i <= n; ++i) {
196  NodeTy *v = vertex[i];
197  NodeTy *w = dom[v];
198  LOG("index" << setw(3) << i << " dom(" << (long)v <<") =" << (long)w << nl);
199  }
200  }
201  #endif
202 
203  return true;
204 }
205 
206 // pass usage
209  return PU;
210 }
211 
212 // the address of this variable is used to identify the pass
213 char DominatorPass::ID = 0;
214 
215 // register pass
216 static PassRegistry<DominatorPass> X("DominatorPass");
217 
218 } // end namespace compiler2
219 } // end namespace jit
220 } // end namespace cacao
221 
222 
223 /*
224  * These are local overrides for various environment variables in Emacs.
225  * Please do not remove this and leave it at the end of the file, where
226  * Emacs will automagically detect them.
227  * ---------------------------------------------------------------------
228  * Local variables:
229  * mode: c++
230  * indent-tabs-mode: t
231  * c-basic-offset: 4
232  * tab-width: 4
233  * End:
234  * vim:noexpandtab:sw=4:ts=4:
235  */
236 
std::set< Key, Compare, Allocator< Key > > type
Definition: set.hpp:38
static SetWidth setw(size_t w)
Definition: OStream.hpp:395
alloc::set< NodeTy * >::type NodeListTy
const_bb_iterator bb_end() const
Definition: MethodC2.hpp:153
This Instruction mark the start of a basic block.
NodeListTy & succ(NodeTy *v, NodeListTy &list)
This Instruction mark the end of a basic block.
#define DEBUG_COND_N(VERBOSE)
Definition: Debug.hpp:112
SuccessorListTy::const_iterator succ_end() const
NodeTy * get_idominator(NodeTy *a) const
Get the immediate dominator.
virtual PassUsage & get_PassUsage(PassUsage &PU) const
Set the requirements for the pass.
Stores the interdependencies of a pass.
Definition: PassUsage.hpp:55
MIIterator i
SuccessorListTy::const_iterator succ_begin() const
NodeTy * find_nearest_common_dom(NodeTy *a, NodeTy *b) const
Find the nearest common dominator.
MIIterator e
#define LOG(STMT)
Analogous to DEBUG.
Definition: logging.hpp:91
bool dominates(NodeTy *a, NodeTy *b) const
True if a dominates b.
const Method & M
virtual bool run(JITData &JD)
Run the Pass.
void Link(NodeTy *v, NodeTy *w)
static PassRegistry< BasicBlockSchedulingPass > X("BasicBlockSchedulingPass")
Nl nl
Definition: OStream.cpp:56
BeginInst * get_init_bb() const
Definition: MethodC2.hpp:133
void add_requires()
PassName is required.
Definition: PassUsage.hpp:78
const_bb_iterator bb_begin() const
Definition: MethodC2.hpp:149