CACAO
LoopPassBase.hpp
Go to the documentation of this file.
1 /* src/vm/jit/compiler2/LoopPassBase.hpp - LoopPassBase
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 
25 #ifndef _JIT_COMPILER2_LOOPPASSBASE
26 #define _JIT_COMPILER2_LOOPPASSBASE
27 
32 
33 #include "toolbox/UnionFind.hpp"
34 
38 
39 namespace cacao {
40 namespace jit {
41 namespace compiler2 {
42 
43 /**
44  * Calculate the Loop Tree.
45  *
46  * The algorithm used here is based on the method proposed in
47  * "Testing Flow Graph Reducibility" by Tarjan @cite Tarjan1974
48  * with the modifications in "SSA-Based Reduction of Operator Strengh" by
49  * Vick @cite VickMScThesis. See also Click's Phd Thesis, Chapter 6
50  * @cite ClickPHD.
51  */
52 template <class _T>
53 class LoopPassBase : public Pass, public memory::ManagerMixin<LoopPassBase<_T> >, public LoopTreeBase<_T> {
54 private:
55  typedef _T NodeType;
61 
62  #if 0
64  NodeListMapTy pred;
65  #endif
69  int n;
70 
73 
74  NodeListTy& succ(const NodeType *v, NodeListTy &list);
75  #if 0
76  void DFS(const NodeType * v);
77 
78  void Link(const NodeType *v, const NodeType *w);
79  const NodeType* Eval(const NodeType *v);
80  void Compress(const NodeType *v);
81  #endif
82 
84 public:
85  LoopPassBase() : Pass() {}
86  virtual bool run(JITData &JD);
87  virtual PassUsage& get_PassUsage(PassUsage &PU) const;
88 };
89 
90 template<class NodeType>
92 private:
94 public:
97  NodeType *a_i = a->get_header();
98  NodeType *b_i = b->get_header();
99  if (dfs[a_i] == dfs[b_i]) {
100  a_i = a->get_exit();
101  b_i = b->get_exit();
102  }
103  return dfs[a_i] < dfs[b_i];
104  }
105 };
106 
107 template <class _T>
108 inline bool LoopPassBase<_T>::run(JITData &JD) {
109  DFSTraversal<NodeType> dfs(get_init_node(JD));
110  int size = dfs.size();
111 
112  alloc::vector<alloc::set<int>::type >::type backedges(size);
113  alloc::vector<alloc::set<int>::type >::type forwardedges(size);
114  alloc::vector<alloc::set<int>::type >::type crossedges(size);
115  alloc::vector<alloc::set<int>::type >::type treeedges(size);
116  alloc::vector<int>::type highpt(size,-1);
117 
118  int end = -1;
119 
120  UnionFindImpl<int> unionfind(end);
121 
122  // store the loop for each bb
123  typename alloc::vector<LoopBase<NodeType>*>::type index_to_loop(size);
124 
125 
126  // initialization
127  for (typename DFSTraversal<NodeType>::iterator i = dfs.begin(), e = dfs.end();
128  i != e ; ++i) {
129  int v = i.get_index();
130 
131  unionfind.make_set(v);
132  // get successors
133  typename DFSTraversal<NodeType>::iterator_list successors;
134  i.get_successors(successors);
135 
136  for (typename DFSTraversal<NodeType>::iterator_list::iterator ii = successors.begin(),
137  ee = successors.end(); ii != ee ; ++ii) {
138  int w = (*ii).get_index();
139  // edge v -> w
140 
141  if ((*ii).get_parent() != i) {
142  if (dfs.is_ancestor(v,w)) {
143  // forward edge
144  forwardedges[w].insert(v);
145  } else if (dfs.is_decendant(v,w)) {
146  // backward edge
147  backedges[w].insert(v);
148  } else {
149  // cross edge
150  crossedges[w].insert(v);
151  }
152  } else {
153  // tree edge
154  treeedges[w].insert(v);
155  }
156  }
157  }
158 
159 
160  #if 0
161  for (int w = 0; w < size ; ++w ) {
162  alloc::set<int>::type set = treeedges[w];
163  // print treeedge
164  for(alloc::set<int>::type::iterator i = set.begin(), e = set.end(); i != e ; ++i) {
165  int v = *i;
166  //LOG2("treeedge: " << setw(3) << v << " -> " << setw(3) << w << nl);
167  }
168  // print backedge
169  set = backedges[w];
170  for(alloc::set<int>::type::iterator i = set.begin(), e = set.end(); i != e ; ++i) {
171  int v = *i;
172  //LOG2("backedge: " << setw(3) << v << " -> " << setw(3) << w << nl);
173  }
174  // print forwardedge
175  set = forwardedges[w];
176  for(alloc::set<int>::type::iterator i = set.begin(), e = set.end(); i != e ; ++i) {
177  int v = *i;
178  //LOG2("forwardedge: " << setw(3) << v << " -> " << setw(3) << w << nl);
179  }
180  // print crossedge
181  set = crossedges[w];
182  for(alloc::set<int>::type::iterator i = set.begin(), e = set.end(); i != e ; ++i) {
183  int v = *i;
184  //LOG2("crossedge: " << setw(3) << v << " -> " << setw(3) << w << nl);
185  }
186  }
187  #endif
188 
191  for (typename DFSTraversal<NodeType>::reverse_iterator i = dfs.rbegin(), e = dfs.rend();
192  i != e ; --i) {
193  int w = i.get_index();
194  //LOG2("w=" << w << nl);
195 
196  P.clear();
197  Q.clear();
198 
199  // get incoming backedges
200  alloc::set<int>::type &backedges_w = backedges[w];
201  for(alloc::set<int>::type::iterator i = backedges_w.begin(), e = backedges_w.end();
202  i != e; ++i) {
203  int v = *i;
204  int v_r = unionfind.find(v);
205  assert(v_r != end && "Element not found!");
206  P.insert(v_r);
207  Q.insert(v_r);
208 
209  // create a new loop
210  LoopBase<NodeType> *loop = this->add_loop(dfs[w],dfs[v]);
211 
212  // set loop
213  if(!index_to_loop[v]) {
214  index_to_loop[v] = loop;
215  }
216  if (index_to_loop[w]) {
217  LoopBase<NodeType> *inner_loop = index_to_loop[w];
218  if(inner_loop != loop) {
219  loop->add_inner_loop(inner_loop);
220  }
221  }
222 
223  //LOG2("Q=P= ");
224  //DEBUG2(print_container(dbg(), Q.begin(),Q.end()));
225  //LOG2(nl);
226 
227  // Q contains the sources of the backedges to w.
228  // It must be order from smallest to largest preorder source to
229  // guarantee strict inner to outer ordering.
230  while (!Q.empty()) {
231  int x;
232  // simulate pop_front
233  { // new scope
234  alloc::set<int>::type::iterator x_it = Q.begin();
235  x = *x_it;
236  Q.erase(x_it);
237  }
238  //LOG2("x=" << x << nl);
239 
240  // is loop header?
241  if (backedges[x].size() != 0) {
242  LoopBase<NodeType> *inner_loop = index_to_loop[x];
243  assert(inner_loop);
244  if(inner_loop != loop) {
245  loop->add_inner_loop(inner_loop);
246  }
247  }
248 
249  alloc::set<int>::type incoming;
250  // collect incoming edges
251  { // new scope
252  alloc::set<int>::type ref1 = forwardedges[x];
253  incoming.insert(ref1.begin(), ref1.end());
254  alloc::set<int>::type ref2 = treeedges[x];
255  incoming.insert(ref2.begin(), ref2.end());
256  alloc::set<int>::type ref3 = crossedges[x];
257  incoming.insert(ref3.begin(), ref3.end());
258  }
259  for(alloc::set<int>::type::iterator i = incoming.begin(), e = incoming.end();
260  i != e; ++i) {
261  int y = *i;
262  //LOG2("y=" << y << nl);
263  int y_r = unionfind.find(y);
264  assert(y_r != end);
265  //LOG2("y_r=" << y_r << nl);
266 
267  //LOG("ND(w)=" << dfs.num_decendants(w) << nl);
268  // test for reducibility
269  // TODO <= vs <
270  // if ( (w > y_r) || ( (w + dfs.num_decendants(w)) <= y_r) ) {
271  if ( (w > y_r) || ( (w + dfs.num_decendants(w)) < y_r) ) {
272  assert(0 && "Graph is irreduciable. Can not yet deal with it.");
273  }
274 
275  // add y_r if appropriate
276  if ( P.find(y_r) == P.end() and y_r != w) {
277  P.insert(y_r);
278  Q.insert(y_r);
279  }
280 
281  // set highpt
282  if (highpt[y_r] == -1) {
283  highpt[y_r] = w;
284  }
285 
286  // set loop
287  if (!index_to_loop[y_r]) {
288  index_to_loop[y_r] = loop;
289  }
290  }
291  }
292  }
293 
294  // now P = P(w) in the current graph
295  for(alloc::set<int>::type::iterator i = P.begin(), e = P.end();
296  i != e; ++i) {
297  int x = *i;
298  unionfind.set_union(x,w);
299  }
300  // duplicate edges?
301 
302  }
303  for (int w = 0; w < size ; ++w ) {
304  //LOG2("highpt[" << w << "]=" << highpt[w] << nl);
305  }
306  for (int w = 0; w < size ; ++w ) {
307  LoopBase<NodeType> *loop = index_to_loop[w];
308  if (!loop) {
309  //LOG2("loop(" << dfs[w] << ") not in a loop" << nl);
310  continue;
311  }
312  this->set_loop(dfs[w],loop);
313  //LOG2("loop(header = " << dfs[w] << ") = " << loop << nl);
314  }
315 
316  // sort from outermost to innermost loop
317  LoopComparator<NodeType> compare_loop(dfs);
318  std::sort(LoopTreeBase<NodeType>::begin(), LoopTreeBase<NodeType>::end(), compare_loop);
319 
320  // add NodeType to loops
323  i != e; ++i) {
325  //LOG("Loop: " << loop << nl);
327  if (parent) {
328  //LOG("parent: " << parent << nl);
329  } else {
331  //LOG("parent: " << "toplevel" << nl);
332  }
333  // add to loop headers
335  }
336  return true;
337 }
338 
339 } // end namespace compiler2
340 } // end namespace jit
341 } // end namespace cacao
342 
343 #endif /* _JIT_COMPILER2_LOOPPASSBASE */
344 
345 
346 /*
347  * These are local overrides for various environment variables in Emacs.
348  * Please do not remove this and leave it at the end of the file, where
349  * Emacs will automagically detect them.
350  * ---------------------------------------------------------------------
351  * Local variables:
352  * mode: c++
353  * indent-tabs-mode: t
354  * c-basic-offset: 4
355  * tab-width: 4
356  * End:
357  * vim:noexpandtab:sw=4:ts=4:
358  */
std::set< Key, Compare, Allocator< Key > > type
Definition: set.hpp:38
bool is_decendant(int w, int v) const
Pass superclass All compiler passes should inheritate this class.
Definition: Pass.hpp:47
void add_top_loop(LoopType *loop)
Definition: LoopBase.hpp:134
NodeType * get_exit() const
Definition: LoopBase.hpp:59
void insert_loop_header(NodeType *node, LoopType *loop)
Definition: LoopBase.hpp:108
virtual bool run(JITData &JD)
Run the Pass.
LoopComparator(DFSTraversal< NodeType > &dfs)
virtual T find(T x)
find the repres to of a given element x
Definition: UnionFind.hpp:116
Custom new/delete handler mixin.
Definition: Manager.hpp:43
MachineLoop * loop
const DFSTraversal< BeginInst > dfs
NodeType * get_init_node(JITData &JD)
Definition: LoopPass.cpp:40
DFSTraversal< NodeType > & dfs
virtual void make_set(T s)
Create a new set.
Definition: UnionFind.hpp:83
void add_inner_loop(LoopBase *inner_loop)
Definition: LoopBase.hpp:71
NodeListTy & succ(const NodeType *v, NodeListTy &list)
alloc::set< const NodeType * >::type NodeListTy
bool is_ancestor(int v, int w) const
JNIEnv jthread jobject jclass jlong size
Definition: jvmti.h:387
LoopBase * get_parent() const
Definition: LoopBase.hpp:62
std::vector< T, Allocator< T > > type
Definition: vector.hpp:38
Stores the interdependencies of a pass.
Definition: PassUsage.hpp:55
Definition: set.cpp:44
MIIterator i
virtual PassUsage & get_PassUsage(PassUsage &PU) const
Set the requirements for the pass.
Definition: LoopPass.cpp:34
MIIterator e
alloc::map< const NodeType *, const NodeType * >::type EdgeMapTy
Calculate the Loop Tree.
alloc::map< const NodeType *, int >::type IndexMapTy
alloc::vector< const NodeType * >::type NodeMapTy
NodeType * get_header() const
Definition: LoopBase.hpp:56
bool operator()(const LoopBase< NodeType > *a, const LoopBase< NodeType > *b)
alloc::map< const NodeType *, NodeListTy >::type NodeListMapTy
virtual T set_union(T r, T s)
union the set that contains r with the set that contains s
Definition: UnionFind.hpp:91
LoopTreeGraph * parent