* src/vm/jit/jit.h (basicblock): Changed type of iinstr to
[cacao.git] / src / vm / jit / allocator / simplereg.c
index cf71e970762827125b347069cd3607ec9eae710c..0b28864ac97930d7a09fc8de52cd38c9eb4ad9fb 100644 (file)
 
    Changes: Stefan Ring
             Christian Thalinger
-                       Christian Ullrich
+            Christian Ullrich
             Michael Starzinger
-                       Edwin Steiner
+            Edwin Steiner
 
-   $Id: simplereg.c 4454 2006-02-06 00:02:50Z edwin $
+   $Id: simplereg.c 5321 2006-09-05 16:12:09Z edwin $
 
 */
 
 #include "vm/jit/reg.h"
 #include "vm/jit/allocator/simplereg.h"
 
-/* function prototypes for this file */
 
-static void interface_regalloc(methodinfo *m, codegendata *cd, registerdata *rd);
-static void local_regalloc(methodinfo *m, codegendata *cd, registerdata *rd);
-static void allocate_scratch_registers(methodinfo *m, registerdata *rd);
+/* function prototypes for this file ******************************************/
 
+static void interface_regalloc(jitdata *jd);
+static void local_regalloc(jitdata *jd);
+static void new_allocate_scratch_registers(jitdata *jd);
+static void allocate_scratch_registers(jitdata *jd);
 
-/* function interface_regalloc *************************************************
 
-       allocates registers for all interface variables
+/* regalloc ********************************************************************
+
+   Does a simple register allocation.
        
 *******************************************************************************/
        
-void regalloc(methodinfo *m, codegendata *cd, registerdata *rd)
+bool new_regalloc(jitdata *jd)
 {
-       interface_regalloc(m, cd, rd);
-       allocate_scratch_registers(m, rd);
-       local_regalloc(m, cd, rd);
+       /* There is a problem with the use of unused float argument
+          registers in leafmethods for stackslots on c7 (2 * Dual Core
+          AMD Opteron(tm) Processor 270) - runtime for the jvm98 _mtrt
+          benchmark is heaviliy increased. This could be prevented by
+          setting rd->argfltreguse to FLT_ARG_CNT before calling
+          allocate_scratch_registers and setting it back to the original
+          value before calling local_regalloc.  */
+
+       interface_regalloc(jd);
+       new_allocate_scratch_registers(jd);
+       local_regalloc(jd);
+
+       /* everthing's ok */
+
+       return true;
 }
 
 
-/* function interface_regalloc *************************************************
+/* interface_regalloc **********************************************************
 
-       allocates registers for all interface variables
+   Allocates registers for all interface variables.
        
 *******************************************************************************/
        
-static void interface_regalloc(methodinfo *m, codegendata *cd, registerdata *rd)
+static void interface_regalloc(jitdata *jd)
 {
+       methodinfo   *m;
+       codegendata  *cd;
+       registerdata *rd;
+
        int     s, t, tt, saved;
        int     intalloc, fltalloc; /* Remember allocated Register/Memory offset */
                      /* in case a more vars are packed into this interface slot */
@@ -94,8 +112,15 @@ static void interface_regalloc(methodinfo *m, codegendata *cd, registerdata *rd)
        /* on HAS_4BYTE_STACKSLOT architectures */
        int     typeloop[] = { TYPE_LNG, TYPE_DBL, TYPE_INT, TYPE_FLT, TYPE_ADR };
 
-       /* rd->memuse was already set in stack.c to allocate stack space for */
-       /* passing arguments to called methods                               */
+       /* get required compiler data */
+
+       m  = jd->m;
+       cd = jd->cd;
+       rd = jd->rd;
+
+       /* rd->memuse was already set in stack.c to allocate stack space
+          for passing arguments to called methods. */
+
 #if defined(__I386__)
        if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
                /* reserve 0(%esp) for Monitorenter/exit Argument on i386 */
@@ -104,7 +129,7 @@ static void interface_regalloc(methodinfo *m, codegendata *cd, registerdata *rd)
        }
 #endif
 
