1 /* 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 1735 2004-12-07 14:33:27Z twisti $
33 /* #define LSRA_DEBUG */
34 /* #define LSRA_SAVEDVAR */
35 /* #define LSRA_MEMORY */
36 /* #define LSRA_PRINTLIFETIMES */
43 #define LSRA_PRINTLIFETIMES
46 #include "mm/memory.h"
47 #include "vm/options.h"
48 #include "vm/jit/lsra.h"
49 #include "vm/jit/reg.h"
50 #include "vm/jit/loop/graph.h"
51 #include "vm/jit/loop/loop.h"
54 void lsra(methodinfo *m, codegendata *cd, registerdata *rd, loopdata *ld, t_inlining_globals *id)
60 char name[1256], name1[1256];
62 utf_sprint(name, m->class->name);
63 utf_sprint(name1, m->name);
65 utf_sprint(name1, m->descriptor);
69 printf("LSRA Start for %s\n", name);
71 if (strcmp(name,"java/lang/SysteminitProperties()V")==0) {
72 printf("-------------------\n");
77 lsra_init(m, cd, id, ls);
78 lsra_setup(m, cd, rd, ls, ld);
87 void lsra_init(methodinfo *m, codegendata *cd, t_inlining_globals *id, lsradata *ls)
91 /* Init LSRA Data Structures */
92 ls->back_edge_panic=false;
93 /* lifetimes für alle Basicblocks allokieren */
94 ls->ss_lifetimes=DMNEW(struct lifetime *, m->basicblockcount);
95 for (i=0; i<m->basicblockcount; i++) ls->ss_lifetimes[i]=NULL;
97 if (cd->maxlocals != id->cumlocals) panic("lsra: Welche locals nehmen?\n");
99 ls->locals_lifetimes=DMNEW(struct lifetime *, cd->maxlocals);
100 for (i=0; i < cd->maxlocals; i++) ls->locals_lifetimes[i]=NULL;
105 void lsra_setup(methodinfo *m, codegendata *cd, registerdata *rd, lsradata *ls, loopdata *ld)
112 struct lifetime *lt, *n;
114 struct stackslot *ss;
117 /* Setup LSRA Data structures */
118 if (opt_loops) panic("lsra with -oloop not possible!\n");
124 /* BBDELETED Blöcke aus loopdata->c_dTable rausschmeissen! */
125 /* Exceptionhandler in loopdata->c_dTable hinzufügen */
127 printf("LSRA lsra_clean_Graph\n");
129 lsra_clean_Graph(m, cd, ls, ld);
132 /* sicherheitshalber Konsistenz von m->basicblocks[..] mit basicblocks->next (Liste) überprüfen */
133 printf("LSRA bb prüfen\n");
135 bptr = m->basicblocks;
136 while (bptr != NULL) {
137 if (i > m->basicblockcount){
138 panic("linked bb list does not correspond with bb array(1)\n");
140 if (bptr != &(m->basicblocks[i])){
141 panic("linked bb list does not correspond with bb array(2)\n");
147 if (i<m->basicblockcount){
148 panic("linked bb list does not correspond with bb array(3)\n");
151 printf("LSRA lsra_dump_Graph\n");
152 lsra_dump_Graph(m, ld->c_dTable);
156 /* Parameter initialisieren = local Vars schreibzugriff bei 0,0*/
158 for (p = 0, i = 0; p < m->paramcount; p++) {
159 t = m->paramtypes[p];
161 if (rd->locals[i][t].type >= 0)
162 lsra_usage_local(ls, i, t, 0, 0, LSRA_STORE);
164 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
169 printf("LSRA lsra_scan_register_canditates\n");
171 lsra_scan_registers_canditates(m, ls);
172 lsra_join_lifetimes(m, cd, ls, ld);
176 /* ls->lifetimes contains only the joined stackslotlifetimes */
177 for (lt=ls->lifetimes; lt != NULL; lt=lt->next) {
180 lt->savedvar=SAVEDVAR;
182 for (ss=lt->local_ss; ss != NULL; ss=ss->next) {
183 ss->s->varnum=v_index;
184 ss->s->varkind=TEMPVAR; /* just another time */
188 /* add ss_lifetimes[i] to ls->lifetimes or local_lifetimes[lt->s->varnum] */
189 for (i=0; i < m->basicblockcount; i++) {
190 if (m->basicblocks[i].flags >= BBREACHED) {
191 for (; ls->ss_lifetimes[i] != NULL;) {
192 lt=ls->ss_lifetimes[i];
194 lt->savedvar=SAVEDVAR;
197 if (lt->local_ss == NULL) panic("lsra_setup: normal Stackslot Lifetimes local_ss == NULL\n");
200 for (ss=lt->local_ss; (ss!=NULL) && (!drop); ss=ss->next) {
201 if (lt->local_ss->next == NULL) { /* only one Stackslot in local_ss */
202 /* Special Treatment for "lonely" LOCAL and ARGVARs */
203 if (ss->s->varkind == LOCALVAR) {
204 /* join with LOCALVAR */
205 /* local Lifetime vom richtigen Type suchen */
206 for (n=ls->locals_lifetimes[lt->local_ss->s->varnum]; (n!=NULL) && (n->type!=lt->local_ss->s->type);n=n->next);
207 lsra_merge_i_lists(n, lt);
208 if (n->local_ss == NULL) /* "pure" Local without Stackslots */
209 n->local_ss = lt->local_ss;
211 lsra_merge_local_ss(n, lt);
215 if (lt->local_ss->s->varkind == ARGVAR) {
219 /* no special treatment (only one Stackslot Lifetimes)? */
220 ss->s->varnum=v_index;
221 ss->s->varkind=TEMPVAR; /* only TEMPVAR possible for now */
225 ls->ss_lifetimes[i]=lt->next;
227 /* link into ls->lifetimes */
228 ls->ss_lifetimes[i]=lt->next;
229 lt->next=ls->lifetimes;
231 lt->v_index=v_index--;
237 /* add local_lifetimes to lifetimes */
238 for (i=0; i < cd->maxlocals; i++) {
239 if (ls->locals_lifetimes[i] != NULL) {
240 for (lt=ls->locals_lifetimes[i]; lt->next != NULL; lt=lt->next);
241 lt->next=ls->lifetimes;
242 ls->lifetimes=ls->locals_lifetimes[i];
246 /* calc lifetime length */
248 printf("Lifetimes before calc_lifetime_length: \n");
249 print_lifetimes(rd, ls->lifetimes);
250 printf("LSRA lsra_calc_lifetime_lengthe\n");
252 lsra_calc_lifetime_length(m, ls, cd, ld);
255 int lsra_get_sbr_end(methodinfo *m, loopdata *ld, int bb, int *bb_visited)
258 struct depthElement *de;
262 ip = m->basicblocks[bb].iinstr + m->basicblocks[bb].icount -1;/* set ip to last instruction */
263 if (ip->opc == ICMD_RET)
265 /* This Block is not the end -> search all following Blocks */
267 for (de=ld->c_dTable[bb]; de != NULL; de=de->next) {
268 if (!bb_visited[de->value]) {
269 j=lsra_get_sbr_end(m, ld, de->value, bb_visited);
270 if (j!=-1) { /* No new return path found */
271 if ((bb_end != -1) && (j!=bb_end)) panic("SBR has more than one exit Blocks\n");
279 void lsra_clean_Graph( methodinfo *m, codegendata *cd, lsradata *ls, loopdata *ld)
282 struct depthElement *de, *n;
283 int *bb_succ, *bb_visited, *ptr, index;
285 struct depthElement **table;
287 struct LoopContainer *lc;
295 /* Exceptionhandler noch in c_dTable aufnehmen */
296 ex=cd->exceptiontable;
298 printf("ExTable(%i): ", cd->exceptiontablelength);
301 for (; ex != NULL; ex = ex->down) {
304 printf("%i ",ex->handler->debug_nr);
306 dF(m, ld, -1, ex->handler->debug_nr);
310 /* Setting up successors of deleted Basic Blocks, in case c_dTable has an edge */
311 /* to a deleted block, so it can be replaced with the next "normal" Block */
312 bb_succ= DMNEW(int, m->basicblockcount);
313 for (i=0; i < m->basicblockcount; i++) {
314 if (m->basicblocks[i].flags >= BBREACHED)
317 for(j=i; ((j < m->basicblockcount) && (m->basicblocks[j].flags < BBREACHED)); j++);
318 if (j < m->basicblockcount)
326 for(i=0; i < m->basicblockcount; i++) {
327 if (m->basicblocks[i].flags < BBREACHED) {
330 for (de=table[i]; de != NULL; de=de->next) {
331 if (de->value < i) back_edge=true;
332 if (bb_succ[de->value] != de->value)
333 de->value = bb_succ[de->value];
334 if (de->value == -1) panic("lsra_clean_Graph: Sprung ins nichts....");
340 if ( ld->c_allLoops == NULL ) {
341 /* Keine Loops in Datenstruktur aber backedge! */
342 /* sollte nach BasicBlock umsortieren (revererse Depth First sort) */
343 /* und überprüfen von jit/loop/loop.c nicht mehr nötig sein */
344 /* TODO bis dahin eine loop über die backedge eintragen */
345 /* anstatt back_edge_panic zu setzen und alle Lifetimes über die */
346 /* gesamt Methode auszudehnen */
347 /* ls->back_edge_panic = true; */
349 /* create loops from all back edges */
351 for(i=0; i < m->basicblockcount; i++) {
352 if (m->basicblocks[i].flags >= BBREACHED) {
353 for (de=table[i]; de != NULL; de=de->next) {
355 if (ld->c_allLoops == NULL) {
356 ld->c_allLoops = lc = DNEW(struct LoopContainer);
358 lc->next=DNEW(struct LoopContainer);
361 lc->nodes=DNEW(struct LoopElement);
362 lc->nodes->next=DNEW(struct LoopElement);
363 lc->nodes->next->next=NULL;
365 lc->nodes->block=&(m->basicblocks[i]);
366 lc->nodes->next->block=&(m->basicblocks[de->value]);
373 printf("-------------Warnung Back Edge + no LOOP..\n");
378 bb_visited=DMNEW(int, m->basicblockcount);
379 for (i=0; i<m->basicblockcount; i++) {
383 /* Add all return possibilities to subroutine returns! */
384 /* --- subroutines will be inlined ---- -> then cancel this part */
386 printf("LSRA Subroutine patching\n");
388 for (i=0; i < m->basicblockcount; i++ ) {
389 /* Search all Subroutine Headers */
390 if (m->basicblocks[i].type == BBTYPE_SBR) {
392 printf("Subroutine at BB %3i num pred: %3i Pred: ",i, ld->c_numPre[i]);
393 for (ptr=ld->c_pre[i], index=0; index < ld->c_numPre[i]; ++index, ++ptr)
394 printf("%3i ", *ptr);
397 if (ld->c_numPre[i] > 1) { /* only if more than one call */
399 printf("Searching End of Subroutine: ");
401 j=lsra_get_sbr_end(m, ld, i, bb_visited); /* get Ending Block of Subroutine */
405 /* ensure, that all Predecessors+1 of the Subroutine Header are in the list */
406 /* in the List is only one Predecessor */
408 if (ld->c_dTable[j] == NULL) panic("No SBR Return in c_dTable\n");
409 if (ld->c_dTable[j]->next != NULL) panic("More than one SBR Return in c_dTable\n");
412 for (ptr=ld->c_pre[i], index=0; index < ld->c_numPre[i]; ++index, ++ptr) {
413 if (*ptr+1!=de->value) { /* Make new Entry */
414 n=DNEW(struct depthElement);
422 printf( "(%3i)table[%3i %3i]: ",m->basicblocks[j].flags,j,m->basicblocks[j].debug_nr);
423 for (de=ld->c_dTable[j]; de != NULL; de=de->next) {
424 printf( "%3i ", de->value);
433 void lsra_dump_Graph(methodinfo *m, struct depthElement **table)
436 struct depthElement *de;
439 printf ("table == NULL\n");
443 for(i=0; i < m->basicblockcount; i++) {
445 switch (m->basicblocks[i].type) {
458 printf("%3i ", m->basicblocks[i].flags);
462 printf( "(F%3i)table[%3i %3i]: ",m->basicblocks[i].flags,i,m->basicblocks[i].debug_nr);
463 for (de=table[i]; de != NULL; de=de->next) {
464 printf( "%3i ", de->value);
468 printf( "table dump end\n");
472 void lsra_main(methodinfo *m, lsradata *ls, registerdata *rd)
474 struct lifetime *lt, *lt_prev, *lt_temp, *int_lt, *int_lt_last, *flt_lt, *flt_lt_last;
476 int lt_count,lt_int_count,lt_flt_count,lt_left_count;
480 int sav_reg_count, tmp_reg_count;
481 struct lsra_reg *reg;
485 int flags; /* 0 INMEMORY->lifetimes, 1 INTREG->int_lt, 2 FLTREG->flt_lt */
488 /* first split lifetimes for integer and float registers */
489 int_lt_last=int_lt=NULL;
490 flt_lt_last=flt_lt=NULL;
493 for (lt_count=0,lt=ls->lifetimes; lt!=NULL;lt=lt->next,lt_count++);
496 for (lt_prev=lt=ls->lifetimes;lt!=NULL;) {
499 if (lt->v_index < 0) { /* stackslot */
502 if (lt->local_ss == NULL) panic("lsra_main Lifetime Stackslot invalid\n");
504 type = lt->local_ss->s->type;
505 } else { /* local var */
506 if (rd->locals[lt->v_index][lt->type].type>=0) {
507 type = rd->locals[lt->v_index][lt->type].type;
508 } else panic("Type Data Mismatch 2\n");
513 #if defined(__I386__)
515 * for i386 put all longs in memory
529 panic("Unknown Type\n");
534 case 1: /* l->lifetimes -> int_lt */
535 if (int_lt == NULL) {
536 int_lt_last=int_lt=lt;
538 int_lt_last->next=lt;
542 case 2: /* l->lifetimes -> flt_lt */
544 flt_lt_last=flt_lt=lt;
546 flt_lt_last->next=lt;
552 if (lt == ls->lifetimes) {
553 lt=lt_prev=ls->lifetimes=ls->lifetimes->next;
555 lt_prev->next=lt->next;
564 lsra_sort_lt(&int_lt);
565 lsra_sort_lt(&(ls->lifetimes));
566 lsra_sort_lt(&flt_lt);
569 for (lt_int_count=0,lt=int_lt; lt!=NULL;lt=lt->next,lt_int_count++);
570 for (lt_flt_count=0,lt=flt_lt; lt!=NULL;lt=lt->next,lt_flt_count++);
571 for (lt_left_count=0,lt=ls->lifetimes; lt!=NULL;lt=lt->next,lt_left_count++);
573 printf("\nLifetimes: %3i left: %3i Intlt: %3i Fltlt: %3i \n",lt_count,lt_left_count,lt_int_count,lt_flt_count);
574 if (lt_count != lt_int_count + lt_flt_count + lt_left_count) {
575 panic ("lifetimes missing\n");
578 lsra_reg_use=rd->savintregcnt;
580 for (reg_count = 0; nregdescint[reg_count] != REG_END; reg_count++);
582 reg=DMNEW(struct lsra_reg,reg_count);
584 for (i=0; i<reg_count ; i++)
585 if (nregdescint[i]==REG_SAV) {
586 reg[sav_reg_count].reg_index=i;
587 reg[sav_reg_count].use=0;
590 tmp_reg_count=sav_reg_count;
591 for (i=0; i<reg_count ; i++) {
592 #if defined(__I386__)
593 if ((method_uses_ecx) && (i==ECX)) continue;
594 if ((method_uses_edx) && (i==EDX)) continue;
596 if (nregdescint[i]==REG_TMP) {
597 reg[tmp_reg_count].reg_index=i;
598 reg[tmp_reg_count].use=0;
602 _lsra_main(m, ls, int_lt, reg, tmp_reg_count, sav_reg_count, &lsra_mem_use, &lsra_reg_use);
603 if (lsra_reg_use > rd->savintregcnt) lsra_reg_use=rd->savintregcnt;
605 rd->maxsavintreguse= lsra_reg_use;
606 lsra_reg_use=rd->savfltregcnt;
609 for (reg_count = 0; nregdescfloat[reg_count] != REG_END; reg_count++);
611 reg=DMNEW(struct lsra_reg,reg_count);
613 for (i=0; i<reg_count ; i++)
614 if ((nregdescfloat[i]==REG_SAV) || (m->isleafmethod && (nregdescfloat[i]==REG_ARG))) {
615 reg[sav_reg_count].reg_index=i;
616 reg[sav_reg_count].use=0;
620 tmp_reg_count=sav_reg_count;
621 for (i=0; i<reg_count ; i++)
622 if (nregdescfloat[i]==REG_TMP) {
623 reg[tmp_reg_count].reg_index=i;
624 reg[tmp_reg_count].use=0;
627 _lsra_main(m,ls, flt_lt, reg, tmp_reg_count, sav_reg_count, &lsra_mem_use, &lsra_reg_use);
628 if (lsra_reg_use > rd->savfltregcnt) lsra_reg_use=rd->savfltregcnt;
631 rd->maxsavfltreguse=lsra_reg_use;
633 #ifndef SPECIALMEMUSE
634 #if defined(__X86_64__)
636 * XXX: we have a problem here, but allocating a little more stack space
637 * is better than having a bug
639 /* if (arguments_num > (intreg_argnum + fltreg_argnum)) */
640 /* ifmemuse = arguments_num - (intreg_argnum + fltreg_argnum); */
641 if (rd->arguments_num > rd->fltreg_argnum)
642 lsra_mem_use = rd->arguments_num - rd->fltreg_argnum;
644 if (rd->arguments_num > rd->intreg_argnum)
645 lsra_mem_use = rd->arguments_num - rd->intreg_argnum;
651 lsra_mem_use = rd->ifmemuse;
655 printf("Alloc Rest\n");
657 lsra_alloc(m, rd, ls->lifetimes,&lsra_mem_use);
659 printf("Alloc Int\n");
661 lsra_alloc(m, rd, int_lt,&lsra_mem_use);
663 printf("Alloc Flt\n");
665 lsra_alloc(m, rd, flt_lt,&lsra_mem_use);
667 #ifdef LSRA_PRINTLIFETIMES
668 printf("Int RA complete \n");
669 printf("Lifetimes after splitting int: \n");
670 print_lifetimes(rd, int_lt);
672 printf("Flt RA complete \n");
673 printf("Lifetimes after splitting flt:\n");
674 print_lifetimes(rd, flt_lt);
676 printf("Rest RA complete \n");
677 printf("Lifetimes after leftt:\n");
678 print_lifetimes(rd, ls->lifetimes);
681 rd->maxmemuse=lsra_mem_use;
684 void lsra_alloc(methodinfo *m, registerdata *rd, struct lifetime *lifet, int *mem_use)
688 struct freemem *fmem;
691 fmem=DNEW(struct freemem);
695 for (lt=lifet;lt!=NULL;lt=lt->next) {
702 regoff=lsra_getmem(lt, fmem, mem_use);
708 if (lt->v_index < 0) {
709 for (n=lt->local_ss; n!=NULL; n=n->next) {
710 lsra_setflags( &(n->s->flags), flags);
713 } else { /* local var */
714 if (rd->locals[lt->v_index][lt->type].type>=0) {
715 /* lsra_setflags( &(rd->locals[lt->v_index][lt->type].flags), flags); */
716 rd->locals[lt->v_index][lt->type].flags= flags;
717 rd->locals[lt->v_index][lt->type].regoff=regoff;
718 } else panic("Type Data mismatch 1\n");
723 void lsra_setflags(int *flags, int newflags)
725 if ( newflags & INMEMORY)
730 if (newflags & SAVEDVAR)
734 int lsra_getmem(struct lifetime *lt, struct freemem *fmem, int *mem_use)
736 struct freemem *fm, *p;
738 /* noch kein Speicher vergeben, oder alle Enden später */
739 if ((fmem->next == NULL) || (fmem->next->end > lt->i_start))
740 fm=lsra_getnewmem(mem_use);
742 /* Speicherstelle frei */
748 for (p=fmem; (p->next!=NULL) && (p->next->end < fm->end); p=p->next);
754 struct freemem *lsra_getnewmem(int *mem_use)
758 fm=DNEW(struct freemem);
765 void _lsra_main( methodinfo *m, lsradata *ls, struct lifetime *lifet, struct lsra_reg *reg, int tmp_reg_count, int sav_reg_count, int *mem_use, int *reg_use)
770 int reg_count, active_count;
772 if ((tmp_reg_count+sav_reg_count) == 0) {
773 for (lt=lifet; lt != NULL; lt=lt->next)
778 ls->active_tmp = NULL;
779 ls->active_sav = NULL;
780 ls->active_tmp_count=0;
781 ls->active_sav_count=0;
782 for (lt=lifet; lt != NULL; lt=lt->next) {
783 lsra_expire_old_intervalls(ls, lt,reg);
784 if (lt->savedvar && (!m->isleafmethod)) {
785 reg_count=sav_reg_count;
786 active_count=ls->active_sav_count;
789 reg_count=tmp_reg_count;
790 active_count=ls->active_sav_count+ls->active_tmp_count;
792 if (active_count == reg_count)
793 spill_at_intervall(ls, lt);
795 for (i=reg_count-1;i>=0;i--) {
798 lt->reg=reg[i].reg_index;
800 if (_reg_use<*reg_use) *reg_use=_reg_use;
804 if (i < sav_reg_count)
805 lsra_add_active(lt, &(ls->active_sav), &(ls->active_sav_count));
807 lsra_add_active(lt, &(ls->active_tmp), &(ls->active_tmp_count));
812 void lsra_add_active(struct lifetime *lt, struct active_lt **active, int *active_count)
814 struct active_lt *alt,*alt1,*alt2;
815 alt=DNEW(struct active_lt);
818 for(alt1=alt2=*active; alt1 != NULL; alt2=alt1, alt1=alt1->next)
819 if (alt1->lt->i_end > lt->i_end) break;
821 if (alt1 == *active) {
825 alt->next = alt2->next;
832 void lsra_expire_old_intervalls(lsradata *ls, struct lifetime *lt, struct lsra_reg *reg)
834 _lsra_expire_old_intervalls(lt, reg, &(ls->active_tmp), &(ls->active_tmp_count));
835 _lsra_expire_old_intervalls(lt, reg, &(ls->active_sav), &(ls->active_sav_count));
838 void _lsra_expire_old_intervalls(struct lifetime *lt, struct lsra_reg *reg, struct active_lt **active, int *active_count)
840 struct active_lt *alt,*alt1;
843 for (alt1=alt=*active; alt != NULL; alt1=alt, alt=alt->next) {
844 if (alt->lt->i_end >= lt->i_start) return;
846 *active = (*active)->next;
848 alt1->next=alt->next;
850 for (i=0;reg[i].reg_index != alt->lt->reg;i++);
856 void spill_at_intervall(lsradata *ls, struct lifetime *lt )
859 _spill_at_intervall(lt, &(ls->active_sav), &(ls->active_sav_count));
861 _spill_at_intervall(lt, &(ls->active_tmp), &(ls->active_tmp_count));
862 if (lt->reg == -1) /* kein tmp mehr frei gewesen */
863 _spill_at_intervall(lt, &(ls->active_sav), &(ls->active_sav_count));
865 if (lt->reg == -2) panic("spill_at_intervall: Keine Register mehr frei gewesen!\n");
868 void _spill_at_intervall(struct lifetime *lt, struct active_lt **active, int *active_count)
870 struct active_lt *alt,*alt1;
871 if (*active == NULL) {
875 /* get last intervall from active */
876 for (alt1=alt=*active; alt->next != NULL; alt1=alt, alt=alt->next);
878 if ((alt->lt->i_end > lt->i_end) && (alt->lt->usagecount < lt->usagecount)) {
879 lt->reg=alt->lt->reg;
883 *active=(*active)->next;
885 alt1->next=alt->next;
886 /* FREE(alt,struct active_lt); */
888 lsra_add_active(lt, active, active_count);
894 int lsra_getmaxblock(methodinfo *m, loopdata *ld, int bb_start)
898 struct depthElement *hp;
901 blocks=DMNEW(int, m->basicblockcount);
902 /* ExTable Ablauf kann in die STD Code BB wieder "hineinspringen" */
904 /* TODO vorher alle "normalen" BB mit 2=bereits besucht initialisieren */
907 for (i=0; i<m->basicblockcount; i++) blocks[i]=-1;
914 for (i=0; i<m->basicblockcount; i++) {
916 if (blocks[i] == 1) {
917 if (i > bb_max) bb_max = i;
918 blocks[i]=2; /* visited */
919 for (hp=ld->c_dTable[i]; hp!=NULL; hp=hp->next) {
920 if (blocks[hp->value] != 2) {
921 blocks[hp->value]=1; /* to visit */
929 printf("ExTable searching: BB_MAX %3i ",bb_max);
930 for (i=0; i<m->basicblockcount; i++)
931 if (blocks[i] != -1) printf("%3i ",i);
938 void lsra_calc_lifetime_length(methodinfo *m, lsradata *ls, codegendata *cd, loopdata *ld)
942 struct l_loop *loops;
943 struct b_loop *block_loop;
945 int *exh_max; /* Exception Handler End BB */
946 int *exh_min; /* Exception Handler Start BB */
947 int *ex_max; /* Exception guarded Area End BB */
948 int *ex_min; /* Exception guarded Area Start BB */
950 int blast,bfirst,ilast,ifirst,usage;
953 struct LoopContainer *lc;
954 struct LoopElement *le;
958 /* Für Exceptionhandler Blocks wurde keine Loop Analyse durchgeführt! */
959 /* -> deshalb vorerst die einzelnen Handler als eine Loop eintragen */
960 /* oder loop analyse extra für jeden Handler aufrufen */
962 /* lifetime der Vars des ExHandlers über guarded Bereich ausdehnen! */
964 /* Falls die einzelnen Blöcke einer Loop nicht durchgehend nummeriert sind */
965 /* auch nicht alle in block_loop eintragen! */
967 exh_max = DMNEW(int, cd->exceptiontablelength);
968 exh_min = DMNEW(int, cd->exceptiontablelength);
969 ex_max = DMNEW(int, cd->exceptiontablelength);
970 ex_min = DMNEW(int, cd->exceptiontablelength);
972 /* BB der Exhandler bestimmen + BB der guarded Area hinzu */
973 ex = cd->exceptiontable;
974 for (i=0; ex != NULL; i++,ex = ex->down) {
975 if (ex->handler == NULL) {
977 printf("lsra_init_blocks EXCEPTIONTABLE without handler!\n");
980 if ((ex->handler->debug_nr < 0) || (ex->handler->debug_nr >= m->basicblockcount)) {
982 printf("lsra_init_blocks EXCEPTIONTABLE Handler Blocknummer invalid! %i\n", ex->handler->debug_nr);
985 exh_min[i]=ex->handler->debug_nr;
986 exh_max[i]=lsra_getmaxblock(m, ld, ex->handler->debug_nr);
988 ex_min[i]=ex->start->debug_nr;
989 ex_max[i]=ex->end->debug_nr;
991 printf("EX %3i exmin %3i exmax %3i exhmin %3i exhmax %3i\n",i,ex_min[i],ex_max[i],exh_min[i],exh_max[i]);
997 /* extend lifetime within loops */
999 for (num_loops=0,lc =ld->c_allLoops;lc!=NULL;num_loops++,lc=lc->next);
1001 /* set up loops[i].b_first .b_last to hold the first and last node of all loops */
1002 loops=DMNEW(struct l_loop,num_loops);
1003 for (i=0,lc=ld->c_allLoops;i<num_loops;i++,lc=lc->next) {
1006 bfirst=m->basicblockcount;
1008 while (le != NULL) {
1009 if (le->node<bfirst) bfirst=le->node;
1010 if (le->node>blast) blast=le->node;
1013 loops[i].b_first=bfirst;
1014 loops[i].b_last=blast;
1018 /* sort loops by b_first desc*/
1019 for (i=0; i<num_loops-1;i++) {
1020 for (j=i+1; j<num_loops;j++) {
1021 if (loops[i].b_first < loops[j].b_first) {
1022 bfirst=loops[j].b_first;
1023 blast=loops[j].b_last;
1024 loops[j].b_first=loops[i].b_first;
1025 loops[j].b_last=loops[i].b_last;
1026 loops[i].b_first=bfirst;
1027 loops[i].b_last=blast;
1032 /* check for nesting_level, overlapping */
1033 for (i=0; i<num_loops-1;i++) {
1034 /*! loops[i].b_first >= loops[i+1].b_first !*/
1035 if (loops[i+1].b_last>=loops[i].b_first) {
1036 if (loops[i+1].b_last<loops[i].b_last) {
1037 /* overlapping -> make one loop of both */
1038 loops[i+1].b_last=loops[i].b_last;
1039 loops[i].b_first=-1;
1042 loops[i].nesting++; /* only boolean if nested... */
1047 /* cumulate basicblocks[i].icount in block_loop[i].instr*/
1048 block_loop=DMNEW(struct b_loop, m->basicblockcount);
1049 for (i=0;i<m->basicblockcount; i++) {
1050 block_loop[i].loop=-1;
1052 block_loop[i].instr=block_loop[i-1].instr+m->basicblocks[i-1].icount;
1054 block_loop[i].instr=0;
1057 /* set block_loop[j].loop to loop index, if Basic Block is in this loop */
1058 for (i=0; i<num_loops;i++) {
1059 if (loops[i].b_first!=-1) {
1061 for (j=loops[i].b_first;j<=loops[i].b_last;j++) block_loop[j].loop=i;
1065 /* now iterate through lifetimes and expand them */
1069 if (ls->back_edge_panic) {
1071 lt->i_end=block_loop[m->basicblockcount-1].instr+m->basicblocks[m->basicblockcount-1].icount;
1077 while (il->next!=NULL) {
1078 if ((il->b_index != il->next->b_index) || ((il->b_index == il->next->b_index) && (il->instr != il->next->instr))) {
1079 if (block_loop[il->b_index].loop == -1)
1080 usage++; /* not in a loop */
1086 /* expand lifetimes in a exceptionhandler to at least the whole handler */
1087 /* TODO do a loop analyze for the exceptionhandler, too*/
1088 for (i=0; i < cd->exceptiontablelength; i++) {
1090 if ( !((bfirst > exh_max[i]) || ( blast < exh_min[i])) ) {
1091 /* Überschneidung mit exh_???[i]-> lt liegt in Exceptionhandler */
1092 /* -> Start auf mindestens die erste Instruktion des geschützten Bereiches legen */
1093 if (bfirst >= exh_min[i]) {
1097 /* -> Ende auf mindestens die letzte Instruktion des geschützten Bereiches legen */
1098 if (blast <= exh_max[i]) {
1100 ilast= m->basicblocks[exh_max[i]].icount-1;
1105 ilast+=block_loop[blast].instr; /* add icount of previous Basic Blocks */
1106 ifirst+=block_loop[bfirst].instr; /* add icount of previous Basic Blocks */
1108 if ((j=block_loop[bfirst].loop)==-1)
1109 j=block_loop[blast].loop;
1112 if (loops[j].b_first<=bfirst) {
1113 bfirst=loops[j].b_first;
1114 ifirst=block_loop[bfirst].instr;
1115 usage+=loops[j].nesting*100;
1117 if (blast <= loops[j].b_last) {
1118 blast=loops[j].b_last;
1119 ilast=block_loop[blast].instr+m->basicblocks[blast].icount;
1120 usage+=loops[j].nesting*100;
1128 lt->usagecount=usage;
1134 for (i=0; i<num_loops;i++) {
1135 printf("LoopNR: %3i Start: %3i End: %3i Nesting: %3i Block_loop[%3i]:",i,loops[i].b_first,loops[i].b_last,loops[i].nesting,i);
1136 for (j=0;j<m->basicblockcount;j++)
1137 if (block_loop[j].loop==i) printf(" %3i",j);
1143 /* void lsra_sort_lt(struct lifetime **lifet) */
1145 /* struct lifetime *lt, lt_new, *temp, *tmp; */
1147 /* lt_new.next=NULL; */
1149 /* for (lt=*lifet; lt!= NULL;) { */
1150 /* temp=lt->next; */
1152 /* for(tmp=<_new; (tmp->next!= NULL) && (tmp->next->i_start < lt->i_start); tmp=tmp->next); */
1153 /* lt->next=tmp->next; */
1157 /* *lifet=lt_new.next; */
1162 void _lsra_merge_lt(struct lifetime **p, int i1, int i2)
1164 struct lifetime *iptr, *iptr1, *iptr2;
1166 if ( (iptr1=p[i2])==NULL) return;
1167 if ( (iptr=p[i1])==NULL) return;
1172 while ((iptr != NULL) && (iptr1 != NULL)) {
1173 if (iptr->i_start < iptr1->i_start) {
1197 void lsra_merge_lt(struct lifetime **p, int top)
1201 for (j=1; j<top; j*=2)
1202 for (i=1; i<top; i+=2*j)
1203 _lsra_merge_lt(p, i, i+j);
1204 _lsra_merge_lt(p, 0, 1);
1207 void lsra_sort_lt(struct lifetime **lifet)
1209 /* sort lifetimes by increasing start point */
1210 /* struct lifetime **plt,**plt1; */
1211 struct lifetime *lt, *temp, *tmp;
1213 struct lifetime **p;
1215 p=DMNEW(struct lifetime *, P_MAX);
1216 for (i=0; i<P_MAX; i++) p[i]=NULL;
1220 for (lt=*lifet; lt!= NULL;) {
1230 if (temp->i_start < tmp->i_start) {
1232 /* temp->next == tmp */
1242 lsra_merge_lt(p, P_MAX);
1246 lsra_merge_lt(p, top);
1250 #ifdef LSRA_PRINTLIFETIMES
1251 void print_lifetimes(registerdata *rd, struct lifetime *lt)
1255 int type,flags,regoff,j,varkind;
1258 for (n=lt,j=0; n!=NULL; n=n->next,j++) {
1259 if (n->v_index < 0) { /* stackslot */
1260 type = n->local_ss->s->type;
1261 flags=n->local_ss->s->flags;
1262 regoff=n->local_ss->s->regoff;
1263 varkind=n->local_ss->s->varkind;
1264 } else { /* local var */
1265 if (rd->locals[n->v_index][n->type].type>=0) {
1266 type = rd->locals[n->v_index][n->type].type;
1267 flags=rd->locals[n->v_index][n->type].flags;
1268 regoff=rd->locals[n->v_index][n->type].regoff;
1271 panic("Type Data mismatch 3\n");
1273 printf("i_Start: %3i i_stop: %3i reg: %3i VI: %3i Usage: %3i type: %3i flags: %3i varkind: %3i ILst: ",n->i_start,n->i_end,regoff,n->v_index,n->usagecount,type,flags, varkind);
1274 for (ni=n->i_list; ni!=NULL; ni=ni->next) {
1275 if (ni==ni->next) panic("loop in instruction list!\n");
1276 printf( "(%3i,%3i) ",ni->b_index,ni->instr);
1280 printf( "%3i Lifetimes printed \n",j);
1284 struct stackslot *lsra_make_ss(stackptr s, int bb_index)
1286 struct stackslot *ss;
1288 ss=DNEW(struct stackslot);
1294 /* merge i_list from lt1 to lt in order */
1295 void lsra_merge_i_lists(struct lifetime *lt, struct lifetime *lt1)
1297 struct _i_list *iptr, *iptr1, *iptr2;
1299 /* merge i_lists in order */
1301 iptr2=lt->i_list=NULL;
1303 while ((iptr != NULL) && (iptr1 != NULL)) {
1304 if (iptr1->instr == -1) {
1305 /* throw away, just for joining */
1308 if ((iptr->b_index > iptr1->b_index)|| ((iptr->b_index == iptr1->b_index) && (iptr->instr > iptr1->instr))) {
1309 if (lt->i_list==NULL) {
1317 if (lt->i_list==NULL) {
1329 panic("lsra_merge_i_lists: Empty Instruction List in Lifetime\n");
1332 if (lt->i_list==NULL)
1338 if (lt->i_list==NULL)
1345 /* merge local_ss from lt1 to lt in order */
1346 void lsra_merge_local_ss(struct lifetime *lt, struct lifetime *lt1)
1348 struct stackslot *ssptr, *ssptr1, *ssptr2;
1350 /* merge stackslots in order */
1352 ssptr2=lt->local_ss=NULL;
1353 ssptr1=lt1->local_ss;
1354 while ((ssptr != NULL) && (ssptr1 != NULL)) {
1356 if (ssptr->s > ssptr1->s) {
1357 if (lt->local_ss==NULL) {
1365 if (lt->local_ss==NULL) {
1366 lt->local_ss=ssptr1;
1368 ssptr2->next=ssptr1;
1371 ssptr1=ssptr1->next;
1376 panic("lsra_merge_local_ss: Empty Stackslot List in Lifetime\n");
1379 if (lt->local_ss==NULL)
1380 lt->local_ss=ssptr1;
1382 ssptr2->next=ssptr1;
1385 if (lt->local_ss==NULL)
1393 void dump_join( struct lifetime *lt_passing)
1395 struct lifetime *lt;
1396 struct stackslot *ss;
1399 for (lt=lt_passing,i=0; lt != NULL; lt=lt->next, ++i) {
1400 printf("Lifetime(%2i)\n PT: ",i);
1401 for ( ss=lt->passthrough; ss!=NULL; ss=ss->next)
1402 printf("(%2i, %2i, %6p) ",ss->bb, ss->s->varnum, (void *)ss->s);
1404 for (ss = lt->local_ss; ss!=NULL; ss=ss->next)
1405 printf("(%2i, %2i, %6p) ", ss->bb, ss->s->varnum, (void *)ss->s);
1411 void lsra_join_lifetimes(methodinfo *m, codegendata *cd, lsradata *ls, loopdata *ld)
1413 int i, j, index, stacks_top;
1414 int in1, out1, in2, out2, temp;
1415 struct depthElement *de;
1417 int *in_stacks, *out_stacks;
1419 struct stackslot **stacks, *ss, *ss1, *ss_new;
1420 struct lifetime *lt, *lt_prev, *lt_new, *lt_passing;
1421 struct stackslot *p, *q, *r;
1427 in=m->basicblocks[0].instack; /* ?falls Instack des Startblocks != leer ?*/
1428 if (in != NULL) printf("------------ Instack von BB0 nicht leer! -------\n");
1431 /* join copies of dup/swap? or let just codegen copy the contents? */
1432 /* -> ?TODO? save at ICMD_DUP* and ICMD_SWAP Copy Info */
1434 /* out_stacks hold an index to stacks, which holds the joined stacks */
1435 /* in_stacks hold an index to out_stacks, with which they are joined */
1436 /* an initial index of -1 mark, that they where not visited yet */
1437 in_stacks = DMNEW(int, m->basicblockcount);
1438 out_stacks = DMNEW(int, m->basicblockcount);
1439 stacks = DMNEW(struct stackslot *, m->basicblockcount);
1440 /* for (i=0; i< m->basicblockcount; i++) stacks[i]=NULL; */
1441 for (i=0; i < m->basicblockcount; i++ ) in_stacks[i]=out_stacks[i]=-1;
1444 for (i=0; i < m->basicblockcount; i++)
1445 if (m->basicblocks[i].flags >= BBREACHED) {
1446 if ((out=m->basicblocks[i].outstack) != NULL) {
1447 ss=lsra_make_ss(out, i);
1449 stacks[stacks_top]=ss;
1450 out_stacks[i]=stacks_top++;
1451 for (de=ld->c_dTable[i]; de != NULL; de=de->next) {
1452 if (in_stacks[de->value] == -1) { /* not visited==joined yet */
1453 in_stacks[de->value] = i;
1454 ss=lsra_make_ss(m->basicblocks[de->value].instack, de->value);
1455 ss->next=stacks[out_stacks[i]];
1456 stacks[out_stacks[i]]=ss;
1457 } else { /* in stacks already joined -> join with others */
1458 /* join this outstack to index in_stack[de->value] points to */
1459 for (ss=stacks[out_stacks[i]]; ss->next != NULL; ss=ss->next); /* get last element */
1460 ss->next=stacks[out_stacks[in_stacks[de->value]]];
1461 stacks[out_stacks[in_stacks[de->value]]]=stacks[out_stacks[i]];
1462 stacks[out_stacks[i]]=NULL;
1463 /* update all prior out_stacks indexes to this new join */
1464 for (j=0; j <= i; j++) {
1465 if (out_stacks[j] == out_stacks[i]) {
1466 out_stacks[j]=out_stacks[in_stacks[de->value]];
1474 /* leere einträge aus stacks entfernen */
1475 for (i=index=0; i< stacks_top;) {
1476 if (stacks[index]!=NULL) { /* nächsten freien Platz suchen */
1480 if (stacks[i]==NULL) { /* nächsten bestetzten Platz zum verschieben suchen*/
1482 } else { /* von i nach index umhängen */
1483 stacks[index]=stacks[i];
1491 /* 0 <= i < index | join all corresponding stackslots of in- and outstacks of stacks[i] to lt_new */
1492 /* and put lt_new in lt_passing (if passthrough ss exist in them) or ls->lifetimes */
1493 for (i=0; i < index; i++) {
1494 while (stacks[i]->s != NULL) {
1496 for (ss=stacks[i]; ss!=NULL; ss=ss->next) {
1497 /* search stackslot ss->s lifetimelist of basicblock(ss->bb) (ss_lifetimes) */
1498 /* remember the link before found lifetime, to remove it afterwards */
1499 for (lt_prev=lt=ls->ss_lifetimes[ss->bb]; lt!=NULL; lt_prev=lt, lt=lt->next) {
1500 for (ss1=lt->local_ss; (ss1!=NULL) && (ss1->s != ss->s); ss1 = ss1->next);
1501 if (ss1 != NULL) break; /* found */
1504 if (lt==NULL) panic("lsra_join_lifetimes error in lifetimelist\n");
1506 /* Remove found lifetime from Block Stackslot Lifetimelist */
1507 if (lt==ls->ss_lifetimes[ss->bb]) {
1508 ls->ss_lifetimes[ss->bb]=lt->next;
1510 lt_prev->next=lt->next;
1515 if (lt->i_list->instr==-1) {
1516 if (out_stacks[in_stacks[ss->bb]] == out_stacks[ss->bb]) {
1517 /* Throughpassing Basicblock is already in one "join Group" */
1518 /* If this stackslot ((lt->local_ss)ss1->s == ss->s) is already in lt_new->local_ss */
1519 /* do not add it a second time! */
1520 if (lt_new != NULL) {
1521 for (ss_new=lt_new->local_ss; (ss_new != NULL) && (ss_new->s != ss1->s); ss_new = ss_new->next);
1522 if (ss_new != NULL) drop = true;
1527 /* lt->s->varkind=TEMPVAR */; /* no LOCALVAR, ARGVAR or STACKVAR with joined lifetimes */
1528 lt->v_index=-1; /* not a local var */
1530 /* join Lifetime lt to lt_new */
1531 if (lt_new == NULL) {
1533 lt_new->passthrough = NULL;
1535 lsra_merge_i_lists( lt_new, lt);
1536 lsra_merge_local_ss( lt_new, lt);
1540 pt=(lt->i_list->instr==-1); /* remember this now, because merge_i_list could once destroy this link*/
1542 /* add stackslot to local_ss of lt_new */
1543 ss_new = DNEW(struct stackslot);
1545 lt_new->savedvar |= (lt->savedvar & SAVEDVAR);
1547 if (pt) { /*lt->i_list->instr==-1) {*/
1548 /* BB passes this stackslot through -> join later with other side!*/
1549 if (out_stacks[in_stacks[ss->bb]] != out_stacks[ss->bb]) {
1550 /* Stackslot ist not passed through to same (this) "join group" */
1552 p = DNEW(struct stackslot);
1553 p->bb = ss->bb; /* Basic Block index of joined Lifetime */
1555 /* sort p in lt_new->passthrough list by increasing stackslot adress */
1556 /* there are no two stackslots allowed, which "join" the same "join groups" */
1557 /* in case one has to be dropped, keep the one with the "greater" address */
1560 in2=out_stacks[in_stacks[p->bb]];
1561 out2=out_stacks[p->bb];
1562 if (in2 > out2) { temp=in2; in2=out2; out2=temp; }
1563 for (q=lt_new->passthrough; (q != NULL);) {
1564 in1=out_stacks[in_stacks[q->bb]];
1565 out1=out_stacks[q->bb];
1566 if (in1 > out1) { temp=in1; in1=out1; out1=temp; }
1568 if ((in1 == in2) && (out1 == out2)) { /* p->s would join to same group -> drop the one with the lower address */
1569 if (p->s < q->s) /* drop p->s, it has the lower address */
1571 else { /* drop q from the list, since it has the lower address */
1572 if (q == lt_new->passthrough ) {
1573 lt_new->passthrough=q->next;
1575 } else { /* r points to the previous element */
1582 r=q; /* remember position for sorting p in */
1588 /* List Empty or all elements greater than p->s */
1589 p->next=lt_new->passthrough;
1590 lt_new->passthrough=p;
1599 ss->s=ss->s->prev; /* Next Stackslot for next Iteration */
1601 if (lt_new->passthrough != NULL) {
1602 lt_new->next=lt_passing;
1605 lt_new->next=ls->lifetimes;
1606 ls->lifetimes=lt_new;
1611 /* join lifetimes with same stackslots in ->passthrough in lt_passing */
1612 for (lt=lt_passing; lt != NULL; lt=lt->next) {
1613 while (lt->passthrough != NULL) {
1615 printf("before \n");
1616 dump_join(lt_passing);
1618 s=lt->passthrough->s;
1619 lt->passthrough=lt->passthrough->next; /* drop this stackslot from lt_passthrough list */
1620 /* search for next lifetime, which has the same stackslot in passthrough */
1621 /* lt_new->next will point to it */
1622 /* there has to be another lifetime after lt with same s in passthrough */
1623 for (lt_new=lt; (lt_new->next != NULL); lt_new=lt_new->next) {
1624 /* passthrough is sorted by increasing address of s */
1625 /* remember in q the list element before p with p->s == s */
1626 for (p=lt_new->next->passthrough; (p!=NULL) && (p->s < s); q=p,p=p->next);
1627 if ((p != NULL) && (p->s == s)) {
1628 /* found -> now drop this stackslot from lt_new's passtrough list */
1629 if (p == lt_new->next->passthrough) { /* first element in list */
1630 lt_new->next->passthrough = lt_new->next->passthrough->next;
1637 if (lt_new->next==NULL)
1638 panic("lsra_join_lifetimes error in lt_passing lifetimelist\n");
1640 /* join lt and lt_new->next to lt */
1641 lt->savedvar |= (lt_new->next->savedvar & SAVEDVAR);
1643 /* join local_ss lists */
1645 if (lt_new->next->local_ss == NULL)
1646 panic("lsra_join_lifetimes Lifetime without stackslot\n");
1648 /* for (ss=lt_new->next->local_ss; (ss->next != NULL); ss=ss->next); */
1649 /* ss->next=lt->local_ss; */
1650 /* lt->local_ss=lt_new->next->local_ss; */
1651 lsra_merge_local_ss(lt, lt_new->next);
1653 /* merge i_lists in order */
1654 lsra_merge_i_lists(lt, lt_new->next);
1656 /* join passthrough lists in ascending order */
1657 /* if there are duplicates, it happened that a join was done through the */
1658 /* other joins till now, so just drop both of them */
1660 q=lt_new->next->passthrough;
1661 lt->passthrough=NULL;
1662 ss=NULL; /* pointer to the end of lt->passthrough */
1663 while ( (p!=NULL) && (q!=NULL) ) {
1674 /* Drop both stackslots -> they where just joined through some other joins */
1690 if (lt->passthrough == NULL)
1696 if (lt->passthrough == NULL)
1701 lt_new->next=lt_new->next->next; /* throw away joined lifetime lt_new->next */
1704 dump_join(lt_passing);
1709 if (lt_passing!=NULL) {
1710 for (lt=lt_passing; (lt->next!=NULL); lt=lt->next);
1711 lt->next=ls->lifetimes;
1712 ls->lifetimes=lt_passing;
1717 struct _i_list *lsra_add_i_list(struct _i_list *i_list, int instr, int b_index, int store)
1721 n=DNEW(struct _i_list);
1729 void lsra_add_ss(struct lifetime *lt, stackptr s) {
1730 struct stackslot *ss;
1731 /* Stackslot noch nicht eingetragen? */
1732 if ((lt->local_ss==NULL) || (lt->local_ss->s != s)) {
1733 ss = DNEW(struct stackslot);
1735 ss->next = lt->local_ss;
1737 if (s != NULL) lt->savedvar |= s->flags & SAVEDVAR;
1741 #define lsra_new_stack(ls, s, block, instr) _lsra_new_stack(ls, s, block, instr, LSRA_STORE)
1742 void _lsra_new_stack(lsradata *ls, stackptr s, int block, int instr, int store)
1746 n=DNEW(struct lifetime);
1748 n->savedvar = (s->flags & SAVEDVAR);
1752 if (s->varkind == LOCALVAR)
1753 n->v_index=s->varnum;
1758 n->next=ls->ss_lifetimes[block];
1759 ls->ss_lifetimes[block]=n;
1761 n->i_list=lsra_add_i_list(n->i_list, instr, block, store);
1764 #define lsra_from_stack(ls, s, block, instr) _lsra_from_stack(ls, s, block, instr, LSRA_LOAD)
1765 #define lsra_pop_from_stack(ls, s, block, instr) _lsra_from_stack(ls, s, block, instr, LSRA_POP)
1766 void _lsra_from_stack(lsradata *ls, stackptr s, int block, int instr, int store)
1769 /* ss_lifetimes[block]->local_ss have exactly one entry! */
1770 for (n=ls->ss_lifetimes[block]; (n!=NULL) && (n->local_ss->s!=s);n=n->next);
1772 _lsra_new_stack(ls, s, block, instr, store);
1773 /* ist mit dem neuen joinen hinterher immer so, wenn ein Stackslot in einen BB "reinkommt" */
1774 /* printf("type %i flags %i varkind %i varnum %i regoff %i \n",s->type,s->flags ,s->varkind ,s->varnum ,s->regoff); */
1775 /* panic("lsra_from_stack: Var on Stack not found"); */
1777 n->i_list=lsra_add_i_list(n->i_list, instr, block, store);
1781 void lsra_usage_local(lsradata *ls, s4 v_index, int type, int block, int instr, int store)
1785 /* Lifetime vom richtigen Type suchen */
1786 for (n=ls->locals_lifetimes[v_index]; (n!=NULL) && (n->type!=type);n=n->next);
1790 if (store != LSRA_STORE) printf("lsra_local_store: Read before write Local var: %i paramcount: ?\n", v_index);
1792 lsra_new_local(ls, v_index, type);
1793 /* neue Lifetimes werden immer am Anfang der Liste eingehängt */
1794 n=ls->locals_lifetimes[v_index];
1796 /* add access at (block, instr) to intruction list */
1797 n->i_list=lsra_add_i_list(n->i_list, instr, block, store);
1800 void lsra_new_local(lsradata *ls, s4 v_index, int type)
1804 n=DNEW(struct lifetime);
1809 n->savedvar = SAVEDVAR;
1811 n->next=ls->locals_lifetimes[v_index];
1812 ls->locals_lifetimes[v_index]=n;
1816 void lsra_dump_stack(stackptr s)
1819 printf("%p(R%3i N%3i K%3i T%3i F%3i) ",(void *)s,s->regoff, s->varnum, s->varkind, s->type, s->flags);
1826 void dup_mark( struct dup *dup,stackptr s)
1828 struct stackslot *n;
1829 n = DNEW(struct stackslot);
1830 if (dup->ss == NULL) {
1840 void dup_next( struct dup *dup)
1844 n = DNEW(struct dup);
1845 n->next = dup->next;
1851 void dup_join( struct lsradata *ls, struct dup *dup, int block)
1854 struct stackslot *ss, *ss1;
1855 bool pt; /* joins with passthrough lifetimes not yet possible! */
1856 struct lifetime *join_lt[3]; /* max three lifetimes to join */
1857 struct lifetime *join_lt_prev[3]; /* previous elements for unlinking */
1858 struct lifetime *lt, *lt_prev;
1859 int i, join_lt_top, join_to;
1861 for (i=0; i<3; i++) join_lt[i]=join_lt_prev[i]=NULL;
1862 /* walk through dup structure and clean it up for next block */
1863 /* the first dup entry is alway empty for the next group to come*/
1864 for (d=dup->next; d!= NULL; d = dup->next=dup->next->next) {
1867 for (ss=d->ss; (ss != NULL) && (!pt); ss = ss->next) {
1868 for (lt = lt_prev = ls->ss_lifetimes[block]; lt != NULL ; lt_prev=lt, lt=lt->next) {
1869 for (ss1=lt->local_ss; (ss1!=NULL) && (ss1->s != ss->s); ss1 = ss1->next);
1870 if (ss1 != NULL) break; /* found */
1872 if (lt == NULL) panic("dup_join Lifetimes not found\n");
1873 pt=(lt->i_list->instr == -1); /* joins with passthrough lifetimes not yet possible! */
1874 pt|=(lt->i_list->next == NULL); /* joins with "interface" Stackslots not yet possible! */
1876 join_lt_prev[join_lt_top]=lt_prev;
1877 join_lt[join_lt_top++]=lt;
1880 if (!pt) { /* now join */
1881 /* look if one element is the root of the list (joint_lt == join_lt_prev == ls->ss_lifetimes[block]) */
1882 for (join_to=0; (join_to < join_lt_top) && (join_lt[join_to] != join_lt_prev[join_to]); join_to++);
1883 if (join_to == join_lt_top) /* no root element in join array */
1885 join_lt[join_to]->v_index = -1;
1886 for (i=0; i<join_lt_top; i++) {
1888 /* now join finally */
1889 lsra_merge_i_lists(join_lt[join_to], join_lt[i]);
1890 lsra_merge_local_ss(join_lt[join_to], join_lt[i]);
1891 join_lt[join_to]->savedvar|=(join_lt[i]->savedvar & SAVEDVAR);
1892 /* drop join_lt[i] from list */
1893 join_lt_prev[i]->next = join_lt[i]->next;
1901 void lsra_scan_registers_canditates(methodinfo *m, lsradata *ls)
1919 while (b_index < m->basicblockcount ) {
1921 if (m->basicblocks[b_index].flags >= BBREACHED) {
1922 dst = m->basicblocks[b_index].instack;
1923 if (dst != NULL) { /* create Lifetimes for pass-through Stackslots */
1924 in=m->basicblocks[b_index].instack;
1925 id=m->basicblocks[b_index].indepth;
1926 if (m->basicblocks[b_index].type != BBTYPE_STD) {
1927 /* Pay attention to the top Stackslot in BBTYPE_EXH and BBTYPE_SBR Basicblocks */
1928 /* this is not a passthrough, but set from the "system" to the exception object or */
1929 /* the return adress -> just create a lifetime with a write at instr==0 */
1930 lsra_new_stack(ls, in, b_index, 0);
1935 out=m->basicblocks[b_index].outstack;
1936 od=m->basicblocks[b_index].outdepth;
1938 /* ignore all in-stackslots not in outstack */
1939 for (;id>od; in=in->prev, --id);
1940 /* ignore all out-stackslots not in instack */
1941 for (;od>id; out=out->prev, --od);
1942 /* ignore all non equal stackslots from in and outstack */
1943 for (;in != out; in=in->prev, out=out->prev, --id);
1944 /* set up a lifetime for the rest: */
1945 /* stackslot adress equal, stackslot"number" equal */
1946 for (;in!=NULL; in=in->prev) {
1947 /* Make 2 entries -> one for the instack, one for the out stack */
1948 lsra_new_stack(ls, in, b_index, -1);
1949 lsra_new_stack(ls, in, b_index, -1);
1952 iptr = m->basicblocks[b_index].iinstr;
1953 len = m->basicblocks[b_index].icount;
1956 while (iindex<len) {
1961 printf("bb: %3i bcount: %3i iindex: %3i ilen: %3i opcode: %3i %s\n",b_index,m->basicblockcount,iindex,len,opcode,icmd_names[opcode]);
1962 lsra_dump_stack(src);
1963 lsra_dump_stack(dst);
1968 lsra_usage_local(ls,iptr->op1,TYPE_ADR, b_index,iindex,LSRA_LOAD); /* local read (return adress) */
1973 case ICMD_ELSE_ICONST:
1974 case ICMD_CHECKEXCEPTION:
1975 case ICMD_CHECKASIZE:
1980 case ICMD_INLINE_START:
1981 case ICMD_INLINE_END:
1984 /* pop 0 push 1 const */
1992 /* new stack slot */
1993 lsra_new_stack(ls,dst,b_index,iindex); /* const->stack */
1996 /* pop 0 push 1 load */
2004 lsra_usage_local(ls,iptr->op1,opcode-ICMD_ILOAD, b_index,iindex,LSRA_LOAD); /* local->value */
2005 lsra_new_stack(ls,dst,b_index,iindex); /* value->stack */
2006 /* ?Reference to local var?-> attention if local var is changed */
2010 /* Stack(arrayref,index)->stack */
2022 lsra_new_stack(ls,dst,b_index,iindex); /* arrayref[index]->stack */
2023 lsra_from_stack(ls, src,b_index,iindex); /* stack->index */
2024 lsra_from_stack(ls, src->prev,b_index,iindex); /* stack->arrayref */
2028 /* stack(arrayref,index,value)->arrayref[index]=value */
2040 lsra_from_stack(ls, src,b_index,iindex); /* stack -> value */
2041 lsra_from_stack(ls, src->prev,b_index,iindex); /* stack -> index */
2042 lsra_from_stack(ls, src->prev->prev,b_index,iindex); /* stack -> arrayref */
2045 case ICMD_POP: /* throw away a stackslot -> check if used anyway! */
2046 lsra_pop_from_stack(ls,src,b_index,iindex);
2049 /* pop 1 push 0 store */
2050 /* stack -> local */
2057 lsra_from_stack(ls, src,b_index,iindex); /* stack -> value */
2058 lsra_usage_local(ls,iptr->op1,opcode-ICMD_ISTORE, b_index,iindex,LSRA_STORE); /* local->value */
2067 case ICMD_ARETURN: /*stack(value) -> [empty] */
2069 case ICMD_ATHROW: /* stack(objref) -> undefined */
2071 case ICMD_PUTSTATIC: /* stack(value) -> static_field */
2072 /* pop 1 push 0 branch */
2074 case ICMD_IFNULL: /* stack(value) -> branch? */
2075 case ICMD_IFNONNULL:
2091 /* pop 1 push 0 table branch */
2093 case ICMD_TABLESWITCH:
2094 case ICMD_LOOKUPSWITCH:
2096 case ICMD_NULLCHECKPOP: /****** ????? -1 -> stack *********/
2097 case ICMD_MONITORENTER:
2098 case ICMD_MONITOREXIT:
2099 lsra_from_stack(ls, src,b_index,iindex); /* stack -> value */
2104 case ICMD_POP2: /* throw away 2 stackslots -> check if used anyway! */
2105 lsra_pop_from_stack(ls,src,b_index,iindex);
2106 lsra_pop_from_stack(ls,src->prev,b_index,iindex);
2109 /* pop 2 push 0 branch */
2111 case ICMD_IF_ICMPEQ: /* stack (v1,v2) -> branch(v1,v2) */
2112 case ICMD_IF_ICMPNE:
2113 case ICMD_IF_ICMPLT:
2114 case ICMD_IF_ICMPGE:
2115 case ICMD_IF_ICMPGT:
2116 case ICMD_IF_ICMPLE:
2118 case ICMD_IF_LCMPEQ:
2119 case ICMD_IF_LCMPNE:
2120 case ICMD_IF_LCMPLT:
2121 case ICMD_IF_LCMPGE:
2122 case ICMD_IF_LCMPGT:
2123 case ICMD_IF_LCMPLE:
2125 case ICMD_IF_ACMPEQ:
2126 case ICMD_IF_ACMPNE:
2130 case ICMD_PUTFIELD: /* stack(objref,value) -> objref->method=value */
2132 case ICMD_IASTORECONST:
2133 case ICMD_LASTORECONST:
2134 case ICMD_AASTORECONST:
2135 case ICMD_BASTORECONST:
2136 case ICMD_CASTORECONST:
2137 case ICMD_SASTORECONST:
2138 lsra_from_stack(ls, src,b_index,iindex); /* stack -> value*/
2139 lsra_from_stack(ls, src->prev,b_index,iindex); /* stack -> objref*/
2142 /* pop 0 push 1 dup */
2143 /* merge dupped vars??? */
2145 /* lsra_from_stack(ls, src,b_index,iindex);*/ /* inc usage_count! */
2146 lsra_new_stack(ls,dst,b_index,iindex);
2147 dup_mark(&dup, src);
2148 dup_mark(&dup, dst);
2152 /* pop 0 push 2 dup */
2155 lsra_new_stack(ls,dst->prev,b_index,iindex);
2156 lsra_new_stack(ls,dst,b_index,iindex);
2157 lsra_from_stack(ls, src,b_index,iindex); /* or inc usage_count! */
2158 lsra_from_stack(ls, src->prev,b_index,iindex); /* inc usage_count! */
2160 dup_mark(&dup, src);
2161 dup_mark(&dup, dst);
2162 dup_mark(&dup, dst->prev->prev);
2164 dup_mark(&dup, src->prev);
2165 dup_mark(&dup, dst->prev);
2166 dup_mark(&dup, dst->prev->prev->prev);
2170 /* pop 2 push 3 dup */
2173 lsra_from_stack(ls, src,b_index,iindex); /* from for to, or it will not work! inc usage_count! */
2174 lsra_from_stack(ls, src->prev,b_index,iindex); /*from for to, or it will not work! inc usage_count! */
2175 lsra_new_stack(ls,dst->prev->prev,b_index,iindex);
2176 lsra_new_stack(ls,dst->prev,b_index,iindex);
2177 lsra_new_stack(ls,dst,b_index,iindex);
2178 dup_mark(&dup, src);
2179 dup_mark(&dup, dst);
2180 dup_mark(&dup, dst->prev->prev);
2182 dup_mark(&dup, src->prev);
2183 dup_mark(&dup, dst->prev);
2187 /* pop 3 push 4 dup */
2190 lsra_from_stack(ls, src,b_index,iindex); /* from for to, or it will not work! inc usage_count! */
2191 lsra_from_stack(ls, src->prev,b_index,iindex); /*from for to, or it will not work! inc usage_count! */
2192 lsra_from_stack(ls, src->prev->prev,b_index,iindex); /*from for to, or it will not work! inc usage_count! */
2193 lsra_new_stack(ls,dst->prev->prev->prev,b_index,iindex);
2194 lsra_new_stack(ls,dst->prev->prev,b_index,iindex);
2195 lsra_new_stack(ls,dst->prev,b_index,iindex);
2196 lsra_new_stack(ls,dst,b_index,iindex);
2197 dup_mark(&dup, src);
2198 dup_mark(&dup, dst);
2199 dup_mark(&dup, dst->prev->prev->prev);
2201 dup_mark(&dup, src->prev);
2202 dup_mark(&dup, dst->prev);
2204 dup_mark(&dup, src->prev->prev);
2205 dup_mark(&dup, dst->prev->prev);
2209 /* pop 3 push 5 dup */
2212 lsra_from_stack(ls, src,b_index,iindex); /* from for to, or it will not work! inc usage_count! */
2213 lsra_from_stack(ls, src->prev,b_index,iindex); /*from for to, or it will not work! inc usage_count! */
2214 lsra_from_stack(ls, src->prev->prev,b_index,iindex); /*from for to, or it will not work! inc usage_count! */
2215 lsra_new_stack(ls,dst->prev->prev->prev->prev,b_index,iindex);
2216 lsra_new_stack(ls,dst->prev->prev->prev,b_index,iindex);
2217 lsra_new_stack(ls,dst->prev->prev,b_index,iindex);
2218 lsra_new_stack(ls,dst->prev,b_index,iindex);
2219 lsra_new_stack(ls,dst,b_index,iindex);
2220 dup_mark(&dup, src);
2221 dup_mark(&dup, dst);
2222 dup_mark(&dup, dst->prev->prev->prev);
2224 dup_mark(&dup, src->prev);
2225 dup_mark(&dup, dst->prev);
2226 dup_mark(&dup, dst->prev->prev->prev->prev);
2228 dup_mark(&dup, src->prev->prev);
2229 dup_mark(&dup, dst->prev->prev);
2233 /* pop 4 push 6 dup */
2236 lsra_from_stack(ls, src,b_index,iindex); /* from for to, or it will not work! inc usage_count! */
2237 lsra_from_stack(ls, src->prev,b_index,iindex); /*from for to, or it will not work! inc usage_count! */
2238 lsra_from_stack(ls, src->prev->prev,b_index,iindex); /*from for to, or it will not work! inc usage_count! */
2239 lsra_from_stack(ls, src->prev->prev->prev,b_index,iindex); /*from for to, or it will not work! inc usage_count! */
2240 lsra_new_stack(ls,dst->prev->prev->prev->prev->prev,b_index,iindex);
2241 lsra_new_stack(ls,dst->prev->prev->prev->prev,b_index,iindex);
2242 lsra_new_stack(ls,dst->prev->prev->prev,b_index,iindex);
2243 lsra_new_stack(ls,dst->prev->prev,b_index,iindex);
2244 lsra_new_stack(ls,dst->prev,b_index,iindex);
2245 lsra_new_stack(ls,dst,b_index,iindex);
2246 dup_mark(&dup, src);
2247 dup_mark(&dup, dst);
2248 dup_mark(&dup, dst->prev->prev->prev->prev);
2250 dup_mark(&dup, src->prev);
2251 dup_mark(&dup, dst->prev);
2252 dup_mark(&dup, dst->prev->prev->prev->prev->prev);
2254 dup_mark(&dup, src->prev->prev);
2255 dup_mark(&dup, dst->prev->prev);
2257 dup_mark(&dup, src->prev->prev->prev);
2258 dup_mark(&dup, dst->prev->prev->prev);
2262 /* pop 2 push 2 swap */
2265 lsra_from_stack(ls, src,b_index,iindex); /* from for to, or it will not work! inc usage_count! */
2266 lsra_from_stack(ls, src->prev,b_index,iindex); /*from for to, or it will not work! inc usage_count! */
2267 lsra_new_stack(ls,dst->prev,b_index,iindex);
2268 lsra_new_stack(ls,dst,b_index,iindex);
2269 dup_mark(&dup, src);
2270 dup_mark(&dup, dst->prev);
2272 dup_mark(&dup, src->prev);
2273 dup_mark(&dup, dst);
2323 lsra_from_stack(ls, src,b_index,iindex);
2324 lsra_from_stack(ls, src->prev,b_index,iindex);
2325 lsra_new_stack(ls,dst,b_index,iindex);
2330 case ICMD_IADDCONST:
2331 case ICMD_ISUBCONST:
2332 case ICMD_IMULCONST:
2335 case ICMD_IANDCONST:
2337 case ICMD_IXORCONST:
2338 case ICMD_ISHLCONST:
2339 case ICMD_ISHRCONST:
2340 case ICMD_IUSHRCONST:
2342 case ICMD_LADDCONST:
2343 case ICMD_LSUBCONST:
2344 case ICMD_LMULCONST:
2347 case ICMD_LANDCONST:
2349 case ICMD_LXORCONST:
2350 case ICMD_LSHLCONST:
2351 case ICMD_LSHRCONST:
2352 case ICMD_LUSHRCONST:
2354 case ICMD_IFEQ_ICONST:
2355 case ICMD_IFNE_ICONST:
2356 case ICMD_IFLT_ICONST:
2357 case ICMD_IFGE_ICONST:
2358 case ICMD_IFGT_ICONST:
2359 case ICMD_IFLE_ICONST:
2364 case ICMD_INT2SHORT:
2382 case ICMD_CHECKCAST:
2384 case ICMD_ARRAYLENGTH:
2385 case ICMD_INSTANCEOF:
2388 case ICMD_ANEWARRAY:
2391 lsra_from_stack(ls, src,b_index,iindex);
2392 lsra_new_stack(ls,dst,b_index,iindex);
2397 case ICMD_GETSTATIC:
2401 lsra_new_stack(ls,dst,b_index,iindex);
2404 /* pop many push any */
2405 case ICMD_INVOKEVIRTUAL:
2406 case ICMD_INVOKESPECIAL:
2407 case ICMD_INVOKESTATIC:
2408 case ICMD_INVOKEINTERFACE:
2412 lsra_from_stack(ls, src,b_index,iindex);
2415 if (((methodinfo*)iptr->val.a)->returntype != TYPE_VOID) {
2416 lsra_new_stack(ls,dst,b_index,iindex);
2422 lsra_from_stack(ls, src,b_index,iindex);
2425 lsra_from_stack(ls, src,b_index,iindex);
2428 lsra_from_stack(ls, src,b_index,iindex);
2429 src = src->prev; /* ??????????? */
2430 if (iptr->op1 != TYPE_VOID)
2431 lsra_new_stack(ls,dst,b_index,iindex);
2434 case ICMD_MULTIANEWARRAY:
2437 lsra_from_stack(ls, src,b_index,iindex);
2440 lsra_new_stack(ls,dst,b_index,iindex);
2444 printf("ICMD %d at %d\n", iptr->opc, (int)(iptr - m->instructions));
2445 panic("Missing ICMD code during register allocation");
2449 } /* while instructions */
2452 dup_join(ls, &dup, b_index);
2455 } /* while blocks */
2459 * These are local overrides for various environment variables in Emacs.
2460 * Please do not remove this and leave it at the end of the file, where
2461 * Emacs will automagically detect them.
2462 * ---------------------------------------------------------------------
2465 * indent-tabs-mode: t