1 /* src/vm/jit/allocator/lsra.inc - linear scan register allocator
3 Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
4 C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5 E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6 J. Wenninger, 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., 51 Franklin Street, Fifth Floor, Boston, MA
25 Contact: cacao@cacaojvm.org
27 Authors: Christian Ullrich
29 Changes: Christian Thalinger
32 $Id: lsra.c 4796 2006-04-20 18:04:18Z edwin $
48 #include "mm/memory.h"
49 #include "toolbox/logging.h"
50 #include "vm/builtin.h"
51 #include "vm/exceptions.h"
52 #include "vm/resolve.h"
53 #include "vm/options.h"
54 #include "vm/statistics.h"
55 #include "vm/stringlocal.h"
56 #include "vm/jit/abi.h"
57 #include "vm/jit/reg.h"
58 #include "vm/jit/allocator/lsra.h"
61 /* function prototypes */
62 bool lsra_test(methodinfo *, codegendata *);
63 void lsra_init(methodinfo *, codegendata *, lsradata *);
64 void lsra_setup(methodinfo *, codegendata *, registerdata *, lsradata *);
65 void lsra_main(methodinfo *, lsradata *, registerdata *, codegendata *);
66 void lsra_clean_Graph( methodinfo *, codegendata *, lsradata *);
69 void lsra_dump_stack(stackptr );
71 #ifdef LSRA_PRINTLIFETIMES
72 void print_lifetimes(registerdata *, lsradata *, int *, int);
75 void test_lifetimes( methodinfo *, lsradata *, registerdata *);
78 void lsra_reg_setup(methodinfo *m ,registerdata *,struct lsra_register *,struct lsra_register * );
81 void lsra_scan_registers_canditates(methodinfo *, lsradata *, int);
83 void lsra_join_lifetimes( methodinfo *, lsradata *, int);
84 void lsra_calc_lifetime_length(methodinfo *, lsradata *, codegendata *);
86 void _lsra_new_stack( lsradata *, stackptr , int , int, int);
87 void _lsra_from_stack(lsradata *, stackptr , int , int, int);
88 void lsra_add_ss(struct lifetime *, stackptr );
89 void lsra_usage_local(lsradata *, s4 , int , int , int , int );
91 void _lsra_main( methodinfo *, lsradata *, int *, int, struct lsra_register *, int *);
92 void lsra_expire_old_intervalls(methodinfo *, lsradata *, struct lifetime *, struct lsra_register *);
93 void spill_at_intervall(methodinfo *, lsradata *, struct lifetime *);
94 void lsra_add_active(struct lifetime *, struct lifetime **, int *);
95 void _lsra_expire_old_intervalls(methodinfo *, struct lifetime *, struct lsra_register *, struct lifetime **, int *);
96 void _spill_at_intervall(struct lifetime *, struct lifetime **, int *);
98 void lsra_alloc(methodinfo *, registerdata *, struct lsradata *, int *, int, int *);
99 int lsra_getmem(struct lifetime *, struct freemem *, int *);
100 struct freemem *lsra_getnewmem(int *);
101 void lsra_align_stackslots(struct lsradata *, stackptr, stackptr);
102 void lsra_setflags(int *, int);
105 bool lsra(jitdata *jd)
111 #if defined(ENABLE_STATISTICS)
115 #if defined(LSRA_DEBUG) || defined(LSRA_LEAF)
116 char name[1256], name1[1256];
119 #if defined(LSRA_DEBUG)
125 while (b_index < m->basicblockcount ) {
127 if (m->basicblocks[b_index].flags >= BBREACHED) {
129 in=m->basicblocks[b_index].instack;
130 ind=m->basicblocks[b_index].indepth;
131 for (;ind != 0;in=in->prev, ind--) {
132 /* ARGVAR or LOCALVAR in instack is ok*/
133 if (in->varkind == ARGVAR) printf("ARGVAR in instack: \n");
134 if (in->varkind == LOCALVAR) printf("LOCALVAR in instack\n");
136 out=m->basicblocks[b_index].outstack;
137 outd=m->basicblocks[b_index].outdepth;
138 for (;outd != 0;out=out->prev, outd--) {
139 if (out->varkind == ARGVAR)
140 { log_text("ARGVAR in outstack\n"); assert(0); }
141 if (out->varkind == LOCALVAR)
142 { log_text("LOCALVAR in outstack\n"); assert(0); }
149 #if defined(LSRA_DEBUG) || defined(LSRA_LEAF)
150 printf("Max Lifetimes %i \n", m->maxlifetimes);
151 utf_sprint(name, m->class->name);
152 utf_sprint(name1, m->name);
155 utf_sprint(name1, m->descriptor);
159 printf("/******************************************************/\n");
164 /* printf("LSRA Start for %s opt_from: %i opt_to: %i\n", name, opt_from, opt_to); */
166 if (strcmp(name,"java/util/Vector.<init>(II)V")==0) {
167 printf("-------------------\n");
170 printf("**Leafmethod**\n");
174 /* get required compiler data */
181 lsra_init(m, cd, ls);
184 #if defined(LSRA_USES_REG_RES)
185 for (i=opt_from; i<=opt_to; i++) {
186 icmd_uses_reg_res[i][0]=S|D|YES;
187 icmd_uses_reg_res[i][1]=S|D|YES;
188 icmd_uses_reg_res[i][2]=S|D|YES;
189 icmd_uses_reg_res[i][3]=REG_NULL;
194 lsra_setup(m, cd, rd, ls);
196 #if defined(ENABLE_STATISTICS)
197 /* find conflicts between locals for statistics */
199 /* local Variable Lifetimes are at the end of the lifetime array and */
200 /* have v_index >= 0 */
201 for (locals_start = ls->lifetimecount-1; (locals_start >=0) &&
202 (ls->lifetime[ls->lt_used[locals_start]].v_index >= 0);
204 for (i=locals_start + 1; i < ls->lifetimecount; i++)
205 for (j=i+1; j < ls->lifetimecount; j++)
206 if ( !((ls->lifetime[ls->lt_used[i]].i_end
207 < ls->lifetime[ls->lt_used[j]].i_start)
208 || (ls->lifetime[ls->lt_used[j]].i_end <
209 ls->lifetime[ls->lt_used[i]].i_start)) )
210 count_locals_conflicts += 2;
214 lsra_main(m, ls, rd, cd);
216 /* everything's ok */
221 /* sort Basic Blocks using Depth First Search in reverse post order in */
223 void lsra_DFS(methodinfo *m, lsradata *ls) {
231 stack = DMNEW( int, m->basicblockcount + 1);
232 visited = DMNEW( bool, m->basicblockcount + 1);
233 for (i = 0; i <= m->basicblockcount; i++) {
236 ls->sorted_rev[i]=-1;
239 stack[0] = 0; /* start with Block 0 */
241 visited[0] = ls->num_pred[0]; /* Start Block is handled right and can be */
245 while (not_finished) {
246 while (stack_top != 0) {
248 i = stack[stack_top];
251 for (succ = ls->succ[i]; succ != NULL; succ = succ->next) {
252 visited[succ->value]++;
253 if (visited[succ->value] == ls->num_pred[succ->value]) {
254 /* push the node on the stack, only if all ancestors have */
256 stack[stack_top] = succ->value;
261 not_finished = false;
262 for (i=1; i <= m->basicblockcount; i++) {
263 /* search for visited blocks, which have not reached the num_pred */
264 /* and put them on the stack -> happens with backedges */
265 if ((visited[i] != 0) && (visited[i] < ls->num_pred[i])) {
266 stack[stack_top] = i;
268 visited[i] = ls->num_pred[i];
276 void lsra_get_backedges_(lsradata *ls, int basicblockcount) {
279 struct _backedge *_backedges;
285 /* now look for backedges */
286 ls->backedge_count = 0;
287 for(i=0; i < basicblockcount; i++) {
288 if (ls->sorted[i] != -1)
289 for(s=ls->succ[ls->sorted[i]]; s != NULL; s=s->next) {
290 if (i >= ls->sorted_rev[s->value]) {
291 n=DNEW(struct _backedge);
292 n->start = max(i, ls->sorted_rev[s->value]);
293 n->end = min(i, ls->sorted_rev[s->value]);
294 n->next = _backedges;
296 ls->backedge_count++;
300 /* put _backedges in ls->backedge array */
301 ls->backedge = DMNEW(struct _backedge *, ls->backedge_count);
302 for (n=_backedges, i=0; n != NULL; n=n->next, i++) {
304 ls->backedge[i]->nesting = 1;
308 void lsra_get_nesting(methodinfo *m, lsradata *ls) {
312 for (i=0; i <= m->basicblockcount; i++)
313 if (ls->sorted[i] != -1)
314 ls->sorted_rev[ls->sorted[i]]=i;
316 lsra_get_backedges_(ls, m->basicblockcount + 1);
317 /* - sort backedge by increasing end: */
318 for (i=0; i < ls->backedge_count; i++)
319 for (j=i+1; j < ls->backedge_count; j++)
320 if ((ls->backedge[i]->end > ls->backedge[j]->end) || /* -> swap */
321 ((ls->backedge[i]->end == ls->backedge[j]->end) &&
322 (ls->backedge[i]->start > ls->backedge[j]->start) )) {
324 ls->backedge[i]=ls->backedge[j];
328 /* create ls->nesting */
329 /* look for nesting depth (overlapping backedges*/
330 for (i=0; i < ls->backedge_count - 1; i++) {
331 for (j = i + 1; (j < ls->backedge_count) &&
332 (ls->backedge[i]->start >= ls->backedge[j]->end); j++)
333 ls->backedge[j]->nesting += ls->backedge[i]->nesting;
338 while ( (i < m->basicblockcount + 1) ) {
339 if (j < ls->backedge_count) {
340 while ( i < ls->backedge[j]->end ) {
344 if ( (j+1) < ls->backedge_count)
345 end = min(ls->backedge[j]->start, ls->backedge[j+1]->end - 1);
347 end = ls->backedge[j]->start;
349 ls->nesting[i] = ls->backedge[j]->nesting;
360 printf("sorted: \n");
361 for (i=0; i < ls->backedge_count; i++)
362 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);
363 printf("Nesting Level \n");
364 for (i=0; i<m->basicblockcount; i++) printf(" %3li", ls->nesting[i]);
367 for (i=0; i <= m->basicblockcount; i++) {
368 ls->sorted_rev[i] = -1;
369 ls->nesting[i] = 1+ls->nesting[i]*ls->nesting[i];
373 void lsra_get_backedges( methodinfo *m, lsradata *ls) {
379 /* first remove artificial end basicblock from ls->sorted, succ and pred */
381 for (i=0; i < m->basicblockcount; i++) {
382 for (next=&(ls->succ[i]); *next != NULL; next=&((*next)->next)) {
383 if ( (*next)->value == m->basicblockcount ) {
384 /* artificial end bb found */
385 *next = (*next)->next;
386 if (*next == NULL) break;
389 for (next=&(ls->pred[i]); *next != NULL; next=&((*next)->next)) {
390 if ( (*next)->value == m->basicblockcount ) {
391 /* artificial end bb found */
392 *next = (*next)->next;
393 if (*next == NULL) break;
397 if (ls->sorted[i] == m->basicblockcount) j=i;
400 /* if an artificial end block was removed -> change ls->sorted accordingly*/
402 for (i=j+1; i <= m->basicblockcount; i++) {
403 ls->sorted[i-1] = ls->sorted[i];
404 ls->nesting[i-1] = ls->nesting[i];
407 for (i=0; i < m->basicblockcount; i++)
408 if (ls->sorted[i] != -1)
409 ls->sorted_rev[ls->sorted[i]]=i;
411 lsra_get_backedges_(ls, m->basicblockcount);
413 /* - sort backedge by increasing start */
414 for (i=0; i < ls->backedge_count; i++)
415 for (j=i+1; j < ls->backedge_count; j++)
416 if (ls->backedge[i]->start > ls->backedge[j]->start) { /* -> swap */
418 ls->backedge[i]=ls->backedge[j];
423 printf("sorted: \n");
424 for (i=0; i < ls->backedge_count; i++)
425 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);
426 printf("Nesting Level \n");
427 for (i=0; i<m->basicblockcount; i++) printf(" %3li", ls->nesting[i]);
432 /* - merge overlapping backedges */
435 for (i=0; i < ls->backedge_count-1; i++) {
436 if (ls->backedge[i] != NULL) {
437 for (j = i + 1; (j < ls->backedge_count) && (ls->backedge[j] == NULL); j++ );
438 if (j != ls->backedge_count) {
439 if (ls->backedge[i]->start >= ls->backedge[j]->end) {
441 /* overlapping -> merge */
442 ls->backedge[j]->end = min (ls->backedge[j]->end,
443 ls->backedge[i]->end);
444 ls->backedge[i] = NULL;
451 printf("merged: \n");
452 for (i = 0; i < ls->backedge_count; i++)
453 if (ls->backedge[i] != NULL)
454 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);
456 /* - remove backedge[] == NULL from array */
458 for (j = ls->backedge_count - 1; ((j>=0) && (ls->backedge[j] == NULL));
462 if (ls->backedge[i] == NULL) { /* swap backedge[i] and backedge[j]*/
464 ls->backedge[j] = ls->backedge[i];
468 ls->backedge_count--;
473 for (i=0; i < ls->backedge_count; i++)
474 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);
478 void lsra_add_cfg( methodinfo *m, lsradata *ls, int from, int to) {
481 /* ignore Empty, Deleted,... Basic Blocks as target */
482 /* TODO: Setup BasicBlock array before to avoid this */
483 /* best together with using the basicblock list, so lsra works */
484 /* with opt_loops, too */
485 for (;(to < m->basicblockcount) && (m->basicblocks[to].flags < BBREACHED); to++);
487 for (n=ls->succ[from]; (n!= NULL) && (n->value != to); n=n->next);
488 if (n != NULL) return; /* edge from->to already existing */
490 n=DNEW(struct _list);
493 n->next=ls->succ[from];
496 n=DNEW(struct _list);
498 n->next=ls->pred[to];
503 /* add Edges from guarded Areas to Exception handlers in the CFG */
504 void lsra_add_exceptions(methodinfo *m, codegendata *cd, lsradata *ls) {
507 /* add cfg edges from all bb of a try block to the start of the according */
508 /* exception handler to ensure the right order after depthfirst search */
510 ex=cd->exceptiontable;
512 printf("ExTable(%i): ", cd->exceptiontablelength);
515 for (; ex != NULL; ex = ex->down) {
518 printf("[%i-%i]->%i ",ex->start->debug_nr, ex->end->debug_nr,
519 ex->handler->debug_nr);
520 if (ex->handler->debug_nr >= m->basicblockcount)
521 { log_text("Exceptionhandler Basicblocknummer invalid\n");
523 if (m->basicblocks[ex->handler->debug_nr].flags < BBREACHED)
524 { log_text("Exceptionhandler Basicblocknummer not reachable\n");
526 if (ex->start->debug_nr > ex->end->debug_nr)
527 { log_text("Guarded Area starts after its end\n"); assert(0); }
529 /* loop all valid Basic Blocks of the guarded area and add CFG edges */
530 /* to the appropriate handler */
531 for (i=ex->start->debug_nr; (i <= ex->end->debug_nr) &&
532 (i < m->basicblockcount); i++)
533 if (m->basicblocks[i].flags >= BBREACHED)
534 lsra_add_cfg(m, ls, i, ex->handler->debug_nr);
541 void lsra_add_jsr( methodinfo *m, lsradata *ls, int from, int to) {
542 struct _sbr *sbr, *n;
545 /* ignore Empty, Deleted,... Basic Blocks as target */
546 /* TODO: Setup BasicBlock array before to avoid this */
547 /* best together with using the basicblock list, so lsra works */
548 /* with opt_loops, too */
549 for (; (to < m->basicblockcount) && (m->basicblocks[to].flags < BBREACHED);
552 if (to == m->basicblockcount)
553 { log_text("Invalid subroutine start index\n"); assert(0); }
556 lsra_add_cfg(m, ls, from, to);
558 /* from + 1 ist the return Basic Block Index */
559 for (from++; (from < m->basicblockcount) &&
560 (m->basicblocks[from].flags < BBREACHED); from++);
562 if (from == m->basicblockcount)
563 { log_text("Invalid return basic block index for jsr\n"); assert(0); }
566 /* add subroutine info in ls->sbr.next */
568 /* search for right place to insert */
569 for (sbr = &(ls->sbr); (sbr->next != NULL) && (sbr->next->header < to); sbr=sbr->next);
571 if ((sbr->next!= NULL) && (sbr->next->header == to)) {
572 /* Entry for this sub already exist */
575 /* make new Entry and insert it in ls->sbr.next */
576 n = DNEW( struct _sbr );
586 /* now insert return adress in sbr->ret */
587 ret = DNEW( struct _list);
589 ret->next = sbr->ret;
593 void lsra_add_sub( methodinfo *m, lsradata *ls, int b_index, struct _list *ret, bool *visited )
599 /* break at virtual End Block */
600 if (b_index != m->basicblockcount) {
601 visited[b_index] = true;
604 if (m->basicblocks[b_index].flags < BBREACHED)
606 if (!next_block && !(m->basicblocks[b_index].icount))
610 ip = m->basicblocks[b_index].iinstr + m->basicblocks[b_index].icount -1;
612 if (ip->opc == ICMD_JSR) /* nested Subroutines */
617 if (ip->opc == ICMD_RET) { /* subroutine return found -> add return adresses to CFG */
618 for (l = ret; l != NULL; l = l->next)
619 lsra_add_cfg( m, ls, b_index, l->value);
620 } else { /* follow CFG */
621 for ( l = ls->succ[b_index]; l != NULL; l = l->next)
622 if (!visited[l->value])
623 lsra_add_sub( m, ls, l->value, ret, visited);
625 } else { /* fall through to next block */
626 if (!visited[b_index + 1])
627 lsra_add_sub(m, ls, b_index + 1, ret, visited);
632 /* Add subroutines from ls->sbr list to CFG */
633 void lsra_add_subs(methodinfo *m, lsradata *ls) {
641 visited = DMNEW(int, m->basicblockcount + 1);
642 for (i=0; i <= m->basicblockcount; i++); visited[i] = false;
643 for (sbr = ls->sbr.next; sbr != NULL; sbr=sbr->next) {
645 printf("Subroutine Header: %3i Return Adresses:",sbr->header);
646 for (ret = sbr->ret; ret != NULL; ret = ret->next)
647 printf(" %3i", ret->value);
650 lsra_add_sub( m, ls, sbr->header, sbr->ret, visited );
657 /* Generate the Control Flow Graph */
658 /* ( pred,succ,num_pred of lsradata structure) */
660 void lsra_make_cfg(methodinfo *m, lsradata *ls)
664 int high, low, count;
668 while (b_index < m->basicblockcount ) {
669 if (m->basicblocks[b_index].flags >= BBREACHED) {
670 ip = m->basicblocks[b_index].iinstr +
671 m->basicblocks[b_index].icount -1;
672 /* set ip to last instruction */
674 if (m->basicblocks[b_index].icount) {
675 /* block contains instructions */
676 switch (ip->opc) { /* check type of last instruction */
684 lsra_add_cfg(m, ls, b_index, m->basicblockcount);
685 break; /* function returns -> end of graph */
714 case ICMD_IF_ACMPNE: /* branch -> add next block */
715 lsra_add_cfg(m, ls, b_index, b_index+1);
716 /* fall throu -> add branch target */
719 lsra_add_cfg(m, ls, b_index, m->basicblockindex[ip->op1]);
720 break; /* visit branch (goto) target */
722 case ICMD_TABLESWITCH: /* switch statement */
725 lsra_add_cfg(m, ls, b_index, m->basicblockindex[*s4ptr]);
732 count = (high-low+1);
734 while (--count >= 0) {
736 lsra_add_cfg(m, ls, b_index,
737 m->basicblockindex[*s4ptr]);
741 case ICMD_LOOKUPSWITCH: /* switch statement */
744 lsra_add_cfg(m, ls, b_index, m->basicblockindex[*s4ptr]);
749 while (--count >= 0) {
750 lsra_add_cfg(m, ls, b_index,
751 m->basicblockindex[s4ptr[1]]);
757 lsra_add_jsr(m, ls, b_index, m->basicblockindex[ip->op1]);
764 lsra_add_cfg(m, ls, b_index, b_index + 1 );
766 } /* switch (ip->opc)*/
767 } /* if (m->basicblocks[blockIndex].icount) */
768 } /* if (m->basicblocks[b_index].flags >= BBREACHED) */
770 } /* while (b_index < m->basicblockcount ) */
776 void lsra_init(methodinfo *m, codegendata *cd, lsradata *ls)
780 /* Init LSRA Data Structures */
781 /* allocate lifetimes for all Basicblocks */
782 /* + 1 for an artificial exit node */
783 /* which is needed as "start" point for the reverse postorder sorting */
784 ls->pred = DMNEW(struct _list *, m->basicblockcount+1);
785 ls->succ = DMNEW(struct _list *, m->basicblockcount+1);
786 ls->sorted = DMNEW(int , m->basicblockcount+1);
787 ls->sorted_rev = DMNEW(int , m->basicblockcount+1);
788 ls->num_pred = DMNEW(int , m->basicblockcount+1);
789 ls->nesting = DMNEW(long , m->basicblockcount);
790 for (i=0; i<m->basicblockcount; i++) {
794 ls->sorted_rev[i]=-1;
798 ls->pred[m->basicblockcount]=NULL;
799 ls->succ[m->basicblockcount]=NULL;
800 ls->sorted[m->basicblockcount]=-1;
801 ls->sorted_rev[m->basicblockcount]=-1;
802 ls->num_pred[m->basicblockcount]=0;
805 if (cd->maxlocals != id->cumlocals)
806 { log_text("lsra: Welche locals nehmen?\n"); assert(0); }
809 ls->maxlifetimes = m->maxlifetimes;
810 ls->lifetimecount = ls->maxlifetimes + cd->maxlocals * (TYPE_ADR+1);
811 ls->lifetime = DMNEW(struct lifetime, ls->lifetimecount);
812 ls->lt_used = DMNEW(int, ls->lifetimecount);
813 ls->lt_int = DMNEW(int, ls->lifetimecount);
814 ls->lt_int_count = 0;
815 ls->lt_flt = DMNEW(int, ls->lifetimecount);
816 ls->lt_flt_count = 0;
817 ls->lt_mem = DMNEW(int, ls->lifetimecount);
818 ls->lt_mem_count = 0;
819 for (i=0; i < ls->lifetimecount; i++) ls->lifetime[i].type = -1;
826 void lsra_setup(methodinfo *m, codegendata *cd, registerdata *rd, lsradata *ls)
834 methoddesc *md = m->parseddesc;
836 #if defined(ENABLE_LOOP)
837 /* Loop optimization "destroys" the basicblock array */
838 /* TODO: work with the basicblock list */
840 log_text("lsra not possible with loop optimization\n");
843 #endif /* defined(ENABLE_LOOP) */
845 /* Setup LSRA Data structures */
847 /* Generate the Control Flow Graph */
848 lsra_make_cfg(m, ls);
849 /* gather nesting before adding of Exceptions and Subroutines!!! */
852 lsra_get_nesting( m, ls);
855 printf("Successors:\n");
856 for (i=0; i < m->basicblockcount; i++) {
858 for (nl=ls->succ[i]; nl!= NULL; nl=nl->next)
859 printf("%3i ",nl->value);
862 printf("Predecessors:\n");
863 for (i=0; i < m->basicblockcount; i++) {
865 for (nl=ls->pred[i]; nl!= NULL; nl=nl->next)
866 printf("%3i ",nl->value);
870 for (i=0; i < m->basicblockcount; i++) printf("%3i ", ls->sorted[i]);
872 printf("Sorted_rev: ");
873 for (i=0; i < m->basicblockcount; i++) printf("%3i ", ls->sorted_rev[i]);
876 /* add subroutines before exceptions! They "destroy" the CFG */
877 lsra_add_subs(m, ls);
878 lsra_add_exceptions(m, cd, ls);
880 /* generate reverse post order sort */
883 /* setup backedge and nested data structures*/
884 lsra_get_backedges( m, ls);
886 printf("Successors:\n");
887 for (i=0; i < m->basicblockcount; i++) {
889 for (nl=ls->succ[i]; nl!= NULL; nl=nl->next)
890 printf("%3i ",nl->value);
893 printf("Predecessors:\n");
894 for (i=0; i < m->basicblockcount; i++) {
896 for (nl=ls->pred[i]; nl!= NULL; nl=nl->next)
897 printf("%3i ",nl->value);
901 for (i=0; i < m->basicblockcount; i++) printf("%3i ", ls->sorted[i]);
903 printf("Sorted_rev: ");
904 for (i=0; i < m->basicblockcount; i++) printf("%3i ", ls->sorted_rev[i]);
910 /* compare m->basicblocks[] with the list basicblocks->next */
911 printf("LSRA BB check\n");
913 bptr = m->basicblocks;
914 while (bptr != NULL) {
915 if (i > m->basicblockcount){
916 { log_text("linked bb list does not correspond with bb array(1)\n");
919 if (bptr != &(m->basicblocks[i])){
920 { log_text("linked bb list does not correspond with bb array(2)\n");
927 if (i<m->basicblockcount){
928 { log_text("linked bb list does not correspond with bb array(3)\n");
934 /* Create Stack Slot lifetimes over all basic blocks */
935 for (i=m->basicblockcount-1; i >= 0; i--) {
936 if (ls->sorted[i] != -1) {
937 lsra_scan_registers_canditates(m, ls, ls->sorted[i]);
938 lsra_join_lifetimes(m, ls, ls->sorted[i]);
942 /* Parameter initialisiation for locals [0 .. paramcount[ */
943 /* -> add local var write access at (bb=0,iindex=-1) */
944 /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
945 /* this needs a special treatment, wenn lifetimes get extended */
946 /* over backedges, since this parameter initialisation happens */
947 /* outside of Basic Block 0 !!!! */
948 /* this could have been avoided by marking the read access with -1,0 */
950 for (p = 0, i = 0; p < md->paramcount; p++) {
951 t = md->paramtypes[p].type;
953 if (rd->locals[i][t].type >= 0)
954 /* Param to Local init happens before normal Code */
955 lsra_usage_local(ls, i, t, 0, -1, LSRA_STORE);
957 if (IS_2_WORD_TYPE(t)) /* increment local counter a second time */
958 i++; /* for 2 word types */
961 lsra_calc_lifetime_length(m, ls, cd);
963 #ifdef LSRA_PRINTLIFETIMES
964 printf("Basicblockcount: %4i\n",m->basicblockcount);
965 /* print_lifetimes(rd, ls, ls->lt_used, ls->lifetimecount); */
969 bool lsra_join_ss( struct lsradata *ls, struct stackelement *in,
970 struct stackelement *out, int join_flag) {
971 struct lifetime *lt, *lto;
972 struct stackslot *ss, *ss_last;
975 if (in->varnum != out->varnum) {
976 lt = &(ls->lifetime[-in->varnum - 1]);
978 printf("Lifetime1 %3i:",-in->varnum-1);
979 for (ss=lt->local_ss; ss!=NULL; ss=ss->next)
985 if (join_flag == JOIN_BB)
986 if (lt->type == -1) {
987 log_text("lsra_join_ss: lifetime for instack not found\n");
992 if (out->varnum >= 0) { /* no lifetime for this slot till now */
993 lsra_add_ss(lt, out);
995 lto = &(ls->lifetime[-out->varnum - 1]);
996 if ((join_flag == JOIN_DUP) || (join_flag == JOIN_OP))
997 if ( (lt->flags & JOIN_BB) || (lto->flags & JOIN_BB)) {
999 printf("DUP or OP join rejected for JOIN_BB Lifetime: v_index1 %3i v_index2 %3i\n",in->varnum, out->varnum);
1003 if (join_flag == JOIN_DUP)
1004 if ( (lt->flags & JOIN_OP) || (lto->flags & JOIN_OP)) {
1006 printf("DUP join rejected for JOIN_OP Lifetime: v_index1 %3i v_index2 %3i\n",in->varnum, out->varnum);
1011 if (lto->type == -1) {
1012 log_text("lsra_join_ss: lifetime for outstack not found\n");
1017 if (lto->type != lt->type) {
1018 log_text("lsra_join_ss: in/out stack type mismatch\n");
1023 printf("Lifetime2 %3i:",-out->varnum-1);
1024 for (ss=lto->local_ss; ss!=NULL; ss=ss->next)
1030 lt->flags |= JOINING;
1032 /* take Lifetime lto out of ls->lifetimes */
1035 /* merge lto into lt of in */
1037 ss_last = ss = lto->local_ss;
1038 while (ss != NULL) {
1040 ss->s->varnum = lt->v_index;
1043 if (ss_last != NULL) {
1044 ss_last->next = lt->local_ss;
1045 lt->local_ss = lto->local_ss;
1048 printf("Lifetime1+2 %3i:",-in->varnum-1);
1049 for (ss=lt->local_ss; ss!=NULL; ss=ss->next)
1053 lt->savedvar |= lto->savedvar;
1054 lt->flags |= lto->flags | join_flag;
1055 lt->usagecount += lto->usagecount;
1057 /*join of bb_first_def, i_first_def und *_last_use */
1058 if (lto->bb_first_def < lt->bb_first_def) {
1059 lt->bb_first_def = lto->bb_first_def;
1060 lt->i_first_def = lto->i_first_def;
1061 } else if ((lto->bb_first_def == lt->bb_first_def) &&
1062 ( lto->i_first_def < lt->i_first_def)) {
1063 lt->i_first_def = lto->i_first_def;
1065 if (lto->bb_last_use > lt->bb_last_use) {
1066 lt->bb_last_use = lto->bb_last_use;
1067 lt->i_last_use = lto->i_last_use;
1068 } else if ((lto->bb_last_use == lt->bb_last_use) &&
1069 ( lto->i_last_use > lt->i_last_use)) {
1070 lt->i_last_use = lto->i_last_use;
1077 /* join instack of Basic Block b_index with outstack of predecessors */
1078 void lsra_join_lifetimes(methodinfo *m, lsradata *ls, int b_index) {
1079 struct stackelement *in, *i, *out;
1082 /* do not join instack of Exception Handler */
1083 if (m->basicblocks[b_index].type == BBTYPE_EXH)
1085 in=m->basicblocks[b_index].instack;
1086 /* do not join first instack element of a subroutine header */
1087 if (m->basicblocks[b_index].type == BBTYPE_SBR)
1091 for (pred = ls->pred[b_index]; pred != NULL; pred = pred->next) {
1092 out = m->basicblocks[pred->value].outstack;
1093 for (i=in; (i != NULL); i = i->prev, out=out->prev) {
1094 lsra_join_ss(ls, i, out, JOIN_BB);
1100 void lsra_reg_setup(methodinfo *m , registerdata *rd,
1101 struct lsra_register *int_reg,
1102 struct lsra_register *flt_reg ) {
1103 int i, j, iarg, farg;
1106 bool *fltarg_used, *intarg_used;
1108 int_reg->nregdesc = nregdescint;
1109 flt_reg->nregdesc = nregdescfloat;
1110 if (m->isleafmethod) {
1111 /* Temp and Argumentregister can be used as saved registers */
1112 methoddesc *md = m->parseddesc;
1114 int_reg->sav_top = INT_ARG_CNT + INT_TMP_CNT + INT_SAV_CNT;
1115 int_reg->sav_reg = DMNEW(int, int_reg->sav_top);
1116 int_reg->tmp_reg = NULL;
1117 int_reg->tmp_top = -1;
1118 flt_reg->sav_top = FLT_ARG_CNT + FLT_TMP_CNT + FLT_SAV_CNT;
1119 flt_reg->sav_reg = DMNEW(int, flt_reg->sav_top);
1120 flt_reg->tmp_reg = NULL;
1121 flt_reg->tmp_top = -1;
1124 /* additionaly precolour registers for Local Variables acting as */
1130 intarg_used = DMNEW(bool, INT_ARG_CNT);
1131 for (i=0; i < INT_ARG_CNT; i++)
1132 intarg_used[i]=false;
1134 fltarg_used = DMNEW(bool, FLT_ARG_CNT);
1135 for (i=0; i < FLT_ARG_CNT; i++)
1136 fltarg_used[i]=false;
1138 int_sav_top=int_reg->sav_top;
1139 flt_sav_top=flt_reg->sav_top;
1141 for (i=0; (i < md->paramcount); i++) {
1142 if (!md->params[i].inmemory) {
1143 if (IS_INT_LNG_TYPE(md->paramtypes[i].type)) {
1144 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
1145 if (IS_2_WORD_TYPE(md->paramtypes[i].type)) {
1146 int_reg->sav_reg[--int_sav_top] =
1147 rd->argintregs[GET_HIGH_REG(md->params[i].regoff)];
1148 intarg_used[GET_HIGH_REG(md->params[i].regoff)]=true;
1149 /*used -> don't copy later on */
1150 int_reg->sav_reg[--int_sav_top] =
1151 rd->argintregs[GET_LOW_REG(md->params[i].regoff)];
1152 intarg_used[GET_LOW_REG(md->params[i].regoff)]=true;
1153 /*used -> don't copy later on */
1156 { /* !IS_2_WORD_TYPE(md->paramtypes[i].type */
1157 int_reg->sav_reg[--int_sav_top] =
1158 rd->argintregs[md->params[i].regoff];
1159 intarg_used[md->params[i].regoff]=true;
1160 /*used -> don't copy later on */
1163 #if !defined(SUPPORT_PASS_FLOATARGS_IN_INTREGS)
1164 /* do not precolour float arguments if they are passed in */
1165 /* integer registers. But these integer argument registers */
1166 /* still be used in the method! */
1167 else { /* IS_FLT_DBL_TYPE(md->paramtypes[i].type */
1168 flt_reg->sav_reg[--flt_sav_top] =
1169 rd->argfltregs[md->params[i].regoff];
1170 fltarg_used[md->params[i].regoff]=true;
1177 /* copy rest of argument registers to flt_reg->sav_reg and */
1178 /* int_reg->sav_reg; */
1179 for (i=0; i < INT_ARG_CNT; i++)
1180 if (!intarg_used[i])
1181 int_reg->sav_reg[--int_sav_top]=rd->argintregs[i];
1182 for (i=0; i < FLT_ARG_CNT; i++)
1183 if (!fltarg_used[i])
1184 flt_reg->sav_reg[--flt_sav_top]=rd->argfltregs[i];
1186 /* copy temp registers to flt_reg->sav_reg and int_reg->sav_reg */
1187 for (i=0; i < INT_TMP_CNT; i++)
1188 int_reg->sav_reg[--int_sav_top]=rd->tmpintregs[i];
1189 for (i=0; i < FLT_TMP_CNT; i++)
1190 flt_reg->sav_reg[--flt_sav_top]=rd->tmpfltregs[i];
1193 /* non leaf method -> use Argument Registers [arg[int|flt]reguse */
1194 /* ... [INT|FLT]_ARG_CNT[ as temp reg */
1195 /* divide temp and saved registers */
1196 int_sav_top = int_reg->sav_top = INT_SAV_CNT;
1197 int_reg->sav_reg = DMNEW(int, int_reg->sav_top);
1198 int_reg->tmp_top = INT_TMP_CNT +
1199 max(0, (INT_ARG_CNT - rd->argintreguse));
1200 int_reg->tmp_reg = DMNEW(int, int_reg->tmp_top);
1202 flt_sav_top =flt_reg->sav_top = FLT_SAV_CNT;
1203 flt_reg->sav_reg = DMNEW(int, flt_reg->sav_top);
1204 flt_reg->tmp_top = FLT_TMP_CNT +
1205 max(0 , (FLT_ARG_CNT - rd->argfltreguse));
1206 flt_reg->tmp_reg = DMNEW(int, flt_reg->tmp_top);
1208 /* copy temp and unused argument registers to flt_reg->tmp_reg and */
1209 /* int_reg->tmp_reg */
1210 for (i=0; i < INT_TMP_CNT; i++)
1211 int_reg->tmp_reg[i]=rd->tmpintregs[i];
1212 for (j=rd->argintreguse; j < INT_ARG_CNT; j++, i++)
1213 int_reg->tmp_reg[i]=rd->argintregs[j];
1214 for (i=0; i < FLT_TMP_CNT; i++)
1215 flt_reg->tmp_reg[i]=rd->tmpfltregs[i];
1216 for (j=rd->argfltreguse; j < FLT_ARG_CNT; j++, i++)
1217 flt_reg->tmp_reg[i]=rd->argfltregs[j];
1220 /* now copy saved registers to flt_reg->sav_reg and int_reg->sav_reg */
1221 for (i = INT_SAV_CNT-1; i >= 0; i--)
1222 int_reg->sav_reg[--int_sav_top]=rd->savintregs[i];
1223 for (i = FLT_SAV_CNT-1; i >= 0; i--)
1224 flt_reg->sav_reg[--flt_sav_top]=rd->savfltregs[i];
1228 void lsra_insertion( struct lsradata *ls, int *a, int lo, int hi) {
1231 for (i=lo+1; i<=hi; i++) {
1233 t=ls->lifetime[a[j]].i_start;
1235 while ((j>lo) && (ls->lifetime[a[j-1]].i_start > t)) {
1243 void lsra_qsort( struct lsradata *ls, int *a, int lo, int hi) {
1249 x = ls->lifetime[a[(lo+hi)/2]].i_start;
1252 while (ls->lifetime[a[i]].i_start < x) i++;
1253 while (ls->lifetime[a[j]].i_start > x) j--;
1255 /* exchange a[i], a[j] */
1265 if (lo < j) lsra_qsort( ls, a, lo, j);
1266 if (i < hi) lsra_qsort( ls, a, i, hi);
1268 lsra_insertion(ls, a, lo, hi);
1272 void lsra_param_sort(struct lsradata *ls, int *lifetime, int lifetime_count) {
1277 /* count number of parameters ( .i_start == -1) */
1278 for (param_count=0; (param_count < lifetime_count) &&
1279 (ls->lifetime[lifetime[param_count]].i_start == -1); param_count++);
1281 if (param_count > 0) {
1282 /* now sort the parameters by v_index */
1283 for (i=0; i < param_count -1; i++)
1284 for (j=i+1; j < param_count; j++)
1285 if ( ls->lifetime[lifetime[i]].v_index >
1286 ls->lifetime[lifetime[j]].v_index) {
1289 lifetime[i]=lifetime[j];
1295 void lsra_main(methodinfo *m, lsradata *ls, registerdata *rd, codegendata *cd)
1302 struct lsra_register flt_reg, int_reg;
1304 /* sort lifetimes by increasing start */
1305 lsra_qsort( ls, ls->lt_mem, 0, ls->lt_mem_count - 1);
1306 lsra_qsort( ls, ls->lt_int, 0, ls->lt_int_count - 1);
1307 lsra_qsort( ls, ls->lt_flt, 0, ls->lt_flt_count - 1);
1308 /* sort local vars used as parameter */
1309 lsra_param_sort( ls, ls->lt_int, ls->lt_int_count);
1310 lsra_param_sort( ls, ls->lt_flt, ls->lt_flt_count);
1311 lsra_reg_setup(m, rd, &int_reg, &flt_reg);
1314 printf("INTSAV REG: ");
1315 for (i=0; i<int_reg.sav_top; i++)
1316 printf("%2i ",int_reg.sav_reg[i]);
1317 printf("\nINTTMP REG: ");
1318 for (i=0; i<int_reg.tmp_top; i++)
1319 printf("%2i ",int_reg.tmp_reg[i]);
1320 printf("\nFLTSAV REG: ");
1321 for (i=0; i<flt_reg.sav_top; i++)
1322 printf("%2i ",flt_reg.sav_reg[i]);
1323 printf("\nFLTTMP REG: ");
1324 for (i=0; i<flt_reg.tmp_top; i++)
1325 printf("%2i ",flt_reg.tmp_reg[i]);
1328 ls->active_tmp = DMNEW( struct lifetime *, max(INT_REG_CNT, FLT_REG_CNT));
1329 ls->active_sav = DMNEW( struct lifetime *, max(INT_REG_CNT, FLT_REG_CNT));
1331 lsra_reg_use=INT_SAV_CNT; /* init to no saved reg used... */
1332 _lsra_main(m, ls, ls->lt_int, ls->lt_int_count, &int_reg,
1334 if (lsra_reg_use > INT_SAV_CNT) lsra_reg_use=INT_SAV_CNT;
1335 rd->savintreguse = lsra_reg_use;
1337 lsra_reg_use = FLT_SAV_CNT; /* no saved reg used... */
1339 _lsra_main(m,ls, ls->lt_flt, ls->lt_flt_count, &flt_reg, &lsra_reg_use);
1340 if (lsra_reg_use > FLT_SAV_CNT) lsra_reg_use=FLT_SAV_CNT;
1342 rd->savfltreguse=lsra_reg_use;
1344 /* rd->memuse was already set in stack.c to allocate stack space for */
1345 /* passing arguments to called methods */
1346 #if defined(__I386__)
1347 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
1348 /* reserve 0(%esp) for Monitorenter/exit Argument on i386 */
1354 lsra_mem_use = rd->memuse; /* Init with memuse from stack.c */
1356 lsra_alloc(m, rd, ls, ls->lt_mem, ls->lt_mem_count, &lsra_mem_use);
1357 lsra_alloc(m, rd, ls, ls->lt_int, ls->lt_int_count, &lsra_mem_use);
1358 lsra_alloc(m, rd, ls, ls->lt_flt, ls->lt_flt_count, &lsra_mem_use);
1360 #ifdef LSRA_PRINTLIFETIMES
1361 printf("Int RA complete \n");
1362 printf("Lifetimes after splitting int: \n");
1363 print_lifetimes(rd, ls, ls->lt_int, ls->lt_int_count);
1365 printf("Flt RA complete \n");
1366 printf("Lifetimes after splitting flt:\n");
1367 print_lifetimes(rd, ls, ls->lt_flt, ls->lt_flt_count);
1369 printf("Rest RA complete \n");
1370 printf("Lifetimes after leftt:\n");
1371 print_lifetimes(rd, ls, ls->lt_mem, ls->lt_mem_count);
1373 rd->memuse=lsra_mem_use;
1375 test_lifetimes(m, ls, rd );
1380 void lsra_alloc(methodinfo *m, registerdata *rd, struct lsradata *ls, int *lifet, int lifetimecount, int *mem_use)
1383 struct lifetime *lt;
1384 struct freemem *fmem;
1385 struct stackslot *n;
1387 #ifdef HAS_4BYTE_STACKSLOT
1388 struct freemem *fmem_2;
1391 fmem=DNEW(struct freemem);
1394 #ifdef HAS_4BYTE_STACKSLOT
1395 fmem_2=DNEW(struct freemem);
1400 for (lt_index = 0; lt_index < lifetimecount; lt_index ++) {
1401 lt = &(ls->lifetime[lifet[lt_index]]);
1407 #ifdef HAS_4BYTE_STACKSLOT
1408 if (IS_2_WORD_TYPE(lt->type))
1409 regoff=lsra_getmem(lt, fmem_2, mem_use);
1412 regoff=lsra_getmem(lt, fmem, mem_use);
1418 if (lt->v_index < 0) {
1419 for (n=lt->local_ss; n!=NULL; n=n->next) {
1420 lsra_setflags( &(n->s->flags), flags);
1421 n->s->regoff=regoff;
1423 } else { /* local var */
1424 if (rd->locals[lt->v_index][lt->type].type>=0) {
1425 rd->locals[lt->v_index][lt->type].flags= flags;
1426 rd->locals[lt->v_index][lt->type].regoff=regoff;
1427 } else { log_text("Type Data mismatch 1\n"); assert(0); }
1433 void lsra_setflags(int *flags, int newflags)
1435 if ( newflags & INMEMORY)
1438 *flags &= ~INMEMORY;
1440 if (newflags & SAVEDVAR)
1444 int lsra_getmem(struct lifetime *lt, struct freemem *fmem, int *mem_use)
1446 struct freemem *fm, *p;
1448 /* noch kein Speicher vergeben, oder alle Enden später */
1449 if ((fmem->next == NULL) || (fmem->next->end > lt->i_start)) {
1450 #ifdef HAS_4BYTE_STACKSLOT
1451 if (IS_2_WORD_TYPE(lt->type))
1452 if ( (*mem_use)&1 ) /* align memory location for 2 Word Types */
1454 fm=lsra_getnewmem(mem_use);
1455 if (IS_2_WORD_TYPE(lt->type))
1456 /* allocate a second following Slot for 2 Word Types */
1459 fm=lsra_getnewmem(mem_use);
1462 /* Speicherstelle frei */
1464 fmem->next=fm->next;
1468 for (p=fmem; (p->next!=NULL) && (p->next->end < fm->end); p=p->next);
1474 struct freemem *lsra_getnewmem(int *mem_use)
1478 fm=DNEW(struct freemem);
1485 void _lsra_main( methodinfo *m, lsradata *ls, int *lifet, int lifetimecount,
1486 struct lsra_register *reg, int *reg_use)
1488 struct lifetime *lt;
1492 bool temp; /* reg from temp registers (true) or saved registers (false) */
1494 #if !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
1497 if ((reg->tmp_top+reg->sav_top) == 0) {
1499 /* no registers available */
1500 for (lt_index = 0; lt_index < lifetimecount; lt_index++)
1501 ls->lifetime[lifet[lt_index]].reg = -1;
1505 ls->active_tmp_top = 0;
1506 ls->active_sav_top = 0;
1508 for (lt_index = 0; lt_index < lifetimecount; lt_index++) {
1509 lt = &(ls->lifetime[lifet[lt_index]]);
1511 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
1512 regsneeded = (lt->type == TYPE_LNG)?1:0;
1515 lsra_expire_old_intervalls(m, ls, lt, reg);
1518 if (lt->savedvar || m->isleafmethod) {
1519 /* use Saved Reg (in case of leafmethod all regs are saved regs) */
1520 if (reg->sav_top > regsneeded) {
1521 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
1523 reg_index = PACK_REGS(reg->sav_reg[--reg->sav_top],
1524 reg->sav_reg[--reg->sav_top]);
1528 reg_index = reg->sav_reg[--reg->sav_top];
1530 } else { /* use Temp Reg or if none is free a Saved Reg */
1531 if (reg->tmp_top > regsneeded) {
1533 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
1535 reg_index = PACK_REGS(reg->tmp_reg[--reg->tmp_top],
1536 reg->tmp_reg[--reg->tmp_top]);
1539 reg_index = reg->tmp_reg[--reg->tmp_top];
1542 if (reg->sav_top > regsneeded) {
1544 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
1546 reg_index = PACK_REGS(reg->sav_reg[--reg->sav_top],
1547 reg->sav_reg[--reg->sav_top]);
1550 reg_index = reg->sav_reg[--reg->sav_top];
1553 if (reg_index == -1) /* no reg is available anymore... -> spill */
1554 spill_at_intervall(m, ls, lt);
1556 lt->reg = reg_index;
1558 lsra_add_active(lt, ls->active_tmp, &(ls->active_tmp_top));
1560 if (reg->sav_top<*reg_use) *reg_use=reg->sav_top;
1561 lsra_add_active(lt, ls->active_sav, &(ls->active_sav_top));
1567 void lsra_add_active(struct lifetime *lt, struct lifetime **active, int *active_top)
1571 for(i = 0; (i < *active_top) && (active[i]->i_end < lt->i_end); i++);
1573 for(j = *active_top; j > i; j--) active[j] = active[j-1];
1581 void lsra_expire_old_intervalls(methodinfo *m, lsradata *ls,
1582 struct lifetime *lt, struct lsra_register *reg)
1584 _lsra_expire_old_intervalls(m, lt, reg, ls->active_tmp, &(ls->active_tmp_top));
1585 _lsra_expire_old_intervalls(m, lt, reg, ls->active_sav, &(ls->active_sav_top));
1588 void _lsra_expire_old_intervalls(methodinfo *m, struct lifetime *lt,
1589 struct lsra_register *reg,
1590 struct lifetime **active, int *active_top)
1594 for(i = 0; i < *active_top; i++) {
1595 if (active[i]->i_end > lt->i_start) break;
1597 /* make active[i]->reg available again */
1598 if (m->isleafmethod) {
1599 /* leafmethod -> don't care about type -> put all again into */
1601 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
1602 if (active[i]->type == TYPE_LNG) {
1603 reg->sav_reg[reg->sav_top++] = GET_LOW_REG(active[i]->reg);
1604 reg->sav_reg[reg->sav_top++] = GET_HIGH_REG(active[i]->reg);
1607 reg->sav_reg[reg->sav_top++] = active[i]->reg;
1609 /* no leafmethod -> distinguish between temp and saved register */
1610 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
1611 if (active[i]->type == TYPE_LNG) {
1612 /* no temp and saved regs are packed together, so looking at */
1613 /* LOW_REG is sufficient */
1614 if ( reg->nregdesc[ GET_LOW_REG(active[i]->reg)] == REG_SAV) {
1615 reg->sav_reg[reg->sav_top++] = GET_LOW_REG(active[i]->reg);
1616 reg->sav_reg[reg->sav_top++] = GET_HIGH_REG(active[i]->reg);
1618 reg->tmp_reg[reg->tmp_top++] = GET_LOW_REG(active[i]->reg);
1619 reg->tmp_reg[reg->tmp_top++] = GET_HIGH_REG(active[i]->reg);
1623 if ( reg->nregdesc[active[i]->reg] == REG_SAV) {
1624 reg->sav_reg[reg->sav_top++] = active[i]->reg;
1626 reg->tmp_reg[reg->tmp_top++] = active[i]->reg;
1631 /* active[0..i[ is to be removed */
1632 /* -> move [i..*active_top[ to [0..*active_top-i[ */
1633 for(k = 0, j = i; (j < *active_top); k++,j++)
1634 active[k] = active[j];
1640 void spill_at_intervall(methodinfo *m, lsradata *ls, struct lifetime *lt )
1642 if (lt->savedvar || m->isleafmethod) {
1643 _spill_at_intervall(lt, ls->active_sav, &(ls->active_sav_top));
1645 _spill_at_intervall(lt, ls->active_tmp, &(ls->active_tmp_top));
1646 if (lt->reg == -1) { /* kein tmp mehr frei gewesen */
1647 _spill_at_intervall(lt, ls->active_sav, &(ls->active_sav_top));
1652 void _spill_at_intervall(struct lifetime *lt, struct lifetime **active, int *active_top)
1661 if (*active_top == 0) {
1666 i = *active_top - 1;
1669 /* find intervall which ends later or equal than than lt and has the lowest usagecount lower than lt*/
1671 u_min = lt->usagecount;
1672 for (; (i >= 0) && (active[i]->i_end >= lt->i_end); i--) {
1673 if (active[i]->usagecount < u_min) {
1674 u_min = active[i]->usagecount;
1682 if ((active[i]->i_end >= lt->i_end) && (active[i]->usagecount < lt->usagecount)) {
1684 /* get last intervall from active */
1685 if (active[i]->i_end > lt->i_end) {
1687 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
1688 /* Don't spill between one and two word int types */
1689 if ((active[i]->type == TYPE_LNG) != (lt->type == TYPE_LNG))
1693 lt->reg=active[i]->reg;
1697 for (j = i; j < *active_top; j++)
1698 active[j] = active[j + 1];
1700 lsra_add_active(lt, active, active_top);
1706 void lsra_calc_lifetime_length(methodinfo *m, lsradata *ls, codegendata *cd)
1708 struct lifetime *lt;
1712 struct stackslot *ss;
1714 int *icount_block, icount;
1715 int flags; /* 0 INMEMORY -> ls->lt_mem */
1716 /* 1 INTREG -> ls->lt_int */
1717 /* 2 FLTREG -> ls->lt_flt */
1721 int cum_local_ss,local_ss_count;
1725 icount_block = DMNEW(int, m->basicblockcount);
1726 icount_block[0] = icount = 0;
1727 for (i=1; i < m->basicblockcount; i++) {
1728 if (ls->sorted[i-1] != -1)
1729 icount += m->basicblocks[ ls->sorted[i-1] ].icount;
1730 if (ls->sorted[i] != -1)
1731 icount_block[i] = icount;
1735 printf("icount_block: ");
1736 for (i=0; i < m->basicblockcount; i++)
1737 printf("(%3i-%3i) ",i, icount_block[i]);
1741 /* extend lifetime over backedges */
1742 /* now iterate through lifetimes and expand them */
1745 max_local_ss = cum_local_ss = 0;
1748 for(lt_index = 0 ;lt_index < ls->lifetimecount; lt_index++) {
1749 if ( ls->lifetime[lt_index].type != -1) { /* used lifetime */
1750 /* remember lt_index in lt_sorted */
1751 ls->lt_used[lifetimecount ++] = lt_index;
1752 lt = &(ls->lifetime[lt_index]);
1753 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
1754 /* prevent conflicts between lifetimes of type long by increasing */
1755 /* the lifetime by one instruction */
1756 /* i.e.(ri/rj) ... */
1757 /* (rk/rl) ICMD_LNEG */
1758 /* with i==l and/or j==k */
1759 /* to resolve this during codegeneration a temporary register */
1760 /* would be needed */
1761 if (lt->type == TYPE_LNG)
1765 /* distribute lifetimes to lt_int, lt_flt and lt_mem */
1771 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
1784 #if defined(__I386__)
1786 * for i386 put all floats in memory
1794 { log_text("Unknown Type\n"); assert(0); }
1798 case 0: /* lt_used[lt_used_index] -> lt_rest */
1799 ls->lt_mem[ ls->lt_mem_count++ ] = lt_index;
1801 case 1: /* l->lifetimes -> lt_int */
1802 ls->lt_int[ ls->lt_int_count++ ] = lt_index;
1804 case 2: /* l->lifetimes -> lt_flt */
1805 ls->lt_flt[ ls->lt_flt_count++ ] = lt_index;
1812 for (ss=lt->local_ss; ss != 0; ss = ss->next, local_ss_count++);
1813 if (local_ss_count > max_local_ss) max_local_ss = local_ss_count;
1814 cum_local_ss+=local_ss_count;
1817 if (lt->bb_first_def == -1) {
1818 /* printf("--------- Warning: variable not defined!------------------vi: %i start: %i end: %i\n", lt->v_index, lt->i_start, lt->i_end); */
1819 lt->bb_first_def = 0;
1820 lt->i_first_def = 0;
1823 lt->i_start = icount_block[lt->bb_first_def] + lt->i_first_def;
1825 if (lt->bb_last_use == -1) {
1826 /* printf("--------- Warning: variable not used! --------------------vi: %i start: %i end: %i\n", lt->v_index, lt->i_start, lt->i_end); */
1827 lt->bb_last_use = lt->bb_first_def;
1828 lt->i_last_use = lt->i_first_def;
1831 lt->i_end = icount_block[lt->bb_last_use] + lt->i_last_use;
1833 if (lt->i_start > lt->i_end)
1834 printf("Warning: last use before first def! vi: %i start: %i end: %i\n", lt->v_index, lt->i_start, lt->i_end);
1836 if ((lt->bb_first_def != lt->bb_last_use) ||
1837 (lt->i_first_def == -1)) {
1838 /* Lifetime goes over more than one Basic Block -> */
1839 /* check for necessary extension over backedges */
1840 /* see lsra_get_backedges */
1841 /* Arguments are set "before" Block 0, so they have */
1842 /* a lifespan of more then one block, too */
1844 for (i=0; i < ls->backedge_count; i++) {
1845 if (!( (lt->bb_first_def > ls->backedge[i]->start) ||
1846 (lt->bb_last_use < ls->backedge[i]->end) )) {
1847 /* Live intervall intersects with a backedge */
1848 /* if (lt->bb_first_def <= ls->backedge[i]->start) */
1849 if (lt->bb_last_use <= ls->backedge[i]->start)
1850 lt->i_end = icount_block[ls->backedge[i]->start] +
1851 m->basicblocks[ls->sorted[ls->backedge[i]->start]].icount;
1855 #ifdef USAGE_PER_INSTR
1856 lt->usagecount = lt->usagecount / ( lt->i_end - lt->i_start + 1);
1860 ls->lifetimecount = lifetimecount;
1863 for (i=0; i<m->basicblockcount; i++)
1864 if (m->basicblocks[i].flags >= BBREACHED)
1865 i_count+=m->basicblocks[i].icount;
1866 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);
1870 #ifdef LSRA_PRINTLIFETIMES
1871 void print_lifetimes(registerdata *rd, lsradata *ls, int *lt, int lifetimecount)
1875 int type,flags,regoff,varkind;
1877 for (lt_index = 0; lt_index < lifetimecount; lt_index++) {
1878 n = &(ls->lifetime[lt[lt_index]]);
1879 if (n->v_index < 0) { /* stackslot */
1880 type = n->local_ss->s->type;
1881 flags=n->local_ss->s->flags;
1882 regoff=n->local_ss->s->regoff;
1883 varkind=n->local_ss->s->varkind;
1884 } else { /* local var */
1885 if (rd->locals[n->v_index][n->type].type>=0) {
1886 type = rd->locals[n->v_index][n->type].type;
1887 flags=rd->locals[n->v_index][n->type].flags;
1888 regoff=rd->locals[n->v_index][n->type].regoff;
1891 { log_text("Type Data mismatch 3\n"); assert(0); }
1893 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);
1895 printf( "%3i Lifetimes printed \n",lt_index);
1899 struct stackslot *lsra_make_ss(stackptr s, int bb_index)
1901 struct stackslot *ss;
1903 ss=DNEW(struct stackslot);
1909 void lsra_add_ss(struct lifetime *lt, stackptr s) {
1910 struct stackslot *ss;
1911 /* Stackslot noch nicht eingetragen? */
1913 if (s->varnum != lt->v_index) {
1914 ss = DNEW(struct stackslot);
1916 ss->s->varnum = lt->v_index;
1917 ss->next = lt->local_ss;
1919 if (s != NULL) lt->savedvar |= s->flags & SAVEDVAR;
1920 if (s != NULL) lt->type = s->type;
1922 printf("New ss vn %i s %p ss %p\n",ss->s->varnum, ss->s, ss);
1927 struct lifetime *get_ss_lifetime(lsradata *ls, stackptr s) {
1930 if (s->varnum >= 0) { /* new stackslot lifetime */
1931 if (-ls->v_index - 1 >= ls->maxlifetimes) {
1932 printf("%i %i\n", -ls->v_index - 1, ls->maxlifetimes);
1934 assert(-ls->v_index - 1 < ls->maxlifetimes);
1936 n = &(ls->lifetime[-ls->v_index - 1]);
1938 n->v_index = ls->v_index--;
1941 n->bb_last_use = -1;
1942 n->bb_first_def = -1;
1947 n = &(ls->lifetime[-s->varnum - 1]);
1953 #define IS_TEMP_VAR(s) (((s)->varkind != ARGVAR) && ((s)->varkind != LOCALVAR))
1955 #define lsra_join_3_stack(ls, dst, src1, src2, join_type) \
1956 if ( IS_TEMP_VAR(dst) ) { \
1958 if ( IS_TEMP_VAR(src1) && ((src1)->type == (dst)->type)) { \
1959 join_ret = lsra_join_ss(ls, dst, src1, join_type); \
1961 if ((!join_ret) && IS_TEMP_VAR(src2) && ((src2)->type == (dst)->type)) { \
1962 lsra_join_ss(ls, dst, src2, join_type); \
1966 #define lsra_join_2_stack(ls, dst, src, join_type) \
1967 if ( IS_TEMP_VAR(dst) ) { \
1968 if ( (IS_TEMP_VAR(src)) && ((src)->type == (dst)->type)) { \
1969 lsra_join_ss(ls, dst, src, join_type); \
1973 #define lsra_join_dup(ls, s1, s2, s3) { \
1974 if (IS_TEMP_VAR(s1)) { \
1976 if (IS_TEMP_VAR(s2)) \
1977 join_ret = lsra_join_ss(ls, s1, s2, JOIN);/* undangerous join!*/ \
1978 if (IS_TEMP_VAR(s3)) { \
1979 if (join_ret) /* first join succesfull -> second of type */ \
1981 lsra_join_ss(ls, s1, s3, JOIN_DUP); \
1983 lsra_join_ss(ls, s1, s3, JOIN); /* first join did not */ \
1984 /* happen -> second undangerous */ \
1987 if (IS_TEMP_VAR(s2) && IS_TEMP_VAR(s3)) \
1988 lsra_join_ss(ls, s2, s3, JOIN_DUP); \
1991 #define lsra_new_stack(ls, s, block, instr) if ((s)->varkind != ARGVAR) _lsra_new_stack(ls, s, block, instr, LSRA_STORE)
1992 void _lsra_new_stack(lsradata *ls, stackptr s, int block, int instr, int store)
1996 if (s->varkind == LOCALVAR) {
1997 lsra_usage_local(ls, s->varnum, s->type, block, instr, LSRA_STORE);
1998 } else /* if (s->varkind != ARGVAR) */ {
2000 n=get_ss_lifetime( ls, s );
2002 if (store == LSRA_BB_IN)
2003 n->flags |= JOIN_BB;
2004 /* remember first def -> overwrite everytime */
2005 n->bb_first_def = ls->sorted_rev[block];
2006 n->i_first_def = instr;
2008 n->usagecount+=ls->nesting[ls->sorted_rev[block]];
2012 #define lsra_from_stack(ls, s, block, instr) if ((s)->varkind != ARGVAR) _lsra_from_stack(ls, s, block, instr, LSRA_LOAD)
2013 #define lsra_pop_from_stack(ls, s, block, instr) if ((s)->varkind != ARGVAR) _lsra_from_stack(ls, s, block, instr, LSRA_POP)
2014 void _lsra_from_stack(lsradata *ls, stackptr s, int block, int instr, int store)
2018 if (s->varkind == LOCALVAR) {
2019 lsra_usage_local(ls, s->varnum, s->type, block, instr, LSRA_LOAD);
2020 } else /* if (s->varkind != ARGVAR) */ {
2021 if (s->varkind == STACKVAR )
2022 /* No STACKVARS possible with lsra! */
2023 s->varkind = TEMPVAR;
2025 n=get_ss_lifetime( ls, s );
2027 if (store == LSRA_BB_OUT)
2028 n->flags |= JOIN_BB;
2029 if (n->flags & JOINING)
2030 n->flags &= ~JOINING;
2031 n->usagecount+=ls->nesting[ls->sorted_rev[block]];
2033 /* remember last USE, so only write, if USE Field is undefined (==-1) */
2034 if (n->bb_last_use == -1) {
2035 n->bb_last_use = ls->sorted_rev[block];
2036 n->i_last_use = instr;
2041 void lsra_usage_local(lsradata *ls, s4 v_index, int type, int block, int instr, int store)
2045 n = &(ls->lifetime[ ls->maxlifetimes + v_index * (TYPE_ADR+1) + type]);
2047 if (n->type == -1) { /* new local lifetime */
2049 /* if (store != LSRA_STORE) printf("lsra_local_store: Read before write Local var: %i paramcount: ?\n", v_index); */
2054 n->savedvar = SAVEDVAR;
2058 n->bb_last_use = -1;
2059 n->bb_first_def = -1;
2061 n->usagecount+=ls->nesting[ls->sorted_rev[block]];
2062 /* add access at (block, instr) to instruction list */
2063 /* remember last USE, so only write, if USE Field is undefined (==-1) */
2064 /* count store as use, too -> defined and not used vars would overwrite */
2066 if (n->bb_last_use == -1) {
2067 n->bb_last_use = ls->sorted_rev[block];
2068 n->i_last_use = instr;
2070 if (store == LSRA_STORE) {
2071 /* store == LSRA_STORE, remember first def -> overwrite everytime */
2072 n->bb_first_def = ls->sorted_rev[block];
2073 n->i_first_def = instr;
2078 void lsra_dump_stack(stackptr s)
2081 printf("%p(R%3i N%3i K%3i T%3i F%3i) ",(void *)s,s->regoff, s->varnum, s->varkind, s->type, s->flags);
2089 void lsra_scan_registers_canditates(methodinfo *m, lsradata *ls, int b_index)
2092 builtintable_entry *bte;
2100 bool join_ret; /* for lsra_join* Macros */
2101 #if defined(LSRA_USES_REG_RES)
2102 int v_index_min_before_instruction;
2103 int v_index_min[REG_RES_CNT];
2105 for (i=0; i < REG_RES_CNT; i++) {
2106 ls->reg_res_free[i] = -1;
2107 v_index_min[i] = ls->v_index;
2111 /* get instruction count for BB and remember the max instruction count */
2113 iindex = m->basicblocks[b_index].icount - 1;
2115 src = m->basicblocks[b_index].instack;
2116 if (m->basicblocks[b_index].type != BBTYPE_STD) {
2119 log_text("No Incoming Stackslot for Exception/Subroutine BB\n");
2123 lsra_new_stack(ls, src, b_index, 0);
2124 if (src->varkind == STACKVAR)
2125 src->varkind = TEMPVAR;
2128 for (;src != NULL; src=src->prev) {
2129 /* no ARGVAR possible at BB Boundaries with LSRA! */
2130 /* -> change to TEMPVAR */
2131 if (src->varkind == ARGVAR ) {
2132 src->varkind = TEMPVAR;
2133 /* On Architectures with own return registers a return stackslot is */
2134 /* marked as varkind=ARGVAR with varnum=-1 */
2135 /* but for lsra a varkind==TEMPVAR, varnum=-1 would mean, that already */
2136 /* a lifetime was allocated! */
2137 if (src->varnum < 0) src->varnum = 0;
2139 else if (src->varkind == LOCALVAR )
2140 /* only allowed for top most ss at sbr or exh entries! */
2141 { log_text("LOCALVAR at basicblock instack\n"); assert(0); }
2143 if (src->varkind == STACKVAR )
2144 /* no Interfaces at BB Boundaries with LSRA! */
2145 /* -> change to TEMPVAR */
2146 src->varkind = TEMPVAR;
2147 /*******************************************************************************
2148 Check this - ? For every incoming Stack Slot a lifetime has to be created ?
2149 *******************************************************************************/
2150 _lsra_new_stack(ls, src, b_index, 0, LSRA_BB_IN);
2153 src = m->basicblocks[b_index].outstack;
2154 for (;src != NULL; src=src->prev) {
2155 if (src->varkind == ARGVAR )
2156 { log_text("ARGVAR at basicblock outstack\n"); assert(0); }
2157 else if (src->varkind == LOCALVAR )
2158 { log_text("LOCALVAR at basicblock outstack\n"); assert(0); }
2160 /* no Interfaces at BB Boundaries with LSRA! */
2161 /* -> change to TEMPVAR */
2162 if (src->varkind == STACKVAR )
2163 src->varkind = TEMPVAR;
2164 _lsra_from_stack(ls, src, b_index, iindex, LSRA_BB_OUT);
2168 /* set iptr to last instruction of BB */
2169 iptr = m->basicblocks[b_index].iinstr + iindex;
2171 for (;iindex >= 0; iindex--, iptr--) {
2172 /* get source and destination Stack for the current instruction */
2173 /* destination stack is available as iptr->dst */
2175 /* source stack is either the destination stack of the previos */
2176 /* instruction, or the basicblock instack for the first instruction */
2177 if (iindex) /* != 0 is > 0 here, since iindex ist always >= 0 */
2180 src=m->basicblocks[b_index].instack;
2182 #if defined(LSRA_USES_REG_RES)
2183 /* remember last Stack Slot v_index, so not all lifetimes have to */
2184 /* be checked for reserved register allocation */
2185 v_index_min_before_instruction = ls->v_index;
2189 /* printf("bb: %3i bcount: %3i iindex: %3i ilen: %3i opcode: %3i %s\n",b_index,m->basicblockcount,iindex,len,opcode,icmd_names[opcode]); */
2190 /* lsra_dump_stack(src); */
2191 /* lsra_dump_stack(dst); */
2198 /* local read (return adress) */
2199 lsra_usage_local(ls, iptr->op1, TYPE_ADR, b_index, iindex,
2203 case ICMD_ELSE_ICONST:
2204 case ICMD_CHECKNULL:
2208 case ICMD_PUTSTATICCONST:
2209 case ICMD_INLINE_START:
2210 case ICMD_INLINE_END:
2214 /* local = local+<const> */
2215 lsra_usage_local(ls, iptr->op1, TYPE_INT, b_index, iindex,
2217 lsra_usage_local(ls, iptr->op1, TYPE_INT, b_index, iindex,
2221 /* pop 0 push 1 const: const->stack */
2227 /* new stack slot */
2228 lsra_new_stack(ls, dst, b_index, iindex);
2231 /* pop 0 push 1 load: local->stack */
2237 if (dst->varkind != LOCALVAR) {
2238 /* local->value on stack */
2239 lsra_usage_local(ls, iptr->op1, opcode - ICMD_ILOAD, b_index,
2241 lsra_new_stack(ls, dst, b_index, iindex); /* value->stack */
2242 } else /* if (dst->varnum != iptr->op1) */ {
2243 /* local -> local */
2244 lsra_usage_local(ls, iptr->op1, opcode - ICMD_ILOAD, b_index,
2245 iindex,LSRA_LOAD); /* local->value */
2246 lsra_usage_local(ls, dst->varnum, opcode - ICMD_ILOAD, b_index,
2247 iindex, LSRA_STORE); /* local->value */
2253 /* Stack(arrayref,index)->stack */
2264 lsra_from_stack(ls, src, b_index, iindex);
2265 /* stack->arrayref */
2266 lsra_from_stack(ls, src->prev, b_index, iindex);
2267 /* arrayref[index]->stack */
2268 lsra_new_stack(ls, dst, b_index, iindex);
2272 /* stack(arrayref,index,value)->arrayref[index]=value */
2283 lsra_from_stack(ls, src,b_index, iindex); /* stack -> value */
2284 lsra_from_stack(ls, src->prev, b_index, iindex); /* stack -> index*/
2285 /* stack -> arrayref */
2286 lsra_from_stack(ls, src->prev->prev, b_index, iindex);
2289 /* pop 1 push 0 store: stack -> local */
2295 if (src->varkind != LOCALVAR) {
2296 lsra_from_stack(ls, src, b_index, iindex); /* stack -> value */
2297 lsra_usage_local(ls, iptr->op1, opcode-ICMD_ISTORE, b_index,
2298 iindex, LSRA_STORE); /* local->value */
2299 } else /* if (src->varnum != iptr->op1) */ {
2300 lsra_usage_local(ls, iptr->op1, opcode-ICMD_ISTORE, b_index,
2301 iindex, LSRA_STORE); /* local->value */
2302 lsra_usage_local(ls, src->varnum, opcode-ICMD_ISTORE, b_index,
2303 iindex, LSRA_LOAD); /* local->value */
2308 case ICMD_POP: /* throw away a stackslot */
2309 /* TODO: check if used anyway (DUP...) and change codegen to */
2310 /* ignore this stackslot */
2311 lsra_pop_from_stack(ls, src, b_index, iindex);
2319 case ICMD_ARETURN: /* stack(value) -> [empty] */
2321 case ICMD_ATHROW: /* stack(objref) -> undefined */
2323 case ICMD_PUTSTATIC: /* stack(value) -> static_field */
2324 case ICMD_PUTFIELDCONST:
2326 /* pop 1 push 0 branch */
2327 case ICMD_IFNULL: /* stack(value) -> branch? */
2328 case ICMD_IFNONNULL:
2344 /* pop 1 push 0 table branch */
2345 case ICMD_TABLESWITCH:
2346 case ICMD_LOOKUPSWITCH:
2348 case ICMD_MONITORENTER:
2349 case ICMD_MONITOREXIT:
2350 lsra_from_stack(ls, src, b_index, iindex); /* stack -> value */
2354 case ICMD_POP2: /* throw away 2 stackslots */
2355 /* TODO: check if used anyway (DUP...) and change codegen to */
2356 /* ignore this stackslot */
2357 lsra_pop_from_stack(ls, src, b_index, iindex);
2358 lsra_pop_from_stack(ls, src->prev, b_index, iindex);
2361 /* pop 2 push 0 branch */
2363 case ICMD_IF_ICMPEQ: /* stack (v1,v2) -> branch(v1,v2) */
2364 case ICMD_IF_ICMPNE:
2365 case ICMD_IF_ICMPLT:
2366 case ICMD_IF_ICMPGE:
2367 case ICMD_IF_ICMPGT:
2368 case ICMD_IF_ICMPLE:
2370 case ICMD_IF_LCMPEQ:
2371 case ICMD_IF_LCMPNE:
2372 case ICMD_IF_LCMPLT:
2373 case ICMD_IF_LCMPGE:
2374 case ICMD_IF_LCMPGT:
2375 case ICMD_IF_LCMPLE:
2377 case ICMD_IF_ACMPEQ:
2378 case ICMD_IF_ACMPNE:
2381 case ICMD_PUTFIELD: /* stack(objref,value) -> objref = value */
2383 case ICMD_IASTORECONST:
2384 case ICMD_LASTORECONST:
2385 case ICMD_AASTORECONST:
2386 case ICMD_BASTORECONST:
2387 case ICMD_CASTORECONST:
2388 case ICMD_SASTORECONST:
2389 lsra_from_stack(ls, src, b_index, iindex); /* stack -> value*/
2390 lsra_from_stack(ls, src->prev, b_index, iindex);
2393 /* pop 0 push 1 dup */
2394 case ICMD_DUP: /* src == dst->prev, src -> dst */
2395 /* lsra_from_stack(ls, src,b_index,iindex);*/
2396 lsra_new_stack(ls, dst, b_index, iindex);
2398 #ifdef JOIN_DUP_STACK
2399 /* src is identical to dst->prev */
2400 lsra_join_2_stack(ls, src, dst, JOIN_DUP);
2404 /* pop 0 push 2 dup */
2406 /* lsra_from_stack(ls, src,b_index, iindex); */
2407 /* lsra_from_stack(ls, src->prev, b_index, iindex); */
2408 lsra_new_stack(ls, dst->prev, b_index, iindex);
2409 lsra_new_stack(ls, dst, b_index, iindex);
2411 #ifdef JOIN_DUP_STACK
2412 lsra_join_2_stack(ls, src, dst, JOIN_DUP);
2413 lsra_join_2_stack(ls, src->prev, dst->prev, JOIN_DUP);
2414 /* src is identical to dst->prev->prev */
2415 /* src->prev is identical to dst->prev->prev->prev */
2419 /* pop 2 push 3 dup */
2421 lsra_from_stack(ls, src, b_index, iindex);
2422 lsra_from_stack(ls, src->prev, b_index, iindex);
2423 lsra_new_stack(ls, dst->prev->prev, b_index, iindex);
2424 lsra_new_stack(ls, dst->prev, b_index, iindex);
2425 lsra_new_stack(ls, dst, b_index, iindex);
2426 #ifdef JOIN_DUP_STACK
2427 lsra_join_dup(ls, src, dst, dst->prev->prev);
2428 lsra_join_2_stack(ls, src->prev, dst->prev, JOIN);
2432 /* pop 3 push 4 dup */
2434 lsra_from_stack(ls, src,b_index, iindex);
2435 lsra_from_stack(ls, src->prev, b_index, iindex);
2436 lsra_from_stack(ls, src->prev->prev, b_index, iindex);
2437 lsra_new_stack(ls, dst->prev->prev->prev, b_index, iindex);
2438 lsra_new_stack(ls, dst->prev->prev, b_index, iindex);
2439 lsra_new_stack(ls, dst->prev, b_index, iindex);
2440 lsra_new_stack(ls, dst, b_index, iindex);
2442 #ifdef JOIN_DUP_STACK
2443 lsra_join_dup(ls, src, dst, dst->prev->prev->prev);
2444 lsra_join_2_stack(ls, src->prev, dst->prev, JOIN);
2445 lsra_join_2_stack(ls, src->prev->prev, dst->prev->prev, JOIN);
2449 /* pop 3 push 5 dup */
2451 lsra_from_stack(ls, src, b_index, iindex);
2452 lsra_from_stack(ls, src->prev, b_index, iindex);
2453 lsra_from_stack(ls, src->prev->prev, b_index, iindex);
2454 lsra_new_stack(ls, dst->prev->prev->prev->prev, b_index, iindex);
2455 lsra_new_stack(ls, dst->prev->prev->prev, b_index, iindex);
2456 lsra_new_stack(ls, dst->prev->prev, b_index, iindex);
2457 lsra_new_stack(ls, dst->prev, b_index, iindex);
2458 lsra_new_stack(ls, dst, b_index, iindex);
2460 #ifdef JOIN_DUP_STACK
2461 lsra_join_dup(ls, src, dst, dst->prev->prev->prev);
2462 lsra_join_dup(ls, src->prev, dst->prev,
2463 dst->prev->prev->prev->prev);
2464 lsra_join_2_stack(ls, src->prev->prev, dst->prev->prev, JOIN);
2468 /* pop 4 push 6 dup */
2470 lsra_from_stack(ls, src, b_index, iindex);
2471 lsra_from_stack(ls, src->prev, b_index, iindex);
2472 lsra_from_stack(ls, src->prev->prev, b_index, iindex);
2473 lsra_from_stack(ls, src->prev->prev->prev, b_index, iindex);
2474 lsra_new_stack(ls, dst->prev->prev->prev->prev->prev, b_index,
2476 lsra_new_stack(ls, dst->prev->prev->prev->prev, b_index, iindex);
2477 lsra_new_stack(ls, dst->prev->prev->prev, b_index, iindex);
2478 lsra_new_stack(ls, dst->prev->prev, b_index, iindex);
2479 lsra_new_stack(ls, dst->prev, b_index, iindex);
2480 lsra_new_stack(ls, dst, b_index, iindex);
2482 #ifdef JOIN_DUP_STACK
2483 lsra_join_dup(ls, src, dst, dst->prev->prev->prev->prev);
2484 lsra_join_dup(ls, src->prev, dst->prev,
2485 dst->prev->prev->prev->prev->prev);
2486 lsra_join_2_stack(ls, src->prev->prev, dst->prev->prev, JOIN);
2487 lsra_join_2_stack(ls, src->prev->prev->prev, dst->prev->prev->prev,
2492 /* pop 2 push 2 swap */
2494 lsra_from_stack(ls, src, b_index, iindex);
2495 lsra_from_stack(ls, src->prev, b_index, iindex);
2496 lsra_new_stack(ls, dst->prev, b_index, iindex);
2497 lsra_new_stack(ls, dst, b_index, iindex);
2499 lsra_join_2_stack(ls, src->prev, dst, JOIN);
2500 lsra_join_2_stack(ls, src, dst->prev, JOIN);
2538 lsra_from_stack(ls, src, b_index, iindex);
2539 lsra_from_stack(ls, src->prev, b_index, iindex);
2540 lsra_new_stack(ls, dst, b_index, iindex);
2541 #ifdef JOIN_DEST_STACK
2542 lsra_join_3_stack(ls, dst, src->prev, src, JOIN_OP);
2547 lsra_from_stack(ls, src, b_index, iindex);
2548 lsra_from_stack(ls, src->prev,b_index,iindex);
2549 lsra_new_stack(ls, dst, b_index, iindex);
2550 #ifdef JOIN_DEST_STACK
2551 lsra_join_2_stack(ls, src, dst, JOIN_OP);
2569 lsra_from_stack(ls, src, b_index, iindex);
2570 lsra_from_stack(ls, src->prev, b_index, iindex);
2571 lsra_new_stack(ls, dst, b_index, iindex);
2575 case ICMD_LADDCONST:
2576 case ICMD_LSUBCONST:
2577 case ICMD_LMULCONST:
2581 case ICMD_LANDCONST:
2583 case ICMD_LXORCONST:
2584 case ICMD_LSHLCONST:
2585 case ICMD_LSHRCONST:
2586 case ICMD_LUSHRCONST:
2588 case ICMD_IADDCONST:
2589 case ICMD_ISUBCONST:
2590 case ICMD_IMULCONST:
2594 case ICMD_IANDCONST:
2596 case ICMD_IXORCONST:
2597 case ICMD_ISHLCONST:
2598 case ICMD_ISHRCONST:
2599 case ICMD_IUSHRCONST:
2601 case ICMD_IFEQ_ICONST:
2602 case ICMD_IFNE_ICONST:
2603 case ICMD_IFLT_ICONST:
2604 case ICMD_IFGE_ICONST:
2605 case ICMD_IFGT_ICONST:
2606 case ICMD_IFLE_ICONST:
2611 case ICMD_INT2SHORT:
2629 case ICMD_CHECKCAST:
2630 lsra_from_stack(ls, src, b_index, iindex);
2631 lsra_new_stack(ls, dst, b_index, iindex);
2632 #ifdef JOIN_DEST_STACK
2633 lsra_join_2_stack(ls, src, dst, JOIN_OP);
2637 /* TODO: check if for these ICMDs JOIN_DEST_STACK works, too! */
2638 case ICMD_ARRAYLENGTH:
2639 case ICMD_INSTANCEOF:
2642 case ICMD_ANEWARRAY:
2645 lsra_from_stack(ls, src, b_index, iindex);
2646 lsra_new_stack(ls, dst, b_index, iindex);
2650 case ICMD_GETSTATIC:
2653 lsra_new_stack(ls, dst, b_index, iindex);
2656 /* pop many push any */
2658 case ICMD_INVOKESTATIC:
2659 case ICMD_INVOKESPECIAL:
2660 case ICMD_INVOKEVIRTUAL:
2661 case ICMD_INVOKEINTERFACE:
2665 md = lm->parseddesc;
2667 unresolved_method *um = iptr->target;
2668 md = um->methodref->parseddesc.md;
2672 lsra_from_stack(ls, src, b_index, iindex);
2675 if (md->returntype.type != TYPE_VOID)
2676 lsra_new_stack(ls, dst, b_index, iindex);
2685 lsra_from_stack(ls, src, b_index, iindex);
2688 if (md->returntype.type != TYPE_VOID)
2689 lsra_new_stack(ls, dst, b_index, iindex);
2692 case ICMD_MULTIANEWARRAY:
2695 lsra_from_stack(ls, src, b_index, iindex);
2698 lsra_new_stack(ls, dst, b_index, iindex);
2703 new_internalerror("Unknown ICMD %d during register allocation",
2708 #if defined(LSRA_USES_REG_RES)
2710 int /* length, */ maxlength, j;
2711 int index, reg_res,start_iindex, end_iindex;
2712 struct stackslot * ss;
2718 if ((reg_res = icmd_uses_reg_res[opcode][REG_RES_CNT])==REG_NULL)
2719 /* no preferred "output" register for this ICMD -> start with */
2722 for (j=0; j < REG_RES_CNT; j++, reg_res=(reg_res+1)%REG_RES_CNT) {
2725 if ((iindex == 0) || (icmd_uses_reg_res[opcode][reg_res])) {
2726 /* least iindex looked at, or reg_res does not */
2727 /* "fully" survivy this ICMD */
2728 if (ls->reg_res_free[reg_res] != -1) {
2729 /* reg_res is free from ls->reg_res_free[] til here */
2730 /* (iindex). Now search for the longest lifetime, */
2731 /* which fits in this intervall and if found assign */
2733 if (icmd_uses_reg_res[opcode][reg_res] & D)
2734 /* ICMD destroys REG_RES as destination operand */
2735 start_iindex = iindex +1;
2737 start_iindex = iindex;
2738 for (i = (-v_index_min[reg_res] - 1);
2739 i < (-ls->v_index -1); i++) {
2740 n = &(ls->lifetime[i]);
2741 if (!(n->flags & (JOINING || JOIN_BB))) {
2742 /* do not assign reserved Regs to lifetimes */
2743 /* not completely seen till now */
2744 if ((n->type == TYPE_INT)
2745 || (n->type == TYPE_ADR)) {
2746 if (n->savedvar == 0) {
2747 if ((n->bb_last_use == n->bb_first_def)
2749 == ls->sorted_rev[b_index])) {
2751 <= ls->reg_res_free[reg_res])
2752 && (n->i_first_def >=
2755 /* length = n->i_last_use - */
2756 /* n->i_first_def; */
2757 /* if (length > maxlength) { */
2758 /* maxlength = length; */
2762 /* there is a lifetime, which a reserved register can */
2763 /* be assigned to */
2765 ls->lifetime[i].reg = lsra_reg_res[reg_res];
2766 for (ss = ls->lifetime[i].local_ss; ss != NULL;
2768 ss->s->regoff = lsra_reg_res[reg_res];
2770 /* drop lifetime, no further processing required */
2771 ls->lifetime[i].type = -1;
2773 ls->reg_res_free[reg_res] = n->i_first_def;
2780 /* if (length > 1) */
2781 /* printf("%i reg res Lifetimes assigned for this intervall \n",length); */
2783 if (icmd_uses_reg_res[opcode][reg_res] & S)
2784 /* ICMD destroys REG_RES as source operand */
2785 ls->reg_res_free[reg_res] = -1;
2787 ls->reg_res_free[reg_res] = iindex;
2789 v_index_min[reg_res] = v_index_min_before_instruction;
2791 if (ls->reg_res_free[reg_res] == -1)
2792 ls->reg_res_free[reg_res] = iindex;
2795 #endif /* defined(LSRA_USES_REG_RES) */
2801 i = 14; /* maxstack */
2813 printf(" %3i (%p)", t->varnum);
2816 printf(" %3i %s\n", iindex, icmd_names[opcode]);
2826 int lsra_test_lt(registerdata *rd, struct lifetime *n, int store, int *values, bool inmemory) {
2830 value_index = n->reg;
2832 if (IS_FLT_DBL_TYPE(n->type)) {
2833 value_index = rd->memuse + INT_REG_CNT + n->reg;
2835 value_index = rd->memuse + n->reg;
2839 if ((store == LSRA_LOAD) || (store == LSRA_POP)) {
2840 if (values[value_index] == VS) {
2842 /* this happens through not really returning right from subroutines while the test */
2843 /* so this (in this case) useless warning is inhibited till this case is handled */
2845 if (n->i_start != -1) { /* not a parameter */
2846 printf("lsra_test: Warning: v_index %3i type %3i reg %3i", n->v_index, n->type, n->reg);
2849 printf(" not initialized\n");
2852 } else if (values[value_index] != n->v_index) {
2853 printf("lsra_test: Error: v_index %3i type %3i reg %3i", n->v_index, n->type, n->reg);
2856 printf("Conflict: %3i \n", values[value_index]);
2860 } else { /* LSRA_STORE */
2861 values[value_index] = n->v_index;
2866 int lsra_test_local( lsradata *ls, registerdata *rd, int v_index, int type, int store, int *values) {
2869 n = &(ls->lifetime[ ls->maxlifetimes + v_index * (TYPE_ADR+1) + type]);
2871 { log_text("lsra_test: Local Var Lifetime not initialized!\n"); assert(0); }
2873 return lsra_test_lt(rd, n, store, values, rd->locals[v_index][type].flags & INMEMORY);
2876 #define lsra_test_new_stack( ls, rd, s, values) lsra_test_stack(ls, rd, s, values, LSRA_STORE)
2877 #define lsra_test_from_stack( ls, rd, s, values) lsra_test_stack(ls, rd, s, values,LSRA_LOAD)
2878 #define lsra_test_pop_from_stack( ls, rd, s, values) lsra_test_stack(ls, rd, s, values, LSRA_LOAD)
2879 int lsra_test_stack( lsradata *ls, registerdata *rd, stackptr s, int *values, int store)
2884 if (s->varkind == LOCALVAR) {
2885 return lsra_test_local(ls, rd, s->varnum, s->type, store, values);
2887 if (s->varkind != ARGVAR) {
2889 { log_text("lsra_test: Stackslot not initialized!\n"); assert(0); }
2890 n = &(ls->lifetime[-s->varnum - 1]);
2892 { log_text("lsra_test: Stackslot Lifetime not initialized!\n"); assert(0); }
2894 return lsra_test_lt(rd, n, store, values, s->flags & INMEMORY);
2899 int _test_lifetimes(methodinfo *m, lsradata *ls, registerdata *rd, int b_index, int *values, int rec_depth)
2901 struct stackslot *ss;
2917 if (rec_depth > 1000) {
2918 printf("%s.%s rec_depth > 1000\n", m->class->name->text, m->name->text);
2923 end_of_method = false;
2924 iptr = m->basicblocks[b_index].iinstr;
2926 dst = m->basicblocks[b_index].instack;
2928 if (m->basicblocks[b_index].type != BBTYPE_STD) {
2929 /* init incoming stackslot (exception or return address) */
2930 ret = lsra_test_new_stack(ls, rd , dst , values);
2934 for (iindex =0 ;(iindex < m->basicblocks[b_index].icount) && (ret == -1) ; iindex++, iptr++) {
2943 ret = lsra_test_local(ls, rd, iptr->op1, TYPE_ADR, LSRA_LOAD, values); /* local read (return adress) */
2946 case ICMD_ELSE_ICONST:
2947 case ICMD_CHECKNULL:
2948 case ICMD_CHECKASIZE:
2949 case ICMD_CHECKEXCEPTION:
2952 case ICMD_PUTSTATICCONST:
2953 case ICMD_INLINE_START:
2954 case ICMD_INLINE_END:
2958 end_of_method = true;
2962 ret = lsra_test_local(ls, rd,iptr->op1,TYPE_INT, LSRA_LOAD, values); /* local */
2963 ret = lsra_test_local(ls, rd,iptr->op1,TYPE_INT, LSRA_STORE, values); /* local = local+<const> */
2966 /* pop 0 push 1 const */
2974 /* new stack slot */
2975 ret = lsra_test_new_stack(ls, rd,dst, values); /* const->stack */
2978 /* pop 0 push 1 load */
2986 if (dst->varkind != LOCALVAR) {
2987 ret = lsra_test_local(ls, rd,iptr->op1,opcode-ICMD_ILOAD, LSRA_LOAD, values); /* local->value */
2988 ret = lsra_test_new_stack(ls, rd,dst, values); /* value->stack */
2989 } else if (dst->varnum != iptr->op1) {
2990 ret = lsra_test_local(ls, rd,iptr->op1,opcode-ICMD_ILOAD, LSRA_LOAD, values); /* local->value */
2991 ret = lsra_test_local(ls, rd,dst->varnum,opcode-ICMD_ILOAD, LSRA_STORE, values); /* local->value */
2997 /* Stack(arrayref,index)->stack */
3008 ret = lsra_test_from_stack(ls, rd, src, values); /* stack->index */
3009 ret = lsra_test_from_stack(ls, rd, src->prev, values); /* stack->arrayref */
3010 ret = lsra_test_new_stack(ls, rd, dst, values); /* arrayref[index]->stack */
3014 /* stack(arrayref,index,value)->arrayref[index]=value */
3026 ret = lsra_test_from_stack(ls, rd, src, values); /* stack -> value */
3027 ret = lsra_test_from_stack(ls, rd, src->prev, values); /* stack -> index */
3028 ret = lsra_test_from_stack(ls, rd, src->prev->prev, values); /* stack -> arrayref */
3031 case ICMD_POP: /* throw away a stackslot -> check if used anyway! */
3032 ret = lsra_test_pop_from_stack(ls, rd,src, values);
3035 /* pop 1 push 0 store */
3036 /* stack -> local */
3043 if (src->varkind != LOCALVAR) {
3044 ret = lsra_test_from_stack(ls, rd, src, values); /* stack -> value */
3045 ret = lsra_test_local(ls, rd,iptr->op1,opcode-ICMD_ISTORE, LSRA_STORE, values); /* local->value */
3046 } else if (src->varnum != iptr->op1) {
3047 ret = lsra_test_local(ls, rd,iptr->op1,opcode-ICMD_ISTORE, LSRA_STORE, values); /* local->value */
3048 ret = lsra_test_local(ls, rd,src->varnum,opcode-ICMD_ISTORE, LSRA_LOAD, values); /* local->value */
3058 case ICMD_ARETURN: /* stack(value) -> [empty] */
3059 case ICMD_ATHROW: /* stack(objref) -> undefined */
3060 end_of_method = true;
3061 ret = lsra_test_from_stack(ls, rd, src, values); /* stack -> value */
3063 case ICMD_PUTSTATIC: /* stack(value) -> static_field */
3064 case ICMD_PUTFIELDCONST:
3065 /* pop 1 push 0 branch */
3066 case ICMD_MONITORENTER:
3067 case ICMD_MONITOREXIT:
3068 ret = lsra_test_from_stack(ls, rd, src, values); /* stack -> value */
3071 case ICMD_IFNULL: /* stack(value) -> branch? */
3072 case ICMD_IFNONNULL:
3085 ret = lsra_test_from_stack(ls, rd, src, values); /* stack -> value */
3088 /* pop 1 push 0 table branch */
3090 case ICMD_TABLESWITCH:
3091 ret = lsra_test_from_stack(ls, rd, src, values); /* stack -> value */
3093 case ICMD_LOOKUPSWITCH:
3094 ret = lsra_test_from_stack(ls, rd, src, values); /* stack -> value */
3099 case ICMD_POP2: /* throw away 2 stackslots -> check if used anyway! */
3100 ret = lsra_test_pop_from_stack(ls, rd,src, values);
3101 ret = lsra_test_pop_from_stack(ls, rd,src->prev, values);
3104 /* pop 2 push 0 branch */
3106 case ICMD_IF_ICMPEQ: /* stack (v1,v2) -> branch(v1,v2) */
3107 case ICMD_IF_ICMPNE:
3108 case ICMD_IF_ICMPLT:
3109 case ICMD_IF_ICMPGE:
3110 case ICMD_IF_ICMPGT:
3111 case ICMD_IF_ICMPLE:
3113 case ICMD_IF_LCMPEQ:
3114 case ICMD_IF_LCMPNE:
3115 case ICMD_IF_LCMPLT:
3116 case ICMD_IF_LCMPGE:
3117 case ICMD_IF_LCMPGT:
3118 case ICMD_IF_LCMPLE:
3120 case ICMD_IF_ACMPEQ:
3121 case ICMD_IF_ACMPNE:
3122 ret = lsra_test_from_stack(ls, rd, src, values); /* stack -> value*/
3123 ret = lsra_test_from_stack(ls, rd, src->prev, values); /* stack -> objref*/
3128 case ICMD_PUTFIELD: /* stack(objref,value) -> objref->method=value */
3130 case ICMD_IASTORECONST:
3131 case ICMD_LASTORECONST:
3132 case ICMD_AASTORECONST:
3133 case ICMD_BASTORECONST:
3134 case ICMD_CASTORECONST:
3135 case ICMD_SASTORECONST:
3136 ret = lsra_test_from_stack(ls, rd, src, values); /* stack -> value*/
3137 ret = lsra_test_from_stack(ls, rd, src->prev, values); /* stack -> objref*/
3140 /* pop 0 push 1 dup */
3141 /* merge dupped vars??? */
3142 case ICMD_DUP: /* src == dst->prev, src -> dst */
3143 /* ret = lsra_test_from_stack(ls, rd, src,b_index,iindex);*/ /* just inc usage count? */
3144 ret = lsra_test_new_stack(ls, rd,dst, values);
3147 /* pop 0 push 2 dup */
3150 /* ret = lsra_test_from_stack(ls, rd, src,b_index,iindex); */ /* just inc usage count? */
3151 /* ret = lsra_test_from_stack(ls, rd, src->prev,b_index,iindex); */ /* just inc usage count? */
3152 ret = lsra_test_new_stack(ls, rd,dst->prev, values);
3153 ret = lsra_test_new_stack(ls, rd,dst, values);
3156 /* pop 2 push 3 dup */
3159 ret = lsra_test_from_stack(ls, rd, src, values);
3160 ret = lsra_test_from_stack(ls, rd, src->prev, values);
3161 ret = lsra_test_new_stack(ls, rd,dst->prev->prev, values);
3162 ret = lsra_test_new_stack(ls, rd,dst->prev, values);
3163 ret = lsra_test_new_stack(ls, rd,dst, values);
3166 /* pop 3 push 4 dup */
3169 ret = lsra_test_from_stack(ls, rd, src, values);
3170 ret = lsra_test_from_stack(ls, rd, src->prev, values);
3171 ret = lsra_test_from_stack(ls, rd, src->prev->prev, values);
3172 ret = lsra_test_new_stack(ls, rd,dst->prev->prev->prev, values);
3173 ret = lsra_test_new_stack(ls, rd,dst->prev->prev, values);
3174 ret = lsra_test_new_stack(ls, rd,dst->prev, values);
3175 ret = lsra_test_new_stack(ls, rd,dst, values);
3178 /* pop 3 push 5 dup */
3181 ret = lsra_test_from_stack(ls, rd, src, values);
3182 ret = lsra_test_from_stack(ls, rd, src->prev, values);
3183 ret = lsra_test_from_stack(ls, rd, src->prev->prev, values);
3184 ret = lsra_test_new_stack(ls, rd,dst->prev->prev->prev->prev, values);
3185 ret = lsra_test_new_stack(ls, rd,dst->prev->prev->prev, values);
3186 ret = lsra_test_new_stack(ls, rd,dst->prev->prev, values);
3187 ret = lsra_test_new_stack(ls, rd,dst->prev, values);
3188 ret = lsra_test_new_stack(ls, rd,dst, values);
3191 /* pop 4 push 6 dup */
3194 ret = lsra_test_from_stack(ls, rd, src, values);
3195 ret = lsra_test_from_stack(ls, rd, src->prev, values);
3196 ret = lsra_test_from_stack(ls, rd, src->prev->prev, values);
3197 ret = lsra_test_from_stack(ls, rd, src->prev->prev->prev, values);
3198 ret = lsra_test_new_stack(ls, rd,dst->prev->prev->prev->prev->prev, values);
3199 ret = lsra_test_new_stack(ls, rd,dst->prev->prev->prev->prev, values);
3200 ret = lsra_test_new_stack(ls, rd,dst->prev->prev->prev, values);
3201 ret = lsra_test_new_stack(ls, rd,dst->prev->prev, values);
3202 ret = lsra_test_new_stack(ls, rd,dst->prev, values);
3203 ret = lsra_test_new_stack(ls, rd,dst, values);
3207 /* pop 2 push 2 swap */
3210 ret = lsra_test_from_stack(ls, rd, src, values);
3211 ret = lsra_test_from_stack(ls, rd, src->prev, values);
3212 ret = lsra_test_new_stack(ls, rd,dst->prev, values);
3213 ret = lsra_test_new_stack(ls, rd,dst, values);
3263 ret = lsra_test_from_stack(ls, rd, src, values);
3264 ret = lsra_test_from_stack(ls, rd, src->prev, values);
3265 ret = lsra_test_new_stack(ls, rd,dst, values);
3269 case ICMD_IADDCONST:
3270 case ICMD_ISUBCONST:
3271 case ICMD_IMULCONST:
3275 case ICMD_IANDCONST:
3277 case ICMD_IXORCONST:
3278 case ICMD_ISHLCONST:
3279 case ICMD_ISHRCONST:
3280 case ICMD_IUSHRCONST:
3282 case ICMD_LADDCONST:
3283 case ICMD_LSUBCONST:
3284 case ICMD_LMULCONST:
3288 case ICMD_LANDCONST:
3290 case ICMD_LXORCONST:
3291 case ICMD_LSHLCONST:
3292 case ICMD_LSHRCONST:
3293 case ICMD_LUSHRCONST:
3295 case ICMD_IFEQ_ICONST:
3296 case ICMD_IFNE_ICONST:
3297 case ICMD_IFLT_ICONST:
3298 case ICMD_IFGE_ICONST:
3299 case ICMD_IFGT_ICONST:
3300 case ICMD_IFLE_ICONST:
3305 case ICMD_INT2SHORT:
3323 case ICMD_CHECKCAST:
3324 case ICMD_ARRAYCHECKCAST:
3326 case ICMD_ARRAYLENGTH:
3327 case ICMD_INSTANCEOF:
3330 case ICMD_ANEWARRAY:
3333 ret = lsra_test_from_stack(ls, rd, src, values);
3334 ret = lsra_test_new_stack(ls, rd,dst, values);
3339 case ICMD_GETSTATIC:
3341 ret = lsra_test_new_stack(ls, rd,dst, values);
3344 /* pop many push any */
3345 case ICMD_INVOKEVIRTUAL:
3346 case ICMD_INVOKESPECIAL:
3347 case ICMD_INVOKESTATIC:
3348 case ICMD_INVOKEINTERFACE:
3349 #error XXX FIXME TWISTI: use md->paramcount (2005/10/4)
3352 ret = lsra_test_from_stack(ls, rd, src, values);
3355 if (((unresolved_method *) iptr->target)->methodref->parseddesc.md->returntype.type != TYPE_VOID)
3356 ret = lsra_test_new_stack(ls, rd,dst, values);
3362 ret = lsra_test_from_stack(ls, rd, src, values);
3365 if (((builtintable_entry *) iptr->val.a)->md->returntype.type != TYPE_VOID)
3366 ret = lsra_test_new_stack(ls, rd,dst, values);
3369 case ICMD_MULTIANEWARRAY:
3372 ret = lsra_test_from_stack(ls, rd, src, values);
3375 ret = lsra_test_new_stack(ls, rd, dst, values);
3379 printf("ICMD %d at %d\n", iptr->opc, (int)(iptr - m->instructions));
3380 { log_text("Missing ICMD code during register allocation"); assert(0); }
3385 printf("BB: %i IIndex %i \n", b_index, iindex);
3390 for (succ = ls->succ[b_index]; succ != NULL; succ = succ->next)
3393 if (end_of_method) {
3394 /* XRETURN or ATHROW encountered */
3395 /* take a 50% chance to end testing */
3396 /* otherwise follow successor (possible exception handler) */
3397 if (rand() % 2) i = 0;
3403 for (i=0, succ = ls->succ[b_index]; i!=j; i++, succ=succ->next);
3405 if ( (ret=_test_lifetimes(m, ls, rd, succ->value, values, rec_depth + 1)) != -1) {
3406 printf("[BB %3i IIndex %3i]",b_index, iindex);
3413 void test_lifetimes( methodinfo *m, lsradata *ls, registerdata *rd)
3415 int *values, i, j, p, t;
3417 methoddesc *md = m->parseddesc;
3419 v_max = rd->memuse + INT_REG_CNT + FLT_REG_CNT;
3421 if ( (values = MNEW(int, v_max)) == NULL )
3422 { log_text("test_lifetimes: out of memory\n"); assert(0); }
3425 for (j=0; (j < 100) && (ret == -1); j++ ) {
3426 for (i=0; i < v_max; i++) values[i]=VS;
3428 for (p = 0, i = 0; p < md->paramcount; p++) {
3429 t = md->paramtypes[p].type;
3431 if (rd->locals[i][t].type >= 0)
3432 lsra_test_local( ls, rd, i, t, LSRA_STORE, values);
3435 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
3439 if ((ret=_test_lifetimes(m, ls, rd, 0, values, 0)) != -1) {
3445 MFREE(values, int, v_max);
3450 * These are local overrides for various environment variables in Emacs.
3451 * Please do not remove this and leave it at the end of the file, where
3452 * Emacs will automagically detect them.
3453 * ---------------------------------------------------------------------
3456 * indent-tabs-mode: t
3460 * vim:noexpandtab:sw=4:ts=4: