bounds are never violated. The function to call is
optimize_loops().
- $Id: analyze.c 1203 2004-06-22 23:14:55Z twisti $
+ $Id: analyze.c 1454 2004-11-05 14:19:32Z twisti $
*/
printf("Dynamic\t\t%d/%d\n", lv->dynamic_l, lv->dynamic_u);
}
-void show_right_side()
+void show_right_side(methodinfo *m)
{
int i;
printf("\n *** Head *** \nType:\t");
- show_trace(c_rightside);
+ show_trace(m->loopdata->c_rightside);
printf("\n *** Nested Loops: ***\n");
for (i=0; i<m->basicblockcount; ++i)
- printf("%d\t", c_nestedLoops[i]);
+ printf("%d\t", m->loopdata->c_nestedLoops[i]);
printf("\n");
printf("\n *** Hierarchie: ***\n");
for (i=0; i<m->basicblockcount; ++i)
- printf("%d\t", c_hierarchie[i]);
+ printf("%d\t", m->loopdata->c_hierarchie[i]);
printf("\n");
printf("\n *** Current Loop ***\n");
for (i=0; i<m->basicblockcount; ++i)
- printf("%d\t", c_current_loop[i]);
+ printf("%d\t", m->loopdata->c_current_loop[i]);
printf("\n");
}
-void resultPass3()
+void resultPass3(methodinfo *m)
{
int i;
- struct LoopContainer *lc = c_allLoops;
+ struct LoopContainer *lc = m->loopdata->c_allLoops;
printf("\n\n****** PASS 3 ******\n\n");
printf("\nNested Loops:\n");
for (i=0; i<m->basicblockcount; ++i)
- printf("%d ", c_nestedLoops[i]);
+ printf("%d ", m->loopdata->c_nestedLoops[i]);
printf("\n");
for (i=0; i<m->basicblockcount; ++i)
- printf("%d ", c_hierarchie[i]);
+ printf("%d ", m->loopdata->c_hierarchie[i]);
printf("\n");
fflush(stdout);
}
#ifdef STATISTICS
-void show_loop_statistics()
+void show_loop_statistics(loopdata *ld)
{
printf("\n\n****** LOOP STATISTICS ****** \n\n");
- if (c_stat_or)
+ if (ld->c_stat_or)
printf("Optimization cancelled by or\n");
- else if (c_stat_exception)
+ else if (ld->c_stat_exception)
printf("Optimization cancelled by exception\n");
else {
- printf("Number of array accesses:\t%d\n", c_stat_array_accesses);
- if (c_stat_array_accesses) {
- printf("\nFully optimized:\t%d\n", c_stat_full_opt);
- printf("Not optimized:\t\t%d\n", c_stat_no_opt);
- printf("Upper optimized:\t%d\n", c_stat_upper_opt);
- printf("Lower optimized:\t%d\n", c_stat_lower_opt);
+ printf("Number of array accesses:\t%d\n", ld->c_stat_array_accesses);
+ if (ld->c_stat_array_accesses) {
+ printf("\nFully optimized:\t%d\n", ld->c_stat_full_opt);
+ printf("Not optimized:\t\t%d\n", ld->c_stat_no_opt);
+ printf("Upper optimized:\t%d\n", ld->c_stat_upper_opt);
+ printf("Lower optimized:\t%d\n", ld->c_stat_lower_opt);
}
}
}
-void show_procedure_statistics()
+void show_procedure_statistics(loopdata *ld)
{
printf("\n\n****** PROCEDURE STATISTICS ****** \n\n");
- printf("Number of loops:\t\t%d\n", c_stat_num_loops);
- printf("Number of array accesses:\t%d\n", c_stat_sum_accesses);
- if (c_stat_sum_accesses) {
- printf("\nFully optimized:\t%d\n", c_stat_sum_full);
- printf("Not optimized:\t\t%d\n", c_stat_sum_no);
- printf("Upper optimized:\t%d\n", c_stat_sum_upper);
- printf("Lower optimized:\t%d\n", c_stat_sum_lower);
+ printf("Number of loops:\t\t%d\n", ld->c_stat_num_loops);
+ printf("Number of array accesses:\t%d\n", ld->c_stat_sum_accesses);
+ if (ld->c_stat_sum_accesses) {
+ printf("\nFully optimized:\t%d\n", ld->c_stat_sum_full);
+ printf("Not optimized:\t\t%d\n", ld->c_stat_sum_no);
+ printf("Upper optimized:\t%d\n", ld->c_stat_sum_upper);
+ printf("Lower optimized:\t%d\n", ld->c_stat_sum_lower);
}
- printf("Opt. cancelled by or:\t\t%d\n", c_stat_sum_or);
- printf("Opt. cancelled by exception:\t%d\n", c_stat_sum_exception);
+ printf("Opt. cancelled by or:\t\t%d\n", ld->c_stat_sum_or);
+ printf("Opt. cancelled by exception:\t%d\n", ld->c_stat_sum_exception);
}
#endif
finding algorith sometimes (eg. when loopbody ends with a if-else construct)
reports a single loop as two loops with the same header node.
*/
-void analyze_double_headers()
+void analyze_double_headers(loopdata *ld)
{
int toCheck;
- struct LoopContainer *t1, *t2, *t3;
+ LoopContainer *t1, *t2, *t3;
- t1 = c_allLoops;
+ t1 = ld->c_allLoops;
while (t1 != NULL) { /* for all loops do */
toCheck = t1->loop_head; /* get header node */
Each loop, that is a nested loop, stores its direct surrounding loop as a
parent. Top level loops have no parents.
*/
-void analyze_nested(methodinfo *m)
+
+void analyze_nested(methodinfo *m, loopdata *ld)
{
/* i/count/tmp are counters */
/* toOverwrite is used while loop hierarchie is built (see below) */
struct LoopElement *le;
/* init global structures */
- c_nestedLoops = DMNEW(int, m->basicblockcount);
- c_hierarchie = DMNEW(int, m->basicblockcount);
+ ld->c_nestedLoops = DMNEW(int, m->basicblockcount);
+ ld->c_hierarchie = DMNEW(int, m->basicblockcount);
for (i=0; i<m->basicblockcount; ++i) {
- c_nestedLoops[i] = -1;
- c_hierarchie[i] = -1;
+ ld->c_nestedLoops[i] = -1;
+ ld->c_hierarchie[i] = -1;
}
/* if there are no optimizable loops -> return */
- if (c_allLoops == NULL)
+ if (ld->c_allLoops == NULL)
return;
- temp = c_allLoops;
+ temp = ld->c_allLoops;
while (temp != NULL) { /* for all loops, do */
header = temp->loop_head;
/* toOverwrite is number of current parent loop (-1 if none) */
- toOverwrite = c_nestedLoops[header];
+ toOverwrite = ld->c_nestedLoops[header];
- c_hierarchie[header] = toOverwrite;
+ ld->c_hierarchie[header] = toOverwrite;
if (toOverwrite == header) /* check for loops with same header */
printf("C_ERROR: Loops have same header\n");
le = temp->nodes;
while (le != NULL) { /* for all loop nodes, do */
- tmp = c_nestedLoops[le->node];
+ tmp = ld->c_nestedLoops[le->node];
/* if node is part of parent loop -> overwrite it with nested */
if (tmp == toOverwrite)
- c_nestedLoops[le->node] = header;
+ ld->c_nestedLoops[le->node] = header;
else {
- c_hierarchie[tmp] = header;
+ ld->c_hierarchie[tmp] = header;
#ifdef LOOP_DEBUG
/* printf("set head of %d to %d", tmp, header); */
#endif
}
/* init root of hierarchie tree */
- root = DMNEW(struct LoopContainer, 1);
- LoopContainerInit(m, root, -1);
+ ld->root = DMNEW(struct LoopContainer, 1);
+ LoopContainerInit(m, ld->root, -1);
/* obtain parent pointer and build hierarchie tree */
- start = c_allLoops;
+ start = ld->c_allLoops;
while (start != NULL) {
/* look for parent of loop pointed at by start */
- first = c_allLoops;
+ first = ld->c_allLoops;
while (first != NULL) {
/* the parent of the loop, pointed at by start has been found */
- if (first->loop_head == c_hierarchie[start->loop_head]) {
+ if (first->loop_head == ld->c_hierarchie[start->loop_head]) {
#ifdef LOOP_DEBUG
/* printf("set parent to pointer\n"); */
#endif
/* printf("set parent to root\n"); */
#endif
- start->parent = root;
- start->tree_right = root->tree_down;
- root->tree_down = start;
+ start->parent = ld->root;
+ start->tree_right = ld->root->tree_down;
+ ld->root->tree_down = start;
}
/* if a parent exists, increase this nodes indegree */
else
/* insert exceptions into tree */
#ifdef LOOP_DEBUG
printf("--- Showing tree ---\n");
- show_tree(root, 0);
+ show_tree(ld->root, 0);
printf(" --- End ---\n");
#endif
for (len = 0; len < m->exceptiontablelength; ++len)
- insert_exception(m, root, m->exceptiontable + len);
+ insert_exception(m, ld->root, m->exceptiontable + len);
/* determine sequence of loops for optimization by topological sort */
/* init queue */
start = NULL;
- temp = c_allLoops;
+ temp = ld->c_allLoops;
while (temp != NULL) {
/* a loops with indegree == 0 are pushed onto the stack */
/* pop each node from the stack and decrease its parents indegree by one */
/* when the parents indegree reaches zero, push it onto the stack as well */
- if ((last->parent != root) && (--last->parent->in_degree == 0)) {
+ if ((last->parent != ld->root) && (--last->parent->in_degree == 0)) {
last->parent->next = start;
start = last->parent;
}
start = start->next;
last = last->next;
- if ((last->parent != root) && (--last->parent->in_degree == 0)) {
+ if ((last->parent != ld->root) && (--last->parent->in_degree == 0)) {
last->parent->next = start;
start = last->parent;
}
}
last->next = NULL;
- c_allLoops = first;
+ ld->c_allLoops = first;
#ifdef LOOP_DEBUG
printf("*** Hierarchie Results \n");
#endif
}
+
/* This function is used to add variables that occur as index variables in
array accesses (ARRAY_INDEX) or as variables, that change their value (VAR_MOD)
to the list of interesting vars (c_loopvars) for the current loop.
*/
-void add_to_vars(int var, int type, int direction)
+
+void add_to_vars(loopdata *ld, int var, int type, int direction)
{
struct LoopVar *lv;
/* printf("Added to vars %d %d %d\n", var, type, direction); */
- lv = c_loopvars;
+ lv = ld->c_loopvars;
while (lv != NULL) { /* check if var has been previously added */
if (lv->value == var) {
if (type == ARRAY_INDEX)
/* no dynamic bounds have been determined so far */
lv->dynamic_l = lv->dynamic_l_v = lv->dynamic_u = lv->dynamic_u_v = 0;
- lv->next = c_loopvars; /* add var to list */
- c_loopvars = lv;
+ lv->next = ld->c_loopvars; /* add var to list */
+ ld->c_loopvars = lv;
}
+
/* This function checks, whether a given loop with header node contains array
accesses. If so, it returns 1, else it returns 0 and the loops needs no
further consideration in the optimization process. When array accesses are
stored in c_loopvars. For all variables (integer), which values are changed,
a flag in c_var_modified is set.
*/
-int analyze_for_array_access(methodinfo *m, int node)
+
+int analyze_for_array_access(methodinfo *m, loopdata *ld, int node)
{
basicblock bp;
instruction *ip;
struct depthElement *d;
struct Trace *t;
- if (c_toVisit[node] > 0) { /* node has not been visited yet */
- c_toVisit[node] = 0;
+ if (ld->c_toVisit[node] > 0) { /* node has not been visited yet */
+ ld->c_toVisit[node] = 0;
bp = m->basicblocks[node]; /* prepare an instruction scan */
ip = bp.iinstr;
if (t->type == TRACE_IVAR) {
/* if it is a variable, add it to list of index variables */
- add_to_vars(t->var, ARRAY_INDEX, D_UNKNOWN);
+ add_to_vars(ld, t->var, ARRAY_INDEX, D_UNKNOWN);
access++;
}
else if (t->type == TRACE_ICONST)
if (t->type == TRACE_IVAR) {
/* if it is a variable, add it to list of index variables */
- add_to_vars(t->var, ARRAY_INDEX, D_UNKNOWN);
+ add_to_vars(ld, t->var, ARRAY_INDEX, D_UNKNOWN);
access++;
}
else if (t->type == TRACE_ICONST)
break;
case ICMD_ISTORE: /* integer store */
- c_var_modified[ip->op1] = 1;
+ ld->c_var_modified[ip->op1] = 1;
/* try to find out, how it was modified */
t = tracing(&bp, i-1, 0);
if (t->type == TRACE_IVAR) {
if ((t->constant > 0) && (t->var == ip->op1))
/* a constant was added to the same var */
- add_to_vars(t->var, VAR_MOD, D_UP);
+ add_to_vars(ld, t->var, VAR_MOD, D_UP);
else if (t->var == ip->op1)
/* a constant was subtracted from the same var */
- add_to_vars(t->var, VAR_MOD, D_DOWN);
+ add_to_vars(ld, t->var, VAR_MOD, D_DOWN);
else
- add_to_vars(t->var, VAR_MOD, D_UNKNOWN);
+ add_to_vars(ld, t->var, VAR_MOD, D_UNKNOWN);
}
else
- add_to_vars(ip->op1, VAR_MOD, D_UNKNOWN);
+ add_to_vars(ld, ip->op1, VAR_MOD, D_UNKNOWN);
break;
case ICMD_IINC: /* simple add/sub of a constant */
- c_var_modified[ip->op1] = 1;
+ ld->c_var_modified[ip->op1] = 1;
if (ip->val.i > 0)
- add_to_vars(ip->op1, VAR_MOD, D_UP);
+ add_to_vars(ld, ip->op1, VAR_MOD, D_UP);
else
- add_to_vars(ip->op1, VAR_MOD, D_DOWN);
+ add_to_vars(ld, ip->op1, VAR_MOD, D_DOWN);
break;
case ICMD_LSTORE:
case ICMD_FSTORE:
case ICMD_DSTORE:
case ICMD_ASTORE:
- c_var_modified[ip->op1] = 1;
+ ld->c_var_modified[ip->op1] = 1;
break;
}
}
- d = c_dTable[node];
+ d = ld->c_dTable[node];
while (d != NULL) { /* check all successors of block */
- access += analyze_for_array_access(m, d->value);
+ access += analyze_for_array_access(m, ld, d->value);
d = d->next;
}
return 0;
}
+
/* This function scans the exception graph structure to find modifications of
array index variables of the current loop. If any modifications are found,
1 is returned, else 0.
*/
-int quick_scan(methodinfo *m, int node)
+
+int quick_scan(methodinfo *m, loopdata *ld, int node)
{
basicblock bp;
instruction *ip;
int count, i;
struct LoopVar *lv;
struct depthElement *d;
-
- /* printf("QS: %d - %d\n", node, c_exceptionVisit[node]); */
+
+ /* printf("QS: %d - %d\n", node, ld->c_exceptionVisit[node]); */
- if (c_exceptionVisit[node] > 0) { /* node is part of exception graph */
- c_exceptionVisit[node] = -1;
+ if (ld->c_exceptionVisit[node] > 0) { /* node is part of exception graph */
+ ld->c_exceptionVisit[node] = -1;
bp = m->basicblocks[node]; /* setup scan of all instructions */
ip = bp.iinstr;
case ICMD_ISTORE:
case ICMD_IINC: /* a variable is modified */
- lv = c_loopvars; /* is it an array index var ? */
+ lv = ld->c_loopvars; /* is it an array index var ? */
while (lv != NULL) {
if ((lv->index) && (lv->value == ip->op1))
return 1; /* yes, so return 1 */
}
}
- d = c_exceptionGraph[node]; /* check all successor nodes */
+ d = ld->c_exceptionGraph[node]; /* check all successor nodes */
while (d != NULL) {
- if (quick_scan(m, d->value) > 0)
+ if (quick_scan(m, ld, d->value) > 0)
return 1; /* if an access is found return 1 */
d = d->next;
}
return 0;
}
+
/* This function returns 1, when the condition of the loop contains
or statements or when an array index variable is modified in any
catch block within the loop.
*/
-int analyze_or_exceptions(methodinfo *m, int head, struct LoopContainer *lc)
+
+int analyze_or_exceptions(methodinfo *m, loopdata *ld, int head, struct LoopContainer *lc)
{
struct depthElement *d;
int i, k, value, flag, count;
struct LoopElement *le;
- d = c_dTable[head];
+ d = ld->c_dTable[head];
count = flag = 0;
/* analyze for or-statements */
if ((count > 1) && (flag == 0)){/* if all successors part of the loop, exit */
#ifdef STATISTICS
- c_stat_or++;
+ ld->c_stat_or++;
#endif
return 0;
}
if (!m->exceptiontablelength) /* when there are no exceptions, exit */
return 1;
- if ((c_exceptionGraph = (struct depthElement **) malloc(sizeof(struct depthElement *) * m->basicblockcount)) == NULL)
+ if ((ld->c_exceptionGraph = (struct depthElement **) malloc(sizeof(struct depthElement *) * m->basicblockcount)) == NULL)
c_mem_error();
- if ((c_exceptionVisit = (int *) malloc(sizeof(int) * m->basicblockcount)) == NULL)
+ if ((ld->c_exceptionVisit = (int *) malloc(sizeof(int) * m->basicblockcount)) == NULL)
c_mem_error();
for (k=0; k<m->basicblockcount; ++k) {
- c_exceptionVisit[k] = -1;
- c_exceptionGraph[k] = NULL;
+ ld->c_exceptionVisit[k] = -1;
+ ld->c_exceptionGraph[k] = NULL;
}
/* for all nodes that start catch block check whether they are part of loop */
- for (i = 0; i < c_old_xtablelength; i++) {
+ for (i = 0; i < ld->c_old_xtablelength; i++) {
value = m->basicblockindex[m->exceptiontable[i].startpc];
le = lc->nodes;
/* build a graph structure, that contains all nodes that are */
/* part of the catc block */
- dF_Exception(m, -1, m->basicblockindex[m->exceptiontable[i].handlerpc]);
+ dF_Exception(m, ld, -1, m->basicblockindex[m->exceptiontable[i].handlerpc]);
/* if array index variables are modified there, return 0 */
- if (quick_scan(m, m->basicblockindex[m->exceptiontable[i].handlerpc]) > 0) {
+ if (quick_scan(m, ld, m->basicblockindex[m->exceptiontable[i].handlerpc]) > 0) {
#ifdef STATISTICS
- c_stat_exception++;
+ ld->c_stat_exception++;
#endif
/* printf("C_INFO: loopVar modified in exception\n"); */
return 0;
return 1;
}
+
/* This function sets a flag in c_var_modified for all variables that have
been found as part of an assigment in the loop.
*/
-void scan_global_list()
+
+void scan_global_list(loopdata *ld)
{
struct LoopVar *lv;
- lv = c_loopvars;
+ lv = ld->c_loopvars;
while (lv != NULL) {
if (lv->modified)
- c_var_modified[lv->value] = 1;
+ ld->c_var_modified[lv->value] = 1;
lv = lv->next;
}
}
+
/* This function analyses the condition in the loop header and trys to find
out, whether some dynamic guarantees can be set up.
*/
-void init_constraints(methodinfo *m, int head)
+
+void init_constraints(methodinfo *m, loopdata *ld, int head)
{
basicblock bp;
instruction *ip;
l_mod = r_mod = 0;
if (left->type == TRACE_IVAR) { /* is a loop variable on left side ? */
- lv_left = c_loopvars;
+ lv_left = ld->c_loopvars;
while (lv_left != NULL) {
if (lv_left->value == left->var) {
l_mod = lv_left->modified; /* yes, but has it been modified ? */
}
if (right->type == TRACE_IVAR){ /* is a loop variable on right side ? */
- lv_right = c_loopvars;
+ lv_right = ld->c_loopvars;
while (lv_right != NULL) {
if (lv_right->value == right->var) {
r_mod = lv_right->modified; /* yes, but has it been modified ? */
}
if ((l_mod - r_mod) == 0) { /* both 1 or both 0 -> no dynamic contraints*/
- c_rightside = NULL; /* possible */
+ ld->c_rightside = NULL; /* possible */
return;
}
/* make sure that right side's value does not change during loop execution */
if (right->type == TRACE_UNKNOWN) {
- c_rightside = NULL;
+ ld->c_rightside = NULL;
return;
}
printf("C_ERROR: debugging error 0x01\n");
}
- c_rightside = right;
+ ld->c_rightside = right;
- switch (c_rightside->type) {
+ switch (ld->c_rightside->type) {
case TRACE_ICONST:
- c_rs_needed_instr = 1;
+ ld->c_rs_needed_instr = 1;
break;
case TRACE_ALENGTH:
- c_rs_needed_instr = 2;
+ ld->c_rs_needed_instr = 2;
break;
case TRACE_IVAR:
- c_rs_needed_instr = 3;
+ ld->c_rs_needed_instr = 3;
break;
default:
printf("C_ERROR: wrong right-side type\n");
}
}
+
/* This function is needed to add and record new static tests (before loop
entry) of variables to make guaratees for index variables. type states
the kind of the test. arrayRef is the array, which length is tested
against, varRef is the variable, that is testes and constant is the
constant value, that is tested.
*/
-void add_new_constraint(methodinfo *m, int type, int arrayRef, int varRef, int constant)
+
+void add_new_constraint(methodinfo *m, loopdata *ld, int type, int arrayRef, int varRef, int constant)
{
struct Constraint *tc;
switch (type) {
case TEST_ZERO: /* a variable is tested against a const */
- tc = c_constraints[varRef]; /* does a test already exist for this var ? */
+ tc = ld->c_constraints[varRef]; /* does a test already exist for this var ? */
while (tc != NULL) {
if (tc->type == TEST_ZERO) {
if (constant < tc->constant)
tc->type = TEST_ZERO;
tc->varRef = varRef;
tc->constant = constant;
- tc->next = c_constraints[varRef];
- c_constraints[varRef] = tc;
- c_needed_instr += 3;
+ tc->next = ld->c_constraints[varRef];
+ ld->c_constraints[varRef] = tc;
+ ld->c_needed_instr += 3;
break;
case TEST_ALENGTH: /* variable is tested against array length */
- tc = c_constraints[varRef]; /* does a test already exist for this var ? */
+ tc = ld->c_constraints[varRef]; /* does a test already exist for this var ? */
while (tc != NULL) {
if ((tc->type == TEST_ALENGTH) && (tc->arrayRef == arrayRef)) {
if (constant > tc->constant)
tc->arrayRef = arrayRef;
tc->varRef = varRef;
tc->constant = constant;
- tc->next = c_constraints[varRef];
- c_constraints[varRef] = tc;
- c_needed_instr += 6;
+ tc->next = ld->c_constraints[varRef];
+ ld->c_constraints[varRef] = tc;
+ ld->c_needed_instr += 6;
/* if arrayRef is not already tested against null, insert that test */
- if (!(c_null_check[arrayRef])) {
- c_null_check[arrayRef] = 1;
- c_needed_instr +=2;
+ if (!(ld->c_null_check[arrayRef])) {
+ ld->c_null_check[arrayRef] = 1;
+ ld->c_needed_instr +=2;
}
break;
case TEST_CONST_ALENGTH: /* a const is tested against array length */
/* does a test already exist for this array */
- tc = c_constraints[m->maxlocals];
+ tc = ld->c_constraints[m->maxlocals];
while (tc != NULL) {
if ((tc->type == TEST_CONST_ALENGTH) && (tc->arrayRef == arrayRef)) {
if (constant > tc->constant)
tc->type = TEST_CONST_ALENGTH;
tc->arrayRef = arrayRef;
tc->constant = constant;
- tc->next = c_constraints[m->maxlocals];
- c_constraints[m->maxlocals] = tc;
- c_needed_instr += 4;
+ tc->next = ld->c_constraints[m->maxlocals];
+ ld->c_constraints[m->maxlocals] = tc;
+ ld->c_needed_instr += 4;
/* if arrayRef is not already tested against null, insert that test */
- if (!(c_null_check[arrayRef])) {
- c_null_check[arrayRef] = 1;
- c_needed_instr +=2;
+ if (!(ld->c_null_check[arrayRef])) {
+ ld->c_null_check[arrayRef] = 1;
+ ld->c_needed_instr +=2;
}
break;
case TEST_UNMOD_ZERO: /* test unmodified var against constant */
/* search if test already exists */
- tc = c_constraints[varRef];
+ tc = ld->c_constraints[varRef];
while (tc != NULL) {
if (tc->type == TEST_UNMOD_ZERO) {
if (constant < tc->constant)
tc->type = TEST_UNMOD_ZERO;
tc->varRef = varRef;
tc->constant = constant;
- tc->next = c_constraints[varRef];
- c_constraints[varRef] = tc;
- c_needed_instr += 3;
+ tc->next = ld->c_constraints[varRef];
+ ld->c_constraints[varRef] = tc;
+ ld->c_needed_instr += 3;
break;
case TEST_UNMOD_ALENGTH: /* test unmodified var against array length */
/* search if test alreay exists */
- tc = c_constraints[varRef];
+ tc = ld->c_constraints[varRef];
while (tc != NULL) {
if ((tc->type == TEST_UNMOD_ALENGTH) && (tc->arrayRef == arrayRef)) {
if (constant > tc->constant)
tc->varRef = varRef;
tc->arrayRef = arrayRef;
tc->constant = constant;
- tc->next = c_constraints[varRef];
- c_constraints[varRef] = tc;
- c_needed_instr += 6;
+ tc->next = ld->c_constraints[varRef];
+ ld->c_constraints[varRef] = tc;
+ ld->c_needed_instr += 6;
/* if arrayRef is not already tested against null, insert that test */
- if (!(c_null_check[arrayRef])) {
- c_null_check[arrayRef] = 1;
- c_needed_instr +=2;
+ if (!(ld->c_null_check[arrayRef])) {
+ ld->c_null_check[arrayRef] = 1;
+ ld->c_needed_instr +=2;
}
break;
/* checks */
/*!! varRef -> maxlocals */
/* search if test already exists */
- tc = c_constraints[m->maxlocals];
+ tc = ld->c_constraints[m->maxlocals];
while (tc != NULL) {
if (tc->type == TEST_RS_ZERO) {
if (constant < tc->constant)
c_mem_error();
tc->type = TEST_RS_ZERO;
tc->constant = constant;
- tc->next = c_constraints[m->maxlocals];
- c_constraints[m->maxlocals] = tc;
- c_needed_instr += (2 + c_rs_needed_instr);
+ tc->next = ld->c_constraints[m->maxlocals];
+ ld->c_constraints[m->maxlocals] = tc;
+ ld->c_needed_instr += (2 + ld->c_rs_needed_instr);
/* if arrayRef on right side is not already tested against null, */
/* insert that test */
- if ((c_rightside->type == TRACE_ALENGTH) && (!(c_null_check[c_rightside->var]))) {
- c_null_check[c_rightside->var] = 1;
- c_needed_instr +=2;
+ if ((ld->c_rightside->type == TRACE_ALENGTH) && (!(ld->c_null_check[ld->c_rightside->var]))) {
+ ld->c_null_check[ld->c_rightside->var] = 1;
+ ld->c_needed_instr +=2;
}
break;
/* checks */
/*!! varRef -> maxlocals */
/* search if test already exists */
- tc = c_constraints[m->maxlocals];
+ tc = ld->c_constraints[m->maxlocals];
while (tc != NULL)
{
if ((tc->type == TEST_RS_ALENGTH) && (tc->arrayRef == arrayRef))
tc->type = TEST_RS_ALENGTH;
tc->arrayRef = arrayRef;
tc->constant = constant;
- tc->next = c_constraints[m->maxlocals];
- c_constraints[m->maxlocals] = tc;
- c_needed_instr += (3 + c_rs_needed_instr);
+ tc->next = ld->c_constraints[m->maxlocals];
+ ld->c_constraints[m->maxlocals] = tc;
+ ld->c_needed_instr += (3 + ld->c_rs_needed_instr);
/* if arrayRef is not already tested against null, insert that test */
- if (!(c_null_check[arrayRef])) {
- c_null_check[arrayRef] = 1;
- c_needed_instr +=2;
+ if (!(ld->c_null_check[arrayRef])) {
+ ld->c_null_check[arrayRef] = 1;
+ ld->c_needed_instr +=2;
}
/* if arrayRef on right side is not already tested against null, */
/* insert that test */
- if ((c_rightside->type == TRACE_ALENGTH) && (!(c_null_check[c_rightside->var]))) {
- c_null_check[c_rightside->var] = 1;
- c_needed_instr +=2;
+ if ((ld->c_rightside->type == TRACE_ALENGTH) && (!(ld->c_null_check[ld->c_rightside->var]))) {
+ ld->c_null_check[ld->c_rightside->var] = 1;
+ ld->c_needed_instr +=2;
}
break;
}
}
+
/* This functions adds new static (before loop enry) tests of variables to the
program to be able to guarantee certain values for index variables in array
access (to safely remove bound checks).
*/
-int insert_static(methodinfo *m, int arrayRef, struct Trace *index, struct Changes *varChanges, int special)
+
+int insert_static(methodinfo *m, loopdata *ld, int arrayRef, struct Trace *index, struct Changes *varChanges, int special)
{
struct LoopVar *lv;
int varRef;
case TRACE_IVAR: /* it is a variable */
if (index->neg < 0) { /* if it's a negated var, return */
#ifdef STATISTICS
- c_stat_no_opt++;
+ ld->c_stat_no_opt++;
#endif
return OPT_NONE;
}
varRef = index->var;
high = low = 0;
- if (c_var_modified[varRef]) { /* volatile var */
+ if (ld->c_var_modified[varRef]) { /* volatile var */
- lv = c_loopvars; /* get reference to loop variable */
+ lv = ld->c_loopvars; /* get reference to loop variable */
while ((lv != NULL) && (lv->value != varRef))
lv = lv->next;
/* the var is never decremented, so we add a static test againt */
/* constant */
if (varChanges->lower_bound > varChanges->upper_bound)
- add_new_constraint(m, TEST_ZERO, arrayRef, varRef, index->constant);
+ add_new_constraint(m, ld, TEST_ZERO, arrayRef, varRef, index->constant);
else
- add_new_constraint(m, TEST_ZERO, arrayRef, varRef, varChanges->lower_bound+index->constant);
+ add_new_constraint(m, ld, TEST_ZERO, arrayRef, varRef, varChanges->lower_bound+index->constant);
low = 1;
}
else if ((lv->dynamic_l_v) && (!special)) {
/* the variable is decremented, but it is checked against a */
/* bound in the loop condition */
if (varChanges->lower_bound <= varChanges->upper_bound) {
- add_new_constraint(m, TEST_RS_ZERO, arrayRef, varRef, varChanges->lower_bound+index->constant+lv->dynamic_l);
+ add_new_constraint(m, ld, TEST_RS_ZERO, arrayRef, varRef, varChanges->lower_bound+index->constant+lv->dynamic_l);
low = 1;
}
}
/* the var is never incremented, so we add a static test againt */
/* constant */
if (varChanges->lower_bound > varChanges->upper_bound)
- add_new_constraint(m, TEST_ALENGTH, arrayRef, varRef, index->constant);
+ add_new_constraint(m, ld, TEST_ALENGTH, arrayRef, varRef, index->constant);
else
- add_new_constraint(m, TEST_ALENGTH, arrayRef, varRef, varChanges->upper_bound+index->constant);
+ add_new_constraint(m, ld, TEST_ALENGTH, arrayRef, varRef, varChanges->upper_bound+index->constant);
high = 1;
}
else if ((lv->dynamic_u_v) && (!special)) {
/* the variable is decremented, but it is checked against a */
/* bound in the loop condition */
if (varChanges->lower_bound <= varChanges->upper_bound) {
- add_new_constraint(m, TEST_RS_ALENGTH, arrayRef, varRef, varChanges->upper_bound+index->constant+lv->dynamic_u);
+ add_new_constraint(m, ld, TEST_RS_ALENGTH, arrayRef, varRef, varChanges->upper_bound+index->constant+lv->dynamic_u);
high = 1;
}
}
}
else { /* the var is never modified at all */
- add_new_constraint(m, TEST_UNMOD_ZERO, arrayRef, index->var, index->constant);
- add_new_constraint(m, TEST_UNMOD_ALENGTH, arrayRef, index->var, index->constant);
+ add_new_constraint(m, ld, TEST_UNMOD_ZERO, arrayRef, index->var, index->constant);
+ add_new_constraint(m, ld, TEST_UNMOD_ALENGTH, arrayRef, index->var, index->constant);
low = high = 1;
}
if ((high > 0) && (low > 0)) {
/* printf("fully optimzed\n"); */
#ifdef STATISTICS
- c_stat_full_opt++;
+ ld->c_stat_full_opt++;
#endif
return OPT_FULL;
}
else if (high > 0) {
/* printf("upper optimzed\n"); */
#ifdef STATISTICS
- c_stat_upper_opt++;
+ ld->c_stat_upper_opt++;
#endif
return OPT_UPPER;
}
else if (low > 0) {
/* printf("lower optimzed\n"); */
#ifdef STATISTICS
- c_stat_lower_opt++;
+ ld->c_stat_lower_opt++;
#endif
return OPT_LOWER;
}
else {
/* printf("not optimzed\n"); */
#ifdef STATISTICS
- c_stat_no_opt++;
+ ld->c_stat_no_opt++;
#endif
return OPT_NONE;
}
case TRACE_ICONST: /* if it is a constant, optimization is easy */
if (index->constant < 0) {
#ifdef STATISTICS
- c_stat_no_opt++;
+ ld->c_stat_no_opt++;
#endif
return OPT_NONE; /* negative index -> bad */
}
else {
- add_new_constraint(m, TEST_CONST_ALENGTH, arrayRef, 0, index->constant);
+ add_new_constraint(m, ld, TEST_CONST_ALENGTH, arrayRef, 0, index->constant);
#ifdef STATISTICS
- c_stat_full_opt++;
+ ld->c_stat_full_opt++;
#endif
return OPT_FULL; /* else just test constant against array length */
}
case TRACE_UNKNOWN:
case TRACE_AVAR:
#ifdef STATISTICS
- c_stat_no_opt++;
+ ld->c_stat_no_opt++;
#endif
return OPT_NONE;
}
/* fisrt, the reference must be loaded, then a null-pointer check is inserted */
/* if not already done earlier. Finally an arraylength instruction is added */
#define LOAD_ARRAYLENGTH(a) { \
- if (c_null_check[a]) { \
+ if (ld->c_null_check[a]) { \
LOAD_ADDR(a); \
GOTO_NOOPT_IF_NULL; \
- c_null_check[a] = 0; \
+ ld->c_null_check[a] = 0; \
} \
LOAD_ADDR(a); \
inst->opc = ICMD_ARRAYLENGTH; \
/* Depending of the type of the right side, the apropriate instructions are */
/* created. */
#define LOAD_RIGHT_SIDE { \
- switch (c_rightside->type) { \
+ switch (ld->c_rightside->type) { \
case TRACE_ICONST: \
- LOAD_CONST(c_rightside->constant); \
+ LOAD_CONST(ld->c_rightside->constant); \
break; \
case TRACE_IVAR: \
- LOAD_VAR(c_rightside->var); \
- LOAD_CONST(c_rightside->constant); \
+ LOAD_VAR(ld->c_rightside->var); \
+ LOAD_CONST(ld->c_rightside->constant); \
ADD; \
break; \
case TRACE_ALENGTH: \
- LOAD_ARRAYLENGTH(c_rightside->var); \
+ LOAD_ARRAYLENGTH(ld->c_rightside->var); \
break; \
default: \
panic("C_ERROR: illegal trace on rightside of loop-header"); \
}
}
+
/* Add the new header node of a loop that has been duplicated to all parent
loops in nesting hierarchie.
*/
-void header_into_parent_loops(struct LoopContainer *lc, basicblock *to_insert, basicblock *replace, basicblock *after)
+
+void header_into_parent_loops(loopdata *ld, struct LoopContainer *lc, basicblock *to_insert, basicblock *replace, basicblock *after)
{
/* we have to insert the node to_insert before the node after and replace */
/* the pointer of to_insert by the node replace */
struct LoopElement *le, *t;
/* if the top of the tree is reached, then return */
- if ((lc == NULL) || (lc == root))
+ if ((lc == NULL) || (lc == ld->root))
return;
/* create new node, that should be inserted */
}
/* go up one hierarchie level */
- header_into_parent_loops(lc->parent, to_insert, replace, after);
+ header_into_parent_loops(ld, lc->parent, to_insert, replace, after);
}
+
/* Add a new node (not header) of a duplicated loop to all parent loops in
nesting hierarchie
*/
-void node_into_parent_loops(struct LoopContainer *lc, basicblock *to_insert)
+
+void node_into_parent_loops(loopdata *ld, struct LoopContainer *lc, basicblock *to_insert)
{
struct LoopElement *le, *t;
/* if the top of the tree is reached, then return */
- if ((lc == NULL) || (lc == root))
+ if ((lc == NULL) || (lc == ld->root))
return;
/* create new node, that should be inserted */
- t = DMNEW(struct LoopElement, 1);
+ t = DNEW(LoopElement);
t->block = to_insert;
t->node = -1;
le->next = t;
/* go up one hierarchie level */
- node_into_parent_loops(NULL, to_insert);
+ node_into_parent_loops(ld, NULL, to_insert);
}
to redirect internal jumps inside the exception handler to the newly
created (copied) nodes.
*/
+
void patch_handler(struct LoopContainer *lc, basicblock *bptr, basicblock *original_head, basicblock *new_head)
{
instruction *ip;
}
-/* This function copys the exception handler and redirects all jumps from the
+/* copy_handler ****************************************************************
+
+ This function copys the exception handler and redirects all jumps from the
original head to the new head in the original exception handler. All
redirection in the copied exception handler is done in patch_handler(...).
-*/
-void copy_handler(methodinfo *m, struct LoopContainer *lc, basicblock *bptr, basicblock *original_head, basicblock *new_head)
+
+*******************************************************************************/
+
+void copy_handler(methodinfo *m, loopdata *ld, struct LoopContainer *lc, basicblock *bptr, basicblock *original_head, basicblock *new_head)
{
instruction *ip;
s4 *s4ptr;
struct LoopElement *le;
basicblock *new, *temp;
- /* If this node has already been copied, return */
+ /* If this node has already been copied, return */
if (bptr->lflags & HANDLER_PART)
return;
- /* The exception handler exists, when control flow enters loop again */
+ /* The exception handler exists, when control flow enters loop again */
if (bptr->lflags & LOOP_PART)
return;
}
}
- /* mark block as part of handler */
+ /* mark block as part of handler */
bptr->lflags |= HANDLER_PART;
- /* copy node */
+ /* copy node */
new = DMNEW(basicblock, 1);
memcpy(new, bptr, sizeof(basicblock));
- new->debug_nr = c_debug_nr++;
+ new->debug_nr = m->c_debug_nr++;
- c_last_block_copied = new;
+ ld->c_last_block_copied = new;
- /* copy instructions and allow one more slot for possible GOTO */
+ /* copy instructions and allow one more slot for possible GOTO */
new->iinstr = DMNEW(instruction, bptr->icount + 1);
- memcpy(new->iinstr, bptr->iinstr, bptr->icount*sizeof(instruction));
+ memcpy(new->iinstr, bptr->iinstr, bptr->icount * sizeof(instruction));
- /* update original block */
+ /* update original block */
bptr->copied_to = new;
- /* append block to global list of basic blocks */
+ /* append block to global list of basic blocks */
temp = m->basicblocks;
while (temp->next)
/* find next block to copy, depending on last instruction of BB */
if (bptr->icount == 0) {
- copy_handler(m, lc, bptr->next, original_head, new_head);
+ copy_handler(m, ld, lc, bptr->next, original_head, new_head);
return;
- }
+ }
ip = bptr->iinstr + (bptr->icount - 1);
- switch (ip->opc) {
- case ICMD_RETURN:
- case ICMD_IRETURN:
- case ICMD_LRETURN:
- case ICMD_FRETURN:
- case ICMD_DRETURN:
- case ICMD_ARETURN:
- case ICMD_ATHROW:
- break;
+ switch (ip->opc) {
+ case ICMD_RETURN:
+ case ICMD_IRETURN:
+ case ICMD_LRETURN:
+ case ICMD_FRETURN:
+ case ICMD_DRETURN:
+ case ICMD_ARETURN:
+ case ICMD_ATHROW:
+ break;
- case ICMD_IFEQ:
- case ICMD_IFNE:
- case ICMD_IFLT:
- case ICMD_IFGE:
- case ICMD_IFGT:
- case ICMD_IFLE:
+ case ICMD_IFEQ:
+ case ICMD_IFNE:
+ case ICMD_IFLT:
+ case ICMD_IFGE:
+ case ICMD_IFGT:
+ case ICMD_IFLE:
- case ICMD_IF_LCMPEQ:
- case ICMD_IF_LCMPLT:
- case ICMD_IF_LCMPLE:
- case ICMD_IF_LCMPNE:
- case ICMD_IF_LCMPGT:
- case ICMD_IF_LCMPGE:
+ case ICMD_IF_LCMPEQ:
+ case ICMD_IF_LCMPLT:
+ case ICMD_IF_LCMPLE:
+ case ICMD_IF_LCMPNE:
+ case ICMD_IF_LCMPGT:
+ case ICMD_IF_LCMPGE:
- case ICMD_IF_LEQ:
- case ICMD_IF_LNE:
- case ICMD_IF_LLT:
- case ICMD_IF_LGE:
- case ICMD_IF_LGT:
- case ICMD_IF_LLE:
+ case ICMD_IF_LEQ:
+ case ICMD_IF_LNE:
+ case ICMD_IF_LLT:
+ case ICMD_IF_LGE:
+ case ICMD_IF_LGT:
+ case ICMD_IF_LLE:
- case ICMD_IFNULL:
- case ICMD_IFNONNULL:
+ case ICMD_IFNULL:
+ case ICMD_IFNONNULL:
- case ICMD_IF_ICMPEQ:
- case ICMD_IF_ICMPNE:
- case ICMD_IF_ICMPLT:
- case ICMD_IF_ICMPGE:
- case ICMD_IF_ICMPGT:
- case ICMD_IF_ICMPLE:
- case ICMD_IF_ACMPEQ:
- case ICMD_IF_ACMPNE:
- copy_handler(m, lc, bptr->next, original_head, new_head);
- /* fall through */
+ case ICMD_IF_ICMPEQ:
+ case ICMD_IF_ICMPNE:
+ case ICMD_IF_ICMPLT:
+ case ICMD_IF_ICMPGE:
+ case ICMD_IF_ICMPGT:
+ case ICMD_IF_ICMPLE:
+ case ICMD_IF_ACMPEQ:
+ case ICMD_IF_ACMPNE:
+ copy_handler(m, ld, lc, bptr->next, original_head, new_head);
+ /* fall through */
- case ICMD_GOTO:
+ case ICMD_GOTO:
- /* redirect jump from original_head to new_head */
- if ((basicblock *) ip->target == original_head)
- ip->target = (void *) new_head;
+ /* redirect jump from original_head to new_head */
+ if ((basicblock *) ip->target == original_head)
+ ip->target = (void *) new_head;
- copy_handler(m, lc, (basicblock *) (ip->target), original_head, new_head);
+ copy_handler(m, ld, lc, (basicblock *) (ip->target), original_head, new_head);
- break;
+ break;
- case ICMD_TABLESWITCH:
- s4ptr = ip->val.a;
- tptr = (void **) ip->target;
+ case ICMD_TABLESWITCH:
+ s4ptr = ip->val.a;
+ tptr = (void **) ip->target;
- /* default branch */
- if (((basicblock *) *tptr) == original_head)
- tptr[0] = (void *) new_head;
-
- copy_handler(m, lc, (basicblock *) *tptr, original_head, new_head);
+ /* default branch */
+ if (((basicblock *) *tptr) == original_head)
+ tptr[0] = (void *) new_head;
- s4ptr++;
- low = *s4ptr;
- s4ptr++;
- high = *s4ptr;
+ copy_handler(m, ld, lc, (basicblock *) *tptr, original_head, new_head);
- count = (high-low+1);
+ s4ptr++;
+ low = *s4ptr;
+ s4ptr++;
+ high = *s4ptr;
- while (--count >= 0) {
- tptr++;
- /* redirect jump from original_head to new_head */
- if (((basicblock *) *tptr) == original_head)
- tptr[0] = (void *) new_head;
- copy_handler(m, lc, (basicblock *) *tptr, original_head, new_head);
- }
- break;
-
- case ICMD_LOOKUPSWITCH:
- s4ptr = ip->val.a;
- tptr = (void **) ip->target;
+ count = (high-low+1);
- /* default branch */
+ while (--count >= 0) {
+ tptr++;
+ /* redirect jump from original_head to new_head */
if (((basicblock *) *tptr) == original_head)
tptr[0] = (void *) new_head;
+ copy_handler(m, ld, lc, (basicblock *) *tptr, original_head, new_head);
+ }
+ break;
+
+ case ICMD_LOOKUPSWITCH:
+ s4ptr = ip->val.a;
+ tptr = (void **) ip->target;
- copy_handler(m, lc, (basicblock *) *tptr, original_head, new_head);
+ /* default branch */
+ if (((basicblock *) *tptr) == original_head)
+ tptr[0] = (void *) new_head;
- ++s4ptr;
- count = *s4ptr;
+ copy_handler(m, ld, lc, (basicblock *) *tptr, original_head, new_head);
- while (--count >= 0) {
- ++tptr;
- /* redirect jump from original_head to new_head */
- if (((basicblock *) *tptr) == original_head)
- tptr[0] = (void *) new_head;
- copy_handler(m, lc, (basicblock *) *tptr, original_head, new_head);
- }
- break;
+ ++s4ptr;
+ count = *s4ptr;
+
+ while (--count >= 0) {
+ ++tptr;
+ /* redirect jump from original_head to new_head */
+ if (((basicblock *) *tptr) == original_head)
+ tptr[0] = (void *) new_head;
+ copy_handler(m, ld, lc, (basicblock *) *tptr, original_head, new_head);
+ }
+ break;
- case ICMD_JSR:
- c_last_target = bptr;
- copy_handler(m, lc, (basicblock *) (ip->target), original_head, new_head);
- break;
+ case ICMD_JSR:
+ ld->c_last_target = bptr;
+ copy_handler(m, ld, lc, (basicblock *) (ip->target), original_head, new_head);
+ break;
- case ICMD_RET:
- copy_handler(m, lc, c_last_target->next, original_head, new_head);
- break;
+ case ICMD_RET:
+ copy_handler(m, ld, lc, ld->c_last_target->next, original_head, new_head);
+ break;
- default:
- copy_handler(m, lc, bptr->next, original_head, new_head);
- break;
- }
-
+ default:
+ copy_handler(m, ld, lc, bptr->next, original_head, new_head);
+ break;
+ }
}
have to be duplicated as well. The following function together with the
two helper functions copy_handler and patch_handler perform this task.
*/
-void update_internal_exceptions(methodinfo *m, struct LoopContainer *lc, basicblock *original_head, basicblock *new_head)
+
+void update_internal_exceptions(methodinfo *m, loopdata *ld, struct LoopContainer *lc, basicblock *original_head, basicblock *new_head)
{
exceptiontable *ex, *new;
struct LoopContainer *l;
/* Call update_internal for all nested (=child) loops */
l = lc->tree_down;
while (l != NULL) {
- update_internal_exceptions(m, l, original_head, new_head);
+ update_internal_exceptions(m, ld, l, original_head, new_head);
l = l->tree_right;
}
while (ex != NULL) {
/* Copy the exception and patch the jumps */
- copy_handler(m, lc, ex->handler, original_head, new_head);
+ copy_handler(m, ld, lc, ex->handler, original_head, new_head);
patch_handler(lc, ex->handler, original_head, new_head);
/* Insert a new exception into the global exception table */
}
+
/* If a loop is duplicated, all exceptions that contain this loop have to be
extended to the copied nodes as well. The following function checks for
all exceptions of all parent loops, whether they contain the loop pointed to
by lc. If so, the exceptions are extended to contain all newly created nodes.
*/
-void update_external_exceptions(methodinfo *m, struct LoopContainer *lc, int loop_head)
+
+void update_external_exceptions(methodinfo *m, loopdata *ld, struct LoopContainer *lc, int loop_head)
{
exceptiontable *ex, *new;
ex->down = new;
/* Set new start and end point of this exception */
- new->start = c_first_block_copied;
- new->end = c_last_block_copied;
+ new->start = ld->c_first_block_copied;
+ new->end = ld->c_last_block_copied;
ex = new->next;
}
}
/* Call update_external for parent node */
- update_external_exceptions(m, lc->parent, loop_head);
+ update_external_exceptions(m, ld, lc->parent, loop_head);
}
-
/* This function is needed to insert the static checks, stored in c_constraints
into the intermediate code.
*/
-void create_static_checks(methodinfo *m, struct LoopContainer *lc)
+
+void create_static_checks(methodinfo *m, loopdata *ld, struct LoopContainer *lc)
{
int i, stackdepth, cnt;
struct Constraint *tc1;
exceptiontable *ex;
#ifdef STATISTICS
- /* show_loop_statistics(); */
+ /* show_loop_statistics(l); */
#endif
- loop_head = &m->basicblocks[c_current_head];
- c_first_block_copied = c_last_block_copied = NULL;
+ loop_head = &m->basicblocks[ld->c_current_head];
+ ld->c_first_block_copied = ld->c_last_block_copied = NULL;
/* the loop nodes are copied */
le = lc->nodes;
{
bptr = DMNEW(basicblock, 1);
memcpy(bptr, le->block, sizeof(basicblock));
- bptr->debug_nr = c_debug_nr++;
+ bptr->debug_nr = m->c_debug_nr++;
/* determine beginning of copied loop to extend exception handler, that */
/* protect this loop */
- if (c_first_block_copied == NULL)
- c_first_block_copied = bptr;
+ if (ld->c_first_block_copied == NULL)
+ ld->c_first_block_copied = bptr;
/* copy instructions and add one more slot for possible GOTO */
bptr->iinstr = DMNEW(instruction, bptr->icount + 1);
temp->next = bptr;
bptr->next = NULL;
- node_into_parent_loops(lc->parent, bptr);
+ node_into_parent_loops(ld, lc->parent, bptr);
le = le->next;
}
- c_last_block_copied = bptr;
+ ld->c_last_block_copied = bptr;
/* create an additional basicblock for dynamic checks */
original_start = bptr = DMNEW(basicblock, 1);
/* copy current loop header to new basic block */
memcpy(bptr, loop_head, sizeof(basicblock));
- bptr->debug_nr = c_debug_nr++;
+ bptr->debug_nr = m->c_debug_nr++;
/* insert the new basic block and move header before first loop node */
le = lc->nodes;
/* if first loop block is first BB of global list, insert loop_head at */
/* beginning of global BB list */
if (temp == le->block) {
- if (c_newstart == NULL) {
- c_needs_redirection = true;
- c_newstart = loop_head;
+ if (ld->c_newstart == NULL) {
+ ld->c_needs_redirection = true;
+ ld->c_newstart = loop_head;
loop_head->next = m->basicblocks;
}
else {
- loop_head->next = c_newstart;
- c_newstart = loop_head;
+ loop_head->next = ld->c_newstart;
+ ld->c_newstart = loop_head;
}
}
else {
/* insert new header node into nodelists of all enclosing loops */
- header_into_parent_loops(lc, loop_head, original_start, le->block);
+ header_into_parent_loops(ld, lc, loop_head, original_start, le->block);
/* prepare instruction array to insert checks */
- inst = loop_head->iinstr = DMNEW(instruction, c_needed_instr + 2);
- loop_head->icount = c_needed_instr + 1;
+ inst = loop_head->iinstr = DMNEW(instruction, ld->c_needed_instr + 2);
+ loop_head->icount = ld->c_needed_instr + 1;
/* init instruction array */
- for (cnt=0; cnt<c_needed_instr + 1; ++cnt) {
+ for (cnt=0; cnt<ld->c_needed_instr + 1; ++cnt) {
inst[0].opc = ICMD_NOP;
inst[0].dst = NULL;
}
/* step through all inserted checks and create instructions for them */
for (i=0; i<m->maxlocals+1; ++i)
{
- tc1 = c_constraints[i];
+ tc1 = ld->c_constraints[i];
while (tc1 != NULL)
{
switch (tc1->type)
tc1 = tc1->next;
}
- c_constraints[i] = NULL;
+ ld->c_constraints[i] = NULL;
}
/* if all tests succeed, jump to optimized loop header */
/* if exceptions have to be correct due to loop duplication these two */
/* functions perform this task. */
- update_internal_exceptions(m, lc, loop_head, original_start);
- update_external_exceptions(m, lc->parent, lc->loop_head);
+ update_internal_exceptions(m, ld, lc, loop_head, original_start);
+ update_external_exceptions(m, ld, lc->parent, lc->loop_head);
}
return tmp;
}
+
/* This function performs the main task of bound check removal. It removes
all bound-checks in node. change is a pointer to an array of struct Changes
that reflect for all local variables, how their values have changed from
the start of the loop. The special flag is needed to deal with the header
node.
*/
-void remove_boundchecks(methodinfo *m, int node, int from, struct Changes **change, int special)
+
+void remove_boundchecks(methodinfo *m, loopdata *ld, int node, int from, struct Changes **change, int special)
{
basicblock bp;
instruction *ip;
/* a flag, that is set, when previous optimzations have to be taken back */
degrade_checks = 0;
- if (c_current_loop[node] > 0) { /* this node is part of the loop */
- if (c_current_loop[node] > 1) { /* it is not the header node */
+ if (ld->c_current_loop[node] > 0) { /* this node is part of the loop */
+ if (ld->c_current_loop[node] > 1) { /* it is not the header node */
/* get variable changes, already recorded for this node */
- t1 = c_dTable[node]->changes;
+ t1 = ld->c_dTable[node]->changes;
if (t1 != NULL) { /* it is not the first visit */
- if ((c_nestedLoops[node] != c_current_head) && (c_nestedLoops[node] == c_nestedLoops[from])) {
+ if ((ld->c_nestedLoops[node] != ld->c_current_head) && (ld->c_nestedLoops[node] == ld->c_nestedLoops[from])) {
/* we are looping in a nested loop, so made optimizations */
/* need to be reconsidered */
degrade_checks = 1;
}
else { /* first visit */
/* printf("first visit - constraints cloned\n"); */
- c_dTable[node]->changes = constraints_clone(m, change);
+ ld->c_dTable[node]->changes = constraints_clone(m, change);
}
/* tmp now holds a copy of the updated variable changes */
- tmp = constraints_clone(m, c_dTable[node]->changes);
+ tmp = constraints_clone(m, ld->c_dTable[node]->changes);
}
else if (special) { /* header and need special traetment */
/* printf("special treatment called\n"); */
#ifdef STATISTICS
if (ip->op1 == OPT_UNCHECKED) { /* found new access */
- c_stat_array_accesses++;
+ ld->c_stat_array_accesses++;
ip->op1 = OPT_NONE;
- c_stat_no_opt++;
+ ld->c_stat_no_opt++;
}
#endif
/* can only optimize known arrays that do not change */
- if ((t_array->type != TRACE_AVAR) || (c_var_modified[t_array->var]))
+ if ((t_array->type != TRACE_AVAR) || (ld->c_var_modified[t_array->var]))
break;
switch (t_index->type) { /* now we look at the index */
case OPT_UNCHECKED:
break;
case OPT_NONE:
- c_stat_no_opt--;
+ ld->c_stat_no_opt--;
break;
case OPT_FULL:
- c_stat_full_opt--;
+ ld->c_stat_full_opt--;
break;
case OPT_UPPER:
- c_stat_upper_opt--;
+ ld->c_stat_upper_opt--;
break;
case OPT_LOWER:
- c_stat_lower_opt--;
+ ld->c_stat_lower_opt--;
break;
}
#endif
if (degrade_checks) /* replace existing optimization */
- ip->op1 = insert_static(m, t_array->var, t_index, NULL, special);
+ ip->op1 = insert_static(m, ld, t_array->var, t_index, NULL, special);
else {
/* Check current optimization and try to improve it by */
/* inserting new checks */
switch (ip->op1) {
case OPT_UNCHECKED:
- ip->op1 = insert_static(m, t_array->var, t_index, NULL, special);
+ ip->op1 = insert_static(m, ld, t_array->var, t_index, NULL, special);
break;
case OPT_NONE:
- ip->op1 = insert_static(m, t_array->var, t_index, NULL, special);
+ ip->op1 = insert_static(m, ld, t_array->var, t_index, NULL, special);
break;
case OPT_UPPER:
- opt_level = insert_static(m, t_array->var, t_index, NULL, special);
+ opt_level = insert_static(m, ld, t_array->var, t_index, NULL, special);
if ((opt_level == OPT_FULL) || (opt_level == OPT_LOWER))
ip->op1 = OPT_FULL;
break;
case OPT_LOWER:
- opt_level = insert_static(m, t_array->var, t_index, NULL, special);
+ opt_level = insert_static(m, ld, t_array->var, t_index, NULL, special);
if ((opt_level == OPT_FULL) || (opt_level == OPT_UPPER))
ip->op1 = OPT_FULL;
break;
case OPT_FULL:
#ifdef STATISTICS
- c_stat_full_opt++;
+ ld->c_stat_full_opt++;
#endif
break;
}
case OPT_UNCHECKED:
break;
case OPT_NONE:
- c_stat_no_opt--;
+ ld->c_stat_no_opt--;
break;
case OPT_FULL:
- c_stat_full_opt--;
+ ld->c_stat_full_opt--;
break;
case OPT_UPPER:
- c_stat_upper_opt--;
+ ld->c_stat_upper_opt--;
break;
case OPT_LOWER:
- c_stat_lower_opt--;
+ ld->c_stat_lower_opt--;
break;
}
#endif
if (degrade_checks)
- ip->op1 = insert_static(m, t_array->var, t_index, t, special);
+ ip->op1 = insert_static(m, ld, t_array->var, t_index, t, special);
else {
/* Check current optimization and try to improve it by */
/* insert new check. t reflects var changes for index */
switch (ip->op1) {
case OPT_UNCHECKED:
- ip->op1 = insert_static(m, t_array->var, t_index, t, special);
+ ip->op1 = insert_static(m, ld, t_array->var, t_index, t, special);
break;
case OPT_NONE:
- ip->op1 = insert_static(m, t_array->var, t_index, t, special);
+ ip->op1 = insert_static(m, ld, t_array->var, t_index, t, special);
break;
case OPT_UPPER:
- opt_level = insert_static(m, t_array->var, t_index, t, special);
+ opt_level = insert_static(m, ld, t_array->var, t_index, t, special);
if ((opt_level == OPT_FULL) || (opt_level == OPT_LOWER))
ip->op1 = OPT_FULL;
break;
case OPT_LOWER:
- opt_level = insert_static(m, t_array->var, t_index, t, special);
+ opt_level = insert_static(m, ld, t_array->var, t_index, t, special);
if ((opt_level == OPT_FULL) || (opt_level == OPT_UPPER))
ip->op1 = OPT_FULL;
break;
case OPT_FULL:
#ifdef STATISTICS
- c_stat_full_opt++;
+ ld->c_stat_full_opt++;
#endif
break;
}
} /* for */
if (!special) { /* we are not interested in only the header */
- d = c_dTable[node];
+ d = ld->c_dTable[node];
while (d != NULL) { /* check all sucessors of current node */
- remove_boundchecks(m, d->value, node, tmp, special);
+ remove_boundchecks(m, ld, d->value, node, tmp, special);
d = d->next;
}
}
} /* if */
}
+
/* This function calls the bound-check removal function for the header node
with a special flag. It is important to notice, that no dynamic
constraint hold in the header node (because the comparison is done at
block end).
*/
-void remove_header_boundchecks(methodinfo *m, int node, struct Changes **changes)
+
+void remove_header_boundchecks(methodinfo *m, loopdata *ld, int node, struct Changes **changes)
{
- remove_boundchecks(m, node, -1, changes, BOUNDCHECK_SPECIAL);
+ remove_boundchecks(m, ld, node, -1, changes, BOUNDCHECK_SPECIAL);
}
+
/* Marks all basicblocks that are part of the loop
*/
+
void mark_loop_nodes(struct LoopContainer *lc)
{
struct LoopElement *le = lc->nodes;
}
}
+
/* Clears mark for all basicblocks that are part of the loop
*/
-void unmark_loop_nodes(struct LoopContainer *lc)
+void unmark_loop_nodes(LoopContainer *lc)
{
- struct LoopElement *le = lc->nodes;
+ LoopElement *le = lc->nodes;
while (le != NULL) {
le->block->lflags = 0;
le = le->next;
- }
+ }
}
identify array accesses suitable for optimization (bound check removal). The
intermediate code is then modified to reflect these optimizations.
*/
-void optimize_single_loop(methodinfo *m, struct LoopContainer *lc)
+void optimize_single_loop(methodinfo *m, loopdata *ld, LoopContainer *lc)
{
struct LoopElement *le;
struct depthElement *d;
if ((changes = (struct Changes **) malloc(m->maxlocals * sizeof(struct Changes *))) == NULL)
c_mem_error();
- head = c_current_head = lc->loop_head;
- c_needed_instr = c_rs_needed_instr = 0;
+ head = ld->c_current_head = lc->loop_head;
+ ld->c_needed_instr = ld->c_rs_needed_instr = 0;
/* init array for null ptr checks */
for (i=0; i<m->maxlocals; ++i)
- c_null_check[i] = 0;
+ ld->c_null_check[i] = 0;
/* don't optimize root node (it is the main procedure, not a loop) */
return;
/* setup variables with initial values */
- c_loopvars = NULL;
+ ld->c_loopvars = NULL;
for (i=0; i < m->basicblockcount; ++i) {
- c_toVisit[i] = 0;
- c_current_loop[i] = -1;
- if ((d = c_dTable[i]) != NULL)
+ ld->c_toVisit[i] = 0;
+ ld->c_current_loop[i] = -1;
+ if ((d = ld->c_dTable[i]) != NULL)
d->changes = NULL;
}
for (i=0; i < m->maxlocals; ++i) {
- c_var_modified[i] = 0;
+ ld->c_var_modified[i] = 0;
if (changes[i] != NULL) {
changes[i] = NULL;
}
}
for (i=0; i < (m->maxlocals+1); ++i) {
- if (c_constraints[i] != NULL) {
- c_constraints[i] = NULL;
+ if (ld->c_constraints[i] != NULL) {
+ ld->c_constraints[i] = NULL;
}
}
node = le->node;
if (node == head)
- c_current_loop[node] = 1; /* the header node gets 1 */
- else if (c_nestedLoops[node] == head)
- c_current_loop[node] = 2; /* top level nodes get 2 */
+ ld->c_current_loop[node] = 1; /* the header node gets 1 */
+ else if (ld->c_nestedLoops[node] == head)
+ ld->c_current_loop[node] = 2; /* top level nodes get 2 */
else
- c_current_loop[node] = 3; /* nodes, part of nested loop get 3 */
+ ld->c_current_loop[node] = 3; /* nodes, part of nested loop get 3 */
- c_toVisit[node] = 1;
+ ld->c_toVisit[node] = 1;
le = le->next;
}
fflush(stdout);
#endif
- if (analyze_for_array_access(m, head) > 0) {/* loop contains array access */
+ if (analyze_for_array_access(m, ld, head) > 0) {/* loop contains array access */
#ifdef LOOP_DEBUG
struct LoopVar *lv;
printf("analyze for array access finished and found\n");
fflush(stdout);
- lv = c_loopvars;
+ lv = ld->c_loopvars;
while (lv != NULL) {
if (lv->modified)
printf("Var --> %d\n", lv->value);
/* for performance reasons the list of all interesting loop vars is */
/* scaned and for all modified vars a flag in c_var_modified is set */
- scan_global_list();
+ scan_global_list(ld);
#ifdef LOOP_DEBUG
printf("global list scanned\n");
/* if the loop header contains or-conditions or an index variable */
/* is modified in the catch-block within the loop, a conservative */
/* approach is taken and optimizations are cancelled */
- if (analyze_or_exceptions(m, head, lc) > 0) {
+ if (analyze_or_exceptions(m, ld, head, lc) > 0) {
#ifdef LOOP_DEBUG
printf("Analyzed for or/exception - no problems \n");
fflush(stdout);
#endif
- init_constraints(m, head); /* analyze dynamic bounds in header */
+ init_constraints(m, ld, head); /* analyze dynamic bounds in header */
#ifdef LOOP_DEBUG
show_right_side();
#endif
- if (c_rightside == NULL)
+ if (ld->c_rightside == NULL)
return;
/* single pass bound check removal - for all successors, do */
- remove_header_boundchecks(m, head, changes);
+ remove_header_boundchecks(m, ld, head, changes);
- d = c_dTable[head];
+ d = ld->c_dTable[head];
while (d != NULL) {
- remove_boundchecks(m, d->value, -1, changes, BOUNDCHECK_REGULAR);
+ remove_boundchecks(m, ld, d->value, -1, changes, BOUNDCHECK_REGULAR);
d = d->next;
}
fflush(stdout);
#endif
- create_static_checks(m, lc); /* create checks */
+ create_static_checks(m, ld, lc); /* create checks */
#ifdef LOOP_DEBUG
printf("END: create static checks\n");
printf("No array accesses found\n"); */
#ifdef STATISTICS
- c_stat_num_loops++; /* increase number of loops */
-
- c_stat_sum_accesses += c_stat_array_accesses;
- c_stat_sum_full += c_stat_full_opt;
- c_stat_sum_no += c_stat_no_opt;
- c_stat_sum_lower += c_stat_lower_opt;
- c_stat_sum_upper += c_stat_upper_opt;
- c_stat_sum_or += c_stat_or;
- c_stat_sum_exception += c_stat_exception;
-
- c_stat_array_accesses = 0;
- c_stat_full_opt = 0;
- c_stat_no_opt = 0;
- c_stat_lower_opt = 0;
- c_stat_upper_opt = 0;
- c_stat_or = c_stat_exception = 0;
+ ld->c_stat_num_loops++; /* increase number of loops */
+
+ ld->c_stat_sum_accesses += ld->c_stat_array_accesses;
+ ld->c_stat_sum_full += ld->c_stat_full_opt;
+ ld->c_stat_sum_no += ld->c_stat_no_opt;
+ ld->c_stat_sum_lower += ld->c_stat_lower_opt;
+ ld->c_stat_sum_upper += ld->c_stat_upper_opt;
+ ld->c_stat_sum_or += ld->c_stat_or;
+ ld->c_stat_sum_exception += ld->c_stat_exception;
+
+ ld->c_stat_array_accesses = 0;
+ ld->c_stat_full_opt = 0;
+ ld->c_stat_no_opt = 0;
+ ld->c_stat_lower_opt = 0;
+ ld->c_stat_upper_opt = 0;
+ ld->c_stat_or = ld->c_stat_exception = 0;
#endif
}
+
/* This function preforms necessary setup work, before the recursive function
optimize_single loop can be called.
*/
-void optimize_loops(methodinfo *m)
+void optimize_loops(methodinfo *m, loopdata *ld)
{
- struct LoopContainer *lc = c_allLoops;
+ LoopContainer *lc = ld->c_allLoops;
/* first, merge loops with same header node - all loops with the same */
/* header node are optimizied in one pass, because they all depend on the */
fflush(stdout);
#endif
- analyze_double_headers();
+ analyze_double_headers(ld);
/* create array with loop nesting levels - nested loops cause problems, */
/* especially, when they modify index variables used in surrounding loops */
fflush(stdout);
#endif
- analyze_nested(m);
+ analyze_nested(m, ld);
#ifdef LOOP_DEBUG
printf("analyze nested done\n");
#endif
/* create array with entries for current loop */
- c_current_loop = DMNEW(int, m->basicblockcount);
- c_toVisit = DMNEW(int, m->basicblockcount);
- c_var_modified = DMNEW(int, m->maxlocals);
- c_null_check = DMNEW(int, m->maxlocals);
+ ld->c_current_loop = DMNEW(int, m->basicblockcount);
+ ld->c_toVisit = DMNEW(int, m->basicblockcount);
+ ld->c_var_modified = DMNEW(int, m->maxlocals);
+ ld->c_null_check = DMNEW(int, m->maxlocals);
- if ((c_constraints = (struct Constraint **) malloc((m->maxlocals+1) * sizeof(struct Constraint *))) == NULL)
+ if ((ld->c_constraints = (struct Constraint **) malloc((m->maxlocals+1) * sizeof(struct Constraint *))) == NULL)
c_mem_error();
#ifdef STATISTICS
- c_stat_num_loops = 0; /* set statistic vars to zero */
- c_stat_array_accesses = c_stat_sum_accesses = 0;
- c_stat_full_opt = c_stat_sum_full = 0;
- c_stat_no_opt = c_stat_sum_no = 0;
- c_stat_lower_opt = c_stat_sum_lower = 0;
- c_stat_upper_opt = c_stat_sum_upper = 0;
- c_stat_or = c_stat_sum_or = 0;
- c_stat_exception = c_stat_sum_exception = 0;
+ ld->c_stat_num_loops = 0; /* set statistic vars to zero */
+ ld->c_stat_array_accesses = ld->c_stat_sum_accesses = 0;
+ ld->c_stat_full_opt = ld->c_stat_sum_full = 0;
+ ld->c_stat_no_opt = ld->c_stat_sum_no = 0;
+ ld->c_stat_lower_opt = ld->c_stat_sum_lower = 0;
+ ld->c_stat_upper_opt = ld->c_stat_sum_upper = 0;
+ ld->c_stat_or = ld->c_stat_sum_or = 0;
+ ld->c_stat_exception = ld->c_stat_sum_exception = 0;
#endif
/* init vars needed by all loops */
- c_needs_redirection = false;
- c_newstart = NULL;
- c_old_xtablelength = m->exceptiontablelength;
+ ld->c_needs_redirection = false;
+ ld->c_newstart = NULL;
+ ld->c_old_xtablelength = m->exceptiontablelength;
/* loops have been topologically sorted */
- lc = c_allLoops;
+ lc = ld->c_allLoops;
while (lc != NULL) {
- optimize_single_loop(m, lc);
+ optimize_single_loop(m, ld, lc);
#ifdef LOOP_DEBUG
printf(" *** Optimized loop *** \n");
#endif
/* if global BB list start is modified, set block to new start */
- if (c_needs_redirection == true)
- m->basicblocks = c_newstart;
+ if (ld->c_needs_redirection == true)
+ m->basicblocks = ld->c_newstart;
}
Authors: Christian Thalinger
- $Id: analyze.h 1203 2004-06-22 23:14:55Z twisti $
+ $Id: analyze.h 1454 2004-11-05 14:19:32Z twisti $
*/
#ifndef _ANALYZE_H
#define _ANALYZE_H
-
#include "global.h"
+#include "jit/loop/loop.h"
-void optimize_loops(methodinfo *m);
+void optimize_loops(methodinfo *m, loopdata *ld);
#endif /* _ANALYZE_H */
Contains the functions which build a list, that represents the
control flow graph of the procedure, that is being analyzed.
- $Id: graph.c 1203 2004-06-22 23:14:55Z twisti $
+ $Id: graph.c 1454 2004-11-05 14:19:32Z twisti $
*/
depthFirst() builds the control flow graph out of the intermediate code of
the procedure, that is to be optimized and stores the list in the global
variable c_dTable
-*/
-void depthFirst(methodinfo *m)
+*/
+
+void depthFirst(methodinfo *m, loopdata *ld)
{
int i;
/* allocate memory and init gobal variables needed by function dF(m, int, int) */
- c_defnum = DMNEW(int, m->basicblockcount);
- c_numPre = DMNEW(int, m->basicblockcount);
- c_parent = DMNEW(int, m->basicblockcount);
- c_reverse = DMNEW(int, m->basicblockcount);
- c_pre = DMNEW(int *, m->basicblockcount);
- c_dTable = DMNEW(struct depthElement *, m->basicblockcount);
+ ld->c_defnum = DMNEW(int, m->basicblockcount);
+ ld->c_numPre = DMNEW(int, m->basicblockcount);
+ ld->c_parent = DMNEW(int, m->basicblockcount);
+ ld->c_reverse = DMNEW(int, m->basicblockcount);
+ ld->c_pre = DMNEW(int *, m->basicblockcount);
+ ld->c_dTable = DMNEW(struct depthElement *, m->basicblockcount);
for (i = 0; i < m->basicblockcount; ++i) {
- c_defnum[i] = c_parent[i] = -1;
- c_numPre[i] = c_reverse[i] = 0;
+ ld->c_defnum[i] = ld->c_parent[i] = -1;
+ ld->c_numPre[i] = ld->c_reverse[i] = 0;
- c_pre[i] = DMNEW(int, m->basicblockcount);
- c_dTable[i] = NULL;
+ ld->c_pre[i] = DMNEW(int, m->basicblockcount);
+ ld->c_dTable[i] = NULL;
}
- c_globalCount = 0;
- c_allLoops = NULL;
+ ld->c_globalCount = 0;
+ ld->c_allLoops = NULL;
- dF(m, -1, 0); /* call helper function dF that traverses basic block structure */
+ dF(m, ld, -1, 0); /* call helper function dF that traverses basic block structure */
}
control flow graph in a depth-first order, thereby building up the adeacency
list c_dTable
*/
-void dF(methodinfo *m, int from, int blockIndex)
+
+void dF(methodinfo *m, loopdata *ld, int from, int blockIndex)
{
instruction *ip;
s4 *s4ptr;
if (from >= 0) {
/* the current basic block has a predecessor (ie. is not the first one) */
-/* if ((hp = (struct depthElement *) malloc(sizeof(struct depthElement))) == NULL) */
- /* c_mem_error(); */
hp = DNEW(struct depthElement);/* create new depth element */
- hp->next = c_dTable[from]; /* insert values */
+ hp->next = ld->c_dTable[from]; /* insert values */
hp->value = blockIndex;
hp->changes = NULL;
- c_dTable[from] = hp; /* insert into table */
+ ld->c_dTable[from] = hp; /* insert into table */
}
if (from == blockIndex) { /* insert one node loops into loop container */
-/* if ((tmp = (struct LoopContainer *) malloc(sizeof(struct LoopContainer))) == NULL) */
-/* c_mem_error(); */
tmp = DNEW(struct LoopContainer);
LoopContainerInit(m, tmp, blockIndex);
- tmp->next = c_allLoops;
- c_allLoops = tmp;
+ tmp->next = ld->c_allLoops;
+ ld->c_allLoops = tmp;
}
#ifdef C_DEBUG
ip = m->basicblocks[blockIndex].iinstr + m->basicblocks[blockIndex].icount -1;
/* set ip to last instruction */
- if (c_defnum[blockIndex] == -1) { /* current block has not been visited */
- c_defnum[blockIndex] = c_globalCount; /* update global count */
- c_parent[blockIndex] = from; /* write parent block of current one */
- c_reverse[c_globalCount] = blockIndex;
- ++c_globalCount;
+ if (ld->c_defnum[blockIndex] == -1) { /* current block has not been visited */
+ ld->c_defnum[blockIndex] = ld->c_globalCount; /* update global count */
+ ld->c_parent[blockIndex] = from; /* write parent block of current one */
+ ld->c_reverse[ld->c_globalCount] = blockIndex;
+ ++ld->c_globalCount;
if (!m->basicblocks[blockIndex].icount) {
/* block does not contain instructions */
- dF(m, blockIndex, blockIndex+1);
+ dF(m, ld, blockIndex, blockIndex+1);
}
else { /* for all successors, do */
switch (ip->opc) { /* check type of last instruction */
case ICMD_IF_ICMPLE:
case ICMD_IF_ACMPEQ:
case ICMD_IF_ACMPNE: /* branch -> check next block */
- dF(m, blockIndex, blockIndex + 1);
+ dF(m, ld, blockIndex, blockIndex + 1);
/* fall throu */
case ICMD_GOTO:
- dF(m, blockIndex, m->basicblockindex[ip->op1]);
+ dF(m, ld, blockIndex, m->basicblockindex[ip->op1]);
break; /* visit branch (goto) target */
case ICMD_TABLESWITCH: /* switch statement */
s4ptr = ip->val.a;
- dF(m, blockIndex, m->basicblockindex[*s4ptr]); /* default branch */
+ dF(m, ld, blockIndex, m->basicblockindex[*s4ptr]); /* default branch */
s4ptr++;
low = *s4ptr;
while (--count >= 0) {
s4ptr++;
- dF(m, blockIndex, m->basicblockindex[*s4ptr]);
+ dF(m, ld, blockIndex, m->basicblockindex[*s4ptr]);
}
break;
case ICMD_LOOKUPSWITCH: /* switch statement */
s4ptr = ip->val.a;
- dF(m, blockIndex, m->basicblockindex[*s4ptr]); /* default branch */
+ dF(m, ld, blockIndex, m->basicblockindex[*s4ptr]); /* default branch */
++s4ptr;
count = *s4ptr++;
while (--count >= 0) {
- dF(m, blockIndex, m->basicblockindex[s4ptr[1]]);
+ dF(m, ld, blockIndex, m->basicblockindex[s4ptr[1]]);
s4ptr += 2;
}
break;
case ICMD_JSR:
- c_last_jump = blockIndex;
- dF(m, blockIndex, m->basicblockindex[ip->op1]);
+ ld->c_last_jump = blockIndex;
+ dF(m, ld, blockIndex, m->basicblockindex[ip->op1]);
break;
case ICMD_RET:
- dF(m, blockIndex, c_last_jump+1);
+ dF(m, ld, blockIndex, ld->c_last_jump+1);
break;
default:
- dF(m, blockIndex, blockIndex + 1);
+ dF(m, ld, blockIndex, blockIndex + 1);
break;
}
}
}
- for (ptr = c_pre[blockIndex], cnt = 0; cnt < c_numPre[blockIndex]; ++cnt, ++ptr)
+ for (ptr = ld->c_pre[blockIndex], cnt = 0; cnt < ld->c_numPre[blockIndex]; ++cnt, ++ptr)
{
if (*ptr == from)
break;
}
- if (cnt >= c_numPre[blockIndex]) {
- c_pre[blockIndex][c_numPre[blockIndex]] = from;
+ if (cnt >= ld->c_numPre[blockIndex]) {
+ ld->c_pre[blockIndex][ld->c_numPre[blockIndex]] = from;
/* add predeccessors to list c_pre */
- c_numPre[blockIndex]++; /* increase number of predecessors */
- }
+ ld->c_numPre[blockIndex]++; /* increase number of predecessors */
+ }
}
+
/*
- a slightly modified version of dF(m, int, int) that is used to traverse the part
+ a slightly modified version of dF(m, ld, int, int) that is used to traverse the part
of the control graph that is not reached by normal program flow but by the
raising of exceptions (code of catch blocks)
*/
-void dF_Exception(methodinfo *m, int from, int blockIndex)
+
+void dF_Exception(methodinfo *m, loopdata *ld, int from, int blockIndex)
{
instruction *ip;
s4 *s4ptr;
int high, low, count;
struct depthElement *hp;
- if (c_exceptionVisit[blockIndex] < 0) /* has block been visited, return */
- c_exceptionVisit[blockIndex] = 1;
+ if (ld->c_exceptionVisit[blockIndex] < 0) /* has block been visited, return */
+ ld->c_exceptionVisit[blockIndex] = 1;
else
return;
- if (c_dTable[blockIndex] != NULL) /* back to regular code section */
+ if (ld->c_dTable[blockIndex] != NULL) /* back to regular code section */
return;
if (from >= 0) { /* build exception graph (in c_exceptionGraph) */
-/* if ((hp = (struct depthElement *) malloc(sizeof(struct depthElement))) == NULL) */
-/* c_mem_error(); */
hp = DNEW(struct depthElement);
- hp->next = c_exceptionGraph[from];
+ hp->next = ld->c_exceptionGraph[from];
hp->value = blockIndex;
hp->changes = NULL;
- c_exceptionGraph[from] = hp;
+ ld->c_exceptionGraph[from] = hp;
}
#ifdef C_DEBUG
ip = m->basicblocks[blockIndex].iinstr + m->basicblocks[blockIndex].icount -1;
if (!m->basicblocks[blockIndex].icount)
- dF_Exception(m, blockIndex, blockIndex+1);
+ dF_Exception(m, ld, blockIndex, blockIndex+1);
else {
switch (ip->opc) {
case ICMD_RETURN:
case ICMD_IF_ICMPLE:
case ICMD_IF_ACMPEQ:
case ICMD_IF_ACMPNE:
- dF_Exception(m, blockIndex, blockIndex + 1);
+ dF_Exception(m, ld, blockIndex, blockIndex + 1);
/* fall throu */
case ICMD_GOTO:
- dF_Exception(m, blockIndex, m->basicblockindex[ip->op1]);
+ dF_Exception(m, ld, blockIndex, m->basicblockindex[ip->op1]);
break;
case ICMD_TABLESWITCH:
s4ptr = ip->val.a;
/* default branch */
- dF_Exception(m, blockIndex, m->basicblockindex[*s4ptr]);
+ dF_Exception(m, ld, blockIndex, m->basicblockindex[*s4ptr]);
s4ptr++;
low = *s4ptr;
while (--count >= 0) {
s4ptr++;
- dF_Exception(m, blockIndex, m->basicblockindex[*s4ptr]);
+ dF_Exception(m, ld, blockIndex, m->basicblockindex[*s4ptr]);
}
break;
s4ptr = ip->val.a;
/* default branch */
- dF_Exception(m, blockIndex, m->basicblockindex[*s4ptr]);
+ dF_Exception(m, ld, blockIndex, m->basicblockindex[*s4ptr]);
++s4ptr;
count = *s4ptr++;
while (--count >= 0) {
- dF_Exception(m, blockIndex, m->basicblockindex[s4ptr[1]]);
+ dF_Exception(m, ld, blockIndex, m->basicblockindex[s4ptr[1]]);
s4ptr += 2;
}
break;
case ICMD_JSR:
- c_last_jump = blockIndex;
- dF_Exception(m, blockIndex, m->basicblockindex[ip->op1]);
+ ld->c_last_jump = blockIndex;
+ dF_Exception(m, ld, blockIndex, m->basicblockindex[ip->op1]);
break;
case ICMD_RET:
- dF_Exception(m, blockIndex, c_last_jump+1);
+ dF_Exception(m, ld, blockIndex, ld->c_last_jump+1);
break;
default:
- dF_Exception(m, blockIndex, blockIndex + 1);
+ dF_Exception(m, ld, blockIndex, blockIndex + 1);
break;
}
}
/*
Test function -> will be removed in final release
*/
-void resultPass1()
+void resultPass1(methodinfo *m)
{
int i, j;
struct depthElement *hp;
+ struct loopdata *l;
+
+ l=m->loopdata;
printf("\n\n****** PASS 1 ******\n\n");
- printf("Number of Nodes: %d\n\n", c_globalCount);
+ printf("Number of Nodes: %d\n\n", ld->c_globalCount);
printf("Predecessors:\n");
for (i=0; i<m->basicblockcount; ++i) {
printf("Block %d:\t", i);
- for (j=0; j<c_numPre[i]; ++j)
- printf("%d ", c_pre[i][j]);
+ for (j=0; j<ld->c_numPre[i]; ++j)
+ printf("%d ", ld->c_pre[i][j]);
printf("\n");
}
printf("\n");
printf("Graph:\n");
for (i=0; i<m->basicblockcount; ++i) {
printf("Block %d:\t", i);
- hp = c_dTable[i];
+ hp = ld->c_dTable[i];
while (hp != NULL) {
printf("%d ", hp->value);
Authors: Christian Thalinger
- $Id: graph.h 1203 2004-06-22 23:14:55Z twisti $
+ $Id: graph.h 1454 2004-11-05 14:19:32Z twisti $
*/
#include "loop.h"
+
void LoopContainerInit(methodinfo *m, struct LoopContainer *lc, int i);
-void depthFirst(methodinfo *m);
-void dF(methodinfo *m, int from, int blockIndex);
-void dF_Exception(methodinfo *m, int from, int blockIndex);
+void depthFirst(methodinfo *m, loopdata *ld);
+void dF(methodinfo *m, loopdata *ld, int from, int blockIndex);
+void dF_Exception(methodinfo *m, loopdata *ld, int from, int blockIndex);
-void resultPass1();
+void resultPass1(methodinfo *);
#endif /* _GRAPH_H */
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
algorithm that uses dominator trees (found eg. in modern compiler
implementation by a.w. appel)
- $Id: loop.c 1203 2004-06-22 23:14:55Z twisti $
+ $Id: loop.c 1454 2004-11-05 14:19:32Z twisti $
*/
#include "toolbox/logging.h"
#include "toolbox/memory.h"
-/* GLOBAL VARS */
-
-int c_debug_nr; /* a counter to number all BB with an unique */
- /* value */
-
-/* modified by graph.c */
-
-int *c_defnum; /* array that stores a number for each node when*/
- /* control flow graph is traveres depth first */
-int *c_parent; /* for each node that array stores its parent */
-int *c_reverse; /* for each def number that array stores the */
- /* corresponding node */
-int c_globalCount; /* counter for def numbering */
-int *c_numPre; /* array that stores for each node its number */
- /* predecessors */
-int **c_pre; /* array of array that stores predecessors */
-int c_last_jump; /* stores the source node of the last jsr instr */
-struct basicblock *c_last_target; /* stores the source BB of the last jsr instr */
-
-struct depthElement **c_dTable; /* adjacency list for control flow graph */
-struct depthElement **c_exceptionGraph; /* adjacency list for exception graph */
-
-struct LoopContainer *c_allLoops; /* list of all loops */
-struct LoopContainer *c_loop_root; /* root of loop hierarchie tree */
-
-int *c_exceptionVisit; /* array that stores a flag for each node part */
- /* of the exception graph */
-
-/* modified by loop.c */
-
-int *c_semi_dom; /* store for each node its semi dominator */
-int *c_idom; /* store for each node its dominator */
-int *c_same_dom; /* temp array to hold nodes with same dominator */
-int *c_ancestor; /* store for each node its ancestor with lowest */
- /* semi dominator */
-int *c_numBucket;
-int **c_bucket;
-
-int *c_contains; /* store for each node whether it's part of loop*/
-int *c_stack; /* a simple stack as array */
-int c_stackPointer; /* stackpointer */
-
-
-/* modified by analyze.c */
-
-struct LoopContainer *root; /* the root pointer for the hierarchie tree of */
- /* all loops in that procedure */
-
-int c_needed_instr; /* number of instructions that have to be */
- /* inserted before loop header to make sure */
- /* array optimization is legal */
-int c_rs_needed_instr; /* number of instructions needed to load the */
- /* value ofthe right side of the loop condition */
-int *c_nestedLoops; /* store for each node the header node of the */
- /* loop this node belongs to, -1 for none */
-int *c_hierarchie; /* store a loop hierarchie */
-int *c_toVisit; /* set for each node that is part of the loop */
-
-int *c_current_loop; /* for each node: */
- /* store 0: node is not part of loop */
- /* store 1: node is loop header */
- /* store 2: node is in loop but not part of any */
- /* nested loop */
- /* store 3: node is part of nested loop */
-
-int c_current_head; /* store number of node that is header of loop */
-int *c_var_modified; /* store for each local variable whether its */
- /* value is changed in the loop */
-
-struct Trace *c_rightside; /* right side of loop condition */
-struct Constraint **c_constraints;
- /* array that stores for each variable a list */
- /* static tests (constraints) that have to be */
- /* performed before loop entry */
- /* IMPORTANT: c_constraints[maxlocals] stores */
- /* the tests for constants and the */
- /* right side of loop condition */
-
-struct LoopVar *c_loopvars; /* a list of all intersting variables of the */
- /* current loop (variables that are modified or */
- /* used as array index */
-
-struct basicblock *c_first_block_copied; /* pointer to the first block, that is copied */
- /* during loop duplication */
-
-struct basicblock *c_last_block_copied; /* last block, that is copied during loop */
- /* duplication */
-
-int *c_null_check; /* array to store for local vars, whether they */
- /* need to be checked against the null reference*/
- /* in the loop head */
-
-bool c_needs_redirection; /* if a loop header is inserted as first block */
- /* into the global BB list, this is set to true */
-
-struct basicblock *c_newstart; /* if a loop header is inserted as first block */
- /* into the gloal BB list, this pointer is the */
- /* new start */
-int c_old_xtablelength; /* used to store the original tablelength */
-
-/* set debug mode */
-#define C_DEBUG
-
-
-/* declare statistic variables */
-#ifdef STATISTICS
-
-int c_stat_num_loops; /* number of loops */
-
-/* statistics per loop */
-int c_stat_array_accesses; /* number of array accesses */
-
-int c_stat_full_opt; /* number of fully optimized accesses */
-int c_stat_no_opt; /* number of not optimized accesses */
-int c_stat_lower_opt; /* number of accesses where check against zero */
- /* is removed */
-int c_stat_upper_opt; /* number of accesses where check against array */
- /* lengh is removed */
-int c_stat_or; /* set if optimization is cancelled because of */
- /* or in loop condition */
-int c_stat_exception; /* set if optimization is cancelled because of */
- /* index var modified in catch block */
-
-/* statistics per procedure */
-int c_stat_sum_accesses; /* number of array accesses */
-
-int c_stat_sum_full; /* number of fully optimized accesses */
-int c_stat_sum_no; /* number of not optimized accesses */
-int c_stat_sum_lower; /* number of accesses where check against zero */
- /* is removed */
-int c_stat_sum_upper; /* number of accesses where check against array */
- /* lengh is removed */
-int c_stat_sum_or; /* set if optimization is cancelled because of */
- /* or in loop condition */
-int c_stat_sum_exception; /* set if optimization is cancelled because of */
-
-#endif
/*
This function allocates and initializes variables, that are used by the
loop detection algorithm
*/
-void setup(methodinfo *m)
+void setup(methodinfo *m, loopdata *ld)
{
int i;
- c_semi_dom = DMNEW(int, m->basicblockcount);
- c_idom = DMNEW(int, m->basicblockcount);
- c_same_dom = DMNEW(int, m->basicblockcount);
- c_numBucket = DMNEW(int, m->basicblockcount);
- c_ancestor = DMNEW(int, m->basicblockcount);
- c_contains = DMNEW(int, m->basicblockcount);
- c_stack = DMNEW(int, m->basicblockcount);
- c_bucket = DMNEW(int*, m->basicblockcount);
+ ld->c_semi_dom = DMNEW(int, m->basicblockcount);
+ ld->c_idom = DMNEW(int, m->basicblockcount);
+ ld->c_same_dom = DMNEW(int, m->basicblockcount);
+ ld->c_numBucket = DMNEW(int, m->basicblockcount);
+ ld->c_ancestor = DMNEW(int, m->basicblockcount);
+ ld->c_contains = DMNEW(int, m->basicblockcount);
+ ld->c_stack = DMNEW(int, m->basicblockcount);
+ ld->c_bucket = DMNEW(int*, m->basicblockcount);
for (i = 0; i < m->basicblockcount; ++i) {
- c_numBucket[i] = 0;
- c_stack[i] = c_ancestor[i] = c_semi_dom[i] = c_same_dom[i] = c_idom[i] = -1;
+ ld->c_numBucket[i] = 0;
+ ld->c_stack[i] = ld->c_ancestor[i] = ld->c_semi_dom[i] = ld->c_same_dom[i] = ld->c_idom[i] = -1;
- c_bucket[i] = DMNEW(int, m->basicblockcount);
+ ld->c_bucket[i] = DMNEW(int, m->basicblockcount);
}
}
ancestor of the node v in the control graph, which semi-dominator has the
lowest def-num.
*/
-int findLowAnc(int v)
+
+int findLowAnc(loopdata *ld, int v)
{
int u = v; /* u is the node which has the current lowest semi-dom */
- while (c_ancestor[v] != -1) { /* as long as v has an ancestor, continue */
- if (c_defnum[c_semi_dom[v]] < c_defnum[c_semi_dom[u]])
+ while (ld->c_ancestor[v] != -1) { /* as long as v has an ancestor, continue */
+ if (ld->c_defnum[ld->c_semi_dom[v]] < ld->c_defnum[ld->c_semi_dom[u]])
/* if v's semi-dom is smaller */
u = v; /* it gets the new current node u */
- v = c_ancestor[v]; /* climb one step up in the tree */
+ v = ld->c_ancestor[v]; /* climb one step up in the tree */
}
return u; /* return node with the lowest semi-dominator def-num */
}
dominators in c_bucket and eventually determines the single dominator in a
final pass.
*/
-void dominators()
+
+void dominators(loopdata *ld)
{
int i, j, semi, s, n, v, actual, p, y;
- for (n=(c_globalCount-1); n>0; --n) { /* for all nodes (except last), do */
- actual = c_reverse[n];
- semi = p = c_parent[actual];
+ for (n=(ld->c_globalCount-1); n>0; --n) { /* for all nodes (except last), do */
+ actual = ld->c_reverse[n];
+ semi = p = ld->c_parent[actual];
/* for all predecessors of current node, do */
- for (i=0; i<c_numPre[actual]; ++i) {
- v = c_pre[actual][i];
+ for (i=0; i<ld->c_numPre[actual]; ++i) {
+ v = ld->c_pre[actual][i];
- if (c_defnum[v] <= c_defnum[actual])
+ if (ld->c_defnum[v] <= ld->c_defnum[actual])
s = v; /* if predecessor has lower def-num than node */
/* it becomes candidate for semi dominator */
else
- s = c_semi_dom[findLowAnc(v)];
+ s = ld->c_semi_dom[findLowAnc(ld, v)];
/* else the semi-dominator of it's ancestor */
/* with lowest def-num becomes candidate */
- if (c_defnum[s] < c_defnum[semi])
+ if (ld->c_defnum[s] < ld->c_defnum[semi])
semi = s; /* if the def-num of the new candidate is lower */
/* than old one, it gets new semi dominator */
}
/* write semi dominator -> according to SEMIDOMINATOR THEOREM */
- c_semi_dom[actual] = semi;
- c_ancestor[actual] = p;
+ ld->c_semi_dom[actual] = semi;
+ ld->c_ancestor[actual] = p;
- c_bucket[semi][c_numBucket[semi]] = actual;
- c_numBucket[semi]++; /* defer calculation of dominator to final pass */
+ ld->c_bucket[semi][ld->c_numBucket[semi]] = actual;
+ ld->c_numBucket[semi]++; /* defer calculation of dominator to final pass */
/* first clause of DOMINATOR THEOREM, try to find dominator now */
- for (j=0; j<c_numBucket[p]; ++j) {
- v = c_bucket[p][j];
- y = findLowAnc(v);
+ for (j=0; j<ld->c_numBucket[p]; ++j) {
+ v = ld->c_bucket[p][j];
+ y = findLowAnc(ld, v);
- if (c_semi_dom[y] == c_semi_dom[v])
- c_idom[v] = p; /* if y's dominator is already known */
+ if (ld->c_semi_dom[y] == ld->c_semi_dom[v])
+ ld->c_idom[v] = p; /* if y's dominator is already known */
/* found it and write to c_idom */
else
- c_same_dom[v] = y; /* wait till final pass */
+ ld->c_same_dom[v] = y; /* wait till final pass */
}
- c_numBucket[p] = 0;
+ ld->c_numBucket[p] = 0;
}
/* final pass to get missing dominators ->second clause of DOMINATOR THEORM */
- for (j=1; j<(c_globalCount-1); ++j) {
- if (c_same_dom[c_reverse[j]] != -1)
- c_idom[c_reverse[j]] = c_idom[c_same_dom[c_reverse[j]]];
+ for (j=1; j<(ld->c_globalCount-1); ++j) {
+ if (ld->c_same_dom[ld->c_reverse[j]] != -1)
+ ld->c_idom[ld->c_reverse[j]] = ld->c_idom[ld->c_same_dom[ld->c_reverse[j]]];
}
}
connection between two nodes in the control flow graph is possibly part
of a loop (is a backEdge).
*/
-int isBackEdge(int from, int to)
+
+int isBackEdge(loopdata *ld, int from, int to)
{
- int tmp = c_idom[to]; /* speed optimization: if the to-node is dominated */
+ int tmp = ld->c_idom[to]; /* speed optimization: if the to-node is dominated */
while (tmp != -1) { /* by the from node as it is most of the time, */
if (tmp == from) /* there is no backEdge */
return 0;
- tmp = c_idom[tmp];
+ tmp = ld->c_idom[tmp];
}
- tmp = c_idom[from]; /* if from-node doesn't dominate to-node, we have */
+ tmp = ld->c_idom[from]; /* if from-node doesn't dominate to-node, we have */
while (tmp != -1) { /* to climb all the way up from the from-node to */
if (tmp == to) /* the top to check, whether it is dominated by to */
return 1; /* if so, return a backedge */
- tmp = c_idom[tmp];
+ tmp = ld->c_idom[tmp];
}
return 0; /* else, there is no backedge */
These stack functions are helper functions for createLoop(int, int)
to manage the set of nodes in the current loop.
*/
-void push(methodinfo *m, int i, struct LoopContainer *lc)
+
+void push(methodinfo *m, loopdata *ld, int i, struct LoopContainer *lc)
{
struct LoopElement *le = lc->nodes, *t;
- if (!c_contains[i]) {
+ if (!ld->c_contains[i]) {
t = DMNEW(struct LoopElement, 1);
t->node = i;
t->block = &m->basicblocks[i];
- c_contains[i] = 1;
+ ld->c_contains[i] = 1;
if (i < le->node)
{
le->next = t;
}
- c_stack[c_stackPointer++] = i;
+ ld->c_stack[ld->c_stackPointer++] = i;
}
}
-int pop()
+int pop(loopdata *ld)
{
- return (c_stack[--c_stackPointer]);
+ return (ld->c_stack[--ld->c_stackPointer]);
}
-int isFull()
+int isFull(loopdata *ld)
{
- return (c_stackPointer);
+ return (ld->c_stackPointer);
}
the loop with a known header node and a member node of the loop (and a
back edge between these two nodes).
*/
-void createLoop(methodinfo *m, int header, int member)
+
+void createLoop(methodinfo *m, loopdata *ld, int header, int member)
{
int i, nextMember;
LoopContainerInit(m, currentLoop, header); /* set up loop structure */
for (i=0; i<m->basicblockcount; ++i)
- c_contains[i] = 0;
- c_contains[header] = 1;
+ ld->c_contains[i] = 0;
+ ld->c_contains[header] = 1;
- c_stackPointer = 0; /* init stack with first node of the loop */
- push(m, member, currentLoop);
+ ld->c_stackPointer = 0; /* init stack with first node of the loop */
+ push(m, ld, member, currentLoop);
- while (isFull()) { /* while there are still unvisited nodes */
- nextMember = pop();
+ while (isFull(ld)) { /* while there are still unvisited nodes */
+ nextMember = pop(ld);
/* push all predecessors, while they are not equal to loop header */
- for (i=0; i<c_numPre[nextMember]; ++i)
- push(m, c_pre[nextMember][i], currentLoop);
+ for (i=0; i<ld->c_numPre[nextMember]; ++i)
+ push(m, ld, ld->c_pre[nextMember][i], currentLoop);
}
- currentLoop->next = c_allLoops;
- c_allLoops = currentLoop;
+ currentLoop->next = ld->c_allLoops;
+ ld->c_allLoops = currentLoop;
}
/* After all dominators have been calculated, the loops can be detected and
added to the global list c_allLoops.
*/
-void detectLoops(methodinfo *m)
+
+void detectLoops(methodinfo *m, loopdata *ld)
{
int i;
struct depthElement *h;
-
+
/* for all edges in the control flow graph do */
for (i=0; i<m->basicblockcount; ++i) {
- h = c_dTable[i];
+ h = ld->c_dTable[i];
while (h != NULL) {
/* if it's a backedge, than add a new loop to list */
- if (isBackEdge(i, h->value))
- createLoop(m, h->value, i);
+ if (isBackEdge(ld, i, h->value))
+ createLoop(m, ld, h->value, i);
h = h->next;
}
}
This function is called by higher level routines to perform the loop
detection and set up the c_allLoops list.
*/
-void analyseGraph(methodinfo *m)
+
+void analyseGraph(methodinfo *m, loopdata *ld)
{
- setup(m);
- dominators();
- detectLoops(m);
+ setup(m, ld);
+ dominators(ld);
+ detectLoops(m, ld);
}
/*
Test function -> will be removed in final release
*/
-void resultPass2()
+
+void resultPass2(loopdata *ld)
{
int i;
- struct LoopContainer *lc = c_allLoops;
+ struct LoopContainer *lc = ld->c_allLoops;
struct LoopElement *le;
printf("\n\n****** PASS 2 ******\n\n");
Authors: Christopher Kruegel
- $Id: loop.h 1203 2004-06-22 23:14:55Z twisti $
+ $Id: loop.h 1454 2004-11-05 14:19:32Z twisti $
*/
#define _LOOP_H
#include "global.h"
+#include "jit/jit.h"
+
/* Different types for struct Trace */
#define TRACE_UNKNOWN 0 /* unknown */
#define HANDLER_VISITED 0x4 /* flag to prevent loop if copying catch blocks */
+typedef struct LoopElement LoopElement;
+typedef struct LoopContainer LoopContainer;
+typedef struct loopdata loopdata;
+
/* This struct records information about interesting vars (vars that are modified
or used as an array index in loops.
};
-/* Used to build a list of all basicblock, the loop consists of
-*/
+/* Used to build a list of all basicblock, the loop consists of */
+
struct LoopElement {
- int node;
- struct basicblock *block;
- struct LoopElement *next;
+ s4 node;
+ basicblock *block;
+ LoopElement *next;
};
This structure stores informations about a single loop
*/
struct LoopContainer {
- int toOpt; /* does this loop need optimization */
- struct LoopElement *nodes; /* list of BBs this loop consists of */
- int loop_head;
- int in_degree; /* needed to topological sort loops to */
- /* get the order of optimizing them */
- struct LoopContainer *next; /* list pointer */
- struct LoopContainer *parent; /* points to parent loop, if this BB */
- /* is head of a loop */
- struct LoopContainer *tree_right; /* used for tree hierarchie of loops */
- struct LoopContainer *tree_down;
- exceptiontable *exceptions; /* list of exception in that loop */
+ s4 toOpt; /* does this loop need optimization */
+ LoopElement *nodes; /* list of BBs this loop consists of */
+ s4 loop_head;
+ s4 in_degree; /* needed to topological sort loops to*/
+ /* get the order of optimizing them */
+ LoopContainer *next; /* list pointer */
+ LoopContainer *parent; /* points to parent loop, if this BB */
+ /* is head of a loop */
+ LoopContainer *tree_right; /* used for tree hierarchie of loops */
+ LoopContainer *tree_down;
+ exceptiontable *exceptions; /* list of exception in that loop */
};
-/* global variables */
-extern int c_debug_nr;
-extern int *c_defnum;
-extern int *c_parent;
-extern int *c_reverse;
-extern int c_globalCount;
-extern int *c_numPre;
-extern int **c_pre;
-extern int c_last_jump;
-extern struct basicblock *c_last_target;
-extern struct depthElement **c_dTable;
-extern struct depthElement **c_exceptionGraph;
-extern struct LoopContainer *c_allLoops;
-extern struct LoopContainer *c_loop_root;
-extern int *c_exceptionVisit;
-
-
-/* global loop variables */
-extern int *c_semi_dom;
-extern int *c_idom;
-extern int *c_same_dom;
-extern int *c_ancestor;
-extern int *c_numBucket;
-extern int **c_bucket;
-extern int *c_contains;
-extern int *c_stack;
-extern int c_stackPointer;
-
-
-/* global analyze variables */
-extern struct LoopContainer *root;
-extern int c_needed_instr;
-extern int c_rs_needed_instr;
-extern int *c_nestedLoops;
-extern int *c_hierarchie;
-extern int *c_toVisit;
-extern int *c_current_loop;
-extern int c_current_head;
-extern int *c_var_modified;
-extern struct Trace *c_rightside;
-extern struct Constraint **c_constraints;
-extern struct LoopVar *c_loopvars;
-extern struct basicblock *c_first_block_copied;
-extern struct basicblock *c_last_block_copied;
-extern int *c_null_check;
-extern bool c_needs_redirection;
-extern struct basicblock *c_newstart;
-extern int c_old_xtablelength;
-
-
-/* global statistic variables */
+struct loopdata {
+ /* modified by graph.c */
+
+ int *c_defnum; /* array that stores a number for each node when*/
+ /* control flow graph is traveres depth first */
+ int *c_parent; /* for each node that array stores its parent */
+ int *c_reverse; /* for each def number that array stores the */
+ /* corresponding node */
+ int c_globalCount; /* counter for def numbering */
+ int *c_numPre; /* array that stores for each node its number */
+ /* predecessors */
+ int **c_pre; /* array of array that stores predecessors */
+ int c_last_jump; /* stores the source node of the last jsr instr */
+ struct basicblock *c_last_target; /* stores the source BB of the last jsr instr */
+
+ struct depthElement **c_dTable; /* adjacency list for control flow graph */
+ struct depthElement **c_exceptionGraph; /* adjacency list for exception graph */
+
+ struct LoopContainer *c_allLoops; /* list of all loops */
+ struct LoopContainer *c_loop_root; /* root of loop hierarchie tree */
+
+ int *c_exceptionVisit; /* array that stores a flag for each node part */
+ /* of the exception graph */
+
+ /* modified by loop.c */
+
+ int *c_semi_dom; /* store for each node its semi dominator */
+ int *c_idom; /* store for each node its dominator */
+ int *c_same_dom; /* temp array to hold nodes with same dominator */
+ int *c_ancestor; /* store for each node its ancestor with lowest */
+ /* semi dominator */
+ int *c_numBucket;
+ int **c_bucket;
+
+ int *c_contains; /* store for each node whether it's part of loop*/
+ int *c_stack; /* a simple stack as array */
+ int c_stackPointer; /* stackpointer */
+
+
+ /* modified by analyze.c */
+
+ struct LoopContainer *root; /* the root pointer for the hierarchie tree of */
+ /* all loops in that procedure */
+
+ int c_needed_instr; /* number of instructions that have to be */
+ /* inserted before loop header to make sure */
+ /* array optimization is legal */
+ int c_rs_needed_instr; /* number of instructions needed to load the */
+ /* value ofthe right side of the loop condition */
+ int *c_nestedLoops; /* store for each node the header node of the */
+ /* loop this node belongs to, -1 for none */
+ int *c_hierarchie; /* store a loop hierarchie */
+ int *c_toVisit; /* set for each node that is part of the loop */
+
+ int *c_current_loop; /* for each node: */
+ /* store 0: node is not part of loop */
+ /* store 1: node is loop header */
+ /* store 2: node is in loop but not part of any */
+ /* nested loop */
+ /* store 3: node is part of nested loop */
+
+ int c_current_head; /* store number of node that is header of loop */
+ int *c_var_modified; /* store for each local variable whether its */
+ /* value is changed in the loop */
+
+ struct Trace *c_rightside; /* right side of loop condition */
+ struct Constraint **c_constraints;
+ /* array that stores for each variable a list */
+ /* static tests (constraints) that have to be */
+ /* performed before loop entry */
+ /* IMPORTANT: c_constraints[maxlocals] stores */
+ /* the tests for constants and the */
+ /* right side of loop condition */
+
+ struct LoopVar *c_loopvars; /* a list of all intersting variables of the */
+ /* current loop (variables that are modified or */
+ /* used as array index */
+
+ struct basicblock *c_first_block_copied; /* pointer to the first block, that is copied */
+ /* during loop duplication */
+
+ struct basicblock *c_last_block_copied; /* last block, that is copied during loop */
+ /* duplication */
+
+ int *c_null_check; /* array to store for local vars, whether they */
+ /* need to be checked against the null reference*/
+ /* in the loop head */
+
+ bool c_needs_redirection; /* if a loop header is inserted as first block */
+ /* into the global BB list, this is set to true */
+
+ struct basicblock *c_newstart; /* if a loop header is inserted as first block */
+ /* into the gloal BB list, this pointer is the */
+ /* new start */
+ int c_old_xtablelength; /* used to store the original tablelength */
+
+ /* set debug mode */
+#define C_DEBUG
+
+
+ /* declare statistic variables */
#ifdef STATISTICS
-extern int c_stat_num_loops;
-extern int c_stat_array_accesses;
-extern int c_stat_full_opt;
-extern int c_stat_no_opt;
-extern int c_stat_lower_opt;
-extern int c_stat_upper_opt;
-extern int c_stat_or;
-extern int c_stat_exception;
-extern int c_stat_sum_accesses;
-extern int c_stat_sum_full;
-extern int c_stat_sum_no;
-extern int c_stat_sum_lower;
-extern int c_stat_sum_upper;
-extern int c_stat_sum_or;
-extern int c_stat_sum_exception;
+ int c_stat_num_loops; /* number of loops */
+
+ /* statistics per loop */
+ int c_stat_array_accesses; /* number of array accesses */
+
+ int c_stat_full_opt; /* number of fully optimized accesses */
+ int c_stat_no_opt; /* number of not optimized accesses */
+ int c_stat_lower_opt; /* number of accesses where check against zero */
+ /* is removed */
+ int c_stat_upper_opt; /* number of accesses where check against array */
+ /* lengh is removed */
+ int c_stat_or; /* set if optimization is cancelled because of */
+ /* or in loop condition */
+ int c_stat_exception; /* set if optimization is cancelled because of */
+ /* index var modified in catch block */
+
+ /* statistics per procedure */
+ int c_stat_sum_accesses; /* number of array accesses */
+
+ int c_stat_sum_full; /* number of fully optimized accesses */
+ int c_stat_sum_no; /* number of not optimized accesses */
+ int c_stat_sum_lower; /* number of accesses where check against zero */
+ /* is removed */
+ int c_stat_sum_upper; /* number of accesses where check against array */
+ /* lengh is removed */
+ int c_stat_sum_or; /* set if optimization is cancelled because of */
+ /* or in loop condition */
+ int c_stat_sum_exception; /* set if optimization is cancelled because of */
#endif
+};
/* function prototypes */
-void analyseGraph(methodinfo *m);
+
+void analyseGraph(methodinfo *m, loopdata *ld);
void c_mem_error();
#endif /* _LOOP_H */
* tab-width: 4
* End:
*/
-
instruction. For more details see function tracing(basicblock, int,
int) below.
- $Id: tracing.c 1274 2004-07-05 17:24:40Z twisti $
+ $Id: tracing.c 1454 2004-11-05 14:19:32Z twisti $
*/
/* A function that creates a new trace structure and initializes its values
*/
-struct Trace* create_trace(int type, int var, int constant, int nr)
+Trace* create_trace(int type, int var, int constant, int nr)
{
- struct Trace *t;
-/* if ((t = (struct Trace *) malloc(sizeof(struct Trace))) == NULL) */
-/* c_mem_error(); */
- t = DNEW(struct Trace);
+ Trace *t;
+
+ t = DNEW(Trace);
t->type = type;
backward scan over the instructions, it trys to identify the source of the
arguments of this add function. The following function performs this task.
*/
-struct Trace* add(struct Trace* a, struct Trace* b)
+Trace* add(Trace* a, Trace* b)
{
switch (a->type) { /* check the first argument of add. when it */
case TRACE_UNKNOWN: /* is unknown or array-address, return unknown */
backward scan over the instructions, it trys to identify the source of the
argument of this neg function. The following function performs this task.
*/
-struct Trace* negate(struct Trace* a)
+Trace* negate(Trace* a)
{
switch (a->type) { /* check argument type */
case TRACE_IVAR: /* when it is variable/array length value */
this sub function. The following function performs this task, by applaying the
negate function on the second argument and then adds the values.
*/
-struct Trace* sub(struct Trace* a, struct Trace* b)
+Trace* sub(Trace* a, Trace* b)
{
- struct Trace *c = negate(b);
+ Trace *c = negate(b);
return add(a, c);
}
the argument ofthis array length function. The following function performs
this task.
*/
-struct Trace* array_length(struct Trace* a)
+Trace* array_length(Trace* a)
{
if (a->type == TRACE_AVAR) /* if argument is an array ref., mark the type */
a->type = TRACE_ALENGTH; /* as array length of this array reference */
}
-/* This function is used to identify the types of operands of an intermediate
- code instruction.It is needed by functions, that analyze array accesses. If
- something is stored into or loaded from an array, we have to find out, which
- array really has been accessed. When a compare instruction is encountered at
- a loop header, the type of its operands have to be detected to construct
- dynamic bounds for some variables in the loop. This function returns a struct
- Trace (see loop.h for more details about this structure). block is the basic
- block to be examined, index holds the offset of the examined instruction in
- this block. The arguments are retrieved by using the stack structure, the
- compilation process sets up. During the backwards scan of the code, it is
- possible, that other instructions temporaray put or get values from the stack
- and hide the value, we are interested in below them. The value temp counts
- the number of values on the stack, the are located beyond the target value.
-*/
-struct Trace* tracing(basicblock *block, int index, int temp)
+/* tracing *********************************************************************
+
+ This function is used to identify the types of operands of an intermediate
+ code instruction. It is needed by functions, that analyze array accesses. If
+ something is stored into or loaded from an array, we have to find out,
+ which array really has been accessed. When a compare instruction is
+ encountered at a loop header, the type of its operands have to be detected
+ to construct dynamic bounds for some variables in the loop. This function
+ returns a struct Trace (see loop.h for more details about this structure).
+ block is the basic block to be examined, index holds the offset of the
+ examined instruction in this block. The arguments are retrieved by using
+ the stack structure, the compilation process sets up. During the backwards
+ scan of the code, it is possible, that other instructions temporary put or
+ get values from the stack and hide the value, we are interested in below
+ them. The value temp counts the number of values on the stack, the are
+ located beyond the target value.
+
+*******************************************************************************/
+
+Trace* tracing(basicblock *block, int index, int temp)
{
int args, retval;
instruction *ip;
Authors: Christian Thalinger
- $Id: tracing.h 1141 2004-06-05 23:19:24Z twisti $
+ $Id: tracing.h 1454 2004-11-05 14:19:32Z twisti $
*/
#ifndef _TRACING_H
#define _TRACING_H
+
#include "jit/jit.h"
+
+typedef struct Trace Trace;
+
+
/*
This struct is needed to record the source of operands of intermediate code
instructions. The instructions are scanned backwards and the stack is
};
-
/* function protoypes */
-struct Trace* create_trace(int type, int var, int constant, int nr);
-struct Trace* add(struct Trace* a, struct Trace* b);
-struct Trace* negate(struct Trace* a);
-struct Trace* sub(struct Trace* a, struct Trace* b);
-struct Trace* array_length(struct Trace* a);
-struct Trace* tracing(struct basicblock *block, int index, int temp);
+
+Trace* create_trace(int type, int var, int constant, int nr);
+Trace* add(Trace* a, Trace* b);
+Trace* negate(Trace* a);
+Trace* sub(Trace* a, Trace* b);
+Trace* array_length(Trace* a);
+Trace* tracing(basicblock *block, int index, int temp);
#endif /* _TRACING_H */
bounds are never violated. The function to call is
optimize_loops().
- $Id: analyze.c 1203 2004-06-22 23:14:55Z twisti $
+ $Id: analyze.c 1454 2004-11-05 14:19:32Z twisti $
*/
printf("Dynamic\t\t%d/%d\n", lv->dynamic_l, lv->dynamic_u);
}
-void show_right_side()
+void show_right_side(methodinfo *m)
{
int i;
printf("\n *** Head *** \nType:\t");
- show_trace(c_rightside);
+ show_trace(m->loopdata->c_rightside);
printf("\n *** Nested Loops: ***\n");
for (i=0; i<m->basicblockcount; ++i)
- printf("%d\t", c_nestedLoops[i]);
+ printf("%d\t", m->loopdata->c_nestedLoops[i]);
printf("\n");
printf("\n *** Hierarchie: ***\n");
for (i=0; i<m->basicblockcount; ++i)
- printf("%d\t", c_hierarchie[i]);
+ printf("%d\t", m->loopdata->c_hierarchie[i]);
printf("\n");
printf("\n *** Current Loop ***\n");
for (i=0; i<m->basicblockcount; ++i)
- printf("%d\t", c_current_loop[i]);
+ printf("%d\t", m->loopdata->c_current_loop[i]);
printf("\n");
}
-void resultPass3()
+void resultPass3(methodinfo *m)
{
int i;
- struct LoopContainer *lc = c_allLoops;
+ struct LoopContainer *lc = m->loopdata->c_allLoops;
printf("\n\n****** PASS 3 ******\n\n");
printf("\nNested Loops:\n");
for (i=0; i<m->basicblockcount; ++i)
- printf("%d ", c_nestedLoops[i]);
+ printf("%d ", m->loopdata->c_nestedLoops[i]);
printf("\n");
for (i=0; i<m->basicblockcount; ++i)
- printf("%d ", c_hierarchie[i]);
+ printf("%d ", m->loopdata->c_hierarchie[i]);
printf("\n");
fflush(stdout);
}
#ifdef STATISTICS
-void show_loop_statistics()
+void show_loop_statistics(loopdata *ld)
{
printf("\n\n****** LOOP STATISTICS ****** \n\n");
- if (c_stat_or)
+ if (ld->c_stat_or)
printf("Optimization cancelled by or\n");
- else if (c_stat_exception)
+ else if (ld->c_stat_exception)
printf("Optimization cancelled by exception\n");
else {
- printf("Number of array accesses:\t%d\n", c_stat_array_accesses);
- if (c_stat_array_accesses) {
- printf("\nFully optimized:\t%d\n", c_stat_full_opt);
- printf("Not optimized:\t\t%d\n", c_stat_no_opt);
- printf("Upper optimized:\t%d\n", c_stat_upper_opt);
- printf("Lower optimized:\t%d\n", c_stat_lower_opt);
+ printf("Number of array accesses:\t%d\n", ld->c_stat_array_accesses);
+ if (ld->c_stat_array_accesses) {
+ printf("\nFully optimized:\t%d\n", ld->c_stat_full_opt);
+ printf("Not optimized:\t\t%d\n", ld->c_stat_no_opt);
+ printf("Upper optimized:\t%d\n", ld->c_stat_upper_opt);
+ printf("Lower optimized:\t%d\n", ld->c_stat_lower_opt);
}
}
}
-void show_procedure_statistics()
+void show_procedure_statistics(loopdata *ld)
{
printf("\n\n****** PROCEDURE STATISTICS ****** \n\n");
- printf("Number of loops:\t\t%d\n", c_stat_num_loops);
- printf("Number of array accesses:\t%d\n", c_stat_sum_accesses);
- if (c_stat_sum_accesses) {
- printf("\nFully optimized:\t%d\n", c_stat_sum_full);
- printf("Not optimized:\t\t%d\n", c_stat_sum_no);
- printf("Upper optimized:\t%d\n", c_stat_sum_upper);
- printf("Lower optimized:\t%d\n", c_stat_sum_lower);
+ printf("Number of loops:\t\t%d\n", ld->c_stat_num_loops);
+ printf("Number of array accesses:\t%d\n", ld->c_stat_sum_accesses);
+ if (ld->c_stat_sum_accesses) {
+ printf("\nFully optimized:\t%d\n", ld->c_stat_sum_full);
+ printf("Not optimized:\t\t%d\n", ld->c_stat_sum_no);
+ printf("Upper optimized:\t%d\n", ld->c_stat_sum_upper);
+ printf("Lower optimized:\t%d\n", ld->c_stat_sum_lower);
}
- printf("Opt. cancelled by or:\t\t%d\n", c_stat_sum_or);
- printf("Opt. cancelled by exception:\t%d\n", c_stat_sum_exception);
+ printf("Opt. cancelled by or:\t\t%d\n", ld->c_stat_sum_or);
+ printf("Opt. cancelled by exception:\t%d\n", ld->c_stat_sum_exception);
}
#endif
finding algorith sometimes (eg. when loopbody ends with a if-else construct)
reports a single loop as two loops with the same header node.
*/
-void analyze_double_headers()
+void analyze_double_headers(loopdata *ld)
{
int toCheck;
- struct LoopContainer *t1, *t2, *t3;
+ LoopContainer *t1, *t2, *t3;
- t1 = c_allLoops;
+ t1 = ld->c_allLoops;
while (t1 != NULL) { /* for all loops do */
toCheck = t1->loop_head; /* get header node */
Each loop, that is a nested loop, stores its direct surrounding loop as a
parent. Top level loops have no parents.
*/
-void analyze_nested(methodinfo *m)
+
+void analyze_nested(methodinfo *m, loopdata *ld)
{
/* i/count/tmp are counters */
/* toOverwrite is used while loop hierarchie is built (see below) */
struct LoopElement *le;
/* init global structures */
- c_nestedLoops = DMNEW(int, m->basicblockcount);
- c_hierarchie = DMNEW(int, m->basicblockcount);
+ ld->c_nestedLoops = DMNEW(int, m->basicblockcount);
+ ld->c_hierarchie = DMNEW(int, m->basicblockcount);
for (i=0; i<m->basicblockcount; ++i) {
- c_nestedLoops[i] = -1;
- c_hierarchie[i] = -1;
+ ld->c_nestedLoops[i] = -1;
+ ld->c_hierarchie[i] = -1;
}
/* if there are no optimizable loops -> return */
- if (c_allLoops == NULL)
+ if (ld->c_allLoops == NULL)
return;
- temp = c_allLoops;
+ temp = ld->c_allLoops;
while (temp != NULL) { /* for all loops, do */
header = temp->loop_head;
/* toOverwrite is number of current parent loop (-1 if none) */
- toOverwrite = c_nestedLoops[header];
+ toOverwrite = ld->c_nestedLoops[header];
- c_hierarchie[header] = toOverwrite;
+ ld->c_hierarchie[header] = toOverwrite;
if (toOverwrite == header) /* check for loops with same header */
printf("C_ERROR: Loops have same header\n");
le = temp->nodes;
while (le != NULL) { /* for all loop nodes, do */
- tmp = c_nestedLoops[le->node];
+ tmp = ld->c_nestedLoops[le->node];
/* if node is part of parent loop -> overwrite it with nested */
if (tmp == toOverwrite)
- c_nestedLoops[le->node] = header;
+ ld->c_nestedLoops[le->node] = header;
else {
- c_hierarchie[tmp] = header;
+ ld->c_hierarchie[tmp] = header;
#ifdef LOOP_DEBUG
/* printf("set head of %d to %d", tmp, header); */
#endif
}
/* init root of hierarchie tree */
- root = DMNEW(struct LoopContainer, 1);
- LoopContainerInit(m, root, -1);
+ ld->root = DMNEW(struct LoopContainer, 1);
+ LoopContainerInit(m, ld->root, -1);
/* obtain parent pointer and build hierarchie tree */
- start = c_allLoops;
+ start = ld->c_allLoops;
while (start != NULL) {
/* look for parent of loop pointed at by start */
- first = c_allLoops;
+ first = ld->c_allLoops;
while (first != NULL) {
/* the parent of the loop, pointed at by start has been found */
- if (first->loop_head == c_hierarchie[start->loop_head]) {
+ if (first->loop_head == ld->c_hierarchie[start->loop_head]) {
#ifdef LOOP_DEBUG
/* printf("set parent to pointer\n"); */
#endif
/* printf("set parent to root\n"); */
#endif
- start->parent = root;
- start->tree_right = root->tree_down;
- root->tree_down = start;
+ start->parent = ld->root;
+ start->tree_right = ld->root->tree_down;
+ ld->root->tree_down = start;
}
/* if a parent exists, increase this nodes indegree */
else
/* insert exceptions into tree */
#ifdef LOOP_DEBUG
printf("--- Showing tree ---\n");
- show_tree(root, 0);
+ show_tree(ld->root, 0);
printf(" --- End ---\n");
#endif
for (len = 0; len < m->exceptiontablelength; ++len)
- insert_exception(m, root, m->exceptiontable + len);
+ insert_exception(m, ld->root, m->exceptiontable + len);
/* determine sequence of loops for optimization by topological sort */
/* init queue */
start = NULL;
- temp = c_allLoops;
+ temp = ld->c_allLoops;
while (temp != NULL) {
/* a loops with indegree == 0 are pushed onto the stack */
/* pop each node from the stack and decrease its parents indegree by one */
/* when the parents indegree reaches zero, push it onto the stack as well */
- if ((last->parent != root) && (--last->parent->in_degree == 0)) {
+ if ((last->parent != ld->root) && (--last->parent->in_degree == 0)) {
last->parent->next = start;
start = last->parent;
}
start = start->next;
last = last->next;
- if ((last->parent != root) && (--last->parent->in_degree == 0)) {
+ if ((last->parent != ld->root) && (--last->parent->in_degree == 0)) {
last->parent->next = start;
start = last->parent;
}
}
last->next = NULL;
- c_allLoops = first;
+ ld->c_allLoops = first;
#ifdef LOOP_DEBUG
printf("*** Hierarchie Results \n");
#endif
}
+
/* This function is used to add variables that occur as index variables in
array accesses (ARRAY_INDEX) or as variables, that change their value (VAR_MOD)
to the list of interesting vars (c_loopvars) for the current loop.
*/
-void add_to_vars(int var, int type, int direction)
+
+void add_to_vars(loopdata *ld, int var, int type, int direction)
{
struct LoopVar *lv;
/* printf("Added to vars %d %d %d\n", var, type, direction); */
- lv = c_loopvars;
+ lv = ld->c_loopvars;
while (lv != NULL) { /* check if var has been previously added */
if (lv->value == var) {
if (type == ARRAY_INDEX)
/* no dynamic bounds have been determined so far */
lv->dynamic_l = lv->dynamic_l_v = lv->dynamic_u = lv->dynamic_u_v = 0;
- lv->next = c_loopvars; /* add var to list */
- c_loopvars = lv;
+ lv->next = ld->c_loopvars; /* add var to list */
+ ld->c_loopvars = lv;
}
+
/* This function checks, whether a given loop with header node contains array
accesses. If so, it returns 1, else it returns 0 and the loops needs no
further consideration in the optimization process. When array accesses are
stored in c_loopvars. For all variables (integer), which values are changed,
a flag in c_var_modified is set.
*/
-int analyze_for_array_access(methodinfo *m, int node)
+
+int analyze_for_array_access(methodinfo *m, loopdata *ld, int node)
{
basicblock bp;
instruction *ip;
struct depthElement *d;
struct Trace *t;
- if (c_toVisit[node] > 0) { /* node has not been visited yet */
- c_toVisit[node] = 0;
+ if (ld->c_toVisit[node] > 0) { /* node has not been visited yet */
+ ld->c_toVisit[node] = 0;
bp = m->basicblocks[node]; /* prepare an instruction scan */
ip = bp.iinstr;
if (t->type == TRACE_IVAR) {
/* if it is a variable, add it to list of index variables */
- add_to_vars(t->var, ARRAY_INDEX, D_UNKNOWN);
+ add_to_vars(ld, t->var, ARRAY_INDEX, D_UNKNOWN);
access++;
}
else if (t->type == TRACE_ICONST)
if (t->type == TRACE_IVAR) {
/* if it is a variable, add it to list of index variables */
- add_to_vars(t->var, ARRAY_INDEX, D_UNKNOWN);
+ add_to_vars(ld, t->var, ARRAY_INDEX, D_UNKNOWN);
access++;
}
else if (t->type == TRACE_ICONST)
break;
case ICMD_ISTORE: /* integer store */
- c_var_modified[ip->op1] = 1;
+ ld->c_var_modified[ip->op1] = 1;
/* try to find out, how it was modified */
t = tracing(&bp, i-1, 0);
if (t->type == TRACE_IVAR) {
if ((t->constant > 0) && (t->var == ip->op1))
/* a constant was added to the same var */
- add_to_vars(t->var, VAR_MOD, D_UP);
+ add_to_vars(ld, t->var, VAR_MOD, D_UP);
else if (t->var == ip->op1)
/* a constant was subtracted from the same var */
- add_to_vars(t->var, VAR_MOD, D_DOWN);
+ add_to_vars(ld, t->var, VAR_MOD, D_DOWN);
else
- add_to_vars(t->var, VAR_MOD, D_UNKNOWN);
+ add_to_vars(ld, t->var, VAR_MOD, D_UNKNOWN);
}
else
- add_to_vars(ip->op1, VAR_MOD, D_UNKNOWN);
+ add_to_vars(ld, ip->op1, VAR_MOD, D_UNKNOWN);
break;
case ICMD_IINC: /* simple add/sub of a constant */
- c_var_modified[ip->op1] = 1;
+ ld->c_var_modified[ip->op1] = 1;
if (ip->val.i > 0)
- add_to_vars(ip->op1, VAR_MOD, D_UP);
+ add_to_vars(ld, ip->op1, VAR_MOD, D_UP);
else
- add_to_vars(ip->op1, VAR_MOD, D_DOWN);
+ add_to_vars(ld, ip->op1, VAR_MOD, D_DOWN);
break;
case ICMD_LSTORE:
case ICMD_FSTORE:
case ICMD_DSTORE:
case ICMD_ASTORE:
- c_var_modified[ip->op1] = 1;
+ ld->c_var_modified[ip->op1] = 1;
break;
}
}
- d = c_dTable[node];
+ d = ld->c_dTable[node];
while (d != NULL) { /* check all successors of block */
- access += analyze_for_array_access(m, d->value);
+ access += analyze_for_array_access(m, ld, d->value);
d = d->next;
}
return 0;
}
+
/* This function scans the exception graph structure to find modifications of
array index variables of the current loop. If any modifications are found,
1 is returned, else 0.
*/
-int quick_scan(methodinfo *m, int node)
+
+int quick_scan(methodinfo *m, loopdata *ld, int node)
{
basicblock bp;
instruction *ip;
int count, i;
struct LoopVar *lv;
struct depthElement *d;
-
- /* printf("QS: %d - %d\n", node, c_exceptionVisit[node]); */
+
+ /* printf("QS: %d - %d\n", node, ld->c_exceptionVisit[node]); */
- if (c_exceptionVisit[node] > 0) { /* node is part of exception graph */
- c_exceptionVisit[node] = -1;
+ if (ld->c_exceptionVisit[node] > 0) { /* node is part of exception graph */
+ ld->c_exceptionVisit[node] = -1;
bp = m->basicblocks[node]; /* setup scan of all instructions */
ip = bp.iinstr;
case ICMD_ISTORE:
case ICMD_IINC: /* a variable is modified */
- lv = c_loopvars; /* is it an array index var ? */
+ lv = ld->c_loopvars; /* is it an array index var ? */
while (lv != NULL) {
if ((lv->index) && (lv->value == ip->op1))
return 1; /* yes, so return 1 */
}
}
- d = c_exceptionGraph[node]; /* check all successor nodes */
+ d = ld->c_exceptionGraph[node]; /* check all successor nodes */
while (d != NULL) {
- if (quick_scan(m, d->value) > 0)
+ if (quick_scan(m, ld, d->value) > 0)
return 1; /* if an access is found return 1 */
d = d->next;
}
return 0;
}
+
/* This function returns 1, when the condition of the loop contains
or statements or when an array index variable is modified in any
catch block within the loop.
*/
-int analyze_or_exceptions(methodinfo *m, int head, struct LoopContainer *lc)
+
+int analyze_or_exceptions(methodinfo *m, loopdata *ld, int head, struct LoopContainer *lc)
{
struct depthElement *d;
int i, k, value, flag, count;
struct LoopElement *le;
- d = c_dTable[head];
+ d = ld->c_dTable[head];
count = flag = 0;
/* analyze for or-statements */
if ((count > 1) && (flag == 0)){/* if all successors part of the loop, exit */
#ifdef STATISTICS
- c_stat_or++;
+ ld->c_stat_or++;
#endif
return 0;
}
if (!m->exceptiontablelength) /* when there are no exceptions, exit */
return 1;
- if ((c_exceptionGraph = (struct depthElement **) malloc(sizeof(struct depthElement *) * m->basicblockcount)) == NULL)
+ if ((ld->c_exceptionGraph = (struct depthElement **) malloc(sizeof(struct depthElement *) * m->basicblockcount)) == NULL)
c_mem_error();
- if ((c_exceptionVisit = (int *) malloc(sizeof(int) * m->basicblockcount)) == NULL)
+ if ((ld->c_exceptionVisit = (int *) malloc(sizeof(int) * m->basicblockcount)) == NULL)
c_mem_error();
for (k=0; k<m->basicblockcount; ++k) {
- c_exceptionVisit[k] = -1;
- c_exceptionGraph[k] = NULL;
+ ld->c_exceptionVisit[k] = -1;
+ ld->c_exceptionGraph[k] = NULL;
}
/* for all nodes that start catch block check whether they are part of loop */
- for (i = 0; i < c_old_xtablelength; i++) {
+ for (i = 0; i < ld->c_old_xtablelength; i++) {
value = m->basicblockindex[m->exceptiontable[i].startpc];
le = lc->nodes;
/* build a graph structure, that contains all nodes that are */
/* part of the catc block */
- dF_Exception(m, -1, m->basicblockindex[m->exceptiontable[i].handlerpc]);
+ dF_Exception(m, ld, -1, m->basicblockindex[m->exceptiontable[i].handlerpc]);
/* if array index variables are modified there, return 0 */
- if (quick_scan(m, m->basicblockindex[m->exceptiontable[i].handlerpc]) > 0) {
+ if (quick_scan(m, ld, m->basicblockindex[m->exceptiontable[i].handlerpc]) > 0) {
#ifdef STATISTICS
- c_stat_exception++;
+ ld->c_stat_exception++;
#endif
/* printf("C_INFO: loopVar modified in exception\n"); */
return 0;
return 1;
}
+
/* This function sets a flag in c_var_modified for all variables that have
been found as part of an assigment in the loop.
*/
-void scan_global_list()
+
+void scan_global_list(loopdata *ld)
{
struct LoopVar *lv;
- lv = c_loopvars;
+ lv = ld->c_loopvars;
while (lv != NULL) {
if (lv->modified)
- c_var_modified[lv->value] = 1;
+ ld->c_var_modified[lv->value] = 1;
lv = lv->next;
}
}
+
/* This function analyses the condition in the loop header and trys to find
out, whether some dynamic guarantees can be set up.
*/
-void init_constraints(methodinfo *m, int head)
+
+void init_constraints(methodinfo *m, loopdata *ld, int head)
{
basicblock bp;
instruction *ip;
l_mod = r_mod = 0;
if (left->type == TRACE_IVAR) { /* is a loop variable on left side ? */
- lv_left = c_loopvars;
+ lv_left = ld->c_loopvars;
while (lv_left != NULL) {
if (lv_left->value == left->var) {
l_mod = lv_left->modified; /* yes, but has it been modified ? */
}
if (right->type == TRACE_IVAR){ /* is a loop variable on right side ? */
- lv_right = c_loopvars;
+ lv_right = ld->c_loopvars;
while (lv_right != NULL) {
if (lv_right->value == right->var) {
r_mod = lv_right->modified; /* yes, but has it been modified ? */
}
if ((l_mod - r_mod) == 0) { /* both 1 or both 0 -> no dynamic contraints*/
- c_rightside = NULL; /* possible */
+ ld->c_rightside = NULL; /* possible */
return;
}
/* make sure that right side's value does not change during loop execution */
if (right->type == TRACE_UNKNOWN) {
- c_rightside = NULL;
+ ld->c_rightside = NULL;
return;
}
printf("C_ERROR: debugging error 0x01\n");
}
- c_rightside = right;
+ ld->c_rightside = right;
- switch (c_rightside->type) {
+ switch (ld->c_rightside->type) {
case TRACE_ICONST:
- c_rs_needed_instr = 1;
+ ld->c_rs_needed_instr = 1;
break;
case TRACE_ALENGTH:
- c_rs_needed_instr = 2;
+ ld->c_rs_needed_instr = 2;
break;
case TRACE_IVAR:
- c_rs_needed_instr = 3;
+ ld->c_rs_needed_instr = 3;
break;
default:
printf("C_ERROR: wrong right-side type\n");
}
}
+
/* This function is needed to add and record new static tests (before loop
entry) of variables to make guaratees for index variables. type states
the kind of the test. arrayRef is the array, which length is tested
against, varRef is the variable, that is testes and constant is the
constant value, that is tested.
*/
-void add_new_constraint(methodinfo *m, int type, int arrayRef, int varRef, int constant)
+
+void add_new_constraint(methodinfo *m, loopdata *ld, int type, int arrayRef, int varRef, int constant)
{
struct Constraint *tc;
switch (type) {
case TEST_ZERO: /* a variable is tested against a const */
- tc = c_constraints[varRef]; /* does a test already exist for this var ? */
+ tc = ld->c_constraints[varRef]; /* does a test already exist for this var ? */
while (tc != NULL) {
if (tc->type == TEST_ZERO) {
if (constant < tc->constant)
tc->type = TEST_ZERO;
tc->varRef = varRef;
tc->constant = constant;
- tc->next = c_constraints[varRef];
- c_constraints[varRef] = tc;
- c_needed_instr += 3;
+ tc->next = ld->c_constraints[varRef];
+ ld->c_constraints[varRef] = tc;
+ ld->c_needed_instr += 3;
break;
case TEST_ALENGTH: /* variable is tested against array length */
- tc = c_constraints[varRef]; /* does a test already exist for this var ? */
+ tc = ld->c_constraints[varRef]; /* does a test already exist for this var ? */
while (tc != NULL) {
if ((tc->type == TEST_ALENGTH) && (tc->arrayRef == arrayRef)) {
if (constant > tc->constant)
tc->arrayRef = arrayRef;
tc->varRef = varRef;
tc->constant = constant;
- tc->next = c_constraints[varRef];
- c_constraints[varRef] = tc;
- c_needed_instr += 6;
+ tc->next = ld->c_constraints[varRef];
+ ld->c_constraints[varRef] = tc;
+ ld->c_needed_instr += 6;
/* if arrayRef is not already tested against null, insert that test */
- if (!(c_null_check[arrayRef])) {
- c_null_check[arrayRef] = 1;
- c_needed_instr +=2;
+ if (!(ld->c_null_check[arrayRef])) {
+ ld->c_null_check[arrayRef] = 1;
+ ld->c_needed_instr +=2;
}
break;
case TEST_CONST_ALENGTH: /* a const is tested against array length */
/* does a test already exist for this array */
- tc = c_constraints[m->maxlocals];
+ tc = ld->c_constraints[m->maxlocals];
while (tc != NULL) {
if ((tc->type == TEST_CONST_ALENGTH) && (tc->arrayRef == arrayRef)) {
if (constant > tc->constant)
tc->type = TEST_CONST_ALENGTH;
tc->arrayRef = arrayRef;
tc->constant = constant;
- tc->next = c_constraints[m->maxlocals];
- c_constraints[m->maxlocals] = tc;
- c_needed_instr += 4;
+ tc->next = ld->c_constraints[m->maxlocals];
+ ld->c_constraints[m->maxlocals] = tc;
+ ld->c_needed_instr += 4;
/* if arrayRef is not already tested against null, insert that test */
- if (!(c_null_check[arrayRef])) {
- c_null_check[arrayRef] = 1;
- c_needed_instr +=2;
+ if (!(ld->c_null_check[arrayRef])) {
+ ld->c_null_check[arrayRef] = 1;
+ ld->c_needed_instr +=2;
}
break;
case TEST_UNMOD_ZERO: /* test unmodified var against constant */
/* search if test already exists */
- tc = c_constraints[varRef];
+ tc = ld->c_constraints[varRef];
while (tc != NULL) {
if (tc->type == TEST_UNMOD_ZERO) {
if (constant < tc->constant)
tc->type = TEST_UNMOD_ZERO;
tc->varRef = varRef;
tc->constant = constant;
- tc->next = c_constraints[varRef];
- c_constraints[varRef] = tc;
- c_needed_instr += 3;
+ tc->next = ld->c_constraints[varRef];
+ ld->c_constraints[varRef] = tc;
+ ld->c_needed_instr += 3;
break;
case TEST_UNMOD_ALENGTH: /* test unmodified var against array length */
/* search if test alreay exists */
- tc = c_constraints[varRef];
+ tc = ld->c_constraints[varRef];
while (tc != NULL) {
if ((tc->type == TEST_UNMOD_ALENGTH) && (tc->arrayRef == arrayRef)) {
if (constant > tc->constant)
tc->varRef = varRef;
tc->arrayRef = arrayRef;
tc->constant = constant;
- tc->next = c_constraints[varRef];
- c_constraints[varRef] = tc;
- c_needed_instr += 6;
+ tc->next = ld->c_constraints[varRef];
+ ld->c_constraints[varRef] = tc;
+ ld->c_needed_instr += 6;
/* if arrayRef is not already tested against null, insert that test */
- if (!(c_null_check[arrayRef])) {
- c_null_check[arrayRef] = 1;
- c_needed_instr +=2;
+ if (!(ld->c_null_check[arrayRef])) {
+ ld->c_null_check[arrayRef] = 1;
+ ld->c_needed_instr +=2;
}
break;
/* checks */
/*!! varRef -> maxlocals */
/* search if test already exists */
- tc = c_constraints[m->maxlocals];
+ tc = ld->c_constraints[m->maxlocals];
while (tc != NULL) {
if (tc->type == TEST_RS_ZERO) {
if (constant < tc->constant)
c_mem_error();
tc->type = TEST_RS_ZERO;
tc->constant = constant;
- tc->next = c_constraints[m->maxlocals];
- c_constraints[m->maxlocals] = tc;
- c_needed_instr += (2 + c_rs_needed_instr);
+ tc->next = ld->c_constraints[m->maxlocals];
+ ld->c_constraints[m->maxlocals] = tc;
+ ld->c_needed_instr += (2 + ld->c_rs_needed_instr);
/* if arrayRef on right side is not already tested against null, */
/* insert that test */
- if ((c_rightside->type == TRACE_ALENGTH) && (!(c_null_check[c_rightside->var]))) {
- c_null_check[c_rightside->var] = 1;
- c_needed_instr +=2;
+ if ((ld->c_rightside->type == TRACE_ALENGTH) && (!(ld->c_null_check[ld->c_rightside->var]))) {
+ ld->c_null_check[ld->c_rightside->var] = 1;
+ ld->c_needed_instr +=2;
}
break;
/* checks */
/*!! varRef -> maxlocals */
/* search if test already exists */
- tc = c_constraints[m->maxlocals];
+ tc = ld->c_constraints[m->maxlocals];
while (tc != NULL)
{
if ((tc->type == TEST_RS_ALENGTH) && (tc->arrayRef == arrayRef))
tc->type = TEST_RS_ALENGTH;
tc->arrayRef = arrayRef;
tc->constant = constant;
- tc->next = c_constraints[m->maxlocals];
- c_constraints[m->maxlocals] = tc;
- c_needed_instr += (3 + c_rs_needed_instr);
+ tc->next = ld->c_constraints[m->maxlocals];
+ ld->c_constraints[m->maxlocals] = tc;
+ ld->c_needed_instr += (3 + ld->c_rs_needed_instr);
/* if arrayRef is not already tested against null, insert that test */
- if (!(c_null_check[arrayRef])) {
- c_null_check[arrayRef] = 1;
- c_needed_instr +=2;
+ if (!(ld->c_null_check[arrayRef])) {
+ ld->c_null_check[arrayRef] = 1;
+ ld->c_needed_instr +=2;
}
/* if arrayRef on right side is not already tested against null, */
/* insert that test */
- if ((c_rightside->type == TRACE_ALENGTH) && (!(c_null_check[c_rightside->var]))) {
- c_null_check[c_rightside->var] = 1;
- c_needed_instr +=2;
+ if ((ld->c_rightside->type == TRACE_ALENGTH) && (!(ld->c_null_check[ld->c_rightside->var]))) {
+ ld->c_null_check[ld->c_rightside->var] = 1;
+ ld->c_needed_instr +=2;
}
break;
}
}
+
/* This functions adds new static (before loop enry) tests of variables to the
program to be able to guarantee certain values for index variables in array
access (to safely remove bound checks).
*/
-int insert_static(methodinfo *m, int arrayRef, struct Trace *index, struct Changes *varChanges, int special)
+
+int insert_static(methodinfo *m, loopdata *ld, int arrayRef, struct Trace *index, struct Changes *varChanges, int special)
{
struct LoopVar *lv;
int varRef;
case TRACE_IVAR: /* it is a variable */
if (index->neg < 0) { /* if it's a negated var, return */
#ifdef STATISTICS
- c_stat_no_opt++;
+ ld->c_stat_no_opt++;
#endif
return OPT_NONE;
}
varRef = index->var;
high = low = 0;
- if (c_var_modified[varRef]) { /* volatile var */
+ if (ld->c_var_modified[varRef]) { /* volatile var */
- lv = c_loopvars; /* get reference to loop variable */
+ lv = ld->c_loopvars; /* get reference to loop variable */
while ((lv != NULL) && (lv->value != varRef))
lv = lv->next;
/* the var is never decremented, so we add a static test againt */
/* constant */
if (varChanges->lower_bound > varChanges->upper_bound)
- add_new_constraint(m, TEST_ZERO, arrayRef, varRef, index->constant);
+ add_new_constraint(m, ld, TEST_ZERO, arrayRef, varRef, index->constant);
else
- add_new_constraint(m, TEST_ZERO, arrayRef, varRef, varChanges->lower_bound+index->constant);
+ add_new_constraint(m, ld, TEST_ZERO, arrayRef, varRef, varChanges->lower_bound+index->constant);
low = 1;
}
else if ((lv->dynamic_l_v) && (!special)) {
/* the variable is decremented, but it is checked against a */
/* bound in the loop condition */
if (varChanges->lower_bound <= varChanges->upper_bound) {
- add_new_constraint(m, TEST_RS_ZERO, arrayRef, varRef, varChanges->lower_bound+index->constant+lv->dynamic_l);
+ add_new_constraint(m, ld, TEST_RS_ZERO, arrayRef, varRef, varChanges->lower_bound+index->constant+lv->dynamic_l);
low = 1;
}
}
/* the var is never incremented, so we add a static test againt */
/* constant */
if (varChanges->lower_bound > varChanges->upper_bound)
- add_new_constraint(m, TEST_ALENGTH, arrayRef, varRef, index->constant);
+ add_new_constraint(m, ld, TEST_ALENGTH, arrayRef, varRef, index->constant);
else
- add_new_constraint(m, TEST_ALENGTH, arrayRef, varRef, varChanges->upper_bound+index->constant);
+ add_new_constraint(m, ld, TEST_ALENGTH, arrayRef, varRef, varChanges->upper_bound+index->constant);
high = 1;
}
else if ((lv->dynamic_u_v) && (!special)) {
/* the variable is decremented, but it is checked against a */
/* bound in the loop condition */
if (varChanges->lower_bound <= varChanges->upper_bound) {
- add_new_constraint(m, TEST_RS_ALENGTH, arrayRef, varRef, varChanges->upper_bound+index->constant+lv->dynamic_u);
+ add_new_constraint(m, ld, TEST_RS_ALENGTH, arrayRef, varRef, varChanges->upper_bound+index->constant+lv->dynamic_u);
high = 1;
}
}
}
else { /* the var is never modified at all */
- add_new_constraint(m, TEST_UNMOD_ZERO, arrayRef, index->var, index->constant);
- add_new_constraint(m, TEST_UNMOD_ALENGTH, arrayRef, index->var, index->constant);
+ add_new_constraint(m, ld, TEST_UNMOD_ZERO, arrayRef, index->var, index->constant);
+ add_new_constraint(m, ld, TEST_UNMOD_ALENGTH, arrayRef, index->var, index->constant);
low = high = 1;
}
if ((high > 0) && (low > 0)) {
/* printf("fully optimzed\n"); */
#ifdef STATISTICS
- c_stat_full_opt++;
+ ld->c_stat_full_opt++;
#endif
return OPT_FULL;
}
else if (high > 0) {
/* printf("upper optimzed\n"); */
#ifdef STATISTICS
- c_stat_upper_opt++;
+ ld->c_stat_upper_opt++;
#endif
return OPT_UPPER;
}
else if (low > 0) {
/* printf("lower optimzed\n"); */
#ifdef STATISTICS
- c_stat_lower_opt++;
+ ld->c_stat_lower_opt++;
#endif
return OPT_LOWER;
}
else {
/* printf("not optimzed\n"); */
#ifdef STATISTICS
- c_stat_no_opt++;
+ ld->c_stat_no_opt++;
#endif
return OPT_NONE;
}
case TRACE_ICONST: /* if it is a constant, optimization is easy */
if (index->constant < 0) {
#ifdef STATISTICS
- c_stat_no_opt++;
+ ld->c_stat_no_opt++;
#endif
return OPT_NONE; /* negative index -> bad */
}
else {
- add_new_constraint(m, TEST_CONST_ALENGTH, arrayRef, 0, index->constant);
+ add_new_constraint(m, ld, TEST_CONST_ALENGTH, arrayRef, 0, index->constant);
#ifdef STATISTICS
- c_stat_full_opt++;
+ ld->c_stat_full_opt++;
#endif
return OPT_FULL; /* else just test constant against array length */
}
case TRACE_UNKNOWN:
case TRACE_AVAR:
#ifdef STATISTICS
- c_stat_no_opt++;
+ ld->c_stat_no_opt++;
#endif
return OPT_NONE;
}
/* fisrt, the reference must be loaded, then a null-pointer check is inserted */
/* if not already done earlier. Finally an arraylength instruction is added */
#define LOAD_ARRAYLENGTH(a) { \
- if (c_null_check[a]) { \
+ if (ld->c_null_check[a]) { \
LOAD_ADDR(a); \
GOTO_NOOPT_IF_NULL; \
- c_null_check[a] = 0; \
+ ld->c_null_check[a] = 0; \
} \
LOAD_ADDR(a); \
inst->opc = ICMD_ARRAYLENGTH; \
/* Depending of the type of the right side, the apropriate instructions are */
/* created. */
#define LOAD_RIGHT_SIDE { \
- switch (c_rightside->type) { \
+ switch (ld->c_rightside->type) { \
case TRACE_ICONST: \
- LOAD_CONST(c_rightside->constant); \
+ LOAD_CONST(ld->c_rightside->constant); \
break; \
case TRACE_IVAR: \
- LOAD_VAR(c_rightside->var); \
- LOAD_CONST(c_rightside->constant); \
+ LOAD_VAR(ld->c_rightside->var); \
+ LOAD_CONST(ld->c_rightside->constant); \
ADD; \
break; \
case TRACE_ALENGTH: \
- LOAD_ARRAYLENGTH(c_rightside->var); \
+ LOAD_ARRAYLENGTH(ld->c_rightside->var); \
break; \
default: \
panic("C_ERROR: illegal trace on rightside of loop-header"); \
}
}
+
/* Add the new header node of a loop that has been duplicated to all parent
loops in nesting hierarchie.
*/
-void header_into_parent_loops(struct LoopContainer *lc, basicblock *to_insert, basicblock *replace, basicblock *after)
+
+void header_into_parent_loops(loopdata *ld, struct LoopContainer *lc, basicblock *to_insert, basicblock *replace, basicblock *after)
{
/* we have to insert the node to_insert before the node after and replace */
/* the pointer of to_insert by the node replace */
struct LoopElement *le, *t;
/* if the top of the tree is reached, then return */
- if ((lc == NULL) || (lc == root))
+ if ((lc == NULL) || (lc == ld->root))
return;
/* create new node, that should be inserted */
}
/* go up one hierarchie level */
- header_into_parent_loops(lc->parent, to_insert, replace, after);
+ header_into_parent_loops(ld, lc->parent, to_insert, replace, after);
}
+
/* Add a new node (not header) of a duplicated loop to all parent loops in
nesting hierarchie
*/
-void node_into_parent_loops(struct LoopContainer *lc, basicblock *to_insert)
+
+void node_into_parent_loops(loopdata *ld, struct LoopContainer *lc, basicblock *to_insert)
{
struct LoopElement *le, *t;
/* if the top of the tree is reached, then return */
- if ((lc == NULL) || (lc == root))
+ if ((lc == NULL) || (lc == ld->root))
return;
/* create new node, that should be inserted */
- t = DMNEW(struct LoopElement, 1);
+ t = DNEW(LoopElement);
t->block = to_insert;
t->node = -1;
le->next = t;
/* go up one hierarchie level */
- node_into_parent_loops(NULL, to_insert);
+ node_into_parent_loops(ld, NULL, to_insert);
}
to redirect internal jumps inside the exception handler to the newly
created (copied) nodes.
*/
+
void patch_handler(struct LoopContainer *lc, basicblock *bptr, basicblock *original_head, basicblock *new_head)
{
instruction *ip;
}
-/* This function copys the exception handler and redirects all jumps from the
+/* copy_handler ****************************************************************
+
+ This function copys the exception handler and redirects all jumps from the
original head to the new head in the original exception handler. All
redirection in the copied exception handler is done in patch_handler(...).
-*/
-void copy_handler(methodinfo *m, struct LoopContainer *lc, basicblock *bptr, basicblock *original_head, basicblock *new_head)
+
+*******************************************************************************/
+
+void copy_handler(methodinfo *m, loopdata *ld, struct LoopContainer *lc, basicblock *bptr, basicblock *original_head, basicblock *new_head)
{
instruction *ip;
s4 *s4ptr;
struct LoopElement *le;
basicblock *new, *temp;
- /* If this node has already been copied, return */
+ /* If this node has already been copied, return */
if (bptr->lflags & HANDLER_PART)
return;
- /* The exception handler exists, when control flow enters loop again */
+ /* The exception handler exists, when control flow enters loop again */
if (bptr->lflags & LOOP_PART)
return;
}
}
- /* mark block as part of handler */
+ /* mark block as part of handler */
bptr->lflags |= HANDLER_PART;
- /* copy node */
+ /* copy node */
new = DMNEW(basicblock, 1);
memcpy(new, bptr, sizeof(basicblock));
- new->debug_nr = c_debug_nr++;
+ new->debug_nr = m->c_debug_nr++;
- c_last_block_copied = new;
+ ld->c_last_block_copied = new;
- /* copy instructions and allow one more slot for possible GOTO */
+ /* copy instructions and allow one more slot for possible GOTO */
new->iinstr = DMNEW(instruction, bptr->icount + 1);
- memcpy(new->iinstr, bptr->iinstr, bptr->icount*sizeof(instruction));
+ memcpy(new->iinstr, bptr->iinstr, bptr->icount * sizeof(instruction));
- /* update original block */
+ /* update original block */
bptr->copied_to = new;
- /* append block to global list of basic blocks */
+ /* append block to global list of basic blocks */
temp = m->basicblocks;
while (temp->next)
/* find next block to copy, depending on last instruction of BB */
if (bptr->icount == 0) {
- copy_handler(m, lc, bptr->next, original_head, new_head);
+ copy_handler(m, ld, lc, bptr->next, original_head, new_head);
return;
- }
+ }
ip = bptr->iinstr + (bptr->icount - 1);
- switch (ip->opc) {
- case ICMD_RETURN:
- case ICMD_IRETURN:
- case ICMD_LRETURN:
- case ICMD_FRETURN:
- case ICMD_DRETURN:
- case ICMD_ARETURN:
- case ICMD_ATHROW:
- break;
+ switch (ip->opc) {
+ case ICMD_RETURN:
+ case ICMD_IRETURN:
+ case ICMD_LRETURN:
+ case ICMD_FRETURN:
+ case ICMD_DRETURN:
+ case ICMD_ARETURN:
+ case ICMD_ATHROW:
+ break;
- case ICMD_IFEQ:
- case ICMD_IFNE:
- case ICMD_IFLT:
- case ICMD_IFGE:
- case ICMD_IFGT:
- case ICMD_IFLE:
+ case ICMD_IFEQ:
+ case ICMD_IFNE:
+ case ICMD_IFLT:
+ case ICMD_IFGE:
+ case ICMD_IFGT:
+ case ICMD_IFLE:
- case ICMD_IF_LCMPEQ:
- case ICMD_IF_LCMPLT:
- case ICMD_IF_LCMPLE:
- case ICMD_IF_LCMPNE:
- case ICMD_IF_LCMPGT:
- case ICMD_IF_LCMPGE:
+ case ICMD_IF_LCMPEQ:
+ case ICMD_IF_LCMPLT:
+ case ICMD_IF_LCMPLE:
+ case ICMD_IF_LCMPNE:
+ case ICMD_IF_LCMPGT:
+ case ICMD_IF_LCMPGE:
- case ICMD_IF_LEQ:
- case ICMD_IF_LNE:
- case ICMD_IF_LLT:
- case ICMD_IF_LGE:
- case ICMD_IF_LGT:
- case ICMD_IF_LLE:
+ case ICMD_IF_LEQ:
+ case ICMD_IF_LNE:
+ case ICMD_IF_LLT:
+ case ICMD_IF_LGE:
+ case ICMD_IF_LGT:
+ case ICMD_IF_LLE:
- case ICMD_IFNULL:
- case ICMD_IFNONNULL:
+ case ICMD_IFNULL:
+ case ICMD_IFNONNULL:
- case ICMD_IF_ICMPEQ:
- case ICMD_IF_ICMPNE:
- case ICMD_IF_ICMPLT:
- case ICMD_IF_ICMPGE:
- case ICMD_IF_ICMPGT:
- case ICMD_IF_ICMPLE:
- case ICMD_IF_ACMPEQ:
- case ICMD_IF_ACMPNE:
- copy_handler(m, lc, bptr->next, original_head, new_head);
- /* fall through */
+ case ICMD_IF_ICMPEQ:
+ case ICMD_IF_ICMPNE:
+ case ICMD_IF_ICMPLT:
+ case ICMD_IF_ICMPGE:
+ case ICMD_IF_ICMPGT:
+ case ICMD_IF_ICMPLE:
+ case ICMD_IF_ACMPEQ:
+ case ICMD_IF_ACMPNE:
+ copy_handler(m, ld, lc, bptr->next, original_head, new_head);
+ /* fall through */
- case ICMD_GOTO:
+ case ICMD_GOTO:
- /* redirect jump from original_head to new_head */
- if ((basicblock *) ip->target == original_head)
- ip->target = (void *) new_head;
+ /* redirect jump from original_head to new_head */
+ if ((basicblock *) ip->target == original_head)
+ ip->target = (void *) new_head;
- copy_handler(m, lc, (basicblock *) (ip->target), original_head, new_head);
+ copy_handler(m, ld, lc, (basicblock *) (ip->target), original_head, new_head);
- break;
+ break;
- case ICMD_TABLESWITCH:
- s4ptr = ip->val.a;
- tptr = (void **) ip->target;
+ case ICMD_TABLESWITCH:
+ s4ptr = ip->val.a;
+ tptr = (void **) ip->target;
- /* default branch */
- if (((basicblock *) *tptr) == original_head)
- tptr[0] = (void *) new_head;
-
- copy_handler(m, lc, (basicblock *) *tptr, original_head, new_head);
+ /* default branch */
+ if (((basicblock *) *tptr) == original_head)
+ tptr[0] = (void *) new_head;
- s4ptr++;
- low = *s4ptr;
- s4ptr++;
- high = *s4ptr;
+ copy_handler(m, ld, lc, (basicblock *) *tptr, original_head, new_head);
- count = (high-low+1);
+ s4ptr++;
+ low = *s4ptr;
+ s4ptr++;
+ high = *s4ptr;
- while (--count >= 0) {
- tptr++;
- /* redirect jump from original_head to new_head */
- if (((basicblock *) *tptr) == original_head)
- tptr[0] = (void *) new_head;
- copy_handler(m, lc, (basicblock *) *tptr, original_head, new_head);
- }
- break;
-
- case ICMD_LOOKUPSWITCH:
- s4ptr = ip->val.a;
- tptr = (void **) ip->target;
+ count = (high-low+1);
- /* default branch */
+ while (--count >= 0) {
+ tptr++;
+ /* redirect jump from original_head to new_head */
if (((basicblock *) *tptr) == original_head)
tptr[0] = (void *) new_head;
+ copy_handler(m, ld, lc, (basicblock *) *tptr, original_head, new_head);
+ }
+ break;
+
+ case ICMD_LOOKUPSWITCH:
+ s4ptr = ip->val.a;
+ tptr = (void **) ip->target;
- copy_handler(m, lc, (basicblock *) *tptr, original_head, new_head);
+ /* default branch */
+ if (((basicblock *) *tptr) == original_head)
+ tptr[0] = (void *) new_head;
- ++s4ptr;
- count = *s4ptr;
+ copy_handler(m, ld, lc, (basicblock *) *tptr, original_head, new_head);
- while (--count >= 0) {
- ++tptr;
- /* redirect jump from original_head to new_head */
- if (((basicblock *) *tptr) == original_head)
- tptr[0] = (void *) new_head;
- copy_handler(m, lc, (basicblock *) *tptr, original_head, new_head);
- }
- break;
+ ++s4ptr;
+ count = *s4ptr;
+
+ while (--count >= 0) {
+ ++tptr;
+ /* redirect jump from original_head to new_head */
+ if (((basicblock *) *tptr) == original_head)
+ tptr[0] = (void *) new_head;
+ copy_handler(m, ld, lc, (basicblock *) *tptr, original_head, new_head);
+ }
+ break;
- case ICMD_JSR:
- c_last_target = bptr;
- copy_handler(m, lc, (basicblock *) (ip->target), original_head, new_head);
- break;
+ case ICMD_JSR:
+ ld->c_last_target = bptr;
+ copy_handler(m, ld, lc, (basicblock *) (ip->target), original_head, new_head);
+ break;
- case ICMD_RET:
- copy_handler(m, lc, c_last_target->next, original_head, new_head);
- break;
+ case ICMD_RET:
+ copy_handler(m, ld, lc, ld->c_last_target->next, original_head, new_head);
+ break;
- default:
- copy_handler(m, lc, bptr->next, original_head, new_head);
- break;
- }
-
+ default:
+ copy_handler(m, ld, lc, bptr->next, original_head, new_head);
+ break;
+ }
}
have to be duplicated as well. The following function together with the
two helper functions copy_handler and patch_handler perform this task.
*/
-void update_internal_exceptions(methodinfo *m, struct LoopContainer *lc, basicblock *original_head, basicblock *new_head)
+
+void update_internal_exceptions(methodinfo *m, loopdata *ld, struct LoopContainer *lc, basicblock *original_head, basicblock *new_head)
{
exceptiontable *ex, *new;
struct LoopContainer *l;
/* Call update_internal for all nested (=child) loops */
l = lc->tree_down;
while (l != NULL) {
- update_internal_exceptions(m, l, original_head, new_head);
+ update_internal_exceptions(m, ld, l, original_head, new_head);
l = l->tree_right;
}
while (ex != NULL) {
/* Copy the exception and patch the jumps */
- copy_handler(m, lc, ex->handler, original_head, new_head);
+ copy_handler(m, ld, lc, ex->handler, original_head, new_head);
patch_handler(lc, ex->handler, original_head, new_head);
/* Insert a new exception into the global exception table */
}
+
/* If a loop is duplicated, all exceptions that contain this loop have to be
extended to the copied nodes as well. The following function checks for
all exceptions of all parent loops, whether they contain the loop pointed to
by lc. If so, the exceptions are extended to contain all newly created nodes.
*/
-void update_external_exceptions(methodinfo *m, struct LoopContainer *lc, int loop_head)
+
+void update_external_exceptions(methodinfo *m, loopdata *ld, struct LoopContainer *lc, int loop_head)
{
exceptiontable *ex, *new;
ex->down = new;
/* Set new start and end point of this exception */
- new->start = c_first_block_copied;
- new->end = c_last_block_copied;
+ new->start = ld->c_first_block_copied;
+ new->end = ld->c_last_block_copied;
ex = new->next;
}
}
/* Call update_external for parent node */
- update_external_exceptions(m, lc->parent, loop_head);
+ update_external_exceptions(m, ld, lc->parent, loop_head);
}
-
/* This function is needed to insert the static checks, stored in c_constraints
into the intermediate code.
*/
-void create_static_checks(methodinfo *m, struct LoopContainer *lc)
+
+void create_static_checks(methodinfo *m, loopdata *ld, struct LoopContainer *lc)
{
int i, stackdepth, cnt;
struct Constraint *tc1;
exceptiontable *ex;
#ifdef STATISTICS
- /* show_loop_statistics(); */
+ /* show_loop_statistics(l); */
#endif
- loop_head = &m->basicblocks[c_current_head];
- c_first_block_copied = c_last_block_copied = NULL;
+ loop_head = &m->basicblocks[ld->c_current_head];
+ ld->c_first_block_copied = ld->c_last_block_copied = NULL;
/* the loop nodes are copied */
le = lc->nodes;
{
bptr = DMNEW(basicblock, 1);
memcpy(bptr, le->block, sizeof(basicblock));
- bptr->debug_nr = c_debug_nr++;
+ bptr->debug_nr = m->c_debug_nr++;
/* determine beginning of copied loop to extend exception handler, that */
/* protect this loop */
- if (c_first_block_copied == NULL)
- c_first_block_copied = bptr;
+ if (ld->c_first_block_copied == NULL)
+ ld->c_first_block_copied = bptr;
/* copy instructions and add one more slot for possible GOTO */
bptr->iinstr = DMNEW(instruction, bptr->icount + 1);
temp->next = bptr;
bptr->next = NULL;
- node_into_parent_loops(lc->parent, bptr);
+ node_into_parent_loops(ld, lc->parent, bptr);
le = le->next;
}
- c_last_block_copied = bptr;
+ ld->c_last_block_copied = bptr;
/* create an additional basicblock for dynamic checks */
original_start = bptr = DMNEW(basicblock, 1);
/* copy current loop header to new basic block */
memcpy(bptr, loop_head, sizeof(basicblock));
- bptr->debug_nr = c_debug_nr++;
+ bptr->debug_nr = m->c_debug_nr++;
/* insert the new basic block and move header before first loop node */
le = lc->nodes;
/* if first loop block is first BB of global list, insert loop_head at */
/* beginning of global BB list */
if (temp == le->block) {
- if (c_newstart == NULL) {
- c_needs_redirection = true;
- c_newstart = loop_head;
+ if (ld->c_newstart == NULL) {
+ ld->c_needs_redirection = true;
+ ld->c_newstart = loop_head;
loop_head->next = m->basicblocks;
}
else {
- loop_head->next = c_newstart;
- c_newstart = loop_head;
+ loop_head->next = ld->c_newstart;
+ ld->c_newstart = loop_head;
}
}
else {
/* insert new header node into nodelists of all enclosing loops */
- header_into_parent_loops(lc, loop_head, original_start, le->block);
+ header_into_parent_loops(ld, lc, loop_head, original_start, le->block);
/* prepare instruction array to insert checks */
- inst = loop_head->iinstr = DMNEW(instruction, c_needed_instr + 2);
- loop_head->icount = c_needed_instr + 1;
+ inst = loop_head->iinstr = DMNEW(instruction, ld->c_needed_instr + 2);
+ loop_head->icount = ld->c_needed_instr + 1;
/* init instruction array */
- for (cnt=0; cnt<c_needed_instr + 1; ++cnt) {
+ for (cnt=0; cnt<ld->c_needed_instr + 1; ++cnt) {
inst[0].opc = ICMD_NOP;
inst[0].dst = NULL;
}
/* step through all inserted checks and create instructions for them */
for (i=0; i<m->maxlocals+1; ++i)
{
- tc1 = c_constraints[i];
+ tc1 = ld->c_constraints[i];
while (tc1 != NULL)
{
switch (tc1->type)
tc1 = tc1->next;
}
- c_constraints[i] = NULL;
+ ld->c_constraints[i] = NULL;
}
/* if all tests succeed, jump to optimized loop header */
/* if exceptions have to be correct due to loop duplication these two */
/* functions perform this task. */
- update_internal_exceptions(m, lc, loop_head, original_start);
- update_external_exceptions(m, lc->parent, lc->loop_head);
+ update_internal_exceptions(m, ld, lc, loop_head, original_start);
+ update_external_exceptions(m, ld, lc->parent, lc->loop_head);
}
return tmp;
}
+
/* This function performs the main task of bound check removal. It removes
all bound-checks in node. change is a pointer to an array of struct Changes
that reflect for all local variables, how their values have changed from
the start of the loop. The special flag is needed to deal with the header
node.
*/
-void remove_boundchecks(methodinfo *m, int node, int from, struct Changes **change, int special)
+
+void remove_boundchecks(methodinfo *m, loopdata *ld, int node, int from, struct Changes **change, int special)
{
basicblock bp;
instruction *ip;
/* a flag, that is set, when previous optimzations have to be taken back */
degrade_checks = 0;
- if (c_current_loop[node] > 0) { /* this node is part of the loop */
- if (c_current_loop[node] > 1) { /* it is not the header node */
+ if (ld->c_current_loop[node] > 0) { /* this node is part of the loop */
+ if (ld->c_current_loop[node] > 1) { /* it is not the header node */
/* get variable changes, already recorded for this node */
- t1 = c_dTable[node]->changes;
+ t1 = ld->c_dTable[node]->changes;
if (t1 != NULL) { /* it is not the first visit */
- if ((c_nestedLoops[node] != c_current_head) && (c_nestedLoops[node] == c_nestedLoops[from])) {
+ if ((ld->c_nestedLoops[node] != ld->c_current_head) && (ld->c_nestedLoops[node] == ld->c_nestedLoops[from])) {
/* we are looping in a nested loop, so made optimizations */
/* need to be reconsidered */
degrade_checks = 1;
}
else { /* first visit */
/* printf("first visit - constraints cloned\n"); */
- c_dTable[node]->changes = constraints_clone(m, change);
+ ld->c_dTable[node]->changes = constraints_clone(m, change);
}
/* tmp now holds a copy of the updated variable changes */
- tmp = constraints_clone(m, c_dTable[node]->changes);
+ tmp = constraints_clone(m, ld->c_dTable[node]->changes);
}
else if (special) { /* header and need special traetment */
/* printf("special treatment called\n"); */
#ifdef STATISTICS
if (ip->op1 == OPT_UNCHECKED) { /* found new access */
- c_stat_array_accesses++;
+ ld->c_stat_array_accesses++;
ip->op1 = OPT_NONE;
- c_stat_no_opt++;
+ ld->c_stat_no_opt++;
}
#endif
/* can only optimize known arrays that do not change */
- if ((t_array->type != TRACE_AVAR) || (c_var_modified[t_array->var]))
+ if ((t_array->type != TRACE_AVAR) || (ld->c_var_modified[t_array->var]))
break;
switch (t_index->type) { /* now we look at the index */
case OPT_UNCHECKED:
break;
case OPT_NONE:
- c_stat_no_opt--;
+ ld->c_stat_no_opt--;
break;
case OPT_FULL:
- c_stat_full_opt--;
+ ld->c_stat_full_opt--;
break;
case OPT_UPPER:
- c_stat_upper_opt--;
+ ld->c_stat_upper_opt--;
break;
case OPT_LOWER:
- c_stat_lower_opt--;
+ ld->c_stat_lower_opt--;
break;
}
#endif
if (degrade_checks) /* replace existing optimization */
- ip->op1 = insert_static(m, t_array->var, t_index, NULL, special);
+ ip->op1 = insert_static(m, ld, t_array->var, t_index, NULL, special);
else {
/* Check current optimization and try to improve it by */
/* inserting new checks */
switch (ip->op1) {
case OPT_UNCHECKED:
- ip->op1 = insert_static(m, t_array->var, t_index, NULL, special);
+ ip->op1 = insert_static(m, ld, t_array->var, t_index, NULL, special);
break;
case OPT_NONE:
- ip->op1 = insert_static(m, t_array->var, t_index, NULL, special);
+ ip->op1 = insert_static(m, ld, t_array->var, t_index, NULL, special);
break;
case OPT_UPPER:
- opt_level = insert_static(m, t_array->var, t_index, NULL, special);
+ opt_level = insert_static(m, ld, t_array->var, t_index, NULL, special);
if ((opt_level == OPT_FULL) || (opt_level == OPT_LOWER))
ip->op1 = OPT_FULL;
break;
case OPT_LOWER:
- opt_level = insert_static(m, t_array->var, t_index, NULL, special);
+ opt_level = insert_static(m, ld, t_array->var, t_index, NULL, special);
if ((opt_level == OPT_FULL) || (opt_level == OPT_UPPER))
ip->op1 = OPT_FULL;
break;
case OPT_FULL:
#ifdef STATISTICS
- c_stat_full_opt++;
+ ld->c_stat_full_opt++;
#endif
break;
}
case OPT_UNCHECKED:
break;
case OPT_NONE:
- c_stat_no_opt--;
+ ld->c_stat_no_opt--;
break;
case OPT_FULL:
- c_stat_full_opt--;
+ ld->c_stat_full_opt--;
break;
case OPT_UPPER:
- c_stat_upper_opt--;
+ ld->c_stat_upper_opt--;
break;
case OPT_LOWER:
- c_stat_lower_opt--;
+ ld->c_stat_lower_opt--;
break;
}
#endif
if (degrade_checks)
- ip->op1 = insert_static(m, t_array->var, t_index, t, special);
+ ip->op1 = insert_static(m, ld, t_array->var, t_index, t, special);
else {
/* Check current optimization and try to improve it by */
/* insert new check. t reflects var changes for index */
switch (ip->op1) {
case OPT_UNCHECKED:
- ip->op1 = insert_static(m, t_array->var, t_index, t, special);
+ ip->op1 = insert_static(m, ld, t_array->var, t_index, t, special);
break;
case OPT_NONE:
- ip->op1 = insert_static(m, t_array->var, t_index, t, special);
+ ip->op1 = insert_static(m, ld, t_array->var, t_index, t, special);
break;
case OPT_UPPER:
- opt_level = insert_static(m, t_array->var, t_index, t, special);
+ opt_level = insert_static(m, ld, t_array->var, t_index, t, special);
if ((opt_level == OPT_FULL) || (opt_level == OPT_LOWER))
ip->op1 = OPT_FULL;
break;
case OPT_LOWER:
- opt_level = insert_static(m, t_array->var, t_index, t, special);
+ opt_level = insert_static(m, ld, t_array->var, t_index, t, special);
if ((opt_level == OPT_FULL) || (opt_level == OPT_UPPER))
ip->op1 = OPT_FULL;
break;
case OPT_FULL:
#ifdef STATISTICS
- c_stat_full_opt++;
+ ld->c_stat_full_opt++;
#endif
break;
}
} /* for */
if (!special) { /* we are not interested in only the header */
- d = c_dTable[node];
+ d = ld->c_dTable[node];
while (d != NULL) { /* check all sucessors of current node */
- remove_boundchecks(m, d->value, node, tmp, special);
+ remove_boundchecks(m, ld, d->value, node, tmp, special);
d = d->next;
}
}
} /* if */
}
+
/* This function calls the bound-check removal function for the header node
with a special flag. It is important to notice, that no dynamic
constraint hold in the header node (because the comparison is done at
block end).
*/
-void remove_header_boundchecks(methodinfo *m, int node, struct Changes **changes)
+
+void remove_header_boundchecks(methodinfo *m, loopdata *ld, int node, struct Changes **changes)
{
- remove_boundchecks(m, node, -1, changes, BOUNDCHECK_SPECIAL);
+ remove_boundchecks(m, ld, node, -1, changes, BOUNDCHECK_SPECIAL);
}
+
/* Marks all basicblocks that are part of the loop
*/
+
void mark_loop_nodes(struct LoopContainer *lc)
{
struct LoopElement *le = lc->nodes;
}
}
+
/* Clears mark for all basicblocks that are part of the loop
*/
-void unmark_loop_nodes(struct LoopContainer *lc)
+void unmark_loop_nodes(LoopContainer *lc)
{
- struct LoopElement *le = lc->nodes;
+ LoopElement *le = lc->nodes;
while (le != NULL) {
le->block->lflags = 0;
le = le->next;
- }
+ }
}
identify array accesses suitable for optimization (bound check removal). The
intermediate code is then modified to reflect these optimizations.
*/
-void optimize_single_loop(methodinfo *m, struct LoopContainer *lc)
+void optimize_single_loop(methodinfo *m, loopdata *ld, LoopContainer *lc)
{
struct LoopElement *le;
struct depthElement *d;
if ((changes = (struct Changes **) malloc(m->maxlocals * sizeof(struct Changes *))) == NULL)
c_mem_error();
- head = c_current_head = lc->loop_head;
- c_needed_instr = c_rs_needed_instr = 0;
+ head = ld->c_current_head = lc->loop_head;
+ ld->c_needed_instr = ld->c_rs_needed_instr = 0;
/* init array for null ptr checks */
for (i=0; i<m->maxlocals; ++i)
- c_null_check[i] = 0;
+ ld->c_null_check[i] = 0;
/* don't optimize root node (it is the main procedure, not a loop) */
return;
/* setup variables with initial values */
- c_loopvars = NULL;
+ ld->c_loopvars = NULL;
for (i=0; i < m->basicblockcount; ++i) {
- c_toVisit[i] = 0;
- c_current_loop[i] = -1;
- if ((d = c_dTable[i]) != NULL)
+ ld->c_toVisit[i] = 0;
+ ld->c_current_loop[i] = -1;
+ if ((d = ld->c_dTable[i]) != NULL)
d->changes = NULL;
}
for (i=0; i < m->maxlocals; ++i) {
- c_var_modified[i] = 0;
+ ld->c_var_modified[i] = 0;
if (changes[i] != NULL) {
changes[i] = NULL;
}
}
for (i=0; i < (m->maxlocals+1); ++i) {
- if (c_constraints[i] != NULL) {
- c_constraints[i] = NULL;
+ if (ld->c_constraints[i] != NULL) {
+ ld->c_constraints[i] = NULL;
}
}
node = le->node;
if (node == head)
- c_current_loop[node] = 1; /* the header node gets 1 */
- else if (c_nestedLoops[node] == head)
- c_current_loop[node] = 2; /* top level nodes get 2 */
+ ld->c_current_loop[node] = 1; /* the header node gets 1 */
+ else if (ld->c_nestedLoops[node] == head)
+ ld->c_current_loop[node] = 2; /* top level nodes get 2 */
else
- c_current_loop[node] = 3; /* nodes, part of nested loop get 3 */
+ ld->c_current_loop[node] = 3; /* nodes, part of nested loop get 3 */
- c_toVisit[node] = 1;
+ ld->c_toVisit[node] = 1;
le = le->next;
}
fflush(stdout);
#endif
- if (analyze_for_array_access(m, head) > 0) {/* loop contains array access */
+ if (analyze_for_array_access(m, ld, head) > 0) {/* loop contains array access */
#ifdef LOOP_DEBUG
struct LoopVar *lv;
printf("analyze for array access finished and found\n");
fflush(stdout);
- lv = c_loopvars;
+ lv = ld->c_loopvars;
while (lv != NULL) {
if (lv->modified)
printf("Var --> %d\n", lv->value);
/* for performance reasons the list of all interesting loop vars is */
/* scaned and for all modified vars a flag in c_var_modified is set */
- scan_global_list();
+ scan_global_list(ld);
#ifdef LOOP_DEBUG
printf("global list scanned\n");
/* if the loop header contains or-conditions or an index variable */
/* is modified in the catch-block within the loop, a conservative */
/* approach is taken and optimizations are cancelled */
- if (analyze_or_exceptions(m, head, lc) > 0) {
+ if (analyze_or_exceptions(m, ld, head, lc) > 0) {
#ifdef LOOP_DEBUG
printf("Analyzed for or/exception - no problems \n");
fflush(stdout);
#endif
- init_constraints(m, head); /* analyze dynamic bounds in header */
+ init_constraints(m, ld, head); /* analyze dynamic bounds in header */
#ifdef LOOP_DEBUG
show_right_side();
#endif
- if (c_rightside == NULL)
+ if (ld->c_rightside == NULL)
return;
/* single pass bound check removal - for all successors, do */
- remove_header_boundchecks(m, head, changes);
+ remove_header_boundchecks(m, ld, head, changes);
- d = c_dTable[head];
+ d = ld->c_dTable[head];
while (d != NULL) {
- remove_boundchecks(m, d->value, -1, changes, BOUNDCHECK_REGULAR);
+ remove_boundchecks(m, ld, d->value, -1, changes, BOUNDCHECK_REGULAR);
d = d->next;
}
fflush(stdout);
#endif
- create_static_checks(m, lc); /* create checks */
+ create_static_checks(m, ld, lc); /* create checks */
#ifdef LOOP_DEBUG
printf("END: create static checks\n");
printf("No array accesses found\n"); */
#ifdef STATISTICS
- c_stat_num_loops++; /* increase number of loops */
-
- c_stat_sum_accesses += c_stat_array_accesses;
- c_stat_sum_full += c_stat_full_opt;
- c_stat_sum_no += c_stat_no_opt;
- c_stat_sum_lower += c_stat_lower_opt;
- c_stat_sum_upper += c_stat_upper_opt;
- c_stat_sum_or += c_stat_or;
- c_stat_sum_exception += c_stat_exception;
-
- c_stat_array_accesses = 0;
- c_stat_full_opt = 0;
- c_stat_no_opt = 0;
- c_stat_lower_opt = 0;
- c_stat_upper_opt = 0;
- c_stat_or = c_stat_exception = 0;
+ ld->c_stat_num_loops++; /* increase number of loops */
+
+ ld->c_stat_sum_accesses += ld->c_stat_array_accesses;
+ ld->c_stat_sum_full += ld->c_stat_full_opt;
+ ld->c_stat_sum_no += ld->c_stat_no_opt;
+ ld->c_stat_sum_lower += ld->c_stat_lower_opt;
+ ld->c_stat_sum_upper += ld->c_stat_upper_opt;
+ ld->c_stat_sum_or += ld->c_stat_or;
+ ld->c_stat_sum_exception += ld->c_stat_exception;
+
+ ld->c_stat_array_accesses = 0;
+ ld->c_stat_full_opt = 0;
+ ld->c_stat_no_opt = 0;
+ ld->c_stat_lower_opt = 0;
+ ld->c_stat_upper_opt = 0;
+ ld->c_stat_or = ld->c_stat_exception = 0;
#endif
}
+
/* This function preforms necessary setup work, before the recursive function
optimize_single loop can be called.
*/
-void optimize_loops(methodinfo *m)
+void optimize_loops(methodinfo *m, loopdata *ld)
{
- struct LoopContainer *lc = c_allLoops;
+ LoopContainer *lc = ld->c_allLoops;
/* first, merge loops with same header node - all loops with the same */
/* header node are optimizied in one pass, because they all depend on the */
fflush(stdout);
#endif
- analyze_double_headers();
+ analyze_double_headers(ld);
/* create array with loop nesting levels - nested loops cause problems, */
/* especially, when they modify index variables used in surrounding loops */
fflush(stdout);
#endif
- analyze_nested(m);
+ analyze_nested(m, ld);
#ifdef LOOP_DEBUG
printf("analyze nested done\n");
#endif
/* create array with entries for current loop */
- c_current_loop = DMNEW(int, m->basicblockcount);
- c_toVisit = DMNEW(int, m->basicblockcount);
- c_var_modified = DMNEW(int, m->maxlocals);
- c_null_check = DMNEW(int, m->maxlocals);
+ ld->c_current_loop = DMNEW(int, m->basicblockcount);
+ ld->c_toVisit = DMNEW(int, m->basicblockcount);
+ ld->c_var_modified = DMNEW(int, m->maxlocals);
+ ld->c_null_check = DMNEW(int, m->maxlocals);
- if ((c_constraints = (struct Constraint **) malloc((m->maxlocals+1) * sizeof(struct Constraint *))) == NULL)
+ if ((ld->c_constraints = (struct Constraint **) malloc((m->maxlocals+1) * sizeof(struct Constraint *))) == NULL)
c_mem_error();
#ifdef STATISTICS
- c_stat_num_loops = 0; /* set statistic vars to zero */
- c_stat_array_accesses = c_stat_sum_accesses = 0;
- c_stat_full_opt = c_stat_sum_full = 0;
- c_stat_no_opt = c_stat_sum_no = 0;
- c_stat_lower_opt = c_stat_sum_lower = 0;
- c_stat_upper_opt = c_stat_sum_upper = 0;
- c_stat_or = c_stat_sum_or = 0;
- c_stat_exception = c_stat_sum_exception = 0;
+ ld->c_stat_num_loops = 0; /* set statistic vars to zero */
+ ld->c_stat_array_accesses = ld->c_stat_sum_accesses = 0;
+ ld->c_stat_full_opt = ld->c_stat_sum_full = 0;
+ ld->c_stat_no_opt = ld->c_stat_sum_no = 0;
+ ld->c_stat_lower_opt = ld->c_stat_sum_lower = 0;
+ ld->c_stat_upper_opt = ld->c_stat_sum_upper = 0;
+ ld->c_stat_or = ld->c_stat_sum_or = 0;
+ ld->c_stat_exception = ld->c_stat_sum_exception = 0;
#endif
/* init vars needed by all loops */
- c_needs_redirection = false;
- c_newstart = NULL;
- c_old_xtablelength = m->exceptiontablelength;
+ ld->c_needs_redirection = false;
+ ld->c_newstart = NULL;
+ ld->c_old_xtablelength = m->exceptiontablelength;
/* loops have been topologically sorted */
- lc = c_allLoops;
+ lc = ld->c_allLoops;
while (lc != NULL) {
- optimize_single_loop(m, lc);
+ optimize_single_loop(m, ld, lc);
#ifdef LOOP_DEBUG
printf(" *** Optimized loop *** \n");
#endif
/* if global BB list start is modified, set block to new start */
- if (c_needs_redirection == true)
- m->basicblocks = c_newstart;
+ if (ld->c_needs_redirection == true)
+ m->basicblocks = ld->c_newstart;
}
Authors: Christian Thalinger
- $Id: analyze.h 1203 2004-06-22 23:14:55Z twisti $
+ $Id: analyze.h 1454 2004-11-05 14:19:32Z twisti $
*/
#ifndef _ANALYZE_H
#define _ANALYZE_H
-
#include "global.h"
+#include "jit/loop/loop.h"
-void optimize_loops(methodinfo *m);
+void optimize_loops(methodinfo *m, loopdata *ld);
#endif /* _ANALYZE_H */
Contains the functions which build a list, that represents the
control flow graph of the procedure, that is being analyzed.
- $Id: graph.c 1203 2004-06-22 23:14:55Z twisti $
+ $Id: graph.c 1454 2004-11-05 14:19:32Z twisti $
*/
depthFirst() builds the control flow graph out of the intermediate code of
the procedure, that is to be optimized and stores the list in the global
variable c_dTable
-*/
-void depthFirst(methodinfo *m)
+*/
+
+void depthFirst(methodinfo *m, loopdata *ld)
{
int i;
/* allocate memory and init gobal variables needed by function dF(m, int, int) */
- c_defnum = DMNEW(int, m->basicblockcount);
- c_numPre = DMNEW(int, m->basicblockcount);
- c_parent = DMNEW(int, m->basicblockcount);
- c_reverse = DMNEW(int, m->basicblockcount);
- c_pre = DMNEW(int *, m->basicblockcount);
- c_dTable = DMNEW(struct depthElement *, m->basicblockcount);
+ ld->c_defnum = DMNEW(int, m->basicblockcount);
+ ld->c_numPre = DMNEW(int, m->basicblockcount);
+ ld->c_parent = DMNEW(int, m->basicblockcount);
+ ld->c_reverse = DMNEW(int, m->basicblockcount);
+ ld->c_pre = DMNEW(int *, m->basicblockcount);
+ ld->c_dTable = DMNEW(struct depthElement *, m->basicblockcount);
for (i = 0; i < m->basicblockcount; ++i) {
- c_defnum[i] = c_parent[i] = -1;
- c_numPre[i] = c_reverse[i] = 0;
+ ld->c_defnum[i] = ld->c_parent[i] = -1;
+ ld->c_numPre[i] = ld->c_reverse[i] = 0;
- c_pre[i] = DMNEW(int, m->basicblockcount);
- c_dTable[i] = NULL;
+ ld->c_pre[i] = DMNEW(int, m->basicblockcount);
+ ld->c_dTable[i] = NULL;
}
- c_globalCount = 0;
- c_allLoops = NULL;
+ ld->c_globalCount = 0;
+ ld->c_allLoops = NULL;
- dF(m, -1, 0); /* call helper function dF that traverses basic block structure */
+ dF(m, ld, -1, 0); /* call helper function dF that traverses basic block structure */
}
control flow graph in a depth-first order, thereby building up the adeacency
list c_dTable
*/
-void dF(methodinfo *m, int from, int blockIndex)
+
+void dF(methodinfo *m, loopdata *ld, int from, int blockIndex)
{
instruction *ip;
s4 *s4ptr;
if (from >= 0) {
/* the current basic block has a predecessor (ie. is not the first one) */
-/* if ((hp = (struct depthElement *) malloc(sizeof(struct depthElement))) == NULL) */
- /* c_mem_error(); */
hp = DNEW(struct depthElement);/* create new depth element */
- hp->next = c_dTable[from]; /* insert values */
+ hp->next = ld->c_dTable[from]; /* insert values */
hp->value = blockIndex;
hp->changes = NULL;
- c_dTable[from] = hp; /* insert into table */
+ ld->c_dTable[from] = hp; /* insert into table */
}
if (from == blockIndex) { /* insert one node loops into loop container */
-/* if ((tmp = (struct LoopContainer *) malloc(sizeof(struct LoopContainer))) == NULL) */
-/* c_mem_error(); */
tmp = DNEW(struct LoopContainer);
LoopContainerInit(m, tmp, blockIndex);
- tmp->next = c_allLoops;
- c_allLoops = tmp;
+ tmp->next = ld->c_allLoops;
+ ld->c_allLoops = tmp;
}
#ifdef C_DEBUG
ip = m->basicblocks[blockIndex].iinstr + m->basicblocks[blockIndex].icount -1;
/* set ip to last instruction */
- if (c_defnum[blockIndex] == -1) { /* current block has not been visited */
- c_defnum[blockIndex] = c_globalCount; /* update global count */
- c_parent[blockIndex] = from; /* write parent block of current one */
- c_reverse[c_globalCount] = blockIndex;
- ++c_globalCount;
+ if (ld->c_defnum[blockIndex] == -1) { /* current block has not been visited */
+ ld->c_defnum[blockIndex] = ld->c_globalCount; /* update global count */
+ ld->c_parent[blockIndex] = from; /* write parent block of current one */
+ ld->c_reverse[ld->c_globalCount] = blockIndex;
+ ++ld->c_globalCount;
if (!m->basicblocks[blockIndex].icount) {
/* block does not contain instructions */
- dF(m, blockIndex, blockIndex+1);
+ dF(m, ld, blockIndex, blockIndex+1);
}
else { /* for all successors, do */
switch (ip->opc) { /* check type of last instruction */
case ICMD_IF_ICMPLE:
case ICMD_IF_ACMPEQ:
case ICMD_IF_ACMPNE: /* branch -> check next block */
- dF(m, blockIndex, blockIndex + 1);
+ dF(m, ld, blockIndex, blockIndex + 1);
/* fall throu */
case ICMD_GOTO:
- dF(m, blockIndex, m->basicblockindex[ip->op1]);
+ dF(m, ld, blockIndex, m->basicblockindex[ip->op1]);
break; /* visit branch (goto) target */
case ICMD_TABLESWITCH: /* switch statement */
s4ptr = ip->val.a;
- dF(m, blockIndex, m->basicblockindex[*s4ptr]); /* default branch */
+ dF(m, ld, blockIndex, m->basicblockindex[*s4ptr]); /* default branch */
s4ptr++;
low = *s4ptr;
while (--count >= 0) {
s4ptr++;
- dF(m, blockIndex, m->basicblockindex[*s4ptr]);
+ dF(m, ld, blockIndex, m->basicblockindex[*s4ptr]);
}
break;
case ICMD_LOOKUPSWITCH: /* switch statement */
s4ptr = ip->val.a;
- dF(m, blockIndex, m->basicblockindex[*s4ptr]); /* default branch */
+ dF(m, ld, blockIndex, m->basicblockindex[*s4ptr]); /* default branch */
++s4ptr;
count = *s4ptr++;
while (--count >= 0) {
- dF(m, blockIndex, m->basicblockindex[s4ptr[1]]);
+ dF(m, ld, blockIndex, m->basicblockindex[s4ptr[1]]);
s4ptr += 2;
}
break;
case ICMD_JSR:
- c_last_jump = blockIndex;
- dF(m, blockIndex, m->basicblockindex[ip->op1]);
+ ld->c_last_jump = blockIndex;
+ dF(m, ld, blockIndex, m->basicblockindex[ip->op1]);
break;
case ICMD_RET:
- dF(m, blockIndex, c_last_jump+1);
+ dF(m, ld, blockIndex, ld->c_last_jump+1);
break;
default:
- dF(m, blockIndex, blockIndex + 1);
+ dF(m, ld, blockIndex, blockIndex + 1);
break;
}
}
}
- for (ptr = c_pre[blockIndex], cnt = 0; cnt < c_numPre[blockIndex]; ++cnt, ++ptr)
+ for (ptr = ld->c_pre[blockIndex], cnt = 0; cnt < ld->c_numPre[blockIndex]; ++cnt, ++ptr)
{
if (*ptr == from)
break;
}
- if (cnt >= c_numPre[blockIndex]) {
- c_pre[blockIndex][c_numPre[blockIndex]] = from;
+ if (cnt >= ld->c_numPre[blockIndex]) {
+ ld->c_pre[blockIndex][ld->c_numPre[blockIndex]] = from;
/* add predeccessors to list c_pre */
- c_numPre[blockIndex]++; /* increase number of predecessors */
- }
+ ld->c_numPre[blockIndex]++; /* increase number of predecessors */
+ }
}
+
/*
- a slightly modified version of dF(m, int, int) that is used to traverse the part
+ a slightly modified version of dF(m, ld, int, int) that is used to traverse the part
of the control graph that is not reached by normal program flow but by the
raising of exceptions (code of catch blocks)
*/
-void dF_Exception(methodinfo *m, int from, int blockIndex)
+
+void dF_Exception(methodinfo *m, loopdata *ld, int from, int blockIndex)
{
instruction *ip;
s4 *s4ptr;
int high, low, count;
struct depthElement *hp;
- if (c_exceptionVisit[blockIndex] < 0) /* has block been visited, return */
- c_exceptionVisit[blockIndex] = 1;
+ if (ld->c_exceptionVisit[blockIndex] < 0) /* has block been visited, return */
+ ld->c_exceptionVisit[blockIndex] = 1;
else
return;
- if (c_dTable[blockIndex] != NULL) /* back to regular code section */
+ if (ld->c_dTable[blockIndex] != NULL) /* back to regular code section */
return;
if (from >= 0) { /* build exception graph (in c_exceptionGraph) */
-/* if ((hp = (struct depthElement *) malloc(sizeof(struct depthElement))) == NULL) */
-/* c_mem_error(); */
hp = DNEW(struct depthElement);
- hp->next = c_exceptionGraph[from];
+ hp->next = ld->c_exceptionGraph[from];
hp->value = blockIndex;
hp->changes = NULL;
- c_exceptionGraph[from] = hp;
+ ld->c_exceptionGraph[from] = hp;
}
#ifdef C_DEBUG
ip = m->basicblocks[blockIndex].iinstr + m->basicblocks[blockIndex].icount -1;
if (!m->basicblocks[blockIndex].icount)
- dF_Exception(m, blockIndex, blockIndex+1);
+ dF_Exception(m, ld, blockIndex, blockIndex+1);
else {
switch (ip->opc) {
case ICMD_RETURN:
case ICMD_IF_ICMPLE:
case ICMD_IF_ACMPEQ:
case ICMD_IF_ACMPNE:
- dF_Exception(m, blockIndex, blockIndex + 1);
+ dF_Exception(m, ld, blockIndex, blockIndex + 1);
/* fall throu */
case ICMD_GOTO:
- dF_Exception(m, blockIndex, m->basicblockindex[ip->op1]);
+ dF_Exception(m, ld, blockIndex, m->basicblockindex[ip->op1]);
break;
case ICMD_TABLESWITCH:
s4ptr = ip->val.a;
/* default branch */
- dF_Exception(m, blockIndex, m->basicblockindex[*s4ptr]);
+ dF_Exception(m, ld, blockIndex, m->basicblockindex[*s4ptr]);
s4ptr++;
low = *s4ptr;
while (--count >= 0) {
s4ptr++;
- dF_Exception(m, blockIndex, m->basicblockindex[*s4ptr]);
+ dF_Exception(m, ld, blockIndex, m->basicblockindex[*s4ptr]);
}
break;
s4ptr = ip->val.a;
/* default branch */
- dF_Exception(m, blockIndex, m->basicblockindex[*s4ptr]);
+ dF_Exception(m, ld, blockIndex, m->basicblockindex[*s4ptr]);
++s4ptr;
count = *s4ptr++;
while (--count >= 0) {
- dF_Exception(m, blockIndex, m->basicblockindex[s4ptr[1]]);
+ dF_Exception(m, ld, blockIndex, m->basicblockindex[s4ptr[1]]);
s4ptr += 2;
}
break;
case ICMD_JSR:
- c_last_jump = blockIndex;
- dF_Exception(m, blockIndex, m->basicblockindex[ip->op1]);
+ ld->c_last_jump = blockIndex;
+ dF_Exception(m, ld, blockIndex, m->basicblockindex[ip->op1]);
break;
case ICMD_RET:
- dF_Exception(m, blockIndex, c_last_jump+1);
+ dF_Exception(m, ld, blockIndex, ld->c_last_jump+1);
break;
default:
- dF_Exception(m, blockIndex, blockIndex + 1);
+ dF_Exception(m, ld, blockIndex, blockIndex + 1);
break;
}
}
/*
Test function -> will be removed in final release
*/
-void resultPass1()
+void resultPass1(methodinfo *m)
{
int i, j;
struct depthElement *hp;
+ struct loopdata *l;
+
+ l=m->loopdata;
printf("\n\n****** PASS 1 ******\n\n");
- printf("Number of Nodes: %d\n\n", c_globalCount);
+ printf("Number of Nodes: %d\n\n", ld->c_globalCount);
printf("Predecessors:\n");
for (i=0; i<m->basicblockcount; ++i) {
printf("Block %d:\t", i);
- for (j=0; j<c_numPre[i]; ++j)
- printf("%d ", c_pre[i][j]);
+ for (j=0; j<ld->c_numPre[i]; ++j)
+ printf("%d ", ld->c_pre[i][j]);
printf("\n");
}
printf("\n");
printf("Graph:\n");
for (i=0; i<m->basicblockcount; ++i) {
printf("Block %d:\t", i);
- hp = c_dTable[i];
+ hp = ld->c_dTable[i];
while (hp != NULL) {
printf("%d ", hp->value);
Authors: Christian Thalinger
- $Id: graph.h 1203 2004-06-22 23:14:55Z twisti $
+ $Id: graph.h 1454 2004-11-05 14:19:32Z twisti $
*/
#include "loop.h"
+
void LoopContainerInit(methodinfo *m, struct LoopContainer *lc, int i);
-void depthFirst(methodinfo *m);
-void dF(methodinfo *m, int from, int blockIndex);
-void dF_Exception(methodinfo *m, int from, int blockIndex);
+void depthFirst(methodinfo *m, loopdata *ld);
+void dF(methodinfo *m, loopdata *ld, int from, int blockIndex);
+void dF_Exception(methodinfo *m, loopdata *ld, int from, int blockIndex);
-void resultPass1();
+void resultPass1(methodinfo *);
#endif /* _GRAPH_H */
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
algorithm that uses dominator trees (found eg. in modern compiler
implementation by a.w. appel)
- $Id: loop.c 1203 2004-06-22 23:14:55Z twisti $
+ $Id: loop.c 1454 2004-11-05 14:19:32Z twisti $
*/
#include "toolbox/logging.h"
#include "toolbox/memory.h"
-/* GLOBAL VARS */
-
-int c_debug_nr; /* a counter to number all BB with an unique */
- /* value */
-
-/* modified by graph.c */
-
-int *c_defnum; /* array that stores a number for each node when*/
- /* control flow graph is traveres depth first */
-int *c_parent; /* for each node that array stores its parent */
-int *c_reverse; /* for each def number that array stores the */
- /* corresponding node */
-int c_globalCount; /* counter for def numbering */
-int *c_numPre; /* array that stores for each node its number */
- /* predecessors */
-int **c_pre; /* array of array that stores predecessors */
-int c_last_jump; /* stores the source node of the last jsr instr */
-struct basicblock *c_last_target; /* stores the source BB of the last jsr instr */
-
-struct depthElement **c_dTable; /* adjacency list for control flow graph */
-struct depthElement **c_exceptionGraph; /* adjacency list for exception graph */
-
-struct LoopContainer *c_allLoops; /* list of all loops */
-struct LoopContainer *c_loop_root; /* root of loop hierarchie tree */
-
-int *c_exceptionVisit; /* array that stores a flag for each node part */
- /* of the exception graph */
-
-/* modified by loop.c */
-
-int *c_semi_dom; /* store for each node its semi dominator */
-int *c_idom; /* store for each node its dominator */
-int *c_same_dom; /* temp array to hold nodes with same dominator */
-int *c_ancestor; /* store for each node its ancestor with lowest */
- /* semi dominator */
-int *c_numBucket;
-int **c_bucket;
-
-int *c_contains; /* store for each node whether it's part of loop*/
-int *c_stack; /* a simple stack as array */
-int c_stackPointer; /* stackpointer */
-
-
-/* modified by analyze.c */
-
-struct LoopContainer *root; /* the root pointer for the hierarchie tree of */
- /* all loops in that procedure */
-
-int c_needed_instr; /* number of instructions that have to be */
- /* inserted before loop header to make sure */
- /* array optimization is legal */
-int c_rs_needed_instr; /* number of instructions needed to load the */
- /* value ofthe right side of the loop condition */
-int *c_nestedLoops; /* store for each node the header node of the */
- /* loop this node belongs to, -1 for none */
-int *c_hierarchie; /* store a loop hierarchie */
-int *c_toVisit; /* set for each node that is part of the loop */
-
-int *c_current_loop; /* for each node: */
- /* store 0: node is not part of loop */
- /* store 1: node is loop header */
- /* store 2: node is in loop but not part of any */
- /* nested loop */
- /* store 3: node is part of nested loop */
-
-int c_current_head; /* store number of node that is header of loop */
-int *c_var_modified; /* store for each local variable whether its */
- /* value is changed in the loop */
-
-struct Trace *c_rightside; /* right side of loop condition */
-struct Constraint **c_constraints;
- /* array that stores for each variable a list */
- /* static tests (constraints) that have to be */
- /* performed before loop entry */
- /* IMPORTANT: c_constraints[maxlocals] stores */
- /* the tests for constants and the */
- /* right side of loop condition */
-
-struct LoopVar *c_loopvars; /* a list of all intersting variables of the */
- /* current loop (variables that are modified or */
- /* used as array index */
-
-struct basicblock *c_first_block_copied; /* pointer to the first block, that is copied */
- /* during loop duplication */
-
-struct basicblock *c_last_block_copied; /* last block, that is copied during loop */
- /* duplication */
-
-int *c_null_check; /* array to store for local vars, whether they */
- /* need to be checked against the null reference*/
- /* in the loop head */
-
-bool c_needs_redirection; /* if a loop header is inserted as first block */
- /* into the global BB list, this is set to true */
-
-struct basicblock *c_newstart; /* if a loop header is inserted as first block */
- /* into the gloal BB list, this pointer is the */
- /* new start */
-int c_old_xtablelength; /* used to store the original tablelength */
-
-/* set debug mode */
-#define C_DEBUG
-
-
-/* declare statistic variables */
-#ifdef STATISTICS
-
-int c_stat_num_loops; /* number of loops */
-
-/* statistics per loop */
-int c_stat_array_accesses; /* number of array accesses */
-
-int c_stat_full_opt; /* number of fully optimized accesses */
-int c_stat_no_opt; /* number of not optimized accesses */
-int c_stat_lower_opt; /* number of accesses where check against zero */
- /* is removed */
-int c_stat_upper_opt; /* number of accesses where check against array */
- /* lengh is removed */
-int c_stat_or; /* set if optimization is cancelled because of */
- /* or in loop condition */
-int c_stat_exception; /* set if optimization is cancelled because of */
- /* index var modified in catch block */
-
-/* statistics per procedure */
-int c_stat_sum_accesses; /* number of array accesses */
-
-int c_stat_sum_full; /* number of fully optimized accesses */
-int c_stat_sum_no; /* number of not optimized accesses */
-int c_stat_sum_lower; /* number of accesses where check against zero */
- /* is removed */
-int c_stat_sum_upper; /* number of accesses where check against array */
- /* lengh is removed */
-int c_stat_sum_or; /* set if optimization is cancelled because of */
- /* or in loop condition */
-int c_stat_sum_exception; /* set if optimization is cancelled because of */
-
-#endif
/*
This function allocates and initializes variables, that are used by the
loop detection algorithm
*/
-void setup(methodinfo *m)
+void setup(methodinfo *m, loopdata *ld)
{
int i;
- c_semi_dom = DMNEW(int, m->basicblockcount);
- c_idom = DMNEW(int, m->basicblockcount);
- c_same_dom = DMNEW(int, m->basicblockcount);
- c_numBucket = DMNEW(int, m->basicblockcount);
- c_ancestor = DMNEW(int, m->basicblockcount);
- c_contains = DMNEW(int, m->basicblockcount);
- c_stack = DMNEW(int, m->basicblockcount);
- c_bucket = DMNEW(int*, m->basicblockcount);
+ ld->c_semi_dom = DMNEW(int, m->basicblockcount);
+ ld->c_idom = DMNEW(int, m->basicblockcount);
+ ld->c_same_dom = DMNEW(int, m->basicblockcount);
+ ld->c_numBucket = DMNEW(int, m->basicblockcount);
+ ld->c_ancestor = DMNEW(int, m->basicblockcount);
+ ld->c_contains = DMNEW(int, m->basicblockcount);
+ ld->c_stack = DMNEW(int, m->basicblockcount);
+ ld->c_bucket = DMNEW(int*, m->basicblockcount);
for (i = 0; i < m->basicblockcount; ++i) {
- c_numBucket[i] = 0;
- c_stack[i] = c_ancestor[i] = c_semi_dom[i] = c_same_dom[i] = c_idom[i] = -1;
+ ld->c_numBucket[i] = 0;
+ ld->c_stack[i] = ld->c_ancestor[i] = ld->c_semi_dom[i] = ld->c_same_dom[i] = ld->c_idom[i] = -1;
- c_bucket[i] = DMNEW(int, m->basicblockcount);
+ ld->c_bucket[i] = DMNEW(int, m->basicblockcount);
}
}
ancestor of the node v in the control graph, which semi-dominator has the
lowest def-num.
*/
-int findLowAnc(int v)
+
+int findLowAnc(loopdata *ld, int v)
{
int u = v; /* u is the node which has the current lowest semi-dom */
- while (c_ancestor[v] != -1) { /* as long as v has an ancestor, continue */
- if (c_defnum[c_semi_dom[v]] < c_defnum[c_semi_dom[u]])
+ while (ld->c_ancestor[v] != -1) { /* as long as v has an ancestor, continue */
+ if (ld->c_defnum[ld->c_semi_dom[v]] < ld->c_defnum[ld->c_semi_dom[u]])
/* if v's semi-dom is smaller */
u = v; /* it gets the new current node u */
- v = c_ancestor[v]; /* climb one step up in the tree */
+ v = ld->c_ancestor[v]; /* climb one step up in the tree */
}
return u; /* return node with the lowest semi-dominator def-num */
}
dominators in c_bucket and eventually determines the single dominator in a
final pass.
*/
-void dominators()
+
+void dominators(loopdata *ld)
{
int i, j, semi, s, n, v, actual, p, y;
- for (n=(c_globalCount-1); n>0; --n) { /* for all nodes (except last), do */
- actual = c_reverse[n];
- semi = p = c_parent[actual];
+ for (n=(ld->c_globalCount-1); n>0; --n) { /* for all nodes (except last), do */
+ actual = ld->c_reverse[n];
+ semi = p = ld->c_parent[actual];
/* for all predecessors of current node, do */
- for (i=0; i<c_numPre[actual]; ++i) {
- v = c_pre[actual][i];
+ for (i=0; i<ld->c_numPre[actual]; ++i) {
+ v = ld->c_pre[actual][i];
- if (c_defnum[v] <= c_defnum[actual])
+ if (ld->c_defnum[v] <= ld->c_defnum[actual])
s = v; /* if predecessor has lower def-num than node */
/* it becomes candidate for semi dominator */
else
- s = c_semi_dom[findLowAnc(v)];
+ s = ld->c_semi_dom[findLowAnc(ld, v)];
/* else the semi-dominator of it's ancestor */
/* with lowest def-num becomes candidate */
- if (c_defnum[s] < c_defnum[semi])
+ if (ld->c_defnum[s] < ld->c_defnum[semi])
semi = s; /* if the def-num of the new candidate is lower */
/* than old one, it gets new semi dominator */
}
/* write semi dominator -> according to SEMIDOMINATOR THEOREM */
- c_semi_dom[actual] = semi;
- c_ancestor[actual] = p;
+ ld->c_semi_dom[actual] = semi;
+ ld->c_ancestor[actual] = p;
- c_bucket[semi][c_numBucket[semi]] = actual;
- c_numBucket[semi]++; /* defer calculation of dominator to final pass */
+ ld->c_bucket[semi][ld->c_numBucket[semi]] = actual;
+ ld->c_numBucket[semi]++; /* defer calculation of dominator to final pass */
/* first clause of DOMINATOR THEOREM, try to find dominator now */
- for (j=0; j<c_numBucket[p]; ++j) {
- v = c_bucket[p][j];
- y = findLowAnc(v);
+ for (j=0; j<ld->c_numBucket[p]; ++j) {
+ v = ld->c_bucket[p][j];
+ y = findLowAnc(ld, v);
- if (c_semi_dom[y] == c_semi_dom[v])
- c_idom[v] = p; /* if y's dominator is already known */
+ if (ld->c_semi_dom[y] == ld->c_semi_dom[v])
+ ld->c_idom[v] = p; /* if y's dominator is already known */
/* found it and write to c_idom */
else
- c_same_dom[v] = y; /* wait till final pass */
+ ld->c_same_dom[v] = y; /* wait till final pass */
}
- c_numBucket[p] = 0;
+ ld->c_numBucket[p] = 0;
}
/* final pass to get missing dominators ->second clause of DOMINATOR THEORM */
- for (j=1; j<(c_globalCount-1); ++j) {
- if (c_same_dom[c_reverse[j]] != -1)
- c_idom[c_reverse[j]] = c_idom[c_same_dom[c_reverse[j]]];
+ for (j=1; j<(ld->c_globalCount-1); ++j) {
+ if (ld->c_same_dom[ld->c_reverse[j]] != -1)
+ ld->c_idom[ld->c_reverse[j]] = ld->c_idom[ld->c_same_dom[ld->c_reverse[j]]];
}
}
connection between two nodes in the control flow graph is possibly part
of a loop (is a backEdge).
*/
-int isBackEdge(int from, int to)
+
+int isBackEdge(loopdata *ld, int from, int to)
{
- int tmp = c_idom[to]; /* speed optimization: if the to-node is dominated */
+ int tmp = ld->c_idom[to]; /* speed optimization: if the to-node is dominated */
while (tmp != -1) { /* by the from node as it is most of the time, */
if (tmp == from) /* there is no backEdge */
return 0;
- tmp = c_idom[tmp];
+ tmp = ld->c_idom[tmp];
}
- tmp = c_idom[from]; /* if from-node doesn't dominate to-node, we have */
+ tmp = ld->c_idom[from]; /* if from-node doesn't dominate to-node, we have */
while (tmp != -1) { /* to climb all the way up from the from-node to */
if (tmp == to) /* the top to check, whether it is dominated by to */
return 1; /* if so, return a backedge */
- tmp = c_idom[tmp];
+ tmp = ld->c_idom[tmp];
}
return 0; /* else, there is no backedge */
These stack functions are helper functions for createLoop(int, int)
to manage the set of nodes in the current loop.
*/
-void push(methodinfo *m, int i, struct LoopContainer *lc)
+
+void push(methodinfo *m, loopdata *ld, int i, struct LoopContainer *lc)
{
struct LoopElement *le = lc->nodes, *t;
- if (!c_contains[i]) {
+ if (!ld->c_contains[i]) {
t = DMNEW(struct LoopElement, 1);
t->node = i;
t->block = &m->basicblocks[i];
- c_contains[i] = 1;
+ ld->c_contains[i] = 1;
if (i < le->node)
{
le->next = t;
}
- c_stack[c_stackPointer++] = i;
+ ld->c_stack[ld->c_stackPointer++] = i;
}
}
-int pop()
+int pop(loopdata *ld)
{
- return (c_stack[--c_stackPointer]);
+ return (ld->c_stack[--ld->c_stackPointer]);
}
-int isFull()
+int isFull(loopdata *ld)
{
- return (c_stackPointer);
+ return (ld->c_stackPointer);
}
the loop with a known header node and a member node of the loop (and a
back edge between these two nodes).
*/
-void createLoop(methodinfo *m, int header, int member)
+
+void createLoop(methodinfo *m, loopdata *ld, int header, int member)
{
int i, nextMember;
LoopContainerInit(m, currentLoop, header); /* set up loop structure */
for (i=0; i<m->basicblockcount; ++i)
- c_contains[i] = 0;
- c_contains[header] = 1;
+ ld->c_contains[i] = 0;
+ ld->c_contains[header] = 1;
- c_stackPointer = 0; /* init stack with first node of the loop */
- push(m, member, currentLoop);
+ ld->c_stackPointer = 0; /* init stack with first node of the loop */
+ push(m, ld, member, currentLoop);
- while (isFull()) { /* while there are still unvisited nodes */
- nextMember = pop();
+ while (isFull(ld)) { /* while there are still unvisited nodes */
+ nextMember = pop(ld);
/* push all predecessors, while they are not equal to loop header */
- for (i=0; i<c_numPre[nextMember]; ++i)
- push(m, c_pre[nextMember][i], currentLoop);
+ for (i=0; i<ld->c_numPre[nextMember]; ++i)
+ push(m, ld, ld->c_pre[nextMember][i], currentLoop);
}
- currentLoop->next = c_allLoops;
- c_allLoops = currentLoop;
+ currentLoop->next = ld->c_allLoops;
+ ld->c_allLoops = currentLoop;
}
/* After all dominators have been calculated, the loops can be detected and
added to the global list c_allLoops.
*/
-void detectLoops(methodinfo *m)
+
+void detectLoops(methodinfo *m, loopdata *ld)
{
int i;
struct depthElement *h;
-
+
/* for all edges in the control flow graph do */
for (i=0; i<m->basicblockcount; ++i) {
- h = c_dTable[i];
+ h = ld->c_dTable[i];
while (h != NULL) {
/* if it's a backedge, than add a new loop to list */
- if (isBackEdge(i, h->value))
- createLoop(m, h->value, i);
+ if (isBackEdge(ld, i, h->value))
+ createLoop(m, ld, h->value, i);
h = h->next;
}
}
This function is called by higher level routines to perform the loop
detection and set up the c_allLoops list.
*/
-void analyseGraph(methodinfo *m)
+
+void analyseGraph(methodinfo *m, loopdata *ld)
{
- setup(m);
- dominators();
- detectLoops(m);
+ setup(m, ld);
+ dominators(ld);
+ detectLoops(m, ld);
}
/*
Test function -> will be removed in final release
*/
-void resultPass2()
+
+void resultPass2(loopdata *ld)
{
int i;
- struct LoopContainer *lc = c_allLoops;
+ struct LoopContainer *lc = ld->c_allLoops;
struct LoopElement *le;
printf("\n\n****** PASS 2 ******\n\n");
Authors: Christopher Kruegel
- $Id: loop.h 1203 2004-06-22 23:14:55Z twisti $
+ $Id: loop.h 1454 2004-11-05 14:19:32Z twisti $
*/
#define _LOOP_H
#include "global.h"
+#include "jit/jit.h"
+
/* Different types for struct Trace */
#define TRACE_UNKNOWN 0 /* unknown */
#define HANDLER_VISITED 0x4 /* flag to prevent loop if copying catch blocks */
+typedef struct LoopElement LoopElement;
+typedef struct LoopContainer LoopContainer;
+typedef struct loopdata loopdata;
+
/* This struct records information about interesting vars (vars that are modified
or used as an array index in loops.
};
-/* Used to build a list of all basicblock, the loop consists of
-*/
+/* Used to build a list of all basicblock, the loop consists of */
+
struct LoopElement {
- int node;
- struct basicblock *block;
- struct LoopElement *next;
+ s4 node;
+ basicblock *block;
+ LoopElement *next;
};
This structure stores informations about a single loop
*/
struct LoopContainer {
- int toOpt; /* does this loop need optimization */
- struct LoopElement *nodes; /* list of BBs this loop consists of */
- int loop_head;
- int in_degree; /* needed to topological sort loops to */
- /* get the order of optimizing them */
- struct LoopContainer *next; /* list pointer */
- struct LoopContainer *parent; /* points to parent loop, if this BB */
- /* is head of a loop */
- struct LoopContainer *tree_right; /* used for tree hierarchie of loops */
- struct LoopContainer *tree_down;
- exceptiontable *exceptions; /* list of exception in that loop */
+ s4 toOpt; /* does this loop need optimization */
+ LoopElement *nodes; /* list of BBs this loop consists of */
+ s4 loop_head;
+ s4 in_degree; /* needed to topological sort loops to*/
+ /* get the order of optimizing them */
+ LoopContainer *next; /* list pointer */
+ LoopContainer *parent; /* points to parent loop, if this BB */
+ /* is head of a loop */
+ LoopContainer *tree_right; /* used for tree hierarchie of loops */
+ LoopContainer *tree_down;
+ exceptiontable *exceptions; /* list of exception in that loop */
};
-/* global variables */
-extern int c_debug_nr;
-extern int *c_defnum;
-extern int *c_parent;
-extern int *c_reverse;
-extern int c_globalCount;
-extern int *c_numPre;
-extern int **c_pre;
-extern int c_last_jump;
-extern struct basicblock *c_last_target;
-extern struct depthElement **c_dTable;
-extern struct depthElement **c_exceptionGraph;
-extern struct LoopContainer *c_allLoops;
-extern struct LoopContainer *c_loop_root;
-extern int *c_exceptionVisit;
-
-
-/* global loop variables */
-extern int *c_semi_dom;
-extern int *c_idom;
-extern int *c_same_dom;
-extern int *c_ancestor;
-extern int *c_numBucket;
-extern int **c_bucket;
-extern int *c_contains;
-extern int *c_stack;
-extern int c_stackPointer;
-
-
-/* global analyze variables */
-extern struct LoopContainer *root;
-extern int c_needed_instr;
-extern int c_rs_needed_instr;
-extern int *c_nestedLoops;
-extern int *c_hierarchie;
-extern int *c_toVisit;
-extern int *c_current_loop;
-extern int c_current_head;
-extern int *c_var_modified;
-extern struct Trace *c_rightside;
-extern struct Constraint **c_constraints;
-extern struct LoopVar *c_loopvars;
-extern struct basicblock *c_first_block_copied;
-extern struct basicblock *c_last_block_copied;
-extern int *c_null_check;
-extern bool c_needs_redirection;
-extern struct basicblock *c_newstart;
-extern int c_old_xtablelength;
-
-
-/* global statistic variables */
+struct loopdata {
+ /* modified by graph.c */
+
+ int *c_defnum; /* array that stores a number for each node when*/
+ /* control flow graph is traveres depth first */
+ int *c_parent; /* for each node that array stores its parent */
+ int *c_reverse; /* for each def number that array stores the */
+ /* corresponding node */
+ int c_globalCount; /* counter for def numbering */
+ int *c_numPre; /* array that stores for each node its number */
+ /* predecessors */
+ int **c_pre; /* array of array that stores predecessors */
+ int c_last_jump; /* stores the source node of the last jsr instr */
+ struct basicblock *c_last_target; /* stores the source BB of the last jsr instr */
+
+ struct depthElement **c_dTable; /* adjacency list for control flow graph */
+ struct depthElement **c_exceptionGraph; /* adjacency list for exception graph */
+
+ struct LoopContainer *c_allLoops; /* list of all loops */
+ struct LoopContainer *c_loop_root; /* root of loop hierarchie tree */
+
+ int *c_exceptionVisit; /* array that stores a flag for each node part */
+ /* of the exception graph */
+
+ /* modified by loop.c */
+
+ int *c_semi_dom; /* store for each node its semi dominator */
+ int *c_idom; /* store for each node its dominator */
+ int *c_same_dom; /* temp array to hold nodes with same dominator */
+ int *c_ancestor; /* store for each node its ancestor with lowest */
+ /* semi dominator */
+ int *c_numBucket;
+ int **c_bucket;
+
+ int *c_contains; /* store for each node whether it's part of loop*/
+ int *c_stack; /* a simple stack as array */
+ int c_stackPointer; /* stackpointer */
+
+
+ /* modified by analyze.c */
+
+ struct LoopContainer *root; /* the root pointer for the hierarchie tree of */
+ /* all loops in that procedure */
+
+ int c_needed_instr; /* number of instructions that have to be */
+ /* inserted before loop header to make sure */
+ /* array optimization is legal */
+ int c_rs_needed_instr; /* number of instructions needed to load the */
+ /* value ofthe right side of the loop condition */
+ int *c_nestedLoops; /* store for each node the header node of the */
+ /* loop this node belongs to, -1 for none */
+ int *c_hierarchie; /* store a loop hierarchie */
+ int *c_toVisit; /* set for each node that is part of the loop */
+
+ int *c_current_loop; /* for each node: */
+ /* store 0: node is not part of loop */
+ /* store 1: node is loop header */
+ /* store 2: node is in loop but not part of any */
+ /* nested loop */
+ /* store 3: node is part of nested loop */
+
+ int c_current_head; /* store number of node that is header of loop */
+ int *c_var_modified; /* store for each local variable whether its */
+ /* value is changed in the loop */
+
+ struct Trace *c_rightside; /* right side of loop condition */
+ struct Constraint **c_constraints;
+ /* array that stores for each variable a list */
+ /* static tests (constraints) that have to be */
+ /* performed before loop entry */
+ /* IMPORTANT: c_constraints[maxlocals] stores */
+ /* the tests for constants and the */
+ /* right side of loop condition */
+
+ struct LoopVar *c_loopvars; /* a list of all intersting variables of the */
+ /* current loop (variables that are modified or */
+ /* used as array index */
+
+ struct basicblock *c_first_block_copied; /* pointer to the first block, that is copied */
+ /* during loop duplication */
+
+ struct basicblock *c_last_block_copied; /* last block, that is copied during loop */
+ /* duplication */
+
+ int *c_null_check; /* array to store for local vars, whether they */
+ /* need to be checked against the null reference*/
+ /* in the loop head */
+
+ bool c_needs_redirection; /* if a loop header is inserted as first block */
+ /* into the global BB list, this is set to true */
+
+ struct basicblock *c_newstart; /* if a loop header is inserted as first block */
+ /* into the gloal BB list, this pointer is the */
+ /* new start */
+ int c_old_xtablelength; /* used to store the original tablelength */
+
+ /* set debug mode */
+#define C_DEBUG
+
+
+ /* declare statistic variables */
#ifdef STATISTICS
-extern int c_stat_num_loops;
-extern int c_stat_array_accesses;
-extern int c_stat_full_opt;
-extern int c_stat_no_opt;
-extern int c_stat_lower_opt;
-extern int c_stat_upper_opt;
-extern int c_stat_or;
-extern int c_stat_exception;
-extern int c_stat_sum_accesses;
-extern int c_stat_sum_full;
-extern int c_stat_sum_no;
-extern int c_stat_sum_lower;
-extern int c_stat_sum_upper;
-extern int c_stat_sum_or;
-extern int c_stat_sum_exception;
+ int c_stat_num_loops; /* number of loops */
+
+ /* statistics per loop */
+ int c_stat_array_accesses; /* number of array accesses */
+
+ int c_stat_full_opt; /* number of fully optimized accesses */
+ int c_stat_no_opt; /* number of not optimized accesses */
+ int c_stat_lower_opt; /* number of accesses where check against zero */
+ /* is removed */
+ int c_stat_upper_opt; /* number of accesses where check against array */
+ /* lengh is removed */
+ int c_stat_or; /* set if optimization is cancelled because of */
+ /* or in loop condition */
+ int c_stat_exception; /* set if optimization is cancelled because of */
+ /* index var modified in catch block */
+
+ /* statistics per procedure */
+ int c_stat_sum_accesses; /* number of array accesses */
+
+ int c_stat_sum_full; /* number of fully optimized accesses */
+ int c_stat_sum_no; /* number of not optimized accesses */
+ int c_stat_sum_lower; /* number of accesses where check against zero */
+ /* is removed */
+ int c_stat_sum_upper; /* number of accesses where check against array */
+ /* lengh is removed */
+ int c_stat_sum_or; /* set if optimization is cancelled because of */
+ /* or in loop condition */
+ int c_stat_sum_exception; /* set if optimization is cancelled because of */
#endif
+};
/* function prototypes */
-void analyseGraph(methodinfo *m);
+
+void analyseGraph(methodinfo *m, loopdata *ld);
void c_mem_error();
#endif /* _LOOP_H */
* tab-width: 4
* End:
*/
-
instruction. For more details see function tracing(basicblock, int,
int) below.
- $Id: tracing.c 1274 2004-07-05 17:24:40Z twisti $
+ $Id: tracing.c 1454 2004-11-05 14:19:32Z twisti $
*/
/* A function that creates a new trace structure and initializes its values
*/
-struct Trace* create_trace(int type, int var, int constant, int nr)
+Trace* create_trace(int type, int var, int constant, int nr)
{
- struct Trace *t;
-/* if ((t = (struct Trace *) malloc(sizeof(struct Trace))) == NULL) */
-/* c_mem_error(); */
- t = DNEW(struct Trace);
+ Trace *t;
+
+ t = DNEW(Trace);
t->type = type;
backward scan over the instructions, it trys to identify the source of the
arguments of this add function. The following function performs this task.
*/
-struct Trace* add(struct Trace* a, struct Trace* b)
+Trace* add(Trace* a, Trace* b)
{
switch (a->type) { /* check the first argument of add. when it */
case TRACE_UNKNOWN: /* is unknown or array-address, return unknown */
backward scan over the instructions, it trys to identify the source of the
argument of this neg function. The following function performs this task.
*/
-struct Trace* negate(struct Trace* a)
+Trace* negate(Trace* a)
{
switch (a->type) { /* check argument type */
case TRACE_IVAR: /* when it is variable/array length value */
this sub function. The following function performs this task, by applaying the
negate function on the second argument and then adds the values.
*/
-struct Trace* sub(struct Trace* a, struct Trace* b)
+Trace* sub(Trace* a, Trace* b)
{
- struct Trace *c = negate(b);
+ Trace *c = negate(b);
return add(a, c);
}
the argument ofthis array length function. The following function performs
this task.
*/
-struct Trace* array_length(struct Trace* a)
+Trace* array_length(Trace* a)
{
if (a->type == TRACE_AVAR) /* if argument is an array ref., mark the type */
a->type = TRACE_ALENGTH; /* as array length of this array reference */
}
-/* This function is used to identify the types of operands of an intermediate
- code instruction.It is needed by functions, that analyze array accesses. If
- something is stored into or loaded from an array, we have to find out, which
- array really has been accessed. When a compare instruction is encountered at
- a loop header, the type of its operands have to be detected to construct
- dynamic bounds for some variables in the loop. This function returns a struct
- Trace (see loop.h for more details about this structure). block is the basic
- block to be examined, index holds the offset of the examined instruction in
- this block. The arguments are retrieved by using the stack structure, the
- compilation process sets up. During the backwards scan of the code, it is
- possible, that other instructions temporaray put or get values from the stack
- and hide the value, we are interested in below them. The value temp counts
- the number of values on the stack, the are located beyond the target value.
-*/
-struct Trace* tracing(basicblock *block, int index, int temp)
+/* tracing *********************************************************************
+
+ This function is used to identify the types of operands of an intermediate
+ code instruction. It is needed by functions, that analyze array accesses. If
+ something is stored into or loaded from an array, we have to find out,
+ which array really has been accessed. When a compare instruction is
+ encountered at a loop header, the type of its operands have to be detected
+ to construct dynamic bounds for some variables in the loop. This function
+ returns a struct Trace (see loop.h for more details about this structure).
+ block is the basic block to be examined, index holds the offset of the
+ examined instruction in this block. The arguments are retrieved by using
+ the stack structure, the compilation process sets up. During the backwards
+ scan of the code, it is possible, that other instructions temporary put or
+ get values from the stack and hide the value, we are interested in below
+ them. The value temp counts the number of values on the stack, the are
+ located beyond the target value.
+
+*******************************************************************************/
+
+Trace* tracing(basicblock *block, int index, int temp)
{
int args, retval;
instruction *ip;
Authors: Christian Thalinger
- $Id: tracing.h 1141 2004-06-05 23:19:24Z twisti $
+ $Id: tracing.h 1454 2004-11-05 14:19:32Z twisti $
*/
#ifndef _TRACING_H
#define _TRACING_H
+
#include "jit/jit.h"
+
+typedef struct Trace Trace;
+
+
/*
This struct is needed to record the source of operands of intermediate code
instructions. The instructions are scanned backwards and the stack is
};
-
/* function protoypes */
-struct Trace* create_trace(int type, int var, int constant, int nr);
-struct Trace* add(struct Trace* a, struct Trace* b);
-struct Trace* negate(struct Trace* a);
-struct Trace* sub(struct Trace* a, struct Trace* b);
-struct Trace* array_length(struct Trace* a);
-struct Trace* tracing(struct basicblock *block, int index, int temp);
+
+Trace* create_trace(int type, int var, int constant, int nr);
+Trace* add(Trace* a, Trace* b);
+Trace* negate(Trace* a);
+Trace* sub(Trace* a, Trace* b);
+Trace* array_length(Trace* a);
+Trace* tracing(basicblock *block, int index, int temp);
#endif /* _TRACING_H */