CACAO
GraphHelper.hpp
Go to the documentation of this file.
1 /* src/vm/jit/compiler2/GraphHelper.hpp - GraphHelper
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_GRAPHHELPER
26 #define _JIT_COMPILER2_GRAPHHELPER
27 
28 
32 #include <iterator>
33 
35 #include "toolbox/logging.hpp"
36 
37 #define DEBUG_NAME "compiler2/GraphHelper"
38 
39 namespace cacao {
40 namespace jit {
41 namespace compiler2 {
42 
43 
44 /**
45  * This helper class creates traversal for a graph.
46  *
47  * The only information required from the graph is the successor relation successor()
48  * and number of vertices num_nodes.
49  */
50 template <class _NodeTy>
51 class DFSTraversal {
52 private:
57 
61 
67 
68  int n;
69  int _size;
70 
71  NodeListTy& successor(_NodeTy *v, NodeListTy &list);
72  int num_nodes(_NodeTy *v) const;
73 
74  int dfs(_NodeTy * v);
75 
76 public:
77  class iterator;
79 
80  explicit DFSTraversal(_NodeTy *entry) {
81  n = -1;
82  _size = num_nodes(entry);
83  LOG("num nodes" << _size << nl);
84  vertex.resize(_size, NULL);
85  // index.resize(_size, -1); auto initialzied
86  parent.resize(_size, -1);
87  succ.resize(_size);
88  number_decendants.clear();
89  number_decendants.resize(_size,0);
90  LOG("vertex size " << vertex.size() << nl);
91 
92  dfs(entry);
93 
94 #ifdef ENABLE_LOGGING
95  LOG("index"<<nl);
96  for(int i = 0, e = _size; i != e ; ++i) {
97  LOG(" node " << (long) vertex[i] << " parent " << parent[i] << nl);
98  }
99 
100  LOG("iterator"<<nl);
101  for(iterator i = begin(), e = end(); i != e; ++i) {
102  LOG(" node " << (long) *i << " parent " << i.get_parent().get_index() << nl);
103  }
104 #endif
105  }
106 
107  int size() const {
108  return _size;
109  }
110 
111  _NodeTy* operator[](unsigned i) const {
112  return vertex[i];
113  }
114 
115  int operator[](_NodeTy *v) const {
116  typename IndexMapTy::const_iterator i = index.find(v);
117  if (i == index.end())
118  return -1;
119  return i->second;
120  }
121 
122  int num_decendants(int v) const {
123  assert(v < _size);
124  return number_decendants[v];
125  }
126 
127  #if 0
128  bool is_ancestor(const _NodeTy *v, const _NodeTy *w) const {
129  return is_ancestor(index[v],index[w]);
130  }
131  #endif
132  inline bool is_ancestor(int v, int w) const {
133  assert(w < _size);
134  for(;w >= 0; w = parent[w]) {
135  if (v == w)
136  return true;
137 
138  }
139  return false;
140  }
141  #if 0
142  bool is_decendant(const _NodeTy *w, const _NodeTy *v) const {
143  return is_ancestor(index[v],index[w]);
144  }
145  #endif
146  bool is_decendant(int w, int v) const {
147  return is_ancestor(v,w);
148  }
149 
150  class iterator : public std::iterator<std::input_iterator_tag,_NodeTy*> {
151  private:
152  int index;
154  public:
155  explicit iterator (DFSTraversal *parent) : index(0), parent(parent) {}
156  explicit iterator (DFSTraversal *parent, int index) : index(index), parent(parent){}
157  iterator (const iterator &it) : index(it.index), parent(it.parent){}
158 
159  _NodeTy* operator*() const {
160  if(index >= 0 && index < parent->size())
161  return parent->vertex[index];
162  return NULL;
163  };
165  ++index;
166  if (parent->size() <= index)
167  index = -1;
168  return *this;
169  }
171  iterator tmp(*this);
172  operator++();
173  return tmp;
174  }
176  --index;
177  if (index < 0)
178  index = -1;
179  return *this;
180  }
182  iterator tmp(*this);
183  operator--();
184  return tmp;
185  }
186 
187  /*
188  * If other.parent is not equal to this->parent the
189  * behaviour is undefined. Not checking parent for
190  * performance reasons.
191  */
192  bool operator==(const iterator &other) const {
193  assert(parent == other.parent);
194  return index == other.index;
195  }
196  bool operator!=(const iterator &other) const {
197  assert(parent == other.parent);
198  return index != other.index;
199  }
200  bool operator<(const iterator &other) const {
201  assert(parent == other.parent);
202  return index < other.index;
203  }
204  bool operator>(const iterator &other) const {
205  assert(parent == other.parent);
206  return index > other.index;
207  }
208  bool operator<=(const iterator &other) const {
209  assert(parent == other.parent);
210  return index <= other.index;
211  }
212  bool operator>=(const iterator &other) const {
213  assert(parent == other.parent);
214  return index >= other.index;
215  }
216 
217  int get_index() const {
218  return index;
219  }
220 
222  return iterator(parent,parent->parent[index]);
223  }
224 
226  for(SuccessorListTy::iterator i = parent->succ[index].begin(),
227  e = parent->succ[index].end(); i != e ; ++i) {
228  list.insert(iterator(parent,*i));
229  }
230  return list;
231  }
232  };
233 
234  typedef iterator reverse_iterator;
235 
236  iterator begin() {
237  return iterator(this);
238  }
239 
240  iterator end() {
241  return iterator(this,-1);
242  }
243 
245  return reverse_iterator(this,size()-1);
246  }
247 
249  return reverse_iterator(this,-1);
250  }
251 
253 };
254 
255 template <class _NodeTy>
257 {
258  assert(v);
259  int my_n = ++n;
260  LOG("my_n for " << (long)v << " (" << my_n << ") " << nl);
261  index[v] = my_n;
262  assert(vertex.size() > (unsigned)my_n);
263  vertex[my_n] = v;
264  // TODO this can be done better
265  NodeListTy succ_v;
266  succ_v = successor(v, succ_v);
267  LOG("number of succ for " << (long)v << " (" << my_n << ") " << " = " << succ_v.size() << nl);
268  for(typename alloc::set<_NodeTy *>::type::const_iterator i = succ_v.begin() , e = succ_v.end();
269  i != e; ++i) {
270  _NodeTy *w = *i;
271  SuccessorListTy &succ_list = succ[my_n];
272  if (index.find(w) == index.end()) {
273  int w_n = dfs(w);
274  parent[w_n] = my_n;
275  succ_list.insert(w_n);
276  } else {
277  succ_list.insert(index[w]);
278  }
279  //pred[w].insert(v);
280  }
281  number_decendants[my_n] = n - my_n;
282  return my_n;
283 }
284 
285 // specialization for BeginInst
286 template <>
288 
289 template <>
291 
292 
293 // Tree
294 namespace tree {
295 
296 template <class T>
297 T get_parent(T a);
298 
299 template <class T>
300 T get_root();
301 
302 template <class T>
303 inline T find_least_common_ancestor(T a, T b) {
304  // collect a's ancestors
305  typename alloc::set<T>::type ancestors;
306 
307  for (; !(a == get_root<T>()) ; a = get_parent(a)) {
308  if (a == b)
309  return a;
310  ancestors.insert(a);
311  }
312 
313  typename alloc::set<T>::type::const_iterator e = ancestors.end();
314  for (; !(b == get_root<T>()) ; b = get_parent(b)) {
315  if (ancestors.find(b) != e)
316  return b;
317  }
318  return get_root<T>();
319 }
320 } // end namespace tree
321 
322 } // end namespace compiler2
323 } // end namespace jit
324 } // end namespace cacao
325 
326 #undef DEBUG_NAME
327 
328 #endif /* _JIT_COMPILER2_GRAPHHELPER */
329 
330 
331 /*
332  * These are local overrides for various environment variables in Emacs.
333  * Please do not remove this and leave it at the end of the file, where
334  * Emacs will automagically detect them.
335  * ---------------------------------------------------------------------
336  * Local variables:
337  * mode: c++
338  * indent-tabs-mode: t
339  * c-basic-offset: 4
340  * tab-width: 4
341  * End:
342  * vim:noexpandtab:sw=4:ts=4:
343  */
alloc::vector< int >::type DecendantMapTy
Definition: GraphHelper.hpp:56
std::set< Key, Compare, Allocator< Key > > type
Definition: set.hpp:38
std::size_t index
bool is_decendant(int w, int v) const
int operator[](_NodeTy *v) const
bool operator==(const iterator &other) const
T find_least_common_ancestor(T a, T b)
This Instruction mark the start of a basic block.
This helper class creates traversal for a graph.
Definition: GraphHelper.hpp:51
const DFSTraversal< BeginInst > dfs
iterator(DFSTraversal *parent, int index)
bool operator<(const iterator &other) const
alloc::set< int >::type SuccessorListTy
Definition: GraphHelper.hpp:59
bool is_ancestor(int v, int w) const
bool operator<=(const iterator &other) const
bool operator!=(const iterator &other) const
alloc::vector< _NodeTy * >::type NodeMapTy
Definition: GraphHelper.hpp:53
Instruction::InstID tmp[]
Definition: Matcher.cpp:55
std::vector< T, Allocator< T > > type
Definition: vector.hpp:38
alloc::vector< int >::type ParentMapTy
Definition: GraphHelper.hpp:55
alloc::set< iterator >::type iterator_list
Definition: GraphHelper.hpp:77
MIIterator i
alloc::set< _NodeTy * >::type NodeListTy
Definition: GraphHelper.hpp:58
alloc::vector< SuccessorListTy >::type SuccessorListMapTy
Definition: GraphHelper.hpp:60
MIIterator e
#define LOG(STMT)
Analogous to DEBUG.
Definition: logging.hpp:91
_NodeTy * operator[](unsigned i) const
bool operator>(const iterator &other) const
bool operator>=(const iterator &other) const
alloc::map< _NodeTy *, int >::type IndexMapTy
Definition: GraphHelper.hpp:54
iterator_list & get_successors(iterator_list &list) const
NodeListTy & successor(_NodeTy *v, NodeListTy &list)
int num_nodes(_NodeTy *v) const
Nl nl
Definition: OStream.cpp:56
LoopTreeGraph * parent