1 /* src/vm/jit/loop/graph.c - control flow graph
3 Copyright (C) 1996-2005 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: Christopher Kruegel
29 Changes: Christian Thalinger
31 Contains the functions which build a list, that represents the
32 control flow graph of the procedure, that is being analyzed.
34 $Id: graph.c 2495 2005-05-22 19:49:53Z twisti $
41 #include "mm/memory.h"
42 #include "toolbox/logging.h"
43 #include "vm/jit/jit.h"
44 #include "vm/jit/loop/graph.h"
45 #include "vm/jit/loop/loop.h"
48 void LoopContainerInit(methodinfo *m, struct LoopContainer *lc, int i)
50 struct LoopElement *le = DMNEW(struct LoopElement, 1);
56 lc->tree_right = NULL;
59 lc->exceptions = NULL;
62 le->node = lc->loop_head = i;
63 le->block = &m->basicblocks[i];
65 /* lc->nodes = (int *) malloc(sizeof(int)*m->basicblockcount);
73 depthFirst() builds the control flow graph out of the intermediate code of
74 the procedure, that is to be optimized and stores the list in the global
78 void depthFirst(methodinfo *m, loopdata *ld)
82 /* allocate memory and init gobal variables needed by function dF(m, int, int) */
84 ld->c_defnum = DMNEW(int, m->basicblockcount);
85 ld->c_numPre = DMNEW(int, m->basicblockcount);
86 ld->c_parent = DMNEW(int, m->basicblockcount);
87 ld->c_reverse = DMNEW(int, m->basicblockcount);
88 ld->c_pre = DMNEW(int *, m->basicblockcount);
89 ld->c_dTable = DMNEW(struct depthElement *, m->basicblockcount);
91 for (i = 0; i < m->basicblockcount; ++i) {
92 ld->c_defnum[i] = ld->c_parent[i] = -1;
93 ld->c_numPre[i] = ld->c_reverse[i] = 0;
95 ld->c_pre[i] = DMNEW(int, m->basicblockcount);
96 ld->c_dTable[i] = NULL;
99 ld->c_globalCount = 0;
100 ld->c_allLoops = NULL;
102 dF(m, ld, -1, 0); /* call helper function dF that traverses basic block structure */
107 dF starts from the first block of the given procedure and traverses the
108 control flow graph in a depth-first order, thereby building up the adeacency
112 void dF(methodinfo *m, loopdata *ld, int from, int blockIndex)
116 int high, low, count;
117 struct depthElement *hp;
118 struct LoopContainer *tmp;
122 /* the current basic block has a predecessor (ie. is not the first one) */
123 hp = DNEW(struct depthElement);/* create new depth element */
125 hp->next = ld->c_dTable[from]; /* insert values */
126 hp->value = blockIndex;
129 ld->c_dTable[from] = hp; /* insert into table */
132 if (from == blockIndex) { /* insert one node loops into loop container */
133 tmp = DNEW(struct LoopContainer);
134 LoopContainerInit(m, tmp, blockIndex);
135 tmp->next = ld->c_allLoops;
136 ld->c_allLoops = tmp;
140 if (blockIndex > m->basicblockcount) {
141 log_text("DepthFirst: BlockIndex exceeded\n");
146 ip = m->basicblocks[blockIndex].iinstr + m->basicblocks[blockIndex].icount -1;
147 /* set ip to last instruction */
149 if (ld->c_defnum[blockIndex] == -1) { /* current block has not been visited */
150 ld->c_defnum[blockIndex] = ld->c_globalCount; /* update global count */
151 ld->c_parent[blockIndex] = from; /* write parent block of current one */
152 ld->c_reverse[ld->c_globalCount] = blockIndex;
155 if (!m->basicblocks[blockIndex].icount) {
156 /* block does not contain instructions */
157 dF(m, ld, blockIndex, blockIndex+1);
159 else { /* for all successors, do */
160 switch (ip->opc) { /* check type of last instruction */
168 break; /* function returns -> end of graph */
197 case ICMD_IF_ACMPNE: /* branch -> check next block */
198 dF(m, ld, blockIndex, blockIndex + 1);
202 dF(m, ld, blockIndex, m->basicblockindex[ip->op1]);
203 break; /* visit branch (goto) target */
205 case ICMD_TABLESWITCH: /* switch statement */
208 dF(m, ld, blockIndex, m->basicblockindex[*s4ptr]); /* default branch */
215 count = (high-low+1);
217 while (--count >= 0) {
219 dF(m, ld, blockIndex, m->basicblockindex[*s4ptr]);
223 case ICMD_LOOKUPSWITCH: /* switch statement */
226 dF(m, ld, blockIndex, m->basicblockindex[*s4ptr]); /* default branch */
231 while (--count >= 0) {
232 dF(m, ld, blockIndex, m->basicblockindex[s4ptr[1]]);
238 ld->c_last_jump = blockIndex;
239 dF(m, ld, blockIndex, m->basicblockindex[ip->op1]);
243 dF(m, ld, blockIndex, ld->c_last_jump+1);
247 dF(m, ld, blockIndex, blockIndex + 1);
253 for (ptr = ld->c_pre[blockIndex], cnt = 0; cnt < ld->c_numPre[blockIndex]; ++cnt, ++ptr)
259 if (cnt >= ld->c_numPre[blockIndex]) {
260 ld->c_pre[blockIndex][ld->c_numPre[blockIndex]] = from;
261 /* add predeccessors to list c_pre */
262 ld->c_numPre[blockIndex]++; /* increase number of predecessors */
269 a slightly modified version of dF(m, ld, int, int) that is used to traverse the part
270 of the control graph that is not reached by normal program flow but by the
271 raising of exceptions (code of catch blocks)
274 void dF_Exception(methodinfo *m, loopdata *ld, int from, int blockIndex)
278 int high, low, count;
279 struct depthElement *hp;
281 if (ld->c_exceptionVisit[blockIndex] < 0) /* has block been visited, return */
282 ld->c_exceptionVisit[blockIndex] = 1;
286 if (ld->c_dTable[blockIndex] != NULL) /* back to regular code section */
289 if (from >= 0) { /* build exception graph (in c_exceptionGraph) */
290 hp = DNEW(struct depthElement);
291 hp->next = ld->c_exceptionGraph[from];
292 hp->value = blockIndex;
295 ld->c_exceptionGraph[from] = hp;
299 if (blockIndex > m->basicblockcount) {
300 log_text("DepthFirst: BlockIndex exceeded");
305 ip = m->basicblocks[blockIndex].iinstr + m->basicblocks[blockIndex].icount -1;
307 if (!m->basicblocks[blockIndex].icount)
308 dF_Exception(m, ld, blockIndex, blockIndex+1);
347 case ICMD_IF_ACMPNE: /* branch -> check next block */
348 dF_Exception(m, ld, blockIndex, blockIndex + 1);
352 dF_Exception(m, ld, blockIndex, m->basicblockindex[ip->op1]);
355 case ICMD_TABLESWITCH:
359 dF_Exception(m, ld, blockIndex, m->basicblockindex[*s4ptr]);
366 count = (high-low+1);
368 while (--count >= 0) {
370 dF_Exception(m, ld, blockIndex, m->basicblockindex[*s4ptr]);
374 case ICMD_LOOKUPSWITCH:
378 dF_Exception(m, ld, blockIndex, m->basicblockindex[*s4ptr]);
383 while (--count >= 0) {
384 dF_Exception(m, ld, blockIndex, m->basicblockindex[s4ptr[1]]);
390 ld->c_last_jump = blockIndex;
391 dF_Exception(m, ld, blockIndex, m->basicblockindex[ip->op1]);
395 dF_Exception(m, ld, blockIndex, ld->c_last_jump+1);
399 dF_Exception(m, ld, blockIndex, blockIndex + 1);
408 Test function -> will be removed in final release
410 void resultPass1(methodinfo *m)
413 struct depthElement *hp;
415 printf("\n\n****** PASS 1 ******\n\n");
416 printf("Number of Nodes: %d\n\n", ld->c_globalCount);
418 printf("Predecessors:\n");
419 for (i=0; i<m->basicblockcount; ++i) {
420 printf("Block %d:\t", i);
421 for (j=0; j<ld->c_numPre[i]; ++j)
422 printf("%d ", ld->c_pre[i][j]);
428 for (i=0; i<m->basicblockcount; ++i) {
429 printf("Block %d:\t", i);
430 hp = ld->c_dTable[i];
433 printf("%d ", hp->value);
443 * These are local overrides for various environment variables in Emacs.
444 * Please do not remove this and leave it at the end of the file, where
445 * Emacs will automagically detect them.
446 * ---------------------------------------------------------------------
449 * indent-tabs-mode: t