CACAO
loop.cpp
Go to the documentation of this file.
1 /* src/vm/jit/loop/loop.cpp
2 
3  Copyright (C) 1996-2012
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 #include <sstream>
26 #include <algorithm>
27 #include <queue>
28 
29 #include "loop.hpp"
30 #include "dominator.hpp"
31 #include "analyze.hpp"
32 #include "duplicate.hpp"
33 #include "toolbox/logging.hpp"
34 
35 #define INDENT 2
36 
37 namespace
38 {
39  void printBasicBlocks(jitdata* jd);
40  void printDominatorTree(basicblock* block, int level);
41  void printLoopTree(LoopContainer* loop, int level);
42 
43  void findLoopBackEdges(jitdata* jd);
44  void findLoops(jitdata* jd);
45  void reverseDepthFirstTraversal(basicblock* next, LoopContainer* loop);
46  void mergeLoops(jitdata* jd);
47  void buildLoopTree(jitdata* jd);
48  void storeLoopsInHeaders(jitdata* jd);
49  void computeLoopDepth(LoopContainer* loop, s4 depth);
50  void sortLoopsInBasicblocks(jitdata* jd);
51 
52 
53  bool compareLoopHeaders(const LoopContainer* a, const LoopContainer* b)
54  {
55  return a->header < b->header;
56  }
57 
58 
59  void printBasicBlocks(jitdata* jd)
60  {
61  /*
62  std::stringstream s;
63  s << "Variables: " << jd->varcount;
64  log_text(s.str().c_str());
65  */
66 
67  // print basic block graph
68  log_text("----- Basic Blocks -----");
69  for (basicblock* bb = jd->basicblocks; bb != 0; bb = bb->next)
70  {
71  std::stringstream str;
72  str << bb->nr;
73 
74  if (bb->type == basicblock::TYPE_EXH)
75  str << "*";
76  else
77  str << " ";
78  if (bb->ld->loop)
79  str << "H";
80  else
81  str << " ";
82  if (bb->ld->leaf)
83  str << "L";
84  else
85  str << " ";
86 
87  str << " --> ";
88  for (s4 i = 0; i < bb->successorcount; i++)
89  {
90  str << bb->successors[i]->nr << " ";
91  }
92 
93  log_text(str.str().c_str());
94  }
95 
96  // print immediate dominators
97  log_text("------ Dominators ------");
98  for (basicblock* bb = jd->basicblocks; bb != 0; bb = bb->next)
99  {
100  std::stringstream str;
101  str << bb->nr << " --> ";
102  if (bb->ld->dom)
103  str << bb->ld->dom->nr;
104  else
105  str << "X";
106 
107  // print variable assignments
108  //str << " " << bb->ld->writtenVariables;
109 
110  log_text(str.str().c_str());
111  }
112 
113  // print dominator tree
114  log_text("------ Dominator Tree ------");
115  printDominatorTree(jd->ld->root, 0);
116 
117  // print loops
118  log_text("------ Loops ------");
119  for (size_t i = 0; i < jd->ld->loops.size(); i++)
120  {
121  LoopContainer* loop = jd->ld->loops[i];
122  std::stringstream str;
123  str << loop->header->nr;
124  for (size_t j = 0; j < loop->nodes.size(); j++)
125  {
126  str << " " << loop->nodes[j]->nr;
127  }
128 
129  // print variable assignments
130  str << " W:" << loop->writtenVariables;
131 
132  // print invariant variables
133  str << " I:" << loop->invariantVariables;
134 
135  // print counter
136  if (loop->hasCounterVariable)
137  str << " counter " << loop->counterVariable << ':' << loop->counterInterval << ',' << loop->counterIncrement;
138 
139  log_text(str.str().c_str());
140  }
141 
142  // print loop tree
143  log_text("------ Loop Tree ------");
144  printLoopTree(jd->ld->rootLoop, 0);
145 
146  log_text("------------------------");
147  }
148 
149  void printDominatorTree(basicblock* block, int level)
150  {
151  std::stringstream str;
152 
153  // print indentation
154  for (int i = 0; i < level; i++)
155  {
156  str << "|";
157  for (int j = 0; j < INDENT - 1; j++)
158  {
159  str << " ";
160  }
161  }
162 
163  // print root
164  str << block->nr;
165  log_text(str.str().c_str());
166 
167  // print children
168  for (size_t i = 0; i < block->ld->children.size(); i++)
169  {
170  printDominatorTree(block->ld->children[i], level + 1);
171  }
172  }
173 
174  void printLoopTree(LoopContainer* loop, int level)
175  {
176  std::stringstream str;
177 
178  // print indentation
179  for (int i = 0; i < level; i++)
180  {
181  str << "|";
182  for (int j = 0; j < INDENT - 1; j++)
183  {
184  str << " ";
185  }
186  }
187 
188  // print root
189  if (loop->header)
190  str << loop->header->nr;
191  else
192  str << "R"; // pseudo root loop
193  log_text(str.str().c_str());
194 
195  // print children
196  for (size_t i = 0; i < loop->children.size(); i++)
197  {
198  printLoopTree(loop->children[i], level + 1);
199  }
200  }
201 
202  void findLoopBackEdges(jitdata* jd)
203  {
204  // Iterate over depthBackEdges and filter those out which are also loopBackEdges.
205  for (std::vector<Edge>::const_iterator edge = jd->ld->depthBackEdges.begin(); edge != jd->ld->depthBackEdges.end(); ++edge)
206  {
207  // Check if edge->to dominates edge->from.
208  // The case edge->to == edge->from is also considered.
209  basicblock* ancestor = edge->from;
210  while (ancestor)
211  {
212  if (ancestor == edge->to)
213  {
214  jd->ld->loopBackEdges.push_back(*edge);
215  break;
216  }
217 
218  // search the dominator tree bottom-up
219  ancestor = ancestor->ld->dom;
220  }
221  }
222  }
223 
224  /**
225  * For every loopBackEdge there is a loop.
226  * This function finds all basicblocks which belong to that loop.
227  */
228  void findLoops(jitdata* jd)
229  {
230  for (std::vector<Edge>::const_iterator edge = jd->ld->loopBackEdges.begin(); edge != jd->ld->loopBackEdges.end(); ++edge)
231  {
232  basicblock* head = edge->to;
233  basicblock* foot = edge->from;
234 
235  LoopContainer* loop = new LoopContainer;
236  //loop->invariantIntervals = IntervalMap(jd->varcount);
237  //loop->headerIntervals = IntervalMap(jd->varcount);
238  jd->ld->loops.push_back(loop);
239 
240  loop->header = head;
241  loop->footers.push_back(foot);
242 
243  // Save loop in basicblock.
244  head->ld->loops.insert(loop);
245 
246  // find all basicblocks contained in this loop
247  reverseDepthFirstTraversal(foot, loop);
248  }
249  }
250 
251  void reverseDepthFirstTraversal(basicblock* next, LoopContainer* loop)
252  {
253  if (next->ld->visited == loop) // already visited
254  return;
255 
256  if (next == loop->header) // Stop the traversal at the header node.
257  return;
258 
259  loop->nodes.push_back(next);
260 
261  // Save loop in basicblock.
262  next->ld->loops.insert(loop);
263 
264  // Mark basicblock to prevent it from being visited again.
265  next->ld->visited = loop;
266 
267  for (s4 i = 0; i < next->predecessorcount; i++)
268  {
269  reverseDepthFirstTraversal(next->predecessors[i], loop);
270  }
271  }
272 
273  /**
274  * There can be loop back edges having the same header node.
275  * This function merges those loops together.
276  */
277  void mergeLoops(jitdata* jd)
278  {
279  // Sort the loops such that two loops having the same header are one after the other.
280  std::sort(jd->ld->loops.begin(), jd->ld->loops.end(), &compareLoopHeaders);
281  //std::sort(jd->ld->loops.begin(), jd->ld->loops.end(), LoopHeaderCompare());
282 
283  for (size_t i = 1; i < jd->ld->loops.size(); i++)
284  {
285  LoopContainer* first = jd->ld->loops[i - 1];
286  LoopContainer* second = jd->ld->loops[i];
287 
288  if (first->header == second->header)
289  {
290  // Copy footer of second loop into first loop
291  assert(second->footers.size() == 1);
292  first->footers.push_back(second->footers.front());
293 
294  // merge loops
295  for (std::vector<basicblock*>::const_iterator it2 = second->nodes.begin(); it2 != second->nodes.end(); ++it2)
296  {
297  basicblock* node = *it2;
298 
299  // Put node into the first loop if it does not already contain it.
300  if (find(first->nodes.begin(), first->nodes.end(), node) == first->nodes.end())
301  {
302  first->nodes.push_back(node);
303  }
304 
305  // Remove second loop from node and save first loop in it.
306  node->ld->loops.erase(second);
307  node->ld->loops.insert(first);
308  }
309 
310  // Remove second loop from header too.
311  first->header->ld->loops.erase(second);
312 
313  // delete second loop
314  delete second;
315  jd->ld->loops.erase(jd->ld->loops.begin() + i);
316  i--;
317  }
318  }
319  }
320 
321  /**
322  * Builds the loop hierarchy.
323  */
324  void buildLoopTree(jitdata* jd)
325  {
326  std::queue<LoopContainer*> successors;
327 
328  // Create a pseudo loop that contains all other loops.
329  jd->ld->rootLoop = new LoopContainer;
330  for (std::vector<LoopContainer*>::const_iterator it = jd->ld->loops.begin(); it != jd->ld->loops.end(); ++it)
331  {
332  (*it)->parent = jd->ld->rootLoop;
333  successors.push(*it);
334  }
335 
336  // Do a breadth-first traversal through the loop nodes.
337  while (!successors.empty())
338  {
339  LoopContainer* current = successors.front();
340  successors.pop();
341 
342  // find all successors
343  for (std::vector<LoopContainer*>::const_iterator it = jd->ld->loops.begin(); it != jd->ld->loops.end(); ++it)
344  {
345  LoopContainer* candidate = *it;
346 
347  // candidate is a sub loop of current iff its header is contained in current.
348  for (std::vector<basicblock*>::const_iterator nodeIt = current->nodes.begin(); nodeIt != current->nodes.end(); ++nodeIt)
349  {
350  // The headers of two different loops are always different.
351  // So it is not necessary to compare the headers.
352 
353  if (candidate->header == *nodeIt)
354  {
355  // Remember the parent of the sub loop.
356  // We overwrite a previously written value.
357  // Because we are doing a breadth-first traversal and we overwrite a previously written value,
358  // we will eventually get the longest paths from the root to the leaves.
359  candidate->parent = current;
360 
361  successors.push(candidate);
362  break;
363  }
364  }
365  }
366  }
367 
368  // Finally build the tree so that it can be traversed top-down.
369  for (std::vector<LoopContainer*>::const_iterator it = jd->ld->loops.begin(); it != jd->ld->loops.end(); ++it)
370  {
371  LoopContainer* loop = *it;
372  if (loop->parent)
373  loop->parent->children.push_back(loop);
374  }
375  }
376 
377  void storeLoopsInHeaders(jitdata* jd)
378  {
379  for (std::vector<LoopContainer*>::const_iterator it = jd->ld->loops.begin(); it != jd->ld->loops.end(); ++it)
380  {
381  (*it)->header->ld->loop = (*it);
382  }
383  }
384 
385  void computeLoopDepth(LoopContainer* loop, s4 depth)
386  {
387  loop->depth = depth;
388  for (std::vector<LoopContainer*>::iterator childIt = loop->children.begin(); childIt != loop->children.end(); ++childIt)
389  {
390  computeLoopDepth(*childIt, depth + 1);
391  }
392  }
393 
394  void sortLoopsInBasicblocks(jitdata* jd)
395  {
396  for (basicblock* block = jd->basicblocks; block != 0; block = block->next)
397  {
398  block->ld->loops.sort();
399  }
400  }
401 }
402 
403 
405 {
406  //log_message_method("removeArrayBoundChecks: ", jd->m);
407 
408  createRoot(jd);
410  buildDominatorTree(jd);
411 
412  findLoopBackEdges(jd);
413  findLoops(jd);
414  mergeLoops(jd);
415  buildLoopTree(jd);
416  storeLoopsInHeaders(jd);
417  computeLoopDepth(jd->ld->rootLoop, 0);
418  sortLoopsInBasicblocks(jd);
419 
420  analyzeLoops(jd);
421  findLeaves(jd);
422 
424 
425  //printBasicBlocks(jd);
426 
427  if (jd->exceptiontablelength == 0) // Currently only methods without try blocks are allowed.
428  {
429  if (findFreeVariable(jd))
430  {
433  }
434  }
435  else
436  {
437  //log_text("Exception handler found.");
438  }
439 }
440 
441 /*
442  * These are local overrides for various environment variables in Emacs.
443  * Please do not remove this and leave it at the end of the file, where
444  * Emacs will automagically detect them.
445  * ---------------------------------------------------------------------
446  * Local variables:
447  * mode: c++
448  * indent-tabs-mode: t
449  * c-basic-offset: 4
450  * tab-width: 4
451  * End:
452  * vim:noexpandtab:sw=4:ts=4:
453  */
454 
s4 exceptiontablelength
Definition: jit.hpp:167
VariableSet writtenVariables
void removePartiallyRedundantChecks(jitdata *jd)
Definition: duplicate.cpp:930
Represents a single loop.
basicblock * basicblocks
Definition: jit.hpp:141
Definition: jit.hpp:126
basicblock * next
Definition: jit.hpp:337
MachineLoop * loop
VariableSet invariantVariables
void printBasicBlocks(jitdata *)
void findLeaves(jitdata *jd)
Marks all basicblocks which are leaves.
Definition: analyze.cpp:963
void analyzeLoops(jitdata *jd)
Analyzes all loops and for every loop it finds.
Definition: analyze.cpp:929
void createRoot(jitdata *jd)
Definition: dominator.cpp:39
MachineBasicBlock * current
jlong jlong jlong jlong jint depth
Definition: jvmti.h:497
BeginInst *& block
LoopContainer * parent
basicblock ** predecessors
Definition: jit.hpp:332
s4 predecessorcount
Definition: jit.hpp:330
void buildDominatorTree(jitdata *jd)
Uses the immediate dominators to build a dominator tree which can be traversed from the root to the l...
Definition: dominator.cpp:221
MIIterator i
#define INDENT
Definition: loop.cpp:35
int32_t s4
Definition: types.hpp:45
std::vector< basicblock * > footers
void removeFullyRedundantChecks(jitdata *jd)
Removes all array bound checks that are fully redundant.
Definition: analyze.cpp:977
bool findFreeVariable(jitdata *jd)
Definition: duplicate.cpp:914
Interval counterInterval
void removeArrayBoundChecks(jitdata *jd)
Definition: loop.cpp:404
std::vector< basicblock * > nodes
struct LoopContainer LoopContainer
Definition: loop.hpp:31
s4 nr
Definition: jit.hpp:312
static java_object_t * next
Definition: copy.c:43
std::vector< LoopContainer * > children
#define str(x)
#define log_text(s)
Definition: logging.hpp:170
void groupArrayBoundsChecks(jitdata *jd)
Definition: duplicate.cpp:938
void calculateDominators(jitdata *jd)
Calculates the immediate dominators of all basicblocks.
Definition: dominator.cpp:73
basicblock * header