1 /* src/vm/jit/lsra.inc - linear scan register allocator
3 Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4 R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5 C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6 Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 Contact: cacao@complang.tuwien.ac.at
27 Authors: Christian Ullrich
29 $Id: lsra.inc 2297 2005-04-13 12:50:07Z christian $
35 #include "mm/memory.h"
36 #include "vm/options.h"
37 #include "vm/jit/lsra.h"
38 #include "vm/jit/reg.h"
39 #include "vm/statistics.h"
41 bool lsra(methodinfo *m, codegendata *cd, registerdata *rd, t_inlining_globals *id)
45 #if defined(STATISTICS)
49 #if defined(LSRA_DEBUG) || defined(LSRA_LEAF)
50 char name[1256], name1[1256];
53 #if defined(LSRA_DEBUG)
59 while (b_index < m->basicblockcount ) {
61 if (m->basicblocks[b_index].flags >= BBREACHED) {
63 in=m->basicblocks[b_index].instack;
64 ind=m->basicblocks[b_index].indepth;
65 for (;ind != 0;in=in->prev, ind--) {
66 if (in->varkind == ARGVAR) printf("ARGVAR in instack: \n"); /*ARGVAR in instack ok*/
67 if (in->varkind == LOCALVAR) printf("LOCALVAR in instack\n");
69 out=m->basicblocks[b_index].outstack;
70 outd=m->basicblocks[b_index].outdepth;
71 for (;outd != 0;out=out->prev, outd--) {
72 if (out->varkind == ARGVAR) panic("ARGVAR in outstack\n");
73 if (out->varkind == LOCALVAR) panic("LOCALVAR in outstack\n");
80 #if defined(LSRA_DEBUG) || defined(LSRA_LEAF)
81 utf_sprint(name, m->class->name);
82 utf_sprint(name1, m->name);
85 utf_sprint(name1, m->descriptor);
89 printf("/******************************************************/\n");
94 printf("LSRA Start for %s opt_from: %i opt_to: %i\n", name, opt_from, opt_to);
96 if (strcmp(name,"java/lang/ClassLoader.defaultGetSystemClassLoader()Ljava/lang/ClassLoader;")==0) {
97 printf("-------------------\n");
100 printf("**Leafmethod**\n");
105 lsra_init(m, cd, id, ls);
108 #if defined(LSRA_USES_REG_RES)
109 for (i=opt_from; i<=opt_to; i++) {
110 icmd_uses_reg_res[i][0]=S|D|YES;
111 icmd_uses_reg_res[i][1]=S|D|YES;
112 icmd_uses_reg_res[i][2]=S|D|YES;
113 icmd_uses_reg_res[i][3]=REG_NULL;
119 if (!lsra_setup(m, cd, rd, ls))
123 #if defined(STATISTICS)
124 /* find conflicts between locals for statistics */
126 /* local Variable Lifetimes are at the end of the lifetime array and have v_index >= 0 */
127 for (locals_start = ls->lifetimecount-1; (locals_start >=0) && (ls->lifetime[ls->lt_used[locals_start]].v_index >= 0); locals_start--);
128 for (i=locals_start + 1; i < ls->lifetimecount; i++)
129 for (j=i+1; j < ls->lifetimecount; j++)
130 if ( !((ls->lifetime[ls->lt_used[i]].i_end < ls->lifetime[ls->lt_used[j]].i_start) || (ls->lifetime[ls->lt_used[j]].i_end<ls->lifetime[ls->lt_used[i]].i_start)) )
131 count_locals_conflicts += 2;
135 lsra_main(m, ls, rd, cd);
140 void lsra_DFS_(lsradata *ls, bool *mark, int bblock, int *n) {
146 for (p=ls->pred[bblock]; p != NULL; p=p->next)
147 lsra_DFS_(ls, mark, p->value, n);
148 ls->sorted[*n]=bblock;
153 void lsra_DFS(methodinfo *m, lsradata *ls) {
157 mark=DMNEW(bool, m->basicblockcount);
158 n=m->basicblockcount;
160 for (i=0; i <= m->basicblockcount; i++) mark[i]=false;
162 lsra_DFS_(ls, mark, m->basicblockcount, &n);
166 void lsra_DFS_2(methodinfo *m, lsradata *ls) {
174 stack = DMNEW( int, m->basicblockcount + 1);
175 visited = DMNEW( bool, m->basicblockcount + 1);
176 for (i = 0; i <= m->basicblockcount; i++) {
179 ls->sorted_rev[i]=-1;
182 stack[0] = 0; /* start with Block 0 */
184 visited[0] = ls->num_pred[0]; /* Start Block is handled right and can be put in sorted */
185 p = 0; /*m->basicblockcount;*/
187 while (not_finished) {
188 while (stack_top != 0) {
190 i = stack[stack_top];
193 for (succ = ls->succ[i]; succ != NULL; succ = succ->next) {
194 visited[succ->value]++;
195 if (visited[succ->value] == ls->num_pred[succ->value]) {
196 /* push the node on the stack, only if all ancestors have been visited */
197 stack[stack_top] = succ->value;
202 not_finished = false;
203 for (i=1; i <= m->basicblockcount; i++) {
204 /* search for visited blocks, which have not reached the num_pred */
205 /* and put them on the stack -> happens with backedges */
206 if ((visited[i] != 0) && (visited[i] < ls->num_pred[i])) {
207 stack[stack_top] = i;
209 visited[i] = ls->num_pred[i];
217 void lsra_get_backedges( methodinfo *m, lsradata *ls) {
218 struct _list **next, *s;
220 struct _backedge *_backedges;
225 /* todofirst remove artificial end basicblock from ls->sorted, succ and pred */
227 for (i=0; i < m->basicblockcount; i++) {
228 for (next=&(ls->succ[i]); *next != NULL; next=&((*next)->next)) {
229 if ( (*next)->value == m->basicblockcount ) { /* artificial end bb found */
230 *next = (*next)->next;
231 if (*next == NULL) break;
234 for (next=&(ls->pred[i]); *next != NULL; next=&((*next)->next)) {
235 if ( (*next)->value == m->basicblockcount ) { /* artificial end bb found */
236 *next = (*next)->next;
237 if (*next == NULL) break;
241 if (ls->sorted[i] == m->basicblockcount) j=i;
244 for (i=j+1; i <= m->basicblockcount; i++)
245 ls->sorted[i-1]=ls->sorted[i];
246 for (i=0; i < m->basicblockcount; i++)
247 if (ls->sorted[i] != -1)
248 ls->sorted_rev[ls->sorted[i]]=i;
249 /* now look for backedges */
250 ls->backedge_count = 0;
251 for(i=0; i < m->basicblockcount; i++) {
252 if (ls->sorted[i] != -1)
253 for(s=ls->succ[ls->sorted[i]]; s != NULL; s=s->next) {
254 if (i >= ls->sorted_rev[s->value]) {
255 n=DNEW(struct _backedge);
256 n->start = max(i, ls->sorted_rev[s->value]);
257 n->end = min(i, ls->sorted_rev[s->value]);
258 n->next = _backedges;
260 ls->backedge_count++;
261 /* printf("Backedge: %i %i\n", ls->sorted[i], s->value); */
265 /* put _backedges in ls->backedge array */
266 ls->backedge = DMNEW(struct _backedge *, ls->backedge_count);
267 for (n=_backedges, i=0; n != NULL; n=n->next, i++)
269 /* union backedges? */
270 /* - sort backedge by increasing start: */
271 /* printf("unsorted: \n"); */
272 /* for (i=0; i < ls->backedge_count; i++) */
273 /* printf("Backedge: %i - %i, %i - %i\n",ls->sorted[ls->backedge[i]->start],ls->sorted[ls->backedge[i]->end],ls->backedge[i]->start, ls->backedge[i]->end); */
274 for (i=0; i < ls->backedge_count; i++)
275 for (j=i+1; j < ls->backedge_count; j++)
276 if (ls->backedge[i]->start > ls->backedge[j]->start) { /* -> swap */
278 ls->backedge[i]=ls->backedge[j];
281 /* create ls->nesting */
282 for (i=0; i < ls->backedge_count; i++)
283 for (j=ls->backedge[i]->end; j<=ls->backedge[i]->start; j++)
286 printf("sorted: \n");
287 for (i=0; i < ls->backedge_count; i++)
288 printf("Backedge: %i - %i, %i - %i\n",ls->sorted[ls->backedge[i]->start],ls->sorted[ls->backedge[i]->end],ls->backedge[i]->start, ls->backedge[i]->end);
289 printf("Nesting Level \n");
290 for (i=0; i<m->basicblockcount; i++) printf(" %3li", ls->nesting[i]);
293 /* - merge overlapping backedges */
294 for (i=0; i < ls->backedge_count-1; i++)
295 if (ls->backedge[i]->start >= ls->backedge[i+1]->end) {/* overlapping -> merge */
296 /* ls->backedge[i+1]->start = ls->backedge[i]->start; */
297 ls->backedge[i+1]->end = min (ls->backedge[i+1]->end, ls->backedge[i]->end);
298 ls->backedge[i] = NULL;
301 printf("merged: \n");
302 for (i=0; i < ls->backedge_count; i++)
303 if (ls->backedge[i] != NULL)
304 printf("Backedge: %i - %i, %i - %i\n",ls->sorted[ls->backedge[i]->start],ls->sorted[ls->backedge[i]->end],ls->backedge[i]->start, ls->backedge[i]->end);
306 /* - remove backedge[] == NULL from array */
308 for ( j = ls->backedge_count -1; ((j>=0) && ( ls->backedge[j] == NULL)); j--);
311 if (ls->backedge[i] == NULL) { /* swap be[i] mit be[j] */
313 ls->backedge[j] = ls->backedge[i];
317 ls->backedge_count--;
322 for (i=0; i < ls->backedge_count; i++)
323 printf("Backedge: %i - %i, %i - %i\n",ls->sorted[ls->backedge[i]->start],ls->sorted[ls->backedge[i]->end],ls->backedge[i]->start, ls->backedge[i]->end);
327 void lsra_add_cfg( methodinfo *m, lsradata *ls, int from, int to) {
330 for (;(to < m->basicblockcount) && (m->basicblocks[to].flags < BBREACHED); to++);
332 for (n=ls->succ[from]; (n!= NULL) && (n->value != to); n=n->next);
333 if (n != NULL) return; /* edge from->to already existing */
335 n=DNEW(struct _list);
338 n->next=ls->succ[from];
341 n=DNEW(struct _list);
343 n->next=ls->pred[to];
348 void lsra_add_exceptions(methodinfo *m, codegendata *cd, lsradata *ls) {
351 /* add cfg edges from all bb of a try block to the start of the according exception handler */
352 /* to ensure the right order after depthfirst search */
354 ex=cd->exceptiontable;
356 printf("ExTable(%i): ", cd->exceptiontablelength);
359 for (; ex != NULL; ex = ex->down) {
362 printf("[%i-%i]->%i ",ex->start->debug_nr, ex->end->debug_nr,ex->handler->debug_nr);
363 if (ex->handler->debug_nr >= m->basicblockcount)
364 panic("Exceptionhandler Basicblocknummer invalid\n");
365 if (m->basicblocks[ex->handler->debug_nr].flags < BBREACHED)
366 panic("Exceptionhandler Basicblocknummer not reachable\n");
367 if (ex->start->debug_nr > ex->end->debug_nr)
368 panic("Guarded Area starts after its end\n");
370 /* loop all valid Basic Blocks of the guarded area and add CFG edges to the appropriate handler */
371 for (i=ex->start->debug_nr; (i <= ex->end->debug_nr) && (i < m->basicblockcount); i++)
372 if (m->basicblocks[i].flags >= BBREACHED)
373 lsra_add_cfg(m, ls, i, ex->handler->debug_nr);
380 void lsra_add_jsr( methodinfo *m, lsradata *ls, int from, int to) {
381 struct _sbr *sbr, *n;
384 for (; (to < m->basicblockcount) && (m->basicblocks[to].flags < BBREACHED); to++);
386 if (to == m->basicblockcount)
387 panic("Invalid subroutine start index\n");
390 lsra_add_cfg(m, ls, from, to);
392 for (from++; (from < m->basicblockcount) && (m->basicblocks[from].flags < BBREACHED); from++);
394 if (from == m->basicblockcount)
395 panic("Invalid return basic block index for jsr\n");
398 /* add subroutine info in ls->sbr.next */
400 /* search for right place to insert */
401 for (sbr = &(ls->sbr); (sbr->next != NULL) && (sbr->next->header < to); sbr=sbr->next);
403 if ((sbr->next!= NULL) && (sbr->next->header == to)) {
404 /* Entry for this sub already exist */
407 /* make new Entry and insert it in ls->sbr.next */
408 n = DNEW( struct _sbr );
418 /* now insert return adress in sbr->ret */
419 ret = DNEW( struct _list);
421 ret->next = sbr->ret;
425 void lsra_add_sub( methodinfo *m, lsradata *ls, int b_index, struct _list *ret ) {
432 if (m->basicblocks[b_index].flags < BBREACHED)
434 if (!next_block && !(m->basicblocks[b_index].icount))
438 ip = m->basicblocks[b_index].iinstr + m->basicblocks[b_index].icount -1;
440 if (ip->opc == ICMD_JSR) /* nested Subroutines */
445 if (ip->opc == ICMD_RET) { /* subroutine return found -> add return adresses to CFG */
446 for (l = ret; l != NULL; l = l->next)
447 lsra_add_cfg( m, ls, b_index, l->value);
448 } else { /* follow CFG */
449 for ( l = ls->succ[b_index]; l != NULL; l = l->next)
450 lsra_add_sub( m, ls, l->value, ret);
452 } else { /* fall through to next block */
453 lsra_add_sub(m, ls, b_index+1, ret);
457 void lsra_add_subs(methodinfo *m, lsradata *ls) {
463 for (sbr = ls->sbr.next; sbr != NULL; sbr=sbr->next) {
465 printf("Subroutine Header: %3i Return Adresses:",sbr->header);
466 for (ret = sbr->ret; ret != NULL; ret = ret->next)
467 printf(" %3i", ret->value);
470 lsra_add_sub( m, ls, sbr->header, sbr->ret );
475 void lsra_make_cfg(methodinfo *m, lsradata *ls)
479 int high, low, count;
483 while (b_index < m->basicblockcount ) {
484 if (m->basicblocks[b_index].flags >= BBREACHED) {
485 ip = m->basicblocks[b_index].iinstr + m->basicblocks[b_index].icount -1;
486 /* set ip to last instruction */
488 if (m->basicblocks[b_index].icount) {
489 /* block contains instructions */
490 switch (ip->opc) { /* check type of last instruction */
499 lsra_add_cfg(m, ls, b_index, m->basicblockcount);
501 break; /* function returns -> end of graph */
530 case ICMD_IF_ACMPNE: /* branch -> check next block */
531 lsra_add_cfg(m, ls, b_index, b_index+1);
535 lsra_add_cfg(m, ls, b_index, m->basicblockindex[ip->op1]);
536 break; /* visit branch (goto) target */
538 case ICMD_TABLESWITCH: /* switch statement */
541 lsra_add_cfg(m, ls, b_index, m->basicblockindex[*s4ptr]);
548 count = (high-low+1);
550 while (--count >= 0) {
552 lsra_add_cfg(m, ls, b_index, m->basicblockindex[*s4ptr]);
556 case ICMD_LOOKUPSWITCH: /* switch statement */
559 lsra_add_cfg(m, ls, b_index, m->basicblockindex[*s4ptr]);
564 while (--count >= 0) {
565 lsra_add_cfg(m, ls, b_index, m->basicblockindex[s4ptr[1]]);
571 lsra_add_jsr(m, ls, b_index, m->basicblockindex[ip->op1]);
578 lsra_add_cfg(m, ls, b_index, b_index + 1 );
580 } /* switch (ip->opc)*/
581 } /* if (m->basicblocks[blockIndex].icount) */
582 } /* if (m->basicblocks[b_index].flags >= BBREACHED) */
584 } /* while (b_index < m->basicblockcount ) */
590 void lsra_init(methodinfo *m, codegendata *cd, t_inlining_globals *id, lsradata *ls)
594 /* Init LSRA Data Structures */
595 /* lifetimes für alle Basicblocks allokieren */
596 ls->pred = DMNEW(struct _list *, m->basicblockcount+1); /* + 1 for a artificial exit node */
597 ls->succ = DMNEW(struct _list *, m->basicblockcount+1); /* + 1 for a artificial exit node */
598 ls->sorted = DMNEW(int , m->basicblockcount+1); /* + 1 for a artificial exit node */
599 ls->sorted_rev = DMNEW(int , m->basicblockcount+1); /* + 1 for a artificial exit node */
600 ls->num_pred = DMNEW(int , m->basicblockcount+1); /* + 1 for a artificial exit node */
601 ls->nesting = DMNEW(long , m->basicblockcount);
602 for (i=0; i<m->basicblockcount; i++) {
606 ls->sorted_rev[i]=-1;
610 ls->pred[m->basicblockcount]=NULL;
611 ls->succ[m->basicblockcount]=NULL;
612 ls->sorted[m->basicblockcount]=-1;
613 ls->sorted_rev[m->basicblockcount]=-1;
614 ls->num_pred[m->basicblockcount]=0;
616 /* ls->ss_lifetimes=NULL; */
618 if (cd->maxlocals != id->cumlocals) panic("lsra: Welche locals nehmen?\n");
621 ls->maxlifetimes = m->maxlifetimes;
622 ls->lifetimecount = ls->maxlifetimes + cd->maxlocals * (TYPE_ADR+1);
623 ls->lifetime = DMNEW(struct lifetime, ls->lifetimecount);
624 ls->lt_used = DMNEW(int, ls->lifetimecount);
626 ls->lt_int_count = 0;
628 ls->lt_flt_count = 0;
630 ls->lt_rest_count = 0;
631 for (i=0; i < ls->lifetimecount; i++) ls->lifetime[i].type = -1;
639 bool lsra_test(methodinfo *m, codegendata *cd)
648 /* in case of exceptionhandlers or subroutines return to regalloc */
649 if (cd->exceptiontablelength > 0)
655 for (i=0; i< m->basicblockcount; i++) {
656 ip = m->basicblocks[i].iinstr + m->basicblocks[i].icount -1;/* set ip to last instruction */
657 if (ip->opc == ICMD_JSR) {
658 /* check Instack of sub */
659 /* printf("SBR Instackdepth: %3i\n",m->basicblocks[m->basicblockindex[ip->op1]].indepth);*/
667 bool lsra_setup(methodinfo *m, codegendata *cd, registerdata *rd, lsradata *ls)
676 #ifdef LSRA_DUMP_LOOPDATA
677 struct LoopContainer *lc;
678 struct LoopElement *le;
681 /* in case of exceptionhandlers or subroutines return to regalloc */
682 #if (! (defined(LSRA_DO_SR) && defined(LSRA_DO_EX)) )
683 if (!lsra_test(m,cd))
687 /* Setup LSRA Data structures */
691 lsra_make_cfg(m, ls);
693 lsra_add_subs(m, ls); /* add subroutines before exceptions! They "destroy" the CFG */
694 lsra_add_exceptions(m, cd, ls);
698 lsra_get_backedges( m, ls);
700 printf("Successors:\n");
701 for (i=0; i < m->basicblockcount; i++) {
703 for (nl=ls->succ[i]; nl!= NULL; nl=nl->next)
704 printf("%3i ",nl->value);
707 printf("Predecessors:\n");
708 for (i=0; i < m->basicblockcount; i++) {
710 for (nl=ls->pred[i]; nl!= NULL; nl=nl->next)
711 printf("%3i ",nl->value);
715 for (i=0; i < m->basicblockcount; i++) printf("%3i ", ls->sorted[i]);
717 printf("Sorted_rev: ");
718 for (i=0; i < m->basicblockcount; i++) printf("%3i ", ls->sorted_rev[i]);
724 /* sicherheitshalber Konsistenz von m->basicblocks[..] mit basicblocks->next (Liste) überprüfen */
725 printf("LSRA bb prüfen\n");
727 bptr = m->basicblocks;
728 while (bptr != NULL) {
729 if (i > m->basicblockcount){
730 panic("linked bb list does not correspond with bb array(1)\n");
732 if (bptr != &(m->basicblocks[i])){
733 panic("linked bb list does not correspond with bb array(2)\n");
739 if (i<m->basicblockcount){
740 panic("linked bb list does not correspond with bb array(3)\n");
747 for (i=m->basicblockcount-1; i >= 0; i--) {
748 if (ls->sorted[i] != -1) {
749 lsra_scan_registers_canditates(m, ls, ls->sorted[i]);
750 lsra_join_lifetimes(m, ls, ls->sorted[i]);
754 /* Parameter initialisiation for locals 0 .. paramcount */
755 /* Parameter initialisieren == local Vars readaccess at 0,-1*/
757 for (p = 0, i = 0; p < m->paramcount; p++) {
758 t = m->paramtypes[p];
760 if (rd->locals[i][t].type >= 0)
761 lsra_usage_local(ls, i, t, 0, -1, LSRA_STORE); /* Param to Local init happens before normal Code */
763 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
767 lsra_calc_lifetime_length(m, ls, cd);
769 #ifdef LSRA_PRINTLIFETIMES
770 printf("Basicblockcount: %4i Max Instr/BB: %4i\n",m->basicblockcount, ls->icount_max);
771 /* print_lifetimes(rd, ls, ls->lt_used, ls->lifetimecount); */
776 bool lsra_join_ss( struct lsradata *ls, struct stackelement *in, struct stackelement *out, int join_flag) {
777 struct lifetime *lt, *lto;
778 struct stackslot *ss, *ss_last;
781 if (in->varnum != out->varnum) {
782 lt = &(ls->lifetime[-in->varnum - 1]);
785 if (join_flag == JOIN_BB)
786 if (lt->type == -1) panic("lsra_join_ss: lifetime for instack not found\n");
788 #if 0 /* was once upon a time */
789 if (lt->type == -1) /* lifetime was assigned a REG_RES and has been thrown away */
793 if (out->varnum >= 0) { /* no lifetime for this slot till now */
794 lsra_add_ss(lt, out);
797 lto = &(ls->lifetime[-out->varnum - 1]);
799 if ((join_flag == JOIN_DUP) || (join_flag == JOIN_OP))
800 if ( (lt->flags & JOIN_BB) || (lto->flags & JOIN_BB)) {
802 printf("DUP or OP join rejected for JOIN_BB Lifetime: v_index1 %3i v_index2 %3i\n",in->varnum, out->varnum);
806 if (join_flag == JOIN_DUP)
807 if ( (lt->flags & JOIN_OP) || (lto->flags & JOIN_OP)) {
809 printf("DUP join rejected for JOIN_OP Lifetime: v_index1 %3i v_index2 %3i\n",in->varnum, out->varnum);
813 /* if (join_flag == JOIN_OP) */
814 /* if ( (lt->flags & JOIN_DUP) || (lto->flags & JOIN_DUP)) { */
815 /* #ifdef LSRA_DEBUG */
816 /* printf("OP join rejected for JOIN_DUP Lifetime: v_index1 %3i v_index2 %3i\n",in->varnum, out->varnum); */
821 #if 0 /* was once upon a time */
822 if (join_flag == JOIN_BB)
824 if (lto->type == -1) panic("lsra_join_ss: lifetime for outstack not found\n");
826 #if 0 /* was once upon a time */
827 if (lto->type == -1) /* lifetime was assigned a REG_RES and has been thrown away */
831 if (lto->type != lt->type) panic ("lsra_join_ss: in/out stack type mismatch\n");
835 lt->flags |= JOINING;
837 /* take Lifetime lto out of ls->lifetimes */
840 /* merge lto into lt of in */
842 ss_last = ss = lto->local_ss;
845 ss->s->varnum = lt->v_index;
848 if (ss_last != NULL) {
849 ss_last->next = lt->local_ss;
850 lt->local_ss = lto->local_ss;
852 lt->savedvar |= lto->savedvar;
853 lt->flags |= lto->flags | join_flag;
854 lt->usagecount += lto->usagecount;
856 /*join of bb_first_def, i_first_def und *_last_use */
857 if (lto->bb_first_def < lt->bb_first_def) {
858 lt->bb_first_def = lto->bb_first_def;
859 lt->i_first_def = lto->i_first_def;
860 } else if ((lto->bb_first_def == lt->bb_first_def) && ( lto->i_first_def < lt->i_first_def)) {
861 lt->i_first_def = lto->i_first_def;
863 if (lto->bb_last_use > lt->bb_last_use) {
864 lt->bb_last_use = lto->bb_last_use;
865 lt->i_last_use = lto->i_last_use;
866 } else if ((lto->bb_last_use == lt->bb_last_use) && ( lto->i_last_use > lt->i_last_use)) {
867 lt->i_last_use = lto->i_last_use;
874 /* join instack of Basic Block b_index with outstack of predecessors */
875 void lsra_join_lifetimes(methodinfo *m, lsradata *ls, int b_index) {
876 struct stackelement *in, *i, *out;
879 /* do not join instack of Exception Handler */
880 if (m->basicblocks[b_index].type == BBTYPE_EXH)
882 in=m->basicblocks[b_index].instack;
883 if (m->basicblocks[b_index].type == BBTYPE_SBR)
884 in=in->prev; /* do not join first instack element of a subroutine header */
887 for (pred = ls->pred[b_index]; pred != NULL; pred = pred->next) {
888 out = m->basicblocks[pred->value].outstack;
889 for (i=in; (i != NULL); i = i->prev, out=out->prev) {
890 lsra_join_ss(ls, i, out, JOIN_BB);
896 void lsra_reg_setup(methodinfo *m ,registerdata *rd, struct lsra_register *int_reg,struct lsra_register *flt_reg ) {
903 bool *fltarg_used, *intarg_used;
905 int_reg->nregdesc = nregdescint;
906 flt_reg->nregdesc = nregdescfloat;
907 if (m->isleafmethod) {
908 /* Temp and Argumentregister can be used as "saved" registers */
910 int_reg->sav_top = rd->intreg_argnum + rd->tmpintregcnt + rd->savintregcnt;
911 int_reg->sav_reg = DMNEW(int, int_reg->sav_top);
912 int_reg->tmp_reg = NULL;
913 int_reg->tmp_top = -1;
914 flt_reg->sav_top = rd->fltreg_argnum + rd->tmpfltregcnt + rd->savfltregcnt;
915 flt_reg->sav_reg = DMNEW(int, flt_reg->sav_top);
916 flt_reg->tmp_reg = NULL;
917 flt_reg->tmp_top = -1;
920 /* additionaly precolour registers for Local Variables acting as Parameters */
922 farg = rd->fltreg_argnum;
923 iarg = rd->intreg_argnum;
925 intarg_used = DMNEW(bool, rd->intreg_argnum);
926 for (i=0; i < rd->intreg_argnum; i++)
927 intarg_used[i]=false;
929 fltarg_used = DMNEW(bool, rd->fltreg_argnum);
930 for (i=0; i < rd->fltreg_argnum; i++)
931 fltarg_used[i]=false;
933 int_sav_top=int_reg->sav_top;
934 flt_sav_top=flt_reg->sav_top;
940 printf("Paramcount: %i ", m->paramcount);
942 for (i=0; (i < m->paramcount) && ((farg < rd->fltreg_argnum) ||(iarg < rd->intreg_argnum) ); i++) {
944 printf("Type %3i %3i", i, m->paramtypes[i]);
946 switch (m->paramtypes[i]) {
949 #if !defined(__I386__)
950 case TYPE_LNG: /* i386->longs stay in Memory */
953 #ifndef CONSECUTIVE_FLOATARGS
956 if (rd->locals[localindex][m->paramtypes[i]].type >= 0)
957 if (iarg < rd->intreg_argnum) {
958 int_reg->sav_reg[--int_sav_top]=rd->argintregs[iarg];
959 intarg_used[iarg]=true; /* used -> don't copy later on */
963 #if !defined(__I386__)
964 case TYPE_DBL: /* i386->longs stay in Memory */
967 #ifndef CONSECUTIVE_INTARGS
970 if (rd->locals[localindex][m->paramtypes[i]].type >= 0)
971 if (farg < rd->fltreg_argnum) {
972 flt_reg->sav_reg[--flt_sav_top]=rd->argfltregs[farg];
973 fltarg_used[farg]=true; /* used -> don't copy later on */
977 if ( IS_2_WORD_TYPE(m->paramtypes[i]))
985 /* copy rest of argument registers to flt_reg->sav_reg and int_reg->sav_reg; */
986 for (i=0; i < rd->intreg_argnum; i++)
988 int_reg->sav_reg[--int_sav_top]=rd->argintregs[i];
989 for (i=0; i < rd->fltreg_argnum; i++)
991 flt_reg->sav_reg[--flt_sav_top]=rd->argfltregs[i];
993 /* copy temp registers to flt_reg->sav_reg and int_reg->sav_reg */
994 for (i=0; i < rd->tmpintregcnt; i++)
995 int_reg->sav_reg[--int_sav_top]=rd->tmpintregs[i];
996 for (i=0; i < rd->tmpfltregcnt; i++)
997 flt_reg->sav_reg[--flt_sav_top]=rd->tmpfltregs[i];
1000 /* non leaf method -> don't use Argument Registers, divide temp and saved registers */
1001 int_sav_top = int_reg->sav_top = rd->savintregcnt;
1002 int_reg->sav_reg = DMNEW(int, int_reg->sav_top);
1003 int_reg->tmp_top = rd->tmpintregcnt;
1004 int_reg->tmp_reg = DMNEW(int, int_reg->tmp_top);
1005 flt_sav_top =flt_reg->sav_top = rd->savfltregcnt;
1006 flt_reg->sav_reg = DMNEW(int, flt_reg->sav_top);
1007 flt_reg->tmp_top = rd->tmpfltregcnt;
1008 flt_reg->tmp_reg = DMNEW(int, flt_reg->tmp_top);
1010 /* copy temp registers to flt_reg->tmp_reg and int_reg->tmp_reg */
1011 for (i=0; i < rd->tmpintregcnt; i++)
1012 int_reg->tmp_reg[i]=rd->tmpintregs[i];
1013 for (i=0; i < rd->tmpfltregcnt; i++)
1014 flt_reg->tmp_reg[i]=rd->tmpfltregs[i];
1017 /* now copy saved registers to flt_reg->sav_reg and int_reg->sav_reg */
1018 for (i = rd->savintregcnt-1; i >= 0; i--)
1019 int_reg->sav_reg[--int_sav_top]=rd->savintregs[i];
1020 for (i = rd->savfltregcnt-1; i >= 0; i--)
1021 flt_reg->sav_reg[--flt_sav_top]=rd->savfltregs[i];
1025 void lsra_insertion( struct lsradata *ls, int *a, int lo, int hi) {
1028 for (i=lo+1; i<=hi; i++) {
1030 t=ls->lifetime[a[j]].i_start;
1032 while ((j>lo) && (ls->lifetime[a[j-1]].i_start > t)) {
1033 /* ls->lifetime[a[j]].i_start = ls->lifetime[a[j-1]].i_start; */
1038 /* ls->lifetime[a[j]].i_start=t; */
1042 void lsra_qsort( struct lsradata *ls, int *a, int lo, int hi) {
1048 x = ls->lifetime[a[(lo+hi)/2]].i_start;
1052 while (ls->lifetime[a[i]].i_start < x) i++;
1053 while (ls->lifetime[a[j]].i_start > x) j--;
1055 /* exchange a[i], a[j] */
1065 if (lo < j) lsra_qsort( ls, a, lo, j);
1066 if (i < hi) lsra_qsort( ls, a, i, hi);
1068 lsra_insertion(ls, a, lo, hi);
1072 void lsra_param_sort(struct lsradata *ls, int *lifetime, int lifetime_count) {
1077 /* count number of parameters ( .i_start == -1) */
1078 for (param_count=0; (param_count < lifetime_count) && (ls->lifetime[lifetime[param_count]].i_start == -1); param_count++);
1080 if (param_count > 0) {
1081 /* now sort the parameters by v_index */
1082 for (i=0; i < param_count -1; i++)
1083 for (j=i+1; j < param_count; j++)
1084 if ( ls->lifetime[lifetime[i]].v_index > ls->lifetime[lifetime[j]].v_index) {
1087 lifetime[i]=lifetime[j];
1093 void lsra_main(methodinfo *m, lsradata *ls, registerdata *rd, codegendata *cd)
1095 struct lifetime *lt;
1100 int flags; /* 0 INMEMORY-> ls->lt_rest, 1 INTREG-> ls->lt_int, 2 FLTREG-> ls->lt_flt */
1102 struct lsra_register flt_reg, int_reg;
1107 /* first split lifetimes for integer and float registers */
1109 ls->lt_int = DMNEW(int, ls->lifetimecount); /* todo: do count and split of int/float lifetimes already in lsra_calc_lifetimelength! */
1110 ls->lt_flt = DMNEW(int, ls->lifetimecount);
1111 ls->lt_rest = DMNEW(int, ls->lifetimecount);
1112 ls->lt_int_count = 0;
1113 ls->lt_flt_count = 0;
1114 ls->lt_rest_count = 0;
1117 for (lt_used_index = 0; lt_used_index < ls->lifetimecount; lt_used_index ++) {
1118 lt = &(ls->lifetime[ls->lt_used[lt_used_index]]);
1123 #if defined(__I386__) || defined(USETWOREGS)
1125 * for i386 put all longs in memory
1127 /* for PowerPC (USETWOREGS) for now into memory, too */
1136 #if defined(__I386__)
1138 * for i386 put all longs in memory
1147 panic("Unknown Type\n");
1151 case 0: /* lt_used[lt_used_index] -> lt_rest */
1152 ls->lt_rest[ ls->lt_rest_count++ ] = ls->lt_used[lt_used_index];
1154 case 1: /* l->lifetimes -> lt_int */
1155 ls->lt_int[ ls->lt_int_count++ ] = ls->lt_used[lt_used_index];
1157 case 2: /* l->lifetimes -> lt_flt */
1158 ls->lt_flt[ ls->lt_flt_count++ ] = ls->lt_used[lt_used_index];
1163 lsra_qsort( ls, ls->lt_rest, 0, ls->lt_rest_count - 1);
1164 lsra_qsort( ls, ls->lt_int, 0, ls->lt_int_count - 1);
1165 lsra_qsort( ls, ls->lt_flt, 0, ls->lt_flt_count - 1);
1167 lsra_param_sort( ls, ls->lt_int, ls->lt_int_count);
1168 lsra_param_sort( ls, ls->lt_flt, ls->lt_flt_count);
1170 lsra_reg_setup(m, rd, &int_reg, &flt_reg);
1173 printf("INTSAV REG: ");
1174 for (i=0; i<int_reg.sav_top; i++)
1175 printf("%2i ",int_reg.sav_reg[i]);
1176 printf("\nINTTMP REG: ");
1177 for (i=0; i<int_reg.tmp_top; i++)
1178 printf("%2i ",int_reg.tmp_reg[i]);
1179 printf("\nFLTSAV REG: ");
1180 for (i=0; i<flt_reg.sav_top; i++)
1181 printf("%2i ",flt_reg.sav_reg[i]);
1182 printf("\nFLTTMP REG: ");
1183 for (i=0; i<flt_reg.tmp_top; i++)
1184 printf("%2i ",flt_reg.tmp_reg[i]);
1187 lsra_reg_use=rd->savintregcnt;
1188 _lsra_main(m, ls, ls->lt_int, ls->lt_int_count, &int_reg, &lsra_reg_use);
1189 if (lsra_reg_use > rd->savintregcnt) lsra_reg_use=rd->savintregcnt;
1190 rd->maxsavintreguse= lsra_reg_use;
1191 lsra_reg_use=rd->savfltregcnt;
1193 _lsra_main(m,ls, ls->lt_flt, ls->lt_flt_count, &flt_reg, &lsra_reg_use);
1194 if (lsra_reg_use > rd->savfltregcnt) lsra_reg_use=rd->savfltregcnt;
1196 rd->maxsavfltreguse=lsra_reg_use;
1198 /* allocate stack space for passing arguments to called methods */
1200 #if !defined(SPECIALMEMUSE)
1201 /* For this to work properly the integer argument register count must be */
1202 /* less or equal the float argument register count (e.g. x86_64). */
1203 /* (arch.h: INT_ARG_CNT <= FLT_ARG_CNT) */
1204 if (rd->arguments_num > INT_ARG_CNT) {
1205 lsra_mem_use = rd->arguments_num - INT_ARG_CNT;
1211 lsra_mem_use = rd->ifmemuse; /* Init with if_memuse from pregregpass */
1215 printf("Alloc Rest\n");
1217 lsra_alloc(m, rd, ls, ls->lt_rest, ls->lt_rest_count,&lsra_mem_use);
1219 printf("Alloc Int\n");
1221 lsra_alloc(m, rd, ls, ls->lt_int, ls->lt_int_count, &lsra_mem_use);
1223 printf("Alloc Flt\n");
1225 lsra_alloc(m, rd, ls, ls->lt_flt, ls->lt_flt_count, &lsra_mem_use);
1227 #ifdef LSRA_PRINTLIFETIMES
1228 printf("Int RA complete \n");
1229 printf("Lifetimes after splitting int: \n");
1230 print_lifetimes(rd, ls, ls->lt_int, ls->lt_int_count);
1232 printf("Flt RA complete \n");
1233 printf("Lifetimes after splitting flt:\n");
1234 print_lifetimes(rd, ls, ls->lt_flt, ls->lt_flt_count);
1236 printf("Rest RA complete \n");
1237 printf("Lifetimes after leftt:\n");
1238 print_lifetimes(rd, ls, ls->lt_rest, ls->lt_rest_count);
1240 rd->maxmemuse=lsra_mem_use;
1242 test_lifetimes(m, ls, rd );
1247 void lsra_alloc(methodinfo *m, registerdata *rd, struct lsradata *ls, int *lifet, int lifetimecount, int *mem_use)
1250 struct lifetime *lt;
1251 struct freemem *fmem;
1252 struct stackslot *n;
1255 struct freemem *fmem_2;
1258 fmem=DNEW(struct freemem);
1262 fmem_2=DNEW(struct freemem);
1267 /* for (lt=lifet;lt!=NULL;lt=lt->next) { */
1268 for (lt_index = 0; lt_index < lifetimecount; lt_index ++) {
1269 lt = &(ls->lifetime[lifet[lt_index]]);
1276 if (IS_2_WORD_TYPE(lt->type))
1277 regoff=lsra_getmem(lt, fmem_2, mem_use);
1280 regoff=lsra_getmem(lt, fmem, mem_use);
1286 if (lt->v_index < 0) {
1287 for (n=lt->local_ss; n!=NULL; n=n->next) {
1288 lsra_setflags( &(n->s->flags), flags);
1289 n->s->regoff=regoff;
1291 } else { /* local var */
1292 if (rd->locals[lt->v_index][lt->type].type>=0) {
1293 /* lsra_setflags( &(rd->locals[lt->v_index][lt->type].flags), flags); */
1294 rd->locals[lt->v_index][lt->type].flags= flags;
1295 rd->locals[lt->v_index][lt->type].regoff=regoff;
1296 } else panic("Type Data mismatch 1\n");
1302 void lsra_setflags(int *flags, int newflags)
1304 if ( newflags & INMEMORY)
1307 *flags &= ~INMEMORY;
1309 if (newflags & SAVEDVAR)
1313 int lsra_getmem(struct lifetime *lt, struct freemem *fmem, int *mem_use)
1315 struct freemem *fm, *p;
1317 /* noch kein Speicher vergeben, oder alle Enden später */
1318 if ((fmem->next == NULL) || (fmem->next->end > lt->i_start)) {
1319 fm=lsra_getnewmem(mem_use);
1321 if (IS_2_WORD_TYPE(lt->type)) (*mem_use)++;
1324 /* Speicherstelle frei */
1326 fmem->next=fm->next;
1330 for (p=fmem; (p->next!=NULL) && (p->next->end < fm->end); p=p->next);
1336 struct freemem *lsra_getnewmem(int *mem_use)
1340 fm=DNEW(struct freemem);
1347 void _lsra_main( methodinfo *m, lsradata *ls, int *lifet, int lifetimecount, struct lsra_register *reg, int *reg_use)
1349 struct lifetime *lt;
1352 bool temp; /* reg from temp registers (true) or saved registers (false) */
1354 if ((reg->tmp_top+reg->sav_top) == 0) {
1355 /* for (lt=lifet; lt != NULL; lt=lt->next) */
1357 for (lt_index = 0; lt_index < lifetimecount; lt_index++)
1358 ls->lifetime[lifet[lt_index]].reg = -1;
1362 ls->active_tmp = NULL;
1363 ls->active_sav = NULL;
1365 /* for (lt=lifet; lt != NULL; lt=lt->next) { */
1366 for (lt_index = 0; lt_index < lifetimecount; lt_index++) {
1367 lt = &(ls->lifetime[lifet[lt_index]]);
1369 lsra_expire_old_intervalls(m, ls, lt, reg);
1372 if (lt->savedvar || m->isleafmethod) { /* -> use Saved Reg (in case of leafmethod all regs are "saved" regs) */
1373 if (reg->sav_top > 0) {
1374 reg_index = reg->sav_reg[--reg->sav_top];
1376 } else { /* use Temp Reg or if non free a Saved Reg */
1377 if (reg->tmp_top > 0) {
1379 reg_index = reg->tmp_reg[--reg->tmp_top];
1382 if (reg->sav_top > 0)
1383 reg_index = reg->sav_reg[--reg->sav_top];
1385 if (reg_index == -1) /* no reg is available anymore... -> spill */
1386 spill_at_intervall(m, ls, lt);
1388 lt->reg = reg_index;
1390 lsra_add_active(lt, &(ls->active_tmp));
1392 if (reg->sav_top<*reg_use) *reg_use=reg->sav_top;
1393 lsra_add_active(lt, &(ls->active_sav));
1399 void lsra_add_active(struct lifetime *lt, struct active_lt **active)
1401 struct active_lt *alt,*alt1,*alt2;
1402 alt=DNEW(struct active_lt);
1405 for(alt1=alt2=*active; alt1 != NULL; alt2=alt1, alt1=alt1->next)
1406 if (alt1->lt->i_end > lt->i_end) break;
1408 if (alt1 == *active) {
1409 alt->next = *active;
1412 alt->next = alt2->next;
1418 void lsra_expire_old_intervalls(methodinfo *m, lsradata *ls, struct lifetime *lt, struct lsra_register *reg)
1420 _lsra_expire_old_intervalls(m, lt, reg, &(ls->active_tmp));
1421 _lsra_expire_old_intervalls(m, lt, reg, &(ls->active_sav));
1424 void _lsra_expire_old_intervalls(methodinfo *m, struct lifetime *lt, struct lsra_register *reg, struct active_lt **active)
1426 struct active_lt *alt,*alt1;
1429 for (alt1=alt=*active; alt != NULL; alt1=alt, alt=alt->next) {
1430 if (alt->lt->i_end > lt->i_start) return;
1432 *active = (*active)->next;
1434 alt1->next=alt->next;
1436 /* make alt->lt->reg available again */
1437 if (m->isleafmethod) {
1438 /* leafmethod -> don't care about type -> put all again into reg->sav_reg */
1439 reg->sav_reg[reg->sav_top++] = alt->lt->reg;
1441 /* no leafmethod -> distinguish between temp and saved register */
1442 if ( reg->nregdesc[alt->lt->reg] == REG_SAV)
1443 reg->sav_reg[reg->sav_top++] = alt->lt->reg;
1445 reg->tmp_reg[reg->tmp_top++] = alt->lt->reg;
1450 void spill_at_intervall(methodinfo *m, lsradata *ls, struct lifetime *lt )
1452 if (lt->savedvar || m->isleafmethod)
1453 _spill_at_intervall(lt, &(ls->active_sav));
1455 _spill_at_intervall(lt, &(ls->active_tmp));
1456 if (lt->reg == -1) /* kein tmp mehr frei gewesen */
1457 _spill_at_intervall(lt, &(ls->active_sav));
1459 /* if (lt->reg == -2) panic("spill_at_intervall: Keine Register mehr frei gewesen!\n"); */
1462 void _spill_at_intervall(struct lifetime *lt, struct active_lt **active)
1464 struct active_lt *alt,*alt1;
1465 if (*active == NULL) {
1469 /* get last intervall from active */
1470 for (alt1=alt=*active; alt->next != NULL; alt1=alt, alt=alt->next);
1473 if ((alt->lt->i_end > lt->i_end) || (alt->lt->usagecount < lt->usagecount)) {
1475 if (alt->lt->i_end > lt->i_end) {
1477 lt->reg=alt->lt->reg;
1481 *active=(*active)->next;
1483 alt1->next=alt->next;
1484 lsra_add_active(lt, active);
1491 void lsra_calc_lifetime_length(methodinfo *m, lsradata *ls, codegendata *cd)
1493 struct lifetime *lt;
1496 /* struct stackslot *ss; */
1497 int *icount_block, icount;
1501 int cum_local_ss,local_ss_count;
1505 icount_block = DMNEW(int, m->basicblockcount);
1506 icount_block[0] = icount = 0;
1507 for (i=1; i < m->basicblockcount; i++) {
1508 if (ls->sorted[i-1] != -1)
1509 icount += m->basicblocks[ ls->sorted[i-1] ].icount;
1510 if (ls->sorted[i] != -1)
1511 icount_block[i] = icount;
1515 printf("icount_block: ");
1516 for (i=0; i < m->basicblockcount; i++)
1517 printf("(%3i-%3i) ",i, icount_block[i]);
1521 /* extend lifetime over backedges */
1522 /* now iterate through lifetimes and expand them */
1525 max_local_ss = cum_local_ss = 0;
1528 for(lt_index = 0 ;lt_index < ls->lifetimecount; lt_index++) {
1529 if ( ls->lifetime[lt_index].type != -1) { /* used lifetime */
1530 ls->lt_used[lifetimecount ++] = lt_index; /* remember lt_index in lt_sorted */
1531 lt = &(ls->lifetime[lt_index]);
1534 for (ss=lt->local_ss; ss != 0; ss = ss->next, local_ss_count++);
1535 if (local_ss_count > max_local_ss) max_local_ss = local_ss_count;
1536 cum_local_ss+=local_ss_count;
1539 if (lt->bb_first_def == -1) {
1540 /* printf("--------- Warning: variable not defined!------------------vi: %i start: %i end: %i\n", lt->v_index, lt->i_start, lt->i_end); */
1541 lt->bb_first_def = 0;
1542 lt->i_first_def = 0;
1545 /* lt->i_start =lt->bb_first_def * ls->icount_max + lt->i_first_def; */
1546 lt->i_start = icount_block[lt->bb_first_def] + lt->i_first_def;
1548 if (lt->bb_last_use == -1) {
1549 /* printf("--------- Warning: variable not used! --------------------vi: %i start: %i end: %i\n", lt->v_index, lt->i_start, lt->i_end); */
1550 lt->bb_last_use = lt->bb_first_def;
1551 lt->i_last_use = lt->i_first_def;
1554 /* lt->i_end = lt->bb_last_use * ls->icount_max + lt->i_last_use; */
1555 lt->i_end = icount_block[lt->bb_last_use] + lt->i_last_use;
1557 if (lt->i_start > lt->i_end)
1558 printf("--------- Warning: last use before first def! ------------vi: %i start: %i end: %i\n", lt->v_index, lt->i_start, lt->i_end);
1561 /* expand lifetimes in a exceptionhandler to at least the whole handler */
1562 /* TODO do a loop analyze for the exceptionhandler*/
1564 /* every lifetime of a guarded area, which is used in the exc. handler, */
1565 /* has to be expanded to at least the whole guarded area */
1566 for (i=0; i < cd->exceptiontablelength; i++) {
1567 if ( !((bfirst > ls->ex[i].handler_max) || ( blast < ls->ex[i].handler_min)) ) {
1568 /* lifetime lt lies within the exceptionhandler */
1569 /* expand to at least the extends of this exceptionhandler */
1571 /* -> Lifetime start has to be at minimum the start of the exceptionhandler */
1572 if (bfirst >= ls->ex[i].handler_min) {
1573 bfirst=ls->ex[i].handler_min;
1576 /* -> Lifetime end has to be at minimum the end of the exceptionhandler */
1577 if (blast <= ls->ex[i].handler_max) {
1578 blast=ls->ex[i].handler_max;
1579 ilast= m->basicblocks[ls->ex[i].handler_max].icount-1;
1585 if (lt->bb_first_def != lt->bb_last_use) {
1586 /* Lifetime goes over more than one Basic Block -> */
1587 /* check for necessary extension over backedges */
1588 /* see lsra_get_backedges */
1590 for (i=0; i < ls->backedge_count; i++) {
1591 if (!( (lt->bb_first_def > ls->backedge[i]->start) ||
1592 (lt->bb_last_use < ls->backedge[i]->end) )) {
1593 /* Live intervall intersects with a backedge */
1594 /* if (lt->bb_first_def <= ls->backedge[i]->start) */
1595 /* lt->i_start = (m->basicblockcount - ls->backedge[i]->start) * ls->icount_max; */
1596 if (lt->bb_last_use <= ls->backedge[i]->start)
1597 /* lt->i_end = ls->backedge[i]->start * ls->icount_max + m->basicblocks[ls->sorted[ls->backedge[i]->start]].icount-1; */
1598 lt->i_end = icount_block[ls->backedge[i]->start] + m->basicblocks[ls->sorted[ls->backedge[i]->start]].icount;
1602 #ifdef USAGE_PER_INSTR
1603 lt->usagecount = lt->usagecount / ( lt->i_end - lt->i_start + 1);
1607 /* printf("%5i %5i ====== \n", ls->lifetimecount, lifetimecount); */
1608 ls->lifetimecount = lifetimecount;
1611 for (i=0; i<m->basicblockcount; i++)
1612 if (m->basicblocks[i].flags >= BBREACHED)
1613 i_count+=m->basicblocks[i].icount;
1614 printf("Instr: %5i Lifetimes: %5i Local SS Max: %4i Cum: %4i m->maxlifetimes %4i\n",i_count, lifetimecount, max_local_ss, cum_local_ss, m->maxlifetimes);
1618 #ifdef LSRA_PRINTLIFETIMES
1619 void print_lifetimes(registerdata *rd, lsradata *ls, int *lt, int lifetimecount)
1623 int type,flags,regoff,varkind;
1625 for (lt_index = 0; lt_index < lifetimecount; lt_index++) {
1626 n = &(ls->lifetime[lt[lt_index]]);
1627 if (n->v_index < 0) { /* stackslot */
1628 type = n->local_ss->s->type;
1629 flags=n->local_ss->s->flags;
1630 regoff=n->local_ss->s->regoff;
1631 varkind=n->local_ss->s->varkind;
1632 } else { /* local var */
1633 if (rd->locals[n->v_index][n->type].type>=0) {
1634 type = rd->locals[n->v_index][n->type].type;
1635 flags=rd->locals[n->v_index][n->type].flags;
1636 regoff=rd->locals[n->v_index][n->type].regoff;
1639 panic("Type Data mismatch 3\n");
1641 printf("i_Start: %3i(%3i,%3i) i_stop: %3i(%3i,%3i) reg: %3i VI: %3i type: %3i flags: %3i varkind: %3i usage: %3li ltflags: %xi \n",n->i_start, ls->sorted[n->bb_first_def], n->i_first_def,n->i_end, ls->sorted[n->bb_last_use], n->i_last_use,regoff,n->v_index,type,flags, varkind, n->usagecount, n->flags);
1643 printf( "%3i Lifetimes printed \n",lt_index);
1647 struct stackslot *lsra_make_ss(stackptr s, int bb_index)
1649 struct stackslot *ss;
1651 ss=DNEW(struct stackslot);
1657 void lsra_add_ss(struct lifetime *lt, stackptr s) {
1658 struct stackslot *ss;
1659 /* Stackslot noch nicht eingetragen? */
1661 if (s->varnum != lt->v_index) {
1662 ss = DNEW(struct stackslot);
1664 ss->s->varnum = lt->v_index;
1665 ss->next = lt->local_ss;
1667 if (s != NULL) lt->savedvar |= s->flags & SAVEDVAR;
1668 if (s != NULL) lt->type = s->type;
1672 struct lifetime *get_ss_lifetime(lsradata *ls, stackptr s) {
1675 if (s->varnum >= 0) { /* new Lifetime *//* existiert noch nicht -> neue anlegen */
1676 n = &(ls->lifetime[-ls->v_index - 1]);
1678 n->v_index = ls->v_index--;
1681 n->bb_last_use = -1;
1682 n->bb_first_def = -1;
1687 n = &(ls->lifetime[-s->varnum - 1]);
1693 #define lsra_new_stack(ls, s, block, instr) if ((s)->varkind != ARGVAR) _lsra_new_stack(ls, s, block, instr, LSRA_STORE)
1694 void _lsra_new_stack(lsradata *ls, stackptr s, int block, int instr, int store)
1698 if (s->varkind == LOCALVAR) {
1699 lsra_usage_local(ls, s->varnum, s->type, block, instr, LSRA_STORE);
1700 } else /* if (s->varkind != ARGVAR) */ {
1702 n=get_ss_lifetime( ls, s );
1704 if (store == LSRA_BB_IN)
1705 n->flags |= JOIN_BB;
1706 /* remember first def -> overwrite everytime */
1707 n->bb_first_def = ls->sorted_rev[block];
1708 n->i_first_def = instr;
1710 n->usagecount+=ls->nesting[ls->sorted_rev[block]];
1714 #define IS_TEMP_VAR(s) ( ((s)->varkind != ARGVAR) && ((s)->varkind != LOCALVAR) )
1716 #define lsra_join_3_stack(ls, dst, src1, src2, join_type) \
1717 if ( IS_TEMP_VAR(dst) ) { \
1719 if ( IS_TEMP_VAR(src1) && ((src1)->type == (dst)->type)) { \
1720 join_ret = lsra_join_ss(ls, dst, src1, join_type); \
1722 if ( (!join_ret) && IS_TEMP_VAR(src2) && ((src2)->type == (dst)->type)) { \
1723 lsra_join_ss(ls, dst, src2, join_type); \
1727 #define lsra_join_2_stack(ls, dst, src, join_type) \
1728 if ( IS_TEMP_VAR(dst) ) { \
1729 if ( (IS_TEMP_VAR(src)) && ((src)->type == (dst)->type)) { \
1730 lsra_join_ss(ls, dst, src, join_type); \
1734 #define lsra_join_dup(ls, s1, s2, s3) { \
1735 if (IS_TEMP_VAR(s1)) { \
1737 if (IS_TEMP_VAR(s2)) \
1738 join_ret = lsra_join_ss(ls, s1, s2, JOIN); /* undangerous join! */ \
1739 if (IS_TEMP_VAR(s3)) { \
1740 if (join_ret) /* first join succesfull -> second of type JOIN_DUP */ \
1741 lsra_join_ss(ls, s1, s3, JOIN_DUP); \
1743 lsra_join_ss(ls, s1, s3, JOIN); /* first join did not happen -> second undangerous */ \
1746 if (IS_TEMP_VAR(s2) && IS_TEMP_VAR(s3)) \
1747 lsra_join_ss(ls, s2, s3, JOIN_DUP); \
1751 #ifdef JOIN_DEST_STACK
1752 #define lsra_join_dup(ls, s1, s2, s3) { \
1753 if (IS_TEMP_VAR(s1)) { \
1754 if (IS_TEMP_VAR(s2)) \
1755 lsra_join_ss(ls, s1, s2, JOIN_DUP); \
1757 if (IS_TEMP_VAR(s3)) \
1758 lsra_join_ss(ls, s1, s3, JOIN_DUP); \
1762 #define lsra_join_dup(ls, s1, s2, s3) { \
1763 if (IS_TEMP_VAR(s1)) { \
1764 if (IS_TEMP_VAR(s2)) \
1765 lsra_join_ss(ls, s1, s2, JOIN_DUP); \
1766 if (IS_TEMP_VAR(s3)) \
1767 lsra_join_ss(ls, s1, s3, JOIN_DUP); \
1769 if (IS_TEMP_VAR(s2) && IS_TEMP_VAR(s3)) \
1770 lsra_join_ss(ls, s2, s3, JOIN_DUP); \
1775 #define lsra_from_stack(ls, s, block, instr) if ((s)->varkind != ARGVAR) _lsra_from_stack(ls, s, block, instr, LSRA_LOAD)
1776 #define lsra_pop_from_stack(ls, s, block, instr) if ((s)->varkind != ARGVAR) _lsra_from_stack(ls, s, block, instr, LSRA_POP)
1777 void _lsra_from_stack(lsradata *ls, stackptr s, int block, int instr, int store)
1781 if (s->varkind == LOCALVAR) {
1782 lsra_usage_local(ls, s->varnum, s->type, block, instr, LSRA_LOAD);
1783 } else /* if (s->varkind != ARGVAR) */ {
1785 n=get_ss_lifetime( ls, s );
1787 if (store == LSRA_BB_OUT)
1788 n->flags |= JOIN_BB;
1789 if (n->flags & JOINING)
1790 n->flags &= ~JOINING;
1791 n->usagecount+=ls->nesting[ls->sorted_rev[block]];
1793 /* remember last USE, so only write, if USE Field is undefined (==-1) */
1794 if (n->bb_last_use == -1) {
1795 n->bb_last_use = ls->sorted_rev[block];
1796 n->i_last_use = instr;
1801 void lsra_usage_local(lsradata *ls, s4 v_index, int type, int block, int instr, int store)
1805 n = &(ls->lifetime[ ls->maxlifetimes + v_index * (TYPE_ADR+1) + type]);
1807 if (n->type == -1) { /* new local lifetime */
1809 /* if (store != LSRA_STORE) printf("lsra_local_store: Read before write Local var: %i paramcount: ?\n", v_index); */
1814 n->savedvar = SAVEDVAR;
1818 n->bb_last_use = -1;
1819 n->bb_first_def = -1;
1821 n->usagecount+=ls->nesting[ls->sorted_rev[block]];
1822 /* add access at (block, instr) to intruction list */
1823 if (store == LSRA_LOAD) {
1824 /* remember last USE, so only write, if USE Field is undefined (==-1) */
1825 if (n->bb_last_use == -1) {
1826 n->bb_last_use = ls->sorted_rev[block];
1827 n->i_last_use = instr;
1830 /* store == LSRA_STORE, remember first def -> overwrite everytime */
1831 n->bb_first_def = ls->sorted_rev[block];
1832 n->i_first_def = instr;
1837 void lsra_dump_stack(stackptr s)
1840 printf("%p(R%3i N%3i K%3i T%3i F%3i) ",(void *)s,s->regoff, s->varnum, s->varkind, s->type, s->flags);
1848 void lsra_scan_registers_canditates(methodinfo *m, lsradata *ls, int b_index)
1856 bool join_ret; /* for lsra_join* Macros */
1857 #if defined(LSRA_USES_REG_RES)
1858 int v_index_min_before_instruction;
1859 int v_index_min[REG_RES_CNT];
1861 for (i=0; i < REG_RES_CNT; i++) {
1862 ls->reg_res_free[i] = -1;
1863 v_index_min[i] = ls->v_index;
1867 src = m->basicblocks[b_index].instack;
1868 if (m->basicblocks[b_index].type != BBTYPE_STD) {
1871 panic("No Incoming Stackslot for Exception or Subroutine Basic Block\n");
1873 lsra_new_stack(ls, src, b_index, 0);
1874 if (src->varkind == STACKVAR)
1875 src->varkind = TEMPVAR;
1878 for (;src != NULL; src=src->prev) {
1879 if (src->varkind == ARGVAR ) /* no ARGVAR possible at BB Boundaries with LSRA! -> change to TEMPVAR */
1880 src->varkind = TEMPVAR;
1881 else if (src->varkind == LOCALVAR )
1882 panic("LOCALVAR at basicblock instack\n"); /* only allowed for top most ss at sbr or exh entries! */
1884 if (src->varkind == STACKVAR ) /* no Interfaces at BB Boundaries with LSRA! -> change to TEMPVAR */
1885 src->varkind = TEMPVAR;
1886 _lsra_new_stack(ls, src, b_index, iindex, LSRA_BB_IN);
1889 src = m->basicblocks[b_index].outstack;
1890 for (;src != NULL; src=src->prev) {
1891 if (src->varkind == ARGVAR )
1892 panic("ARGVAR at basicblock outstack\n");
1893 else if (src->varkind == LOCALVAR )
1894 panic("LOCALVAR at basicblock outstack\n");
1896 if (src->varkind == STACKVAR ) /* no Interfaces at BB Boundaries with LSRA! -> change to TEMPVAR */
1897 src->varkind = TEMPVAR;
1898 _lsra_from_stack(ls, src, b_index, iindex, LSRA_BB_OUT);
1902 iptr = m->basicblocks[b_index].iinstr;
1903 iindex = m->basicblocks[b_index].icount - 1;
1906 if ((iindex+1) > ls->icount_max)
1907 ls->icount_max = iindex+1;
1910 for (;iindex >= 0; iindex--, iptr--) {
1913 if (iindex) /* > 0 */
1916 src=m->basicblocks[b_index].instack;
1917 #if defined(LSRA_USES_REG_RES)
1918 v_index_min_before_instruction = ls->v_index;
1921 /* printf("bb: %3i bcount: %3i iindex: %3i ilen: %3i opcode: %3i %s\n",b_index,m->basicblockcount,iindex,len,opcode,icmd_names[opcode]); */
1922 /* lsra_dump_stack(src); */
1923 /* lsra_dump_stack(dst); */
1929 lsra_usage_local(ls,iptr->op1,TYPE_ADR, b_index,iindex,LSRA_LOAD); /* local read (return adress) */
1934 case ICMD_ELSE_ICONST:
1935 case ICMD_CHECKEXCEPTION:
1936 case ICMD_CHECKASIZE:
1937 case ICMD_PUTSTATICCONST:
1938 case ICMD_INLINE_START:
1939 case ICMD_INLINE_END:
1944 lsra_usage_local(ls,iptr->op1,TYPE_INT, b_index,iindex,LSRA_LOAD); /* local */
1945 lsra_usage_local(ls,iptr->op1,TYPE_INT, b_index,iindex,LSRA_STORE); /* local = local+<const> */
1948 /* pop 0 push 1 const */
1956 /* new stack slot */
1957 lsra_new_stack(ls,dst,b_index,iindex); /* const->stack */
1960 /* pop 0 push 1 load */
1968 if (dst->varkind != LOCALVAR) {
1969 lsra_usage_local(ls,iptr->op1,opcode-ICMD_ILOAD, b_index,iindex,LSRA_LOAD); /* local->value */
1970 lsra_new_stack(ls,dst,b_index,iindex); /* value->stack */
1971 } else if (dst->varnum != iptr->op1) {
1972 lsra_usage_local(ls,iptr->op1,opcode-ICMD_ILOAD, b_index,iindex,LSRA_LOAD); /* local->value */
1973 lsra_usage_local(ls,dst->varnum,opcode-ICMD_ILOAD, b_index,iindex,LSRA_STORE); /* local->value */
1979 /* Stack(arrayref,index)->stack */
1991 lsra_from_stack(ls, src,b_index,iindex); /* stack->index */
1992 lsra_from_stack(ls, src->prev,b_index,iindex); /* stack->arrayref */
1993 lsra_new_stack(ls,dst,b_index,iindex); /* arrayref[index]->stack */
1997 /* stack(arrayref,index,value)->arrayref[index]=value */
2009 lsra_from_stack(ls, src,b_index,iindex); /* stack -> value */
2010 lsra_from_stack(ls, src->prev,b_index,iindex); /* stack -> index */
2011 lsra_from_stack(ls, src->prev->prev,b_index,iindex); /* stack -> arrayref */
2014 case ICMD_POP: /* throw away a stackslot -> check if used anyway! */
2015 lsra_pop_from_stack(ls,src,b_index,iindex);
2018 /* pop 1 push 0 store */
2019 /* stack -> local */
2026 if (src->varkind != LOCALVAR) {
2027 lsra_from_stack(ls, src,b_index,iindex); /* stack -> value */
2028 lsra_usage_local(ls,iptr->op1,opcode-ICMD_ISTORE, b_index,iindex,LSRA_STORE); /* local->value */
2029 } else if (src->varnum != iptr->op1) {
2030 lsra_usage_local(ls,iptr->op1,opcode-ICMD_ISTORE, b_index,iindex,LSRA_STORE); /* local->value */
2031 lsra_usage_local(ls,src->varnum,opcode-ICMD_ISTORE, b_index,iindex,LSRA_LOAD); /* local->value */
2041 case ICMD_ARETURN: /* stack(value) -> [empty] */
2042 case ICMD_ATHROW: /* stack(objref) -> undefined */
2043 lsra_from_stack(ls, src,b_index,iindex); /* stack -> value */
2045 case ICMD_PUTSTATIC: /* stack(value) -> static_field */
2046 case ICMD_PUTFIELDCONST:
2047 /* pop 1 push 0 branch */
2048 case ICMD_NULLCHECKPOP: /****** ????? -1 -> stack *********/
2049 case ICMD_MONITORENTER:
2050 case ICMD_MONITOREXIT:
2051 lsra_from_stack(ls, src,b_index,iindex); /* stack -> value */
2054 case ICMD_IFNULL: /* stack(value) -> branch? */
2055 case ICMD_IFNONNULL:
2068 lsra_from_stack(ls, src,b_index,iindex); /* stack -> value */
2071 /* pop 1 push 0 table branch */
2073 case ICMD_TABLESWITCH:
2074 lsra_from_stack(ls, src,b_index,iindex); /* stack -> value */
2076 case ICMD_LOOKUPSWITCH:
2077 lsra_from_stack(ls, src,b_index,iindex); /* stack -> value */
2082 case ICMD_POP2: /* throw away 2 stackslots -> check if used anyway! */
2083 lsra_pop_from_stack(ls,src,b_index,iindex);
2084 lsra_pop_from_stack(ls,src->prev,b_index,iindex);
2087 /* pop 2 push 0 branch */
2089 case ICMD_IF_ICMPEQ: /* stack (v1,v2) -> branch(v1,v2) */
2090 case ICMD_IF_ICMPNE:
2091 case ICMD_IF_ICMPLT:
2092 case ICMD_IF_ICMPGE:
2093 case ICMD_IF_ICMPGT:
2094 case ICMD_IF_ICMPLE:
2096 case ICMD_IF_LCMPEQ:
2097 case ICMD_IF_LCMPNE:
2098 case ICMD_IF_LCMPLT:
2099 case ICMD_IF_LCMPGE:
2100 case ICMD_IF_LCMPGT:
2101 case ICMD_IF_LCMPLE:
2103 case ICMD_IF_ACMPEQ:
2104 case ICMD_IF_ACMPNE:
2105 lsra_from_stack(ls, src,b_index,iindex); /* stack -> value*/
2106 lsra_from_stack(ls, src->prev,b_index,iindex); /* stack -> objref*/
2111 case ICMD_PUTFIELD: /* stack(objref,value) -> objref->method=value */
2113 case ICMD_IASTORECONST:
2114 case ICMD_LASTORECONST:
2115 case ICMD_AASTORECONST:
2116 case ICMD_BASTORECONST:
2117 case ICMD_CASTORECONST:
2118 case ICMD_SASTORECONST:
2119 lsra_from_stack(ls, src,b_index,iindex); /* stack -> value*/
2120 lsra_from_stack(ls, src->prev,b_index,iindex); /* stack -> objref*/
2123 /* pop 0 push 1 dup */
2124 /* merge dupped vars??? */
2125 case ICMD_DUP: /* src == dst->prev, src -> dst */
2126 /* lsra_from_stack(ls, src,b_index,iindex);*/ /* just inc usage count? */
2127 lsra_new_stack(ls,dst,b_index,iindex);
2129 /* #if (defined(JOIN_DUP_STACK) && !defined(JOIN_DEST_STACK)) */
2130 #ifdef JOIN_DUP_STACK
2131 /* src is identical to dst->prev */
2132 lsra_join_2_stack(ls, src, dst, JOIN_DUP);
2136 /* pop 0 push 2 dup */
2139 /* lsra_from_stack(ls, src,b_index,iindex); */ /* just inc usage count? */
2140 /* lsra_from_stack(ls, src->prev,b_index,iindex); */ /* just inc usage count? */
2141 lsra_new_stack(ls,dst->prev,b_index,iindex);
2142 lsra_new_stack(ls,dst,b_index,iindex);
2144 /* #if (defined(JOIN_DUP_STACK) && !defined(JOIN_DEST_STACK)) */
2145 #ifdef JOIN_DUP_STACK
2146 lsra_join_2_stack(ls, src, dst, JOIN_DUP);
2147 lsra_join_2_stack(ls, src->prev, dst->prev, JOIN_DUP);
2148 /* src is identical to dst->prev->prev */
2149 /* src->prev is identical to dst->prev->prev->prev */
2153 /* pop 2 push 3 dup */
2156 lsra_from_stack(ls, src, b_index, iindex);
2157 lsra_from_stack(ls, src->prev, b_index, iindex);
2158 lsra_new_stack(ls, dst->prev->prev, b_index, iindex);
2159 lsra_new_stack(ls, dst->prev, b_index, iindex);
2160 lsra_new_stack(ls, dst, b_index, iindex);
2161 #ifdef JOIN_DUP_STACK
2162 lsra_join_dup(ls, src, dst, dst->prev->prev);
2163 lsra_join_2_stack(ls, src->prev, dst->prev, JOIN);
2167 /* pop 3 push 4 dup */
2170 lsra_from_stack(ls, src,b_index,iindex);
2171 lsra_from_stack(ls, src->prev,b_index,iindex);
2172 lsra_from_stack(ls, src->prev->prev,b_index,iindex);
2173 lsra_new_stack(ls,dst->prev->prev->prev,b_index,iindex);
2174 lsra_new_stack(ls,dst->prev->prev,b_index,iindex);
2175 lsra_new_stack(ls,dst->prev,b_index,iindex);
2176 lsra_new_stack(ls,dst,b_index,iindex);
2178 #ifdef JOIN_DUP_STACK
2179 lsra_join_dup(ls, src, dst, dst->prev->prev->prev);
2180 lsra_join_2_stack(ls, src->prev, dst->prev, JOIN);
2181 lsra_join_2_stack(ls, src->prev->prev, dst->prev->prev, JOIN);
2185 /* pop 3 push 5 dup */
2188 lsra_from_stack(ls, src,b_index,iindex);
2189 lsra_from_stack(ls, src->prev,b_index,iindex);
2190 lsra_from_stack(ls, src->prev->prev,b_index,iindex);
2191 lsra_new_stack(ls,dst->prev->prev->prev->prev,b_index,iindex);
2192 lsra_new_stack(ls,dst->prev->prev->prev,b_index,iindex);
2193 lsra_new_stack(ls,dst->prev->prev,b_index,iindex);
2194 lsra_new_stack(ls,dst->prev,b_index,iindex);
2195 lsra_new_stack(ls,dst,b_index,iindex);
2197 #ifdef JOIN_DUP_STACK
2198 lsra_join_dup(ls, src, dst, dst->prev->prev->prev);
2199 lsra_join_dup(ls, src->prev, dst->prev, dst->prev->prev->prev->prev);
2200 lsra_join_2_stack(ls, src->prev->prev, dst->prev->prev, JOIN);
2204 /* pop 4 push 6 dup */
2207 lsra_from_stack(ls, src,b_index,iindex);
2208 lsra_from_stack(ls, src->prev,b_index,iindex);
2209 lsra_from_stack(ls, src->prev->prev,b_index,iindex);
2210 lsra_from_stack(ls, src->prev->prev->prev,b_index,iindex);
2211 lsra_new_stack(ls,dst->prev->prev->prev->prev->prev,b_index,iindex);
2212 lsra_new_stack(ls,dst->prev->prev->prev->prev,b_index,iindex);
2213 lsra_new_stack(ls,dst->prev->prev->prev,b_index,iindex);
2214 lsra_new_stack(ls,dst->prev->prev,b_index,iindex);
2215 lsra_new_stack(ls,dst->prev,b_index,iindex);
2216 lsra_new_stack(ls,dst,b_index,iindex);
2218 #ifdef JOIN_DUP_STACK
2219 lsra_join_dup(ls, src, dst, dst->prev->prev->prev->prev);
2220 lsra_join_dup(ls, src->prev, dst->prev, dst->prev->prev->prev->prev->prev);
2221 lsra_join_2_stack(ls, src->prev->prev, dst->prev->prev, JOIN);
2222 lsra_join_2_stack(ls, src->prev->prev->prev, dst->prev->prev->prev, JOIN);
2226 /* pop 2 push 2 swap */
2229 lsra_from_stack(ls, src,b_index,iindex);
2230 lsra_from_stack(ls, src->prev,b_index,iindex);
2231 lsra_new_stack(ls,dst->prev,b_index,iindex);
2232 lsra_new_stack(ls,dst,b_index,iindex);
2234 lsra_join_2_stack(ls, src->prev, dst, JOIN);
2235 lsra_join_2_stack(ls, src, dst->prev, JOIN);
2272 lsra_from_stack(ls, src,b_index,iindex);
2273 lsra_from_stack(ls, src->prev,b_index,iindex);
2274 lsra_new_stack(ls,dst,b_index,iindex);
2275 #ifdef JOIN_DEST_STACK
2276 lsra_join_3_stack(ls, dst, src->prev, src, JOIN_OP);
2281 lsra_from_stack(ls, src, b_index, iindex);
2282 lsra_from_stack(ls, src->prev,b_index,iindex);
2283 lsra_new_stack(ls, dst, b_index, iindex);
2284 #ifdef JOIN_DEST_STACK
2285 lsra_join_2_stack(ls, src, dst, JOIN_OP);
2302 lsra_from_stack(ls, src,b_index,iindex);
2303 lsra_from_stack(ls, src->prev,b_index,iindex);
2304 lsra_new_stack(ls,dst,b_index,iindex);
2308 case ICMD_IADDCONST:
2309 case ICMD_ISUBCONST:
2310 case ICMD_IMULCONST:
2314 case ICMD_IANDCONST:
2316 case ICMD_IXORCONST:
2317 case ICMD_ISHLCONST:
2318 case ICMD_ISHRCONST:
2319 case ICMD_IUSHRCONST:
2321 case ICMD_LADDCONST:
2322 case ICMD_LSUBCONST:
2323 case ICMD_LMULCONST:
2327 case ICMD_LANDCONST:
2329 case ICMD_LXORCONST:
2330 case ICMD_LSHLCONST:
2331 case ICMD_LSHRCONST:
2332 case ICMD_LUSHRCONST:
2334 case ICMD_IFEQ_ICONST:
2335 case ICMD_IFNE_ICONST:
2336 case ICMD_IFLT_ICONST:
2337 case ICMD_IFGE_ICONST:
2338 case ICMD_IFGT_ICONST:
2339 case ICMD_IFLE_ICONST:
2344 case ICMD_INT2SHORT:
2362 case ICMD_CHECKCAST:
2363 lsra_from_stack(ls, src, b_index, iindex);
2364 lsra_new_stack(ls, dst, b_index, iindex);
2365 #ifdef JOIN_DEST_STACK
2366 lsra_join_2_stack(ls, src, dst, JOIN_OP);
2370 case ICMD_ARRAYLENGTH:
2371 case ICMD_INSTANCEOF:
2374 case ICMD_ANEWARRAY:
2377 lsra_from_stack(ls, src,b_index,iindex);
2378 lsra_new_stack(ls,dst,b_index,iindex);
2383 case ICMD_GETSTATIC:
2385 lsra_new_stack(ls,dst,b_index,iindex);
2388 /* pop many push any */
2389 case ICMD_INVOKEVIRTUAL:
2390 case ICMD_INVOKESPECIAL:
2391 case ICMD_INVOKESTATIC:
2392 case ICMD_INVOKEINTERFACE:
2395 lsra_from_stack(ls, src,b_index,iindex);
2398 if (((methodinfo*)iptr->val.a)->returntype != TYPE_VOID) {
2399 lsra_new_stack(ls,dst,b_index,iindex);
2404 lsra_from_stack(ls, src,b_index,iindex);
2407 lsra_from_stack(ls, src,b_index,iindex);
2410 lsra_from_stack(ls, src,b_index,iindex);
2411 src = src->prev; /* ??????????? */
2412 if (iptr->op1 != TYPE_VOID)
2413 lsra_new_stack(ls,dst,b_index,iindex);
2416 case ICMD_MULTIANEWARRAY:
2419 lsra_from_stack(ls, src,b_index,iindex);
2422 lsra_new_stack(ls,dst,b_index,iindex);
2426 printf("ICMD %d at %d\n", iptr->opc, (int)(iptr - m->instructions));
2427 panic("Missing ICMD code during register allocation");
2430 #if defined(LSRA_USES_REG_RES)
2433 int length, maxlength, j;
2434 int index, reg_res,start_iindex;
2435 struct stackslot * ss;
2439 for (j=0, reg_res = icmd_uses_reg_res[opcode][REG_RES_CNT]; j < REG_RES_CNT; j++, reg_res=(reg_res+1)%REG_RES_CNT) {
2440 if (reg_res == -1) reg_res = EDX; /* patch because icmd_uses_reg_res [][REG_RES_CNT] ist defaulting to -1 */
2443 if ((iindex == 0) || (icmd_uses_reg_res[opcode][reg_res])) {
2444 if (ls->reg_res_free[reg_res] != -1) {
2445 /* reg_res is free from ls->reg_res_free[] til here (iindex) */
2446 /* now search for the longest lifetime, which fits in this intervall */
2447 /* and if found assign edx to it */
2448 if (icmd_uses_reg_res[opcode][reg_res] & D) /* ICMD destroys REG_RES as destination operand */
2449 start_iindex = iindex +1;
2451 start_iindex = iindex;
2452 for (i = (-v_index_min[reg_res] - 1); i < (-ls->v_index -1); i++) {
2454 n = &(ls->lifetime[i]);
2455 if (!(n->flags & (JOINING || JOIN_BB))) { /* do not assign reserved Regs to lifetimes not fully seen till now */
2456 if ((n->type == TYPE_INT) || (n->type == TYPE_ADR)) {
2457 if (n->savedvar == 0) {
2458 if ((n->bb_last_use == n->bb_first_def) && (n->bb_last_use == ls->sorted_rev[b_index])) {
2459 if ((n->i_last_use <= ls->reg_res_free[reg_res]) && (n->i_first_def >= start_iindex)) {
2461 length = n->i_last_use - n->i_first_def;
2462 if (length > maxlength) {
2473 if (icmd_uses_reg_res[opcode][reg_res] & S) /* ICMD destroys REG_RES as source operand */
2474 ls->reg_res_free[reg_res] = -1;
2476 ls->reg_res_free[reg_res] = iindex;
2478 if (index != -1) { /* there is a lifetime, which a reserved register can be assigned to */
2482 n=&(ls->lifetime[index]);
2483 printf("------ SS Index %i in REG_RES %i bb %3i instr %3i - bb %3i instr %3i\n", lsra_reg_res[reg_res], n->v_index, ls->sorted[n->bb_first_def], n->i_first_def, ls->sorted[n->bb_last_use], n->i_last_use);
2486 ls->lifetime[index].reg = lsra_reg_res[reg_res];
2487 for (ss = ls->lifetime[index].local_ss; ss != NULL; ss=ss->next) {
2488 ss->s->regoff = lsra_reg_res[reg_res];
2490 ls->lifetime[index].type = -1; /* drop lifetime, no further processing required */
2493 v_index_min[reg_res] = v_index_min_before_instruction;
2495 if (ls->reg_res_free[reg_res] == -1)
2496 ls->reg_res_free[reg_res] = iindex;
2508 int lsra_test_lt(registerdata *rd, struct lifetime *n, int store, int *values, bool inmemory) {
2512 value_index = n->reg;
2514 if (IS_FLT_DBL_TYPE(n->type)) {
2515 value_index = rd->maxmemuse + rd->intregsnum + n->reg;
2517 value_index = rd->maxmemuse + n->reg;
2521 if ((store == LSRA_LOAD) || (store == LSRA_POP)) {
2522 if (values[value_index] == VS) {
2523 if (n->i_start != -1) { /* not a parameter */
2524 printf("lsra_test: Warning: v_index %3i type %3i reg %3i", n->v_index, n->type, n->reg);
2527 printf(" not initialized\n");
2529 } else if (values[value_index] != n->v_index) {
2530 printf("lsra_test: Error: v_index %3i type %3i reg %3i", n->v_index, n->type, n->reg);
2533 printf("Conflict: %3i \n", values[value_index]);
2537 } else { /* LSRA_STORE */
2538 values[value_index] = n->v_index;
2543 int lsra_test_local( lsradata *ls, registerdata *rd, int v_index, int type, int store, int *values) {
2546 n = &(ls->lifetime[ ls->maxlifetimes + v_index * (TYPE_ADR+1) + type]);
2548 panic("lsra_test: Local Var Lifetime not initialized!\n");
2550 return lsra_test_lt(rd, n, store, values, rd->locals[v_index][type].flags & INMEMORY);
2553 #define lsra_test_new_stack( ls, rd, s, values) lsra_test_stack(ls, rd, s, values, LSRA_STORE)
2554 #define lsra_test_from_stack( ls, rd, s, values) lsra_test_stack(ls, rd, s, values,LSRA_LOAD)
2555 #define lsra_test_pop_from_stack( ls, rd, s, values) lsra_test_stack(ls, rd, s, values, LSRA_LOAD)
2556 int lsra_test_stack( lsradata *ls, registerdata *rd, stackptr s, int *values, int store)
2561 if (s->varkind == LOCALVAR) {
2562 return lsra_test_local(ls, rd, s->varnum, s->type, store, values);
2564 if (s->varkind != ARGVAR) {
2566 panic("lsra_test: Stackslot not initialized!\n");
2567 n = &(ls->lifetime[-s->varnum - 1]);
2569 panic("lsra_test: Stackslot Lifetime not initialized!\n");
2571 return lsra_test_lt(rd, n, store, values, s->flags & INMEMORY);
2576 int _test_lifetimes(methodinfo *m, lsradata *ls, registerdata *rd, int b_index, int *values)
2578 struct stackslot *ss;
2595 iptr = m->basicblocks[b_index].iinstr;
2597 dst = m->basicblocks[b_index].instack;
2599 for (iindex =0 ;(iindex < m->basicblocks[b_index].icount) && (ret == -1) ; iindex++, iptr++) {
2608 ret = lsra_test_local(ls, rd, iptr->op1, TYPE_ADR, LSRA_LOAD, values); /* local read (return adress) */
2613 case ICMD_ELSE_ICONST:
2614 case ICMD_CHECKEXCEPTION:
2615 case ICMD_CHECKASIZE:
2616 case ICMD_PUTSTATICCONST:
2617 case ICMD_INLINE_START:
2618 case ICMD_INLINE_END:
2623 ret = lsra_test_local(ls, rd,iptr->op1,TYPE_INT, LSRA_LOAD, values); /* local */
2624 ret = lsra_test_local(ls, rd,iptr->op1,TYPE_INT, LSRA_STORE, values); /* local = local+<const> */
2627 /* pop 0 push 1 const */
2635 /* new stack slot */
2636 ret = lsra_test_new_stack(ls, rd,dst, values); /* const->stack */
2639 /* pop 0 push 1 load */
2647 if (dst->varkind != LOCALVAR) {
2648 ret = lsra_test_local(ls, rd,iptr->op1,opcode-ICMD_ILOAD, LSRA_LOAD, values); /* local->value */
2649 ret = lsra_test_new_stack(ls, rd,dst, values); /* value->stack */
2650 } else if (dst->varnum != iptr->op1) {
2651 ret = lsra_test_local(ls, rd,iptr->op1,opcode-ICMD_ILOAD, LSRA_LOAD, values); /* local->value */
2652 ret = lsra_test_local(ls, rd,dst->varnum,opcode-ICMD_ILOAD, LSRA_STORE, values); /* local->value */
2658 /* Stack(arrayref,index)->stack */
2669 ret = lsra_test_from_stack(ls, rd, src, values); /* stack->index */
2670 ret = lsra_test_from_stack(ls, rd, src->prev, values); /* stack->arrayref */
2671 ret = lsra_test_new_stack(ls, rd, dst, values); /* arrayref[index]->stack */
2675 /* stack(arrayref,index,value)->arrayref[index]=value */
2687 ret = lsra_test_from_stack(ls, rd, src, values); /* stack -> value */
2688 ret = lsra_test_from_stack(ls, rd, src->prev, values); /* stack -> index */
2689 ret = lsra_test_from_stack(ls, rd, src->prev->prev, values); /* stack -> arrayref */
2692 case ICMD_POP: /* throw away a stackslot -> check if used anyway! */
2693 ret = lsra_test_pop_from_stack(ls, rd,src, values);
2696 /* pop 1 push 0 store */
2697 /* stack -> local */
2704 if (src->varkind != LOCALVAR) {
2705 ret = lsra_test_from_stack(ls, rd, src, values); /* stack -> value */
2706 ret = lsra_test_local(ls, rd,iptr->op1,opcode-ICMD_ISTORE, LSRA_STORE, values); /* local->value */
2707 } else if (src->varnum != iptr->op1) {
2708 ret = lsra_test_local(ls, rd,iptr->op1,opcode-ICMD_ISTORE, LSRA_STORE, values); /* local->value */
2709 ret = lsra_test_local(ls, rd,src->varnum,opcode-ICMD_ISTORE, LSRA_LOAD, values); /* local->value */
2719 case ICMD_ARETURN: /* stack(value) -> [empty] */
2720 case ICMD_ATHROW: /* stack(objref) -> undefined */
2721 ret = lsra_test_from_stack(ls, rd, src, values); /* stack -> value */
2723 case ICMD_PUTSTATIC: /* stack(value) -> static_field */
2724 case ICMD_PUTFIELDCONST:
2725 /* pop 1 push 0 branch */
2726 case ICMD_NULLCHECKPOP: /****** ????? -1 -> stack *********/
2727 case ICMD_MONITORENTER:
2728 case ICMD_MONITOREXIT:
2729 ret = lsra_test_from_stack(ls, rd, src, values); /* stack -> value */
2732 case ICMD_IFNULL: /* stack(value) -> branch? */
2733 case ICMD_IFNONNULL:
2746 ret = lsra_test_from_stack(ls, rd, src, values); /* stack -> value */
2749 /* pop 1 push 0 table branch */
2751 case ICMD_TABLESWITCH:
2752 ret = lsra_test_from_stack(ls, rd, src, values); /* stack -> value */
2754 case ICMD_LOOKUPSWITCH:
2755 ret = lsra_test_from_stack(ls, rd, src, values); /* stack -> value */
2760 case ICMD_POP2: /* throw away 2 stackslots -> check if used anyway! */
2761 ret = lsra_test_pop_from_stack(ls, rd,src, values);
2762 ret = lsra_test_pop_from_stack(ls, rd,src->prev, values);
2765 /* pop 2 push 0 branch */
2767 case ICMD_IF_ICMPEQ: /* stack (v1,v2) -> branch(v1,v2) */
2768 case ICMD_IF_ICMPNE:
2769 case ICMD_IF_ICMPLT:
2770 case ICMD_IF_ICMPGE:
2771 case ICMD_IF_ICMPGT:
2772 case ICMD_IF_ICMPLE:
2774 case ICMD_IF_LCMPEQ:
2775 case ICMD_IF_LCMPNE:
2776 case ICMD_IF_LCMPLT:
2777 case ICMD_IF_LCMPGE:
2778 case ICMD_IF_LCMPGT:
2779 case ICMD_IF_LCMPLE:
2781 case ICMD_IF_ACMPEQ:
2782 case ICMD_IF_ACMPNE:
2783 ret = lsra_test_from_stack(ls, rd, src, values); /* stack -> value*/
2784 ret = lsra_test_from_stack(ls, rd, src->prev, values); /* stack -> objref*/
2789 case ICMD_PUTFIELD: /* stack(objref,value) -> objref->method=value */
2791 case ICMD_IASTORECONST:
2792 case ICMD_LASTORECONST:
2793 case ICMD_AASTORECONST:
2794 case ICMD_BASTORECONST:
2795 case ICMD_CASTORECONST:
2796 case ICMD_SASTORECONST:
2797 ret = lsra_test_from_stack(ls, rd, src, values); /* stack -> value*/
2798 ret = lsra_test_from_stack(ls, rd, src->prev, values); /* stack -> objref*/
2801 /* pop 0 push 1 dup */
2802 /* merge dupped vars??? */
2803 case ICMD_DUP: /* src == dst->prev, src -> dst */
2804 /* ret = lsra_test_from_stack(ls, rd, src,b_index,iindex);*/ /* just inc usage count? */
2805 ret = lsra_test_new_stack(ls, rd,dst, values);
2808 /* pop 0 push 2 dup */
2811 /* ret = lsra_test_from_stack(ls, rd, src,b_index,iindex); */ /* just inc usage count? */
2812 /* ret = lsra_test_from_stack(ls, rd, src->prev,b_index,iindex); */ /* just inc usage count? */
2813 ret = lsra_test_new_stack(ls, rd,dst->prev, values);
2814 ret = lsra_test_new_stack(ls, rd,dst, values);
2817 /* pop 2 push 3 dup */
2820 ret = lsra_test_from_stack(ls, rd, src, values);
2821 ret = lsra_test_from_stack(ls, rd, src->prev, values);
2822 ret = lsra_test_new_stack(ls, rd,dst->prev->prev, values);
2823 ret = lsra_test_new_stack(ls, rd,dst->prev, values);
2824 ret = lsra_test_new_stack(ls, rd,dst, values);
2827 /* pop 3 push 4 dup */
2830 ret = lsra_test_from_stack(ls, rd, src, values);
2831 ret = lsra_test_from_stack(ls, rd, src->prev, values);
2832 ret = lsra_test_from_stack(ls, rd, src->prev->prev, values);
2833 ret = lsra_test_new_stack(ls, rd,dst->prev->prev->prev, values);
2834 ret = lsra_test_new_stack(ls, rd,dst->prev->prev, values);
2835 ret = lsra_test_new_stack(ls, rd,dst->prev, values);
2836 ret = lsra_test_new_stack(ls, rd,dst, values);
2839 /* pop 3 push 5 dup */
2842 ret = lsra_test_from_stack(ls, rd, src, values);
2843 ret = lsra_test_from_stack(ls, rd, src->prev, values);
2844 ret = lsra_test_from_stack(ls, rd, src->prev->prev, values);
2845 ret = lsra_test_new_stack(ls, rd,dst->prev->prev->prev->prev, values);
2846 ret = lsra_test_new_stack(ls, rd,dst->prev->prev->prev, values);
2847 ret = lsra_test_new_stack(ls, rd,dst->prev->prev, values);
2848 ret = lsra_test_new_stack(ls, rd,dst->prev, values);
2849 ret = lsra_test_new_stack(ls, rd,dst, values);
2852 /* pop 4 push 6 dup */
2855 ret = lsra_test_from_stack(ls, rd, src, values);
2856 ret = lsra_test_from_stack(ls, rd, src->prev, values);
2857 ret = lsra_test_from_stack(ls, rd, src->prev->prev, values);
2858 ret = lsra_test_from_stack(ls, rd, src->prev->prev->prev, values);
2859 ret = lsra_test_new_stack(ls, rd,dst->prev->prev->prev->prev->prev, values);
2860 ret = lsra_test_new_stack(ls, rd,dst->prev->prev->prev->prev, values);
2861 ret = lsra_test_new_stack(ls, rd,dst->prev->prev->prev, values);
2862 ret = lsra_test_new_stack(ls, rd,dst->prev->prev, values);
2863 ret = lsra_test_new_stack(ls, rd,dst->prev, values);
2864 ret = lsra_test_new_stack(ls, rd,dst, values);
2868 /* pop 2 push 2 swap */
2871 ret = lsra_test_from_stack(ls, rd, src, values);
2872 ret = lsra_test_from_stack(ls, rd, src->prev, values);
2873 ret = lsra_test_new_stack(ls, rd,dst->prev, values);
2874 ret = lsra_test_new_stack(ls, rd,dst, values);
2924 ret = lsra_test_from_stack(ls, rd, src, values);
2925 ret = lsra_test_from_stack(ls, rd, src->prev, values);
2926 ret = lsra_test_new_stack(ls, rd,dst, values);
2930 case ICMD_IADDCONST:
2931 case ICMD_ISUBCONST:
2932 case ICMD_IMULCONST:
2936 case ICMD_IANDCONST:
2938 case ICMD_IXORCONST:
2939 case ICMD_ISHLCONST:
2940 case ICMD_ISHRCONST:
2941 case ICMD_IUSHRCONST:
2943 case ICMD_LADDCONST:
2944 case ICMD_LSUBCONST:
2945 case ICMD_LMULCONST:
2949 case ICMD_LANDCONST:
2951 case ICMD_LXORCONST:
2952 case ICMD_LSHLCONST:
2953 case ICMD_LSHRCONST:
2954 case ICMD_LUSHRCONST:
2956 case ICMD_IFEQ_ICONST:
2957 case ICMD_IFNE_ICONST:
2958 case ICMD_IFLT_ICONST:
2959 case ICMD_IFGE_ICONST:
2960 case ICMD_IFGT_ICONST:
2961 case ICMD_IFLE_ICONST:
2966 case ICMD_INT2SHORT:
2984 case ICMD_CHECKCAST:
2986 case ICMD_ARRAYLENGTH:
2987 case ICMD_INSTANCEOF:
2990 case ICMD_ANEWARRAY:
2993 ret = lsra_test_from_stack(ls, rd, src, values);
2994 ret = lsra_test_new_stack(ls, rd,dst, values);
2999 case ICMD_GETSTATIC:
3001 ret = lsra_test_new_stack(ls, rd,dst, values);
3004 /* pop many push any */
3005 case ICMD_INVOKEVIRTUAL:
3006 case ICMD_INVOKESPECIAL:
3007 case ICMD_INVOKESTATIC:
3008 case ICMD_INVOKEINTERFACE:
3011 ret = lsra_test_from_stack(ls, rd, src, values);
3014 if (((methodinfo*)iptr->val.a)->returntype != TYPE_VOID) {
3015 ret = lsra_test_new_stack(ls, rd,dst, values);
3020 ret = lsra_test_from_stack(ls, rd, src, values);
3023 ret = lsra_test_from_stack(ls, rd, src, values);
3026 ret = lsra_test_from_stack(ls, rd, src, values);
3027 src = src->prev; /* ??????????? */
3028 if (iptr->op1 != TYPE_VOID)
3029 ret = lsra_test_new_stack(ls, rd, dst, values);
3032 case ICMD_MULTIANEWARRAY:
3035 ret = lsra_test_from_stack(ls, rd, src, values);
3038 ret = lsra_test_new_stack(ls, rd, dst, values);
3042 printf("ICMD %d at %d\n", iptr->opc, (int)(iptr - m->instructions));
3043 panic("Missing ICMD code during register allocation");
3047 printf("BB: %i IIndex %i \n", b_index, iindex);
3052 for (succ = ls->succ[b_index]; succ != NULL; succ = succ->next)
3058 for (i=0, succ = ls->succ[b_index]; i!=j; i++, succ=succ->next);
3060 if ( (ret=_test_lifetimes(m, ls, rd, succ->value, values)) != -1) {
3061 printf("[BB %3i IIndex %3i]",b_index, iindex);
3068 void test_lifetimes( methodinfo *m, lsradata *ls, registerdata *rd)
3070 int *values, i, j, p, t;
3073 v_max = rd->maxmemuse + rd->intregsnum + rd->fltregsnum;
3075 if ( (values = calloc( v_max, sizeof(int))) == NULL )
3076 panic("test_lifetimes: out of memory\n");
3079 for (j=0; (j < 100) && (ret == -1); j++ ) {
3080 for (i=0; i < v_max; i++) values[i]=VS;
3082 for (p = 0, i = 0; p < m->paramcount; p++) {
3083 t = m->paramtypes[p];
3085 if (rd->locals[i][t].type >= 0)
3086 lsra_test_local( ls, rd, i, t, LSRA_STORE, values);
3089 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
3093 if ((ret=_test_lifetimes(m, ls, rd, 0, values)) != -1) {
3105 * These are local overrides for various environment variables in Emacs.
3106 * Please do not remove this and leave it at the end of the file, where
3107 * Emacs will automagically detect them.
3108 * ---------------------------------------------------------------------
3111 * indent-tabs-mode: t