CACAO
graph.cpp
Go to the documentation of this file.
1 /* src/vm/jit/optimizing/graph.cpp - CFG
2 
3  Copyright (C) 2005-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., 59 Temple Place - Suite 330, Boston, MA
21  02111-1307, USA.
22 
23 */
24 
25 #include <stdlib.h>
26 
27 #include "config.h"
28 
29 #include "mm/dumpmemory.hpp"
30 
31 #include "toolbox/bitvector.hpp"
32 
33 #include "vm/jit/jit.hpp"
34 
38 
39 #ifdef GRAPH_DEBUG_VERBOSE
40 #include "vm/options.hpp"
41 #endif
42 
43 /* Helpers for graph_make_cfg */
46 
47 void graph_add_edge( graphdata *gd, int from, int to );
48 
49 /* Helper for graph_get_first_* */
52 
53 void graph_phi_moves(jitdata *jd, basicblock *bptr, basicblock *dst_goto);
54 
55 #ifdef GRAPH_DEBUG_VERBOSE
56 void graph_print(lsradata *ls, graphdata *gd);
57 #endif
58 
59 
60 graphdata *graph_init(int basicblockcount) {
61  graphdata *gd;
62  int i;
63 
64  gd = NEW(graphdata);
65 #ifdef GRAPH_DEBUG_CHECK
66  /* Remember basicblockcount, so Array Bound checks can be made */
67  gd->basicblockcount = basicblockcount;
68 #endif
69 
70  gd->num_succ = DMNEW(int, basicblockcount);
71  gd->successor = DMNEW(graph_element *, basicblockcount);
72 
73  gd->num_pred = DMNEW(int, basicblockcount);
74  gd->predecessor = DMNEW(graph_element *, basicblockcount);
75 
76  for(i = 0; i < basicblockcount; i++) {
77  gd->num_succ[i] = gd->num_pred[i] = 0;
78  gd->successor[i] = NULL;
79  gd->predecessor[i] = NULL;
80  }
81  return gd;
82 }
83 
84 int graph_get_num_predecessor(graphdata *gd, int b_index) {
85  _GRAPH_CHECK_BOUNDS(b_index, 0, gd->basicblockcount);
86  return gd->num_pred[b_index];
87 }
88 
89 int graph_get_num_successor(graphdata *gd, int b_index) {
90  _GRAPH_CHECK_BOUNDS(b_index, 0, gd->basicblockcount);
91  return gd->num_succ[b_index];
92 }
93 
95  _GRAPH_CHECK_BOUNDS(b_index, 0, gd->basicblockcount);
96  return graph_get_first_(gd->successor[b_index], i);
97 }
98 
100  _GRAPH_CHECK_BOUNDS(b_index, 0, gd->basicblockcount);
101  return graph_get_first_(gd->predecessor[b_index], i);
102 }
103 
105  if ((*i) == NULL)
106  return -1;
107  (*i) = (*i)->next;
108  if ( (*i) == NULL )
109  return -1;
110  else
111  return (*i)->value;
112 }
113 
115  if ( ((*i) = ge) == NULL)
116  return -1;
117  else
118  return (*i)->value;
119 }
120 
122  _GRAPH_CHECK_BOUNDS(b_index, 0, gd->basicblockcount);
123  return (gd->num_pred[b_index] > 1);
124 }
125 
126 bool graph_has_multiple_successors( graphdata *gd, int b_index) {
127  _GRAPH_CHECK_BOUNDS(b_index, 0, gd->basicblockcount);
128  return (gd->num_succ[b_index] > 1);
129 }
130 
131 void graph_add_edge( graphdata *gd, int from, int to ) {
133  graph_element *n;
134  int b;
135 
136  /* prevent multiple similar edges from TABLESWITCH and */
137  /* LOOKUPSWITCH */
138  b = graph_get_first_successor(gd, from, &i);
139  for( ; (b != -1) && ( b != to); b = graph_get_next(&i));
140  if (b != -1) /* edge from->to already existing */
141  return;
142 
143  /* We need two new graph_elements. One for successors and one for */
144  /* predecessors */
145  n = DMNEW(graph_element, 2);
146 
147  n->value=to;
148  n->next=gd->successor[from];
149  gd->successor[from]=n;
150  gd->num_succ[from]++;
151 
152  n++; /* take next allocated graph_element */
153  n->value=from;
154  n->next=gd->predecessor[to];
155  gd->predecessor[to]=n;
156  gd->num_pred[to]++;
157 }
158 
159 /* split the edge from BB from shown by iterator i with new_block */
160 void graph_split_edge(graphdata *gd, int from, graphiterator *i, int new_block) {
161  graphiterator i_pred;
162  graph_element *n;
163  int l, succ;
164 
165  /* i->value is the BB index of the "old" successor */
166 
167  succ = (*i)->value;
168 
169  /* search for iterator showing predecessor edge from BB succ back to */
170  /* from */
171 
172  l = graph_get_first_predecessor(gd, succ, &i_pred);
173  for(; (l != -1) && (l != from); l = graph_get_next(&i_pred));
174  _GRAPH_ASSERT(l == from);
175 
176  /* change CFG entries */
177 
178  (*i)->value = new_block;
179  i_pred->value = new_block;
180 
181  /* and insert the CFG successor and predecesser entries for new_block */
182  /* 2 entries needed */
183 
184  n = DMNEW(graph_element, 2);
185 
186  /* make the successor entry for new_block */
187 
188  n->value = succ;
189  n->next = gd->successor[new_block];
190  gd->successor[new_block] = n;
191  gd->num_succ[new_block]++;
192 
193  /* make the predecessor entry for new_block */
194 
195  n++;
196  n->value = from;
197  n->next = gd->predecessor[new_block];
198  gd->predecessor[new_block] = n;
199  gd->num_pred[new_block]++;
200 }
201 
202 /***********************************************
203 Generate the Control Flow Graph
204 ( pred,succ,num_pred of lsradata structure)
205 ************************************************/
207  instruction *iptr;
208  lookup_target_t *lookup;
209  branch_target_t *table;
210  int len, i, l;
211  methodinfo *m;
212  codegendata *cd;
213  registerdata *rd;
214  lsradata *ls;
215  basicblock *bptr;
216 
217  m = jd->m;
218  cd = jd->cd;
219  rd = jd->rd;
220  ls = jd->ls;
221 
222  /* Add edge from new Basic Block 0 (parameter initialization) */
223  graph_add_edge(gd, 0, 1);
224 
225  for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
226  if (bptr->state >= basicblock::REACHED) {
227  if ((len = bptr->icount)) {
228  /* set iptr to last non NOP instruction */
229  iptr = bptr->iinstr + bptr->icount -1;
230  while ((len>0) && (iptr->opc == ICMD_NOP)) {
231  len--;
232  iptr--;
233  }
234  /* block contains instructions */
235  switch (iptr->opc) { /* check type of last instruction */
236  case ICMD_RETURN:
237  case ICMD_IRETURN:
238  case ICMD_LRETURN:
239  case ICMD_FRETURN:
240  case ICMD_DRETURN:
241  case ICMD_ARETURN:
242  case ICMD_ATHROW:
243  break; /* function returns -> end of graph */
244 
245  case ICMD_IFNULL:
246  case ICMD_IFNONNULL:
247  case ICMD_IFEQ:
248  case ICMD_IFNE:
249  case ICMD_IFLT:
250  case ICMD_IFGE:
251  case ICMD_IFGT:
252  case ICMD_IFLE:
253  case ICMD_IF_LEQ:
254  case ICMD_IF_LNE:
255  case ICMD_IF_LLT:
256  case ICMD_IF_LGE:
257  case ICMD_IF_LGT:
258  case ICMD_IF_LLE:
259  case ICMD_IF_ICMPEQ:
260  case ICMD_IF_ICMPNE:
261  case ICMD_IF_ICMPLT:
262  case ICMD_IF_ICMPGE:
263  case ICMD_IF_ICMPGT:
264  case ICMD_IF_ICMPLE:
265  case ICMD_IF_LCMPEQ:
266  case ICMD_IF_LCMPNE:
267  case ICMD_IF_LCMPLT:
268  case ICMD_IF_LCMPGE:
269  case ICMD_IF_LCMPGT:
270  case ICMD_IF_LCMPLE:
271  case ICMD_IF_ACMPEQ:
272  case ICMD_IF_ACMPNE: /* branch -> add next block */
273  /* Add branch target */
274  graph_add_cfg(jd, gd, bptr, iptr->dst.block);
275  /* Add fall through path */
276  graph_add_cfg(jd, gd, bptr, bptr->next);
277  break;
278 
279 
280  case ICMD_GOTO:
281  graph_add_cfg(jd, gd, bptr, iptr->dst.block);
282  break; /* visit branch (goto) target */
283 
284  case ICMD_TABLESWITCH: /* switch statement */
285  table = iptr->dst.table;
286  l = iptr->sx.s23.s2.tablelow;
287  i = iptr->sx.s23.s3.tablehigh;
288  i = i - l + 1;
289 
290  /* Add default target */
291 
292  graph_add_cfg(jd, gd, bptr, table[0].block);
293  table += i;
294 
295  while (--i >= 0) {
296  graph_add_cfg(jd, gd, bptr, table->block);
297  --table;
298  }
299  break;
300 
301  case ICMD_LOOKUPSWITCH: /* switch statement */
302  lookup = iptr->dst.lookup;
303  i = iptr->sx.s23.s2.lookupcount;
304 
305  while (--i >= 0) {
306  graph_add_cfg(jd, gd, bptr, lookup->target.block);
307  lookup++;
308  }
309 
310  graph_add_cfg(jd, gd, bptr, iptr->sx.s23.s3.lookupdefault.block);
311  break;
312 
313  case ICMD_RET:
314  case ICMD_JSR:
315  assert(0);
316  break;
317 
318  case ICMD_NOP:
319  assert(0);
320 
321  default:
322  graph_add_cfg(jd, gd, bptr, bptr + 1 );
323  break;
324  } /* switch (iptr->opc)*/
325  } /* if (bptr->icount) */
326  } /* if (bptr->state >= basicblock::REACHED) */
327  } /* for (bptr = ...; bptr != NULL; bptr = bptr->next) */
328 
329  graph_add_exceptions(jd, gd);
330  transform_CFG(jd, gd);
331 
332 #ifdef GRAPH_DEBUG_VERBOSE
333  if (compileverbose)
334  graph_print(ls, gd);
335 #endif
336 }
337 
338 /*****************************************************************
339 add Edges from guarded Areas to Exception handlers in the CFG
340 *****************************************************************/
342 #if 0
343  basicblock *bptr;
345  codegendata *cd;
346 
347  cd = jd->cd;
348 
349  /* add cfg edges from all bb of a try block to the start of the according */
350  /* exception handler to ensure the right order after depthfirst search */
351 
352  ex=jd->exceptiontable;
353 
354 #ifdef GRAPH_DEBUG_VERBOSE
355  if (compileverbose)
356  printf("ExTable(%i): ", jd->exceptiontablelength);
357 #endif
358 
359  for (; ex != NULL; ex = ex->down) {
360 
361 #ifdef GRAPH_DEBUG_VERBOSE
362  if (compileverbose)
363  printf("[%i-%i]->%i ",ex->start->nr, ex->end->nr,
364  ex->handler->nr);
365 #endif
366 
367  _GRAPH_ASSERT(ex->handler->nr < jd->new_basicblockcount);
368  _GRAPH_ASSERT(ex->handler->state >= basicblock::REACHED);
369  _GRAPH_ASSERT(ex->start->nr <= ex->end->nr);
370 
371  /* loop all valid Basic Blocks of the guarded area and add CFG edges */
372  /* to the appropriate handler */
373  for (bptr = ex->start; (bptr != NULL) && (bptr != ex->end); bptr = bptr->next)
374  if (bptr->state >= basicblock::REACHED)
375  graph_add_cfg(jd, gd, bptr, ex->handler);
376 
377  _GRAPH_ASSERT((bptr != NULL)
378  && ((bptr->state >=basicblock::REACHED) || (bptr == ex->end)));
379  }
380 #ifdef GRAPH_DEBUG_VERBOSE
381  if (compileverbose)
382  printf("\n");
383 #endif
384 #endif
385 }
386 
387 
388 /******************************************************************
389 Add the CFG Edge into next und succ
390 ******************************************************************/
392  basicblock *to) {
393 
394  /* ignore Empty, Deleted,... Basic Blocks as target */
395  /* TODO: Setup BasicBlock array before to avoid this */
396  /* best together with using the basicblock list, so lsra works */
397  /* with opt_loops, too */
398 
399  for (; (to != NULL) && (to->state < basicblock::REACHED); to = to->next);
400 
401  _GRAPH_ASSERT(to != NULL);
402 
403 
404  /* add one to from and to, so the to be inserted Basic Block 0 is */
405  /* already regarded */
406  graph_add_edge( gd, from->nr + 1, to->nr + 1);
407 }
408 
409 
410 /*****************************************************************
411 Sort Basic Blocks using Depth First search in reverse post order
412 In: ls->basicblockcount, ls->basicblocks[], gd->
413 Out: ls->sorted, ls->sorted_rev
414 *****************************************************************/
415 
416 void graph_DFS(lsradata *ls, graphdata *gd) {
417  int *stack;
418  int *visited;
419  int stack_top;
420  bool not_finished;
421  int i,p,s, num_pred;
422  graphiterator iter;
423 
424  ls->sorted = DMNEW(int, ls->basicblockcount);
425  ls->sorted_rev = DMNEW(int, ls->basicblockcount);
426 
427  stack = DMNEW( int, ls->basicblockcount);
428  visited = (int *)DMNEW( bool, ls->basicblockcount);
429  for (i = 0; i < ls->basicblockcount; i++) {
430  visited[i] = 0;
431  ls->sorted[i]=-1;
432  ls->sorted_rev[i]=-1;
433  }
434 
435  stack[0] = 0; /* start with Block 0 */
436  stack_top = 1;
437  /* Start Block is handled right and can be put in sorted */
438  visited[0] = graph_get_num_predecessor(gd , 0);
439  p = 0;
440  not_finished = true;
441  while (not_finished) {
442  while (stack_top != 0) {
443  stack_top--;
444  i = stack[stack_top];
445  ls->sorted[p]=i;
446  p++;
447  s = graph_get_first_successor(gd, i, &iter);
448  for (; s != -1; s = graph_get_next(&iter)) {
449  visited[s]++;
450  if (visited[s] == graph_get_num_predecessor(gd, s)) {
451  /* push the node on the stack, only if all ancestors have */
452  /* been visited */
453  stack[stack_top] = s;
454  stack_top++;
455  }
456  }
457  }
458  not_finished = false;
459  for (i=1; i < ls->basicblockcount; i++) {
460  /* search for visited blocks, which have not reached the num_pre */
461  /* and put them on the stack -> happens with backedges */
462  num_pred = graph_get_num_predecessor(gd, i);
463  if ((visited[i] != 0) && (visited[i] < num_pred)) {
464  stack[stack_top] = i;
465  stack_top++;
466  visited[i] = num_pred;
467  not_finished=true;
468  break;
469  }
470  }
471  }
472 
473  for(i = 0; i < ls->basicblockcount; i++)
474  if (ls->sorted[i] != -1)
475  ls->sorted_rev[ls->sorted[i]] = i;
476 }
477 
478 
479 void graph_init_basicblock(jitdata *jd, basicblock *bptr, int b_index) {
480  bptr->nr = b_index;
481  bptr->icount = 0;
482  bptr->iinstr = NULL;
483  bptr->type = basicblock::TYPE_STD;
484  bptr->state = basicblock::FINISHED;
485  bptr->invars = NULL;
486  bptr->outvars = NULL;
487  bptr->indepth = 0;
488  bptr->outdepth = 0;
489  bptr->branchrefs = NULL;
490  bptr->mpc = -1;
491  bptr->next = NULL;
492  bptr->method = jd->m;
493 }
494 
495 /*********************************************************************+
496 After the "original" CFG has been created, it has to be adopted for
497 SSA. (inluding insertion of new Basic Blocks - edge splitting)
498 
499 **********************************************************************/
501  int i, j, k, n, num_new_blocks;
502  int **var_def;
503  basicblock *tmp, *bptr;
504  s4 *in, *out, *new_in_stack, *new_out_stack;
505  graphiterator iter;
506  int *num_succ;
507  struct graph_element **successor;
508  int *num_pred;
509  struct graph_element **predecessor;
510  methodinfo *m;
511  codegendata *cd;
512  registerdata *rd;
513  lsradata *ls;
514 
515  m = jd->m;
516  cd = jd->cd;
517  rd = jd->rd;
518  ls = jd->ls;
519 
520  /* with SSA a new Basic Block 0 is inserted for parameter initialisation */
521  /* & look for nodes with multiple successors leading to nodes with */
522  /* multiple predecessor -> if found insert a new block between to split */
523  /* this edge. As first step count how many blocks have to be inserted. */
524 
525  num_new_blocks = 1;
526  for(i = 0; i< jd->basicblockcount + 1; i++) {
527  if (graph_has_multiple_successors(gd, i)) {
528  k = graph_get_first_successor(gd, i, &iter);
529  for(; k != -1; k = graph_get_next(&iter)) {
530  /* check for successor blocks with more than one */
531  /* predecessor. For each found incremet num_new_blocks */
533  num_new_blocks++;
534  }
535  }
536  }
537 
538  /* increase now basicblockcount accordingly. */
539  ls->basicblockcount = jd->basicblockcount + num_new_blocks;
540 
542  for(i = 0; i< ls->basicblockcount; i++)
543  ls->basicblocks[i] = NULL;
544 
545  /* copy Basic Block References to ls->basicblocks */
546 
547  for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
548  _GRAPH_ASSERT(bptr->nr < jd->basicblockcount);
549  ls->basicblocks[bptr->nr + 1] = bptr;
550  bptr->nr = bptr->nr+1;
551  }
552 
553  /* Create new Basic Blocks:
554  0, [jd->basicblockcount..ls->basicblockcount[ */
555  /* num_new_blocks have to be inserted*/
556 
557  tmp = DMNEW( basicblock, num_new_blocks);
558  ls->basicblocks[0] = tmp;
559  graph_init_basicblock( jd, tmp, 0);
560  tmp++;
561  ls->basicblocks[0]->next = ls->basicblocks[1];
562 
563  if (ls->basicblockcount > jd->basicblockcount + 1) {
564 
565  /* new Blocks have to be inserted */
566 
567  num_succ = DMNEW(int, ls->basicblockcount);
568  successor = DMNEW(graph_element *, ls->basicblockcount);
569 
570  num_pred = DMNEW(int, ls->basicblockcount);
571  predecessor = DMNEW(graph_element *, ls->basicblockcount);
572 
573  /* regard the + 1 for the already inserted new BB 0 */
574  /* So recreate ls->var_def */
575 
576  var_def = DMNEW(int *, ls->basicblockcount);
577  for(i = 0; i < jd->basicblockcount + 1; i++) {
578  var_def[i] = ls->var_def[i];
579  num_succ[i] = gd->num_succ[i];
580  num_pred[i] = gd->num_pred[i];
581  successor[i] = gd->successor[i];
582  predecessor[i] = gd->predecessor[i];
583  }
584  for(i = jd->basicblockcount + 1; i < ls->basicblockcount; i++) {
585  var_def[i] = bv_new(jd->varcount);
586  graph_init_basicblock( jd, tmp, i);
587  ls->basicblocks[i] = tmp;
588  tmp++;
589 
590  num_succ[i] = 0;
591  num_pred[i] = 0;
592  successor[i] = NULL;
593  predecessor[i] = NULL;
594  }
595  ls->var_def = var_def;
596  gd->num_succ = num_succ;
597  gd->num_pred = num_pred;
598  gd->successor = successor;
599  gd->predecessor = predecessor;
600 #ifdef GRAPH_DEBUG_CHECK
601  /* Remember basicblockcount, so Array Bound checks can be made */
603 #endif
604  }
605 
606  /* Now Split the edges */
607 
608  num_new_blocks = jd->basicblockcount + 1; /* first free new block index */
609  for(i = 0; i < jd->basicblockcount + 1; i++) {
610  if (graph_has_multiple_successors(gd, i)) {/* more than one successor */
611  j = graph_get_first_successor( gd, i, &iter);
612  for(; j != -1; j = graph_get_next(&iter)) {
613  if (graph_has_multiple_predecessors(gd, j)) {
614  /* and more than one predecessor -> split edge */
615  _GRAPH_ASSERT(num_new_blocks < ls->basicblockcount);
616 
617  /* insert new Block num_new_blocks */
618 
619  /* splite the edge from BB i to j with the new BB */
620  /* num_new_blocks ( i->j --> i->nnb->j)*/
621  /* iter_succ shows the edge from i to j */
622 
623  graph_split_edge(gd, i, &iter, num_new_blocks);
624 
625  ls->basicblocks[num_new_blocks]->indepth =
626  ls->basicblocks[i]->outdepth;
627  out = ls->basicblocks[i]->outvars;
628  ls->basicblocks[num_new_blocks]->invars = in = NULL;
629 
630  if (ls->basicblocks[num_new_blocks]->indepth > 0)
631  new_in_stack = DMNEW( s4,
632  ls->basicblocks[num_new_blocks]->indepth);
633  new_out_stack = DMNEW( s4,
634  ls->basicblocks[num_new_blocks]->indepth);
635 
636  for(n=0; n<ls->basicblocks[num_new_blocks]->indepth; n++) {
637  new_in_stack[n] = out[n];
638  new_out_stack[n] = out[n];
639  }
640  ls->basicblocks[num_new_blocks]->invars = new_in_stack;
641 
642  /* Create Outstack */
643  ls->basicblocks[num_new_blocks]->outvars =
644  new_out_stack;
645  ls->basicblocks[num_new_blocks]->outdepth =
646  ls->basicblocks[num_new_blocks]->indepth;
647 
648  _GRAPH_ASSERT(ls->basicblocks[num_new_blocks]->outdepth ==
649  ls->basicblocks[j]->indepth );
650 
651  num_new_blocks++;
652  }
653  }
654  }
655  }
656 }
657 
659  int n, len;
660  int pred, succ;
661  basicblock *last_block;
662  instruction *iptr;
663  graphiterator iter;
664  methodinfo *m;
665  lsradata *ls;
666 
667  m = jd->m;
668  ls = jd->ls;
669 
670  /* the "real" last Block is always an empty block */
671  /* so take the one before, to insert new blocks after it */
672  last_block = &(jd->basicblocks[jd->basicblockcount - 1]);
673  _GRAPH_ASSERT(last_block->next->next == NULL);
674  _GRAPH_ASSERT(last_block->next->state <= basicblock::REACHED);
675  last_block->next->nr = ls->basicblockcount;
676 
677  /* look through new blocks */
678  for(n = jd->basicblockcount + 1; n < ls->basicblockcount ; n++) {
679  /* if a phi move happens at this block, we need this block */
680  /* if not, remove him from the CFG */
681  if (ls->num_phi_moves[n] > 0) {
682  /* i can only have one predecessor and one successor! */
685 
686  succ = graph_get_first_successor(gd, n, &iter);
687  pred = graph_get_first_predecessor(gd, n, &iter);
688 
689  /* set iptr to last instruction */
690  len = ls->basicblocks[pred]->icount;
691  iptr = ls->basicblocks[pred]->iinstr + len - 1;
692  while ((len>0) && (iptr->opc == ICMD_NOP)) {
693  len--;
694  iptr--;
695  }
696 
697 
698  /* with JSR there can not be multiple successors */
699  _GRAPH_ASSERT(iptr->opc != ICMD_JSR);
700  /* If the return Statment has more successors and */
701  /* one of these has more predecessor, we are in */
702  /* troubles - one would have to insert a new Block */
703  /* after the one which executes the ICMD_JSR */
704  /* !!TODO!! if subroutines will not be inlined */
705  _GRAPH_ASSERT(iptr->opc != ICMD_RET);
706 
707  /* link new block into basicblocks list */
708  /* if edge to split is the "fallthrough" path of the */
709  /* conditional, then link the new block inbetween */
710  /* and generate no ICMD */
711  /* else if edge to split is the branch, generate a */
712  /* ICMD_GOTO and add new BB at the end of the BB List*/
713  if ((ls->basicblocks[pred]->next == ls->basicblocks[succ])
714  && (iptr->opc != ICMD_LOOKUPSWITCH)
715  && (iptr->opc != ICMD_TABLESWITCH)
716  && (iptr->opc != ICMD_GOTO)) {
717  /* GOTO, *SWITCH have no fallthrough path */
718 
719  /* link into fallthrough path */
720 
721 
722  ls->basicblocks[n]->next =
723  ls->basicblocks[pred]->next;
724  ls->basicblocks[pred]->next =
725  ls->basicblocks[n];
726 #if 1
727  /* generate no instructions */
728  ls->basicblocks[n]->icount = 1;
729  ls->basicblocks[n]->iinstr = NEW(instruction);
730  ls->basicblocks[n]->iinstr[0].opc = ICMD_NOP;
731 #else
732  graph_phi_moves(jd, ls->basicblocks[n], NULL);
733 #endif
734  } else {
735  /* Block n is in the Branch path */
736  /* link Block at the end */
737  ls->basicblocks[n]->next =last_block->next;
738  last_block->next = ls->basicblocks[n];
739  last_block = ls->basicblocks[n];
740 
741  /* change the Branch Target to BB i */
742 
743  switch(iptr->opc) {
744  case ICMD_LOOKUPSWITCH:
745  {
746  s4 i;
747  lookup_target_t *lookup;
748 
749  lookup = iptr->dst.lookup;
750 
751  i = iptr->sx.s23.s2.lookupcount;
752 
753  while (--i >= 0) {
754  if (lookup->target.block == ls->basicblocks[succ])
755  /* target found -> change */
756  lookup->target.block = ls->basicblocks[n];
757  lookup++;
758  }
759 
760  if (iptr->sx.s23.s3.lookupdefault.block == ls->basicblocks[succ])
761  /* target found -> change */
762  iptr->sx.s23.s3.lookupdefault.block = ls->basicblocks[n];
763  }
764  break;
765  case ICMD_TABLESWITCH:
766  {
767  s4 i, l;
768  branch_target_t *table;
769 
770  table = iptr->dst.table;
771 
772  l = iptr->sx.s23.s2.tablelow;
773  i = iptr->sx.s23.s3.tablehigh;
774 
775  i = i - l + 1;
776 
777  if (table[0].block == ls->basicblocks[succ]) /* default target */
778  /* target found -> change*/
779  table[0].block = ls->basicblocks[n];
780 
781  table += i;
782 
783  while (--i >= 0) {
784  if (table->block == ls->basicblocks[succ])
785  /* target found -> change */
786  table->block = ls->basicblocks[n];
787  --table;
788  }
789  }
790  break;
791  case ICMD_IFNULL:
792  case ICMD_IFNONNULL:
793  case ICMD_IFEQ:
794  case ICMD_IFNE:
795  case ICMD_IFLT:
796  case ICMD_IFGE:
797  case ICMD_IFGT:
798  case ICMD_IFLE:
799  case ICMD_IF_LEQ:
800  case ICMD_IF_LNE:
801  case ICMD_IF_LLT:
802  case ICMD_IF_LGE:
803  case ICMD_IF_LGT:
804  case ICMD_IF_LLE:
805  case ICMD_IF_ICMPEQ:
806  case ICMD_IF_ICMPNE:
807  case ICMD_IF_ICMPLT:
808  case ICMD_IF_ICMPGE:
809  case ICMD_IF_ICMPGT:
810  case ICMD_IF_ICMPLE:
811  case ICMD_IF_LCMPEQ:
812  case ICMD_IF_LCMPNE:
813  case ICMD_IF_LCMPLT:
814  case ICMD_IF_LCMPGE:
815  case ICMD_IF_LCMPGT:
816  case ICMD_IF_LCMPLE:
817  case ICMD_IF_ACMPEQ:
818  case ICMD_IF_ACMPNE:
819  case ICMD_GOTO:
820  _GRAPH_ASSERT(iptr->dst.block == ls->basicblocks[succ]);
821  iptr->dst.block = ls->basicblocks[n];
822  break;
823  default:
824  /* Exception Edge to split */
825  /* not handled by now -> fallback to regalloc */
826  exit(1);
827  }
828 #if 1
829  /* Generate the ICMD_GOTO */
830  ls->basicblocks[n]->icount = 1;
831  ls->basicblocks[n]->iinstr =
832  DNEW(instruction);
833  ls->basicblocks[n]->iinstr->opc =
834  ICMD_GOTO;
835  ls->basicblocks[n]->iinstr->dst.block =
836  ls->basicblocks[succ];
837 #else
838  graph_phi_moves(jd, ls->basicblocks[n], ls->basicblocks[succ]);
839 #endif
840  }
841  }
842  }
843 }
844 
845 /* graph_phi_moves *************************************************************
846 
847 generate the instruction array for Basicblock n (== ls->basicblocks[n])
848 
849 IN:
850 basicblock *bptr Basicblock to change with ->iinstr == NULL
851 basicblock *dst_goto Destination Block for ICMD_GOTO at end of Block, or
852  NULL for no ICMD_GOTO
853 
854 OUT:
855 bptr->iinstr points to a newly allocated instruction array containing
856  the phi moves, the optional ICMD_GOTO at the end.
857 bptr->icount Count of instructions in bptr->iinstr
858 
859 *******************************************************************************/
860 
861 void graph_phi_moves(jitdata *jd, basicblock *bptr, basicblock *dst_goto) {
862  int lt_d,lt_s,i;
863  lsradata *ls;
864  instruction *iptr;
865 
866  ls = jd->ls;
867 
868  _GRAPH_ASSERT(ls->num_phi_moves[bptr->nr] > 0);
869  bptr->icount = ls->num_phi_moves[bptr->nr];
870  if (dst_goto != NULL)
871  bptr->icount++;
872  bptr->iinstr = iptr = DMNEW(instruction, bptr->icount);
873 
874  _GRAPH_ASSERT(iptr != NULL);
875 
876  /* Moves from phi functions with highest indices have to be */
877  /* inserted first, since this is the order as is used for */
878  /* conflict resolution */
879 
880  for(i = ls->num_phi_moves[bptr->nr] - 1; i >= 0 ; i--) {
881  lt_d = ls->phi_moves[bptr->nr][i][0];
882  lt_s = ls->phi_moves[bptr->nr][i][1];
883 
884 #if defined(GRAPH_DEBUG_VERBOSE)
885  if (compileverbose)
886  printf("graph_phi_moves: BB %3i Move %3i <- %3i\n", bptr->nr,
887  lt_d, lt_s);
888 #endif
889  if (lt_s == jitdata::UNUSED) {
890 #if defined(SSA_DEBUG_VERBOSE)
891  if (compileverbose)
892  printf(" ... not processed \n");
893 #endif
894  continue;
895  }
896 
897  _GRAPH_ASSERT(d->type != -1);
898  _GRAPH_ASSERT(s->type == -1);
899 
900  iptr->opc = ICMD_MOVE;
901  iptr->s1.varindex = ls->lifetime[lt_s].v_index;
902  iptr->dst.varindex = ls->lifetime[lt_d].v_index;
903  iptr++;
904  }
905 
906  if (dst_goto != NULL) {
907  iptr->opc = ICMD_GOTO;
908  iptr->dst.block = dst_goto;
909  }
910 }
911 
912 #ifdef GRAPH_DEBUG_VERBOSE
914  int i,j;
915  graphiterator iter;
916  printf("graph_print: basicblockcount %3i\n", ls->basicblockcount);
917 
918  printf("CFG: \n");
919  for(i = 0; i < ls->basicblockcount; i++) {
920  printf("%3i: ",i);
921  j = graph_get_first_successor(gd, i, &iter);
922  for(; j != -1; j = graph_get_next(&iter)) {
923  printf("%3i ",j);
924  }
925  printf("\n");
926  }
927  printf("Pred: \n");
928  for(i = 0; i < ls->basicblockcount; i++) {
929  printf("%3i: ",i);
930  j = graph_get_first_predecessor(gd, i, &iter);
931  for(; j != -1; j = graph_get_next(&iter)) {
932  printf("%3i ", j);
933  }
934  printf("\n");
935  }
936 }
937 #endif
938 
939 
940 
941 /*
942  * These are local overrides for various environment variables in Emacs.
943  * Please do not remove this and leave it at the end of the file, where
944  * Emacs will automagically detect them.
945  * ---------------------------------------------------------------------
946  * Local variables:
947  * mode: c++
948  * indent-tabs-mode: t
949  * c-basic-offset: 4
950  * tab-width: 4
951  * End:
952  * vim:noexpandtab:sw=4:ts=4:
953  */
int graph_get_next(graphiterator *i)
Definition: graph.cpp:104
basicblock * block
s4 exceptiontablelength
Definition: jit.hpp:167
struct graph_element ** predecessor
Definition: graph.hpp:67
bool graph_has_multiple_predecessors(graphdata *gd, int b_index)
Definition: graph.cpp:121
basicblock * basicblocks
Definition: jit.hpp:141
Definition: jit.hpp:126
int *** phi_moves
Definition: lsra.hpp:197
exception_entry * exceptiontable
Definition: jit.hpp:168
#define NEW(type)
Definition: memory.hpp:93
argument_type from
State state
Definition: jit.hpp:313
bitvector * var_def
Definition: lsra.hpp:154
s4 * invars
Definition: jit.hpp:323
int basicblockcount
Definition: lsra.hpp:188
basicblock * next
Definition: jit.hpp:337
struct graph_element * next
Definition: graph.hpp:57
s4 outdepth
Definition: jit.hpp:326
int basicblockcount
Definition: graph.hpp:62
int v_index
Definition: lsra.hpp:97
void graph_add_cfg(jitdata *jd, graphdata *gd, basicblock *, basicblock *)
Definition: graph.cpp:391
s4 mpc
Definition: jit.hpp:345
codegendata * cd
Definition: jit.hpp:129
int32_t varindex
Definition: instruction.hpp:63
void graph_add_edge(graphdata *gd, int from, int to)
Definition: graph.cpp:131
int graph_get_first_predecessor(graphdata *gd, int b_index, graphiterator *i)
Definition: graph.cpp:99
int graph_get_first_(graph_element *ge, graphiterator *i)
Definition: graph.cpp:114
struct lifetime * lifetime
Definition: lsra.hpp:168
branchref * branchrefs
Definition: jit.hpp:335
lookup_target_t * lookup
#define _GRAPH_CHECK_BOUNDS(i, l, h)
Definition: graph.hpp:43
instruction * iinstr
Definition: jit.hpp:319
struct graph_element ** successor
Definition: graph.hpp:65
s4 icount
Definition: jit.hpp:318
void graph_DFS(lsradata *ls, graphdata *gd)
Definition: graph.cpp:416
#define DNEW(type)
Definition: dumpmemory.hpp:370
s4 varcount
Definition: jit.hpp:151
int * num_phi_moves
Definition: lsra.hpp:196
BeginInst *& block
branch_target_t target
Definition: instruction.hpp:57
dst_operand_t dst
Instruction::InstID tmp[]
Definition: Matcher.cpp:55
bool compileverbose
Definition: options.cpp:82
alloc::list< PassInfo::IDTy >::type & stack
void transform_CFG(jitdata *, graphdata *)
Definition: graph.cpp:500
Definition: method.hpp:155
int graph_get_num_successor(graphdata *gd, int b_index)
Definition: graph.cpp:89
int * num_pred
Definition: graph.hpp:66
s4 indepth
Definition: jit.hpp:325
void transform_BB(jitdata *jd, graphdata *gd)
Definition: graph.cpp:658
MIIterator i
basicblock ** basicblocks
Definition: lsra.hpp:189
int32_t s4
Definition: types.hpp:45
void graph_make_cfg(jitdata *jd, graphdata *gd)
Definition: graph.cpp:206
registerdata * rd
Definition: jit.hpp:130
int * sorted
Definition: lsra.hpp:155
s4 * outvars
Definition: jit.hpp:324
union instruction::@12 sx
void graph_add_exceptions(jitdata *jd, graphdata *gd)
Definition: graph.cpp:341
int32_t varindex
int * sorted_rev
Definition: lsra.hpp:156
s1_operand_t s1
basicblock * block
Definition: instruction.hpp:50
int * num_succ
Definition: graph.hpp:64
int graph_get_num_predecessor(graphdata *gd, int b_index)
Definition: graph.cpp:84
void graph_split_edge(graphdata *gd, int from, graphiterator *i, int new_block)
Definition: graph.cpp:160
methodinfo * m
Definition: jit.hpp:127
methodinfo * method
Definition: jit.hpp:342
void graph_phi_moves(jitdata *jd, basicblock *bptr, basicblock *dst_goto)
Definition: graph.cpp:861
s4 nr
Definition: jit.hpp:312
s4 basicblockcount
Definition: jit.hpp:144
#define DMNEW(type, num)
Definition: dumpmemory.hpp:371
OStream & out()
Definition: OStream.cpp:39
struct instruction::@12::@13 s23
void graph_init_basicblock(jitdata *jd, basicblock *bptr, int b_index)
Definition: graph.cpp:479
bitvector bv_new(int size)
Definition: bitvector.cpp:122
#define _GRAPH_ASSERT(a)
Definition: graph.hpp:44
bool graph_has_multiple_successors(graphdata *gd, int b_index)
Definition: graph.cpp:126
Type type
Definition: jit.hpp:315
void graph_print(lsradata *ls, graphdata *gd)
Definition: graph.cpp:913
#define printf(...)
Definition: ssa2.cpp:40
branch_target_t * table
graphdata * graph_init(int basicblockcount)
Definition: graph.cpp:60
int graph_get_first_successor(graphdata *gd, int b_index, graphiterator *i)
Definition: graph.cpp:94