* src/vm/jit/jit.c (jit_compile_intern) [ENABLE_SSA]: Adapted for changes.
* src/vm/jit/optimizing/ssa3.c: Changed a lot.
* src/vm/jit/stack.c (stack_reach_next_block) [STACK_VERBOSE]: More verbosity to identify basicblocks where an IF can be followed by a GOTO.
branch_target_t *table;
lookup_target_t *lookup;
int i;
+ bool has_fallthrough;
/* process all basic blocks to find the predecessor/successor counts */
iptr--;
}
+ if (iptr->opc == ICMD_GOTO) {
+
+ /*
+ This is needed for the following special case caused by
+ stack_reach_next_block:
+ I.e. there might be instructions causing control flow before
+ a GOTO:
+
+ ....
+ 129: 192: IFEQ Ti102 0 (0x00000000) --> L052
+ 131: 193: NOP
+ 0: 0: GOTO --> L060
+ */
+
+ bptr->successorcount++;
+
+ tbptr = iptr->dst.block;
+ tbptr->predecessorcount++;
+
+ if (iptr == bptr->iinstr) {
+ continue;
+ }
+
+ iptr--;
+
+ while (iptr->opc == ICMD_NOP) {
+ if (iptr == bptr->iinstr) {
+ break;
+ }
+ iptr--;
+ }
+
+ has_fallthrough = false;
+ } else {
+ has_fallthrough = true;
+ }
+
switch (icmd_table[iptr->opc].controlflow) {
case CF_END:
bptr->successorcount += 2;
tbptr = iptr->dst.block;
- ntbptr = bptr->next;
-
tbptr->predecessorcount++;
- ntbptr->predecessorcount++;
+
+ if (has_fallthrough) {
+ ntbptr = bptr->next;
+ ntbptr->predecessorcount++;
+ }
break;
case CF_JSR:
break;
default:
- bptr->successorcount++;
+ if (has_fallthrough) {
+ bptr->successorcount++;
- tbptr = bptr->next;
+ tbptr = bptr->next;
- /* An exception handler has no predecessors. */
+ /* An exception handler has no predecessors. */
- if (tbptr->type != BBTYPE_EXH)
- tbptr->predecessorcount++;
+ if (tbptr->type != BBTYPE_EXH)
+ tbptr->predecessorcount++;
+ }
break;
}
}
iptr--;
}
+ if (iptr->opc == ICMD_GOTO) {
+ tbptr = iptr->dst.block;
+
+ cfg_allocate_successors(bptr);
+
+ cfg_insert_successors(bptr, tbptr);
+
+ cfg_allocate_predecessors(tbptr);
+
+ cfg_insert_predecessors(tbptr, bptr);
+
+ if (iptr == bptr->iinstr) {
+ continue;
+ }
+
+ iptr--;
+
+ while (iptr->opc == ICMD_NOP) {
+ if (iptr == bptr->iinstr) {
+ break;
+ }
+ iptr--;
+ }
+
+ has_fallthrough = false;
+
+ } else {
+ has_fallthrough = true;
+ }
+
switch (icmd_table[iptr->opc].controlflow) {
case CF_END:
cfg_allocate_successors(bptr);
cfg_insert_successors(bptr, tbptr);
- cfg_insert_successors(bptr, ntbptr);
+ if (has_fallthrough) {
+ cfg_insert_successors(bptr, ntbptr);
+ }
cfg_allocate_predecessors(tbptr);
- cfg_allocate_predecessors(ntbptr);
+ if (has_fallthrough) {
+ cfg_allocate_predecessors(ntbptr);
+ }
cfg_insert_predecessors(tbptr, bptr);
- cfg_insert_predecessors(ntbptr, bptr);
+ if (has_fallthrough) {
+ cfg_insert_predecessors(ntbptr, bptr);
+ }
break;
case CF_JSR:
break;
default:
- tbptr = bptr->next;
+ if (has_fallthrough) {
+ tbptr = bptr->next;
- cfg_allocate_successors(bptr);
+ cfg_allocate_successors(bptr);
- bptr->successors[0] = tbptr;
- bptr->successorcount++;
+ bptr->successors[0] = tbptr;
+ bptr->successorcount++;
- /* An exception handler has no predecessors. */
+ /* An exception handler has no predecessors. */
- if (tbptr->type != BBTYPE_EXH) {
- cfg_allocate_predecessors(tbptr);
+ if (tbptr->type != BBTYPE_EXH) {
+ cfg_allocate_predecessors(tbptr);
- tbptr->predecessors[tbptr->predecessorcount] = bptr;
- tbptr->predecessorcount++;
+ tbptr->predecessors[tbptr->predecessorcount] = bptr;
+ tbptr->predecessorcount++;
+ }
}
break;
}
# endif /* defined(ENABLE_LSRA) && !defined(ENABLE_SSA) */
#if defined(ENABLE_SSA)
/* allocate registers */
- if ((opt_lsra) /*&& strcmp(jd->m->name->text, "findClass") != 0*/) {
+ if ((opt_lsra) /*&& (strcmp(jd->m->name->text, "findClass") == 0 || jd->exceptiontablelength == 0)*/) {
jd->ls = DNEW(lsradata);
jd->ls = NULL;
ssa(jd);
TODO
- * Adapt for exception handling
+ * Adapt for exception handling [done]
* Eliminiation of redundand PHI functions
* Create PHI functions lazyly, when they are used for the first time
(I suspect that currently PHIs are created that are never used).
+ * REWRITE. The code was never designed for producion.
*/
#include "vm/jit/jit.h"
#include "toolbox/list.h"
#if 1
-#define printf(...) do { if (getenv("VERB")) printf(__VA_ARGS__); } while (0)
-#define show_method(...) do { if (getenv("VERB")) show_method(__VA_ARGS__); } while (0)
-#define show_basicblock(...) do { if (getenv("VERB")) show_basicblock(__VA_ARGS__); } while (0)
+static inline bool test_do_verbose(jitdata *jd) {
+ return strcmp(jd->m->name->text, "close") == 0 &&
+ strcmp(jd->m->class->name->text, "antlr/PreservingFileWriter") == 0;
+}
+static bool do_verbose = 0;
+#define WHEN do_verbose
+#define printf(...) do { if (WHEN) printf(__VA_ARGS__); } while (0)
+#define show_method(...) do { if (WHEN) show_method(__VA_ARGS__); } while (0)
+#define show_basicblock(...) do { if (WHEN) show_basicblock(__VA_ARGS__); } while (0)
#endif
/*
iptr->sx.s23.s3.jsrtarget.block = create_block(ssa, bptr, iptr->sx.s23.s3.jsrtarget.block);
break;
}
- if ((iptr->opc == ICMD_GOTO) || (iptr->opc == ICMD_JSR) || (iptr->opc == ICMD_RET) || icmd_table[iptr->opc].controlflow == CF_END)
+ if ((iptr->opc == ICMD_GOTO) || (iptr->opc == ICMD_JSR) || (iptr->opc == ICMD_RET) || icmd_table[iptr->opc].controlflow == CF_END || (iptr->opc == ICMD_TABLESWITCH) || (iptr->opc == ICMD_LOOKUPSWITCH))
gt = true;
else if (iptr->opc != ICMD_NOP)
gt = false;
if (! bptr->subbasicblocks) {
bptr->subbasicblocks = DNEW(basicblock);
ass(bptr->subbasicblocks, bptr);
+ bptr->subbasicblocks->subbasicblocks = NULL;
bptr->subbasicblocks->next = NULL;
}
printf("xx split\n");
}
+ /* To not break references to block bptr, we will replace
+ the block by the first fragment later. */
+
+ if (tosplit == bptr->subbasicblocks) tosplit = bptr;
+
return tosplit;
}
/* assigned in caller */
ee->start = from;
- ee->end = from->next;
+ /* XXX evil hack: if from is first fragment of BB, then from->next is not the next fragment */
+ ee->end = from->subbasicblocks ? from->subbasicblocks->next : from->next;
ee->handler = exh;
ee->catchtype = catchtype;
ee->next = NULL;
pei = 0;
FOR_EACH_INSTRUCTION(ittry, iptr) {
if (icmd_table[iptr->opc].flags & ICMDTABLE_PEI) {
+ /* try is basicblock fragment till (including) the pei */
try = split_basicblock_at(ssa, ittry, iptr);
+ /* ee is handler for try */
ee = create_exception_handler(ssa, try, pei, bptr, catchtype);
ee->handler->invars[0] = ssa->jd->vartop + exhandler_count;
exhandler_count += 1;
}
}
}
+ /* XXX
+ <------------------->
+ <---><--><--->missing */
if (firstee) {
lastee->next = ite->next;
lastee->down = ite->down;
if (jd->localcount == 0) return;
+ if (test_do_verbose(jd)) do_verbose = 1;
+
printf("=============== [ before %s ] =========================\n", jd->m->name->text);
show_method(jd, 3);
printf("=============== [ /before ] =========================\n");
printf("=============== [ after ] =========================\n");
show_method(jd, 3);
printf("=============== [ /after ] =========================\n");
+
+ do_verbose = 0;
}
void eliminate_subbasicblocks(jitdata *jd) {
next = bptr->next;
*bptr = *(bptr->subbasicblocks);
bptr->subbasicblocks = NULL;
+
+ /* *prev = bptr->subbasicblocks;
+ bptr = bptr->subbasicblocks; */
+
while (bptr->next) {
bptr = bptr->next;
}
bptr->next = next;
}
}
+
+ if (test_do_verbose(jd)) do_verbose = 1;
printf("=============== [ elim ] =========================\n");
show_method(jd, 3);
printf("=============== [ /elim ] =========================\n");
+ do_verbose = 0;
}
/*
assert(iptr->opc == ICMD_NOP);
iptr->opc = ICMD_GOTO;
iptr->dst.block = tbptr;
+#if defined(STACK_VERBOSE)
+ if (iptr->line == 0) printf("goto with line 0 in L%03d\n", sd->bptr->nr);
+#endif
if (tbptr->flags < BBFINISHED)
sd->repeat = true; /* XXX check if we really need to repeat */