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  static char ID;
86  LoopPassBase() : Pass() {}
87  virtual bool run(JITData &JD);
88  virtual PassUsage& get_PassUsage(PassUsage &PU) const;
89 };
90 
91 template<class NodeType>
93 private:
95 public:
98  NodeType *a_i = a->get_header();
99  NodeType *b_i = b->get_header();
100  if (dfs[a_i] == dfs[b_i]) {
101  a_i = a->get_exit();
102  b_i = b->get_exit();
103  }
104  return dfs[a_i] < dfs[b_i];
105  }
106 };
107 
108 template <class _T>
109 inline bool LoopPassBase<_T>::run(JITData &JD) {
110  DFSTraversal<NodeType> dfs(get_init_node(JD));
111  int size = dfs.size();
112 
113  alloc::vector<alloc::set<int>::type >::type backedges(size);
114  alloc::vector<alloc::set<int>::type >::type forwardedges(size);
115  alloc::vector<alloc::set<int>::type >::type crossedges(size);
116  alloc::vector<alloc::set<int>::type >::type treeedges(size);
117  alloc::vector<int>::type highpt(size,-1);
118 
119  int end = -1;
120 
121  UnionFindImpl<int> unionfind(end);
122 
123  // store the loop for each bb
124  typename alloc::vector<LoopBase<NodeType>*>::type index_to_loop(size);
125 
126 
127  // initialization
128  for (typename DFSTraversal<NodeType>::iterator i = dfs.begin(), e = dfs.end();
129  i != e ; ++i) {
130  int v = i.get_index();
131 
132  unionfind.make_set(v);
133  // get successors
134  typename DFSTraversal<NodeType>::iterator_list successors;
135  i.get_successors(successors);
136 
137  for (typename DFSTraversal<NodeType>::iterator_list::iterator ii = successors.begin(),
138  ee = successors.end(); ii != ee ; ++ii) {
139  int w = (*ii).get_index();
140  // edge v -> w
141 
142  if ((*ii).get_parent() != i) {
143  if (dfs.is_ancestor(v,w)) {
144  // forward edge
145  forwardedges[w].insert(v);
146  } else if (dfs.is_decendant(v,w)) {
147  // backward edge
148  backedges[w].insert(v);
149  } else {
150  // cross edge
151  crossedges[w].insert(v);
152  }
153  } else {
154  // tree edge
155  treeedges[w].insert(v);
156  }
157  }
158  }
159 
160 
161  #if 0
162  for (int w = 0; w < size ; ++w ) {
163  alloc::set<int>::type set = treeedges[w];
164  // print treeedge
165  for(alloc::set<int>::type::iterator i = set.begin(), e = set.end(); i != e ; ++i) {
166  int v = *i;
167  //LOG2("treeedge: " << setw(3) << v << " -> " << setw(3) << w << nl);
168  }
169  // print backedge
170  set = backedges[w];
171  for(alloc::set<int>::type::iterator i = set.begin(), e = set.end(); i != e ; ++i) {
172  int v = *i;
173  //LOG2("backedge: " << setw(3) << v << " -> " << setw(3) << w << nl);
174  }
175  // print forwardedge
176  set = forwardedges[w];
177  for(alloc::set<int>::type::iterator i = set.begin(), e = set.end(); i != e ; ++i) {
178  int v = *i;
179  //LOG2("forwardedge: " << setw(3) << v << " -> " << setw(3) << w << nl);
180  }
181  // print crossedge
182  set = crossedges[w];
183  for(alloc::set<int>::type::iterator i = set.begin(), e = set.end(); i != e ; ++i) {
184  int v = *i;
185  //LOG2("crossedge: " << setw(3) << v << " -> " << setw(3) << w << nl);
186  }
187  }
188  #endif
189 
192  for (typename DFSTraversal<NodeType>::reverse_iterator i = dfs.rbegin(), e = dfs.rend();
193  i != e ; --i) {
194  int w = i.get_index();
195  //LOG2("w=" << w << nl);
196 
197  P.clear();
198  Q.clear();
199 
200  // get incoming backedges
201  alloc::set<int>::type &backedges_w = backedges[w];
202  for(alloc::set<int>::type::iterator i = backedges_w.begin(), e = backedges_w.end();
203  i != e; ++i) {
204  int v = *i;
205  int v_r = unionfind.find(v);
206  assert(v_r != end && "Element not found!");
207  P.insert(v_r);
208  Q.insert(v_r);
209 
210  // create a new loop
211  LoopBase<NodeType> *loop = this->add_loop(dfs[w],dfs[v]);
212 
213  // set loop
214  if(!index_to_loop[v]) {
215  index_to_loop[v] = loop;
216  }
217  if (index_to_loop[w]) {
218  LoopBase<NodeType> *inner_loop = index_to_loop[w];
219  if(inner_loop != loop) {
220  loop->add_inner_loop(inner_loop);
221  }
222  }
223 
224  //LOG2("Q=P= ");
225  //DEBUG2(print_container(dbg(), Q.begin(),Q.end()));
226  //LOG2(nl);
227 
228  // Q contains the sources of the backedges to w.
229  // It must be order from smallest to largest preorder source to
230  // guarantee strict inner to outer ordering.
231  while (!Q.empty()) {
232  int x;
233  // simulate pop_front
234  { // new scope
235  alloc::set<int>::type::iterator x_it = Q.begin();
236  x = *x_it;
237  Q.erase(x_it);
238  }
239  //LOG2("x=" << x << nl);
240 
241  // is loop header?
242  if (backedges[x].size() != 0) {
243  LoopBase<NodeType> *inner_loop = index_to_loop[x];
244  assert(inner_loop);
245  if(inner_loop != loop) {
246  loop->add_inner_loop(inner_loop);
247  }
248  }
249 
250  alloc::set<int>::type incoming;
251  // collect incoming edges
252  { // new scope
253  alloc::set<int>::type ref1 = forwardedges[x];
254  incoming.insert(ref1.begin(), ref1.end());
255  alloc::set<int>::type ref2 = treeedges[x];
256  incoming.insert(ref2.begin(), ref2.end());
257  alloc::set<int>::type ref3 = crossedges[x];
258  incoming.insert(ref3.begin(), ref3.end());
259  }
260  for(alloc::set<int>::type::iterator i = incoming.begin(), e = incoming.end();
261  i != e; ++i) {
262  int y = *i;
263  //LOG2("y=" << y << nl);
264  int y_r = unionfind.find(y);
265  assert(y_r != end);
266  //LOG2("y_r=" << y_r << nl);
267 
268  //LOG("ND(w)=" << dfs.num_decendants(w) << nl);
269  // test for reducibility
270  // TODO <= vs <
271  // if ( (w > y_r) || ( (w + dfs.num_decendants(w)) <= y_r) ) {
272  if ( (w > y_r) || ( (w + dfs.num_decendants(w)) < y_r) ) {
273  assert(0 && "Graph is irreduciable. Can not yet deal with it.");
274  }
275 
276  // add y_r if appropriate
277  if ( P.find(y_r) == P.end() and y_r != w) {
278  P.insert(y_r);
279  Q.insert(y_r);
280  }
281 
282  // set highpt
283  if (highpt[y_r] == -1) {
284  highpt[y_r] = w;
285  }
286 
287  // set loop
288  if (!index_to_loop[y_r]) {
289  index_to_loop[y_r] = loop;
290  }
291  }
292  }
293  }
294 
295  // now P = P(w) in the current graph
296  for(alloc::set<int>::type::iterator i = P.begin(), e = P.end();
297  i != e; ++i) {
298  int x = *i;
299  unionfind.set_union(x,w);
300  }
301  // duplicate edges?
302 
303  }
304  for (int w = 0; w < size ; ++w ) {
305  //LOG2("highpt[" << w << "]=" << highpt[w] << nl);
306  }
307  for (int w = 0; w < size ; ++w ) {
308  LoopBase<NodeType> *loop = index_to_loop[w];
309  if (!loop) {
310  //LOG2("loop(" << dfs[w] << ") not in a loop" << nl);
311  continue;
312  }
313  this->set_loop(dfs[w],loop);
314  //LOG2("loop(header = " << dfs[w] << ") = " << loop << nl);
315  }
316 
317  // sort from outermost to innermost loop
318  LoopComparator<NodeType> compare_loop(dfs);
319  std::sort(LoopTreeBase<NodeType>::begin(), LoopTreeBase<NodeType>::end(), compare_loop);
320 
321  // add NodeType to loops
324  i != e; ++i) {
326  //LOG("Loop: " << loop << nl);
328  if (parent) {
329  //LOG("parent: " << parent << nl);
330  } else {
332  //LOG("parent: " << "toplevel" << nl);
333  }
334  // add to loop headers
336  }
337  return true;
338 }
339 
340 } // end namespace compiler2
341 } // end namespace jit
342 } // end namespace cacao
343 
344 #endif /* _JIT_COMPILER2_LOOPPASSBASE */
345 
346 
347 /*
348  * These are local overrides for various environment variables in Emacs.
349  * Please do not remove this and leave it at the end of the file, where
350  * Emacs will automagically detect them.
351  * ---------------------------------------------------------------------
352  * Local variables:
353  * mode: c++
354  * indent-tabs-mode: t
355  * c-basic-offset: 4
356  * tab-width: 4
357  * End:
358  * vim:noexpandtab:sw=4:ts=4:
359  */
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:48
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