Merging 7888.
authorPeter Molnar <pm@complang.tuwien.ac.at>
Thu, 28 Feb 2008 09:26:32 +0000 (10:26 +0100)
committerPeter Molnar <pm@complang.tuwien.ac.at>
Thu, 28 Feb 2008 09:26:32 +0000 (10:26 +0100)
src/vm/jit/cfg.c
src/vm/jit/jit.c
src/vm/jit/jit.h
src/vm/jit/optimizing/ssa.c
src/vm/jit/optimizing/ssa3.c
src/vm/jit/s390/asmpart.S
src/vm/jit/s390/md.c

index 2df6dd7baa6be195a94fdb75c038ce4e49744156..dcd0ed98632c68ed429c17007d77f74f66c9b6ef 100644 (file)
@@ -413,6 +413,82 @@ void cfg_add_root(jitdata *jd) {
        }
 }
 
+/* cfg_add_exceptional_edges ***************************************************
+   Edges from basicblocks to their exception handlers and from exception 
+   handlers to the blocks they handle exceptions for are added. Further
+   the number of potentially throwing instructions in the basicblocks are 
+   counted.
+
+   We don't consider nor do we determine the types of exceptions thrown. Edges
+   are added from every block to every potential handler.
+
+*******************************************************************************/
+
+void cfg_add_exceptional_edges(jitdata *jd) {
+       basicblock *bptr;
+       instruction *iptr;
+       exception_entry *ee;
+
+       /* Count the number of exceptional exits for every block.
+        * Every PEI is an exceptional out.
+        */
+
+       FOR_EACH_BASICBLOCK(jd, bptr) {
+
+               if (bptr->flags == BBUNDEF) {
+                       continue;
+               }
+
+               FOR_EACH_INSTRUCTION(bptr, iptr) {
+                       if (icmd_table[iptr->opc].flags & ICMDTABLE_PEI) {      
+                               bptr->exouts += 1;
+                       }
+               }
+       }
+
+       /* Count the number of exception handlers for every block. */
+
+       for (ee = jd->exceptiontable; ee; ee = ee->down) {
+               for (bptr = ee->start; bptr != ee->end; bptr = bptr->next) {
+                       /* Linking a block with a handler, even if there are no exceptional exits
+                          breaks stuff in other passes. */
+                       if (bptr->exouts > 0) {
+                               bptr->exhandlercount += 1;
+                               ee->handler->expredecessorcount += 1;
+                       }
+               }
+       }
+
+       /* Allocate and fill exception handler arrays. */
+
+       for (ee = jd->exceptiontable; ee; ee = ee->down) {
+               for (bptr = ee->start; bptr != ee->end; bptr = bptr->next) {
+                       if (bptr->exouts > 0) {
+
+                               if (bptr->exhandlers == NULL) {
+                                       bptr->exhandlers = DMNEW(basicblock *, bptr->exhandlercount);
+                                       /* Move pointer past the end of the array, 
+                                        * It will be filled in the reverse order.
+                                        */
+                                       bptr->exhandlers += bptr->exhandlercount;
+                               }
+
+                               bptr->exhandlers -= 1;
+                               *(bptr->exhandlers) = ee->handler;
+
+                               if (ee->handler->expredecessors == NULL) {
+                                       ee->handler->expredecessors = DMNEW(basicblock *, ee->handler->expredecessorcount);
+                                       ee->handler->expredecessors += ee->handler->expredecessorcount;
+                               }
+
+                               ee->handler->expredecessors -= 1;
+                               *(ee->handler->expredecessors) = bptr;
+                       }
+               }
+       }
+}
+
 /*
  * 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
index 40ff40fe7ad74f6a6ed18e58466c73fe23fc04e0..c1b348950f12607f9b69c490f443b46a0bc18c4c 100644 (file)
@@ -764,12 +764,12 @@ static u1 *jit_compile_intern(jitdata *jd)
 # endif /* defined(ENABLE_LSRA) && !defined(ENABLE_SSA) */
 #if defined(ENABLE_SSA)
                /* allocate registers */
