*** empty log message ***
authorchristian <none@none>
Sun, 28 Nov 2004 16:37:23 +0000 (16:37 +0000)
committerchristian <none@none>
Sun, 28 Nov 2004 16:37:23 +0000 (16:37 +0000)
jit/lsra.h
jit/lsra.inc
src/vm/jit/lsra.h
src/vm/jit/lsra.inc

index f40ec07d9523ffd6359df4c6a5c81554d6dcf545..e4b59d2d0da633c55c9051fe46a0a086486064b9 100644 (file)
@@ -27,7 +27,7 @@
 
    Authors: Christian Ullrich
 
-   $Id: lsra.h 1590 2004-11-25 13:24:49Z christian $
+   $Id: lsra.h 1597 2004-11-28 16:37:23Z christian $
 
 */
 
 #define LSRA_POP -1
 
 struct lifetime {
-       int   index; /* unique index, LOCALVAR varnum or negative*/
-       int   b_start; /* bb of first use */
-       int   b_end;   /* bb of last use */
        int i_start; /* instruction number of first use */
        int i_end; /* instruction number of last use */
-       int length; /* lifetime in instructions */
-       stackptr s; /* stackslot or NULL */
-       int v_index; /* local variable index or -1 */
+       int v_index; /* local variable index or negative for stackslots */
        int type;
-       int usagecount; /* number of refernces*/
+       int usagecount; /* number of references*/
        int reg; /* regoffset durch lsra zugewiesen */
        int savedvar;
        struct stackslot *passthrough; /* List of Stackslots in Lifetime, which are passed through a Basic Block */
-       struct stackslot *local_ss;
+       struct stackslot *local_ss; /* Stackslots for this Lifetime or NULL (=="pure" Local Var) */
        struct _i_list *i_list; /* list of instructions with references to var */
        struct lifetime *next;
 };
 
