1 /* src/vm/jit/optimizing/graph.c - CFG
3 Copyright (C) 2005, 2006 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4 R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5 C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6 Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 Contact: cacao@complang.tuwien.ac.at
27 Authors: Christian Ullrich
33 #include "mm/memory.h"
35 #include "toolbox/bitvector.h"
37 #include "vm/jit/optimizing/lsra.h"
38 #include "vm/jit/optimizing/ssa.h"
39 #include "vm/jit/optimizing/graph.h"
41 #ifdef GRAPH_DEBUG_VERBOSE
42 #include "vm/options.h"
46 /* Helpers for graph_make_cfg */
47 void graph_add_jsr( methodinfo *m, graphdata *gd, struct _sbr *sbr,int from,
49 void graph_add_cfg( methodinfo *m, graphdata *gd, int from, int to);
50 void graph_add_exceptions(methodinfo *m, codegendata *cd, graphdata *gd);
51 void graph_add_subs(methodinfo *m, graphdata *gd, struct _sbr *sbr);
52 void graph_add_edge( graphdata *gd, int from, int to );
53 /* Helper for graph_make_subs */
54 void graph_add_sub( methodinfo *m, graphdata *gd, int b_index,
55 graph_element *ret, bool *visited );
56 /* Helper for graph_get_first_* */
57 int graph_get_first_(graph_element *ge, graphiterator *i);
58 void transform_CFG(jitdata *, graphdata *);
60 #ifdef GRAPH_DEBUG_VERBOSE
61 void graph_print(lsradata *ls, graphdata *gd);
65 graphdata *graph_init(int basicblockcount) {
70 #ifdef GRAPH_DEBUG_CHECK
71 /* Remember basicblockcount, so Array Bound checks can be made */
72 gd->basicblockcount = basicblockcount;
75 gd->num_succ = DMNEW(int, basicblockcount);
76 gd->successor = DMNEW(graph_element *, basicblockcount);
78 gd->num_pred = DMNEW(int, basicblockcount);
79 gd->predecessor = DMNEW(graph_element *, basicblockcount);
81 for(i = 0; i < basicblockcount; i++) {
82 gd->num_succ[i] = gd->num_pred[i] = 0;
83 gd->successor[i] = NULL;
84 gd->predecessor[i] = NULL;
89 int graph_get_num_predecessor(graphdata *gd, int b_index) {
90 _GRAPH_CHECK_BOUNDS(b_index, 0, gd->basicblockcount);
91 return gd->num_pred[b_index];
94 int graph_get_num_successor(graphdata *gd, int b_index) {
95 _GRAPH_CHECK_BOUNDS(b_index, 0, gd->basicblockcount);
96 return gd->num_succ[b_index];
99 int graph_get_first_successor(graphdata *gd, int b_index, graphiterator *i) {
100 _GRAPH_CHECK_BOUNDS(b_index, 0, gd->basicblockcount);
101 return graph_get_first_(gd->successor[b_index], i);
104 int graph_get_first_predecessor(graphdata *gd, int b_index, graphiterator *i) {
105 _GRAPH_CHECK_BOUNDS(b_index, 0, gd->basicblockcount);
106 return graph_get_first_(gd->predecessor[b_index], i);
109 int graph_get_next(graphiterator *i) {
119 int graph_get_first_(graph_element *ge, graphiterator *i) {
120 if ( ((*i) = ge) == NULL)
126 bool graph_has_multiple_predecessors( graphdata *gd, int b_index) {
127 _GRAPH_CHECK_BOUNDS(b_index, 0, gd->basicblockcount);
128 return (gd->num_pred[b_index] > 1);
131 bool graph_has_multiple_successors( graphdata *gd, int b_index) {
132 _GRAPH_CHECK_BOUNDS(b_index, 0, gd->basicblockcount);
133 return (gd->num_succ[b_index] > 1);
136 void graph_add_edge( graphdata *gd, int from, int to ) {
141 /* prevent multiple similar edges from TABLESWITCH and */
143 b = graph_get_first_successor(gd, from, &i);
144 for( ; (b != -1) && ( b != to); b = graph_get_next(&i));
145 if (b != -1) /* edge from->to already existing */
148 /* We need two new graph_elements. One for successors and one for */
150 n = DMNEW(graph_element, 2);
153 n->next=gd->successor[from];
154 gd->successor[from]=n;
155 gd->num_succ[from]++;
157 n++; /* take next allocated graph_element */
159 n->next=gd->predecessor[to];
160 gd->predecessor[to]=n;
164 /* split the edge from BB from shown by iterator i wiht new_block */
165 void graph_split_edge(graphdata *gd, int from, graphiterator *i, int new_block) {
166 graphiterator i_pred;
170 /* i->value is the BB index of the "old" successor */
172 /* search for iterator showing predecessor edge from BB succ back to */
174 l = graph_get_first_predecessor(gd, succ, &i_pred);
175 for(; (l != -1) && (l != from); l = graph_get_next(&i_pred));
176 _GRAPH_ASSERT(l == from);
178 /* change CFG entries */
179 (*i)->value = new_block;
180 i_pred->value = new_block;
182 /* and insert the CFG successor and predecesser entries for new_block */
183 /* 2 entries needed */
184 n = DMNEW(graph_element, 2);
185 /* make the successor entry for new_block */
187 n->next = gd->successor[new_block];
188 gd->successor[new_block] = n;
189 gd->num_succ[new_block]++;
192 /* make the predecessor entry for new_block */
194 n->next = gd->predecessor[new_block];
195 gd->predecessor[new_block] = n;
196 gd->num_pred[new_block]++;
199 /***********************************************
200 Generate the Control Flow Graph
201 ( pred,succ,num_pred of lsradata structure)
202 ************************************************/
203 void graph_make_cfg(jitdata *jd,graphdata *gd) {
206 int high, low, count;
209 struct _sbr sbr; /* list of subroutines, sorted by header */
222 /* Add edge from new Basic Block 0 (parameter initialization) */
223 graph_add_edge(gd, 0, 1);
226 while (b_index < m->basicblockcount ) {
227 if (m->basicblocks[b_index].flags >= BBREACHED) {
228 fall_through = false;
230 if ((len = m->basicblocks[b_index].icount)) {
231 /* set ip to last non NOP instruction */
232 ip = m->basicblocks[b_index].iinstr +
233 m->basicblocks[b_index].icount -1;
234 while ((len>0) && (ip->opc == ICMD_NOP)) {
238 /* block contains instructions */
239 switch (ip->opc) { /* check type of last instruction */
247 /* graph_add_cfg(m, gd, b_index, m->basicblockcount); */
248 break; /* function returns -> end of graph */
277 case ICMD_IF_ACMPNE: /* branch -> add next block */
279 /* graph_add_cfg(m, gd, b_index, b_index+1); */
280 /* fall throu -> add branch target */
283 graph_add_cfg(m, gd, b_index, m->basicblockindex[ip->op1]);
285 graph_add_cfg(m, gd, b_index, b_index+1);
286 break; /* visit branch (goto) target */
288 case ICMD_TABLESWITCH: /* switch statement */
291 graph_add_cfg(m, gd, b_index, m->basicblockindex[*s4ptr]);
298 count = (high-low+1);
300 while (--count >= 0) {
302 graph_add_cfg(m, gd, b_index,
303 m->basicblockindex[*s4ptr]);
307 case ICMD_LOOKUPSWITCH: /* switch statement */
310 graph_add_cfg(m, gd, b_index, m->basicblockindex[*s4ptr]);
315 while (--count >= 0) {
316 graph_add_cfg(m, gd, b_index,
317 m->basicblockindex[s4ptr[1]]);
323 graph_add_jsr(m, gd, &sbr, b_index, m->basicblockindex[ip->op1]);
330 graph_add_cfg(m, gd, b_index, b_index + 1 );
332 } /* switch (ip->opc)*/
333 } /* if (m->basicblocks[blockIndex].icount) */
334 } /* if (m->basicblocks[b_index].flags >= BBREACHED) */
336 } /* while (b_index < m->basicblockcount ) */
338 /* add subroutines before exceptions! They "destroy" the CFG */
339 graph_add_subs(m, gd, &sbr);
340 graph_add_exceptions(m, cd, gd);
341 transform_CFG(jd, gd);
342 #ifdef GRAPH_DEBUG_VERBOSE
348 /*****************************************************************
349 add Edges from guarded Areas to Exception handlers in the CFG
350 *****************************************************************/
351 void graph_add_exceptions(methodinfo *m, codegendata *cd, graphdata *gd) {
354 /* add cfg edges from all bb of a try block to the start of the according */
355 /* exception handler to ensure the right order after depthfirst search */
357 ex=jd->exceptiontable;
358 #ifdef GRAPH_DEBUG_VERBOSE
360 printf("ExTable(%i): ", jd->exceptiontablelength);
363 for (; ex != NULL; ex = ex->down) {
365 #ifdef GRAPH_DEBUG_VERBOSE
367 printf("[%i-%i]->%i ",ex->start->nr, ex->end->nr,
370 _GRAPH_ASSERT(ex->handler->nr < m->basicblockcount);
371 _GRAPH_ASSERT(m->basicblocks[ex->handler->nr].flags >= BBREACHED);
372 _GRAPH_ASSERT(ex->start->nr <= ex->end->nr);
374 /* loop all valid Basic Blocks of the guarded area and add CFG edges */
375 /* to the appropriate handler */
376 for (i=ex->start->nr; (i <= ex->end->nr) &&
377 (i < m->basicblockcount); i++)
378 if (m->basicblocks[i].flags >= BBREACHED)
379 graph_add_cfg(m, gd, i, ex->handler->nr);
381 #ifdef GRAPH_DEBUG_VERBOSE
387 /**************************************************
388 Add subroutines from ls->sbr list to CFG
389 **************************************************/
390 void graph_add_subs(methodinfo *m, graphdata *gd, struct _sbr *sbr) {
394 #ifdef GRAPH_DEBUG_VERBOSE
398 visited = (bool *)DMNEW(int, m->basicblockcount + 1);
399 for (i=0; i <= m->basicblockcount; i++) visited[i] = false;
400 for (_sbr = sbr->next; _sbr != NULL; _sbr=_sbr->next) {
401 #ifdef GRAPH_DEBUG_VERBOSE
402 if (compileverbose) {
403 printf("Subroutine Header: %3i Return Adresses:",_sbr->header);
404 for (ret = _sbr->ret; ret != NULL; ret = ret->next)
405 printf(" %3i", ret->value);
409 graph_add_sub( m, gd, _sbr->header, _sbr->ret, visited );
414 /******************************************************************
415 Add the CFG Edge into next und succ
416 ******************************************************************/
417 void graph_add_cfg( methodinfo *m, graphdata *gd, int from, int to) {
419 /* ignore Empty, Deleted,... Basic Blocks as target */
420 /* TODO: Setup BasicBlock array before to avoid this */
421 /* best together with using the basicblock list, so lsra works */
422 /* with opt_loops, too */
423 for (;(to < m->basicblockcount) && (m->basicblocks[to].flags < BBREACHED);
426 /* add one to from and to, so the to be inserted Basic Block 0 is */
427 /* already regarded */
428 graph_add_edge( gd, from + 1, to + 1);
431 /*******************************************************************
432 Remember Subroutine "jumps" in ls->sbr and add the CFG Edge of the
433 "jump" into succ and pred
434 *******************************************************************/
435 void graph_add_jsr( methodinfo *m, graphdata *gd, struct _sbr *sbr, int from,
437 struct _sbr *_sbr, *n;
440 /* ignore Empty, Deleted,... Basic Blocks as target */
441 /* TODO: Setup BasicBlock array before to avoid this */
442 /* best together with using the basicblock list, so lsra works */
443 /* with opt_loops, too */
444 for (; (to < m->basicblockcount) && (m->basicblocks[to].flags < BBREACHED);
446 _GRAPH_ASSERT( to != m->basicblockcount );
448 graph_add_cfg(m, gd, from, to);
450 /* from + 1 ist the return Basic Block Index */
451 for (from++; (from < m->basicblockcount) &&
452 (m->basicblocks[from].flags < BBREACHED); from++);
453 _GRAPH_ASSERT(from != m->basicblockcount);
455 /* add subroutine info in ls->sbr.next */
457 /* search for right place to insert */
458 for (_sbr = sbr; (_sbr->next != NULL) && (_sbr->next->header < to);
461 if ((_sbr->next!= NULL) && (_sbr->next->header == to)) {
462 /* Entry for this sub already exist */
465 /* make new Entry and insert it in ls->sbr.next */
466 n = DNEW( struct _sbr );
470 n->next = _sbr->next;
476 /* now insert return adress in sbr->ret */
477 ret = DNEW(graph_element);
479 ret->next = _sbr->ret;
483 /**************************************************
484 Add a subroutine to CFG
485 **************************************************/
486 void graph_add_sub(methodinfo *m, graphdata *gd, int b_index,
487 graph_element *ret, bool *visited ) {
494 /* break at virtual End Block */
495 if (b_index != m->basicblockcount) {
496 visited[b_index] = true;
499 if (m->basicblocks[b_index].flags < BBREACHED)
501 if (!next_block && !(m->basicblocks[b_index].icount))
505 ip = m->basicblocks[b_index].iinstr +
506 m->basicblocks[b_index].icount - 1;
508 if (ip->opc == ICMD_JSR) /* nested Subroutines */
513 if (ip->opc == ICMD_RET) {
514 /* subroutine return found -> add return adresses to CFG */
515 for (l = ret; l != NULL; l = l->next)
516 graph_add_cfg( m, gd, b_index, l->value);
517 } else { /* follow CFG */
518 s = graph_get_first_successor(gd, b_index, &i);
519 for(; s != -1; s = graph_get_next(&i))
521 graph_add_sub( m, gd, l->value, ret, visited);
523 } else { /* fall through to next block */
524 if (b_index + 1 < m->basicblockcount)
525 if (!visited[b_index + 1])
526 graph_add_sub(m, gd, b_index + 1, ret, visited);
531 /*****************************************************************
532 Sort Basic Blocks using Depth First search in reverse post order
533 In: ls->basicblockcount, ls->basicblocks[], gd->
534 Out: ls->sorted, ls->sorted_rev
535 *****************************************************************/
537 void graph_DFS(lsradata *ls, graphdata *gd) {
545 ls->sorted = DMNEW(int, ls->basicblockcount);
546 ls->sorted_rev = DMNEW(int, ls->basicblockcount);
548 stack = DMNEW( int, ls->basicblockcount);
549 visited = (int *)DMNEW( bool, ls->basicblockcount);
550 for (i = 0; i < ls->basicblockcount; i++) {
553 ls->sorted_rev[i]=-1;
556 stack[0] = 0; /* start with Block 0 */
558 /* Start Block is handled right and can be put in sorted */
559 visited[0] = graph_get_num_predecessor(gd , 0);
562 while (not_finished) {
563 while (stack_top != 0) {
565 i = stack[stack_top];
568 s = graph_get_first_successor(gd, i, &iter);
569 for (; s != -1; s = graph_get_next(&iter)) {
571 if (visited[s] == graph_get_num_predecessor(gd, s)) {
572 /* push the node on the stack, only if all ancestors have */
574 stack[stack_top] = s;
579 not_finished = false;
580 for (i=1; i < ls->basicblockcount; i++) {
581 /* search for visited blocks, which have not reached the num_pre */
582 /* and put them on the stack -> happens with backedges */
583 num_pred = graph_get_num_predecessor(gd, i);
584 if ((visited[i] != 0) && (visited[i] < num_pred)) {
585 stack[stack_top] = i;
587 visited[i] = num_pred;
594 for(i = 0; i < ls->basicblockcount; i++)
595 if (ls->sorted[i] != -1)
596 ls->sorted_rev[ls->sorted[i]] = i;
600 void graph_init_basicblock( basicblock *bptr, int b_index) {
604 bptr->type = BBTYPE_STD;
605 bptr->flags = BBFINISHED;
606 bptr->instack = NULL;
607 bptr->outstack = NULL;
610 bptr->branchrefs = NULL;
615 /*********************************************************************+
616 After the "original" CFG has been created, it has to be adopted for
617 SSA. (inluding insertion of new Basic Blocks)
619 TODO: Do not insert blocks right now - just adopt the call graph!
620 After the phi moves are determined create only the needed Blocks
621 **********************************************************************/
622 void transform_CFG(jitdata *jd, graphdata *gd) {
623 int i, j, k, n, num_new_blocks;
626 stackptr in, out, new_stack;
629 struct graph_element **successor;
631 struct graph_element **predecessor;
642 /* with SSA a new Basic Block 0 is inserted for parameter initialisation */
643 /* & look for nodes with multiple successors leading to nodes with */
644 /* multiple predecessor -> if found insert a new block between to split */
645 /* this edge. As first step count how many blocks have to be inserted. */
648 for(i = 0; i< m->basicblockcount + 1; i++) {
649 if (graph_has_multiple_successors(gd, i)) {
650 k = graph_get_first_successor(gd, i, &iter);
651 for(; k != -1; k = graph_get_next(&iter)) {
652 /* check for successor blocks with more than one */
653 /* predecessor. For each found incremet num_new_blocks */
654 if (graph_has_multiple_predecessors(gd, k))
660 /* increase now basicblockcount accordingly. */
661 ls->basicblockcount = m->basicblockcount + num_new_blocks + 1;
663 ls->basicblocks = DMNEW(basicblock *, ls->basicblockcount);
664 /* copy Basic Block References to ls->basicblocks */
665 for(i = 0; i< m->basicblockcount; i++) {
666 ls->basicblocks[i+1] = &(m->basicblocks[i]);
667 ls->basicblocks[i+1]->nr = i+1;
670 /* Create new Basic Blocks: 0, [m->basicblockcount..ls->basicblockcount[ */
671 /* num_new_blocks + 1 have to be inserted*/
672 tmp = DMNEW( basicblock, num_new_blocks + 1);
673 ls->basicblocks[0] = tmp;
674 graph_init_basicblock( tmp, 0);
676 ls->basicblocks[0]->next = ls->basicblocks[1];
678 if (ls->basicblockcount > m->basicblockcount + 1) {
679 /* new Blocks have to be inserted */
680 num_succ = DMNEW(int, ls->basicblockcount);
681 successor = DMNEW(graph_element *, ls->basicblockcount);
683 num_pred = DMNEW(int, ls->basicblockcount);
684 predecessor = DMNEW(graph_element *, ls->basicblockcount);
686 /* regard the + 1 for the already regarded new BB 0 */
687 /* So recreate ls->var_def */
688 var_def = DMNEW(int *, ls->basicblockcount);
689 for(i = 0; i < m->basicblockcount + 1; i++) {
690 var_def[i] = ls->var_def[i];
691 num_succ[i] = gd->num_succ[i];
692 num_pred[i] = gd->num_pred[i];
693 successor[i] = gd->successor[i];
694 predecessor[i] = gd->predecessor[i];
696 for(i = m->basicblockcount + 1; i < ls->basicblockcount; i++) {
697 var_def[i] = bv_new(ls->max_vars);
698 graph_init_basicblock( tmp, i);
699 ls->basicblocks[i] = tmp;
705 predecessor[i] = NULL;
707 ls->var_def = var_def;
708 gd->num_succ = num_succ;
709 gd->num_pred = num_pred;
710 gd->successor = successor;
711 gd->predecessor = predecessor;
712 #ifdef GRAPH_DEBUG_CHECK
713 /* Remember basicblockcount, so Array Bound checks can be made */
714 gd->basicblockcount = ls->basicblockcount;
718 /* Now Split the edges */
719 num_new_blocks = m->basicblockcount + 1; /* first free new block index */
720 for(i = 0; i < m->basicblockcount + 1; i++) {
721 if (graph_has_multiple_successors(gd, i)) {/* more than one successor */
722 j = graph_get_first_successor( gd, i, &iter);
723 for(; j != -1; j = graph_get_next(&iter)) {
724 if (graph_has_multiple_predecessors(gd, j)) {
725 /* and more than one predecessor -> split edge */
726 _GRAPH_ASSERT(num_new_blocks < ls->basicblockcount);
728 /* insert new Block num_new_blocks */
730 /* splite the edge from BB i to j with the new BB */
731 /* num_new_blocks ( i->j --> i->nnb->j)*/
732 /* iter_succ shows the edge from i to j */
733 graph_split_edge(gd, i, &iter, num_new_blocks);
735 ls->basicblocks[num_new_blocks]->indepth =
736 ls->basicblocks[i]->outdepth;
737 out = ls->basicblocks[i]->outstack;
738 ls->basicblocks[num_new_blocks]->instack = in = NULL;
740 if (ls->basicblocks[num_new_blocks]->indepth > 0)
741 new_stack = DMNEW( stackelement,
742 ls->basicblocks[num_new_blocks]->indepth);
743 for(n=0; n<ls->basicblocks[num_new_blocks]->indepth; n++) {
747 in->prev = new_stack++;
750 in->type = out->type;
751 in->varkind = STACKVAR;
758 ls->basicblocks[num_new_blocks]->instack = in;
763 /* Create Outstack */
764 ls->basicblocks[num_new_blocks]->outstack =
765 ls->basicblocks[num_new_blocks]->instack;
766 ls->basicblocks[num_new_blocks]->outdepth =
767 ls->basicblocks[num_new_blocks]->indepth;
769 _GRAPH_ASSERT(ls->basicblocks[num_new_blocks]->outdepth ==
770 ls->basicblocks[j]->indepth );
773 /* decrease nr temporarly, because ssa_set_interface*/
774 /* adds 1 since it is called from stack.c, where there is */
775 /* no new BB 0 inserted like now */
776 ls->basicblocks[num_new_blocks]->nr--;
777 ssa_set_interface(cd, ls, ls->basicblocks[num_new_blocks]);
778 ls->basicblocks[num_new_blocks]->nr++;
786 void transform_BB(jitdata *jd, graphdata *gd) {
789 basicblock *last_block;
798 /* the "real" last Block is always an empty block */
799 /* so take the one before, to insert new blocks after it */
800 last_block = &(m->basicblocks[m->basicblockcount - 1]);
801 _GRAPH_ASSERT(last_block->next->next == NULL);
802 _GRAPH_ASSERT(last_block->next->flags <= BBREACHED);
803 last_block->next->nr = ls->basicblockcount;
805 /* look through new blocks */
806 for(i = m->basicblockcount + 1; i < ls->basicblockcount ; i++) {
807 /* if a phi move happens at this block, we need this block */
808 /* if not, remove him from the CFG */
809 if (ls->num_phi_moves[i] > 0) {
810 /* i can only have one predecessor and one successor! */
811 _GRAPH_ASSERT( graph_has_multiple_predecessors(gd,i) == false);
812 _GRAPH_ASSERT( graph_has_multiple_successors(gd,i) == false);
814 succ = graph_get_first_successor(gd, i, &iter);
815 pred = graph_get_first_predecessor(gd, i, &iter);
817 /* set ip to last instruction */
818 len = ls->basicblocks[pred]->icount;
819 ip = ls->basicblocks[pred]->iinstr + len - 1;
820 while ((len>0) && (ip->opc == ICMD_NOP)) {
826 /* with JSR there can not be multiple successors */
827 _GRAPH_ASSERT(ip->opc != ICMD_JSR);
828 /* If the return Statment has more successors and */
829 /* one of these has more predecessor, we are in */
830 /* troubles - one would have to insert a new Block */
831 /* after the one which executes the ICMD_JSR */
832 /* !!TODO!! if subroutines will not be inlined */
833 _GRAPH_ASSERT(ip->opc != ICMD_RET);
835 /* link new block into basicblocks list */
836 /* if edge to split is the "fallthrough" path of the */
837 /* conditional, then link the new block inbetween */
838 /* and generate no ICMD */
839 /* else if edge to split is the branch, generate a */
840 /* ICMD_GOTO and add new BB at and of BB List */
841 if ((ls->basicblocks[pred]->next == ls->basicblocks[succ])
842 && (ip->opc != ICMD_LOOKUPSWITCH)
843 && (ip->opc != ICMD_TABLESWITCH)
844 && (ip->opc != ICMD_GOTO)) {
845 /* GOTO, *SWITCH have no fallthrough path */
847 /* link into fallthrough path */
850 ls->basicblocks[i]->next =
851 ls->basicblocks[pred]->next;
852 ls->basicblocks[pred]->next =
854 /* generate no instructions */
855 ls->basicblocks[i]->icount = 1;
856 ls->basicblocks[i]->iinstr = NEW(instruction);
857 ls->basicblocks[i]->iinstr[0].opc = ICMD_NOP;
859 /* Block i is in the Branch path */
860 /* link Block at the end */
861 ls->basicblocks[i]->next =last_block->next;
862 last_block->next = ls->basicblocks[i];
863 last_block = ls->basicblocks[i];
865 /* change the Branch Target to BB i */
870 case ICMD_LOOKUPSWITCH:
875 tptr = (void **) ip->target;
876 if ((basicblock*)tptr[0] == ls->basicblocks[succ]) {
877 /* target found -> change*/
878 tptr[0] = ls->basicblocks[i];
882 l = s4ptr[0]; /* default */
883 k = s4ptr[1]; /* count */
889 if ((basicblock*)tptr[0] == ls->basicblocks[succ])
891 /* target found -> change */
892 tptr[0] = ls->basicblocks[i];
897 case ICMD_TABLESWITCH:
902 tptr = (void **) ip->target;
905 l = s4ptr[1]; /* low */
906 k = s4ptr[2]; /* high */
910 if ((basicblock*)tptr[0] == ls->basicblocks[succ])
912 /* target found -> change*/
913 tptr[0] = ls->basicblocks[i];
918 if ((basicblock*)tptr[0] == ls->basicblocks[succ])
920 /* target found -> change*/
921 tptr[0] = ls->basicblocks[i];
956 _GRAPH_ASSERT(ip->target == ls->basicblocks[succ]);
957 ip->target = ls->basicblocks[i];
960 /* Exception Edge to split */
961 /* not handled by now -> fallback to regalloc */
965 /* Generate the ICMD_GOTO */
966 ls->basicblocks[i]->icount = 1;
967 ls->basicblocks[i]->iinstr =
969 ls->basicblocks[i]->iinstr->opc =
971 ls->basicblocks[i]->iinstr->target =
972 ls->basicblocks[succ];
973 ls->basicblocks[i]->iinstr->op1 = succ;
975 ls->basicblocks[i]->iinstr[0].dst =
976 ls->basicblocks[i]->outstack;
981 #ifdef GRAPH_DEBUG_VERBOSE
982 void graph_print(lsradata *ls, graphdata *gd) {
985 printf("graph_print: basicblockcount %3i\n", ls->basicblockcount);
988 for(i = 0; i < ls->basicblockcount; i++) {
990 j = graph_get_first_successor(gd, i, &iter);
991 for(; j != -1; j = graph_get_next(&iter)) {
997 for(i = 0; i < ls->basicblockcount; i++) {
999 j = graph_get_first_predecessor(gd, i, &iter);
1000 for(; j != -1; j = graph_get_next(&iter)) {
1011 * These are local overrides for various environment variables in Emacs.
1012 * Please do not remove this and leave it at the end of the file, where
1013 * Emacs will automagically detect them.
1014 * ---------------------------------------------------------------------
1017 * indent-tabs-mode: t