-               if ((opt_lsra) && (jd->exceptiontablelength == 0)) {
+               if ((opt_lsra) /*&& strcmp(jd->m->name->text, "findClass") != 0*/) {
                        jd->ls = DNEW(lsradata);
                        jd->ls = NULL;
                        ssa(jd);
                        /*lsra(jd);*/ regalloc(jd);
-
+                       eliminate_subbasicblocks(jd);
                        STATISTICS(count_methods_allocated_by_lsra++);
 
                } else
index 83953ac2e032179e9310155401a969bf06ea1a81..51ba842261cb205401c604be44278242f107eee5 100644 (file)
@@ -552,6 +552,14 @@ struct basicblock {
        basicblock  **domfrontier;  /* Dominance frontier                         */
        s4            domfrontiercount;
 
+       basicblock  **exhandlers;   /* Exception handlers for this block */
+       s4            exhandlercount;
+       basicblock  **expredecessors; /* Blocks this block is exception handler for */
+       s4            expredecessorcount;
+       s4            exouts;       /* Number of exceptional exits */
+
+       basicblock   *subbasicblocks;
+
        void         *vp;           /* Freely used by different passes            */
 #endif
 };
@@ -560,11 +568,24 @@ struct basicblock {
        for ((it) = (bptr)->successors; (it) != (bptr)->successors + (bptr)->successorcount; ++(it))
 
 #define FOR_EACH_PREDECESSOR(bptr, it) \
-       for ((it) = (bptr)->predecessors; (it) != (bptr)->predecessors + (bptr)->predecessorcount; ++(it))
+       for ( \
+               (it) = (bptr)->predecessors; \
+               (it) != (bptr)->predecessors + ((bptr)->predecessorcount < 0 ? 0 : (bptr)->predecessorcount); \
+               ++(it) \
+       )
 
 #define FOR_EACH_INSTRUCTION(bptr, it) \
        for ((it) = (bptr)->iinstr; (it) != (bptr)->iinstr + (bptr)->icount; ++(it))
 
+#if defined(ENABLE_SSA)
+
+#define FOR_EACH_EXHANDLER(bptr, it) \
+       for ((it) = (bptr)->exhandlers; (it) != (bptr)->exhandlers + (bptr)->exhandlercount; ++(it))
+
+#define FOR_EACH_EXPREDECESSOR(bptr, it) \
+       for ((it) = (bptr)->expredecessors; (it) != (bptr)->expredecessors + (bptr)->expredecessorcount; ++(it))
+
+#endif
 
 /* [+]...the javalocals array: This array is indexed by the javaindex (the    */
 /*       local variable index ocurring in the original bytecode). An element  */
index 7430d79f98d203897eed87ff5ab5ffec6ab82710..0874f64284f350440edbfa66b3ec2bb044477274 100644 (file)
@@ -118,14 +118,15 @@ void ssa(jitdata *jd) {
 #endif
 
        cfg_add_root(jd);
-       dominator_tree_build(jd);
+       cfg_add_exceptional_edges(jd);
        /*pythonpass_run(jd, "foo", "cfg_print");*/
-       dominance_frontier_build(jd);
        /*dominator_tree_validate(jd, dd);*/
        /*pythonpass_run(jd, "ssa2", "main");*/
        /*pythonpass_run(jd, "alt_ssa", "main");*/
        pythonpass_run(jd, "foo", "before");
        if (getenv("XSSA")) {
+               dominator_tree_build(jd);
+               dominance_frontier_build(jd);
                xssa(jd);
        } else {
                yssa(jd);
index 6225515d57bca2c3fda64a8103af954b5781fbe7..55379d2ce16c0d0e1e969dcdce64dd49ac09c028 100644 (file)
@@ -44,6 +44,7 @@
 #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)
 #endif
 
 /*
@@ -53,14 +54,30 @@ move set and get uses into jit.h
 
 #define ICMD_PHI 666
 
+#define eqi(a, b) (((a) && (b) || (!(a) && !(b)))
+
+#define nn(x) ((x) < 0 ? 0 : (x))
+
+#define ass(dst, src) *(dst) = *(src)
+
 static inline const char *instruction_name(const instruction *iptr) {
-       if (iptr->opc == ICMD_PHI) {
+       if (iptr == NULL) {
+               return "null";
+       } else if (iptr->opc == ICMD_PHI) {
                return "phi";
        } else {
                return icmd_table[iptr->opc].name;
        }
 }
 
+static inline s4 instruction_line(const instruction *iptr) {
+       if (iptr == NULL) {
+               return -1;
+       } else {
+               return iptr->line;
+       }
+}
+
 typedef struct phi_function {
        s4 dst;
        s4 *args;
@@ -71,12 +88,16 @@ typedef struct phi_function {
 typedef struct basicblock_info {
        bool visited;
        bool active;
+       bool traversed;
        unsigned backward_branches;
 
        instruction **state_array;
 
        unsigned phi_count;
+       unsigned phi_max;
        phi_function *phi_functions;
+       unsigned complete_predecessors;
+       bool cow;
 } basicblock_info;
 
 typedef struct ssa_info {
@@ -89,6 +110,49 @@ typedef struct ssa_info {
        s4 s_buf[3];
 } ssa_info;
 
+static unsigned get_predecessor_count(basicblock *bb) {
+       unsigned ret;
+       basicblock **itpred;
+
+       ret = nn(bb->predecessorcount);
+
+       FOR_EACH_EXPREDECESSOR(bb, itpred) {
+               ret += (*itpred)->exouts;
+       }
+
+       return ret;
+}
+
+static unsigned get_predecessor_index(basicblock *from, basicblock *to) {
+       basicblock **itpred;
+       unsigned j = 0;
+
+       for (itpred = to->predecessors; itpred != to->predecessors + nn(to->predecessorcount); ++itpred) {
+               if (*itpred == from) break;
+               j++;
+       }
+       
+       if (j == nn(to->predecessorcount)) {
+               assert(j != nn(to->predecessorcount));
+       }
+
+       return j;
+}
+
+static void phi_set_argument(basicblock *bb, instruction *phi, unsigned j, instruction *value) {
+       phi_function *pf = (phi_function *)(
+               (char *)phi - OFFSET(phi_function, instr)
+       );
+       assert(j < phi->s1.argcount);
+       if (value == NULL) {
+               pf->args[j] = pf->local;
+       } else {
+               pf->args[j] = value->dst.varindex;
+       }
+       /*phi->sx.s23.s2.args[j] = value->dst.varindex;*/
+       printf(" *** in bb%d setting phi arg %d for local %d to %s@%d (%d)\n", bb->nr, j, pf->local, instruction_name(value), instruction_line(value), value ? value->dst.varindex : -1);
+}
+
 static inline basicblock_info *bb_info(basicblock *bb) {
        return (basicblock_info *)(bb->vp);
 }
@@ -103,50 +167,34 @@ static void mark_loops(basicblock *bb) {
                FOR_EACH_SUCCESSOR(bb, itsucc) {
                        mark_loops(*itsucc);
                }
+               FOR_EACH_EXHANDLER(bb, itsucc) {
+                       mark_loops(*itsucc);
+               }
                bbi->active = false;
        } else if (bbi->active) {
                bbi->backward_branches += 1;
        }
 }
 
-typedef void (*traverse_fun)(ssa_info *ssa, basicblock *bb);
-
-static void traverse(ssa_info *ssa, basicblock *bb, traverse_fun fun) {
-       basicblock **itsucc, **itpred;
-       unsigned complete_preds;
-
-       /* Process block */
-
-       fun(ssa, bb);
-
-       /* Recurse */
-
-       FOR_EACH_SUCCESSOR(bb, itsucc) {
-               complete_preds = 0;
-               FOR_EACH_PREDECESSOR(*itsucc, itpred) {
-                       if (bb_info(*itpred)->state_array) {
-                               complete_preds += 1;
-                       }
-               }
-               if (complete_preds == ((*itsucc)->predecessorcount - bb_info(*itsucc)->backward_branches)) {
-                       printf(" *** Traverse bb%d => bb%d\n", bb->nr, (*itsucc)->nr);
-                       traverse(ssa, *itsucc, fun);
-               }
-       }
-
-}
-
 static instruction *create_phi(ssa_info *ssa, basicblock *bb, s4 local) {
        basicblock_info *bbi = bb_info(bb);
        phi_function *phi;
+       s4 *itarg;
+       unsigned arg_count = get_predecessor_count(bb);
 
-       printf(" *** BB%d phi for local %d\n", bb->nr, local);
+       printf(" *** BB%d phi #%d for local %d\n", bb->nr, bbi->phi_count, local);
 
        phi = bbi->phi_functions + bbi->phi_count;
+       assert(bbi->phi_count < bbi->phi_max);
        bbi->phi_count += 1;
 
+
        phi->local = local;
-       phi->args = DMNEW(s4, bb->predecessorcount);
+       phi->args = DMNEW(s4, arg_count);
+       for (itarg = phi->args; itarg != phi->args + arg_count; ++itarg) {
+               /* Invalidate */
+               *itarg = 0x7fffffff;
+       }
 
        assert(ssa->locals_count < ssa->max_locals);
        ssa->locals[ssa->locals_count] = ssa->jd->var[local];
@@ -155,12 +203,30 @@ static instruction *create_phi(ssa_info *ssa, basicblock *bb, s4 local) {
 
        phi->instr.opc = ICMD_PHI;
        phi->instr.dst.varindex = phi->dst;
-       phi->instr.s1.argcount = bb->predecessorcount;
-       phi->instr.sx.s23.s2.args = phi->args;
+       phi->instr.s1.argcount = arg_count;
+       phi->instr.sx.s23.s2.args = NULL;
 
        return &(phi->instr);
 }
 
+static bool is_my_phi(basicblock *bb, instruction *iptr) {
+       basicblock_info *bbi = bb_info(bb);
+       if (iptr == NULL) {
+               return false;
+       }
+       if (iptr->opc != ICMD_PHI) {
+               return false;
+       }
+       if (    
+               ((char *)bbi->phi_functions <= (char *)iptr) &&
+               ((char *)iptr < (char *)(bbi->phi_functions + bbi->phi_count))
+       ) {
+               return true;
+       } else {
+               return false;
+       }
+}
+
 static void rename_def(ssa_info *ssa, basicblock *bptr, instruction *iptr) {
        basicblock_info *bbi = bb_info(bptr);
        assert(bbi->state_array);
@@ -241,6 +307,148 @@ static void set_uses(ssa_info *ssa, instruction *iptr, s4 *uses, unsigned uses_c
        }
 }
 
+typedef void (*traverse_fun)(ssa_info *ssa, basicblock *bb);
+
+static void traverse(ssa_info *ssa, basicblock *bb, traverse_fun fun) {
+       basicblock_info *bbi = bb_info(bb);
+       basicblock **itsucc, **itpred;
+       basicblock_info *succi;
+       unsigned complete_preds;
+       unsigned j;
+
+       /*if (bbi->traversed) {
+               return;
+       }*/
+
+       /* Process block */
+
+       fun(ssa, bb);
+
+       /*bbi->traversed = true;*/
+
+       /* Recurse */
+
+       FOR_EACH_SUCCESSOR(bb, itsucc) {
+               merge(ssa, bbi->state_array, *itsucc, get_predecessor_index(bb, *itsucc));
+               succi = bb_info(*itsucc);
+               succi->complete_predecessors += 1;
+               if (succi->complete_predecessors == (/*nn((*itsucc)->predecessorcount)*/ get_predecessor_count(*itsucc) - succi->backward_branches)) {
+                       printf(" *** Traverse bb%d => bb%d\n", bb->nr, (*itsucc)->nr);
+                       traverse(ssa, *itsucc, fun);
+               }
+       }
+
+       FOR_EACH_EXHANDLER(bb, itsucc) {
+               succi = bb_info(*itsucc);
+               succi->complete_predecessors += bb->exouts; /* XXX this might be 0 */
+               if (succi->complete_predecessors == (/*nn((*itsucc)->predecessorcount)*/ get_predecessor_count(*itsucc) - succi->backward_branches)) {
+                       printf(" *** Traverse bb%d => bb%d\n", bb->nr, (*itsucc)->nr);
+                       traverse(ssa, *itsucc, fun);
+               }
+       }
+
+}
+
+void merge(ssa_info *ssa, instruction **state_array, basicblock *succ, unsigned j) {
+       basicblock_info *succi = bb_info(succ);
+       instruction *phi;
+       unsigned i;
+       unsigned a;
+
+#define mprintf(fmt, ...) printf(" *** merge bb? => bb%d > " fmt, succ->nr, __VA_ARGS__)
+
+       mprintf("(%d, %p)\n", j, succi->state_array);
+
+       if (succi->state_array == NULL) {
+
+               succi->state_array = DMNEW(instruction *, ssa->jd->localcount);
+
+               mprintf("creating state_array %p\n", succi->state_array );
+
+
+               if (succi->backward_branches > 0) {
+                       mprintf("bb%d is loop header, creating phis\n", succ->nr);
+                       for (i = 0; i < ssa->jd->localcount; ++i) {
+                               succi->state_array[i] = create_phi(ssa, succ, i);
+                       }
+               } else {
+                       /*
+                       printf(" *** merge bb%d cow state array\n", succ->nr);
+                       succi->state_array = bbi->state_array;
+                       succi->cow = true;
+                       */
+                       MCOPY(succi->state_array, state_array, instruction *, ssa->jd->localcount);
+                       return;
+               }
+       }
+
+       for (i = 0; i < ssa->jd->localcount; ++i) {
+               mprintf("local %d bb: %s@%d, succ: %s@%d\n", i, instruction_name(state_array[i]), instruction_line(state_array[i]), instruction_name(succi->state_array[i]), instruction_line(succi->state_array[i]));
+
+               if (succi->traversed) {
+                       /* Back edge, all phis already created */
+                       /* Only fill in phi arguments */
+                       /* We have created phis for *ALL* locals, so there is random access */
+                       phi_set_argument(succ, &(succi->phi_functions[i].instr), j, state_array[i]);
+               } else if (state_array[i] != succi->state_array[i]) {
+                       mprintf("merge bb%d need phi for local %d\n", succ->nr, i);
+                       /* Create new state array if needed */
+
+                       /*if (succi->cow) {
+                               printf(" *** merge bb%d cloning cow state array\n", succ->nr);
+                               state_array = DMNEW(instruction *, ssa->jd->localcount);
+                               MCOPY(state_array, succi->state_array, instruction *, ssa->jd->localcount);
+                               succi->state_array = state_array;
+                               succi->cow = false;
+                       }*/
+
+                       if (is_my_phi(succ, succi->state_array[i])) {
+                               /* State array is already phi function, just need to fill in argument */
+                               phi_set_argument(succ, succi->state_array[i], j, state_array[i]);
+                       } else {
+                               /* Create phi and initialize all arguments with current state array value
+                                * (We might have already merged this value from within several blocks).
+                                */
+                               phi = create_phi(ssa, succ, i);
+                               for (a = 0; a < get_predecessor_count(succ); ++a) {
+                                       phi_set_argument(succ, phi, a, succi->state_array[i]);
+                               }
+                               phi_set_argument(succ, phi, j, state_array[i]);
+                               succi->state_array[i] = phi;
+                       }
+               }
+       }
+#undef mprintf
+}
+
+static unsigned get_ex_predecessor_index(basicblock *from, unsigned pei, basicblock *to) {
+       unsigned i, j;
+       basicblock **itpred;
+       instruction *iti;
+
+       j = nn(to->predecessorcount);
+
+       FOR_EACH_EXPREDECESSOR(to, itpred) {
+               if ((*itpred)->nr == from->nr) {
+                       j += pei;
+                       return j;
+               } else {
+                       j += (*itpred)->exouts;
+               }
+       }
+
+       assert(0);
+}
+
+static void handle_pei(ssa_info *ssa, basicblock *bb, unsigned pei) {
+       basicblock_info *bbi = bb_info(bb);
+       basicblock **itsucc;
+
+       FOR_EACH_EXHANDLER(bb, itsucc) {
+               merge(ssa, bbi->state_array, *itsucc, get_ex_predecessor_index(bb, pei, *itsucc));
+       }
+}
+
 static void traverse_fun_impl(ssa_info *ssa, basicblock *bb) {
        basicblock_info *bbi = bb_info(bb), *predi;
        basicblock **itpred, *pred;
@@ -249,26 +457,41 @@ static void traverse_fun_impl(ssa_info *ssa, basicblock *bb) {
        instruction *iptr;
        unsigned uses_count;
        s4 *uses, *ituse;
-       
+       unsigned pei = 0;
+
+       assert(! bbi->traversed);
+       bbi->traversed = true;
+
+       /*
        if (bbi->state_array) {
                return;
        }
+       */
+
+       /* bb 0 */
 
        if (bb->predecessorcount == 0) {
+               assert(! bbi->state_array);
                bbi->state_array = DMNEW(instruction *, ssa->jd->localcount);
                MZERO(bbi->state_array, instruction *, ssa->jd->localcount);
                goto process_instructions;
        }
 
+
+       /*
        if ((bb->predecessorcount == 1) && (bb->predecessors[0]->successorcount == 1)) {
                bbi->state_array = bb_info(bb->predecessors[0])->state_array;
                assert(bbi->state_array);
                goto process_instructions;
        }
+       */
 
+       /*
        bbi->state_array = DMNEW(instruction *, ssa->jd->localcount);
        MZERO(bbi->state_array, instruction *, ssa->jd->localcount);
+       */
 
+       /*
        if (bbi->backward_branches > 0) {
                for (i = 0; i < ssa->jd->localcount; ++i) {
                        bbi->state_array[i] = create_phi(ssa, bb, i);
@@ -294,11 +517,18 @@ static void traverse_fun_impl(ssa_info *ssa, basicblock *bb) {
 
                }
        }
+       */
 
 process_instructions:
 
+       assert(bbi->state_array);
+
        FOR_EACH_INSTRUCTION(bb, iptr) {
 
+               if (icmd_table[iptr->opc].flags & ICMDTABLE_PEI) {
+                       handle_pei(ssa, bb, pei++);
+               }
+
                get_uses(ssa, iptr, &uses, &uses_count);
 
                for (ituse = uses; ituse != uses + uses_count; ++ituse) {
@@ -417,28 +647,11 @@ static void ssa_export(ssa_info *ssa) {
        jd->localcount = ssa->locals_count;
 }
 
-static unsigned get_predecessor_index(basicblock *from, basicblock *to) {
-       basicblock **itpred;
-       unsigned j = 0;
-
-       for (itpred = to->predecessors; itpred != to->predecessors + to->predecessorcount; ++itpred) {
-               if (*itpred == from) break;
-               j++;
-       }
-       
-       if (j == to->predecessorcount) {
-               assert(j != to->predecessorcount);
-       }
-
-       return j;
-}
-
-static basicblock *create_block(ssa_info *ssa, basicblock *from, basicblock *to) {
+static basicblock *create_block_intern(ssa_info *ssa, basicblock *from, basicblock *to, unsigned j) {
        basicblock *mid;
        basicblock_info *toi;
        instruction *iptr;
        phi_function *itph;
-       unsigned j = get_predecessor_index(from, to);
        
        mid = DNEW(basicblock);
        MZERO(mid, basicblock, 1);
@@ -458,6 +671,7 @@ static basicblock *create_block(ssa_info *ssa, basicblock *from, basicblock *to)
                iptr->opc = ICMD_COPY;
                iptr->dst.varindex = itph->dst;
                iptr->s1.varindex =  itph->args[j];
+               assert(j < itph->instr.s1.argcount);
                assert(itph->dst < ssa->locals_count);
                assert(itph->args[j] < ssa->locals_count);
                iptr++;
@@ -466,13 +680,20 @@ static basicblock *create_block(ssa_info *ssa, basicblock *from, basicblock *to)
        iptr->opc = ICMD_GOTO;
        iptr->dst.block = to;
 
+       return mid;
+}
+
+static basicblock *create_block(ssa_info *ssa, basicblock *from, basicblock *to) {
+       basicblock *ret;
+       ret = create_block_intern(ssa, from, to, get_predecessor_index(from, to));
+
        while (from->next) {
                from = from->next;
        }
 
-       from->next = mid;
+       from->next = ret;
 
-       return mid;
+       return ret;
 }
 
 static void crate_fallthrough(ssa_info *ssa, basicblock *bptr) {
@@ -551,7 +772,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) || 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)
                                gt = true;
                        else if (iptr->opc != ICMD_NOP)
                                gt = false;
@@ -563,11 +784,162 @@ static void ssa_create_phi_moves(ssa_info *ssa) {
        }
 }
 
+static basicblock *split_basicblock_at(ssa_info *ssa, basicblock *bptr, instruction *iptr) {
+
+       basicblock *newblock;
+       basicblock *tosplit;
+       basicblock **pnext;
+       unsigned icount;
+       basicblock *it;
+       unsigned pos;
+
+       unsigned origidx = iptr - bptr->iinstr;
+
+       printf(" *** split basicblock bb%d at %s/%d/%d\n", bptr->nr, instruction_name(iptr), instruction_line(iptr), origidx);
+       assert(origidx < bptr->icount);
+
+
+       if (! bptr->subbasicblocks) {
+               bptr->subbasicblocks = DNEW(basicblock);
+               ass(bptr->subbasicblocks, bptr);
+               bptr->subbasicblocks->next = NULL;
+       }
+
+       tosplit = bptr->subbasicblocks;
+       pos = 0;
+
+       while (tosplit->next && (origidx >= (pos + tosplit->icount))) {
+               assert(bptr->nr == tosplit->nr);
+               pos += tosplit->icount;
+               tosplit = tosplit->next;
+       }
+
+       assert(bptr->nr == tosplit->nr);
+       
+       icount = iptr - tosplit->iinstr + 1;
+       assert(icount <= tosplit->icount);
+
+       if (icount < tosplit->icount) {
+               newblock = DNEW(basicblock);
+               ass(newblock, tosplit);
+       
+               tosplit->next = newblock;
+               tosplit->icount = icount;
+
+               newblock->icount -= icount;
+               newblock->iinstr += icount;
+               newblock->next = NULL;
+
+               assert(tosplit->nr == bptr->nr);
+               assert(newblock->nr == bptr->nr);
+               assert(newblock->next == NULL);
+       } else {
+               printf("xx split\n");
+       }
+
+       return tosplit;
+}
+
+static exception_entry *create_exception_handler(ssa_info *ssa, basicblock *from, unsigned pei, basicblock *to, classref_or_classinfo catchtype) {
+       basicblock *it;
+       exception_entry *ee = DNEW(exception_entry);
+       basicblock *exh = create_block_intern(ssa, from, to, get_ex_predecessor_index(from, pei, to));
+       exh->type = BBTYPE_EXH;
+       to->type = BBTYPE_STD;
+
+       exh->indepth = exh->outdepth = 1;
+       exh->invars = exh->outvars = DNEW(s4);
+       /* assigned in caller */
+
+       ee->start = from;
+       ee->end = from->next;
+       ee->handler = exh;
+       ee->catchtype = catchtype;
+       ee->next = NULL;
+       ee->down = NULL;
+
+       for (it = ssa->jd->basicblocks; it->next; it = it->next);
+
+       it->next = exh;
+
+       return ee;
+}
+
+static void ssa_create_ex_phi_moves(ssa_info *ssa) {
+       basicblock *bptr;
+       instruction *iptr;
+       basicblock_info *bbi;
+       exception_entry *ite;
+       exception_entry *firstee, *lastee, *ee;
+       basicblock *ittry, *try;
+       classref_or_classinfo catchtype;
+       unsigned pei;
+       unsigned exhandler_count = 0;
+       varinfo *v;
+
+       FOR_EACH_BASICBLOCK(ssa->jd, bptr) {
+               if (! bptr->vp) continue;
+               if (! (bptr->flags >= BBREACHED)) continue;
+               if (bptr->expredecessorcount == 0) continue;
+               bbi = bb_info(bptr);
+               if (bbi->phi_count == 0) continue;
+
+               for (ite = ssa->jd->exceptiontable; ite; ite = ite->down) {
+                       /* Traverse all exhandlers */
+                       if (bptr == ite->handler) {
+                               printf(" *** mess with handler bb%d\n", bptr->nr);
+                               catchtype = ite->catchtype;
+                               firstee = lastee = NULL;
+                               /* If bptr is handler, remove exhandler */
+                               /* Traverse all guarded blocks */
+                               for (ittry = ite->start; ittry != ite->end; ittry = ittry->next) {
+                                       pei = 0;
+                                       FOR_EACH_INSTRUCTION(ittry, iptr) {
+                                               if (icmd_table[iptr->opc].flags & ICMDTABLE_PEI) {
+                                                       try = split_basicblock_at(ssa, ittry, iptr);
+                                                       ee = create_exception_handler(ssa, try, pei, bptr, catchtype);
+                                                       ee->handler->invars[0] = ssa->jd->vartop + exhandler_count;
+                                                       exhandler_count += 1;
+                                                       ssa->jd->exceptiontablelength += 1;
+                                                       if (firstee == NULL) {
+                                                               firstee = lastee = ee;
+                                                       } else {
+                                                               lastee->next = ee;
+                                                               lastee->down = ee;
+                                                               lastee = ee;
+                                                       }
+                                                       pei += 1;
+                                               }
+                                       }
+                               }
+                               if (firstee) {
+                                       lastee->next = ite->next;
+                                       lastee->down = ite->down;
+                                       *ite = *firstee;
+                                       ite = lastee;
+                               }
+                       }
+               }
+       }
+       
+       /* Allocate interface vars */
+
+       ssa->jd->var = DMREALLOC(ssa->jd->var, varinfo, ssa->jd->vartop, ssa->jd->vartop + exhandler_count);
+       for (v = ssa->jd->var + ssa->jd->vartop; v != ssa->jd->var + ssa->jd->vartop + exhandler_count; ++v) {
+               v->type = TYPE_ADR;
+               v->flags = INOUT;
+       }
+       ssa->jd->vartop += exhandler_count;
+       ssa->jd->varcount += exhandler_count;
+}
+
 void yssa(jitdata *jd) {
        basicblock *it;
        basicblock_info *iti;
        ssa_info *ssa;
 
+       if (jd->localcount == 0) return;
+
        printf("=============== [ before %s ] =========================\n", jd->m->name->text);
        show_method(jd, 3);
        printf("=============== [ /before ] =========================\n");
@@ -584,6 +956,7 @@ void yssa(jitdata *jd) {
                        MZERO(iti, basicblock_info, 1);
                        if (jd->localcount > 0) {
                                iti->phi_functions = DMNEW(phi_function, jd->localcount);
+                               iti->phi_max = jd->localcount;
                        }
                        it->vp = iti;
                } else {
@@ -597,17 +970,37 @@ void yssa(jitdata *jd) {
 
        ssa_rename_others(ssa);
 
-       fill_in_phi_args(ssa);
+       /*fill_in_phi_args(ssa);*/
 
        ssa_export(ssa);
 
        ssa_create_phi_moves(ssa);
+       ssa_create_ex_phi_moves(ssa);
 
        printf("=============== [ after ] =========================\n");
        show_method(jd, 3);
        printf("=============== [ /after ] =========================\n");
 }
 
+void eliminate_subbasicblocks(jitdata *jd) {
+       basicblock *bptr, *next;
+
+       FOR_EACH_BASICBLOCK(jd, bptr) {
+               if (bptr->subbasicblocks) {
+                       next = bptr->next;
+                       *bptr = *(bptr->subbasicblocks);
+                       bptr->subbasicblocks = NULL;
+                       while (bptr->next) {
+                               bptr = bptr->next;
+                       }
+                       bptr->next = next;
+               }
+       }
+       printf("=============== [ elim ] =========================\n");
+       show_method(jd, 3);
+       printf("=============== [ /elim ] =========================\n");
+}
+
 /*
  * 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
index 1022d16267b4b466b7366b6dae82a8d5f0ef9d81..da8913a7abd56f83b2ce084e86661f714c479cde 100644 (file)
@@ -343,37 +343,12 @@ L_restore_done:
 #      undef FREGS
 #      undef OUT
 
-#if 0
-
-/* asm_abstractmethoderror *****************************************************
-
-   Creates and throws an AbstractMethodError.
-
-*******************************************************************************/
-
-asm_abstractmethoderror:
-       mov     sp,a0                       /* pass java sp                       */
-       add     $1*8,a0
-       mov     0*8(sp),a1                  /* pass exception address             */
-       sub     $3,a1
-       call    exceptions_asm_new_abstractmethoderror@PLT
-                                           /* exception pointer is return value  */
-       pop     xpc                         /* get exception address              */
-       sub     $3,xpc                      /* exception address is ra - 3        */
-       jmp     L_asm_handle_exception
-
-#endif
-
 /* Offset table for PIC calls, see CALL_PIC */
 
 L_offsets:
        .long  _GLOBAL_OFFSET_TABLE_ - L_offsets
 L_offset_builtin_throw_exception:
        .long  builtin_throw_exception@PLTOFF
-L_offset_jit_asm_compile:
-       .long  jit_asm_compile@PLTOFF
-L_offset_exceptions_get_and_clear_exception:
-       .long  exceptions_get_and_clear_exception@PLTOFF
 L_offset_md_handle_exception:
        .long  md_handle_exception@PLTOFF
 
index 52c6bbc46e8da20b40dd077522dc3075ef33b53d..9274ed12bbdac5e9768fdb292d6a14edc06d4606 100644 (file)
@@ -55,6 +55,7 @@
 
 #include "vm/jit/codegen-common.h"
 #include "vm/jit/s390/codegen.h"
+#include "vm/jit/s390/md.h"
 
 
 /* prototypes *****************************************************************/