CACAO
analyze.cpp
Go to the documentation of this file.
1 /* src/vm/jit/loop/analyze.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 "analyze.hpp"
26 #include "Interval.hpp"
27 #include "toolbox/logging.hpp"
28 #include "vm/jit/ir/icmd.hpp"
30 
31 #include <sstream>
32 
33 namespace
34 {
35  void analyzeLoops(jitdata* jd);
36  void analyzeBasicblockInLoop(jitdata* jd, basicblock* block, LoopContainer* loop);
37  void analyzeFooter(jitdata* jd, LoopContainer* loop);
38  void findLeaves(jitdata* jd);
39 
40  bool isRegularPredecessor(jitdata* jd, basicblock* node, basicblock* pred);
41  LoopContainer* getLoopContainer(jitdata* jd, basicblock* header);
42  IntervalMap analyze(jitdata* jd, basicblock* node, basicblock* target);
43 
44  bool isLocalIntVar(jitdata* jd, s4 varIndex);
45  bool isLocalIntVar(jitdata* jd, s4 var0, s4 var1);
46  bool isLocalVar(jitdata* jd, s4 varIndex);
47 
48  /**
49  * Analyzes a single basicblock that belongs to a loop and finds
50  *
51  * -) all written variables,
52  * -) candidates for the set of invariant integer variables,
53  * -) candidates for the set of invariant array variables.
54  */
55  void analyzeBasicblockInLoop(jitdata* jd, basicblock* block, LoopContainer* loop)
56  {
57  for (instruction* instr = block->iinstr; instr != block->iinstr + block->icount; instr++)
58  {
59  switch (instr->opc)
60  {
61  case ICMD_COPY:
62  case ICMD_MOVE:
63  case ICMD_ILOAD:
64  case ICMD_LLOAD:
65  case ICMD_FLOAD:
66  case ICMD_DLOAD:
67  case ICMD_ALOAD:
68  case ICMD_ISTORE:
69  case ICMD_LSTORE:
70  case ICMD_FSTORE:
71  case ICMD_DSTORE:
72  case ICMD_ASTORE:
73 
74  // Save candidates for the set of invariant integer variables.
75  if (isLocalIntVar(jd, instr->s1.varindex))
76  loop->invariantVariables.insert(instr->s1.varindex);
77 
78  // The dst-variable is changed only if src != dst.
79  if (instr->s1.varindex != instr->dst.varindex)
80  loop->writtenVariables.insert(instr->dst.varindex);
81  break;
82 
83  case ICMD_IALOAD:
84  case ICMD_LALOAD:
85  case ICMD_FALOAD:
86  case ICMD_DALOAD:
87  case ICMD_AALOAD:
88  case ICMD_BALOAD:
89  case ICMD_CALOAD:
90  case ICMD_SALOAD:
91 
92  case ICMD_IASTORE:
93  case ICMD_LASTORE:
94  case ICMD_FASTORE:
95  case ICMD_DASTORE:
96  case ICMD_AASTORE:
97  case ICMD_BASTORE:
98  case ICMD_CASTORE:
99  case ICMD_SASTORE:
100 
101  case ICMD_IASTORECONST:
102  case ICMD_LASTORECONST:
103  case ICMD_FASTORECONST:
104  case ICMD_DASTORECONST:
105  case ICMD_AASTORECONST:
106  case ICMD_BASTORECONST:
107  case ICMD_CASTORECONST:
108  case ICMD_SASTORECONST:
109 
110  // Save candidates for the set of invariant array variables.
111  if (isLocalVar(jd, instr->s1.varindex))
112  loop->invariantArrays.insert(instr->s1.varindex);
113 
114  // fall through
115 
116  default:
117 
118  if (instruction_has_dst(instr))
119  {
120  // Store changed variable.
121  loop->writtenVariables.insert(instr->dst.varindex);
122  }
123  }
124  }
125  }
126 
127  /**
128  * Analyzes the footer of the specified loop (Only the first footer is considered) and
129  * finds all counter variables.
130  *
131  * It is important that analyzeBasicblockInLoop has been called for every basicblock
132  * in this loop except the footer.
133  */
134  void analyzeFooter(jitdata* jd, LoopContainer* loop)
135  {
136  assert(!loop->footers.empty());
137 
138  basicblock* footer = loop->footers.front();
139 
140  enum { SEEKING_JUMP, JUMP_FOUND, INC_FOUND } state = SEEKING_JUMP;
141 
142  for (s4 i = footer->icount - 1; i >= 0; i--)
143  {
144  instruction* instr = &footer->iinstr[i];
145 
146  switch (state)
147  {
148  case SEEKING_JUMP:
149 
150  // Skip NOPs at the end of the basicblock until the jump instruction is found.
151  if (icmd_table[instr->opc].controlflow != CF_NORMAL)
152  state = JUMP_FOUND;
153  break;
154 
155  case JUMP_FOUND:
156 
157  if (instr->opc == ICMD_IINC && // For simplicity only IINC-instructions are considered.
158  isLocalIntVar(jd, instr->dst.varindex) &&
159  !loop->writtenVariables.contains(instr->dst.varindex)) // A counter variable is written only once in the whole loop.
160  {
161  loop->hasCounterVariable = true;
162  loop->counterVariable = instr->dst.varindex;
163  loop->counterIncrement = instr->sx.val.i;
164  state = INC_FOUND;
165  }
166  else
167  {
168  return;
169  }
170  break;
171 
172  case INC_FOUND:
173 
174  switch (instr->opc)
175  {
176  case ICMD_COPY:
177  case ICMD_MOVE:
178  case ICMD_ILOAD:
179  case ICMD_LLOAD:
180  case ICMD_FLOAD:
181  case ICMD_DLOAD:
182  case ICMD_ALOAD:
183  case ICMD_ISTORE:
184  case ICMD_LSTORE:
185  case ICMD_FSTORE:
186  case ICMD_DSTORE:
187  case ICMD_ASTORE:
188  // If src == dst, the counter is definitely not changed.
189  if (instr->s1.varindex == instr->dst.varindex)
190  break;
191  // fall through
192  default:
193  // The counter variable must not be written to in all other instructions.
194  if (instruction_has_dst(instr) && instr->dst.varindex == loop->counterVariable)
195  {
196  loop->hasCounterVariable = false;
197  return;
198  }
199  }
200  break;
201  }
202  }
203  }
204 
205  /**
206  * Returns true if there is no back-edge from pred to node, otherwise false.
207  */
208  inline bool isRegularPredecessor(jitdata* jd, basicblock* node, basicblock* pred)
209  {
210  for (std::vector<Edge>::iterator it = jd->ld->loopBackEdges.begin(); it != jd->ld->loopBackEdges.end(); ++it)
211  {
212  if (it->from == pred && it->to == node)
213  return false;
214  }
215  return true;
216  }
217 
218  /**
219  * Removes all fully redundant array bound checks in node and its predecessors in the CFG.
220  * Returns the interval map for the edge from node to target.
221  */
222  IntervalMap analyze(jitdata* jd, basicblock* node, basicblock* target)
223  {
224  if (node->ld->analyzed)
225  {
226  if (target == node->ld->jumpTarget)
227  return node->ld->targetIntervals;
228  else
229  return node->ld->intervals;
230  }
231 
232  // Prevent this node from being analyzed again.
233  node->ld->analyzed = true;
234 
235  // Define shortcuts.
236  IntervalMap& intervals = node->ld->intervals;
237  IntervalMap& targetIntervals = node->ld->targetIntervals;
238 
239  // Initialize results. That is necessary because analyze can be called recursively.
240  /*targetIntervals = IntervalMap(jd->varcount);
241  intervals = IntervalMap(jd->varcount);*/
242 
243  // If node is a root, the variables (e.g. function arguments) can have any value.
244  // Otherwise we can take the interval maps from the predecessors.
245  if (node->predecessorcount > 0)
246  {
247  // Initialize intervals.
248  if (isRegularPredecessor(jd, node, node->predecessors[0]))
249  intervals = analyze(jd, node->predecessors[0], node);
250 
251  // Combine it with the other intervals.
252  for (s4 i = 1; i < node->predecessorcount; i++)
253  {
254  if (isRegularPredecessor(jd, node, node->predecessors[i]))
255  intervals.unionWith(analyze(jd, node->predecessors[i], node));
256  }
257  }
258 
259  // When a loop is left, we must reset the intervals of the invariant variables.
260  for (s4 i = 0; i < node->predecessorcount; i++)
261  {
262  basicblock* pred = node->predecessors[i];
263  for (LoopList::iterator predLoopIt = pred->ld->loops.begin(); predLoopIt != pred->ld->loops.end(); ++predLoopIt)
264  {
265  LoopContainer* predLoop = *predLoopIt;
266  if (node->ld->loops.find(predLoop) == node->ld->loops.end())
267  {
268  // We left predLoop.
269  // So we must reset the intervals of predLoop's invariant variables.
270  for (VariableSet::iterator it = predLoop->invariantVariables.begin(); it != predLoop->invariantVariables.end(); ++it)
271  {
272  intervals[*it] = predLoop->invariantIntervals[*it];
273  }
274 
275  // Set all intervals referencing an invariant variable to [MIN,MAX].
276  for (size_t j = 0; j < intervals.size(); j++)
277  {
278  // Do not change the interval of an invariant variable.
279  if (predLoop->invariantVariables.contains(j))
280  continue;
281 
282  if (intervals[j].lower().instruction().kind() == NumericInstruction::VARIABLE &&
283  predLoop->invariantVariables.contains(intervals[j].lower().instruction().variable()))
284  {
285  intervals[j] = Interval();
286  }
287  else if (intervals[j].upper().instruction().kind() == NumericInstruction::VARIABLE &&
288  predLoop->invariantVariables.contains(intervals[j].upper().instruction().variable()))
289  {
290  intervals[j] = Interval();
291  }
292  }
293  }
294  }
295  }
296 
297  if (node->ld->loop) // node is a loop header
298  {
299  // Define the interval of the counter variable, not considering a possible overflow.
300  // This interval will be overwritten after the last instruction in this node has been processed.
301  if (node->ld->loop->hasCounterVariable)
302  {
303  if (node->ld->loop->counterIncrement >= 0)
304  node->ld->loop->counterInterval = Interval(intervals[node->ld->loop->counterVariable].lower(), Scalar(Scalar::max()));
305  else
306  node->ld->loop->counterInterval = Interval(Scalar(Scalar::min()), intervals[node->ld->loop->counterVariable].upper());
307  }
308 
309  // If node is the header of a loop L,
310  // set every interval that belongs to a variable which is changed in L to [MIN,MAX].
311  for (VariableSet::iterator it = node->ld->loop->writtenVariables.begin(); it != node->ld->loop->writtenVariables.end(); ++it)
312  {
313  intervals[*it] = Interval();
314  }
315 
316  // Set the interval of every invariant variable x to [x,x] and save old interval.
317  for (VariableSet::iterator it = node->ld->loop->invariantVariables.begin(); it != node->ld->loop->invariantVariables.end(); ++it)
318  {
319  node->ld->loop->invariantIntervals[*it] = intervals[*it];
320  intervals[*it] = Interval(Scalar(NumericInstruction::newVariable(*it)));
321  }
322  }
323 
324  for (instruction* instr = node->iinstr; instr != node->iinstr + node->icount; instr++)
325  {
326  // arguments
327  s4 dst_index = instr->dst.varindex;
328  s4 s1_index = instr->s1.varindex;
329  s4 s2_index = instr->sx.s23.s2.varindex;
330  s4 value = instr->sx.val.i;
331 
332  // Update the variable intervals for this node.
333  // For an unknown instruction, set the corresponding interval to [MIN,MAX].
334  switch (instr->opc)
335  {
336  case ICMD_ICONST:
337  if (isLocalIntVar(jd, dst_index))
338  {
339  intervals[dst_index] = Interval(Scalar(value));
340  }
341  break;
342 
343  case ICMD_COPY:
344  case ICMD_MOVE:
345  case ICMD_ILOAD:
346  case ICMD_ISTORE:
347  if (isLocalIntVar(jd, dst_index))
348  {
349  // The source variable does not have to be local because
350  // the interval of a non-local variable is [MIN,MAX].
351 
352  if (s1_index != dst_index)
353  {
354  // Overwrite dst-interval by s1-interval.
355  intervals[dst_index] = intervals[s1_index];
356  }
357  }
358  break;
359 
360  case ICMD_ARRAYLENGTH:
361  if (isLocalIntVar(jd, dst_index))
362  {
363  // Create interval [s1.length, s1.length]
364  intervals[dst_index] = Interval(Scalar(NumericInstruction::newArrayLength(s1_index)));
365  }
366  break;
367 
368  case ICMD_IINC:
369  case ICMD_IADDCONST:
370  if (isLocalIntVar(jd, dst_index))
371  {
372  Scalar l = intervals[s1_index].lower();
373  Scalar u = intervals[s1_index].upper();
374  Scalar offset(value);
375 
376  if (l.tryAdd(offset) && u.tryAdd(offset))
377  {
378  intervals[dst_index] = Interval(l, u);
379  }
380  else // overflow
381  {
382  intervals[dst_index] = Interval();
383  }
384  }
385  break;
386 
387  case ICMD_ISUBCONST:
388  if (isLocalIntVar(jd, dst_index))
389  {
390  Scalar l = intervals[s1_index].lower();
391  Scalar u = intervals[s1_index].upper();
392  Scalar offset(value);
393 
394  if (l.trySubtract(offset) && u.trySubtract(offset))
395  {
396  intervals[dst_index] = Interval(l, u);
397  }
398  else // overflow
399  {
400  intervals[dst_index] = Interval();
401  }
402  }
403  break;
404 
405  case ICMD_IALOAD:
406  case ICMD_LALOAD:
407  case ICMD_FALOAD:
408  case ICMD_DALOAD:
409  case ICMD_AALOAD:
410  case ICMD_BALOAD:
411  case ICMD_CALOAD:
412  case ICMD_SALOAD:
413 
414  case ICMD_IASTORE:
415  case ICMD_LASTORE:
416  case ICMD_FASTORE:
417  case ICMD_DASTORE:
418  case ICMD_AASTORE:
419  case ICMD_BASTORE:
420  case ICMD_CASTORE:
421  case ICMD_SASTORE:
422 
423  case ICMD_IASTORECONST:
424  case ICMD_LASTORECONST:
425  case ICMD_FASTORECONST:
426  case ICMD_DASTORECONST:
427  case ICMD_AASTORECONST:
428  case ICMD_BASTORECONST:
429  case ICMD_CASTORECONST:
430  case ICMD_SASTORECONST:
431 
432  // Remove array bounds check.
433  if (intervals[s2_index].isWithinBounds(s1_index))
434  instr->flags.bits &= ~INS_FLAG_CHECK;
435  break;
436 
437  case ICMD_IFEQ: // if (S1 == INT_CONST) goto DST
438  {
439  node->ld->jumpTarget = instr->dst.block;
440 
441  Scalar s(value);
442  Interval i(s);
443 
444  // TRUE BRANCH
445  targetIntervals = intervals;
446  targetIntervals[s1_index].intersectWith(i);
447 
448  // FALSE BRANCH
449  intervals[s1_index].tryRemove(s);
450 
451  break;
452  }
453  case ICMD_IFNE: // if (S1 != INT_CONST) goto DST
454  {
455  node->ld->jumpTarget = instr->dst.block;
456 
457  Scalar s(value);
458  Interval i(s);
459 
460  // TRUE BRANCH
461  targetIntervals = intervals;
462  targetIntervals[s1_index].tryRemove(s);
463 
464  // FALSE BRANCH
465  intervals[s1_index].intersectWith(i);
466 
467  break;
468  }
469  case ICMD_IFLT: // if (S1 < INT_CONST) goto DST
470  {
471  node->ld->jumpTarget = instr->dst.block;
472 
473  // TRUE BRANCH
474  {
475  Scalar l(Scalar::min());
476  Scalar u(value);
477 
478  // interval [MIN,value-1]
479  Interval i(l, u);
480  i.tryRemove(u);
481 
482  targetIntervals = intervals;
483  targetIntervals[s1_index].intersectWith(i);
484  }
485 
486  // FALSE BRANCH
487  {
488  Scalar l(value);
489  Scalar u(Scalar::max());
490 
491  // interval [value,MAX].
492  Interval i(l, u);
493 
494  intervals[s1_index].intersectWith(i);
495  }
496 
497  break;
498  }
499  case ICMD_IFLE: // if (S1 <= INT_CONST) goto DST
500  {
501  node->ld->jumpTarget = instr->dst.block;
502 
503  // TRUE BRANCH
504  {
505  Scalar l(Scalar::min());
506  Scalar u(value);
507 
508  // interval [MIN,value]
509  Interval i(l, u);
510 
511  targetIntervals = intervals;
512  targetIntervals[s1_index].intersectWith(i);
513  }
514 
515  // FALSE BRANCH
516  {
517  Scalar l(value);
518  Scalar u(Scalar::max());
519 
520  // interval [value+1,MAX].
521  Interval i(l, u);
522  i.tryRemove(l);
523 
524  intervals[s1_index].intersectWith(i);
525  }
526 
527  break;
528  }
529  case ICMD_IFGT: // if (S1 > INT_CONST) goto DST
530  {
531  node->ld->jumpTarget = instr->dst.block;
532 
533  // TRUE BRANCH
534  {
535  Scalar l(value);
536  Scalar u(Scalar::max());
537 
538  // interval [value+1,MAX]
539  Interval i(l, u);
540  i.tryRemove(l);
541 
542  targetIntervals = intervals;
543  targetIntervals[s1_index].intersectWith(i);
544  }
545 
546  // FALSE BRANCH
547  {
548  Scalar l(Scalar::min());
549  Scalar u(value);
550 
551  // interval [MIN,value].
552  Interval i(l, u);
553 
554  intervals[s1_index].intersectWith(i);
555  }
556 
557  break;
558  }
559  case ICMD_IFGE: // if (S1 >= INT_CONST) goto DST
560  {
561  node->ld->jumpTarget = instr->dst.block;
562 
563  // TRUE BRANCH
564  {
565  Scalar l(value);
566  Scalar u(Scalar::max());
567 
568  // interval [value,MAX]
569  Interval i(l, u);
570 
571  targetIntervals = intervals;
572  targetIntervals[s1_index].intersectWith(i);
573  }
574 
575  // FALSE BRANCH
576  {
577  Scalar l(Scalar::min());
578  Scalar u(value);
579 
580  // interval [MIN,value-1].
581  Interval i(l, u);
582  i.tryRemove(u);
583 
584  intervals[s1_index].intersectWith(i);
585  }
586 
587  break;
588  }
589  case ICMD_IF_ICMPEQ: // if (S1 == S2) goto DST
590  {
591  node->ld->jumpTarget = instr->dst.block;
592 
593  // TRUE BRANCH
594 
595  // S1, S2 lie in the intersection of their intervals.
596  targetIntervals = intervals;
597  targetIntervals[s1_index].intersectWith(intervals[s2_index]);
598  targetIntervals[s2_index] = targetIntervals[s1_index];
599 
600  // FALSE BRANCH
601 
602  IntervalMap temp = intervals;
603 
604  // If the interval of S2 contains only one element A,
605  // then A can be removed from the other interval.
606  if (temp[s2_index].lower() == temp[s2_index].upper())
607  {
608  intervals[s1_index].tryRemove(temp[s2_index].lower());
609  }
610 
611  // If the interval of S1 contains only one element A,
612  // then A can be removed from the other interval.
613  if (temp[s1_index].lower() == temp[s1_index].upper())
614  {
615  intervals[s2_index].tryRemove(temp[s1_index].lower());
616  }
617 
618  break;
619  }
620  case ICMD_IF_ICMPNE: // if (S1 != S2) goto DST
621  {
622  node->ld->jumpTarget = instr->dst.block;
623 
624  // TRUE BRANCH
625 
626  targetIntervals = intervals;
627 
628  // If the interval of S2 contains only one element A,
629  // then A can be removed from the other interval.
630  if (intervals[s2_index].lower() == intervals[s2_index].upper())
631  {
632  targetIntervals[s1_index].tryRemove(intervals[s2_index].lower());
633  }
634 
635  // If the interval of S1 contains only one element A,
636  // then A can be removed from the other interval.
637  if (intervals[s1_index].lower() == intervals[s1_index].upper())
638  {
639  targetIntervals[s2_index].tryRemove(intervals[s1_index].lower());
640  }
641 
642  // FALSE BRANCH
643 
644  // S1, S2 lie in the intersection of their intervals.
645  intervals[s1_index].intersectWith(intervals[s2_index]);
646  intervals[s2_index] = intervals[s1_index];
647 
648  break;
649  }
650  case ICMD_IF_ICMPLT: // if (S1 < S2) goto DST
651  {
652  node->ld->jumpTarget = instr->dst.block;
653 
654  // TRUE BRANCH
655  {
656  targetIntervals = intervals;
657 
658  // Create interval containing all elements less than the biggest instance of S2.
659  Interval lessThan;
660  lessThan.upper(intervals[s2_index].upper());
661  lessThan.tryRemove(intervals[s2_index].upper());
662 
663  // Create interval containing all elements greater than the smallest instance of S1.
664  Interval greaterThan;
665  greaterThan.lower(intervals[s1_index].lower());
666  greaterThan.tryRemove(intervals[s1_index].lower());
667 
668  // S1 is less than the biggest instance of S2.
669  targetIntervals[s1_index].intersectWith(lessThan);
670 
671  // S2 is greater than the smallest instance of S1.
672  targetIntervals[s2_index].intersectWith(greaterThan);
673  }
674 
675  // FALSE BRANCH
676  {
677  // Create interval containing all elements greater than or equal the smallest instance of S2.
678  Interval greaterThan;
679  greaterThan.lower(intervals[s2_index].lower());
680 
681  // Create interval containing all elements less than or equal the biggest instance of S1.
682  Interval lessThan;
683  lessThan.upper(intervals[s1_index].upper());
684 
685  // S1 is greater than or equal the smallest instance of S2.
686  intervals[s1_index].intersectWith(greaterThan);
687 
688  // S2 is less than or equal the biggest instance of S1.
689  intervals[s2_index].intersectWith(lessThan);
690  }
691 
692  break;
693  }
694  case ICMD_IF_ICMPLE: // if (S1 <= S2) goto DST
695  {
696  node->ld->jumpTarget = instr->dst.block;
697 
698  // TRUE BRANCH
699  {
700  targetIntervals = intervals;
701 
702  // Create interval containing all elements less than or equal the biggest instance of S2.
703  Interval lessThan;
704  lessThan.upper(intervals[s2_index].upper());
705 
706  // Create interval containing all elements greater than or equal the smallest instance of S1.
707  Interval greaterThan;
708  greaterThan.lower(intervals[s1_index].lower());
709 
710  // S1 is less than or equal the biggest instance of S2.
711  targetIntervals[s1_index].intersectWith(lessThan);
712 
713  // S2 is greater than or equal the smallest instance of S1.
714  targetIntervals[s2_index].intersectWith(greaterThan);
715  }
716 
717  // FALSE BRANCH
718  {
719  // Create interval containing all elements greater than the smallest instance of S2.
720  Interval greaterThan;
721  greaterThan.lower(intervals[s2_index].lower());
722  greaterThan.tryRemove(intervals[s2_index].lower());
723 
724  // Create interval containing all elements less than the biggest instance of S1.
725  Interval lessThan;
726  lessThan.upper(intervals[s1_index].upper());
727  lessThan.tryRemove(intervals[s1_index].upper());
728 
729  // S1 is greater than the smallest instance of S2.
730  intervals[s1_index].intersectWith(greaterThan);
731 
732  // S2 is less than the biggest instance of S1.
733  intervals[s2_index].intersectWith(lessThan);
734  }
735 
736  break;
737  }
738  case ICMD_IF_ICMPGT: // if (S1 > S2) goto DST
739  {
740  node->ld->jumpTarget = instr->dst.block;
741 
742  // TRUE BRANCH
743  {
744  targetIntervals = intervals;
745 
746  // Create interval containing all elements greater than the smallest instance of S2.
747  Interval greaterThan;
748  greaterThan.lower(intervals[s2_index].lower());
749  greaterThan.tryRemove(intervals[s2_index].lower());
750 
751  // Create interval containing all elements less than the biggest instance of S1.
752  Interval lessThan;
753  lessThan.upper(intervals[s1_index].upper());
754  lessThan.tryRemove(intervals[s1_index].upper());
755 
756  // S1 is greater than the smallest instance of S2.
757  targetIntervals[s1_index].intersectWith(greaterThan);
758 
759  // S2 is less than the biggest instance of S1.
760  targetIntervals[s2_index].intersectWith(lessThan);
761  }
762 
763  // FALSE BRANCH
764  {
765  // Create interval containing all elements less than or equal the biggest instance of S2.
766  Interval lessThan;
767  lessThan.upper(intervals[s2_index].upper());
768 
769  // Create interval containing all elements greater than or equal the smallest instance of S1.
770  Interval greaterThan;
771  greaterThan.lower(intervals[s1_index].lower());
772 
773  // S1 is less than or equal the biggest instance of S2.
774  intervals[s1_index].intersectWith(lessThan);
775 
776  // S2 is greater than or equal the smallest instance of S1.
777  intervals[s2_index].intersectWith(greaterThan);
778  }
779 
780  break;
781  }
782  case ICMD_IF_ICMPGE: // if (S1 >= S2) goto DST
783  {
784  node->ld->jumpTarget = instr->dst.block;
785 
786  // TRUE BRANCH
787  {
788  targetIntervals = intervals;
789 
790  // Create interval containing all elements greater than or equal the smallest instance of S2.
791  Interval greaterThan;
792  greaterThan.lower(intervals[s2_index].lower());
793 
794  // Create interval containing all elements less than or equal the biggest instance of S1.
795  Interval lessThan;
796  lessThan.upper(intervals[s1_index].upper());
797 
798  // S1 is greater than or equal the smallest instance of S2.
799  targetIntervals[s1_index].intersectWith(greaterThan);
800 
801  // S2 is less than or equal the biggest instance of S1.
802  targetIntervals[s2_index].intersectWith(lessThan);
803  }
804 
805  // FALSE BRANCH
806  {
807  // Create interval containing all elements less than the biggest instance of S2.
808  Interval lessThan;
809  lessThan.upper(intervals[s2_index].upper());
810  lessThan.tryRemove(intervals[s2_index].upper());
811 
812  // Create interval containing all elements greater than the smallest instance of S1.
813  Interval greaterThan;
814  greaterThan.lower(intervals[s1_index].lower());
815  greaterThan.tryRemove(intervals[s1_index].lower());
816 
817  // S1 is less than the biggest instance of S2.
818  intervals[s1_index].intersectWith(lessThan);
819 
820  // S2 is greater than the smallest instance of S1.
821  intervals[s2_index].intersectWith(greaterThan);
822  }
823 
824  break;
825  }
826 
827  case ICMD_ALOAD:
828  // do nothing
829  break;
830 
831  default:
832  if (instruction_has_dst(instr))
833  {
834  if (isLocalIntVar(jd, dst_index)) // Integer produced by an unknown instruction.
835  {
836  intervals[dst_index] = Interval(); // [MIN,MAX]
837  }
838  else
839  {
840  // If dst_index is an array, reset all intervals referencing that array.
841  for (size_t i = 0; i < intervals.size(); i++)
842  {
843  if (intervals[i].lower().instruction().kind() == NumericInstruction::ARRAY_LENGTH &&
844  intervals[i].lower().instruction().variable() == dst_index)
845  {
846  intervals[i] = Interval();
847  }
848  else if (intervals[i].upper().instruction().kind() == NumericInstruction::ARRAY_LENGTH &&
849  intervals[i].upper().instruction().variable() == dst_index)
850  {
851  intervals[i] = Interval();
852  }
853  }
854  }
855  }
856  }
857  }
858 
859  /*std::stringstream str;
860  str << "# " << node->nr << " # [F] " << intervals << "| [T] " << targetIntervals;
861  log_text(str.str().c_str());*/
862 
863  // Compute interval of counter variable.
864  if (node->ld->loop && node->ld->loop->hasCounterVariable)
865  {
866  if (node->ld->jumpTarget)
867  {
868  // Check if jump target is part of this loop.
869  if (node->ld->jumpTarget->ld->loops.find(node->ld->loop) == node->ld->jumpTarget->ld->loops.end())
870  {
871  // Jump target is _not_ part of this loop.
872  node->ld->loop->counterInterval.intersectWith(intervals[node->ld->loop->counterVariable]);
873  }
874  else
875  {
876  // Jump target is part of this loop.
877  Interval temp = intervals[node->ld->loop->counterVariable];
878  temp.unionWith(targetIntervals[node->ld->loop->counterVariable]);
879  node->ld->loop->counterInterval.intersectWith(temp);
880  }
881  }
882  else
883  {
884  node->ld->loop->counterInterval.intersectWith(intervals[node->ld->loop->counterVariable]);
885  }
886  }
887 
888  if (target == node->ld->jumpTarget)
889  return targetIntervals;
890 
891  return intervals;
892  }
893 
894  /**
895  * Checks whether the specified variable is local and of type integer.
896  */
897  bool isLocalIntVar(jitdata* jd, s4 varIndex)
898  {
899  varinfo* info = VAR(varIndex);
900  return IS_INT_TYPE(info->type) && (var_is_local(jd, varIndex) || var_is_temp(jd, varIndex));
901  }
902 
903  /**
904  * Checks whether the specified variables are local and of type integer.
905  */
906  bool isLocalIntVar(jitdata* jd, s4 var0, s4 var1)
907  {
908  varinfo* info0 = VAR(var0);
909  varinfo* info1 = VAR(var1);
910  return IS_INT_TYPE(info0->type) && (var_is_local(jd, var0) || var_is_temp(jd, var0))
911  && IS_INT_TYPE(info1->type) && (var_is_local(jd, var1) || var_is_temp(jd, var1));
912  }
913 
914  /**
915  * Checks whether the specified variable is local.
916  */
917  bool isLocalVar(jitdata* jd, s4 varIndex)
918  {
919  return var_is_local(jd, varIndex) || var_is_temp(jd, varIndex);
920  }
921 }
922 
923 /**
924  * Analyzes all loops and for every loop it finds
925  *
926  * -) all written variables,
927  * -) all counter variables.
928  */
930 {
931  for (std::vector<LoopContainer*>::iterator it = jd->ld->loops.begin(); it != jd->ld->loops.end(); ++it)
932  {
933  LoopContainer* loop = *it;
934 
935  assert(!loop->footers.empty());
936 
937  // For simplicity we consider only one back edge per loop
938  basicblock* footer = loop->footers.front();
939 
940  // Analyze all blocks contained in this loop.
941  analyzeBasicblockInLoop(jd, loop->header, loop);
942  for (std::vector<basicblock*>::iterator blockIt = loop->nodes.begin(); blockIt != loop->nodes.end(); ++blockIt)
943  {
944  if (*blockIt != footer)
945  analyzeBasicblockInLoop(jd, *blockIt, loop);
946  }
947  analyzeFooter(jd, loop); // Find counter variables.
948  analyzeBasicblockInLoop(jd, footer, loop); // The footer must be the last node to be analyzed.
949 
950  // Compute the final set of invariant integer variables.
951  // Compute the final set of invariant array variables.
952  for (VariableSet::iterator it = loop->writtenVariables.begin(); it != loop->writtenVariables.end(); ++it)
953  {
954  loop->invariantVariables.remove(*it);
955  loop->invariantArrays.remove(*it);
956  }
957  }
958 }
959 
960 /**
961  * Marks all basicblocks which are leaves.
962  */
964 {
965  for (std::vector<Edge>::const_iterator it = jd->ld->loopBackEdges.begin(); it != jd->ld->loopBackEdges.end(); ++it)
966  {
967  it->from->ld->outgoingBackEdgeCount++;
968  }
969 
970  for (basicblock* b = jd->basicblocks; b != 0; b = b->next)
971  {
972  assert(b->successorcount >= b->ld->outgoingBackEdgeCount);
973  b->ld->leaf = (b->successorcount == b->ld->outgoingBackEdgeCount);
974  }
975 }
976 
978 {
979  for (basicblock* block = jd->basicblocks; block != 0; block = block->next)
980  {
981  if (block->ld->leaf)
982  analyze(jd, block, 0);
983  }
984 }
985 
986 /*
987  * These are local overrides for various environment variables in Emacs.
988  * Please do not remove this and leave it at the end of the file, where
989  * Emacs will automagically detect them.
990  * ---------------------------------------------------------------------
991  * Local variables:
992  * mode: c++
993  * indent-tabs-mode: t
994  * c-basic-offset: 4
995  * tab-width: 4
996  * End:
997  * vim:noexpandtab:sw=4:ts=4:
998  */
999 
val_operand_t val
basicblock * block
VariableSet writtenVariables
Maps variable names to intervals.
Definition: IntervalMap.hpp:38
Represents a single loop.
basicblock * basicblocks
Definition: jit.hpp:141
Definition: jit.hpp:126
static bool instruction_has_dst(const instruction *iptr)
VariableSet invariantArrays
basicblock * next
Definition: jit.hpp:337
Scalar lower() const
Definition: Interval.hpp:67
void unionWith(const IntervalMap &)
Computes the union set of this map with the specified map.
Definition: IntervalMap.hpp:67
MachineLoop * loop
std::set< s4 >::iterator iterator
Definition: VariableSet.hpp:43
VariableSet invariantVariables
#define CF_NORMAL
Definition: icmd.hpp:370
int32_t varindex
Definition: instruction.hpp:63
std::set< s4 >::iterator begin()
Definition: VariableSet.hpp:49
static s4 min()
Definition: Scalar.hpp:47
bool contains(s4 variableIndex)
Definition: VariableSet.hpp:47
Type type
Definition: reg.hpp:44
void findLeaves(jitdata *jd)
Marks all basicblocks which are leaves.
Definition: analyze.cpp:963
An integer interval of the form constant_0 + instruction_0 .
Definition: Interval.hpp:39
instruction * iinstr
Definition: jit.hpp:319
#define VAR(i)
Definition: jit.hpp:252
Definition: reg.hpp:43
void analyzeLoops(jitdata *jd)
Analyzes all loops and for every loop it finds.
Definition: analyze.cpp:929
s4 icount
Definition: jit.hpp:318
static bool var_is_local(const jitdata *jd, s4 i)
Definition: jit.hpp:254
An integral value of the form Constant + NumericInstruction.
Definition: Scalar.hpp:40
void tryRemove(const Scalar &)
Tries to remove the specified scalar from this interval.
Definition: Interval.hpp:118
Scalar upper() const
Definition: Interval.hpp:70
void unionWith(const Interval &)
Computes a superset of the union of this interval with the specified interval.
Definition: Interval.hpp:112
BeginInst *& block
dst_operand_t dst
flags_operand_t flags
basicblock ** predecessors
Definition: jit.hpp:332
s4 predecessorcount
Definition: jit.hpp:330
static s4 max()
Definition: Scalar.hpp:48
static NumericInstruction newArrayLength(s4 variable)
MIIterator i
int32_t s4
Definition: types.hpp:45
union instruction::@12 sx
IntervalMap invariantIntervals
#define IS_INT_TYPE(a)
Definition: global.hpp:134
int32_t varindex
std::vector< basicblock * > footers
icmdtable_entry_t icmd_table[256]
Definition: icmd.cpp:60
static NumericInstruction newVariable(s4 variable)
s1_operand_t s1
int32_t controlflow
Definition: icmd.hpp:396
void removeFullyRedundantChecks(jitdata *jd)
Removes all array bound checks that are fully redundant.
Definition: analyze.cpp:977
std::vector< basicblock * > nodes
static bool var_is_temp(const jitdata *jd, s4 i)
Definition: jit.hpp:273
size_t size() const
Definition: IntervalMap.hpp:44
std::vector< LoopContainer * >::iterator iterator
Definition: LoopList.hpp:46
bool tryAdd(const Scalar &)
Tries to add a scalar to this scalar.
Definition: Scalar.cpp:88
std::set< s4 >::iterator end()
Definition: VariableSet.hpp:50
void remove(s4 variableIndex)
Definition: VariableSet.hpp:46
struct instruction::@12::@13 s23
BeginInst * target
bool trySubtract(const Scalar &)
Tries to subtract a scalar from this scalar.
Definition: Scalar.cpp:118
void insert(s4 variableIndex)
Definition: VariableSet.hpp:45
basicblock * header