1 /* src/vm/jit/loop/graph.c - control flow graph
3 Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
4 C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5 E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6 J. Wenninger, 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., 51 Franklin Street, Fifth Floor, Boston, MA
25 Contact: cacao@cacaojvm.org
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 4699 2006-03-28 14:52:32Z 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(jitdata *jd)
84 /* get required compiler data */
89 /* allocate memory and init gobal variables needed by function dF(m, int, int) */
91 ld->c_defnum = DMNEW(int, m->basicblockcount);
92 ld->c_numPre = DMNEW(int, m->basicblockcount);
93 ld->c_parent = DMNEW(int, m->basicblockcount);
94 ld->c_reverse = DMNEW(int, m->basicblockcount);
95 ld->c_pre = DMNEW(int *, m->basicblockcount);
96 ld->c_dTable = DMNEW(struct depthElement *, m->basicblockcount);
98 for (i = 0; i < m->basicblockcount; ++i) {
99 ld->c_defnum[i] = ld->c_parent[i] = -1;
100 ld->c_numPre[i] = ld->c_reverse[i] = 0;
102 ld->c_pre[i] = DMNEW(int, m->basicblockcount);
103 ld->c_dTable[i] = NULL;
106 ld->c_globalCount = 0;
107 ld->c_allLoops = NULL;
109 dF(m, ld, -1, 0); /* call helper function dF that traverses basic block structure */
114 dF starts from the first block of the given procedure and traverses the
115 control flow graph in a depth-first order, thereby building up the adeacency
119 void dF(methodinfo *m, loopdata *ld, int from, int blockIndex)
123 int high, low, count;
124 struct depthElement *hp;
125 struct LoopContainer *tmp;
129 /* the current basic block has a predecessor (ie. is not the first one) */
130 hp = DNEW(struct depthElement);/* create new depth element */
132 hp->next = ld->c_dTable[from]; /* insert values */
133 hp->value = blockIndex;
136 ld->c_dTable[from] = hp; /* insert into table */
139 if (from == blockIndex) { /* insert one node loops into loop container */
140 tmp = DNEW(struct LoopContainer);
141 LoopContainerInit(m, tmp, blockIndex);
142 tmp->next = ld->c_allLoops;
143 ld->c_allLoops = tmp;
147 if (blockIndex > m->basicblockcount) {
148 log_text("DepthFirst: BlockIndex exceeded\n");
153 ip = m->basicblocks[blockIndex].iinstr + m->basicblocks[blockIndex].icount -1;
154 /* set ip to last instruction */
156 if (ld->c_defnum[blockIndex] == -1) { /* current block has not been visited */
157 ld->c_defnum[blockIndex] = ld->c_globalCount; /* update global count */
158 ld->c_parent[blockIndex] = from; /* write parent block of current one */
159 ld->c_reverse[ld->c_globalCount] = blockIndex;
162 if (!m->basicblocks[blockIndex].icount) {
163 /* block does not contain instructions */
164 dF(m, ld, blockIndex, blockIndex+1);
166 else { /* for all successors, do */
167 switch (ip->opc) { /* check type of last instruction */
175 break; /* function returns -> end of graph */
204 case ICMD_IF_ACMPNE: /* branch -> check next block */
205 dF(m, ld, blockIndex, blockIndex + 1);
209 dF(m, ld, blockIndex, m->basicblockindex[ip->op1]);
210 break; /* visit branch (goto) target */
212 case ICMD_TABLESWITCH: /* switch statement */
215 dF(m, ld, blockIndex, m->basicblockindex[*s4ptr]); /* default branch */
222 count = (high-low+1);
224 while (--count >= 0) {
226 dF(m, ld, blockIndex, m->basicblockindex[*s4ptr]);
230 case ICMD_LOOKUPSWITCH: /* switch statement */
233 dF(m, ld, blockIndex, m->basicblockindex[*s4ptr]); /* default branch */
238 while (--count >= 0) {
239 dF(m, ld, blockIndex, m->basicblockindex[s4ptr[1]]);
245 ld->c_last_jump = blockIndex;
246 dF(m, ld, blockIndex, m->basicblockindex[ip->op1]);
250 dF(m, ld, blockIndex, ld->c_last_jump+1);
254 dF(m, ld, blockIndex, blockIndex + 1);
260 for (ptr = ld->c_pre[blockIndex], cnt = 0; cnt < ld->c_numPre[blockIndex]; ++cnt, ++ptr)
266 if (cnt >= ld->c_numPre[blockIndex]) {
267 ld->c_pre[blockIndex][ld->c_numPre[blockIndex]] = from;
268 /* add predeccessors to list c_pre */
269 ld->c_numPre[blockIndex]++; /* increase number of predecessors */
276 a slightly modified version of dF(m, ld, int, int) that is used to traverse the part
277 of the control graph that is not reached by normal program flow but by the
278 raising of exceptions (code of catch blocks)
281 void dF_Exception(methodinfo *m, loopdata *ld, int from, int blockIndex)
285 int high, low, count;
286 struct depthElement *hp;
288 if (ld->c_exceptionVisit[blockIndex] < 0) /* has block been visited, return */
289 ld->c_exceptionVisit[blockIndex] = 1;
293 if (ld->c_dTable[blockIndex] != NULL) /* back to regular code section */
296 if (from >= 0) { /* build exception graph (in c_exceptionGraph) */
297 hp = DNEW(struct depthElement);
298 hp->next = ld->c_exceptionGraph[from];
299 hp->value = blockIndex;
302 ld->c_exceptionGraph[from] = hp;
306 if (blockIndex > m->basicblockcount) {
307 log_text("DepthFirst: BlockIndex exceeded");
312 ip = m->basicblocks[blockIndex].iinstr + m->basicblocks[blockIndex].icount -1;
314 if (!m->basicblocks[blockIndex].icount)
315 dF_Exception(m, ld, blockIndex, blockIndex+1);
354 case ICMD_IF_ACMPNE: /* branch -> check next block */
355 dF_Exception(m, ld, blockIndex, blockIndex + 1);
359 dF_Exception(m, ld, blockIndex, m->basicblockindex[ip->op1]);
362 case ICMD_TABLESWITCH:
366 dF_Exception(m, ld, blockIndex, m->basicblockindex[*s4ptr]);
373 count = (high-low+1);
375 while (--count >= 0) {
377 dF_Exception(m, ld, blockIndex, m->basicblockindex[*s4ptr]);
381 case ICMD_LOOKUPSWITCH:
385 dF_Exception(m, ld, blockIndex, m->basicblockindex[*s4ptr]);
390 while (--count >= 0) {
391 dF_Exception(m, ld, blockIndex, m->basicblockindex[s4ptr[1]]);
397 ld->c_last_jump = blockIndex;
398 dF_Exception(m, ld, blockIndex, m->basicblockindex[ip->op1]);
402 dF_Exception(m, ld, blockIndex, ld->c_last_jump+1);
406 dF_Exception(m, ld, blockIndex, blockIndex + 1);
415 Test function -> will be removed in final release
417 void resultPass1(methodinfo *m)
420 struct depthElement *hp;
422 printf("\n\n****** PASS 1 ******\n\n");
423 printf("Number of Nodes: %d\n\n", ld->c_globalCount);
425 printf("Predecessors:\n");
426 for (i=0; i<m->basicblockcount; ++i) {
427 printf("Block %d:\t", i);
428 for (j=0; j<ld->c_numPre[i]; ++j)
429 printf("%d ", ld->c_pre[i][j]);
435 for (i=0; i<m->basicblockcount; ++i) {
436 printf("Block %d:\t", i);
437 hp = ld->c_dTable[i];
440 printf("%d ", hp->value);
450 * These are local overrides for various environment variables in Emacs.
451 * Please do not remove this and leave it at the end of the file, where
452 * Emacs will automagically detect them.
453 * ---------------------------------------------------------------------
456 * indent-tabs-mode: t