* src/vm/jit/cfg.c (cfg_build): Support for strange basicblocks, where an IF can...
authorPeter Molnar <pm@complang.tuwien.ac.at>
Wed, 19 Mar 2008 12:04:30 +0000 (13:04 +0100)
committerPeter Molnar <pm@complang.tuwien.ac.at>
Wed, 19 Mar 2008 12:04:30 +0000 (13:04 +0100)
* 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
src/vm/jit/jit.c
src/vm/jit/optimizing/ssa3.c
src/vm/jit/stack.c

index 5abebaddf91aa9c9d80f022d22818f25f0e01632..55832e8d3f9ed2fe5f5ff4efbd1d9465e7417d7a 100644 (file)
@@ -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;
                }
index c1b348950f12607f9b69c490f443b46a0bc18c4c..2c0905e03a7cffc70b264ee3b1a6b4eeea227fa3 100644 (file)
@@ -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);
index 55379d2ce16c0d0e1e969dcdce64dd49ac09c028..775750301f15f8a61fddcb71c9d63081ebed1dfd 100644 (file)
 
    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
 
 /*
@@ -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;
 }
 
 /*
index 3825a0821bda23584e1d5339c4e6856ef0acfa8f..e0343e11d80e8306b6b227a070d7629a65d4dd46 100644 (file)
@@ -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 */