-       if (m->isleafmethod) {
+       if (jd->isleafmethod) {
                /* Reserve argument register, which will be used for Locals acting */
                /* as Parameters */
                if (rd->argintreguse < m->parseddesc->argintreguse)
@@ -139,7 +164,7 @@ static void interface_regalloc(methodinfo *m, codegendata *cd, registerdata *rd)
                                if (!saved) {
 #if defined(HAS_ADDRESS_REGISTER_FILE)
                                        if (IS_ADR_TYPE(t)) {
-                                               if (!m->isleafmethod 
+                                               if (!jd->isleafmethod 
                                                        &&(rd->argadrreguse < ADR_ARG_CNT)) {
                                                        v->regoff = rd->argadrregs[rd->argadrreguse++];
                                                } else if (rd->tmpadrreguse > 0) {
@@ -159,8 +184,7 @@ static void interface_regalloc(methodinfo *m, codegendata *cd, registerdata *rd)
                                                                v->flags |= rd->interfaces[s][fltalloc].flags
                                                                        & INMEMORY;
                                                                v->regoff = rd->interfaces[s][fltalloc].regoff;
-                                                       } else if (!m->isleafmethod 
-                                                                          && (rd->argfltreguse < FLT_ARG_CNT)) {
+                                                       } else if (rd->argfltreguse < FLT_ARG_CNT) {
                                                                v->regoff = rd->argfltregs[rd->argfltreguse++];
                                                        } else if (rd->tmpfltreguse > 0) {
                                                                v->regoff = rd->tmpfltregs[--rd->tmpfltreguse];
@@ -208,9 +232,8 @@ static void interface_regalloc(methodinfo *m, codegendata *cd, registerdata *rd)
                                                                                v->regoff = 
                                                                                    rd->interfaces[s][intalloc].regoff;
                                                                } else 
-                                                                       if (!m->isleafmethod && 
-                                                                               (rd->argintreguse 
-                                                                                + intregsneeded < INT_ARG_CNT)) {
+                                                                       if (rd->argintreguse + intregsneeded 
+                                                                               < INT_ARG_CNT) {
 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
                                                                                if (intregsneeded) 
                                                                                        v->regoff=PACK_REGS( 
@@ -361,15 +384,18 @@ static void interface_regalloc(methodinfo *m, codegendata *cd, registerdata *rd)
 }
 
 
+/* local_regalloc **************************************************************
 
-/* function local_regalloc *****************************************************
-
-       allocates registers for all local variables
+   Allocates registers for all local variables.
        
 *******************************************************************************/
        
-static void local_regalloc(methodinfo *m, codegendata *cd, registerdata *rd)
+static void local_regalloc(jitdata *jd)
 {
+       methodinfo   *m;
+       codegendata  *cd;
+       registerdata *rd;
+
        int     p, s, t, tt;
        int     intalloc, fltalloc;
        varinfo *v;
@@ -381,7 +407,13 @@ static void local_regalloc(methodinfo *m, codegendata *cd, registerdata *rd)
        int     aargcnt;
 #endif
 
-       if (m->isleafmethod) {
+       /* get required compiler data */
+
+       m  = jd->m;
+       cd = jd->cd;
+       rd = jd->rd;
+
+       if (jd->isleafmethod) {
                methoddesc *md = m->parseddesc;
 
                iargcnt = rd->argintreguse;
@@ -932,7 +964,10 @@ static void reg_new_temp_func(registerdata *rd, stackptr s)
 }
 
 
-#define reg_free_temp(rd,s) if (s->varkind == TEMPVAR) reg_free_temp_func(rd, s)
+#define reg_free_temp(rd,s) if (((s)->varkind == TEMPVAR) && (!((s)->flags & STCOPY))) reg_free_temp_func(rd, (s))
+
+/* Do not free regs/memory locations used by Stackslots flagged STCOPY! There is still another Stackslot */
+/* alive using this reg/memory location */
 
 static void reg_free_temp_func(registerdata *rd, stackptr s)
 {
@@ -966,23 +1001,23 @@ static void reg_free_temp_func(registerdata *rd, stackptr s)
 #ifdef HAS_ADDRESS_REGISTER_FILE
        } else if (IS_ADR_TYPE(s->type)) {
                if (s->flags & (SAVEDVAR | SAVEDTMP)) {
-                       s->flags &= ~SAVEDTMP;
+/*                     s->flags &= ~SAVEDTMP; */
                        rd->freesavadrregs[rd->freesavadrtop++] = s->regoff;
                } else
                        rd->freetmpadrregs[rd->freetmpadrtop++] = s->regoff;
 #endif
        } else if (IS_FLT_DBL_TYPE(s->type)) {
                if (s->flags & (SAVEDVAR | SAVEDTMP)) {
-                       s->flags &= ~SAVEDTMP;
+/*                     s->flags &= ~SAVEDTMP; */
                        rd->freesavfltregs[rd->freesavflttop++] = s->regoff;
                } else if (s->flags & TMPARG) {
-                       s->flags &= ~TMPARG;
+/*                     s->flags &= ~TMPARG; */
                        rd->freeargfltregs[rd->freeargflttop++] = s->regoff;
                } else
                        rd->freetmpfltregs[rd->freetmpflttop++] = s->regoff;
        } else { /* IS_INT_LNG_TYPE */
                if (s->flags & (SAVEDVAR | SAVEDTMP)) {
-                       s->flags &= ~SAVEDTMP;
+/*                     s->flags &= ~SAVEDTMP; */
 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
                        if (intregsneeded) {
                                rd->freesavintregs[rd->freesavinttop] =
@@ -995,7 +1030,7 @@ static void reg_free_temp_func(registerdata *rd, stackptr s)
                        rd->freesavinttop += intregsneeded + 1;
 
                } else if (s->flags & TMPARG) {
-                       s->flags &= ~TMPARG;
+/*                     s->flags &= ~TMPARG; */
 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
                        if (intregsneeded) {
                                rd->freeargintregs[rd->freearginttop] =
@@ -1021,45 +1056,170 @@ static void reg_free_temp_func(registerdata *rd, stackptr s)
        }
 }
 
+static bool reg_alloc_dup(stackptr src, stackptr dst) {
+       /* only copy TEMPVARS, do not mess with STACKVAR,      */
+       /* LOCALVAR, or ARGVAR        */
+       if ((src->varkind == TEMPVAR) && (dst->varkind == TEMPVAR)) {
+               /* can not allocate a REG_TMP to a REG_SAV Slot */
+               if (src->flags & INMEMORY) {
+                       dst->regoff  = src->regoff;
+                       dst->flags |= INMEMORY;
+                       return true;
+               } else if ((src->flags & SAVEDVAR) == (dst->flags & SAVEDVAR)) {
+                       dst->regoff  = src->regoff;
+                       dst->flags |= src->flags & SAVEDTMP;
+                       dst->flags |= src->flags & TMPARG;
+                       return true;
+#if 0
+               } else if ((dst->flags & SAVEDVAR) == 0) {
+                       /* can only use a REG_SAV as REG_TMP! */
+                       dst->regoff = src->regoff;
+                       dst->flags |= src->flags & TMPARG;
+                       dst->flags |= SAVEDTMP;
+                       return true;
+#endif
+               } 
+       }
+       /* no copy possible - allocate a new reg/memory location*/
+       return false;
+}
+
+/* Mark the copies (STCOPY) at the dst stack right for DUPx and SWAP */
+static void new_reg_mark_copy(registerdata *rd, stackptr *dupslots, 
+                                                         int nin, int nout, int nthrough)
+{
+       s4 src_regoff[4];
+       s4 src_flags[4];
+       stackptr dst_stackslots[6];
+       int s_bottom, d_bottom, i, j, slots;
+       bool found;
+       stackptr sp;
+       stackptr *argp;
+
+       assert(nin <= 4 && (nout + nthrough) <= 6);
+
+       /* remember all different Registers/Memory Location of used TEMPVAR       */
+       /* instacks in src_varnum[] and src_flags[] _uniquely_. Take the STCOPY   */
+       /* flag of the last (deepest) occurence */
+       slots = nin;
+       argp = dupslots + slots;
+       for (s_bottom = 4; slots--; ) {
+               sp = *--argp;
+               if (sp->varkind == TEMPVAR) {
+                       found = false;
+                       for (i = 3; i >= s_bottom; i--) {
+                               if ((src_regoff[i] == sp->regoff) && 
+                                       ((src_flags[i] & INMEMORY) == (sp->flags & INMEMORY)) ) 
+                               {
+                                       src_flags[i] &= (~STCOPY | (sp->flags & STCOPY));
+                                       found = true;
+                               }
+                       }
+                       if (!found) {
+                               s_bottom--;
+                               src_regoff[s_bottom] = sp->regoff;
+                               src_flags[s_bottom] = sp->flags;
+                       }
+               }
+       }
+
+       /* Remember used TEMPVAR dst Stackslots in dst_stackslots[], since they   */
+       /* have to be from the "lowest" upwards, and the stackelements list is    */
+       /* linked from only top downwards */
+       
+       slots = nthrough + nout;
+       argp = dupslots + nin + nout;
+       for (d_bottom = 6; slots--; ) {
+               sp = *--argp;
+               if (sp->varkind == TEMPVAR) {
+                       d_bottom--;
+                       dst_stackslots[d_bottom] = sp;
+               }
+       }
 
+       /* Mark all reused reg/mem in dst stacklots with STCOPY, if the           */
+       /* corresponding src stackslot was marked STCOPY*/
+       /* if the correspondig STCOPY from the src stackslot was not set, do not  */
+       /* mark the lowest occurence at dst stackslots */
+       /* mark in src_flag reg/mem with STKEEP, if they where reused in the dst  */
+       /* stacklots, so they are not freed afterwards */
+       for (i = d_bottom; i < 6; i++) {
+               for (j = s_bottom; j < 4; j++) {
+                       if ( (src_regoff[j] == dst_stackslots[i]->regoff) &&
+                                ((src_flags[j] & INMEMORY) == (dst_stackslots[i]->flags & INMEMORY)) ) 
+                       {
+                               if (src_flags[j] & STCOPY) {
+                                       dst_stackslots[i]->flags |= STCOPY;
+                               }
+                               else {
+                                       src_flags[j] |= STCOPY;
+                                       dst_stackslots[i]->flags &= ~STCOPY;
+                               }
+                               /* do not free reg/mem of src Stackslot */
+                               src_flags[j] |= STKEEP;
+                       }
+               }
+       }
 
-static void allocate_scratch_registers(methodinfo *m, registerdata *rd)
+       /* free all reg/mem of src stack, which where not marked with STKEEP */
+       for (j=s_bottom; j < 4; j++) {
+               if ((src_flags[j] & STKEEP)==0) {
+                       /* free, if STCOPY of src stackslot is not set */
+                       /* STCOPY is already checked in reg_free_temp macro! */
+                       slots = nin;
+                       argp = dupslots + slots;
+                       while (--slots) {
+                               sp = *--argp;
+                               if ((src_regoff[j] == sp->regoff) && 
+                                       ((src_flags[j] & INMEMORY) == (sp->flags & INMEMORY)) ) 
+                               {
+                                       reg_free_temp(rd, sp);
+                               }
+                       }
+               }
+       }
+}
+
+
+/* allocate_scratch_registers **************************************************
+
+   Allocate temporary (non-interface, non-local) registers.
+
+*******************************************************************************/
+
+static void new_allocate_scratch_registers(jitdata *jd)
 {
-       s4                  opcode;
+       methodinfo         *m;
+       registerdata       *rd;
        s4                  i;
        s4                  len;
-       stackptr            src;
-       stackptr            dst;
-       instruction        *iptr;
+       new_instruction    *iptr;
        basicblock         *bptr;
-       methodinfo         *lm;
        builtintable_entry *bte;
        methoddesc         *md;
+       stackptr           *argp;
+
+       /* get required compiler data */
+
+       m  = jd->m;
+       rd = jd->rd;
 
        /* initialize temp registers */
        reg_init_temp(m, rd);
 
-       bptr = m->basicblocks;
+       bptr = jd->new_basicblocks;
 
        while (bptr != NULL) {
                if (bptr->flags >= BBREACHED) {
-                       dst = bptr->instack;
-
-
                        iptr = bptr->iinstr;
                        len = bptr->icount;
 
                        while (--len >= 0)  {
-                               src = dst;
-                               dst = iptr->dst;
-                               opcode = iptr->opc;
-
-                               switch (opcode) {
+                               switch (iptr->opc) {
 
                                        /* pop 0 push 0 */
 
                                case ICMD_NOP:
-                               case ICMD_ELSE_ICONST:
                                case ICMD_CHECKNULL:
                                case ICMD_IINC:
                                case ICMD_JSR:
@@ -1087,7 +1247,7 @@ static void allocate_scratch_registers(methodinfo *m, registerdata *rd)
                                case ICMD_FLOAD:
                                case ICMD_DLOAD:
                                case ICMD_ALOAD:
-                                       reg_new_temp(rd, dst);
+                                       reg_new_temp(rd, iptr->dst.var);
                                        break;
 
                                        /* pop 2 push 1 */
@@ -1101,9 +1261,9 @@ static void allocate_scratch_registers(methodinfo *m, registerdata *rd)
                                case ICMD_BALOAD:
                                case ICMD_CALOAD:
                                case ICMD_SALOAD:
-                                       reg_free_temp(rd, src);
-                                       reg_free_temp(rd, src->prev);
-                                       reg_new_temp(rd, dst);
+                                       reg_free_temp(rd, iptr->sx.s23.s2.var);
+                                       reg_free_temp(rd, iptr->s1.var);
+                                       reg_new_temp(rd, iptr->dst.var);
                                        break;
 
                                        /* pop 3 push 0 */
@@ -1117,9 +1277,9 @@ static void allocate_scratch_registers(methodinfo *m, registerdata *rd)
                                case ICMD_BASTORE:
                                case ICMD_CASTORE:
                                case ICMD_SASTORE:
-                                       reg_free_temp(rd, src);
-                                       reg_free_temp(rd, src->prev);
-                                       reg_free_temp(rd, src->prev->prev);
+                                       reg_free_temp(rd, iptr->sx.s23.s3.var);
+                                       reg_free_temp(rd, iptr->sx.s23.s2.var);
+                                       reg_free_temp(rd, iptr->s1.var);
                                        break;
 
                                        /* pop 1 push 0 store */
@@ -1171,7 +1331,7 @@ static void allocate_scratch_registers(methodinfo *m, registerdata *rd)
 
                                case ICMD_MONITORENTER:
                                case ICMD_MONITOREXIT:
-                                       reg_free_temp(rd, src);
+                                       reg_free_temp(rd, iptr->s1.var);
                                        break;
 
                                        /* pop 2 push 0 branch */
@@ -1190,6 +1350,32 @@ static void allocate_scratch_registers(methodinfo *m, registerdata *rd)
                                case ICMD_IF_LCMPGT:
                                case ICMD_IF_LCMPLE:
 
+                               case ICMD_IF_FCMPEQ:
+                               case ICMD_IF_FCMPNE:
+
+                               case ICMD_IF_FCMPL_LT:
+                               case ICMD_IF_FCMPL_GE:
+                               case ICMD_IF_FCMPL_GT:
+                               case ICMD_IF_FCMPL_LE:
+
+                               case ICMD_IF_FCMPG_LT:
+                               case ICMD_IF_FCMPG_GE:
+                               case ICMD_IF_FCMPG_GT:
+                               case ICMD_IF_FCMPG_LE:
+
+                               case ICMD_IF_DCMPEQ:
+                               case ICMD_IF_DCMPNE:
+
+                               case ICMD_IF_DCMPL_LT:
+                               case ICMD_IF_DCMPL_GE:
+                               case ICMD_IF_DCMPL_GT:
+                               case ICMD_IF_DCMPL_LE:
+
+                               case ICMD_IF_DCMPG_LT:
+                               case ICMD_IF_DCMPG_GE:
+                               case ICMD_IF_DCMPG_GT:
+                               case ICMD_IF_DCMPG_LE:
+
                                case ICMD_IF_ACMPEQ:
                                case ICMD_IF_ACMPNE:
 
@@ -1205,80 +1391,131 @@ static void allocate_scratch_registers(methodinfo *m, registerdata *rd)
                                case ICMD_BASTORECONST:
                                case ICMD_CASTORECONST:
                                case ICMD_SASTORECONST:
-                                       reg_free_temp(rd, src);
-                                       reg_free_temp(rd, src->prev);
+                                       reg_free_temp(rd, iptr->sx.s23.s2.var);
+                                       reg_free_temp(rd, iptr->s1.var);
                                        break;
 
                                        /* pop 0 push 1 dup */
                                        
                                case ICMD_DUP:
-                                       reg_new_temp(rd, dst);
+                                       /* src === dst->prev (identical Stackslot Element)     */
+                                       /* src --> dst       (copied value, take same reg/mem) */
+
+                                       if (!reg_alloc_dup(iptr->s1.var, iptr->dst.var)) {
+                                               reg_new_temp(rd, iptr->dst.var);
+                                       } else {
+                                               iptr->dst.var->flags |= STCOPY;
+                                       }
                                        break;
 
                                        /* pop 0 push 2 dup */
                                        
                                case ICMD_DUP2:
-                                       reg_new_temp(rd, dst->prev);
-                                       reg_new_temp(rd, dst);
+                                       /* src->prev === dst->prev->prev->prev (identical Stackslot Element)     */
+                                       /* src       === dst->prev->prev       (identical Stackslot Element)     */
+                                       /* src->prev --> dst->prev             (copied value, take same reg/mem) */
+                                       /* src       --> dst                   (copied value, take same reg/mem) */
+                                                                                               
+                                       if (!reg_alloc_dup(iptr->dst.dupslots[0], iptr->dst.dupslots[2+0]))
+                                               reg_new_temp(rd, iptr->dst.dupslots[2+0]);
+                                       if (!reg_alloc_dup(iptr->dst.dupslots[1], iptr->dst.dupslots[2+1]))
+                                               reg_new_temp(rd, iptr->dst.dupslots[2+1]);
+                                       new_reg_mark_copy(rd, iptr->dst.dupslots, 2, 2, 2);
                                        break;
 
                                        /* pop 2 push 3 dup */
                                        
                                case ICMD_DUP_X1:
-                                       reg_free_temp(rd, src);
-                                       reg_new_temp(rd, dst);
-                                       reg_free_temp(rd, src->prev);
-                                       reg_new_temp(rd, dst->prev);
-                                       reg_new_temp(rd, dst->prev->prev);
+                                       /* src->prev --> dst->prev       (copied value, take same reg/mem) */
+                                       /* src       --> dst             (copied value, take same reg/mem) */
+                                       /* src       --> dst->prev->prev (copied value, take same reg/mem) */
+                                                                                               
+                                       if (!reg_alloc_dup(iptr->dst.dupslots[1], iptr->dst.dupslots[2+0]))
+                                               reg_new_temp(rd, iptr->dst.dupslots[2+0]);
+                                       if (!reg_alloc_dup(iptr->dst.dupslots[1], iptr->dst.dupslots[2+2]))
+                                               reg_new_temp(rd, iptr->dst.dupslots[2+2]);
+                                       if (!reg_alloc_dup(iptr->dst.dupslots[0], iptr->dst.dupslots[2+1]))
+                                               reg_new_temp(rd, iptr->dst.dupslots[2+1]);
+                                       new_reg_mark_copy(rd, iptr->dst.dupslots, 2, 3, 0);
                                        break;
 
                                        /* pop 3 push 4 dup */
                                        
                                case ICMD_DUP_X2:
-                                       reg_free_temp(rd, src);
-                                       reg_new_temp(rd, dst);
-                                       reg_free_temp(rd, src->prev);
-                                       reg_new_temp(rd, dst->prev);
-                                       reg_free_temp(rd, src->prev->prev);
-                                       reg_new_temp(rd, dst->prev->prev);
-                                       reg_new_temp(rd, dst->prev->prev->prev);
+                                       /* src->prev->prev --> dst->prev->prev        */
+                                       /* src->prev       --> dst->prev              */
+                                       /* src             --> dst                    */
+                                       /* src             --> dst->prev->prev->prev  */
+                                       
+                                       if (!reg_alloc_dup(iptr->dst.dupslots[2], iptr->dst.dupslots[3+0]))
+                                               reg_new_temp(rd, iptr->dst.dupslots[3+0]);
+                                       if (!reg_alloc_dup(iptr->dst.dupslots[2], iptr->dst.dupslots[3+3]))
+                                               reg_new_temp(rd, iptr->dst.dupslots[3+3]);
+                                       if (!reg_alloc_dup(iptr->dst.dupslots[1], iptr->dst.dupslots[3+2]))
+                                               reg_new_temp(rd, iptr->dst.dupslots[3+2]);
+                                       if (!reg_alloc_dup(iptr->dst.dupslots[0], iptr->dst.dupslots[3+1]))
+                                               reg_new_temp(rd, iptr->dst.dupslots[3+1]);
+                                       new_reg_mark_copy(rd, iptr->dst.dupslots, 3, 4, 0);
                                        break;
 
                                        /* pop 3 push 5 dup */
                                        
                                case ICMD_DUP2_X1:
-                                       reg_free_temp(rd, src);
-                                       reg_new_temp(rd, dst);
-                                       reg_free_temp(rd, src->prev);
-                                       reg_new_temp(rd, dst->prev);
-                                       reg_free_temp(rd, src->prev->prev);
-                                       reg_new_temp(rd, dst->prev->prev);
-                                       reg_new_temp(rd, dst->prev->prev->prev);
-                                       reg_new_temp(rd, dst->prev->prev->prev->prev);
+                                       /* src->prev->prev --> dst->prev->prev             */
+                                       /* src->prev       --> dst->prev                   */
+                                       /* src             --> dst                         */
+                                       /* src->prev       --> dst->prev->prev->prev->prev */
+                                       /* src             --> dst->prev->prev->prev       */
+                                                                                               
+                                       if (!reg_alloc_dup(iptr->dst.dupslots[2], iptr->dst.dupslots[3+1]))
+                                               reg_new_temp(rd, iptr->dst.dupslots[3+1]);
+                                       if (!reg_alloc_dup(iptr->dst.dupslots[2], iptr->dst.dupslots[3+4]))
+                                               reg_new_temp(rd, iptr->dst.dupslots[3+4]);
+                                       if (!reg_alloc_dup(iptr->dst.dupslots[1], iptr->dst.dupslots[3+0]))
+                                               reg_new_temp(rd, iptr->dst.dupslots[3+0]);
+                                       if (!reg_alloc_dup(iptr->dst.dupslots[1], iptr->dst.dupslots[3+3]))
+                                               reg_new_temp(rd, iptr->dst.dupslots[3+3]);
+                                       if (!reg_alloc_dup(iptr->dst.dupslots[0], iptr->dst.dupslots[3+2]))
+                                               reg_new_temp(rd, iptr->dst.dupslots[3+2]);
+                                       new_reg_mark_copy(rd, iptr->dst.dupslots, 3, 5, 0);
                                        break;
 
                                        /* pop 4 push 6 dup */
                                        
                                case ICMD_DUP2_X2:
-                                       reg_free_temp(rd, src);
-                                       reg_new_temp(rd, dst);
-                                       reg_free_temp(rd, src->prev);
-                                       reg_new_temp(rd, dst->prev);
-                                       reg_free_temp(rd, src->prev->prev);
-                                       reg_new_temp(rd, dst->prev->prev);
-                                       reg_free_temp(rd, src->prev->prev->prev);
-                                       reg_new_temp(rd, dst->prev->prev->prev);
-                                       reg_new_temp(rd, dst->prev->prev->prev->prev);
-                                       reg_new_temp(rd, dst->prev->prev->prev->prev->prev);
+                                       /* src->prev->prev->prev --> dst->prev->prev->prev             */
+                                       /* src->prev->prev       --> dst->prev->prev                   */
+                                       /* src->prev             --> dst->prev                         */
+                                       /* src                   --> dst                               */
+                                       /* src->prev             --> dst->prev->prev->prev->prev->prev */
+                                       /* src                   --> dst->prev->prev->prev->prev       */
+                                                                                               
+                                       if (!reg_alloc_dup(iptr->dst.dupslots[3], iptr->dst.dupslots[4+1]))
+                                               reg_new_temp(rd, iptr->dst.dupslots[4+1]);
+                                       if (!reg_alloc_dup(iptr->dst.dupslots[3], iptr->dst.dupslots[4+5]))
+                                               reg_new_temp(rd, iptr->dst.dupslots[4+5]);
+                                       if (!reg_alloc_dup(iptr->dst.dupslots[2], iptr->dst.dupslots[4+0]))
+                                               reg_new_temp(rd, iptr->dst.dupslots[4+0]);
+                                       if (!reg_alloc_dup(iptr->dst.dupslots[2], iptr->dst.dupslots[4+4]))
+                                               reg_new_temp(rd, iptr->dst.dupslots[4+4]);
+                                       if (!reg_alloc_dup(iptr->dst.dupslots[1], iptr->dst.dupslots[4+3]))
+                                               reg_new_temp(rd, iptr->dst.dupslots[4+3]);
+                                       if (!reg_alloc_dup(iptr->dst.dupslots[0], iptr->dst.dupslots[4+2]))
+                                               reg_new_temp(rd, iptr->dst.dupslots[4+2]);
+                                       new_reg_mark_copy(rd, iptr->dst.dupslots, 4, 6, 0);
                                        break;
 
                                        /* pop 2 push 2 swap */
                                        
                                case ICMD_SWAP:
-                                       reg_free_temp(rd, src);
-                                       reg_new_temp(rd, dst->prev);
-                                       reg_free_temp(rd, src->prev);
-                                       reg_new_temp(rd, dst);
+                                       /* src       --> dst->prev   (copy) */
+                                       /* src->prev --> dst         (copy) */
+                                                                                               
+                                       if (!reg_alloc_dup(iptr->dst.dupslots[1], iptr->dst.dupslots[2+0]))
+                                               reg_new_temp(rd, iptr->dst.dupslots[2+0]);
+                                       if (!reg_alloc_dup(iptr->dst.dupslots[0], iptr->dst.dupslots[2+1]))
+                                               reg_new_temp(rd, iptr->dst.dupslots[2+1]);
+                                       new_reg_mark_copy(rd, iptr->dst.dupslots, 2, 2, 0);
                                        break;
 
                                        /* pop 2 push 1 */
@@ -1327,9 +1564,9 @@ static void allocate_scratch_registers(methodinfo *m, registerdata *rd)
                                case ICMD_FCMPG:
                                case ICMD_DCMPL:
                                case ICMD_DCMPG:
-                                       reg_free_temp(rd, src);
-                                       reg_free_temp(rd, src->prev);
-                                       reg_new_temp(rd, dst);
+                                       reg_free_temp(rd, iptr->sx.s23.s2.var);
+                                       reg_free_temp(rd, iptr->s1.var);
+                                       reg_new_temp(rd, iptr->dst.var);
                                        break;
 
                                        /* pop 1 push 1 */
@@ -1360,13 +1597,6 @@ static void allocate_scratch_registers(methodinfo *m, registerdata *rd)
                                case ICMD_LSHRCONST:
                                case ICMD_LUSHRCONST:
 
-                               case ICMD_IFEQ_ICONST:
-                               case ICMD_IFNE_ICONST:
-                               case ICMD_IFLT_ICONST:
-                               case ICMD_IFGE_ICONST:
-                               case ICMD_IFGT_ICONST:
-                               case ICMD_IFLE_ICONST:
-
                                case ICMD_INEG:
                                case ICMD_INT2BYTE:
                                case ICMD_INT2CHAR:
@@ -1397,8 +1627,8 @@ static void allocate_scratch_registers(methodinfo *m, registerdata *rd)
                                case ICMD_ANEWARRAY:
 
                                case ICMD_GETFIELD:
-                                       reg_free_temp(rd, src);
-                                       reg_new_temp(rd, dst);
+                                       reg_free_temp(rd, iptr->s1.var);
+                                       reg_new_temp(rd, iptr->dst.var);
                                        break;
 
                                        /* pop 0 push 1 */
@@ -1406,7 +1636,7 @@ static void allocate_scratch_registers(methodinfo *m, registerdata *rd)
                                case ICMD_GETSTATIC:
 
                                case ICMD_NEW:
-                                       reg_new_temp(rd, dst);
+                                       reg_new_temp(rd, iptr->dst.var);
                                        break;
 
                                        /* pop many push any */
@@ -1415,42 +1645,38 @@ static void allocate_scratch_registers(methodinfo *m, registerdata *rd)
                                case ICMD_INVOKESPECIAL:
                                case ICMD_INVOKEVIRTUAL:
                                case ICMD_INVOKEINTERFACE:
-                                       lm = iptr->val.a;
-
-                                       if (lm)
-                                               md = lm->parseddesc;
-                                       else {
-                                               unresolved_method *um = iptr->target;
-                                               md = um->methodref->parseddesc.md;
-                                       }
+                                       INSTRUCTION_GET_METHODDESC(iptr,md);
                                        i = md->paramcount;
+                                       argp = iptr->sx.s23.s2.args;
                                        while (--i >= 0) {
-                                               reg_free_temp(rd, src);
-                                               src = src->prev;
+                                               reg_free_temp(rd, *argp);
+                                               argp++;
                                        }
                                        if (md->returntype.type != TYPE_VOID)
-                                               reg_new_temp(rd, dst);
+                                               reg_new_temp(rd, iptr->dst.var);
                                        break;
 
                                case ICMD_BUILTIN:
-                                       bte = iptr->val.a;
+                                       bte = iptr->sx.s23.s3.bte;
                                        md = bte->md;
                                        i = md->paramcount;
+                                       argp = iptr->sx.s23.s2.args;
                                        while (--i >= 0) {
-                                               reg_free_temp(rd, src);
-                                               src = src->prev;
+                                               reg_free_temp(rd, *argp);
+                                               argp++;
                                        }
                                        if (md->returntype.type != TYPE_VOID)
-                                               reg_new_temp(rd, dst);
+                                               reg_new_temp(rd, iptr->dst.var);
                                        break;
 
                                case ICMD_MULTIANEWARRAY:
-                                       i = iptr->op1;
+                                       i = iptr->s1.argcount;
+                                       argp = iptr->sx.s23.s2.args;
                                        while (--i >= 0) {
-                                               reg_free_temp(rd, src);
-                                               src = src->prev;
+                                               reg_free_temp(rd, *argp);
+                                               argp++;
                                        }
-                                       reg_new_temp(rd, dst);
+                                       reg_new_temp(rd, iptr->dst.var);
                                        break;
 
                                default:
@@ -1468,7 +1694,11 @@ static void allocate_scratch_registers(methodinfo *m, registerdata *rd)
 
 
 #if defined(ENABLE_STATISTICS)
-void reg_make_statistics( methodinfo *m, codegendata *cd, registerdata *rd) {
+void reg_make_statistics(jitdata *jd)
+{
+       methodinfo   *m;
+       codegendata  *cd;
+       registerdata *rd;
        int i,type;
        s4 len;
        stackptr    src, src_old;
@@ -1478,6 +1708,12 @@ void reg_make_statistics( methodinfo *m, codegendata *cd, registerdata *rd) {
        int size_interface; /* == maximum size of in/out stack at basic block boundaries */
        bool in_register;
 
+       /* get required compiler data */
+
+       m  = jd->m;
+       cd = jd->cd;
+       rd = jd->rd;
+
        in_register = true;
 
        size_interface = 0;
@@ -1499,7 +1735,7 @@ void reg_make_statistics( methodinfo *m, codegendata *cd, registerdata *rd) {
                while (bptr != NULL) {
                        if (bptr->flags >= BBREACHED) {
 
-#if defined(ENABLE_LSRA)
+#if defined(ENABLE_LSRA) || defined(ENABLE_SSA)
                        if (!opt_lsra) {
 #endif 
                                /* check for memory moves from interface to BB instack */
@@ -1548,7 +1784,7 @@ void reg_make_statistics( methodinfo *m, codegendata *cd, registerdata *rd) {
 
                                        dst = dst->prev;
                                }
-#if defined(ENABLE_LSRA)
+#if defined(ENABLE_LSRA) || defined(ENABLE_SSA)
                        }
 #endif 
 
@@ -1615,6 +1851,9 @@ void reg_make_statistics( methodinfo *m, codegendata *cd, registerdata *rd) {
                } /* while blocks */
                count_interface_size += size_interface; /* accummulate the size of the interface (between bb boundaries) */
                if (in_register) count_method_in_register++;
+               if (in_register) {
+                       printf("INREGISTER: %s%s%s\n",m->class->name->text, m->name->text, m->descriptor->text);
+               }
 }
 #endif /* defined(ENABLE_STATISTICS) */