From f40f3f6c7de0cee0e8f77b0b05e3db7e8b23888a Mon Sep 17 00:00:00 2001 From: Peter Molnar Date: Wed, 19 Mar 2008 13:04:30 +0100 Subject: [PATCH] * src/vm/jit/cfg.c (cfg_build): Support for strange basicblocks, where an IF can be followed by a NOP and GOTO. * 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. --- src/vm/jit/cfg.c | 120 +++++++++++++++++++++++++++++------ src/vm/jit/jit.c | 2 +- src/vm/jit/optimizing/ssa3.c | 42 ++++++++++-- src/vm/jit/stack.c | 3 + 4 files changed, 140 insertions(+), 27 deletions(-) diff --git a/src/vm/jit/cfg.c b/src/vm/jit/cfg.c index 5abebaddf..55832e8d3 100644 --- a/src/vm/jit/cfg.c +++ b/src/vm/jit/cfg.c @@ -134,6 +134,7 @@ bool cfg_build(jitdata *jd) branch_target_t *table; lookup_target_t *lookup; int i; + bool has_fallthrough; /* process all basic blocks to find the predecessor/successor counts */ @@ -153,6 +154,43 @@ bool cfg_build(jitdata *jd) 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: @@ -163,10 +201,12 @@ bool cfg_build(jitdata *jd) 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: @@ -224,14 +264,16 @@ bool cfg_build(jitdata *jd) 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; } } @@ -255,6 +297,36 @@ bool cfg_build(jitdata *jd) 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: @@ -268,13 +340,19 @@ bool cfg_build(jitdata *jd) 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: @@ -349,20 +427,22 @@ goto_tail: 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; } diff --git a/src/vm/jit/jit.c b/src/vm/jit/jit.c index c1b348950..2c0905e03 100644 --- a/src/vm/jit/jit.c +++ b/src/vm/jit/jit.c @@ -764,7 +764,7 @@ static u1 *jit_compile_intern(jitdata *jd) # 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); diff --git a/src/vm/jit/optimizing/ssa3.c b/src/vm/jit/optimizing/ssa3.c index 55379d2ce..775750301 100644 --- a/src/vm/jit/optimizing/ssa3.c +++ b/src/vm/jit/optimizing/ssa3.c @@ -29,10 +29,11 @@ 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" @@ -42,9 +43,15 @@ #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 /* @@ -772,7 +779,7 @@ static void ssa_create_phi_moves(ssa_info *ssa) { 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; @@ -802,6 +809,7 @@ static basicblock *split_basicblock_at(ssa_info *ssa, basicblock *bptr, instruct if (! bptr->subbasicblocks) { bptr->subbasicblocks = DNEW(basicblock); ass(bptr->subbasicblocks, bptr); + bptr->subbasicblocks->subbasicblocks = NULL; bptr->subbasicblocks->next = NULL; } @@ -837,6 +845,11 @@ static basicblock *split_basicblock_at(ssa_info *ssa, basicblock *bptr, instruct 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; } @@ -852,7 +865,8 @@ static exception_entry *create_exception_handler(ssa_info *ssa, basicblock *from /* 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; @@ -896,7 +910,9 @@ static void ssa_create_ex_phi_moves(ssa_info *ssa) { 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; @@ -912,6 +928,9 @@ static void ssa_create_ex_phi_moves(ssa_info *ssa) { } } } + /* XXX + <-------------------> + <---><--><--->missing */ if (firstee) { lastee->next = ite->next; lastee->down = ite->down; @@ -940,6 +959,8 @@ void yssa(jitdata *jd) { 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"); @@ -980,6 +1001,8 @@ void yssa(jitdata *jd) { printf("=============== [ after ] =========================\n"); show_method(jd, 3); printf("=============== [ /after ] =========================\n"); + + do_verbose = 0; } void eliminate_subbasicblocks(jitdata *jd) { @@ -990,15 +1013,22 @@ 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; } /* diff --git a/src/vm/jit/stack.c b/src/vm/jit/stack.c index 3825a0821..e0343e11d 100644 --- a/src/vm/jit/stack.c +++ b/src/vm/jit/stack.c @@ -1233,6 +1233,9 @@ static bool stack_reach_next_block(stackdata_t *sd) 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 */ -- 2.25.1