* src/vm/jit/jit.h (FOR_EACH_BASICBLOCK, FOR_EACH_SUCCESSOR, FOR_EACH_PREDECESSOR...
authorPeter Molnar <pm@complang.tuwien.ac.at>
Fri, 15 Feb 2008 17:55:18 +0000 (18:55 +0100)
committerPeter Molnar <pm@complang.tuwien.ac.at>
Fri, 15 Feb 2008 17:55:18 +0000 (18:55 +0100)
* src/vm/jit/optimizing/Makefile.am (SSA_SOURCES) [ENABLE_SSA]: AddeAd ssa3.c
* src/vm/jit/optimizing/ssa.c: Adapted for ssa3.c.
* src/vm/jit/optimizing/ssa2.c: Added copyright header.
* src/vm/jit/optimizing/ssa3.c: New file. Yet another SSA transofrmation algorithm prototype.
* src/vm/jit/python.c: Removed wrappers for creating variables and instructions because they were misdesigned.
* src/vm/jit/optimizing/ssa2.h: Removed.

src/vm/jit/jit.h
src/vm/jit/optimizing/Makefile.am
src/vm/jit/optimizing/ssa.c
src/vm/jit/optimizing/ssa2.c
src/vm/jit/optimizing/ssa2.h [deleted file]
src/vm/jit/optimizing/ssa3.c [new file with mode: 0644]
src/vm/jit/python.c

index c097c32eda03e7391cb12fca95c56eabb1504d32..83953ac2e032179e9310155401a969bf06ea1a81 100644 (file)
@@ -163,6 +163,8 @@ struct jitdata {
        bool             branchtoend;          /* true if end dummy is a target   */
 };
 
+#define FOR_EACH_BASICBLOCK(jd, it) \
+       for ((it) = (jd)->basicblocks; (it) != NULL; (it) = (it)->next)
 
 #define UNUSED                     -1
 
@@ -554,6 +556,16 @@ struct basicblock {
 #endif
 };
 
+#define FOR_EACH_SUCCESSOR(bptr, it) \
+       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))
+
+#define FOR_EACH_INSTRUCTION(bptr, it) \
+       for ((it) = (bptr)->iinstr; (it) != (bptr)->iinstr + (bptr)->icount; ++(it))
+
+
 /* [+]...the javalocals array: This array is indexed by the javaindex (the    */
 /*       local variable index ocurring in the original bytecode). An element  */
 /*       javalocals[javaindex] encodes where to find the contents of the      */
@@ -584,7 +596,10 @@ struct basicblock {
                bptr->type   = BBTYPE_STD;                     \
                bptr->method = (m);                            \
        } while (0)
-                       
+
+static inline bool basicblock_reached(const basicblock *bptr) {
+       return (bptr->flags >= BBREACHED);
+}
 
 /* data-flow constants for the ICMD table ************************************/
 
index 02b29221bc79311cac825b26959e431529a37789..b0e3fba34acdc6158e806733aae1ae5ce5fb585e 100644 (file)
@@ -65,7 +65,8 @@ SSA_SOURCES = \
        dominators.h \
        lifetimes.c \
        lifetimes.h \
-       ssa2.c
+       ssa2.c \
+       ssa3.c
 endif
 
 noinst_LTLIBRARIES = \
index 1e443e387e48bce70f4a2e74dfbdbe5f66f7b743..7430d79f98d203897eed87ff5ab5ffec6ab82710 100644 (file)
@@ -102,6 +102,7 @@ page 441 Algorithm 19.6. Inserting phi-functions:
 
 ******************************************************************************/
 void xssa(jitdata *jd);
