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;
struct freemem *next;
};
-struct sss {
- int bb;
- bool out;
- struct sss *next;
+struct dup {
+ struct stackslot *ss;
+ struct dup *next;
};
typedef struct lsradata lsradata;
#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
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 );
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"
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
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)
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");
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
}
}
- 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;) {
#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);
exceptiontable *ex;
struct depthElement **table;
bool back_edge;
-#ifdef LSRA_DEBUG
struct LoopContainer *lc;
- struct LoopElement *le;
-#endif
table=ld->c_dTable;
#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);
}
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....");
/* 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
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;
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;
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++);
}
_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;
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++;
}
_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;
else
lsra_mem_use = 0;
#endif
+#ifdef SPECIALMEMUSE
+ lsra_mem_use = rd->ifmemuse;
+#endif
#ifdef LSRA_DEBUG
printf("Alloc Rest\n");
#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);
}
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;
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 */
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;
for (i=0;reg[i].reg_index != alt->lt->reg;i++);
reg[i].use=0;
-/* FREE(alt,struct active_lt); */
(*active_count)--;
}
}
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;
}
/* 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;
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++) {
}
}
}
-/* 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 !*/
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;
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 */
}
}
+ /* 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;
}
}
- 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;
}
}
- 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;
#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=<_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=<_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)
{
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
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");
}
}
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;
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
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" */
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);
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;
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);
}
}
}
/* 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)
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];
}
#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;
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 ) {
/* 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;
/* 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 */
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 */
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 */
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 */
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 */
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 */
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 */
} /* while instructions */
} /* if */
-
+ dup_join(ls, &dup, b_index);
b_index++;
} /* while blocks */
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;
struct freemem *next;
};
-struct sss {
- int bb;
- bool out;
- struct sss *next;
+struct dup {
+ struct stackslot *ss;
+ struct dup *next;
};
typedef struct lsradata lsradata;
#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
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 );
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"
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
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)
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");
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
}
}
- 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;) {
#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);
exceptiontable *ex;
struct depthElement **table;
bool back_edge;
-#ifdef LSRA_DEBUG
struct LoopContainer *lc;
- struct LoopElement *le;
-#endif
table=ld->c_dTable;
#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);
}
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....");
/* 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
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;
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;
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++);
}
_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;
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++;
}
_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;
else
lsra_mem_use = 0;
#endif
+#ifdef SPECIALMEMUSE
+ lsra_mem_use = rd->ifmemuse;
+#endif
#ifdef LSRA_DEBUG
printf("Alloc Rest\n");
#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);
}
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;
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 */
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;
for (i=0;reg[i].reg_index != alt->lt->reg;i++);
reg[i].use=0;
-/* FREE(alt,struct active_lt); */
(*active_count)--;
}
}
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;
}
/* 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;
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++) {
}
}
}
-/* 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 !*/
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;
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 */
}
}
+ /* 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;
}
}
- 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;
}
}
- 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;
#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=<_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=<_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)
{
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
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");
}
}
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;
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
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" */
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);
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;
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);
}
}
}
/* 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)
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];
}
#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;
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 ) {
/* 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;
/* 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 */
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 */
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 */
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 */
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 */
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 */
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 */
} /* while instructions */
} /* if */
-
+ dup_join(ls, &dup, b_index);
b_index++;
} /* while blocks */