-/* struct int_list { */
-/*     int value; */
-/*     int_list *next; */
-/* }; */
-
 struct active_lt {
        struct lifetime *lt;
        struct active_lt *next;
@@ -116,10 +106,9 @@ struct freemem {
        struct freemem *next;
 };
 
-struct sss {
-       int bb;
-       bool out;
-       struct sss *next;
+struct dup {
+       struct stackslot *ss;
+       struct dup *next;
 };
 
 typedef struct lsradata lsradata;
@@ -133,6 +122,8 @@ void lsra_clean_Graph( methodinfo *, codegendata *, lsradata *, loopdata *);
 #ifdef LSRA_DEBUG
 void lsra_dump_Graph(methodinfo *, struct depthElement **);
 void lsra_dump_stack(stackptr );
+#endif
+#ifdef LSRA_PRINTLIFETIMES
 void print_lifetimes(registerdata *, struct lifetime *);
 #endif
 
@@ -143,8 +134,9 @@ int lsra_getmaxblock(methodinfo *, loopdata *, int );
 void lsra_calc_lifetime_length(methodinfo *, lsradata *, codegendata *, loopdata *);
 
 void lsra_merge_i_lists(struct lifetime *, struct lifetime *);
+void lsra_merge_local_ss(struct lifetime *, struct lifetime *);
 
-void _lsra_new_stack( lsradata *, stackptr , int , int , int);
+void _lsra_new_stack( lsradata *, stackptr , int , int, int);
 void _lsra_from_stack(lsradata *, stackptr , int , int, int);
 void lsra_add_ss(struct lifetime *, stackptr );
 void lsra_usage_local(lsradata *, s4 , int , int , int , int );
index 8202c285c05301bac9294d0e8a26eb79888f72f9..ba756aa7ae5b3f3295e3b9a54cf83594cf13cd3f 100644 (file)
 
    Authors: Christian Ullrich
 
-   $Id: lsra.inc 1590 2004-11-25 13:24:49Z christian $
+   $Id: lsra.inc 1597 2004-11-28 16:37:23Z christian $
 
 */
 
 /* #define LSRA_DEBUG */
 /* #define LSRA_SAVEDVAR */
 /* #define LSRA_MEMORY */
+/* #define LSRA_PRINTLIFETIMES */
+
+
+#ifdef LSRA_DEBUG
+#define LSRA_PRINTLIFETIMES
+#endif
 
 #include "lsra.h"
 #include "loop/graph.h"
@@ -63,7 +69,7 @@ void lsra(methodinfo *m, codegendata *cd, registerdata *rd, loopdata *ld, t_inli
 
        printf("LSRA Start for %s\n", name); 
 
-       if (strcmp(name,"at/dms/kjc/CSourceClassgenCode(Lat/dms/kjc/BytecodeOptimizer;Ljava/lang/String;Lat/dms/kjc/TypeFactory;)V")==0) {
+       if (strcmp(name,"java/lang/SysteminitProperties()V")==0) {
                printf("-------------------\n");
        }
 #endif
@@ -95,7 +101,6 @@ void lsra_init(methodinfo *m, codegendata *cd, t_inlining_globals *id, lsradata
        for (i=0; i < cd->maxlocals; i++) ls->locals_lifetimes[i]=NULL;
        ls->lifetimes=NULL;
        ls->stackslots=NULL;
-       ls->var_index=-1;
 }
 
 void lsra_setup(methodinfo *m, codegendata *cd, registerdata *rd, lsradata *ls, loopdata *ld)
@@ -108,6 +113,7 @@ void lsra_setup(methodinfo *m, codegendata *cd, registerdata *rd, lsradata *ls,
        struct lifetime *lt, *n;
        int v_index;
        struct stackslot *ss;
+       bool drop;
        
        /* Setup LSRA Data structures */
        if (opt_loops) panic("lsra with -oloop not possible!\n");
@@ -168,8 +174,9 @@ void lsra_setup(methodinfo *m, codegendata *cd, registerdata *rd, lsradata *ls,
 
        v_index=-1;
 
+       /* ls->lifetimes contains only the joined stackslotlifetimes */
        for (lt=ls->lifetimes; lt != NULL; lt=lt->next) {
-               lt->index=v_index;
+               lt->v_index=v_index;
 #ifdef LSRA_SAVEDVAR
                lt->savedvar=SAVEDVAR;
 #endif
@@ -179,15 +186,7 @@ void lsra_setup(methodinfo *m, codegendata *cd, registerdata *rd, lsradata *ls,
                }
        }
 
-       for (i=0; i < cd->maxlocals; i++) {
-               for (lt=ls->locals_lifetimes[i]; lt != NULL; lt=lt->next) {
-/*                     lt->local_ss=NULL; */
-#ifdef LSRA_SAVEDVAR
-                       lt->savedvar=SAVEDVAR;
-#endif
-               }
-       }
-
+       /* add ss_lifetimes[i] to ls->lifetimes or local_lifetimes[lt->s->varnum] */
        for (i=0; i < m->basicblockcount; i++) {
                if (m->basicblocks[i].flags >= BBREACHED) {
                        for (; ls->ss_lifetimes[i] != NULL;) {
@@ -195,48 +194,48 @@ void lsra_setup(methodinfo *m, codegendata *cd, registerdata *rd, lsradata *ls,
 #ifdef LSRA_SAVEDVAR
                                lt->savedvar=SAVEDVAR;
 #endif
-                               if (lt->s->varkind == LOCALVAR) {
-                                       /* join with LOCALVAR */
-                                       /* local Lifetime vom richtigen Type suchen */
-                                       for (n=ls->locals_lifetimes[lt->s->varnum]; (n!=NULL) && (n->type!=lt->s->type);n=n->next);
 #ifdef LSRA_DEBUG
-                                       if (n == NULL) panic("lsra_setup: Local Var not found\n");
+                               if (lt->local_ss == NULL) panic("lsra_setup: normal Stackslot Lifetimes local_ss == NULL\n");
 #endif
-                                       lsra_merge_i_lists(n, lt);
-                                       ss=DNEW(struct stackslot);
-                                       ss->s=lt->s;
-                                       ss->next=n->local_ss;
-                                       n->local_ss=ss;
-
-                                       ls->ss_lifetimes[i]=lt->next;
-                               } else {
-#ifdef LSRA_DEBUG
-                                       if (lt->s == NULL) panic("lsra_setup: Wrong assumption about Stackslot Lifetimes -> s\n");
-
-#endif
-                                       if ((lt->s != NULL) && (lt->s->varkind != ARGVAR)) {
-                                               if (lt->s->varkind != ARGVAR) {
-                                                       lt->s->varkind=TEMPVAR;
-                                                       lt->s->varnum=v_index;
+                               drop=false;
+                               for (ss=lt->local_ss; (ss!=NULL) && (!drop); ss=ss->next) {
+                                       if (lt->local_ss->next == NULL) { /* only one Stackslot in local_ss */
+                                               /* Special Treatment for "lonely" LOCAL and ARGVARs */
+                                               if (ss->s->varkind == LOCALVAR) {
+                                                       /* join with LOCALVAR */
+                                                       /* local Lifetime vom richtigen Type suchen */
+                                                       for (n=ls->locals_lifetimes[lt->local_ss->s->varnum]; (n!=NULL) && (n->type!=lt->local_ss->s->type);n=n->next);
+                                                       lsra_merge_i_lists(n, lt);
+                                                       if (n->local_ss == NULL)  /* "pure" Local without Stackslots */
+                                                               n->local_ss = lt->local_ss;
+                                                       else
+                                                               lsra_merge_local_ss(n, lt);
+
+                                                       drop = true;
                                                }
-                                               lt->index=lt->v_index=v_index;
-                                               for (ss=lt->local_ss; ss!=NULL; ss=ss->next) {
-                                                       ss->s->varnum=v_index;
-                                                       lt->s->varkind=TEMPVAR;
+                                               if (lt->local_ss->s->varkind == ARGVAR) {
+                                                       drop = true;
                                                }
-                                               
-                                               ls->ss_lifetimes[i]=lt->next;
-                                               lt->next=ls->lifetimes;
-                                               ls->lifetimes=lt;
-                                       } else {
-                                               ls->ss_lifetimes[i]=lt->next;
+                                       } else { 
+                                               /* no special treatment (only one Stackslot Lifetimes)? */
+                                               ss->s->varnum=v_index;
+                                               ss->s->varkind=TEMPVAR; /* only TEMPVAR possible for now */
                                        }
-                                       --v_index;
-                               }               
+                               }
+                               if (drop)
+                                       ls->ss_lifetimes[i]=lt->next;
+                               else {
+                                       /* link into ls->lifetimes */
+                                       ls->ss_lifetimes[i]=lt->next;
+                                       lt->next=ls->lifetimes;
+                                       ls->lifetimes=lt;
+                                       lt->v_index=v_index--;
+                               }
                        } /* for */
                } /* if */
        }
 
+       /* add local_lifetimes to lifetimes */
        for (i=0; i < cd->maxlocals; i++) {
                if (ls->locals_lifetimes[i] != NULL) {
                        for (lt=ls->locals_lifetimes[i]; lt->next != NULL; lt=lt->next);
@@ -286,10 +285,7 @@ void lsra_clean_Graph( methodinfo *m, codegendata *cd, lsradata *ls, loopdata *l
        exceptiontable *ex;
        struct depthElement **table;
        bool back_edge;
-#ifdef LSRA_DEBUG
        struct LoopContainer *lc;
-       struct LoopElement *le;
-#endif
 
        table=ld->c_dTable;
 
@@ -304,16 +300,8 @@ void lsra_clean_Graph( methodinfo *m, codegendata *cd, lsradata *ls, loopdata *l
 #endif
 
        for (; ex != NULL; ex = ex->down) {
-#ifdef LSRA_DEBUG
-               if (ex->handler == NULL) {
-                       panic("lsra_init_blocks EXCEPTIONTABLE without handler!\n");
-               } 
-#endif
-#ifdef LSRA_DEBUG
-               if ((ex->handler->debug_nr < 0) || (ex->handler->debug_nr >= m->basicblockcount)) {
-                       panic("lsra_init_blocks EXCEPTIONTABLE Handler Blocknummer invalid! \n");
-               }
 
+#ifdef LSRA_DEBUG
                printf("%i ",ex->handler->debug_nr);
 #endif
                dF(m, ld, -1, ex->handler->debug_nr);
@@ -336,24 +324,12 @@ void lsra_clean_Graph( methodinfo *m, codegendata *cd, lsradata *ls, loopdata *l
        }
 
        back_edge=false;
-#ifdef LSRA_DEBUG
-       printf("\n Cleaning c_dTable ");
-#endif
        for(i=0; i < m->basicblockcount; i++) {
-#ifdef LSRA_DEBUG
-               printf("\n %i-",i);
-#endif
                if (m->basicblocks[i].flags < BBREACHED) {
-#ifdef LSRA_DEBUG
-                       printf("deleted\n");
-#endif
                        table[i]=NULL;
                } else {
                        for (de=table[i]; de != NULL; de=de->next) {
                                if (de->value < i) back_edge=true;
-#ifdef LSRA_DEBUG
-                               printf("%i-%i ",de->value, bb_succ[de->value]);
-#endif
                                if (bb_succ[de->value] != de->value)
                                        de->value = bb_succ[de->value];
                                if (de->value == -1) panic("lsra_clean_Graph: Sprung ins nichts....");
@@ -369,37 +345,44 @@ void lsra_clean_Graph( methodinfo *m, codegendata *cd, lsradata *ls, loopdata *l
                        /* TODO bis dahin eine loop über die backedge eintragen            */
                        /*      anstatt back_edge_panic zu setzen und alle Lifetimes über die */
                        /*      gesamt Methode auszudehnen                                    */
-                       ls->back_edge_panic = true;
-               }
-       }
+/*                     ls->back_edge_panic = true; */
+
+                       /* create loops from all back edges */
+                       
+                       for(i=0; i < m->basicblockcount; i++) {
+                               if (m->basicblocks[i].flags >= BBREACHED) {
+                                       for (de=table[i]; de != NULL; de=de->next) {
+                                               if (de->value < i) {
+                                                       if (ld->c_allLoops == NULL) {
+                                                               ld->c_allLoops = lc = DNEW(struct LoopContainer);
+                                                       } else {
+                                                               lc->next=DNEW(struct LoopContainer);
+                                                               lc=lc->next;
+                                                       }
+                                                       lc->nodes=DNEW(struct LoopElement);
+                                                       lc->nodes->next=DNEW(struct LoopElement);
+                                                       lc->nodes->next->next=NULL;
+
+                                                       lc->nodes->block=&(m->basicblocks[i]);
+                                                       lc->nodes->next->block=&(m->basicblocks[de->value]);
+                                                       lc->next = NULL;
+                                               }
+                                       }
+                               }
+                       }
 #ifdef LSRA_DEBUG
-       if (back_edge) {
-               if ( ld->c_allLoops == NULL ) {
                        printf("-------------Warnung Back Edge + no LOOP..\n");
+#endif
                }
-               else
-                       printf("Back-edges + Loops:\n");
-               lc = ld->c_allLoops;
-               i = 0;
-               while (lc != NULL) {
-                       printf("Loop [%d]: ", ++i);
-                       le = lc->nodes;
-                       while (le != NULL) {
-                               printf("%d ", le->node);
-                               printf("\n");
-                               le = le->next;
-                       }
-                       lc = lc->next;
-               }
-               printf("\n");
        }
-#endif
 
        bb_visited=DMNEW(int, m->basicblockcount);
        for (i=0; i<m->basicblockcount; i++) {
                bb_visited[i]=false;
        }
 
+       /* Add all return possibilities to subroutine returns!           */
+       /* --- subroutines will be inlined ---- -> then cancel this part */
 #ifdef LSRA_DEBUG
        printf("LSRA Subroutine patching\n");
 #endif
@@ -490,7 +473,9 @@ void lsra_dump_Graph(methodinfo *m, struct depthElement **table)
 void lsra_main(methodinfo *m, lsradata *ls, registerdata *rd)
 {
        struct lifetime *lt, *lt_prev, *lt_temp, *int_lt, *int_lt_last, *flt_lt, *flt_lt_last;
+#ifdef LSRA_DEBUG
        int lt_count,lt_int_count,lt_flt_count,lt_left_count;
+#endif
        int i;
        int lsra_mem_use;
        int sav_reg_count, tmp_reg_count;
@@ -501,24 +486,23 @@ void lsra_main(methodinfo *m, lsradata *ls, registerdata *rd)
        int flags; /* 0 INMEMORY->lifetimes, 1 INTREG->int_lt, 2 FLTREG->flt_lt */
        int lsra_reg_use;
 
+       /* first split lifetimes for integer and float registers */
        int_lt_last=int_lt=NULL;
        flt_lt_last=flt_lt=NULL;
 
+#ifdef LSRA_DEBUG
        for (lt_count=0,lt=ls->lifetimes; lt!=NULL;lt=lt->next,lt_count++);
-
+#endif
 
        for (lt_prev=lt=ls->lifetimes;lt!=NULL;) {
                lt->reg = -1;
                
                if (lt->v_index < 0) { /* stackslot */
-                       if (lt->s != NULL)
-                               type = lt->s->type;
-                       else {
+
 #ifdef LSRA_DEBUG
-                               if (lt->local_ss == NULL) panic("lsra_main Lifetime for Stackslot invalid\n");
+                       if (lt->local_ss == NULL) panic("lsra_main Lifetime Stackslot invalid\n");
 #endif
-                               type = lt->local_ss->s->type;
-                       }
+                       type = lt->local_ss->s->type;
                } else { /* local var */
                        if (rd->locals[lt->v_index][lt->type].type>=0) {
                                type = rd->locals[lt->v_index][lt->type].type;
@@ -582,16 +566,16 @@ void lsra_main(methodinfo *m, lsradata *ls, registerdata *rd)
        lsra_sort_lt(&(ls->lifetimes));
        lsra_sort_lt(&flt_lt);
 
+#ifdef LSRA_DEBUG
        for (lt_int_count=0,lt=int_lt; lt!=NULL;lt=lt->next,lt_int_count++);
        for (lt_flt_count=0,lt=flt_lt; lt!=NULL;lt=lt->next,lt_flt_count++);
        for (lt_left_count=0,lt=ls->lifetimes; lt!=NULL;lt=lt->next,lt_left_count++);
 
-#ifdef LSRA_DEBUG
        printf("\nLifetimes: %3i left: %3i Intlt: %3i Fltlt: %3i \n",lt_count,lt_left_count,lt_int_count,lt_flt_count);
-#endif
        if (lt_count != lt_int_count + lt_flt_count + lt_left_count) {
                panic ("lifetimes missing\n");
        } 
+#endif
        lsra_reg_use=rd->savintregcnt;
        if (int_lt!=NULL) {
                for (reg_count = 0; nregdescint[reg_count] != REG_END; reg_count++);
@@ -618,7 +602,6 @@ void lsra_main(methodinfo *m, lsradata *ls, registerdata *rd)
                }
                _lsra_main(m, ls, int_lt, reg, tmp_reg_count, sav_reg_count, &lsra_mem_use, &lsra_reg_use);
                if (lsra_reg_use > rd->savintregcnt) lsra_reg_use=rd->savintregcnt;
-/*             r->maxsavintreguse=lsra_reg_use; */
        }
        rd->maxsavintreguse= lsra_reg_use;
        lsra_reg_use=rd->savfltregcnt;
@@ -629,7 +612,7 @@ void lsra_main(methodinfo *m, lsradata *ls, registerdata *rd)
                reg=DMNEW(struct lsra_reg,reg_count);
                sav_reg_count=0;
                for (i=0; i<reg_count ; i++)
-                       if (nregdescfloat[i]==REG_SAV) {
+                       if ((nregdescfloat[i]==REG_SAV) || (m->isleafmethod && (nregdescfloat[i]==REG_ARG))) {
                                reg[sav_reg_count].reg_index=i;
                                reg[sav_reg_count].use=0;
                                sav_reg_count++;
@@ -644,7 +627,6 @@ void lsra_main(methodinfo *m, lsradata *ls, registerdata *rd)
                        }
                _lsra_main(m,ls, flt_lt, reg, tmp_reg_count, sav_reg_count, &lsra_mem_use, &lsra_reg_use);
                if (lsra_reg_use > rd->savfltregcnt) lsra_reg_use=rd->savfltregcnt;
-/*             r->maxsavfltreguse=0; */
        }
 
        rd->maxsavfltreguse=lsra_reg_use;
@@ -666,6 +648,9 @@ void lsra_main(methodinfo *m, lsradata *ls, registerdata *rd)
        else
                lsra_mem_use = 0;
 #endif
+#ifdef SPECIALMEMUSE
+       lsra_mem_use = rd->ifmemuse;
+#endif
 
 #ifdef LSRA_DEBUG
        printf("Alloc Rest\n");
@@ -680,7 +665,7 @@ void lsra_main(methodinfo *m, lsradata *ls, registerdata *rd)
 #endif
        lsra_alloc(m, rd, flt_lt,&lsra_mem_use);
 
-#ifdef LSRA_DEBUG
+#ifdef LSRA_PRINTLIFETIMES
        printf("Int RA complete \n");
        printf("Lifetimes after splitting int: \n");
        print_lifetimes(rd, int_lt);
@@ -722,11 +707,6 @@ void lsra_alloc(methodinfo *m, registerdata *rd, struct lifetime *lifet, int *me
                }
 
                if (lt->v_index < 0) {
-                       if (lt->s!=NULL) {
-                               lsra_setflags( &(lt->s->flags), flags);
-                               lt->s->regoff=regoff;
-                       }
-
                        for (n=lt->local_ss; n!=NULL; n=n->next) {
                                lsra_setflags( &(n->s->flags), flags);
                                n->s->regoff=regoff;
@@ -757,7 +737,7 @@ int lsra_getmem(struct lifetime *lt, struct freemem *fmem, int *mem_use)
        struct freemem *fm, *p;
 
        /* noch kein Speicher vergeben, oder alle Enden später */
-       if ((fmem->next == NULL) || (fmem->next->end >= lt->i_start)) /* wirklich >= oder reicht > */
+       if ((fmem->next == NULL) || (fmem->next->end > lt->i_start)) 
                fm=lsra_getnewmem(mem_use);
        else {
                /* Speicherstelle frei */
@@ -786,7 +766,6 @@ struct freemem *lsra_getnewmem(int *mem_use)
 void _lsra_main( methodinfo *m, lsradata *ls, struct lifetime *lifet,  struct lsra_reg *reg, int tmp_reg_count, int sav_reg_count, int *mem_use, int *reg_use)
 {
        struct lifetime *lt;
-/*     struct active_lt *a; */
        int i;
        int _reg_use;
        int reg_count, active_count;
@@ -871,7 +850,6 @@ void _lsra_expire_old_intervalls(struct lifetime *lt, struct lsra_reg *reg, stru
 
                for (i=0;reg[i].reg_index != alt->lt->reg;i++);
                reg[i].use=0;
-/*             FREE(alt,struct active_lt); */
                (*active_count)--;
        }
 }
@@ -894,12 +872,11 @@ void _spill_at_intervall(struct lifetime *lt, struct active_lt **active, int *ac
        if (*active == NULL) {
                lt->reg=-2;
                return;
-               panic("No Lifetime in Active List -> no free registers at all!\n");
        }
        /* get last intervall from active */
        for (alt1=alt=*active; alt->next != NULL; alt1=alt, alt=alt->next);
        
-       if (alt->lt->i_end > lt->i_end) {
+       if ((alt->lt->i_end > lt->i_end) && (alt->lt->usagecount < lt->usagecount)) {
                        lt->reg=alt->lt->reg;
                        alt->lt->reg=-1;
                
@@ -1019,12 +996,11 @@ void lsra_calc_lifetime_length(methodinfo *m, lsradata *ls, codegendata *cd, loo
        }
 
        /* extend lifetime within loops */
-
   
        for (num_loops=0,lc =ld->c_allLoops;lc!=NULL;num_loops++,lc=lc->next);
 
+       /* set up loops[i].b_first .b_last to hold the first and last node of all loops */
        loops=DMNEW(struct l_loop,num_loops);
-
        for (i=0,lc=ld->c_allLoops;i<num_loops;i++,lc=lc->next) {
 
                le = lc->nodes;
@@ -1040,8 +1016,6 @@ void lsra_calc_lifetime_length(methodinfo *m, lsradata *ls, codegendata *cd, loo
                loops[i].nesting=0;
        }
 
-/*     for (i=0;i<num_loops;i++) printf("loops[%2i] bfirst: %3i blast %3i nesting %3i\n",i,loops[i].b_first,loops[i].b_last,loops[i].nesting); */
-
        /* sort loops by b_first desc*/
        for (i=0; i<num_loops-1;i++) {
                for (j=i+1; j<num_loops;j++) {
@@ -1055,7 +1029,7 @@ void lsra_calc_lifetime_length(methodinfo *m, lsradata *ls, codegendata *cd, loo
                        }
                }
        }
-/*     for (i=0;i<num_loops;i++) printf("loops[%2i] bfirst: %3i blast %3i nesting %3i\n",i,loops[i].b_first,loops[i].b_last,loops[i].nesting); */
+
        /* check for nesting_level, overlapping */
        for (i=0; i<num_loops-1;i++) {
                /*! loops[i].b_first >= loops[i+1].b_first !*/
@@ -1066,13 +1040,12 @@ void lsra_calc_lifetime_length(methodinfo *m, lsradata *ls, codegendata *cd, loo
                                loops[i].b_first=-1;
                                loops[i].b_last=-1;
                        } else {
-                               /* nested loops */
                                loops[i].nesting++; /* only boolean if nested... */
                        }
                }
        }
-/*     for (i=0;i<num_loops;i++) printf("loops[%2i] bfirst: %3i blast %3i nesting %3i\n",i,loops[i].b_first,loops[i].b_last,loops[i].nesting); */
-                               
+
+       /* cumulate basicblocks[i].icount in block_loop[i].instr*/
        block_loop=DMNEW(struct b_loop, m->basicblockcount);
        for (i=0;i<m->basicblockcount; i++) {
                block_loop[i].loop=-1;
@@ -1082,6 +1055,7 @@ void lsra_calc_lifetime_length(methodinfo *m, lsradata *ls, codegendata *cd, loo
                        block_loop[i].instr=0;
        }
 
+       /* set block_loop[j].loop to loop index, if Basic Block is in this loop */
        for (i=0; i<num_loops;i++) {
                if (loops[i].b_first!=-1) {
                        /* valid loop */
@@ -1089,22 +1063,24 @@ void lsra_calc_lifetime_length(methodinfo *m, lsradata *ls, codegendata *cd, loo
                }
        }
 
+       /* now iterate through lifetimes and expand them */
        lt=ls->lifetimes;
        while(lt!=NULL) {
 
                if (ls->back_edge_panic) {
-                       lt->b_start=0;
                        lt->i_start=0;
-                       lt->b_end=m->basicblockcount-1;
                        lt->i_end=block_loop[m->basicblockcount-1].instr+m->basicblocks[m->basicblockcount-1].icount;
                } else {
-                       usage = 0;
+                       usage = 1;
                        il=lt->i_list;
                        blast=il->b_index;
                        ilast=il->instr;
                        while (il->next!=NULL) {
+                               if ((il->b_index != il->next->b_index) || ((il->b_index == il->next->b_index) && (il->instr != il->next->instr))) {
+                                       if (block_loop[il->b_index].loop == -1)
+                                               usage++; /* not in a loop */
+                               }
                                il=il->next;
-                               usage++;
                        }
                        bfirst=il->b_index;
                        ifirst=il->instr;
@@ -1127,8 +1103,8 @@ void lsra_calc_lifetime_length(methodinfo *m, lsradata *ls, codegendata *cd, loo
                                } 
                        }
 
-                       ilast+=block_loop[blast].instr;
-                       ifirst+=block_loop[bfirst].instr;
+                       ilast+=block_loop[blast].instr;   /* add icount of previous Basic Blocks */
+                       ifirst+=block_loop[bfirst].instr; /* add icount of previous Basic Blocks */
 
                        if ((j=block_loop[bfirst].loop)==-1)
                                j=block_loop[blast].loop;
@@ -1146,12 +1122,10 @@ void lsra_calc_lifetime_length(methodinfo *m, lsradata *ls, codegendata *cd, loo
                                }
                        }
 
-                       lt->length=ilast-ifirst;
-
-                       lt->b_start=bfirst;
-                       lt->b_end=blast;
                        lt->i_start=ifirst;
                        lt->i_end=ilast;
+                       i=ilast-ifirst;
+                       if (i==0) i=1;
                        lt->usagecount=usage;
                }
                lt=lt->next;
@@ -1167,72 +1141,146 @@ void lsra_calc_lifetime_length(methodinfo *m, lsradata *ls, codegendata *cd, loo
 #endif   
 }
 
+/* void lsra_sort_lt(struct lifetime **lifet) */
+/* { */
+/*     struct lifetime *lt, lt_new, *temp, *tmp; */
+
+/*     lt_new.next=NULL; */
+
+/*     for (lt=*lifet; lt!= NULL;) { */
+/*             temp=lt->next; */
+
+/*             for(tmp=&lt_new; (tmp->next!= NULL) && (tmp->next->i_start < lt->i_start); tmp=tmp->next); */
+/*             lt->next=tmp->next; */
+/*             tmp->next=lt; */
+/*             lt=temp; */
+/*     } */
+/*     *lifet=lt_new.next; */
+/* } */
+
+
+#define P_MAX 21
+void _lsra_merge_lt(struct lifetime **p, int i1, int i2)
+{
+       struct lifetime *iptr, *iptr1, *iptr2;
+
+       if ( (iptr1=p[i2])==NULL) return;
+    if ( (iptr=p[i1])==NULL) return;
+
+       iptr2=p[i1]=NULL;
+       p[i2]=NULL;
+
+       while  ((iptr != NULL) && (iptr1 != NULL)) {
+               if (iptr->i_start < iptr1->i_start) {
+                       if (iptr2==NULL) {
+                               p[i1]=iptr;
+                       } else {
+                               iptr2->next=iptr;
+                       }
+                       iptr2=iptr;
+                       iptr=iptr->next;
+               } else {
+                       if (iptr2==NULL) {
+                               p[i1]=iptr1;
+                       } else {
+                               iptr2->next=iptr1;
+                       }
+                       iptr2=iptr1;
+                       iptr1=iptr1->next;
+               }
+       }
+       if (iptr==NULL)
+               iptr2->next=iptr1;
+       if (iptr1==NULL)
+               iptr2->next=iptr;
+}
+
+void lsra_merge_lt(struct lifetime **p, int top)
+{
+       int i,j;
+
+       for (j=1; j<top; j*=2)
+               for (i=1; i<top; i+=2*j)
+                       _lsra_merge_lt(p, i, i+j);
+       _lsra_merge_lt(p, 0, 1);
+}
+       
 void lsra_sort_lt(struct lifetime **lifet)
 {
        /* sort lifetimes by increasing start point */
 /*     struct lifetime **plt,**plt1; */
-       struct lifetime *lt, lt_new, *temp, *tmp;
-/*     int swapped; */
+       struct lifetime *lt, *temp, *tmp;
+       int i, top;
+       struct lifetime **p;
 
-       /* lifetimes are sorted by decreasing start point -> just turn around */
-       /* not really correct through exception and loop lifetime expansion! -> turn around and sort in*/
-       lt_new.next=NULL;
+       p=DMNEW(struct lifetime *, P_MAX);
+       for (i=0; i<P_MAX; i++) p[i]=NULL;
+
+       top=0;
 
        for (lt=*lifet; lt!= NULL;) {
-               temp=lt->next;
+               temp=lt;
+               lt=lt->next;
+               if (lt == NULL) {
+                       p[top]=temp;
+                       temp->next=NULL;
+               } else {
+                       tmp=lt;
+                       lt=lt->next;
 
-               for(tmp=&lt_new; (tmp->next!= NULL) && (tmp->next->i_start < lt->i_start); tmp=tmp->next);
-               lt->next=tmp->next;
-               tmp->next=lt;
-               lt=temp;
+                       if (temp->i_start < tmp->i_start) {
+                               p[top]=temp;
+                               /* temp->next == tmp */
+                               tmp->next=NULL;
+                       } else {
+                               p[top]=tmp;
+                               tmp->next=temp;
+                               temp->next=NULL;
+                       }
+               }
+               top++;
+               if (top == P_MAX) {
+                       lsra_merge_lt(p, P_MAX);
+                       top=1;
+               }
        }
-       *lifet=lt_new.next;
+       lsra_merge_lt(p, top);
+       *lifet=p[0];
 }
 
-
+#ifdef LSRA_PRINTLIFETIMES
 void print_lifetimes(registerdata *rd, struct lifetime *lt)
 {
        struct lifetime *n;
        struct _i_list *ni;
        int type,flags,regoff,j,varkind;
-/*     int i; */
+       /*      int i; */
 
        for (n=lt,j=0; n!=NULL; n=n->next,j++) {
                if (n->v_index < 0) { /* stackslot */
-                       if (n->s != 0) { /* stackslot */
-                               type = n->s->type;
-                               flags=n->s->flags;
-                               regoff=n->s->regoff;
-                               varkind=n->s->varkind;
-                       } else {
-                               if (n->local_ss != 0) {
-                                       type = n->local_ss->s->type;
-                                       flags=n->local_ss->s->flags;
-                                       regoff=n->local_ss->s->regoff;
-                                       varkind=n->local_ss->s->varkind;
-                               }
-                       }
+                       type = n->local_ss->s->type;
+                       flags=n->local_ss->s->flags;
+                       regoff=n->local_ss->s->regoff;
+                       varkind=n->local_ss->s->varkind;
                } else { /* local var */
-/*                     for (i=TYPE_INT; i<=TYPE_ADR; i++) { */
-                               if (rd->locals[n->v_index][n->type].type>=0) {
-                                       type = rd->locals[n->v_index][n->type].type;
-                                       flags=rd->locals[n->v_index][n->type].flags;
-                                       regoff=rd->locals[n->v_index][n->type].regoff;
-                                       varkind=-1;
-                               } else panic("Type Data mismatch 3\n");
-/*                     } */
+                       if (rd->locals[n->v_index][n->type].type>=0) {
+                               type = rd->locals[n->v_index][n->type].type;
+                               flags=rd->locals[n->v_index][n->type].flags;
+                               regoff=rd->locals[n->v_index][n->type].regoff;
+                               varkind=-1;
+                       } else 
+                               panic("Type Data mismatch 3\n");
                }
-               printf("i_Start: %3i i_stop: %3i reg: %3i Index: %3i VI: %3i Usage: %3i length: %3i type: %3i flags: %3i varkind: %3i ILst: ",n->i_start,n->i_end,regoff,n->index,n->v_index,n->usagecount, n->length,type,flags, varkind);
+               printf("i_Start: %3i i_stop: %3i reg: %3i VI: %3i Usage: %3i type: %3i flags: %3i varkind: %3i ILst: ",n->i_start,n->i_end,regoff,n->v_index,n->usagecount,type,flags, varkind);
                for (ni=n->i_list; ni!=NULL; ni=ni->next) {
                        if (ni==ni->next) panic("loop in instruction list!\n");
                        printf( "(%3i,%3i) ",ni->b_index,ni->instr);
                }
                printf("\n");
-/*             if (n->s!=NULL) */
-/*                     printf("   type: %1i flags: %1i varkind: %1i varnum: %3i regoff: %4i\n",n->s->type,n->s->flags,n->s->varkind,n->s->varnum,n->s->regoff); */
        }
        printf( "%3i Lifetimes printed \n",j);
 }
+#endif
 
 struct stackslot *lsra_make_ss(stackptr s, int bb_index)
 {
@@ -1254,33 +1302,92 @@ void lsra_merge_i_lists(struct lifetime *lt, struct lifetime *lt1)
        iptr2=lt->i_list=NULL;
        iptr1=lt1->i_list;
        while  ((iptr != NULL) && (iptr1 != NULL)) {
-               if ((iptr->b_index > iptr1->b_index)|| ((iptr->b_index == iptr1->b_index) && (iptr->instr > iptr1->instr))) {
-                       if (lt->i_list==NULL) {
-                               lt->i_list=iptr;
-/*                             iptr2=lt->i_list; */
+               if (iptr1->instr == -1) { 
+                       /* throw away, just for joining */
+                       iptr1=iptr1->next;
+               } else {
+                       if ((iptr->b_index > iptr1->b_index)|| ((iptr->b_index == iptr1->b_index) && (iptr->instr > iptr1->instr))) {
+                               if (lt->i_list==NULL) {
+                                       lt->i_list=iptr;
+                               } else {
+                                       iptr2->next=iptr;
+                               }
+                               iptr2=iptr;
+                               iptr=iptr->next;
                        } else {
-                               iptr2->next=iptr;
+                               if (lt->i_list==NULL) {
+                                       lt->i_list=iptr1;
+                               } else {
+                                       iptr2->next=iptr1;
+                               }
+                               iptr2=iptr1;
+                               iptr1=iptr1->next;
                        }
-                       iptr2=iptr;
-                       iptr=iptr->next;
+               }
+       }
+#ifdef LSRA_DEBUG
+       if (iptr2 == NULL)
+               panic("lsra_merge_i_lists: Empty Instruction List in Lifetime\n");
+#endif
+       if (iptr==NULL) {
+               if (lt->i_list==NULL)
+                       lt->i_list=iptr1;
+               else
+                       iptr2->next=iptr1;
+       }
+       if (iptr1==NULL) {
+               if (lt->i_list==NULL)
+                       lt->i_list=iptr;
+               else
+                       iptr2->next=iptr;
+       }
+}
+
+/* merge local_ss from lt1 to lt in order */
+void lsra_merge_local_ss(struct lifetime *lt, struct lifetime *lt1)
+{
+       struct stackslot *ssptr, *ssptr1, *ssptr2;
+
+       /* merge stackslots in order */
+       ssptr=lt->local_ss;
+       ssptr2=lt->local_ss=NULL;
+       ssptr1=lt1->local_ss;
+       while  ((ssptr != NULL) && (ssptr1 != NULL)) {
+
+               if (ssptr->s > ssptr1->s) {
+                       if (lt->local_ss==NULL) {
+                               lt->local_ss=ssptr;
+                       } else {
+                               ssptr2->next=ssptr;
+                       }
+                       ssptr2=ssptr;
+                       ssptr=ssptr->next;
                } else {
-                       if (lt->i_list==NULL) {
-                               lt->i_list=iptr1;
-/*                             iptr2=lt->i_list; */
+                       if (lt->local_ss==NULL) {
+                               lt->local_ss=ssptr1;
                        } else {
-                               iptr2->next=iptr1;
+                               ssptr2->next=ssptr1;
                        }
-                       iptr2=iptr1;
-                       iptr1=iptr1->next;
+                       ssptr2=ssptr1;
+                       ssptr1=ssptr1->next;
                }
        }
 #ifdef LSRA_DEBUG
-       if (iptr2 == NULL) panic("lsra_merge_i_lists: Empty Instruction List in Lifetime\n");
+       if (ssptr2 == NULL)
+               panic("lsra_merge_local_ss: Empty Stackslot List in Lifetime\n");
 #endif
-       if (iptr==NULL)
-               iptr2->next=iptr1;
-       if (iptr1==NULL)
-               iptr2->next=iptr;
+       if (ssptr==NULL) {
+               if (lt->local_ss==NULL)
+                       lt->local_ss=ssptr1;
+               else
+                       ssptr2->next=ssptr1;
+       }
+       if (ssptr1==NULL) {
+               if (lt->local_ss==NULL)
+                       lt->local_ss=ssptr;
+               else
+                       ssptr2->next=ssptr;
+       }
 }
 
 #ifdef LSRA_DEBUG
@@ -1293,10 +1400,10 @@ void dump_join( struct lifetime *lt_passing)
        for (lt=lt_passing,i=0; lt != NULL; lt=lt->next, ++i) {
                printf("Lifetime(%2i)\n  PT: ",i);
                for ( ss=lt->passthrough; ss!=NULL; ss=ss->next)
-                       printf("(%2i, %2i, %6p) ",ss->bb, ss->s->varnum, ss->s);
+                       printf("(%2i, %2i, %6p) ",ss->bb, ss->s->varnum, (void *)ss->s);
                printf("\n  SS: ");
                for (ss = lt->local_ss; ss!=NULL; ss=ss->next)
-                       printf("(%2i, %2i, %6p) ", ss->bb, ss->s->varnum, ss->s);
+                       printf("(%2i, %2i, %6p) ", ss->bb, ss->s->varnum, (void *)ss->s);
                printf("\n");
        }
 }
@@ -1310,10 +1417,10 @@ void lsra_join_lifetimes(methodinfo *m, codegendata *cd, lsradata *ls, loopdata
        
        int *in_stacks, *out_stacks;
        stackptr out, s;
-       struct stackslot **stacks, *ss, *ss_new;
+       struct stackslot **stacks, *ss, *ss1, *ss_new;
        struct lifetime *lt, *lt_prev, *lt_new, *lt_passing;
        struct stackslot *p, *q, *r;
-       bool drop;
+       bool drop, pt;
 
 #ifdef LSRA_DEBUG
        stackptr in;
@@ -1390,7 +1497,10 @@ void lsra_join_lifetimes(methodinfo *m, codegendata *cd, lsradata *ls, loopdata
                        for (ss=stacks[i]; ss!=NULL; ss=ss->next) {
                                /* search stackslot ss->s lifetimelist of basicblock(ss->bb) (ss_lifetimes) */
                                /* remember the link before found lifetime, to remove it afterwards         */
-                               for (lt_prev=lt=ls->ss_lifetimes[ss->bb]; (lt!=NULL) && (lt->s != ss->s); lt_prev=lt, lt=lt->next);
+                               for (lt_prev=lt=ls->ss_lifetimes[ss->bb]; lt!=NULL; lt_prev=lt, lt=lt->next) {
+                                       for (ss1=lt->local_ss; (ss1!=NULL) && (ss1->s != ss->s); ss1 = ss1->next);
+                                       if (ss1 != NULL) break; /* found */
+                               }
 #ifdef LSRA_DEBUG
                                if (lt==NULL) panic("lsra_join_lifetimes error in lifetimelist\n");
 #endif
@@ -1406,37 +1516,36 @@ void lsra_join_lifetimes(methodinfo *m, codegendata *cd, lsradata *ls, loopdata
                                if (lt->i_list->instr==-1) {
                                        if (out_stacks[in_stacks[ss->bb]] == out_stacks[ss->bb]) {
                                                /* Throughpassing Basicblock is already in one "join Group" */
-                                               /* If this stackslot (lt->s == ss->s) is already in lt_new->local_ss */
+                                               /* If this stackslot ((lt->local_ss)ss1->s == ss->s) is already in lt_new->local_ss */
                                                /* do not add it a second time! */
                                                if (lt_new != NULL) {
-                                                       for (ss_new=lt_new->local_ss; (ss_new != NULL) && (ss_new->s != lt->s); ss_new = ss_new->next);
+                                                       for (ss_new=lt_new->local_ss; (ss_new != NULL) && (ss_new->s != ss1->s); ss_new = ss_new->next);
                                                        if (ss_new != NULL) drop = true;
                                                }
                                        }
                                }
                                if (!drop) {
-                                       lt->s->varkind=TEMPVAR; /* no LOCALVAR, ARGVAR or STACKVAR with joined lifetimes */
+                                       /* lt->s->varkind=TEMPVAR */; /* no LOCALVAR, ARGVAR or STACKVAR with joined lifetimes */
                                        lt->v_index=-1; /* not a local var */
 
                                        /* join Lifetime lt to lt_new */
                                        if (lt_new == NULL) {
                                                lt_new = lt;
                                                lt_new->passthrough = NULL;
-                                               lt_new->s = NULL;     /* Stackslots are all in local_ss for joined lifetimes */
-                                       } else
+                                       } else {
                                                lsra_merge_i_lists( lt_new, lt);
+                                               lsra_merge_local_ss( lt_new, lt);
+                                       }
+
+
+                                       pt=(lt->i_list->instr==-1); /* remember this now, because merge_i_list could once destroy this link*/
 
                                        /* add stackslot to local_ss of lt_new */
                                        ss_new = DNEW(struct stackslot);
-                                       ss_new->s = ss->s;
-                                       ss_new->bb = ss->bb; /* for debugging only, has no further use */
-                                       ss_new->next = lt_new->local_ss;
-                                       lt_new->local_ss = ss_new;
                                        
                                        lt_new->savedvar |= (lt->savedvar & SAVEDVAR);
 
-
-                                       if (lt->i_list->instr==-1) {
+                                       if (pt) { /*lt->i_list->instr==-1) {*/
                                        /* BB passes this stackslot through -> join later with other side!*/
                                                if (out_stacks[in_stacks[ss->bb]] != out_stacks[ss->bb]) { 
                                                        /* Stackslot ist not passed through to same (this) "join group" */
@@ -1537,9 +1646,10 @@ void lsra_join_lifetimes(methodinfo *m, codegendata *cd, lsradata *ls, loopdata
                        if (lt_new->next->local_ss == NULL)
                                panic("lsra_join_lifetimes Lifetime without stackslot\n");
 #endif
-                       for (ss=lt_new->next->local_ss; (ss->next != NULL); ss=ss->next);
-                       ss->next=lt->local_ss;
-                       lt->local_ss=lt_new->next->local_ss;
+/*                     for (ss=lt_new->next->local_ss; (ss->next != NULL); ss=ss->next); */
+/*                     ss->next=lt->local_ss; */
+/*                     lt->local_ss=lt_new->next->local_ss; */
+                       lsra_merge_local_ss(lt, lt_new->next);
 
                        /* merge i_lists in order */
                        lsra_merge_i_lists(lt, lt_new->next);
@@ -1636,16 +1746,15 @@ void _lsra_new_stack(lsradata *ls, stackptr s, int block, int instr, int store)
 
        n=DNEW(struct lifetime);
 
-       n->index=s->varnum;
        n->savedvar = (s->flags & SAVEDVAR);
-       n->s=s;
+       n->local_ss=NULL;
+       lsra_add_ss( n, s);
        n->usagecount=1;
-       if (n->s->varkind == LOCALVAR)
-               n->v_index=n->s->varnum;
+       if (s->varkind == LOCALVAR)
+               n->v_index=s->varnum;
        else
                n->v_index=-1;
        n->i_list=NULL;
-       n->local_ss=NULL;
 
        n->next=ls->ss_lifetimes[block];
        ls->ss_lifetimes[block]=n;
@@ -1658,15 +1767,14 @@ void _lsra_new_stack(lsradata *ls, stackptr s, int block, int instr, int store)
 void _lsra_from_stack(lsradata *ls, stackptr s, int block, int instr, int store)
 {
        struct lifetime *n;
-       
-       for (n=ls->ss_lifetimes[block]; (n!=NULL) && (n->s!=s);n=n->next);
+       /* ss_lifetimes[block]->local_ss have exactly one entry! */
+       for (n=ls->ss_lifetimes[block]; (n!=NULL) && (n->local_ss->s!=s);n=n->next);
        if (n==NULL) {
                _lsra_new_stack(ls, s, block, instr, store);
                /* ist mit dem neuen joinen hinterher immer so, wenn ein Stackslot in einen BB "reinkommt" */
 /*             printf("type %i flags %i  varkind %i varnum %i regoff %i \n",s->type,s->flags ,s->varkind ,s->varnum ,s->regoff); */
 /*             panic("lsra_from_stack: Var on Stack not found"); */
        } else {
-               n->usagecount++;
                n->i_list=lsra_add_i_list(n->i_list, instr, block, store);
        }
 }
@@ -1688,7 +1796,6 @@ void lsra_usage_local(lsradata *ls, s4 v_index, int type, int block, int instr,
        }
        /* add access at (block, instr) to intruction list */
        n->i_list=lsra_add_i_list(n->i_list, instr, block, store);
-       n->usagecount++;
 }      
 
 void lsra_new_local(lsradata *ls, s4 v_index, int type)
@@ -1698,11 +1805,8 @@ void lsra_new_local(lsradata *ls, s4 v_index, int type)
        n=DNEW(struct lifetime);
        n->local_ss=NULL;
        n->i_list=NULL;
-       n->index=v_index;
        n->v_index=v_index;
-       n->s=NULL;
        n->type=type;
-       n->usagecount=0;
        n->savedvar = SAVEDVAR;
 
        n->next=ls->locals_lifetimes[v_index];
@@ -1720,6 +1824,81 @@ void lsra_dump_stack(stackptr s)
 }
 #endif
 
+void dup_mark( struct dup *dup,stackptr s)
+{
+       struct stackslot *n;
+       n = DNEW(struct stackslot);
+       if (dup->ss == NULL) {
+               dup->ss = n;
+               n->next = NULL;
+       } else {
+               n->next=dup->ss;
+               dup->ss=n;
+       }
+       n->s=s;
+}
+
+void dup_next( struct dup *dup)
+{
+       struct dup *n;
+
+       n = DNEW(struct dup);
+       n->next = dup->next;
+       dup->next=n;
+       n->ss = dup->ss;
+       dup->ss = NULL;
+}
+
+void dup_join( struct lsradata *ls, struct dup *dup, int block)
+{
+       struct dup *d;
+       struct stackslot *ss, *ss1;
+       bool pt; /* joins with passthrough lifetimes not yet possible! */
+       struct lifetime *join_lt[3]; /* max three lifetimes to join */
+       struct lifetime *join_lt_prev[3]; /* previous elements for unlinking */
+       struct lifetime *lt, *lt_prev;
+       int i, join_lt_top, join_to;
+
+       for (i=0; i<3; i++) join_lt[i]=join_lt_prev[i]=NULL;
+       /* walk through dup structure and clean it up for next block */
+       /* the first dup entry is alway empty for the next group to come*/
+       for (d=dup->next; d!= NULL; d = dup->next=dup->next->next) { 
+               pt=false;
+               join_lt_top=0;
+               for (ss=d->ss; (ss != NULL) && (!pt); ss = ss->next) {
+                       for (lt = lt_prev = ls->ss_lifetimes[block]; lt != NULL ; lt_prev=lt, lt=lt->next) {
+                               for (ss1=lt->local_ss; (ss1!=NULL) && (ss1->s != ss->s); ss1 = ss1->next);
+                               if (ss1 != NULL) break; /* found */
+                       }
+                       if (lt == NULL) panic("dup_join Lifetimes not found\n");
+                       pt=(lt->i_list->instr == -1); /* joins with passthrough lifetimes not yet possible! */
+                       pt|=(lt->i_list->next == NULL); /* joins with "interface" Stackslots not yet possible! */
+                       if (!pt) {
+                               join_lt_prev[join_lt_top]=lt_prev;
+                               join_lt[join_lt_top++]=lt;
+                       }
+               }
+               if (!pt) { /* now join */
+                       /* look if one element is the root of the list (joint_lt == join_lt_prev == ls->ss_lifetimes[block]) */
+                       for (join_to=0; (join_to < join_lt_top) && (join_lt[join_to] != join_lt_prev[join_to]); join_to++);
+                       if (join_to == join_lt_top) /* no root element in join array */
+                               join_to=0;
+                       join_lt[join_to]->v_index = -1;
+                       for (i=0; i<join_lt_top; i++) {
+                               if (i != join_to) {
+                                       /* now join finally */
+                                       lsra_merge_i_lists(join_lt[join_to], join_lt[i]);
+                                       lsra_merge_local_ss(join_lt[join_to], join_lt[i]);
+                                       join_lt[join_to]->savedvar|=(join_lt[i]->savedvar & SAVEDVAR);
+                                       /* drop join_lt[i] from list */
+                                       join_lt_prev[i]->next = join_lt[i]->next;
+                               }
+                       }
+               }
+       }
+       dup->next = NULL;
+}
+
 void lsra_scan_registers_canditates(methodinfo *m, lsradata *ls)
 {
        int i;
@@ -1731,9 +1910,12 @@ void lsra_scan_registers_canditates(methodinfo *m, lsradata *ls)
        instruction *iptr;
        stackptr in,out;
        int      id, od;
-
        int b_index;
-
+       struct dup dup;
+       
+       dup.ss=NULL;
+       dup.next=NULL;
+       
        b_index=0;
        while (b_index < m->basicblockcount ) {
 
@@ -1766,7 +1948,6 @@ void lsra_scan_registers_canditates(methodinfo *m, lsradata *ls)
                                        /* Make 2 entries -> one for the instack, one for the out stack */
                                        lsra_new_stack(ls, in, b_index, -1);
                                        lsra_new_stack(ls, in, b_index, -1);
-                                       /*                                      } */
                                }
                        }
                        iptr = m->basicblocks[b_index].iinstr;
@@ -1963,8 +2144,10 @@ void lsra_scan_registers_canditates(methodinfo *m, lsradata *ls)
                                        /* merge dupped vars??? */
                                case ICMD_DUP:
                                        /* lsra_from_stack(ls, src,b_index,iindex);*/ /* inc usage_count! */
-/*                                     dup_alignstackslots(src, dst); */
                                        lsra_new_stack(ls,dst,b_index,iindex);
+                                       dup_mark(&dup, src);
+                                       dup_mark(&dup, dst);
+                                       dup_next(&dup);
                                        break;
 
                                        /* pop 0 push 2 dup */
@@ -1972,10 +2155,17 @@ void lsra_scan_registers_canditates(methodinfo *m, lsradata *ls)
                                case ICMD_DUP2:
                                        lsra_new_stack(ls,dst->prev,b_index,iindex);
                                        lsra_new_stack(ls,dst,b_index,iindex); 
-/*                                     dup_alignstackslots(src, dst); */
-/*                                     dup_alignstackslots(src->prev, dst->prev); */
                                        lsra_from_stack(ls, src,b_index,iindex); /* or inc usage_count! */
                                        lsra_from_stack(ls, src->prev,b_index,iindex); /* inc usage_count! */
+
+                                       dup_mark(&dup, src);
+                                       dup_mark(&dup, dst);
+                                       dup_mark(&dup, dst->prev->prev);
+                                       dup_next(&dup);
+                                       dup_mark(&dup, src->prev);
+                                       dup_mark(&dup, dst->prev);
+                                       dup_mark(&dup, dst->prev->prev->prev);
+                                       dup_next(&dup);
                                        break;
 
                                        /* pop 2 push 3 dup */
@@ -1983,12 +2173,16 @@ void lsra_scan_registers_canditates(methodinfo *m, lsradata *ls)
                                case ICMD_DUP_X1:
                                        lsra_from_stack(ls, src,b_index,iindex); /* from for to, or it will not work! inc usage_count! */
                                        lsra_from_stack(ls, src->prev,b_index,iindex); /*from for to, or it will not work!  inc usage_count! */
-/*                                     dup_alignstackslots(src, dst); */
-/*                                     dup_alignstackslots(src->prev, dst->prev); */
-/*                                     dup_alignstackslots(src, dst->prev->prev); */
                                        lsra_new_stack(ls,dst->prev->prev,b_index,iindex);
                                        lsra_new_stack(ls,dst->prev,b_index,iindex);
                                        lsra_new_stack(ls,dst,b_index,iindex); 
+                                       dup_mark(&dup, src);
+                                       dup_mark(&dup, dst);
+                                       dup_mark(&dup, dst->prev->prev);
+                                       dup_next(&dup);
+                                       dup_mark(&dup, src->prev);
+                                       dup_mark(&dup, dst->prev);
+                                       dup_next(&dup);
                                        break;
 
                                        /* pop 3 push 4 dup */
@@ -1997,14 +2191,20 @@ void lsra_scan_registers_canditates(methodinfo *m, lsradata *ls)
                                        lsra_from_stack(ls, src,b_index,iindex); /* from for to, or it will not work! inc usage_count! */
                                        lsra_from_stack(ls, src->prev,b_index,iindex); /*from for to, or it will not work!  inc usage_count! */
                                        lsra_from_stack(ls, src->prev->prev,b_index,iindex); /*from for to, or it will not work!  inc usage_count! */
-/*                                     dup_alignstackslots(src, dst); */
-/*                                     dup_alignstackslots(src->prev, dst->prev); */
-/*                                     dup_alignstackslots(src->prev->prev, dst->prev->prev); */
-/*                                     dup_alignstackslots(src, dst->prev->prev->prev); */
                                        lsra_new_stack(ls,dst->prev->prev->prev,b_index,iindex);
                                        lsra_new_stack(ls,dst->prev->prev,b_index,iindex);
                                        lsra_new_stack(ls,dst->prev,b_index,iindex);
                                        lsra_new_stack(ls,dst,b_index,iindex); 
+                                       dup_mark(&dup, src);
+                                       dup_mark(&dup, dst);
+                                       dup_mark(&dup, dst->prev->prev->prev);
+                                       dup_next(&dup);
+                                       dup_mark(&dup, src->prev);
+                                       dup_mark(&dup, dst->prev);
+                                       dup_next(&dup);
+                                       dup_mark(&dup, src->prev->prev);
+                                       dup_mark(&dup, dst->prev->prev);
+                                       dup_next(&dup);
                                        break;
 
                                        /* pop 3 push 5 dup */
@@ -2013,16 +2213,22 @@ void lsra_scan_registers_canditates(methodinfo *m, lsradata *ls)
                                        lsra_from_stack(ls, src,b_index,iindex); /* from for to, or it will not work! inc usage_count! */
                                        lsra_from_stack(ls, src->prev,b_index,iindex); /*from for to, or it will not work!  inc usage_count! */
                                        lsra_from_stack(ls, src->prev->prev,b_index,iindex); /*from for to, or it will not work!  inc usage_count! */
-/*                                     dup_alignstackslots(src, dst); */
-/*                                     dup_alignstackslots(src->prev, dst->prev); */
-/*                                     dup_alignstackslots(src->prev->prev, dst->prev->prev); */
-/*                                     dup_alignstackslots(src, dst->prev->prev->prev); */
-/*                                     dup_alignstackslots(src->prev, dst->prev->prev->prev->prev); */
                                        lsra_new_stack(ls,dst->prev->prev->prev->prev,b_index,iindex);
                                        lsra_new_stack(ls,dst->prev->prev->prev,b_index,iindex);
                                        lsra_new_stack(ls,dst->prev->prev,b_index,iindex);
                                        lsra_new_stack(ls,dst->prev,b_index,iindex);
                                        lsra_new_stack(ls,dst,b_index,iindex); 
+                                       dup_mark(&dup, src);
+                                       dup_mark(&dup, dst);
+                                       dup_mark(&dup, dst->prev->prev->prev);
+                                       dup_next(&dup);
+                                       dup_mark(&dup, src->prev);
+                                       dup_mark(&dup, dst->prev);
+                                       dup_mark(&dup, dst->prev->prev->prev->prev);
+                                       dup_next(&dup);
+                                       dup_mark(&dup, src->prev->prev);
+                                       dup_mark(&dup, dst->prev->prev);
+                                       dup_next(&dup);
                                        break;
 
                                        /* pop 4 push 6 dup */
@@ -2032,18 +2238,26 @@ void lsra_scan_registers_canditates(methodinfo *m, lsradata *ls)
                                        lsra_from_stack(ls, src->prev,b_index,iindex); /*from for to, or it will not work!  inc usage_count! */
                                        lsra_from_stack(ls, src->prev->prev,b_index,iindex); /*from for to, or it will not work!  inc usage_count! */
                                        lsra_from_stack(ls, src->prev->prev->prev,b_index,iindex); /*from for to, or it will not work!  inc usage_count! */
-/*                                     dup_alignstackslots(src, dst); */
-/*                                     dup_alignstackslots(src->prev, dst->prev); */
-/*                                     dup_alignstackslots(src->prev->prev, dst->prev->prev); */
-/*                                     dup_alignstackslots(src->prev->prev->prev, dst->prev->prev->prev); */
-/*                                     dup_alignstackslots(src, dst->prev->prev->prev->prev); */
-/*                                     dup_alignstackslots(src->prev, dst->prev->prev->prev->prev->prev); */
                                        lsra_new_stack(ls,dst->prev->prev->prev->prev->prev,b_index,iindex);
                                        lsra_new_stack(ls,dst->prev->prev->prev->prev,b_index,iindex);
                                        lsra_new_stack(ls,dst->prev->prev->prev,b_index,iindex);
                                        lsra_new_stack(ls,dst->prev->prev,b_index,iindex);
                                        lsra_new_stack(ls,dst->prev,b_index,iindex);
                                        lsra_new_stack(ls,dst,b_index,iindex); 
+                                       dup_mark(&dup, src);
+                                       dup_mark(&dup, dst);
+                                       dup_mark(&dup, dst->prev->prev->prev->prev);
+                                       dup_next(&dup);
+                                       dup_mark(&dup, src->prev);
+                                       dup_mark(&dup, dst->prev);
+                                       dup_mark(&dup, dst->prev->prev->prev->prev->prev);
+                                       dup_next(&dup);
+                                       dup_mark(&dup, src->prev->prev);
+                                       dup_mark(&dup, dst->prev->prev);
+                                       dup_next(&dup);
+                                       dup_mark(&dup, src->prev->prev->prev);
+                                       dup_mark(&dup, dst->prev->prev->prev);
+                                       dup_next(&dup);
                                        break;
 
                                        /* pop 2 push 2 swap */
@@ -2051,10 +2265,14 @@ void lsra_scan_registers_canditates(methodinfo *m, lsradata *ls)
                                case ICMD_SWAP:
                                        lsra_from_stack(ls, src,b_index,iindex); /* from for to, or it will not work! inc usage_count! */
                                        lsra_from_stack(ls, src->prev,b_index,iindex); /*from for to, or it will not work!  inc usage_count! */
-/*                                     dst->varnum = src->varnum; */
-/*                                     dst->varkind = src->varkind; */
                                        lsra_new_stack(ls,dst->prev,b_index,iindex);
                                        lsra_new_stack(ls,dst,b_index,iindex);
+                                       dup_mark(&dup, src);
+                                       dup_mark(&dup, dst->prev);
+                                       dup_next(&dup);
+                                       dup_mark(&dup, src->prev);
+                                       dup_mark(&dup, dst);
+                                       dup_next(&dup);
                                        break;
 
                                        /* pop 2 push 1 */
@@ -2232,7 +2450,7 @@ void lsra_scan_registers_canditates(methodinfo *m, lsradata *ls)
                        } /* while instructions */
                } /* if */
                
-
+               dup_join(ls, &dup, b_index);
 
                b_index++;
        } /* while blocks */
index f40ec07d9523ffd6359df4c6a5c81554d6dcf545..e4b59d2d0da633c55c9051fe46a0a086486064b9 100644 (file)
@@ -27,7 +27,7 @@
 
    Authors: Christian Ullrich
 
-   $Id: lsra.h 1590 2004-11-25 13:24:49Z christian $
+   $Id: lsra.h 1597 2004-11-28 16:37:23Z christian $
 
 */
 
 #define LSRA_POP -1
 
 struct lifetime {
-       int   index; /* unique index, LOCALVAR varnum or negative*/
-       int   b_start; /* bb of first use */
-       int   b_end;   /* bb of last use */
        int i_start; /* instruction number of first use */
        int i_end; /* instruction number of last use */
-       int length; /* lifetime in instructions */
-       stackptr s; /* stackslot or NULL */
-       int v_index; /* local variable index or -1 */
+       int v_index; /* local variable index or negative for stackslots */
        int type;
-       int usagecount; /* number of refernces*/
+       int usagecount; /* number of references*/
        int reg; /* regoffset durch lsra zugewiesen */
        int savedvar;
        struct stackslot *passthrough; /* List of Stackslots in Lifetime, which are passed through a Basic Block */
-       struct stackslot *local_ss;
+       struct stackslot *local_ss; /* Stackslots for this Lifetime or NULL (=="pure" Local Var) */
        struct _i_list *i_list; /* list of instructions with references to var */
        struct lifetime *next;
 };
 
-/* struct int_list { */
-/*     int value; */
-/*     int_list *next; */
-/* }; */
-
 struct active_lt {
        struct lifetime *lt;
        struct active_lt *next;
@@ -116,10 +106,9 @@ struct freemem {
        struct freemem *next;
 };
 
-struct sss {
-       int bb;
-       bool out;
-       struct sss *next;
+struct dup {
+       struct stackslot *ss;
+       struct dup *next;
 };
 
 typedef struct lsradata lsradata;
@@ -133,6 +122,8 @@ void lsra_clean_Graph( methodinfo *, codegendata *, lsradata *, loopdata *);
 #ifdef LSRA_DEBUG
 void lsra_dump_Graph(methodinfo *, struct depthElement **);
 void lsra_dump_stack(stackptr );
+#endif
+#ifdef LSRA_PRINTLIFETIMES
 void print_lifetimes(registerdata *, struct lifetime *);
 #endif
 
@@ -143,8 +134,9 @@ int lsra_getmaxblock(methodinfo *, loopdata *, int );
 void lsra_calc_lifetime_length(methodinfo *, lsradata *, codegendata *, loopdata *);
 
 void lsra_merge_i_lists(struct lifetime *, struct lifetime *);
+void lsra_merge_local_ss(struct lifetime *, struct lifetime *);
 
-void _lsra_new_stack( lsradata *, stackptr , int , int , int);
+void _lsra_new_stack( lsradata *, stackptr , int , int, int);
 void _lsra_from_stack(lsradata *, stackptr , int , int, int);
 void lsra_add_ss(struct lifetime *, stackptr );
 void lsra_usage_local(lsradata *, s4 , int , int , int , int );
index 8202c285c05301bac9294d0e8a26eb79888f72f9..ba756aa7ae5b3f3295e3b9a54cf83594cf13cd3f 100644 (file)
 
    Authors: Christian Ullrich
 
-   $Id: lsra.inc 1590 2004-11-25 13:24:49Z christian $
+   $Id: lsra.inc 1597 2004-11-28 16:37:23Z christian $
 
 */
 
 /* #define LSRA_DEBUG */
 /* #define LSRA_SAVEDVAR */
 /* #define LSRA_MEMORY */
+/* #define LSRA_PRINTLIFETIMES */
+
+
+#ifdef LSRA_DEBUG
+#define LSRA_PRINTLIFETIMES
+#endif
 
 #include "lsra.h"
 #include "loop/graph.h"
@@ -63,7 +69,7 @@ void lsra(methodinfo *m, codegendata *cd, registerdata *rd, loopdata *ld, t_inli
 
        printf("LSRA Start for %s\n", name); 
 
-       if (strcmp(name,"at/dms/kjc/CSourceClassgenCode(Lat/dms/kjc/BytecodeOptimizer;Ljava/lang/String;Lat/dms/kjc/TypeFactory;)V")==0) {
+       if (strcmp(name,"java/lang/SysteminitProperties()V")==0) {
                printf("-------------------\n");
        }
 #endif
@@ -95,7 +101,6 @@ void lsra_init(methodinfo *m, codegendata *cd, t_inlining_globals *id, lsradata
        for (i=0; i < cd->maxlocals; i++) ls->locals_lifetimes[i]=NULL;
        ls->lifetimes=NULL;
        ls->stackslots=NULL;
-       ls->var_index=-1;
 }
 
 void lsra_setup(methodinfo *m, codegendata *cd, registerdata *rd, lsradata *ls, loopdata *ld)
@@ -108,6 +113,7 @@ void lsra_setup(methodinfo *m, codegendata *cd, registerdata *rd, lsradata *ls,
        struct lifetime *lt, *n;
        int v_index;
        struct stackslot *ss;
+       bool drop;
        
        /* Setup LSRA Data structures */
        if (opt_loops) panic("lsra with -oloop not possible!\n");
@@ -168,8 +174,9 @@ void lsra_setup(methodinfo *m, codegendata *cd, registerdata *rd, lsradata *ls,
 
        v_index=-1;
 
+       /* ls->lifetimes contains only the joined stackslotlifetimes */
        for (lt=ls->lifetimes; lt != NULL; lt=lt->next) {
-               lt->index=v_index;
+               lt->v_index=v_index;
 #ifdef LSRA_SAVEDVAR
                lt->savedvar=SAVEDVAR;
 #endif
@@ -179,15 +186,7 @@ void lsra_setup(methodinfo *m, codegendata *cd, registerdata *rd, lsradata *ls,
                }
        }
 
-       for (i=0; i < cd->maxlocals; i++) {
-               for (lt=ls->locals_lifetimes[i]; lt != NULL; lt=lt->next) {
-/*                     lt->local_ss=NULL; */
-#ifdef LSRA_SAVEDVAR
-                       lt->savedvar=SAVEDVAR;
-#endif
-               }
-       }
-
+       /* add ss_lifetimes[i] to ls->lifetimes or local_lifetimes[lt->s->varnum] */
        for (i=0; i < m->basicblockcount; i++) {
                if (m->basicblocks[i].flags >= BBREACHED) {
                        for (; ls->ss_lifetimes[i] != NULL;) {
@@ -195,48 +194,48 @@ void lsra_setup(methodinfo *m, codegendata *cd, registerdata *rd, lsradata *ls,
 #ifdef LSRA_SAVEDVAR
                                lt->savedvar=SAVEDVAR;
 #endif
-                               if (lt->s->varkind == LOCALVAR) {
-                                       /* join with LOCALVAR */
-                                       /* local Lifetime vom richtigen Type suchen */
-                                       for (n=ls->locals_lifetimes[lt->s->varnum]; (n!=NULL) && (n->type!=lt->s->type);n=n->next);
 #ifdef LSRA_DEBUG
-                                       if (n == NULL) panic("lsra_setup: Local Var not found\n");
+                               if (lt->local_ss == NULL) panic("lsra_setup: normal Stackslot Lifetimes local_ss == NULL\n");
 #endif
-                                       lsra_merge_i_lists(n, lt);
-                                       ss=DNEW(struct stackslot);
-                                       ss->s=lt->s;
-                                       ss->next=n->local_ss;
-                                       n->local_ss=ss;
-
-                                       ls->ss_lifetimes[i]=lt->next;
-                               } else {
-#ifdef LSRA_DEBUG
-                                       if (lt->s == NULL) panic("lsra_setup: Wrong assumption about Stackslot Lifetimes -> s\n");
-
-#endif
-                                       if ((lt->s != NULL) && (lt->s->varkind != ARGVAR)) {
-                                               if (lt->s->varkind != ARGVAR) {
-                                                       lt->s->varkind=TEMPVAR;
-                                                       lt->s->varnum=v_index;
+                               drop=false;
+                               for (ss=lt->local_ss; (ss!=NULL) && (!drop); ss=ss->next) {
+                                       if (lt->local_ss->next == NULL) { /* only one Stackslot in local_ss */
+                                               /* Special Treatment for "lonely" LOCAL and ARGVARs */
+                                               if (ss->s->varkind == LOCALVAR) {
+                                                       /* join with LOCALVAR */
+                                                       /* local Lifetime vom richtigen Type suchen */
+                                                       for (n=ls->locals_lifetimes[lt->local_ss->s->varnum]; (n!=NULL) && (n->type!=lt->local_ss->s->type);n=n->next);
+                                                       lsra_merge_i_lists(n, lt);
+                                                       if (n->local_ss == NULL)  /* "pure" Local without Stackslots */
+                                                               n->local_ss = lt->local_ss;
+                                                       else
+                                                               lsra_merge_local_ss(n, lt);
+
+                                                       drop = true;
                                                }
-                                               lt->index=lt->v_index=v_index;
-                                               for (ss=lt->local_ss; ss!=NULL; ss=ss->next) {
-                                                       ss->s->varnum=v_index;
-                                                       lt->s->varkind=TEMPVAR;
+                                               if (lt->local_ss->s->varkind == ARGVAR) {
+                                                       drop = true;
                                                }
-                                               
-                                               ls->ss_lifetimes[i]=lt->next;
-                                               lt->next=ls->lifetimes;
-                                               ls->lifetimes=lt;
-                                       } else {
-                                               ls->ss_lifetimes[i]=lt->next;
+                                       } else { 
+                                               /* no special treatment (only one Stackslot Lifetimes)? */
+                                               ss->s->varnum=v_index;
+                                               ss->s->varkind=TEMPVAR; /* only TEMPVAR possible for now */
                                        }
-                                       --v_index;
-                               }               
+                               }
+                               if (drop)
+                                       ls->ss_lifetimes[i]=lt->next;
+                               else {
+                                       /* link into ls->lifetimes */
+                                       ls->ss_lifetimes[i]=lt->next;
+                                       lt->next=ls->lifetimes;
+                                       ls->lifetimes=lt;
+                                       lt->v_index=v_index--;
+                               }
                        } /* for */
                } /* if */
        }
 
+       /* add local_lifetimes to lifetimes */
        for (i=0; i < cd->maxlocals; i++) {
                if (ls->locals_lifetimes[i] != NULL) {
                        for (lt=ls->locals_lifetimes[i]; lt->next != NULL; lt=lt->next);
@@ -286,10 +285,7 @@ void lsra_clean_Graph( methodinfo *m, codegendata *cd, lsradata *ls, loopdata *l
        exceptiontable *ex;
        struct depthElement **table;
        bool back_edge;
-#ifdef LSRA_DEBUG
        struct LoopContainer *lc;
-       struct LoopElement *le;
-#endif
 
        table=ld->c_dTable;
 
@@ -304,16 +300,8 @@ void lsra_clean_Graph( methodinfo *m, codegendata *cd, lsradata *ls, loopdata *l
 #endif
 
        for (; ex != NULL; ex = ex->down) {
-#ifdef LSRA_DEBUG
-               if (ex->handler == NULL) {
-                       panic("lsra_init_blocks EXCEPTIONTABLE without handler!\n");
-               } 
-#endif
-#ifdef LSRA_DEBUG
-               if ((ex->handler->debug_nr < 0) || (ex->handler->debug_nr >= m->basicblockcount)) {
-                       panic("lsra_init_blocks EXCEPTIONTABLE Handler Blocknummer invalid! \n");
-               }
 
+#ifdef LSRA_DEBUG
                printf("%i ",ex->handler->debug_nr);
 #endif
                dF(m, ld, -1, ex->handler->debug_nr);
@@ -336,24 +324,12 @@ void lsra_clean_Graph( methodinfo *m, codegendata *cd, lsradata *ls, loopdata *l
        }
 
        back_edge=false;
-#ifdef LSRA_DEBUG
-       printf("\n Cleaning c_dTable ");
-#endif
        for(i=0; i < m->basicblockcount; i++) {
-#ifdef LSRA_DEBUG
-               printf("\n %i-",i);
-#endif
                if (m->basicblocks[i].flags < BBREACHED) {
-#ifdef LSRA_DEBUG
-                       printf("deleted\n");
-#endif
                        table[i]=NULL;
                } else {
                        for (de=table[i]; de != NULL; de=de->next) {
                                if (de->value < i) back_edge=true;
-#ifdef LSRA_DEBUG
-                               printf("%i-%i ",de->value, bb_succ[de->value]);
-#endif
                                if (bb_succ[de->value] != de->value)
                                        de->value = bb_succ[de->value];
                                if (de->value == -1) panic("lsra_clean_Graph: Sprung ins nichts....");
@@ -369,37 +345,44 @@ void lsra_clean_Graph( methodinfo *m, codegendata *cd, lsradata *ls, loopdata *l
                        /* TODO bis dahin eine loop über die backedge eintragen            */
                        /*      anstatt back_edge_panic zu setzen und alle Lifetimes über die */
                        /*      gesamt Methode auszudehnen                                    */
-                       ls->back_edge_panic = true;
-               }
-       }
+/*                     ls->back_edge_panic = true; */
+
+                       /* create loops from all back edges */
+                       
+                       for(i=0; i < m->basicblockcount; i++) {
+                               if (m->basicblocks[i].flags >= BBREACHED) {
+                                       for (de=table[i]; de != NULL; de=de->next) {
+                                               if (de->value < i) {
+                                                       if (ld->c_allLoops == NULL) {
+                                                               ld->c_allLoops = lc = DNEW(struct LoopContainer);
+                                                       } else {
+                                                               lc->next=DNEW(struct LoopContainer);
+                                                               lc=lc->next;
+                                                       }
+                                                       lc->nodes=DNEW(struct LoopElement);
+                                                       lc->nodes->next=DNEW(struct LoopElement);
+                                                       lc->nodes->next->next=NULL;
+
+                                                       lc->nodes->block=&(m->basicblocks[i]);
+                                                       lc->nodes->next->block=&(m->basicblocks[de->value]);
+                                                       lc->next = NULL;
+                                               }
+                                       }
+                               }
+                       }
 #ifdef LSRA_DEBUG
-       if (back_edge) {
-               if ( ld->c_allLoops == NULL ) {
                        printf("-------------Warnung Back Edge + no LOOP..\n");
+#endif
                }
-               else
-                       printf("Back-edges + Loops:\n");
-               lc = ld->c_allLoops;
-               i = 0;
-               while (lc != NULL) {
-                       printf("Loop [%d]: ", ++i);
-                       le = lc->nodes;
-                       while (le != NULL) {
-                               printf("%d ", le->node);
-                               printf("\n");
-                               le = le->next;
-                       }
-                       lc = lc->next;
-               }
-               printf("\n");
        }
-#endif
 
        bb_visited=DMNEW(int, m->basicblockcount);
        for (i=0; i<m->basicblockcount; i++) {
                bb_visited[i]=false;
        }
 
+       /* Add all return possibilities to subroutine returns!           */
+       /* --- subroutines will be inlined ---- -> then cancel this part */
 #ifdef LSRA_DEBUG
        printf("LSRA Subroutine patching\n");
 #endif
@@ -490,7 +473,9 @@ void lsra_dump_Graph(methodinfo *m, struct depthElement **table)
 void lsra_main(methodinfo *m, lsradata *ls, registerdata *rd)
 {
        struct lifetime *lt, *lt_prev, *lt_temp, *int_lt, *int_lt_last, *flt_lt, *flt_lt_last;
+#ifdef LSRA_DEBUG
        int lt_count,lt_int_count,lt_flt_count,lt_left_count;
+#endif
        int i;
        int lsra_mem_use;
        int sav_reg_count, tmp_reg_count;
@@ -501,24 +486,23 @@ void lsra_main(methodinfo *m, lsradata *ls, registerdata *rd)
        int flags; /* 0 INMEMORY->lifetimes, 1 INTREG->int_lt, 2 FLTREG->flt_lt */
        int lsra_reg_use;
 
+       /* first split lifetimes for integer and float registers */
        int_lt_last=int_lt=NULL;
        flt_lt_last=flt_lt=NULL;
 
+#ifdef LSRA_DEBUG
        for (lt_count=0,lt=ls->lifetimes; lt!=NULL;lt=lt->next,lt_count++);
-
+#endif
 
        for (lt_prev=lt=ls->lifetimes;lt!=NULL;) {
                lt->reg = -1;
                
                if (lt->v_index < 0) { /* stackslot */
-                       if (lt->s != NULL)
-                               type = lt->s->type;
-                       else {
+
 #ifdef LSRA_DEBUG
-                               if (lt->local_ss == NULL) panic("lsra_main Lifetime for Stackslot invalid\n");
+                       if (lt->local_ss == NULL) panic("lsra_main Lifetime Stackslot invalid\n");
 #endif
-                               type = lt->local_ss->s->type;
-                       }
+                       type = lt->local_ss->s->type;
                } else { /* local var */
                        if (rd->locals[lt->v_index][lt->type].type>=0) {
                                type = rd->locals[lt->v_index][lt->type].type;
@@ -582,16 +566,16 @@ void lsra_main(methodinfo *m, lsradata *ls, registerdata *rd)
        lsra_sort_lt(&(ls->lifetimes));
        lsra_sort_lt(&flt_lt);
 
+#ifdef LSRA_DEBUG
        for (lt_int_count=0,lt=int_lt; lt!=NULL;lt=lt->next,lt_int_count++);
        for (lt_flt_count=0,lt=flt_lt; lt!=NULL;lt=lt->next,lt_flt_count++);
        for (lt_left_count=0,lt=ls->lifetimes; lt!=NULL;lt=lt->next,lt_left_count++);
 
-#ifdef LSRA_DEBUG
        printf("\nLifetimes: %3i left: %3i Intlt: %3i Fltlt: %3i \n",lt_count,lt_left_count,lt_int_count,lt_flt_count);
-#endif
        if (lt_count != lt_int_count + lt_flt_count + lt_left_count) {
                panic ("lifetimes missing\n");
        } 
+#endif
        lsra_reg_use=rd->savintregcnt;
        if (int_lt!=NULL) {
                for (reg_count = 0; nregdescint[reg_count] != REG_END; reg_count++);
@@ -618,7 +602,6 @@ void lsra_main(methodinfo *m, lsradata *ls, registerdata *rd)
                }
                _lsra_main(m, ls, int_lt, reg, tmp_reg_count, sav_reg_count, &lsra_mem_use, &lsra_reg_use);
                if (lsra_reg_use > rd->savintregcnt) lsra_reg_use=rd->savintregcnt;
-/*             r->maxsavintreguse=lsra_reg_use; */
        }
        rd->maxsavintreguse= lsra_reg_use;
        lsra_reg_use=rd->savfltregcnt;
@@ -629,7 +612,7 @@ void lsra_main(methodinfo *m, lsradata *ls, registerdata *rd)
                reg=DMNEW(struct lsra_reg,reg_count);
                sav_reg_count=0;
                for (i=0; i<reg_count ; i++)
-                       if (nregdescfloat[i]==REG_SAV) {
+                       if ((nregdescfloat[i]==REG_SAV) || (m->isleafmethod && (nregdescfloat[i]==REG_ARG))) {
                                reg[sav_reg_count].reg_index=i;
                                reg[sav_reg_count].use=0;
                                sav_reg_count++;
@@ -644,7 +627,6 @@ void lsra_main(methodinfo *m, lsradata *ls, registerdata *rd)
                        }
                _lsra_main(m,ls, flt_lt, reg, tmp_reg_count, sav_reg_count, &lsra_mem_use, &lsra_reg_use);
                if (lsra_reg_use > rd->savfltregcnt) lsra_reg_use=rd->savfltregcnt;
-/*             r->maxsavfltreguse=0; */
        }
 
        rd->maxsavfltreguse=lsra_reg_use;
@@ -666,6 +648,9 @@ void lsra_main(methodinfo *m, lsradata *ls, registerdata *rd)
        else
                lsra_mem_use = 0;
 #endif
+#ifdef SPECIALMEMUSE
+       lsra_mem_use = rd->ifmemuse;
+#endif
 
 #ifdef LSRA_DEBUG
        printf("Alloc Rest\n");
@@ -680,7 +665,7 @@ void lsra_main(methodinfo *m, lsradata *ls, registerdata *rd)
 #endif
        lsra_alloc(m, rd, flt_lt,&lsra_mem_use);
 
-#ifdef LSRA_DEBUG
+#ifdef LSRA_PRINTLIFETIMES
        printf("Int RA complete \n");
        printf("Lifetimes after splitting int: \n");
        print_lifetimes(rd, int_lt);
@@ -722,11 +707,6 @@ void lsra_alloc(methodinfo *m, registerdata *rd, struct lifetime *lifet, int *me
                }
 
                if (lt->v_index < 0) {
-                       if (lt->s!=NULL) {
-                               lsra_setflags( &(lt->s->flags), flags);
-                               lt->s->regoff=regoff;
-                       }
-
                        for (n=lt->local_ss; n!=NULL; n=n->next) {
                                lsra_setflags( &(n->s->flags), flags);
                                n->s->regoff=regoff;
@@ -757,7 +737,7 @@ int lsra_getmem(struct lifetime *lt, struct freemem *fmem, int *mem_use)
        struct freemem *fm, *p;
 
        /* noch kein Speicher vergeben, oder alle Enden später */
-       if ((fmem->next == NULL) || (fmem->next->end >= lt->i_start)) /* wirklich >= oder reicht > */
+       if ((fmem->next == NULL) || (fmem->next->end > lt->i_start)) 
                fm=lsra_getnewmem(mem_use);
        else {
                /* Speicherstelle frei */
@@ -786,7 +766,6 @@ struct freemem *lsra_getnewmem(int *mem_use)
 void _lsra_main( methodinfo *m, lsradata *ls, struct lifetime *lifet,  struct lsra_reg *reg, int tmp_reg_count, int sav_reg_count, int *mem_use, int *reg_use)
 {
        struct lifetime *lt;
-/*     struct active_lt *a; */
        int i;
        int _reg_use;
        int reg_count, active_count;
@@ -871,7 +850,6 @@ void _lsra_expire_old_intervalls(struct lifetime *lt, struct lsra_reg *reg, stru
 
                for (i=0;reg[i].reg_index != alt->lt->reg;i++);
                reg[i].use=0;
-/*             FREE(alt,struct active_lt); */
                (*active_count)--;
        }
 }
@@ -894,12 +872,11 @@ void _spill_at_intervall(struct lifetime *lt, struct active_lt **active, int *ac
        if (*active == NULL) {
                lt->reg=-2;
                return;
-               panic("No Lifetime in Active List -> no free registers at all!\n");
        }
        /* get last intervall from active */
        for (alt1=alt=*active; alt->next != NULL; alt1=alt, alt=alt->next);
        
-       if (alt->lt->i_end > lt->i_end) {
+       if ((alt->lt->i_end > lt->i_end) && (alt->lt->usagecount < lt->usagecount)) {
                        lt->reg=alt->lt->reg;
                        alt->lt->reg=-1;
                
@@ -1019,12 +996,11 @@ void lsra_calc_lifetime_length(methodinfo *m, lsradata *ls, codegendata *cd, loo
        }
 
        /* extend lifetime within loops */
-
   
        for (num_loops=0,lc =ld->c_allLoops;lc!=NULL;num_loops++,lc=lc->next);
 
+       /* set up loops[i].b_first .b_last to hold the first and last node of all loops */
        loops=DMNEW(struct l_loop,num_loops);
-
        for (i=0,lc=ld->c_allLoops;i<num_loops;i++,lc=lc->next) {
 
                le = lc->nodes;
@@ -1040,8 +1016,6 @@ void lsra_calc_lifetime_length(methodinfo *m, lsradata *ls, codegendata *cd, loo
                loops[i].nesting=0;
        }
 
-/*     for (i=0;i<num_loops;i++) printf("loops[%2i] bfirst: %3i blast %3i nesting %3i\n",i,loops[i].b_first,loops[i].b_last,loops[i].nesting); */
-
        /* sort loops by b_first desc*/
        for (i=0; i<num_loops-1;i++) {
                for (j=i+1; j<num_loops;j++) {
@@ -1055,7 +1029,7 @@ void lsra_calc_lifetime_length(methodinfo *m, lsradata *ls, codegendata *cd, loo
                        }
                }
        }
-/*     for (i=0;i<num_loops;i++) printf("loops[%2i] bfirst: %3i blast %3i nesting %3i\n",i,loops[i].b_first,loops[i].b_last,loops[i].nesting); */
+
        /* check for nesting_level, overlapping */
        for (i=0; i<num_loops-1;i++) {
                /*! loops[i].b_first >= loops[i+1].b_first !*/
@@ -1066,13 +1040,12 @@ void lsra_calc_lifetime_length(methodinfo *m, lsradata *ls, codegendata *cd, loo
                                loops[i].b_first=-1;
                                loops[i].b_last=-1;
                        } else {
-                               /* nested loops */
                                loops[i].nesting++; /* only boolean if nested... */
                        }
                }
        }
-/*     for (i=0;i<num_loops;i++) printf("loops[%2i] bfirst: %3i blast %3i nesting %3i\n",i,loops[i].b_first,loops[i].b_last,loops[i].nesting); */
-                               
+
+       /* cumulate basicblocks[i].icount in block_loop[i].instr*/
        block_loop=DMNEW(struct b_loop, m->basicblockcount);
        for (i=0;i<m->basicblockcount; i++) {
                block_loop[i].loop=-1;
@@ -1082,6 +1055,7 @@ void lsra_calc_lifetime_length(methodinfo *m, lsradata *ls, codegendata *cd, loo
                        block_loop[i].instr=0;
        }
 
+       /* set block_loop[j].loop to loop index, if Basic Block is in this loop */
        for (i=0; i<num_loops;i++) {
                if (loops[i].b_first!=-1) {
                        /* valid loop */
@@ -1089,22 +1063,24 @@ void lsra_calc_lifetime_length(methodinfo *m, lsradata *ls, codegendata *cd, loo
                }
        }
 
+       /* now iterate through lifetimes and expand them */
        lt=ls->lifetimes;
        while(lt!=NULL) {
 
                if (ls->back_edge_panic) {
-                       lt->b_start=0;
                        lt->i_start=0;
-                       lt->b_end=m->basicblockcount-1;
                        lt->i_end=block_loop[m->basicblockcount-1].instr+m->basicblocks[m->basicblockcount-1].icount;
                } else {
-                       usage = 0;
+                       usage = 1;
                        il=lt->i_list;
                        blast=il->b_index;
                        ilast=il->instr;
                        while (il->next!=NULL) {
+                               if ((il->b_index != il->next->b_index) || ((il->b_index == il->next->b_index) && (il->instr != il->next->instr))) {
+                                       if (block_loop[il->b_index].loop == -1)
+                                               usage++; /* not in a loop */
+                               }
                                il=il->next;
-                               usage++;
                        }
                        bfirst=il->b_index;
                        ifirst=il->instr;
@@ -1127,8 +1103,8 @@ void lsra_calc_lifetime_length(methodinfo *m, lsradata *ls, codegendata *cd, loo
                                } 
                        }
 
-                       ilast+=block_loop[blast].instr;
-                       ifirst+=block_loop[bfirst].instr;
+                       ilast+=block_loop[blast].instr;   /* add icount of previous Basic Blocks */
+                       ifirst+=block_loop[bfirst].instr; /* add icount of previous Basic Blocks */
 
                        if ((j=block_loop[bfirst].loop)==-1)
                                j=block_loop[blast].loop;
@@ -1146,12 +1122,10 @@ void lsra_calc_lifetime_length(methodinfo *m, lsradata *ls, codegendata *cd, loo
                                }
                        }
 
-                       lt->length=ilast-ifirst;
-
-                       lt->b_start=bfirst;
-                       lt->b_end=blast;
                        lt->i_start=ifirst;
                        lt->i_end=ilast;
+                       i=ilast-ifirst;
+                       if (i==0) i=1;
                        lt->usagecount=usage;
                }
                lt=lt->next;
@@ -1167,72 +1141,146 @@ void lsra_calc_lifetime_length(methodinfo *m, lsradata *ls, codegendata *cd, loo
 #endif   
 }
 
+/* void lsra_sort_lt(struct lifetime **lifet) */
+/* { */
+/*     struct lifetime *lt, lt_new, *temp, *tmp; */
+
+/*     lt_new.next=NULL; */
+
+/*     for (lt=*lifet; lt!= NULL;) { */
+/*             temp=lt->next; */
+
+/*             for(tmp=&lt_new; (tmp->next!= NULL) && (tmp->next->i_start < lt->i_start); tmp=tmp->next); */
+/*             lt->next=tmp->next; */
+/*             tmp->next=lt; */
+/*             lt=temp; */
+/*     } */
+/*     *lifet=lt_new.next; */
+/* } */
+
+
+#define P_MAX 21
+void _lsra_merge_lt(struct lifetime **p, int i1, int i2)
+{
+       struct lifetime *iptr, *iptr1, *iptr2;
+
+       if ( (iptr1=p[i2])==NULL) return;
+    if ( (iptr=p[i1])==NULL) return;
+
+       iptr2=p[i1]=NULL;
+       p[i2]=NULL;
+
+       while  ((iptr != NULL) && (iptr1 != NULL)) {
+               if (iptr->i_start < iptr1->i_start) {
+                       if (iptr2==NULL) {
+                               p[i1]=iptr;
+                       } else {
+                               iptr2->next=iptr;
+                       }
+                       iptr2=iptr;
+                       iptr=iptr->next;
+               } else {
+                       if (iptr2==NULL) {
+                               p[i1]=iptr1;
+                       } else {
+                               iptr2->next=iptr1;
+                       }
+                       iptr2=iptr1;
+                       iptr1=iptr1->next;
+               }
+       }
+       if (iptr==NULL)
+               iptr2->next=iptr1;
+       if (iptr1==NULL)
+               iptr2->next=iptr;
+}
+
+void lsra_merge_lt(struct lifetime **p, int top)
+{
+       int i,j;
+
+       for (j=1; j<top; j*=2)
+               for (i=1; i<top; i+=2*j)
+                       _lsra_merge_lt(p, i, i+j);
+       _lsra_merge_lt(p, 0, 1);
+}
+       
 void lsra_sort_lt(struct lifetime **lifet)
 {
        /* sort lifetimes by increasing start point */
 /*     struct lifetime **plt,**plt1; */
-       struct lifetime *lt, lt_new, *temp, *tmp;
-/*     int swapped; */
+       struct lifetime *lt, *temp, *tmp;
+       int i, top;
+       struct lifetime **p;
 
-       /* lifetimes are sorted by decreasing start point -> just turn around */
-       /* not really correct through exception and loop lifetime expansion! -> turn around and sort in*/
-       lt_new.next=NULL;
+       p=DMNEW(struct lifetime *, P_MAX);
+       for (i=0; i<P_MAX; i++) p[i]=NULL;
+
+       top=0;
 
        for (lt=*lifet; lt!= NULL;) {
-               temp=lt->next;
+               temp=lt;
+               lt=lt->next;
+               if (lt == NULL) {
+                       p[top]=temp;
+                       temp->next=NULL;
+               } else {
+                       tmp=lt;
+                       lt=lt->next;
 
-               for(tmp=&lt_new; (tmp->next!= NULL) && (tmp->next->i_start < lt->i_start); tmp=tmp->next);
-               lt->next=tmp->next;
-               tmp->next=lt;
-               lt=temp;
+                       if (temp->i_start < tmp->i_start) {
+                               p[top]=temp;
+                               /* temp->next == tmp */
+                               tmp->next=NULL;
+                       } else {
+                               p[top]=tmp;
+                               tmp->next=temp;
+                               temp->next=NULL;
+                       }
+               }
+               top++;
+               if (top == P_MAX) {
+                       lsra_merge_lt(p, P_MAX);
+                       top=1;
+               }
        }
-       *lifet=lt_new.next;
+       lsra_merge_lt(p, top);
+       *lifet=p[0];
 }
 
-
+#ifdef LSRA_PRINTLIFETIMES
 void print_lifetimes(registerdata *rd, struct lifetime *lt)
 {
        struct lifetime *n;
        struct _i_list *ni;
        int type,flags,regoff,j,varkind;
-/*     int i; */
+       /*      int i; */
 
        for (n=lt,j=0; n!=NULL; n=n->next,j++) {
                if (n->v_index < 0) { /* stackslot */
-                       if (n->s != 0) { /* stackslot */
-                               type = n->s->type;
-                               flags=n->s->flags;
-                               regoff=n->s->regoff;
-                               varkind=n->s->varkind;
-                       } else {
-                               if (n->local_ss != 0) {
-                                       type = n->local_ss->s->type;
-                                       flags=n->local_ss->s->flags;
-                                       regoff=n->local_ss->s->regoff;
-                                       varkind=n->local_ss->s->varkind;
-                               }
-                       }
+                       type = n->local_ss->s->type;
+                       flags=n->local_ss->s->flags;
+                       regoff=n->local_ss->s->regoff;
+                       varkind=n->local_ss->s->varkind;
                } else { /* local var */
-/*                     for (i=TYPE_INT; i<=TYPE_ADR; i++) { */
-                               if (rd->locals[n->v_index][n->type].type>=0) {
-                                       type = rd->locals[n->v_index][n->type].type;
-                                       flags=rd->locals[n->v_index][n->type].flags;
-                                       regoff=rd->locals[n->v_index][n->type].regoff;
-                                       varkind=-1;
-                               } else panic("Type Data mismatch 3\n");
-/*                     } */
+                       if (rd->locals[n->v_index][n->type].type>=0) {
+                               type = rd->locals[n->v_index][n->type].type;
+                               flags=rd->locals[n->v_index][n->type].flags;
+                               regoff=rd->locals[n->v_index][n->type].regoff;
+                               varkind=-1;
+                       } else 
+                               panic("Type Data mismatch 3\n");
                }
-               printf("i_Start: %3i i_stop: %3i reg: %3i Index: %3i VI: %3i Usage: %3i length: %3i type: %3i flags: %3i varkind: %3i ILst: ",n->i_start,n->i_end,regoff,n->index,n->v_index,n->usagecount, n->length,type,flags, varkind);
+               printf("i_Start: %3i i_stop: %3i reg: %3i VI: %3i Usage: %3i type: %3i flags: %3i varkind: %3i ILst: ",n->i_start,n->i_end,regoff,n->v_index,n->usagecount,type,flags, varkind);
                for (ni=n->i_list; ni!=NULL; ni=ni->next) {
                        if (ni==ni->next) panic("loop in instruction list!\n");
                        printf( "(%3i,%3i) ",ni->b_index,ni->instr);
                }
                printf("\n");
-/*             if (n->s!=NULL) */
-/*                     printf("   type: %1i flags: %1i varkind: %1i varnum: %3i regoff: %4i\n",n->s->type,n->s->flags,n->s->varkind,n->s->varnum,n->s->regoff); */
        }
        printf( "%3i Lifetimes printed \n",j);
 }
+#endif
 
 struct stackslot *lsra_make_ss(stackptr s, int bb_index)
 {
@@ -1254,33 +1302,92 @@ void lsra_merge_i_lists(struct lifetime *lt, struct lifetime *lt1)
        iptr2=lt->i_list=NULL;
        iptr1=lt1->i_list;
        while  ((iptr != NULL) && (iptr1 != NULL)) {
-               if ((iptr->b_index > iptr1->b_index)|| ((iptr->b_index == iptr1->b_index) && (iptr->instr > iptr1->instr))) {
-                       if (lt->i_list==NULL) {
-                               lt->i_list=iptr;
-/*                             iptr2=lt->i_list; */
+               if (iptr1->instr == -1) { 
+                       /* throw away, just for joining */
+                       iptr1=iptr1->next;
+               } else {
+                       if ((iptr->b_index > iptr1->b_index)|| ((iptr->b_index == iptr1->b_index) && (iptr->instr > iptr1->instr))) {
+                               if (lt->i_list==NULL) {
+                                       lt->i_list=iptr;
+                               } else {
+                                       iptr2->next=iptr;
+                               }
+                               iptr2=iptr;
+                               iptr=iptr->next;
                        } else {
-                               iptr2->next=iptr;
+                               if (lt->i_list==NULL) {
+                                       lt->i_list=iptr1;
+                               } else {
+                                       iptr2->next=iptr1;
+                               }
+                               iptr2=iptr1;
+                               iptr1=iptr1->next;
                        }
-                       iptr2=iptr;
-                       iptr=iptr->next;
+               }
+       }
+#ifdef LSRA_DEBUG
+       if (iptr2 == NULL)
+               panic("lsra_merge_i_lists: Empty Instruction List in Lifetime\n");
+#endif
+       if (iptr==NULL) {
+               if (lt->i_list==NULL)
+                       lt->i_list=iptr1;
+               else
+                       iptr2->next=iptr1;
+       }
+       if (iptr1==NULL) {
+               if (lt->i_list==NULL)
+                       lt->i_list=iptr;
+               else
+                       iptr2->next=iptr;
+       }
+}
+
+/* merge local_ss from lt1 to lt in order */
+void lsra_merge_local_ss(struct lifetime *lt, struct lifetime *lt1)
+{
+       struct stackslot *ssptr, *ssptr1, *ssptr2;
+
+       /* merge stackslots in order */
+       ssptr=lt->local_ss;
+       ssptr2=lt->local_ss=NULL;
+       ssptr1=lt1->local_ss;
+       while  ((ssptr != NULL) && (ssptr1 != NULL)) {
+
+               if (ssptr->s > ssptr1->s) {
+                       if (lt->local_ss==NULL) {
+                               lt->local_ss=ssptr;
+                       } else {
+                               ssptr2->next=ssptr;
+                       }
+                       ssptr2=ssptr;
+                       ssptr=ssptr->next;
                } else {
-                       if (lt->i_list==NULL) {
-                               lt->i_list=iptr1;
-/*                             iptr2=lt->i_list; */
+                       if (lt->local_ss==NULL) {
+                               lt->local_ss=ssptr1;
                        } else {
-                               iptr2->next=iptr1;
+                               ssptr2->next=ssptr1;
                        }
-                       iptr2=iptr1;
-                       iptr1=iptr1->next;
+                       ssptr2=ssptr1;
+                       ssptr1=ssptr1->next;
                }
        }
 #ifdef LSRA_DEBUG
-       if (iptr2 == NULL) panic("lsra_merge_i_lists: Empty Instruction List in Lifetime\n");
+       if (ssptr2 == NULL)
+               panic("lsra_merge_local_ss: Empty Stackslot List in Lifetime\n");
 #endif
-       if (iptr==NULL)
-               iptr2->next=iptr1;
-       if (iptr1==NULL)
-               iptr2->next=iptr;
+       if (ssptr==NULL) {
+               if (lt->local_ss==NULL)
+                       lt->local_ss=ssptr1;
+               else
+                       ssptr2->next=ssptr1;
+       }
+       if (ssptr1==NULL) {
+               if (lt->local_ss==NULL)
+                       lt->local_ss=ssptr;
+               else
+                       ssptr2->next=ssptr;
+       }
 }
 
 #ifdef LSRA_DEBUG
@@ -1293,10 +1400,10 @@ void dump_join( struct lifetime *lt_passing)
        for (lt=lt_passing,i=0; lt != NULL; lt=lt->next, ++i) {
                printf("Lifetime(%2i)\n  PT: ",i);
                for ( ss=lt->passthrough; ss!=NULL; ss=ss->next)
-                       printf("(%2i, %2i, %6p) ",ss->bb, ss->s->varnum, ss->s);
+                       printf("(%2i, %2i, %6p) ",ss->bb, ss->s->varnum, (void *)ss->s);
                printf("\n  SS: ");
                for (ss = lt->local_ss; ss!=NULL; ss=ss->next)
-                       printf("(%2i, %2i, %6p) ", ss->bb, ss->s->varnum, ss->s);
+                       printf("(%2i, %2i, %6p) ", ss->bb, ss->s->varnum, (void *)ss->s);
                printf("\n");
        }
 }
@@ -1310,10 +1417,10 @@ void lsra_join_lifetimes(methodinfo *m, codegendata *cd, lsradata *ls, loopdata
        
        int *in_stacks, *out_stacks;
        stackptr out, s;
-       struct stackslot **stacks, *ss, *ss_new;
+       struct stackslot **stacks, *ss, *ss1, *ss_new;
        struct lifetime *lt, *lt_prev, *lt_new, *lt_passing;
        struct stackslot *p, *q, *r;
-       bool drop;
+       bool drop, pt;
 
 #ifdef LSRA_DEBUG
        stackptr in;
@@ -1390,7 +1497,10 @@ void lsra_join_lifetimes(methodinfo *m, codegendata *cd, lsradata *ls, loopdata
                        for (ss=stacks[i]; ss!=NULL; ss=ss->next) {
                                /* search stackslot ss->s lifetimelist of basicblock(ss->bb) (ss_lifetimes) */
                                /* remember the link before found lifetime, to remove it afterwards         */
-                               for (lt_prev=lt=ls->ss_lifetimes[ss->bb]; (lt!=NULL) && (lt->s != ss->s); lt_prev=lt, lt=lt->next);
+                               for (lt_prev=lt=ls->ss_lifetimes[ss->bb]; lt!=NULL; lt_prev=lt, lt=lt->next) {
+                                       for (ss1=lt->local_ss; (ss1!=NULL) && (ss1->s != ss->s); ss1 = ss1->next);
+                                       if (ss1 != NULL) break; /* found */
+                               }
 #ifdef LSRA_DEBUG
                                if (lt==NULL) panic("lsra_join_lifetimes error in lifetimelist\n");
 #endif
@@ -1406,37 +1516,36 @@ void lsra_join_lifetimes(methodinfo *m, codegendata *cd, lsradata *ls, loopdata
                                if (lt->i_list->instr==-1) {
                                        if (out_stacks[in_stacks[ss->bb]] == out_stacks[ss->bb]) {
                                                /* Throughpassing Basicblock is already in one "join Group" */
-                                               /* If this stackslot (lt->s == ss->s) is already in lt_new->local_ss */
+                                               /* If this stackslot ((lt->local_ss)ss1->s == ss->s) is already in lt_new->local_ss */
                                                /* do not add it a second time! */
                                                if (lt_new != NULL) {
-                                                       for (ss_new=lt_new->local_ss; (ss_new != NULL) && (ss_new->s != lt->s); ss_new = ss_new->next);
+                                                       for (ss_new=lt_new->local_ss; (ss_new != NULL) && (ss_new->s != ss1->s); ss_new = ss_new->next);
                                                        if (ss_new != NULL) drop = true;
                                                }
                                        }
                                }
                                if (!drop) {
-                                       lt->s->varkind=TEMPVAR; /* no LOCALVAR, ARGVAR or STACKVAR with joined lifetimes */
+                                       /* lt->s->varkind=TEMPVAR */; /* no LOCALVAR, ARGVAR or STACKVAR with joined lifetimes */
                                        lt->v_index=-1; /* not a local var */
 
                                        /* join Lifetime lt to lt_new */
                                        if (lt_new == NULL) {
                                                lt_new = lt;
                                                lt_new->passthrough = NULL;
-                                               lt_new->s = NULL;     /* Stackslots are all in local_ss for joined lifetimes */
-                                       } else
+                                       } else {
                                                lsra_merge_i_lists( lt_new, lt);
+                                               lsra_merge_local_ss( lt_new, lt);
+                                       }
+
+
+                                       pt=(lt->i_list->instr==-1); /* remember this now, because merge_i_list could once destroy this link*/
 
                                        /* add stackslot to local_ss of lt_new */
                                        ss_new = DNEW(struct stackslot);
-                                       ss_new->s = ss->s;
-                                       ss_new->bb = ss->bb; /* for debugging only, has no further use */
-                                       ss_new->next = lt_new->local_ss;
-                                       lt_new->local_ss = ss_new;
                                        
                                        lt_new->savedvar |= (lt->savedvar & SAVEDVAR);
 
-
-                                       if (lt->i_list->instr==-1) {
+                                       if (pt) { /*lt->i_list->instr==-1) {*/
                                        /* BB passes this stackslot through -> join later with other side!*/
                                                if (out_stacks[in_stacks[ss->bb]] != out_stacks[ss->bb]) { 
                                                        /* Stackslot ist not passed through to same (this) "join group" */
@@ -1537,9 +1646,10 @@ void lsra_join_lifetimes(methodinfo *m, codegendata *cd, lsradata *ls, loopdata
                        if (lt_new->next->local_ss == NULL)
                                panic("lsra_join_lifetimes Lifetime without stackslot\n");
 #endif
-                       for (ss=lt_new->next->local_ss; (ss->next != NULL); ss=ss->next);
-                       ss->next=lt->local_ss;
-                       lt->local_ss=lt_new->next->local_ss;
+/*                     for (ss=lt_new->next->local_ss; (ss->next != NULL); ss=ss->next); */
+/*                     ss->next=lt->local_ss; */
+/*                     lt->local_ss=lt_new->next->local_ss; */
+                       lsra_merge_local_ss(lt, lt_new->next);
 
                        /* merge i_lists in order */
                        lsra_merge_i_lists(lt, lt_new->next);
@@ -1636,16 +1746,15 @@ void _lsra_new_stack(lsradata *ls, stackptr s, int block, int instr, int store)
 
        n=DNEW(struct lifetime);
 
-       n->index=s->varnum;
        n->savedvar = (s->flags & SAVEDVAR);
-       n->s=s;
+       n->local_ss=NULL;
+       lsra_add_ss( n, s);
        n->usagecount=1;
-       if (n->s->varkind == LOCALVAR)
-               n->v_index=n->s->varnum;
+       if (s->varkind == LOCALVAR)
+               n->v_index=s->varnum;
        else
                n->v_index=-1;
        n->i_list=NULL;
-       n->local_ss=NULL;
 
        n->next=ls->ss_lifetimes[block];
        ls->ss_lifetimes[block]=n;
@@ -1658,15 +1767,14 @@ void _lsra_new_stack(lsradata *ls, stackptr s, int block, int instr, int store)
 void _lsra_from_stack(lsradata *ls, stackptr s, int block, int instr, int store)
 {
        struct lifetime *n;
-       
-       for (n=ls->ss_lifetimes[block]; (n!=NULL) && (n->s!=s);n=n->next);
+       /* ss_lifetimes[block]->local_ss have exactly one entry! */
+       for (n=ls->ss_lifetimes[block]; (n!=NULL) && (n->local_ss->s!=s);n=n->next);
        if (n==NULL) {
                _lsra_new_stack(ls, s, block, instr, store);
                /* ist mit dem neuen joinen hinterher immer so, wenn ein Stackslot in einen BB "reinkommt" */
 /*             printf("type %i flags %i  varkind %i varnum %i regoff %i \n",s->type,s->flags ,s->varkind ,s->varnum ,s->regoff); */
 /*             panic("lsra_from_stack: Var on Stack not found"); */
        } else {
-               n->usagecount++;
                n->i_list=lsra_add_i_list(n->i_list, instr, block, store);
        }
 }
@@ -1688,7 +1796,6 @@ void lsra_usage_local(lsradata *ls, s4 v_index, int type, int block, int instr,
        }
        /* add access at (block, instr) to intruction list */
        n->i_list=lsra_add_i_list(n->i_list, instr, block, store);
-       n->usagecount++;
 }      
 
 void lsra_new_local(lsradata *ls, s4 v_index, int type)
@@ -1698,11 +1805,8 @@ void lsra_new_local(lsradata *ls, s4 v_index, int type)
        n=DNEW(struct lifetime);
        n->local_ss=NULL;
        n->i_list=NULL;
-       n->index=v_index;
        n->v_index=v_index;
-       n->s=NULL;
        n->type=type;
-       n->usagecount=0;
        n->savedvar = SAVEDVAR;
 
        n->next=ls->locals_lifetimes[v_index];
@@ -1720,6 +1824,81 @@ void lsra_dump_stack(stackptr s)
 }
 #endif
 
+void dup_mark( struct dup *dup,stackptr s)
+{
+       struct stackslot *n;
+       n = DNEW(struct stackslot);
+       if (dup->ss == NULL) {
+               dup->ss = n;
+               n->next = NULL;
+       } else {
+               n->next=dup->ss;
+               dup->ss=n;
+       }
+       n->s=s;
+}
+
+void dup_next( struct dup *dup)
+{
+       struct dup *n;
+
+       n = DNEW(struct dup);
+       n->next = dup->next;
+       dup->next=n;
+       n->ss = dup->ss;
+       dup->ss = NULL;
+}
+
+void dup_join( struct lsradata *ls, struct dup *dup, int block)
+{
+       struct dup *d;
+       struct stackslot *ss, *ss1;
+       bool pt; /* joins with passthrough lifetimes not yet possible! */
+       struct lifetime *join_lt[3]; /* max three lifetimes to join */
+       struct lifetime *join_lt_prev[3]; /* previous elements for unlinking */
+       struct lifetime *lt, *lt_prev;
+       int i, join_lt_top, join_to;
+
+       for (i=0; i<3; i++) join_lt[i]=join_lt_prev[i]=NULL;
+       /* walk through dup structure and clean it up for next block */
+       /* the first dup entry is alway empty for the next group to come*/
+       for (d=dup->next; d!= NULL; d = dup->next=dup->next->next) { 
+               pt=false;
+               join_lt_top=0;
+               for (ss=d->ss; (ss != NULL) && (!pt); ss = ss->next) {
+                       for (lt = lt_prev = ls->ss_lifetimes[block]; lt != NULL ; lt_prev=lt, lt=lt->next) {
+                               for (ss1=lt->local_ss; (ss1!=NULL) && (ss1->s != ss->s); ss1 = ss1->next);
+                               if (ss1 != NULL) break; /* found */
+                       }
+                       if (lt == NULL) panic("dup_join Lifetimes not found\n");
+                       pt=(lt->i_list->instr == -1); /* joins with passthrough lifetimes not yet possible! */
+                       pt|=(lt->i_list->next == NULL); /* joins with "interface" Stackslots not yet possible! */
+                       if (!pt) {
+                               join_lt_prev[join_lt_top]=lt_prev;
+                               join_lt[join_lt_top++]=lt;
+                       }
+               }
+               if (!pt) { /* now join */
+                       /* look if one element is the root of the list (joint_lt == join_lt_prev == ls->ss_lifetimes[block]) */
+                       for (join_to=0; (join_to < join_lt_top) && (join_lt[join_to] != join_lt_prev[join_to]); join_to++);
+                       if (join_to == join_lt_top) /* no root element in join array */
+                               join_to=0;
+                       join_lt[join_to]->v_index = -1;
+                       for (i=0; i<join_lt_top; i++) {
+                               if (i != join_to) {
+                                       /* now join finally */
+                                       lsra_merge_i_lists(join_lt[join_to], join_lt[i]);
+                                       lsra_merge_local_ss(join_lt[join_to], join_lt[i]);
+                                       join_lt[join_to]->savedvar|=(join_lt[i]->savedvar & SAVEDVAR);
+                                       /* drop join_lt[i] from list */
+                                       join_lt_prev[i]->next = join_lt[i]->next;
+                               }
+                       }
+               }
+       }
+       dup->next = NULL;
+}
+
 void lsra_scan_registers_canditates(methodinfo *m, lsradata *ls)
 {
        int i;
@@ -1731,9 +1910,12 @@ void lsra_scan_registers_canditates(methodinfo *m, lsradata *ls)
        instruction *iptr;
        stackptr in,out;
        int      id, od;
-
        int b_index;
-
+       struct dup dup;
+       
+       dup.ss=NULL;
+       dup.next=NULL;
+       
        b_index=0;
        while (b_index < m->basicblockcount ) {
 
@@ -1766,7 +1948,6 @@ void lsra_scan_registers_canditates(methodinfo *m, lsradata *ls)
                                        /* Make 2 entries -> one for the instack, one for the out stack */
                                        lsra_new_stack(ls, in, b_index, -1);
                                        lsra_new_stack(ls, in, b_index, -1);
-                                       /*                                      } */
                                }
                        }
                        iptr = m->basicblocks[b_index].iinstr;
@@ -1963,8 +2144,10 @@ void lsra_scan_registers_canditates(methodinfo *m, lsradata *ls)
                                        /* merge dupped vars??? */
                                case ICMD_DUP:
                                        /* lsra_from_stack(ls, src,b_index,iindex);*/ /* inc usage_count! */
-/*                                     dup_alignstackslots(src, dst); */
                                        lsra_new_stack(ls,dst,b_index,iindex);
+                                       dup_mark(&dup, src);
+                                       dup_mark(&dup, dst);
+                                       dup_next(&dup);
                                        break;
 
                                        /* pop 0 push 2 dup */
@@ -1972,10 +2155,17 @@ void lsra_scan_registers_canditates(methodinfo *m, lsradata *ls)
                                case ICMD_DUP2:
                                        lsra_new_stack(ls,dst->prev,b_index,iindex);
                                        lsra_new_stack(ls,dst,b_index,iindex); 
-/*                                     dup_alignstackslots(src, dst); */
-/*                                     dup_alignstackslots(src->prev, dst->prev); */
                                        lsra_from_stack(ls, src,b_index,iindex); /* or inc usage_count! */
                                        lsra_from_stack(ls, src->prev,b_index,iindex); /* inc usage_count! */
+
+                                       dup_mark(&dup, src);
+                                       dup_mark(&dup, dst);
+                                       dup_mark(&dup, dst->prev->prev);
+                                       dup_next(&dup);
+                                       dup_mark(&dup, src->prev);
+                                       dup_mark(&dup, dst->prev);
+                                       dup_mark(&dup, dst->prev->prev->prev);
+                                       dup_next(&dup);
                                        break;
 
                                        /* pop 2 push 3 dup */
@@ -1983,12 +2173,16 @@ void lsra_scan_registers_canditates(methodinfo *m, lsradata *ls)
                                case ICMD_DUP_X1:
                                        lsra_from_stack(ls, src,b_index,iindex); /* from for to, or it will not work! inc usage_count! */
                                        lsra_from_stack(ls, src->prev,b_index,iindex); /*from for to, or it will not work!  inc usage_count! */
-/*                                     dup_alignstackslots(src, dst); */
-/*                                     dup_alignstackslots(src->prev, dst->prev); */
-/*                                     dup_alignstackslots(src, dst->prev->prev); */
                                        lsra_new_stack(ls,dst->prev->prev,b_index,iindex);
                                        lsra_new_stack(ls,dst->prev,b_index,iindex);
                                        lsra_new_stack(ls,dst,b_index,iindex); 
+                                       dup_mark(&dup, src);
+                                       dup_mark(&dup, dst);
+                                       dup_mark(&dup, dst->prev->prev);
+                                       dup_next(&dup);
+                                       dup_mark(&dup, src->prev);
+                                       dup_mark(&dup, dst->prev);
+                                       dup_next(&dup);
                                        break;
 
                                        /* pop 3 push 4 dup */
@@ -1997,14 +2191,20 @@ void lsra_scan_registers_canditates(methodinfo *m, lsradata *ls)
                                        lsra_from_stack(ls, src,b_index,iindex); /* from for to, or it will not work! inc usage_count! */
                                        lsra_from_stack(ls, src->prev,b_index,iindex); /*from for to, or it will not work!  inc usage_count! */
                                        lsra_from_stack(ls, src->prev->prev,b_index,iindex); /*from for to, or it will not work!  inc usage_count! */
-/*                                     dup_alignstackslots(src, dst); */
-/*                                     dup_alignstackslots(src->prev, dst->prev); */
-/*                                     dup_alignstackslots(src->prev->prev, dst->prev->prev); */
-/*                                     dup_alignstackslots(src, dst->prev->prev->prev); */
                                        lsra_new_stack(ls,dst->prev->prev->prev,b_index,iindex);
                                        lsra_new_stack(ls,dst->prev->prev,b_index,iindex);
                                        lsra_new_stack(ls,dst->prev,b_index,iindex);
                                        lsra_new_stack(ls,dst,b_index,iindex); 
+                                       dup_mark(&dup, src);
+                                       dup_mark(&dup, dst);
+                                       dup_mark(&dup, dst->prev->prev->prev);
+                                       dup_next(&dup);
+                                       dup_mark(&dup, src->prev);
+                                       dup_mark(&dup, dst->prev);
+                                       dup_next(&dup);
+                                       dup_mark(&dup, src->prev->prev);
+                                       dup_mark(&dup, dst->prev->prev);
+                                       dup_next(&dup);
                                        break;
 
                                        /* pop 3 push 5 dup */
@@ -2013,16 +2213,22 @@ void lsra_scan_registers_canditates(methodinfo *m, lsradata *ls)
                                        lsra_from_stack(ls, src,b_index,iindex); /* from for to, or it will not work! inc usage_count! */
                                        lsra_from_stack(ls, src->prev,b_index,iindex); /*from for to, or it will not work!  inc usage_count! */
                                        lsra_from_stack(ls, src->prev->prev,b_index,iindex); /*from for to, or it will not work!  inc usage_count! */
-/*                                     dup_alignstackslots(src, dst); */
-/*                                     dup_alignstackslots(src->prev, dst->prev); */
-/*                                     dup_alignstackslots(src->prev->prev, dst->prev->prev); */
-/*                                     dup_alignstackslots(src, dst->prev->prev->prev); */
-/*                                     dup_alignstackslots(src->prev, dst->prev->prev->prev->prev); */
                                        lsra_new_stack(ls,dst->prev->prev->prev->prev,b_index,iindex);
                                        lsra_new_stack(ls,dst->prev->prev->prev,b_index,iindex);
                                        lsra_new_stack(ls,dst->prev->prev,b_index,iindex);
                                        lsra_new_stack(ls,dst->prev,b_index,iindex);
                                        lsra_new_stack(ls,dst,b_index,iindex); 
+                                       dup_mark(&dup, src);
+                                       dup_mark(&dup, dst);
+                                       dup_mark(&dup, dst->prev->prev->prev);
+                                       dup_next(&dup);
+                                       dup_mark(&dup, src->prev);
+                                       dup_mark(&dup, dst->prev);
+                                       dup_mark(&dup, dst->prev->prev->prev->prev);
+                                       dup_next(&dup);
+                                       dup_mark(&dup, src->prev->prev);
+                                       dup_mark(&dup, dst->prev->prev);
+                                       dup_next(&dup);
                                        break;
 
                                        /* pop 4 push 6 dup */
@@ -2032,18 +2238,26 @@ void lsra_scan_registers_canditates(methodinfo *m, lsradata *ls)
                                        lsra_from_stack(ls, src->prev,b_index,iindex); /*from for to, or it will not work!  inc usage_count! */
                                        lsra_from_stack(ls, src->prev->prev,b_index,iindex); /*from for to, or it will not work!  inc usage_count! */
                                        lsra_from_stack(ls, src->prev->prev->prev,b_index,iindex); /*from for to, or it will not work!  inc usage_count! */
-/*                                     dup_alignstackslots(src, dst); */
-/*                                     dup_alignstackslots(src->prev, dst->prev); */
-/*                                     dup_alignstackslots(src->prev->prev, dst->prev->prev); */
-/*                                     dup_alignstackslots(src->prev->prev->prev, dst->prev->prev->prev); */
-/*                                     dup_alignstackslots(src, dst->prev->prev->prev->prev); */
-/*                                     dup_alignstackslots(src->prev, dst->prev->prev->prev->prev->prev); */
                                        lsra_new_stack(ls,dst->prev->prev->prev->prev->prev,b_index,iindex);
                                        lsra_new_stack(ls,dst->prev->prev->prev->prev,b_index,iindex);
                                        lsra_new_stack(ls,dst->prev->prev->prev,b_index,iindex);
                                        lsra_new_stack(ls,dst->prev->prev,b_index,iindex);
                                        lsra_new_stack(ls,dst->prev,b_index,iindex);
                                        lsra_new_stack(ls,dst,b_index,iindex); 
+                                       dup_mark(&dup, src);
+                                       dup_mark(&dup, dst);
+                                       dup_mark(&dup, dst->prev->prev->prev->prev);
+                                       dup_next(&dup);
+                                       dup_mark(&dup, src->prev);
+                                       dup_mark(&dup, dst->prev);
+                                       dup_mark(&dup, dst->prev->prev->prev->prev->prev);
+                                       dup_next(&dup);
+                                       dup_mark(&dup, src->prev->prev);
+                                       dup_mark(&dup, dst->prev->prev);
+                                       dup_next(&dup);
+                                       dup_mark(&dup, src->prev->prev->prev);
+                                       dup_mark(&dup, dst->prev->prev->prev);
+                                       dup_next(&dup);
                                        break;
 
                                        /* pop 2 push 2 swap */
@@ -2051,10 +2265,14 @@ void lsra_scan_registers_canditates(methodinfo *m, lsradata *ls)
                                case ICMD_SWAP:
                                        lsra_from_stack(ls, src,b_index,iindex); /* from for to, or it will not work! inc usage_count! */
                                        lsra_from_stack(ls, src->prev,b_index,iindex); /*from for to, or it will not work!  inc usage_count! */
-/*                                     dst->varnum = src->varnum; */
-/*                                     dst->varkind = src->varkind; */
                                        lsra_new_stack(ls,dst->prev,b_index,iindex);
                                        lsra_new_stack(ls,dst,b_index,iindex);
+                                       dup_mark(&dup, src);
+                                       dup_mark(&dup, dst->prev);
+                                       dup_next(&dup);
+                                       dup_mark(&dup, src->prev);
+                                       dup_mark(&dup, dst);
+                                       dup_next(&dup);
                                        break;
 
                                        /* pop 2 push 1 */
@@ -2232,7 +2450,7 @@ void lsra_scan_registers_canditates(methodinfo *m, lsradata *ls)
                        } /* while instructions */
                } /* if */
                
-
+               dup_join(ls, &dup, b_index);
 
                b_index++;
        } /* while blocks */