+void yssa(jitdata *jd);
 void ssa(jitdata *jd) {
        struct dominatordata *dd;
        lsradata *ls;
@@ -122,8 +123,13 @@ void ssa(jitdata *jd) {
        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");
-       xssa(jd);
+       if (getenv("XSSA")) {
+               xssa(jd);
+       } else {
+               yssa(jd);
+       }
        pythonpass_run(jd, "foo", "after");
        return;
 
index 9bcc5185302a73ab66bff9c59790d93f028579aa..0246777420daef9c473e51785734a2d1d113e163 100644 (file)
@@ -1,3 +1,29 @@
+/* src/vm/optimizing/ssa2.c
+
+   Copyright (C) 2008
+   CACAOVM - Verein zu Foerderung der freien virtuellen Machine CACAO
+
+   This file is part of CACAO.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
+
+   Reimplementation of code in ssa.c. 
+   Uses the new dominator tree and the new CFG.
+*/
+
 #include "config.h"
 
 #include "mm/memory.h"
@@ -450,7 +476,7 @@ static void ssa_export(ssa_info *ssa) {
        printf(" *** jd->localcount %d, jd->maxlocals %d\n", jd->localcount , jd->maxlocals);
 }
 
-unsigned get_predecessor_index(basicblock *from, basicblock *to) {
+static unsigned get_predecessor_index(basicblock *from, basicblock *to) {
        basicblock **itpred;
        unsigned j = 0;
 
@@ -467,7 +493,7 @@ unsigned get_predecessor_index(basicblock *from, basicblock *to) {
        return j;
 }
 
-basicblock *create_block(ssa_info *ssa, basicblock *from, basicblock *to) {
+static basicblock *create_block(ssa_info *ssa, basicblock *from, basicblock *to) {
        basicblock *mid;
        basicblock_info *toi;
        instruction *iptr;
@@ -509,7 +535,7 @@ basicblock *create_block(ssa_info *ssa, basicblock *from, basicblock *to) {
        return mid;
 }
 
-void crate_fallthrough(ssa_info *ssa, basicblock *bptr) {
+static void crate_fallthrough(ssa_info *ssa, basicblock *bptr) {
        unsigned j;
        basicblock_info *toi;
        instruction *iptr;
@@ -537,7 +563,7 @@ void crate_fallthrough(ssa_info *ssa, basicblock *bptr) {
 
 }
 
-void ssa_create_phi_moves(ssa_info *ssa) {
+static void ssa_create_phi_moves(ssa_info *ssa) {
        basicblock *bptr;
        instruction *iptr;
 
@@ -616,3 +642,16 @@ void xssa(jitdata *jd) {
        printf("=============== [ /after ] =========================\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
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
diff --git a/src/vm/jit/optimizing/ssa2.h b/src/vm/jit/optimizing/ssa2.h
deleted file mode 100644 (file)
index f4bd3b0..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-#ifndef _VM_JIT_OPTIMIZING_SSA2
-#define _VM_JIT_OPTIMIZING_SSA2
-
-#endif
diff --git a/src/vm/jit/optimizing/ssa3.c b/src/vm/jit/optimizing/ssa3.c
new file mode 100644 (file)
index 0000000..6225515
--- /dev/null
@@ -0,0 +1,623 @@
+/* src/vm/optimizing/ssa3.c
+
+   Copyright (C) 2008
+   CACAOVM - Verein zu Foerderung der freien virtuellen Machine CACAO
+
+   This file is part of CACAO.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
+
+   SSA transformation PROTOTYPE based on:
+
+   Moessenboeck, H., 
+   Adding Static Single Assignment Form and a Graph Coloring Register 
+   Allocator to the Java Hotspot Client Compiler, 2000 
+   (http://www.ssw.uni-linz.ac.at/Research/Reports/Report15.html)
+
+   TODO
+
+   * Adapt for exception handling
+   * 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).
+*/
+
+#include "vm/jit/jit.h"
+#include "vm/global.h"
+#include "mm/memory.h"
+#include "mm/dumpmemory.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)
+#endif
+
+/*
+TODO
+move set and get uses into jit.h
+*/
+
+#define ICMD_PHI 666
+
+static inline const char *instruction_name(const instruction *iptr) {
+       if (iptr->opc == ICMD_PHI) {
+               return "phi";
+       } else {
+               return icmd_table[iptr->opc].name;
+       }
+}
+
+typedef struct phi_function {
+       s4 dst;
+       s4 *args;
+       s4 local;
+       instruction instr;
+} phi_function;
+
+typedef struct basicblock_info {
+       bool visited;
+       bool active;
+       unsigned backward_branches;
+
+       instruction **state_array;
+
+       unsigned phi_count;
+       phi_function *phi_functions;
+} basicblock_info;
+
+typedef struct ssa_info {
+       jitdata *jd;
+
+       varinfo locals[3000]; /* XXX hardcoded max */
+       unsigned max_locals;
+       unsigned locals_count;
+
+       s4 s_buf[3];
+} ssa_info;
+
+static inline basicblock_info *bb_info(basicblock *bb) {
+       return (basicblock_info *)(bb->vp);
+}
+
+static void mark_loops(basicblock *bb) {
+       basicblock_info *bbi = bb_info(bb);
+       basicblock **itsucc;
+
+       if (! bbi->visited) {
+               bbi->visited = true;
+               bbi->active = true;
+               FOR_EACH_SUCCESSOR(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;
+
+       printf(" *** BB%d phi for local %d\n", bb->nr, local);
+
+       phi = bbi->phi_functions + bbi->phi_count;
+       bbi->phi_count += 1;
+
+       phi->local = local;
+       phi->args = DMNEW(s4, bb->predecessorcount);
+
+       assert(ssa->locals_count < ssa->max_locals);
+       ssa->locals[ssa->locals_count] = ssa->jd->var[local];
+       phi->dst = ssa->locals_count;
+       ssa->locals_count += 1;
+
+       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;
+
+       return &(phi->instr);
+}
+
+static void rename_def(ssa_info *ssa, basicblock *bptr, instruction *iptr) {
+       basicblock_info *bbi = bb_info(bptr);
+       assert(bbi->state_array);
+
+       bbi->state_array[iptr->dst.varindex] = iptr;
+
+       assert(ssa->locals_count < ssa->max_locals);
+
+       ssa->locals[ssa->locals_count] = ssa->jd->var[iptr->dst.varindex];
+       iptr->dst.varindex = ssa->locals_count;
+       printf(" *** BB%d %s def %d => %d\n", bptr->nr, instruction_name(iptr), iptr->dst.varindex, ssa->locals_count);
+
+       ssa->locals_count += 1;
+}
+
+static void rename_use(ssa_info *ssa, basicblock *bptr, instruction *iptr, s4 *use) {
+       basicblock_info *bbi = bb_info(bptr);
+       assert(bbi->state_array);
+
+       if (bbi->state_array[*use] != NULL) {
+               printf(" *** BB%d %s use %d => %d (%s) \n", bptr->nr, instruction_name(iptr), *use, bbi->state_array[*use]->dst.varindex, instruction_name(bbi->state_array[*use]) );
+               *use = bbi->state_array[*use]->dst.varindex;
+       } else {
+               printf(" *** BB%d %s use keep\n", bptr->nr, instruction_name(iptr));
+       }
+}
+
+static void get_uses(ssa_info *ssa, instruction *iptr, s4 **puses, unsigned *puses_count) {
+       unsigned uses_count = 0;
+
+       switch (icmd_table[iptr->opc].dataflow) {
+               case DF_3_TO_0:
+               case DF_3_TO_1:
+                       ssa->s_buf[2] = iptr->sx.s23.s3.varindex;
+                       uses_count += 1;
+
+               case DF_2_TO_0:
+               case DF_2_TO_1:
+                       ssa->s_buf[1] = iptr->sx.s23.s2.varindex;
+                       uses_count += 1;
+
+               case DF_1_TO_0:
+               case DF_1_TO_1:
+               case DF_COPY:
+               case DF_MOVE:
+                       ssa->s_buf[0] = iptr->s1.varindex;
+                       uses_count += 1;
+
+                       *puses_count = uses_count;
+                       *puses = ssa->s_buf;
+                       break;
+       
+               case DF_N_TO_1:
+               case DF_INVOKE:
+               case DF_BUILTIN:
+
+                       *puses = iptr->sx.s23.s2.args;
+                       *puses_count = iptr->s1.argcount;
+                       break;
+
+               default:
+
+                       *puses_count = 0;
+                       break;
+       }
+}
+
+static void set_uses(ssa_info *ssa, instruction *iptr, s4 *uses, unsigned uses_count) {
+       if (uses == ssa->s_buf) {
+               switch (uses_count) {
+                       case 3:
+                               iptr->sx.s23.s3.varindex = ssa->s_buf[2];
+                       case 2:
+                               iptr->sx.s23.s2.varindex = ssa->s_buf[1];
+                       case 1:
+                               iptr->s1.varindex = ssa->s_buf[0];
+               }
+       }
+}
+
+static void traverse_fun_impl(ssa_info *ssa, basicblock *bb) {
+       basicblock_info *bbi = bb_info(bb), *predi;
+       basicblock **itpred, *pred;
+       unsigned i;
+       bool need_phi;
+       instruction *iptr;
+       unsigned uses_count;
+       s4 *uses, *ituse;
+       
+       if (bbi->state_array) {
+               return;
+       }
+
+       if (bb->predecessorcount == 0) {
+               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);
+               }
+       } else {
+               for (i = 0; i < ssa->jd->localcount; ++i) {
+                       need_phi = false;
+                       assert(bb_info(bb->predecessors[0])->state_array);
+
+                       FOR_EACH_PREDECESSOR(bb, itpred) {
+                               assert(bb_info(*itpred)->state_array);
+                               if (bb_info(bb->predecessors[0])->state_array[i] != bb_info(*itpred)->state_array[i]) {
+                                       need_phi = true;
+                                       break;
+                               }
+                       }
+
+                       if (need_phi) {
+                               bbi->state_array[i] = create_phi(ssa, bb, i);
+                       } else {
+                               bbi->state_array[i] = bb_info(bb->predecessors[0])->state_array[i];
+                       }
+
+               }
+       }
+
+process_instructions:
+
+       FOR_EACH_INSTRUCTION(bb, iptr) {
+
+               get_uses(ssa, iptr, &uses, &uses_count);
+
+               for (ituse = uses; ituse != uses + uses_count; ++ituse) {
+                       if (var_is_local(ssa->jd, *ituse)) {
+                               rename_use(ssa, bb, iptr, ituse);
+                       } else {
+                               *ituse += 0xFFFF;
+                       }
+               }
+
+               set_uses(ssa, iptr, uses, uses_count);
+
+               if (instruction_has_dst(iptr)) {
+                       if (var_is_local(ssa->jd, iptr->dst.varindex)) {
+                               rename_def(ssa, bb, iptr);
+                       } else {
+                               iptr->dst.varindex += 0xFFFF;
+                       }
+               }
+       }
+}
+
+static void ssa_rename_others(ssa_info *ssa) {
+
+       basicblock *bb;
+       instruction *iptr;
+       s4 *itinout, *uses, *ituse;
+       unsigned uses_count;
+       unsigned off = ssa->locals_count - ssa->jd->localcount;
+
+       FOR_EACH_BASICBLOCK(ssa->jd, bb) {
+
+               if (! basicblock_reached(bb)) continue;
+
+               for (itinout = bb->invars; itinout != bb->invars + bb->indepth; ++itinout) {
+                       *itinout += off;
+               }
+
+               for (itinout = bb->outvars; itinout != bb->outvars + bb->outdepth; ++itinout) {
+                       *itinout += off;
+               }
+
+               FOR_EACH_INSTRUCTION(bb, iptr) {
+                       if (instruction_has_dst(iptr)) {
+                               if (iptr->dst.varindex >= 0xFFFF) {
+                                       iptr->dst.varindex += off;
+                                       iptr->dst.varindex -= 0xFFFF;
+                               }
+                       }
+                       get_uses(ssa, iptr, &uses, &uses_count);
+                       for (ituse = uses; ituse != uses + uses_count; ++ituse) {
+                               if (*ituse >= 0xFFFF) {
+                                       *ituse += off;
+                                       *ituse -= 0xFFFF;
+                               }
+                       }
+                       set_uses(ssa, iptr, uses, uses_count);
+               }
+       }
+}
+
+static void fill_in_phi_args(ssa_info *ssa) {
+       basicblock *bb;
+       basicblock_info *bbi;
+       phi_function *itphi;
+       unsigned j;
+       basicblock **itpred;
+       basicblock_info *predi;
+
+       FOR_EACH_BASICBLOCK(ssa->jd, bb) {
+               if (!(bb->flags >= BBREACHED)) continue;
+               bbi = bb_info(bb);
+               j = 0;
+               FOR_EACH_PREDECESSOR(bb, itpred) {
+                       predi = bb_info(*itpred);
+                       for (itphi = bbi->phi_functions; itphi != bbi->phi_functions + bbi->phi_count; ++itphi) {
+                               if (predi->state_array[itphi->local]) {
+                                       itphi->args[j] = predi->state_array[itphi->local]->dst.varindex;
+                               } else {
+                                       itphi->args[j] = itphi->local;
+                               }
+                       }
+                       ++j;
+               }
+       }
+}
+
+static void ssa_export(ssa_info *ssa) {
+       unsigned i, j;
+       jitdata *jd = ssa->jd;
+       varinfo *vars, *it;
+       s4 vartop, varindex;
+
+       vartop = ssa->locals_count + jd->vartop - jd->localcount;
+       vars = DMNEW(varinfo, vartop);
+
+       MCOPY(vars, ssa->locals, varinfo, ssa->locals_count);
+       MCOPY(vars + ssa->locals_count, jd->var + jd->localcount, varinfo, jd->vartop - jd->localcount);
+
+       jd->var = vars;
+       jd->vartop = jd->varcount = vartop;
+
+       jd->local_map = DMREALLOC(jd->local_map, s4, 5 * jd->maxlocals, 5 * (jd->maxlocals + ssa->locals_count - jd->localcount));
+
+       for (i = 0; i < ssa->locals_count - jd->localcount; ++i) {
+               for (j = 0; j < 5; ++j) {
+                       varindex = jd->localcount + i;
+                       if (jd->var[varindex].type != j) {
+                               varindex = UNUSED;
+                       }
+                       jd->local_map[((jd->maxlocals + i) * 5) + j] = varindex;
+               }
+       }
+
+       jd->maxlocals += (ssa->locals_count - jd->localcount);
+       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) {
+       basicblock *mid;
+       basicblock_info *toi;
+       instruction *iptr;
+       phi_function *itph;
+       unsigned j = get_predecessor_index(from, to);
+       
+       mid = DNEW(basicblock);
+       MZERO(mid, basicblock, 1);
+
+       toi = bb_info(to);
+       assert(toi);
+
+       mid->nr = ssa->jd->basicblockcount;
+       ssa->jd->basicblockcount += 1;
+       mid->mpc = -1;
+       mid->type = 666;
+       mid->icount = toi->phi_count + 1;
+       iptr = mid->iinstr = DMNEW(instruction, mid->icount);
+       MZERO(mid->iinstr, instruction, mid->icount);
+
+       for (itph = toi->phi_functions; itph != toi->phi_functions + toi->phi_count; ++itph) {
+               iptr->opc = ICMD_COPY;
+               iptr->dst.varindex = itph->dst;
+               iptr->s1.varindex =  itph->args[j];
+               assert(itph->dst < ssa->locals_count);
+               assert(itph->args[j] < ssa->locals_count);
+               iptr++;
+       }
+
+       iptr->opc = ICMD_GOTO;
+       iptr->dst.block = to;
+
+       while (from->next) {
+               from = from->next;
+       }
+
+       from->next = mid;
+
+       return mid;
+}
+
+static void crate_fallthrough(ssa_info *ssa, basicblock *bptr) {
+       unsigned j;
+       basicblock_info *toi;
+       instruction *iptr;
+       phi_function *itph;
+
+       if (bptr->next == NULL) return;
+
+       j = get_predecessor_index(bptr, bptr->next);
+
+       toi = bb_info(bptr->next);
+       assert(toi);
+
+       bptr->iinstr = DMREALLOC(bptr->iinstr, instruction, bptr->icount, bptr->icount + toi->phi_count);
+       iptr = bptr->iinstr + bptr->icount;
+       bptr->icount += toi->phi_count;
+
+       for (itph = toi->phi_functions; itph != toi->phi_functions + toi->phi_count; ++itph) {
+               iptr->opc = ICMD_COPY;
+               iptr->dst.varindex = itph->dst;
+               iptr->s1.varindex =  itph->args[j];
+               assert(itph->dst < ssa->locals_count);
+               assert(itph->args[j] < ssa->locals_count);
+               iptr++;
+       }
+
+}
+
+static void ssa_create_phi_moves(ssa_info *ssa) {
+       basicblock *bptr;
+       instruction *iptr;
+
+       s4 i, l;
+       branch_target_t *table;
+       lookup_target_t *lookup;
+       bool gt;
+
+       for (bptr = ssa->jd->basicblocks; bptr; bptr = bptr->next) {
+               if (bptr->type == 666) {
+                       bptr->type = BBTYPE_STD;
+                       continue;
+               }
+               if (! bptr->vp) continue;
+               if (! (bptr->flags >= BBREACHED)) continue;
+               gt = false;
+               for (iptr = bptr->iinstr; iptr != bptr->iinstr + bptr->icount; ++iptr) {
+                       switch (icmd_table[iptr->opc].controlflow) {
+                               case CF_IF:
+                               case CF_RET:
+                               case CF_GOTO:
+                                       iptr->dst.block = create_block(ssa, bptr, iptr->dst.block);     
+                                       break;
+                               case CF_TABLE:
+                                       table = iptr->dst.table;
+                                       l = iptr->sx.s23.s2.tablelow;
+                                       i = iptr->sx.s23.s3.tablehigh;
+                                       i = i - l + 1;
+                                       i += 1; /* default */
+                                       while (--i >= 0) {
+                                               table->block = create_block(ssa, bptr, table->block);
+                                               ++table;
+                                       }
+                                       break;
+                               case CF_LOOKUP:
+                                       lookup = iptr->dst.lookup;
+                                       i = iptr->sx.s23.s2.lookupcount;
+                                       while (--i >= 0) {
+                                               lookup->target.block = create_block(ssa, bptr, lookup->target.block);
+                                               lookup++;
+                                       }
+                                       iptr->sx.s23.s3.lookupdefault.block = create_block(ssa, bptr, iptr->sx.s23.s3.lookupdefault.block);
+                                       break;
+                               case CF_JSR:
+                                       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)
+                               gt = true;
+                       else if (iptr->opc != ICMD_NOP)
+                               gt = false;
+               }
+               if (! bptr->next) continue;
+               if (! (bptr->next->flags >= BBREACHED)) continue;
+               if (bptr->next->type == 666) continue;
+               if (!gt) crate_fallthrough(ssa, bptr);
+       }
+}
+
+void yssa(jitdata *jd) {
+       basicblock *it;
+       basicblock_info *iti;
+       ssa_info *ssa;
+
+       printf("=============== [ before %s ] =========================\n", jd->m->name->text);
+       show_method(jd, 3);
+       printf("=============== [ /before ] =========================\n");
+
+       ssa = DNEW(ssa_info);
+       ssa->jd = jd;
+       ssa->max_locals = sizeof(ssa->locals) / sizeof(ssa->locals[0]);
+       MCOPY(ssa->locals, jd->var, varinfo, jd->localcount);
+       ssa->locals_count = jd->localcount;
+
+       FOR_EACH_BASICBLOCK(jd, it) {
+               if (basicblock_reached(it)) {
+                       iti = DNEW(basicblock_info);
+                       MZERO(iti, basicblock_info, 1);
+                       if (jd->localcount > 0) {
+                               iti->phi_functions = DMNEW(phi_function, jd->localcount);
+                       }
+                       it->vp = iti;
+               } else {
+                       it->vp = NULL;
+               }
+       }
+
+       mark_loops(jd->basicblocks);
+
+       traverse(ssa, jd->basicblocks, traverse_fun_impl);
+
+       ssa_rename_others(ssa);
+
+       fill_in_phi_args(ssa);
+
+       ssa_export(ssa);
+
+       ssa_create_phi_moves(ssa);
+
+       printf("=============== [ after ] =========================\n");
+       show_method(jd, 3);
+       printf("=============== [ /after ] =========================\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
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
index 4f5926bf71151102cc4b5d6d4504d855924ee6fc..0192e68fb567fa727ef4225a1e2263e7adf056a0 100644 (file)
@@ -202,7 +202,6 @@ struct field_map_entry {
 typedef struct field_map_entry field_map_entry;
 
 enum field {
-       F_ADD_INSTRUCTIONS,
        F_BASIC_BLOCKS,
        F_CALL_RETURN_TYPE,
        F_CALL_ARGS,
@@ -229,6 +228,7 @@ enum field {
        F_INTERFACE_MAP,
        F_IN_VARS,
        F_IS_CLASS_CONSTANT,
+       F_IS_IN_MEMORY,
        F_IS_INOUT,
        F_IS_LOCAL,
        F_IS_PREALLOCATED,
@@ -253,6 +253,7 @@ enum field {
        F_PEI_EX,
        F_PREDECESSORS,
        F_REACHED,
+       F_REGISTER_OFFSET,
        F_RETURN_TYPE,
        F_S,
        F_SHOW,
@@ -266,7 +267,6 @@ enum field {
 
 /* Keep it soreted alphabetically, so we can support binary search in future. */
 struct field_map_entry field_map[] = {
-       { "add_instructions", F_ADD_INSTRUCTIONS },
        { "basic_blocks", F_BASIC_BLOCKS },
        { "call_return_type", F_CALL_RETURN_TYPE },
        { "call_args", F_CALL_ARGS },
@@ -294,6 +294,7 @@ struct field_map_entry field_map[] = {
        { "in_vars", F_IN_VARS },
        { "is_class_constant", F_IS_CLASS_CONSTANT },
        { "is_inout", F_IS_INOUT },
+       { "is_in_memory", F_IS_IN_MEMORY },
        { "is_local", F_IS_LOCAL },
        { "is_preallocated", F_IS_PREALLOCATED },
        { "is_saved", F_IS_SAVED },
@@ -317,6 +318,7 @@ struct field_map_entry field_map[] = {
        { "pei_ex", F_PEI_EX },
        { "predecessors", F_PREDECESSORS },
        { "reached", F_REACHED },
+       { "register_offset", F_REGISTER_OFFSET },
        { "return_type", F_RETURN_TYPE },
        { "s", F_S },
        { "show", F_SHOW },
@@ -713,6 +715,18 @@ int set_s4(s4 *p, PyObject *o) {
        }
 }
 
+int set_s4_flag(s4 *p, s4 flag, PyObject *o) {
+       if (o == Py_True) {
+               *p |= flag;
+               return 0;
+       } else if (o == Py_False) {
+               *p &= ~flag;
+               return 0;
+       } else {
+               return -1;
+       }
+}
+
 int get_int(PyObject **o, int p) {
        *o = PyInt_FromLong(p);
        return 0;
@@ -1185,40 +1199,6 @@ ITERATOR_FUNC(instruction_iter_func) {
        return -1;
 }
 
-int basicblock_add_instructions(basicblock *bptr, PyObject *args) {
-       int pos = 0, count = 1, dst, src, num;
-
-       if (! PyArg_ParseTuple(args, "|ii", &pos, &count)) {
-               return -1;
-       }
-
-       if ((pos < 0) || (pos > bptr->icount)) {
-               return -1;
-       }
-
-       if (count < 1) {
-               return -1;
-       }
-
-       bptr->iinstr = DMREALLOC(bptr->iinstr, instruction, bptr->icount, bptr->icount + count);
-
-       src = pos;
-       dst = pos + count;
-       num = bptr->icount - pos;
-
-       dst += num;
-       src += num;
-
-       while (num-- > 0) {
-               bptr->iinstr[--dst] = bptr->iinstr[--src];
-       }
-
-       MZERO(bptr->iinstr + pos, instruction, count);
-       bptr->icount += count;
-       
-       return 0;
-}
-
 ITERATOR_FUNC(in_vars_iter_func) {
        basicblock *bptr = (basicblock *)state->data;
        switch (op) {
@@ -1292,7 +1272,6 @@ CLASS_FUNC(basicblock_func) {
                                case F_OUT_VARS:
                                        return get_iter(arg->get.result, in_vars_iter_func, state->root, bptr);
                                case F_SHOW:
-                               case F_ADD_INSTRUCTIONS:
                                        arg->get.is_method = 1;
                                        return 0;
                        }
@@ -1304,9 +1283,6 @@ CLASS_FUNC(basicblock_func) {
                                case F_SHOW:
                                        show_basicblock(state->root->jd, bptr, SHOW_CFG);
                                        return 0;
-                               /* XXX remove */
-                               case F_ADD_INSTRUCTIONS:
-                                       return basicblock_add_instructions(bptr, arg->method_call.args);
                        }
        }
 
@@ -1526,6 +1502,10 @@ CLASS_FUNC(varinfo_func) {
                                        return get_int(arg->get.result, index);
                                case F_UNUSED:
                                        return get_bool(arg->get.result, index == UNUSED);
+                               case F_REGISTER_OFFSET:
+                                       return get_int(arg->get.result, var->vv.regoff);
+                               case F_IS_IN_MEMORY:
+                                       return get_bool(arg->get.result, var->flags & INMEMORY);
                        }
                case CLASS_SET_FIELD:
                        switch (arg->set.field) {
@@ -1575,6 +1555,10 @@ CLASS_FUNC(varinfo_func) {
                                                return 0;
                                        }
                                        break;
+                               case F_REGISTER_OFFSET:
+                                       return set_s4(&(var->vv.regoff), arg->set.value);
+                               case F_IS_IN_MEMORY:
+                                       return set_s4_flags(&(var->flags), INMEMORY, arg->set.value);
                        }
                case CLASS_STR:
                        *arg->str.result = varinfo_str(jd, index, var);
@@ -1618,25 +1602,16 @@ ITERATOR_FUNC(vars_iter_func) {
                case ITERATOR_LENGTH:
                        arg->length = jd->vartop;
                        return 0;
-               /* XXX remove grow */
                case ITERATOR_SUBSCRIPT:
-                       if (vars_grow(jd, arg->subscript.index + 1)) {
-                               if (jd->vartop < (arg->subscript.index + 1)) {
-                                       jd->vartop = (arg->subscript.index + 1);
-                               }
-                               return get_obj(arg->subscript.result, varinfo_func, 
-                                       state->root, jd->var + arg->subscript.index);
-                       }
+                       ITERATOR_SUBSCRIPT_CHECK(jd->vartop);
+                       return get_obj(arg->subscript.result, varinfo_func, 
+                               state->root, jd->var + arg->subscript.index);
                case ITERATOR_SETITEM:
-                       if (vars_grow(jd, arg->setitem.index + 1)) {
-                               if (jd->vartop < (arg->subscript.index + 1)) {
-                                       jd->vartop = (arg->subscript.index + 1);
-                               }
-                               vp = get_vp(arg->setitem.value, varinfo_func);
-                               if (vp) {
-                                       jd->var[arg->setitem.index] = *(varinfo *)vp;
-                                       return 0;
-                               }
+                       ITERATOR_SETITEM_CHECK(jd->vartop);
+                       vp = get_vp(arg->setitem.value, varinfo_func);
+                       if (vp) {
+                               jd->var[arg->setitem.index] = *(varinfo *)vp;
+                               return 0;
                        }
 
        }
@@ -1659,26 +1634,11 @@ ITERATOR_FUNC(map_2_iter_func) {
        return -1;
 }
 
-static inline void map_grow(s4 **pmap, s4 *pold_size, s4 new_size) {
-
-       int i;
-       s4 *map = *pmap;
-       s4 old_size = *pold_size;
-
-       if (new_size > old_size) {
-               *pmap = DMREALLOC(map, s4, old_size * 5, new_size * 5);
-               for (i = old_size * 5; i < (new_size * 5); ++i) {
-                       map[i] = UNUSED;
-               }
-               *pold_size = new_size;
-       }
-}
-
 ITERATOR_FUNC(local_map_iter_func) {
        jitdata *jd = (jitdata *)state->data;
        switch (op) {
                case ITERATOR_SUBSCRIPT:
-                       map_grow(&jd->local_map, &jd->maxlocals, arg->subscript.index + 1);
+                       ITERATOR_SUBSCRIPT_CHECK(jd->maxlocals);
                        return get_iter(arg->subscript.result, map_2_iter_func, state->root,
                                jd->local_map + (5 * arg->subscript.index));
        }
@@ -1689,8 +1649,7 @@ ITERATOR_FUNC(interface_map_iter_func) {
        jitdata *jd = (jitdata *)state->data;
        switch (op) {
                case ITERATOR_SUBSCRIPT:
-                       /* XXX remove grow */
-                       map_grow(&jd->interface_map, &jd->maxinterfaces, arg->subscript.index + 1);
+                       ITERATOR_SUBSCRIPT_CHECK(jd->maxinterfaces);
                        return get_iter(arg->subscript.result, map_2_iter_func, state->root,
                                jd->interface_map + (5 * arg->subscript.index));
        }