1 /* src/vm/jit/optimizing/graph.c - CFG
3 Copyright (C) 2005, 2006, 2008
4 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
6 This file is part of CACAO.
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.
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.
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
29 #include "mm/memory.h"
31 #include "toolbox/bitvector.h"
33 #include "vm/jit/jit.hpp"
35 #include "vm/jit/optimizing/lsra.h"
36 #include "vm/jit/optimizing/ssa.h"
37 #include "vm/jit/optimizing/graph.h"
39 #ifdef GRAPH_DEBUG_VERBOSE
40 #include "vm/options.h"
43 /* Helpers for graph_make_cfg */
44 void graph_add_cfg( jitdata *jd, graphdata *gd, basicblock *, basicblock *);
45 void graph_add_exceptions(jitdata *jd, graphdata *gd);
46 void graph_add_edge( graphdata *gd, int from, int to );
48 /* Helper for graph_get_first_* */
49 int graph_get_first_(graph_element *ge, graphiterator *i);
50 void transform_CFG(jitdata *, graphdata *);
52 void graph_phi_moves(jitdata *jd, basicblock *bptr, basicblock *dst_goto);
54 #ifdef GRAPH_DEBUG_VERBOSE
55 void graph_print(lsradata *ls, graphdata *gd);
59 graphdata *graph_init(int basicblockcount) {
64 #ifdef GRAPH_DEBUG_CHECK
65 /* Remember basicblockcount, so Array Bound checks can be made */
66 gd->basicblockcount = basicblockcount;
69 gd->num_succ = DMNEW(int, basicblockcount);
70 gd->successor = DMNEW(graph_element *, basicblockcount);
72 gd->num_pred = DMNEW(int, basicblockcount);
73 gd->predecessor = DMNEW(graph_element *, basicblockcount);
75 for(i = 0; i < basicblockcount; i++) {
76 gd->num_succ[i] = gd->num_pred[i] = 0;
77 gd->successor[i] = NULL;
78 gd->predecessor[i] = NULL;
83 int graph_get_num_predecessor(graphdata *gd, int b_index) {
84 _GRAPH_CHECK_BOUNDS(b_index, 0, gd->basicblockcount);
85 return gd->num_pred[b_index];
88 int graph_get_num_successor(graphdata *gd, int b_index) {
89 _GRAPH_CHECK_BOUNDS(b_index, 0, gd->basicblockcount);
90 return gd->num_succ[b_index];
93 int graph_get_first_successor(graphdata *gd, int b_index, graphiterator *i) {
94 _GRAPH_CHECK_BOUNDS(b_index, 0, gd->basicblockcount);
95 return graph_get_first_(gd->successor[b_index], i);
98 int graph_get_first_predecessor(graphdata *gd, int b_index, graphiterator *i) {
99 _GRAPH_CHECK_BOUNDS(b_index, 0, gd->basicblockcount);
100 return graph_get_first_(gd->predecessor[b_index], i);
103 int graph_get_next(graphiterator *i) {
113 int graph_get_first_(graph_element *ge, graphiterator *i) {
114 if ( ((*i) = ge) == NULL)
120 bool graph_has_multiple_predecessors( graphdata *gd, int b_index) {
121 _GRAPH_CHECK_BOUNDS(b_index, 0, gd->basicblockcount);
122 return (gd->num_pred[b_index] > 1);
125 bool graph_has_multiple_successors( graphdata *gd, int b_index) {
126 _GRAPH_CHECK_BOUNDS(b_index, 0, gd->basicblockcount);
127 return (gd->num_succ[b_index] > 1);
130 void graph_add_edge( graphdata *gd, int from, int to ) {
135 /* prevent multiple similar edges from TABLESWITCH and */
137 b = graph_get_first_successor(gd, from, &i);
138 for( ; (b != -1) && ( b != to); b = graph_get_next(&i));
139 if (b != -1) /* edge from->to already existing */
142 /* We need two new graph_elements. One for successors and one for */
144 n = DMNEW(graph_element, 2);
147 n->next=gd->successor[from];
148 gd->successor[from]=n;
149 gd->num_succ[from]++;
151 n++; /* take next allocated graph_element */
153 n->next=gd->predecessor[to];
154 gd->predecessor[to]=n;
158 /* split the edge from BB from shown by iterator i with new_block */
159 void graph_split_edge(graphdata *gd, int from, graphiterator *i, int new_block) {
160 graphiterator i_pred;
164 /* i->value is the BB index of the "old" successor */
168 /* search for iterator showing predecessor edge from BB succ back to */
171 l = graph_get_first_predecessor(gd, succ, &i_pred);
172 for(; (l != -1) && (l != from); l = graph_get_next(&i_pred));
173 _GRAPH_ASSERT(l == from);
175 /* change CFG entries */
177 (*i)->value = new_block;
178 i_pred->value = new_block;
180 /* and insert the CFG successor and predecesser entries for new_block */
181 /* 2 entries needed */
183 n = DMNEW(graph_element, 2);
185 /* make the successor entry for new_block */
188 n->next = gd->successor[new_block];
189 gd->successor[new_block] = n;
190 gd->num_succ[new_block]++;
192 /* make the predecessor entry for new_block */
196 n->next = gd->predecessor[new_block];
197 gd->predecessor[new_block] = n;
198 gd->num_pred[new_block]++;
201 /***********************************************
202 Generate the Control Flow Graph
203 ( pred,succ,num_pred of lsradata structure)
204 ************************************************/
205 void graph_make_cfg(jitdata *jd,graphdata *gd) {
207 lookup_target_t *lookup;
208 branch_target_t *table;
221 /* Add edge from new Basic Block 0 (parameter initialization) */
222 graph_add_edge(gd, 0, 1);
224 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
225 if (bptr->flags >= BBREACHED) {
226 if ((len = bptr->icount)) {
227 /* set iptr to last non NOP instruction */
228 iptr = bptr->iinstr + bptr->icount -1;
229 while ((len>0) && (iptr->opc == ICMD_NOP)) {
233 /* block contains instructions */
234 switch (iptr->opc) { /* check type of last instruction */
242 break; /* function returns -> end of graph */
271 case ICMD_IF_ACMPNE: /* branch -> add next block */
272 /* Add branch target */
273 graph_add_cfg(jd, gd, bptr, iptr->dst.block);
274 /* Add fall through path */
275 graph_add_cfg(jd, gd, bptr, bptr->next);
280 graph_add_cfg(jd, gd, bptr, iptr->dst.block);
281 break; /* visit branch (goto) target */
283 case ICMD_TABLESWITCH: /* switch statement */
284 table = iptr->dst.table;
285 l = iptr->sx.s23.s2.tablelow;
286 i = iptr->sx.s23.s3.tablehigh;
289 /* Add default target */
291 graph_add_cfg(jd, gd, bptr, table[0].block);
295 graph_add_cfg(jd, gd, bptr, table->block);
300 case ICMD_LOOKUPSWITCH: /* switch statement */
301 lookup = iptr->dst.lookup;
302 i = iptr->sx.s23.s2.lookupcount;
305 graph_add_cfg(jd, gd, bptr, lookup->target.block);
309 graph_add_cfg(jd, gd, bptr, iptr->sx.s23.s3.lookupdefault.block);
321 graph_add_cfg(jd, gd, bptr, bptr + 1 );
323 } /* switch (iptr->opc)*/
324 } /* if (bptr->icount) */
325 } /* if (bptr->flags >= BBREACHED) */
326 } /* for (bptr = ...; bptr != NULL; bptr = bptr->next) */
328 graph_add_exceptions(jd, gd);
329 transform_CFG(jd, gd);
331 #ifdef GRAPH_DEBUG_VERBOSE
337 /*****************************************************************
338 add Edges from guarded Areas to Exception handlers in the CFG
339 *****************************************************************/
340 void graph_add_exceptions(jitdata *jd, graphdata *gd) {
343 raw_exception_entry *ex;
348 /* add cfg edges from all bb of a try block to the start of the according */
349 /* exception handler to ensure the right order after depthfirst search */
351 ex=jd->exceptiontable;
353 #ifdef GRAPH_DEBUG_VERBOSE
355 printf("ExTable(%i): ", jd->exceptiontablelength);
358 for (; ex != NULL; ex = ex->down) {
360 #ifdef GRAPH_DEBUG_VERBOSE
362 printf("[%i-%i]->%i ",ex->start->nr, ex->end->nr,
366 _GRAPH_ASSERT(ex->handler->nr < jd->new_basicblockcount);
367 _GRAPH_ASSERT(ex->handler->flags >= BBREACHED);
368 _GRAPH_ASSERT(ex->start->nr <= ex->end->nr);
370 /* loop all valid Basic Blocks of the guarded area and add CFG edges */
371 /* to the appropriate handler */
372 for (bptr = ex->start; (bptr != NULL) && (bptr != ex->end); bptr = bptr->next)
373 if (bptr->flags >= BBREACHED)
374 graph_add_cfg(jd, gd, bptr, ex->handler);
376 _GRAPH_ASSERT((bptr != NULL)
377 && ((bptr->flags >=BBREACHED) || (bptr == ex->end)));
379 #ifdef GRAPH_DEBUG_VERBOSE
387 /******************************************************************
388 Add the CFG Edge into next und succ
389 ******************************************************************/
390 void graph_add_cfg( jitdata *jd, graphdata *gd, basicblock *from,
393 /* ignore Empty, Deleted,... Basic Blocks as target */
394 /* TODO: Setup BasicBlock array before to avoid this */
395 /* best together with using the basicblock list, so lsra works */
396 /* with opt_loops, too */
398 for (; (to != NULL) && (to->flags < BBREACHED); to = to->next);
400 _GRAPH_ASSERT(to != NULL);
403 /* add one to from and to, so the to be inserted Basic Block 0 is */
404 /* already regarded */
405 graph_add_edge( gd, from->nr + 1, to->nr + 1);
409 /*****************************************************************
410 Sort Basic Blocks using Depth First search in reverse post order
411 In: ls->basicblockcount, ls->basicblocks[], gd->
412 Out: ls->sorted, ls->sorted_rev
413 *****************************************************************/
415 void graph_DFS(lsradata *ls, graphdata *gd) {
423 ls->sorted = DMNEW(int, ls->basicblockcount);
424 ls->sorted_rev = DMNEW(int, ls->basicblockcount);
426 stack = DMNEW( int, ls->basicblockcount);
427 visited = (int *)DMNEW( bool, ls->basicblockcount);
428 for (i = 0; i < ls->basicblockcount; i++) {
431 ls->sorted_rev[i]=-1;
434 stack[0] = 0; /* start with Block 0 */
436 /* Start Block is handled right and can be put in sorted */
437 visited[0] = graph_get_num_predecessor(gd , 0);
440 while (not_finished) {
441 while (stack_top != 0) {
443 i = stack[stack_top];
446 s = graph_get_first_successor(gd, i, &iter);
447 for (; s != -1; s = graph_get_next(&iter)) {
449 if (visited[s] == graph_get_num_predecessor(gd, s)) {
450 /* push the node on the stack, only if all ancestors have */
452 stack[stack_top] = s;
457 not_finished = false;
458 for (i=1; i < ls->basicblockcount; i++) {
459 /* search for visited blocks, which have not reached the num_pre */
460 /* and put them on the stack -> happens with backedges */
461 num_pred = graph_get_num_predecessor(gd, i);
462 if ((visited[i] != 0) && (visited[i] < num_pred)) {
463 stack[stack_top] = i;
465 visited[i] = num_pred;
472 for(i = 0; i < ls->basicblockcount; i++)
473 if (ls->sorted[i] != -1)
474 ls->sorted_rev[ls->sorted[i]] = i;
478 void graph_init_basicblock(jitdata *jd, basicblock *bptr, int b_index) {
482 bptr->type = BBTYPE_STD;
483 bptr->flags = BBFINISHED;
485 bptr->outvars = NULL;
488 bptr->branchrefs = NULL;
491 bptr->method = jd->m;
494 /*********************************************************************+
495 After the "original" CFG has been created, it has to be adopted for
496 SSA. (inluding insertion of new Basic Blocks - edge splitting)
498 **********************************************************************/
499 void transform_CFG(jitdata *jd, graphdata *gd) {
500 int i, j, k, n, num_new_blocks;
502 basicblock *tmp, *bptr;
503 s4 *in, *out, *new_in_stack, *new_out_stack;
506 struct graph_element **successor;
508 struct graph_element **predecessor;
519 /* with SSA a new Basic Block 0 is inserted for parameter initialisation */
520 /* & look for nodes with multiple successors leading to nodes with */
521 /* multiple predecessor -> if found insert a new block between to split */
522 /* this edge. As first step count how many blocks have to be inserted. */
525 for(i = 0; i< jd->basicblockcount + 1; i++) {
526 if (graph_has_multiple_successors(gd, i)) {
527 k = graph_get_first_successor(gd, i, &iter);
528 for(; k != -1; k = graph_get_next(&iter)) {
529 /* check for successor blocks with more than one */
530 /* predecessor. For each found incremet num_new_blocks */
531 if (graph_has_multiple_predecessors(gd, k))
537 /* increase now basicblockcount accordingly. */
538 ls->basicblockcount = jd->basicblockcount + num_new_blocks;
540 ls->basicblocks = DMNEW(basicblock *, ls->basicblockcount);
541 for(i = 0; i< ls->basicblockcount; i++)
542 ls->basicblocks[i] = NULL;
544 /* copy Basic Block References to ls->basicblocks */
546 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
547 _GRAPH_ASSERT(bptr->nr < jd->basicblockcount);
548 ls->basicblocks[bptr->nr + 1] = bptr;
549 bptr->nr = bptr->nr+1;
552 /* Create new Basic Blocks:
553 0, [jd->basicblockcount..ls->basicblockcount[ */
554 /* num_new_blocks have to be inserted*/
556 tmp = DMNEW( basicblock, num_new_blocks);
557 ls->basicblocks[0] = tmp;
558 graph_init_basicblock( jd, tmp, 0);
560 ls->basicblocks[0]->next = ls->basicblocks[1];
562 if (ls->basicblockcount > jd->basicblockcount + 1) {
564 /* new Blocks have to be inserted */
566 num_succ = DMNEW(int, ls->basicblockcount);
567 successor = DMNEW(graph_element *, ls->basicblockcount);
569 num_pred = DMNEW(int, ls->basicblockcount);
570 predecessor = DMNEW(graph_element *, ls->basicblockcount);
572 /* regard the + 1 for the already inserted new BB 0 */
573 /* So recreate ls->var_def */
575 var_def = DMNEW(int *, ls->basicblockcount);
576 for(i = 0; i < jd->basicblockcount + 1; i++) {
577 var_def[i] = ls->var_def[i];
578 num_succ[i] = gd->num_succ[i];
579 num_pred[i] = gd->num_pred[i];
580 successor[i] = gd->successor[i];
581 predecessor[i] = gd->predecessor[i];
583 for(i = jd->basicblockcount + 1; i < ls->basicblockcount; i++) {
584 var_def[i] = bv_new(jd->varcount);
585 graph_init_basicblock( jd, tmp, i);
586 ls->basicblocks[i] = tmp;
592 predecessor[i] = NULL;
594 ls->var_def = var_def;
595 gd->num_succ = num_succ;
596 gd->num_pred = num_pred;
597 gd->successor = successor;
598 gd->predecessor = predecessor;
599 #ifdef GRAPH_DEBUG_CHECK
600 /* Remember basicblockcount, so Array Bound checks can be made */
601 gd->basicblockcount = ls->basicblockcount;
605 /* Now Split the edges */
607 num_new_blocks = jd->basicblockcount + 1; /* first free new block index */
608 for(i = 0; i < jd->basicblockcount + 1; i++) {
609 if (graph_has_multiple_successors(gd, i)) {/* more than one successor */
610 j = graph_get_first_successor( gd, i, &iter);
611 for(; j != -1; j = graph_get_next(&iter)) {
612 if (graph_has_multiple_predecessors(gd, j)) {
613 /* and more than one predecessor -> split edge */
614 _GRAPH_ASSERT(num_new_blocks < ls->basicblockcount);
616 /* insert new Block num_new_blocks */
618 /* splite the edge from BB i to j with the new BB */
619 /* num_new_blocks ( i->j --> i->nnb->j)*/
620 /* iter_succ shows the edge from i to j */
622 graph_split_edge(gd, i, &iter, num_new_blocks);
624 ls->basicblocks[num_new_blocks]->indepth =
625 ls->basicblocks[i]->outdepth;
626 out = ls->basicblocks[i]->outvars;
627 ls->basicblocks[num_new_blocks]->invars = in = NULL;
629 if (ls->basicblocks[num_new_blocks]->indepth > 0)
630 new_in_stack = DMNEW( s4,
631 ls->basicblocks[num_new_blocks]->indepth);
632 new_out_stack = DMNEW( s4,
633 ls->basicblocks[num_new_blocks]->indepth);
635 for(n=0; n<ls->basicblocks[num_new_blocks]->indepth; n++) {
636 new_in_stack[n] = out[n];
637 new_out_stack[n] = out[n];
639 ls->basicblocks[num_new_blocks]->invars = new_in_stack;
641 /* Create Outstack */
642 ls->basicblocks[num_new_blocks]->outvars =
644 ls->basicblocks[num_new_blocks]->outdepth =
645 ls->basicblocks[num_new_blocks]->indepth;
647 _GRAPH_ASSERT(ls->basicblocks[num_new_blocks]->outdepth ==
648 ls->basicblocks[j]->indepth );
657 void transform_BB(jitdata *jd, graphdata *gd) {
660 basicblock *last_block;
669 /* the "real" last Block is always an empty block */
670 /* so take the one before, to insert new blocks after it */
671 last_block = &(jd->basicblocks[jd->basicblockcount - 1]);
672 _GRAPH_ASSERT(last_block->next->next == NULL);
673 _GRAPH_ASSERT(last_block->next->flags <= BBREACHED);
674 last_block->next->nr = ls->basicblockcount;
676 /* look through new blocks */
677 for(n = jd->basicblockcount + 1; n < ls->basicblockcount ; n++) {
678 /* if a phi move happens at this block, we need this block */
679 /* if not, remove him from the CFG */
680 if (ls->num_phi_moves[n] > 0) {
681 /* i can only have one predecessor and one successor! */
682 _GRAPH_ASSERT( graph_has_multiple_predecessors(gd, n) == false);
683 _GRAPH_ASSERT( graph_has_multiple_successors(gd, n) == false);
685 succ = graph_get_first_successor(gd, n, &iter);
686 pred = graph_get_first_predecessor(gd, n, &iter);
688 /* set iptr to last instruction */
689 len = ls->basicblocks[pred]->icount;
690 iptr = ls->basicblocks[pred]->iinstr + len - 1;
691 while ((len>0) && (iptr->opc == ICMD_NOP)) {
697 /* with JSR there can not be multiple successors */
698 _GRAPH_ASSERT(iptr->opc != ICMD_JSR);
699 /* If the return Statment has more successors and */
700 /* one of these has more predecessor, we are in */
701 /* troubles - one would have to insert a new Block */
702 /* after the one which executes the ICMD_JSR */
703 /* !!TODO!! if subroutines will not be inlined */
704 _GRAPH_ASSERT(iptr->opc != ICMD_RET);
706 /* link new block into basicblocks list */
707 /* if edge to split is the "fallthrough" path of the */
708 /* conditional, then link the new block inbetween */
709 /* and generate no ICMD */
710 /* else if edge to split is the branch, generate a */
711 /* ICMD_GOTO and add new BB at the end of the BB List*/
712 if ((ls->basicblocks[pred]->next == ls->basicblocks[succ])
713 && (iptr->opc != ICMD_LOOKUPSWITCH)
714 && (iptr->opc != ICMD_TABLESWITCH)
715 && (iptr->opc != ICMD_GOTO)) {
716 /* GOTO, *SWITCH have no fallthrough path */
718 /* link into fallthrough path */
721 ls->basicblocks[n]->next =
722 ls->basicblocks[pred]->next;
723 ls->basicblocks[pred]->next =
726 /* generate no instructions */
727 ls->basicblocks[n]->icount = 1;
728 ls->basicblocks[n]->iinstr = NEW(instruction);
729 ls->basicblocks[n]->iinstr[0].opc = ICMD_NOP;
731 graph_phi_moves(jd, ls->basicblocks[n], NULL);
734 /* Block n is in the Branch path */
735 /* link Block at the end */
736 ls->basicblocks[n]->next =last_block->next;
737 last_block->next = ls->basicblocks[n];
738 last_block = ls->basicblocks[n];
740 /* change the Branch Target to BB i */
743 case ICMD_LOOKUPSWITCH:
746 lookup_target_t *lookup;
748 lookup = iptr->dst.lookup;
750 i = iptr->sx.s23.s2.lookupcount;
753 if (lookup->target.block == ls->basicblocks[succ])
754 /* target found -> change */
755 lookup->target.block = ls->basicblocks[n];
759 if (iptr->sx.s23.s3.lookupdefault.block == ls->basicblocks[succ])
760 /* target found -> change */
761 iptr->sx.s23.s3.lookupdefault.block = ls->basicblocks[n];
764 case ICMD_TABLESWITCH:
767 branch_target_t *table;
769 table = iptr->dst.table;
771 l = iptr->sx.s23.s2.tablelow;
772 i = iptr->sx.s23.s3.tablehigh;
776 if (table[0].block == ls->basicblocks[succ]) /* default target */
777 /* target found -> change*/
778 table[0].block = ls->basicblocks[n];
783 if (table->block == ls->basicblocks[succ])
784 /* target found -> change */
785 table->block = ls->basicblocks[n];
819 _GRAPH_ASSERT(iptr->dst.block == ls->basicblocks[succ]);
820 iptr->dst.block = ls->basicblocks[n];
823 /* Exception Edge to split */
824 /* not handled by now -> fallback to regalloc */
828 /* Generate the ICMD_GOTO */
829 ls->basicblocks[n]->icount = 1;
830 ls->basicblocks[n]->iinstr =
832 ls->basicblocks[n]->iinstr->opc =
834 ls->basicblocks[n]->iinstr->dst.block =
835 ls->basicblocks[succ];
837 graph_phi_moves(jd, ls->basicblocks[n], ls->basicblocks[succ]);
844 /* graph_phi_moves *************************************************************
846 generate the instruction array for Basicblock n (== ls->basicblocks[n])
849 basicblock *bptr Basicblock to change with ->iinstr == NULL
850 basicblock *dst_goto Destination Block for ICMD_GOTO at end of Block, or
851 NULL for no ICMD_GOTO
854 bptr->iinstr points to a newly allocated instruction array containing
855 the phi moves, the optional ICMD_GOTO at the end.
856 bptr->icount Count of instructions in bptr->iinstr
858 *******************************************************************************/
860 void graph_phi_moves(jitdata *jd, basicblock *bptr, basicblock *dst_goto) {
867 _GRAPH_ASSERT(ls->num_phi_moves[bptr->nr] > 0);
868 bptr->icount = ls->num_phi_moves[bptr->nr];
869 if (dst_goto != NULL)
871 bptr->iinstr = iptr = DMNEW(instruction, bptr->icount);
873 _GRAPH_ASSERT(iptr != NULL);
875 /* Moves from phi functions with highest indices have to be */
876 /* inserted first, since this is the order as is used for */
877 /* conflict resolution */
879 for(i = ls->num_phi_moves[bptr->nr] - 1; i >= 0 ; i--) {
880 lt_d = ls->phi_moves[bptr->nr][i][0];
881 lt_s = ls->phi_moves[bptr->nr][i][1];
883 #if defined(GRAPH_DEBUG_VERBOSE)
885 printf("graph_phi_moves: BB %3i Move %3i <- %3i\n", bptr->nr,
888 if (lt_s == UNUSED) {
889 #if defined(SSA_DEBUG_VERBOSE)
891 printf(" ... not processed \n");
896 _GRAPH_ASSERT(d->type != -1);
897 _GRAPH_ASSERT(s->type == -1);
899 iptr->opc = ICMD_MOVE;
900 iptr->s1.varindex = ls->lifetime[lt_s].v_index;
901 iptr->dst.varindex = ls->lifetime[lt_d].v_index;
905 if (dst_goto != NULL) {
906 iptr->opc = ICMD_GOTO;
907 iptr->dst.block = dst_goto;
911 #ifdef GRAPH_DEBUG_VERBOSE
912 void graph_print(lsradata *ls, graphdata *gd) {
915 printf("graph_print: basicblockcount %3i\n", ls->basicblockcount);
918 for(i = 0; i < ls->basicblockcount; i++) {
920 j = graph_get_first_successor(gd, i, &iter);
921 for(; j != -1; j = graph_get_next(&iter)) {
927 for(i = 0; i < ls->basicblockcount; i++) {
929 j = graph_get_first_predecessor(gd, i, &iter);
930 for(; j != -1; j = graph_get_next(&iter)) {
941 * These are local overrides for various environment variables in Emacs.
942 * Please do not remove this and leave it at the end of the file, where
943 * Emacs will automagically detect them.
944 * ---------------------------------------------------------------------
947 * indent-tabs-mode: t