1 /* src/vm/jit/lsra.inc - linear scan register allocator
3 Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4 R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5 C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6 Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 Contact: cacao@complang.tuwien.ac.at
27 Authors: Christian Ullrich
29 $Id: lsra.inc 3028 2005-07-13 11:41:53Z twisti $
36 #include "mm/memory.h"
37 #include "vm/options.h"
38 #include "vm/jit/lsra.h"
39 #include "vm/jit/reg.h"
40 #include "vm/statistics.h"
42 bool lsra(methodinfo *m, codegendata *cd, registerdata *rd, t_inlining_globals *id)
46 #if defined(STATISTICS)
50 #if defined(LSRA_DEBUG) || defined(LSRA_LEAF)
51 char name[1256], name1[1256];
54 #if defined(LSRA_DEBUG)
60 while (b_index < m->basicblockcount ) {
62 if (m->basicblocks[b_index].flags >= BBREACHED) {
64 in=m->basicblocks[b_index].instack;
65 ind=m->basicblocks[b_index].indepth;
66 for (;ind != 0;in=in->prev, ind--) {
67 if (in->varkind == ARGVAR) printf("ARGVAR in instack: \n"); /*ARGVAR in instack ok*/
68 if (in->varkind == LOCALVAR) printf("LOCALVAR in instack\n");
70 out=m->basicblocks[b_index].outstack;
71 outd=m->basicblocks[b_index].outdepth;
72 for (;outd != 0;out=out->prev, outd--) {
73 if (out->varkind == ARGVAR) { log_text("ARGVAR in outstack\n"); assert(0); }
74 if (out->varkind == LOCALVAR) { log_text("LOCALVAR in outstack\n"); assert(0); }
81 #if defined(LSRA_DEBUG) || defined(LSRA_LEAF)
82 utf_sprint(name, m->class->name);
83 utf_sprint(name1, m->name);
86 utf_sprint(name1, m->descriptor);
90 printf("/******************************************************/\n");
95 /* printf("LSRA Start for %s opt_from: %i opt_to: %i\n", name, opt_from, opt_to); */
97 if (strcmp(name,"java/lang/ClassLoader.defaultGetSystemClassLoader()Ljava/lang/ClassLoader;")==0) {
98 printf("-------------------\n");
101 printf("**Leafmethod**\n");
106 lsra_init(m, cd, id, ls);
109 #if defined(LSRA_USES_REG_RES)
110 for (i=opt_from; i<=opt_to; i++) {
111 icmd_uses_reg_res[i][0]=S|D|YES;
112 icmd_uses_reg_res[i][1]=S|D|YES;
113 icmd_uses_reg_res[i][2]=S|D|YES;
114 icmd_uses_reg_res[i][3]=REG_NULL;
120 if (!lsra_setup(m, cd, rd, ls))
124 #if defined(STATISTICS)
125 /* find conflicts between locals for statistics */
127 /* local Variable Lifetimes are at the end of the lifetime array and have v_index >= 0 */
128 for (locals_start = ls->lifetimecount-1; (locals_start >=0) && (ls->lifetime[ls->lt_used[locals_start]].v_index >= 0); locals_start--);
129 for (i=locals_start + 1; i < ls->lifetimecount; i++)
130 for (j=i+1; j < ls->lifetimecount; j++)
131 if ( !((ls->lifetime[ls->lt_used[i]].i_end < ls->lifetime[ls->lt_used[j]].i_start) || (ls->lifetime[ls->lt_used[j]].i_end<ls->lifetime[ls->lt_used[i]].i_start)) )
132 count_locals_conflicts += 2;
136 lsra_main(m, ls, rd, cd);
141 void lsra_DFS_(lsradata *ls, bool *mark, int bblock, int *n) {
147 for (p=ls->pred[bblock]; p != NULL; p=p->next)
148 lsra_DFS_(ls, mark, p->value, n);
149 ls->sorted[*n]=bblock;
154 void lsra_DFS(methodinfo *m, lsradata *ls) {
158 mark=DMNEW(bool, m->basicblockcount);
159 n=m->basicblockcount;
161 for (i=0; i <= m->basicblockcount; i++) mark[i]=false;
163 lsra_DFS_(ls, mark, m->basicblockcount, &n);
167 void lsra_DFS_2(methodinfo *m, lsradata *ls) {
175 stack = DMNEW( int, m->basicblockcount + 1);
176 visited = DMNEW( bool, m->basicblockcount + 1);
177 for (i = 0; i <= m->basicblockcount; i++) {
180 ls->sorted_rev[i]=-1;
183 stack[0] = 0; /* start with Block 0 */
185 visited[0] = ls->num_pred[0]; /* Start Block is handled right and can be put in sorted */
186 p = 0; /*m->basicblockcount;*/
188 while (not_finished) {
189 while (stack_top != 0) {
191 i = stack[stack_top];
194 for (succ = ls->succ[i]; succ != NULL; succ = succ->next) {
195 visited[succ->value]++;
196 if (visited[succ->value] == ls->num_pred[succ->value]) {
197 /* push the node on the stack, only if all ancestors have been visited */
198 stack[stack_top] = succ->value;
203 not_finished = false;
204 for (i=1; i <= m->basicblockcount; i++) {
205 /* search for visited blocks, which have not reached the num_pred */
206 /* and put them on the stack -> happens with backedges */
207 if ((visited[i] != 0) && (visited[i] < ls->num_pred[i])) {
208 stack[stack_top] = i;
210 visited[i] = ls->num_pred[i];
218 void lsra_get_backedges( methodinfo *m, lsradata *ls) {
219 struct _list **next, *s;
221 struct _backedge *_backedges;
226 /* todofirst remove artificial end basicblock from ls->sorted, succ and pred */
228 for (i=0; i < m->basicblockcount; i++) {
229 for (next=&(ls->succ[i]); *next != NULL; next=&((*next)->next)) {
230 if ( (*next)->value == m->basicblockcount ) { /* artificial end bb found */
231 *next = (*next)->next;
232 if (*next == NULL) break;
235 for (next=&(ls->pred[i]); *next != NULL; next=&((*next)->next)) {
236 if ( (*next)->value == m->basicblockcount ) { /* artificial end bb found */
237 *next = (*next)->next;
238 if (*next == NULL) break;
242 if (ls->sorted[i] == m->basicblockcount) j=i;
245 for (i=j+1; i <= m->basicblockcount; i++)
246 ls->sorted[i-1]=ls->sorted[i];
247 for (i=0; i < m->basicblockcount; i++)
248 if (ls->sorted[i] != -1)
249 ls->sorted_rev[ls->sorted[i]]=i;
250 /* now look for backedges */
251 ls->backedge_count = 0;
252 for(i=0; i < m->basicblockcount; i++) {
253 if (ls->sorted[i] != -1)
254 for(s=ls->succ[ls->sorted[i]]; s != NULL; s=s->next) {
255 if (i >= ls->sorted_rev[s->value]) {
256 n=DNEW(struct _backedge);
257 n->start = max(i, ls->sorted_rev[s->value]);
258 n->end = min(i, ls->sorted_rev[s->value]);
259 n->next = _backedges;
261 ls->backedge_count++;
262 /* printf("Backedge: %i %i\n", ls->sorted[i], s->value); */
266 /* put _backedges in ls->backedge array */
267 ls->backedge = DMNEW(struct _backedge *, ls->backedge_count);
268 for (n=_backedges, i=0; n != NULL; n=n->next, i++)
270 /* union backedges? */
271 /* - sort backedge by increasing start: */
272 /* printf("unsorted: \n"); */
273 /* for (i=0; i < ls->backedge_count; i++) */
274 /* 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); */
275 for (i=0; i < ls->backedge_count; i++)
276 for (j=i+1; j < ls->backedge_count; j++)
277 if (ls->backedge[i]->start > ls->backedge[j]->start) { /* -> swap */
279 ls->backedge[i]=ls->backedge[j];
282 /* create ls->nesting */
283 for (i=0; i < ls->backedge_count; i++)
284 for (j=ls->backedge[i]->end; j<=ls->backedge[i]->start; j++)
287 printf("sorted: \n");
288 for (i=0; i < ls->backedge_count; i++)
289 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);
290 printf("Nesting Level \n");
291 for (i=0; i<m->basicblockcount; i++) printf(" %3li", ls->nesting[i]);
294 /* - merge overlapping backedges */
295 for (i=0; i < ls->backedge_count-1; i++)
296 if (ls->backedge[i]->start >= ls->backedge[i+1]->end) {/* overlapping -> merge */
297 /* ls->backedge[i+1]->start = ls->backedge[i]->start; */
298 ls->backedge[i+1]->end = min (ls->backedge[i+1]->end, ls->backedge[i]->end);
299 ls->backedge[i] = NULL;
302 printf("merged: \n");
303 for (i=0; i < ls->backedge_count; i++)
304 if (ls->backedge[i] != NULL)
305 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);
307 /* - remove backedge[] == NULL from array */
309 for ( j = ls->backedge_count -1; ((j>=0) && ( ls->backedge[j] == NULL)); j--);
312 if (ls->backedge[i] == NULL) { /* swap be[i] mit be[j] */
314 ls->backedge[j] = ls->backedge[i];
318 ls->backedge_count--;
323 for (i=0; i < ls->backedge_count; i++)
324 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);
328 void lsra_add_cfg( methodinfo *m, lsradata *ls, int from, int to) {
331 for (;(to < m->basicblockcount) && (m->basicblocks[to].flags < BBREACHED); to++);
333 for (n=ls->succ[from]; (n!= NULL) && (n->value != to); n=n->next);
334 if (n != NULL) return; /* edge from->to already existing */
336 n=DNEW(struct _list);
339 n->next=ls->succ[from];
342 n=DNEW(struct _list);
344 n->next=ls->pred[to];
349 void lsra_add_exceptions(methodinfo *m, codegendata *cd, lsradata *ls) {
352 /* add cfg edges from all bb of a try block to the start of the according exception handler */
353 /* to ensure the right order after depthfirst search */
355 ex=cd->exceptiontable;
357 printf("ExTable(%i): ", cd->exceptiontablelength);
360 for (; ex != NULL; ex = ex->down) {
363 printf("[%i-%i]->%i ",ex->start->debug_nr, ex->end->debug_nr,ex->handler->debug_nr);
364 if (ex->handler->debug_nr >= m->basicblockcount)
365 { log_text("Exceptionhandler Basicblocknummer invalid\n"); assert(0); }
366 if (m->basicblocks[ex->handler->debug_nr].flags < BBREACHED)
367 { log_text("Exceptionhandler Basicblocknummer not reachable\n"); assert(0); }
368 if (ex->start->debug_nr > ex->end->debug_nr)
369 { log_text("Guarded Area starts after its end\n"); assert(0); }
371 /* loop all valid Basic Blocks of the guarded area and add CFG edges to the appropriate handler */
372 for (i=ex->start->debug_nr; (i <= ex->end->debug_nr) && (i < m->basicblockcount); i++)
373 if (m->basicblocks[i].flags >= BBREACHED)
374 lsra_add_cfg(m, ls, i, ex->handler->debug_nr);
381 void lsra_add_jsr( methodinfo *m, lsradata *ls, int from, int to) {
382 struct _sbr *sbr, *n;
385 for (; (to < m->basicblockcount) && (m->basicblocks[to].flags < BBREACHED); to++);
387 if (to == m->basicblockcount)
388 { log_text("Invalid subroutine start index\n"); assert(0); }
391 lsra_add_cfg(m, ls, from, to);
393 for (from++; (from < m->basicblockcount) && (m->basicblocks[from].flags < BBREACHED); from++);
395 if (from == m->basicblockcount)
396 { log_text("Invalid return basic block index for jsr\n"); assert(0); }
399 /* add subroutine info in ls->sbr.next */
401 /* search for right place to insert */
402 for (sbr = &(ls->sbr); (sbr->next != NULL) && (sbr->next->header < to); sbr=sbr->next);
404 if ((sbr->next!= NULL) && (sbr->next->header == to)) {
405 /* Entry for this sub already exist */
408 /* make new Entry and insert it in ls->sbr.next */
409 n = DNEW( struct _sbr );
419 /* now insert return adress in sbr->ret */
420 ret = DNEW( struct _list);
422 ret->next = sbr->ret;
426 void lsra_add_sub( methodinfo *m, lsradata *ls, int b_index, struct _list *ret ) {
433 if (m->basicblocks[b_index].flags < BBREACHED)
435 if (!next_block && !(m->basicblocks[b_index].icount))
439 ip = m->basicblocks[b_index].iinstr + m->basicblocks[b_index].icount -1;
441 if (ip->opc == ICMD_JSR) /* nested Subroutines */
446 if (ip->opc == ICMD_RET) { /* subroutine return found -> add return adresses to CFG */
447 for (l = ret; l != NULL; l = l->next)
448 lsra_add_cfg( m, ls, b_index, l->value);
449 } else { /* follow CFG */
450 for ( l = ls->succ[b_index]; l != NULL; l = l->next)
451 lsra_add_sub( m, ls, l->value, ret);
453 } else { /* fall through to next block */
454 lsra_add_sub(m, ls, b_index+1, ret);
458 void lsra_add_subs(methodinfo *m, lsradata *ls) {
464 for (sbr = ls->sbr.next; sbr != NULL; sbr=sbr->next) {
466 printf("Subroutine Header: %3i Return Adresses:",sbr->header);
467 for (ret = sbr->ret; ret != NULL; ret = ret->next)
468 printf(" %3i", ret->value);
471 lsra_add_sub( m, ls, sbr->header, sbr->ret );
476 void lsra_make_cfg(methodinfo *m, lsradata *ls)
480 int high, low, count;
484 while (b_index < m->basicblockcount ) {
485 if (m->basicblocks[b_index].flags >= BBREACHED) {
486 ip = m->basicblocks[b_index].iinstr + m->basicblocks[b_index].icount -1;
487 /* set ip to last instruction */
489 if (m->basicblocks[b_index].icount) {
490 /* block contains instructions */
491 switch (ip->opc) { /* check type of last instruction */
500 lsra_add_cfg(m, ls, b_index, m->basicblockcount);
502 break; /* function returns -> end of graph */
531 case ICMD_IF_ACMPNE: /* branch -> check next block */
532 lsra_add_cfg(m, ls, b_index, b_index+1);
536 lsra_add_cfg(m, ls, b_index, m->basicblockindex[ip->op1]);
537 break; /* visit branch (goto) target */
539 case ICMD_TABLESWITCH: /* switch statement */
542 lsra_add_cfg(m, ls, b_index, m->basicblockindex[*s4ptr]);
549 count = (high-low+1);
551 while (--count >= 0) {
553 lsra_add_cfg(m, ls, b_index, m->basicblockindex[*s4ptr]);
557 case ICMD_LOOKUPSWITCH: /* switch statement */
560 lsra_add_cfg(m, ls, b_index, m->basicblockindex[*s4ptr]);
565 while (--count >= 0) {
566 lsra_add_cfg(m, ls, b_index, m->basicblockindex[s4ptr[1]]);
572 lsra_add_jsr(m, ls, b_index, m->basicblockindex[ip->op1]);
579 lsra_add_cfg(m, ls, b_index, b_index + 1 );
581 } /* switch (ip->opc)*/
582 } /* if (m->basicblocks[blockIndex].icount) */
583 } /* if (m->basicblocks[b_index].flags >= BBREACHED) */
585 } /* while (b_index < m->basicblockcount ) */
591 void lsra_init(methodinfo *m, codegendata *cd, t_inlining_globals *id, lsradata *ls)
595 /* Init LSRA Data Structures */
596 /* lifetimes für alle Basicblocks allokieren */
597 ls->pred = DMNEW(struct _list *, m->basicblockcount+1); /* + 1 for a artificial exit node */
598 ls->succ = DMNEW(struct _list *, m->basicblockcount+1); /* + 1 for a artificial exit node */
599 ls->sorted = DMNEW(int , m->basicblockcount+1); /* + 1 for a artificial exit node */
600 ls->sorted_rev = DMNEW(int , m->basicblockcount+1); /* + 1 for a artificial exit node */
601 ls->num_pred = DMNEW(int , m->basicblockcount+1); /* + 1 for a artificial exit node */
602 ls->nesting = DMNEW(long , m->basicblockcount);
603 for (i=0; i<m->basicblockcount; i++) {
607 ls->sorted_rev[i]=-1;
611 ls->pred[m->basicblockcount]=NULL;
612 ls->succ[m->basicblockcount]=NULL;
613 ls->sorted[m->basicblockcount]=-1;
614 ls->sorted_rev[m->basicblockcount]=-1;
615 ls->num_pred[m->basicblockcount]=0;
617 /* ls->ss_lifetimes=NULL; */
619 if (cd->maxlocals != id->cumlocals) { log_text("lsra: Welche locals nehmen?\n"); assert(0); }
622 ls->maxlifetimes = m->maxlifetimes;
623 ls->lifetimecount = ls->maxlifetimes + cd->maxlocals * (TYPE_ADR+1);
624 ls->lifetime = DMNEW(struct lifetime, ls->lifetimecount);
625 ls->lt_used = DMNEW(int, ls->lifetimecount);
627 ls->lt_int_count = 0;
629 ls->lt_flt_count = 0;
631 ls->lt_rest_count = 0;
632 for (i=0; i < ls->lifetimecount; i++) ls->lifetime[i].type = -1;
640 bool lsra_test(methodinfo *m, codegendata *cd)
649 /* in case of exceptionhandlers or subroutines return to regalloc */
650 if (cd->exceptiontablelength > 0)
656 for (i=0; i< m->basicblockcount; i++) {
657 ip = m->basicblocks[i].iinstr + m->basicblocks[i].icount -1;/* set ip to last instruction */
658 if (ip->opc == ICMD_JSR) {
659 /* check Instack of sub */
660 /* printf("SBR Instackdepth: %3i\n",m->basicblocks[m->basicblockindex[ip->op1]].indepth);*/
668 bool lsra_setup(methodinfo *m, codegendata *cd, registerdata *rd, lsradata *ls)
677 #ifdef LSRA_DUMP_LOOPDATA
678 struct LoopContainer *lc;
679 struct LoopElement *le;
682 /* in case of exceptionhandlers or subroutines return to regalloc */
683 #if (! (defined(LSRA_DO_SR) && defined(LSRA_DO_EX)) )
684 if (!lsra_test(m,cd))
688 /* Setup LSRA Data structures */
692 lsra_make_cfg(m, ls);
694 lsra_add_subs(m, ls); /* add subroutines before exceptions! They "destroy" the CFG */
695 lsra_add_exceptions(m, cd, ls);
699 lsra_get_backedges( m, ls);
701 printf("Successors:\n");
702 for (i=0; i < m->basicblockcount; i++) {
704 for (nl=ls->succ[i]; nl!= NULL; nl=nl->next)
705 printf("%3i ",nl->value);
708 printf("Predecessors:\n");
709 for (i=0; i < m->basicblockcount; i++) {
711 for (nl=ls->pred[i]; nl!= NULL; nl=nl->next)
712 printf("%3i ",nl->value);
716 for (i=0; i < m->basicblockcount; i++) printf("%3i ", ls->sorted[i]);
718 printf("Sorted_rev: ");
719 for (i=0; i < m->basicblockcount; i++) printf("%3i ", ls->sorted_rev[i]);
725 /* sicherheitshalber Konsistenz von m->basicblocks[..] mit basicblocks->next (Liste) überprüfen */
726 printf("LSRA bb prüfen\n");
728 bptr = m->basicblocks;
729 while (bptr != NULL) {
730 if (i > m->basicblockcount){
731 { log_text("linked bb list does not correspond with bb array(1)\n"); assert(0); }
733 if (bptr != &(m->basicblocks[i])){
734 { log_text("linked bb list does not correspond with bb array(2)\n"); assert(0); }
740 if (i<m->basicblockcount){
741 { log_text("linked bb list does not correspond with bb array(3)\n"); assert(0); }
748 for (i=m->basicblockcount-1; i >= 0; i--) {
749 if (ls->sorted[i] != -1) {
750 lsra_scan_registers_canditates(m, ls, ls->sorted[i]);
751 lsra_join_lifetimes(m, ls, ls->sorted[i]);
755 /* Parameter initialisiation for locals 0 .. paramcount */
756 /* Parameter initialisieren == local Vars readaccess at 0,-1*/
758 for (p = 0, i = 0; p < m->paramcount; p++) {
759 t = m->paramtypes[p];
761 if (rd->locals[i][t].type >= 0)
762 lsra_usage_local(ls, i, t, 0, -1, LSRA_STORE); /* Param to Local init happens before normal Code */
764 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
768 lsra_calc_lifetime_length(m, ls, cd);
770 #ifdef LSRA_PRINTLIFETIMES
771 printf("Basicblockcount: %4i Max Instr/BB: %4i\n",m->basicblockcount, ls->icount_max);
772 /* print_lifetimes(rd, ls, ls->lt_used, ls->lifetimecount); */
777 bool lsra_join_ss( struct lsradata *ls, struct stackelement *in, struct stackelement *out, int join_flag) {
778 struct lifetime *lt, *lto;
779 struct stackslot *ss, *ss_last;
782 if (in->varnum != out->varnum) {
783 lt = &(ls->lifetime[-in->varnum - 1]);
786 if (join_flag == JOIN_BB)
787 if (lt->type == -1) { log_text("lsra_join_ss: lifetime for instack not found\n"); assert(0); }
789 #if 0 /* was once upon a time */
790 if (lt->type == -1) /* lifetime was assigned a REG_RES and has been thrown away */
794 if (out->varnum >= 0) { /* no lifetime for this slot till now */
795 lsra_add_ss(lt, out);
798 lto = &(ls->lifetime[-out->varnum - 1]);
800 if ((join_flag == JOIN_DUP) || (join_flag == JOIN_OP))
801 if ( (lt->flags & JOIN_BB) || (lto->flags & JOIN_BB)) {
803 printf("DUP or OP join rejected for JOIN_BB Lifetime: v_index1 %3i v_index2 %3i\n",in->varnum, out->varnum);
807 if (join_flag == JOIN_DUP)
808 if ( (lt->flags & JOIN_OP) || (lto->flags & JOIN_OP)) {
810 printf("DUP join rejected for JOIN_OP Lifetime: v_index1 %3i v_index2 %3i\n",in->varnum, out->varnum);
814 /* if (join_flag == JOIN_OP) */
815 /* if ( (lt->flags & JOIN_DUP) || (lto->flags & JOIN_DUP)) { */
816 /* #ifdef LSRA_DEBUG */
817 /* printf("OP join rejected for JOIN_DUP Lifetime: v_index1 %3i v_index2 %3i\n",in->varnum, out->varnum); */
822 #if 0 /* was once upon a time */
823 if (join_flag == JOIN_BB)
825 if (lto->type == -1) { log_text("lsra_join_ss: lifetime for outstack not found\n"); assert(0); }
827 #if 0 /* was once upon a time */
828 if (lto->type == -1) /* lifetime was assigned a REG_RES and has been thrown away */
832 if (lto->type != lt->type) { log_text("lsra_join_ss: in/out stack type mismatch\n"); assert(0); }
836 lt->flags |= JOINING;
838 /* take Lifetime lto out of ls->lifetimes */
841 /* merge lto into lt of in */
843 ss_last = ss = lto->local_ss;
846 ss->s->varnum = lt->v_index;
849 if (ss_last != NULL) {
850 ss_last->next = lt->local_ss;
851 lt->local_ss = lto->local_ss;
853 lt->savedvar |= lto->savedvar;
854 lt->flags |= lto->flags | join_flag;
855 lt->usagecount += lto->usagecount;
857 /*join of bb_first_def, i_first_def und *_last_use */
858 if (lto->bb_first_def < lt->bb_first_def) {
859 lt->bb_first_def = lto->bb_first_def;
860 lt->i_first_def = lto->i_first_def;
861 } else if ((lto->bb_first_def == lt->bb_first_def) && ( lto->i_first_def < lt->i_first_def)) {
862 lt->i_first_def = lto->i_first_def;
864 if (lto->bb_last_use > lt->bb_last_use) {
865 lt->bb_last_use = lto->bb_last_use;
866 lt->i_last_use = lto->i_last_use;
867 } else if ((lto->bb_last_use == lt->bb_last_use) && ( lto->i_last_use > lt->i_last_use)) {
868 lt->i_last_use = lto->i_last_use;
875 /* join instack of Basic Block b_index with outstack of predecessors */
876 void lsra_join_lifetimes(methodinfo *m, lsradata *ls, int b_index) {
877 struct stackelement *in, *i, *out;
880 /* do not join instack of Exception Handler */
881 if (m->basicblocks[b_index].type == BBTYPE_EXH)
883 in=m->basicblocks[b_index].instack;
884 if (m->basicblocks[b_index].type == BBTYPE_SBR)
885 in=in->prev; /* do not join first instack element of a subroutine header */
888 for (pred = ls->pred[b_index]; pred != NULL; pred = pred->next) {
889 out = m->basicblocks[pred->value].outstack;
890 for (i=in; (i != NULL); i = i->prev, out=out->prev) {
891 lsra_join_ss(ls, i, out, JOIN_BB);
897 void lsra_reg_setup(methodinfo *m ,registerdata *rd, struct lsra_register *int_reg,struct lsra_register *flt_reg ) {
898 int i, j, iarg, farg;
904 bool *fltarg_used, *intarg_used;
906 int_reg->nregdesc = nregdescint;
907 flt_reg->nregdesc = nregdescfloat;
908 if (m->isleafmethod) {
909 /* Temp and Argumentregister can be used as "saved" registers */
911 int_reg->sav_top = INT_ARG_CNT + INT_TMP_CNT + INT_SAV_CNT;
912 int_reg->sav_reg = DMNEW(int, int_reg->sav_top);
913 int_reg->tmp_reg = NULL;
914 int_reg->tmp_top = -1;
915 flt_reg->sav_top = FLT_ARG_CNT + FLT_TMP_CNT + FLT_SAV_CNT;
916 flt_reg->sav_reg = DMNEW(int, flt_reg->sav_top);
917 flt_reg->tmp_reg = NULL;
918 flt_reg->tmp_top = -1;
921 /* additionaly precolour registers for Local Variables acting as Parameters */
926 intarg_used = DMNEW(bool, INT_ARG_CNT);
927 for (i=0; i < INT_ARG_CNT; i++)
928 intarg_used[i]=false;
930 fltarg_used = DMNEW(bool, FLT_ARG_CNT);
931 for (i=0; i < FLT_ARG_CNT; i++)
932 fltarg_used[i]=false;
934 int_sav_top=int_reg->sav_top;
935 flt_sav_top=flt_reg->sav_top;
941 printf("Paramcount: %i ", m->paramcount);
943 for (i=0; (i < m->paramcount) && ((farg < FLT_ARG_CNT) ||(iarg < INT_ARG_CNT) ); i++) {
945 printf("Type %3i %3i", i, m->paramtypes[i]);
947 switch (m->paramtypes[i]) {
950 #if !defined(__I386__)
951 case TYPE_LNG: /* i386->longs stay in Memory */
954 #ifndef CONSECUTIVE_FLOAT_ARGS
957 if (rd->locals[localindex][m->paramtypes[i]].type >= 0)
958 if (iarg < INT_ARG_CNT) {
959 int_reg->sav_reg[--int_sav_top]=rd->argintregs[iarg];
960 intarg_used[iarg]=true; /* used -> don't copy later on */
964 #if !defined(__I386__)
965 case TYPE_DBL: /* i386->longs stay in Memory */
968 #ifndef CONSECUTIVE_INTEGER_ARGS
971 if (rd->locals[localindex][m->paramtypes[i]].type >= 0)
972 if (farg < FLT_ARG_CNT) {
973 flt_reg->sav_reg[--flt_sav_top]=rd->argfltregs[farg];
974 fltarg_used[farg]=true; /* used -> don't copy later on */
978 if ( IS_2_WORD_TYPE(m->paramtypes[i]))
986 /* copy rest of argument registers to flt_reg->sav_reg and int_reg->sav_reg; */
987 for (i=0; i < INT_ARG_CNT; i++)
989 int_reg->sav_reg[--int_sav_top]=rd->argintregs[i];
990 for (i=0; i < FLT_ARG_CNT; i++)
992 flt_reg->sav_reg[--flt_sav_top]=rd->argfltregs[i];
994 /* copy temp registers to flt_reg->sav_reg and int_reg->sav_reg */
995 for (i=0; i < INT_TMP_CNT; i++)
996 int_reg->sav_reg[--int_sav_top]=rd->tmpintregs[i];
997 for (i=0; i < FLT_TMP_CNT; i++)
998 flt_reg->sav_reg[--flt_sav_top]=rd->tmpfltregs[i];
1001 /* non leaf method -> use Argument Registers [arg[int|flt]reguse ... [int|flt]reg_argnum[ as temp reg */
1002 /* divide temp and saved registers */
1003 int_sav_top = int_reg->sav_top = INT_SAV_CNT;
1004 int_reg->sav_reg = DMNEW(int, int_reg->sav_top);
1005 int_reg->tmp_top = INT_TMP_CNT + max(0, (INT_ARG_CNT - rd->argintreguse));
1006 int_reg->tmp_reg = DMNEW(int, int_reg->tmp_top);
1008 flt_sav_top =flt_reg->sav_top = FLT_SAV_CNT;
1009 flt_reg->sav_reg = DMNEW(int, flt_reg->sav_top);
1010 flt_reg->tmp_top = FLT_TMP_CNT + max(0 , (FLT_ARG_CNT - rd->argfltreguse));
1011 flt_reg->tmp_reg = DMNEW(int, flt_reg->tmp_top);
1013 /* copy temp and unused argument registers to flt_reg->tmp_reg and int_reg->tmp_reg */
1014 for (i=0; i < INT_TMP_CNT; i++)
1015 int_reg->tmp_reg[i]=rd->tmpintregs[i];
1016 for (j=rd->argintreguse; j < INT_ARG_CNT; j++, i++)
1017 int_reg->tmp_reg[i]=rd->argintregs[j];
1018 for (i=0; i < FLT_TMP_CNT; i++)
1019 flt_reg->tmp_reg[i]=rd->tmpfltregs[i];
1020 for (j=rd->argfltreguse; j < FLT_ARG_CNT; j++, i++)
1021 flt_reg->tmp_reg[i]=rd->argfltregs[j];
1024 /* now copy saved registers to flt_reg->sav_reg and int_reg->sav_reg */
1025 for (i = INT_SAV_CNT-1; i >= 0; i--)
1026 int_reg->sav_reg[--int_sav_top]=rd->savintregs[i];
1027 for (i = FLT_SAV_CNT-1; i >= 0; i--)
1028 flt_reg->sav_reg[--flt_sav_top]=rd->savfltregs[i];
1032 void lsra_insertion( struct lsradata *ls, int *a, int lo, int hi) {
1035 for (i=lo+1; i<=hi; i++) {
1037 t=ls->lifetime[a[j]].i_start;
1039 while ((j>lo) && (ls->lifetime[a[j-1]].i_start > t)) {
1040 /* ls->lifetime[a[j]].i_start = ls->lifetime[a[j-1]].i_start; */
1045 /* ls->lifetime[a[j]].i_start=t; */
1049 void lsra_qsort( struct lsradata *ls, int *a, int lo, int hi) {
1055 x = ls->lifetime[a[(lo+hi)/2]].i_start;
1059 while (ls->lifetime[a[i]].i_start < x) i++;
1060 while (ls->lifetime[a[j]].i_start > x) j--;
1062 /* exchange a[i], a[j] */
1072 if (lo < j) lsra_qsort( ls, a, lo, j);
1073 if (i < hi) lsra_qsort( ls, a, i, hi);
1075 lsra_insertion(ls, a, lo, hi);
1079 void lsra_param_sort(struct lsradata *ls, int *lifetime, int lifetime_count) {
1084 /* count number of parameters ( .i_start == -1) */
1085 for (param_count=0; (param_count < lifetime_count) && (ls->lifetime[lifetime[param_count]].i_start == -1); param_count++);
1087 if (param_count > 0) {
1088 /* now sort the parameters by v_index */
1089 for (i=0; i < param_count -1; i++)
1090 for (j=i+1; j < param_count; j++)
1091 if ( ls->lifetime[lifetime[i]].v_index > ls->lifetime[lifetime[j]].v_index) {
1094 lifetime[i]=lifetime[j];
1100 void lsra_main(methodinfo *m, lsradata *ls, registerdata *rd, codegendata *cd)
1102 struct lifetime *lt;
1107 int flags; /* 0 INMEMORY-> ls->lt_rest, 1 INTREG-> ls->lt_int, 2 FLTREG-> ls->lt_flt */
1109 struct lsra_register flt_reg, int_reg;
1114 /* first split lifetimes for integer and float registers */
1116 ls->lt_int = DMNEW(int, ls->lifetimecount); /* todo: do count and split of int/float lifetimes already in lsra_calc_lifetimelength! */
1117 ls->lt_flt = DMNEW(int, ls->lifetimecount);
1118 ls->lt_rest = DMNEW(int, ls->lifetimecount);
1119 ls->lt_int_count = 0;
1120 ls->lt_flt_count = 0;
1121 ls->lt_rest_count = 0;
1124 for (lt_used_index = 0; lt_used_index < ls->lifetimecount; lt_used_index ++) {
1125 lt = &(ls->lifetime[ls->lt_used[lt_used_index]]);
1130 #if defined(HAS_4BYTE_STACKSLOT)
1132 * for i386 put all longs in memory
1134 /* for PowerPC for now into memory, too (ignore SUPPORT_COMBINE_INTEGER_REGISTERS)*/
1144 #if defined(__I386__)
1146 * for i386 put all floats in memory
1154 { log_text("Unknown Type\n"); assert(0); }
1158 case 0: /* lt_used[lt_used_index] -> lt_rest */
1159 ls->lt_rest[ ls->lt_rest_count++ ] = ls->lt_used[lt_used_index];
1161 case 1: /* l->lifetimes -> lt_int */
1162 ls->lt_int[ ls->lt_int_count++ ] = ls->lt_used[lt_used_index];
1164 case 2: /* l->lifetimes -> lt_flt */
1165 ls->lt_flt[ ls->lt_flt_count++ ] = ls->lt_used[lt_used_index];
1170 lsra_qsort( ls, ls->lt_rest, 0, ls->lt_rest_count - 1);
1171 lsra_qsort( ls, ls->lt_int, 0, ls->lt_int_count - 1);
1172 lsra_qsort( ls, ls->lt_flt, 0, ls->lt_flt_count - 1);
1174 lsra_param_sort( ls, ls->lt_int, ls->lt_int_count);
1175 lsra_param_sort( ls, ls->lt_flt, ls->lt_flt_count);
1177 lsra_reg_setup(m, rd, &int_reg, &flt_reg);
1180 printf("INTSAV REG: ");
1181 for (i=0; i<int_reg.sav_top; i++)
1182 printf("%2i ",int_reg.sav_reg[i]);
1183 printf("\nINTTMP REG: ");
1184 for (i=0; i<int_reg.tmp_top; i++)
1185 printf("%2i ",int_reg.tmp_reg[i]);
1186 printf("\nFLTSAV REG: ");
1187 for (i=0; i<flt_reg.sav_top; i++)
1188 printf("%2i ",flt_reg.sav_reg[i]);
1189 printf("\nFLTTMP REG: ");
1190 for (i=0; i<flt_reg.tmp_top; i++)
1191 printf("%2i ",flt_reg.tmp_reg[i]);
1194 lsra_reg_use=INT_SAV_CNT;
1195 _lsra_main(m, ls, ls->lt_int, ls->lt_int_count, &int_reg, &lsra_reg_use);
1196 if (lsra_reg_use > INT_SAV_CNT) lsra_reg_use=INT_SAV_CNT;
1197 rd->savintreguse= lsra_reg_use;
1199 lsra_reg_use=FLT_SAV_CNT;
1201 _lsra_main(m,ls, ls->lt_flt, ls->lt_flt_count, &flt_reg, &lsra_reg_use);
1202 if (lsra_reg_use > FLT_SAV_CNT) lsra_reg_use=FLT_SAV_CNT;
1204 rd->savfltreguse=lsra_reg_use;
1206 /* rd->memuse was already set in stack.c to allocate stack space for passing arguments to called methods */
1207 #if defined(__I386__)
1208 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
1209 /* reserve 0(%esp) for Monitorenter/exit Argument on i386 */
1215 lsra_mem_use = rd->memuse; /* Init with if_memuse from stack.c */
1218 printf("Alloc Rest\n");
1220 lsra_alloc(m, rd, ls, ls->lt_rest, ls->lt_rest_count,&lsra_mem_use);
1222 printf("Alloc Int\n");
1224 lsra_alloc(m, rd, ls, ls->lt_int, ls->lt_int_count, &lsra_mem_use);
1226 printf("Alloc Flt\n");
1228 lsra_alloc(m, rd, ls, ls->lt_flt, ls->lt_flt_count, &lsra_mem_use);
1230 #ifdef LSRA_PRINTLIFETIMES
1231 printf("Int RA complete \n");
1232 printf("Lifetimes after splitting int: \n");
1233 print_lifetimes(rd, ls, ls->lt_int, ls->lt_int_count);
1235 printf("Flt RA complete \n");
1236 printf("Lifetimes after splitting flt:\n");
1237 print_lifetimes(rd, ls, ls->lt_flt, ls->lt_flt_count);
1239 printf("Rest RA complete \n");
1240 printf("Lifetimes after leftt:\n");
1241 print_lifetimes(rd, ls, ls->lt_rest, ls->lt_rest_count);
1243 rd->memuse=lsra_mem_use;
1245 test_lifetimes(m, ls, rd );
1250 void lsra_alloc(methodinfo *m, registerdata *rd, struct lsradata *ls, int *lifet, int lifetimecount, int *mem_use)
1253 struct lifetime *lt;
1254 struct freemem *fmem;
1255 struct stackslot *n;
1257 #ifdef HAS_4BYTE_STACKSLOT
1258 struct freemem *fmem_2;
1261 fmem=DNEW(struct freemem);
1264 #ifdef HAS_4BYTE_STACKSLOT
1265 fmem_2=DNEW(struct freemem);
1270 /* for (lt=lifet;lt!=NULL;lt=lt->next) { */
1271 for (lt_index = 0; lt_index < lifetimecount; lt_index ++) {
1272 lt = &(ls->lifetime[lifet[lt_index]]);
1278 #ifdef HAS_4BYTE_STACKSLOT
1279 if (IS_2_WORD_TYPE(lt->type))
1280 regoff=lsra_getmem(lt, fmem_2, mem_use);
1283 regoff=lsra_getmem(lt, fmem, mem_use);
1289 if (lt->v_index < 0) {
1290 for (n=lt->local_ss; n!=NULL; n=n->next) {
1291 lsra_setflags( &(n->s->flags), flags);
1292 n->s->regoff=regoff;
1294 } else { /* local var */
1295 if (rd->locals[lt->v_index][lt->type].type>=0) {
1296 /* lsra_setflags( &(rd->locals[lt->v_index][lt->type].flags), flags); */
1297 rd->locals[lt->v_index][lt->type].flags= flags;
1298 rd->locals[lt->v_index][lt->type].regoff=regoff;
1299 } else { log_text("Type Data mismatch 1\n"); assert(0); }
1305 void lsra_setflags(int *flags, int newflags)
1307 if ( newflags & INMEMORY)
1310 *flags &= ~INMEMORY;
1312 if (newflags & SAVEDVAR)
1316 int lsra_getmem(struct lifetime *lt, struct freemem *fmem, int *mem_use)
1318 struct freemem *fm, *p;
1320 /* noch kein Speicher vergeben, oder alle Enden später */
1321 if ((fmem->next == NULL) || (fmem->next->end > lt->i_start)) {
1322 #ifdef HAS_4BYTE_STACKSLOT
1323 if (IS_2_WORD_TYPE(lt->type))
1324 if ( (*mem_use)&1 ) /* align memory location for 2 Word Types */
1326 fm=lsra_getnewmem(mem_use);
1327 if (IS_2_WORD_TYPE(lt->type)) /* allocate a second following Slot for 2 Word Types */
1330 fm=lsra_getnewmem(mem_use);
1333 /* Speicherstelle frei */
1335 fmem->next=fm->next;
1339 for (p=fmem; (p->next!=NULL) && (p->next->end < fm->end); p=p->next);
1345 struct freemem *lsra_getnewmem(int *mem_use)
1349 fm=DNEW(struct freemem);
1356 void _lsra_main( methodinfo *m, lsradata *ls, int *lifet, int lifetimecount, struct lsra_register *reg, int *reg_use)
1358 struct lifetime *lt;
1361 bool temp; /* reg from temp registers (true) or saved registers (false) */
1363 if ((reg->tmp_top+reg->sav_top) == 0) {
1364 /* for (lt=lifet; lt != NULL; lt=lt->next) */
1366 for (lt_index = 0; lt_index < lifetimecount; lt_index++)
1367 ls->lifetime[lifet[lt_index]].reg = -1;
1371 ls->active_tmp = NULL;
1372 ls->active_sav = NULL;
1374 /* for (lt=lifet; lt != NULL; lt=lt->next) { */
1375 for (lt_index = 0; lt_index < lifetimecount; lt_index++) {
1376 lt = &(ls->lifetime[lifet[lt_index]]);
1378 lsra_expire_old_intervalls(m, ls, lt, reg);
1381 if (lt->savedvar || m->isleafmethod) { /* -> use Saved Reg (in case of leafmethod all regs are "saved" regs) */
1382 if (reg->sav_top > 0) {
1383 reg_index = reg->sav_reg[--reg->sav_top];
1385 } else { /* use Temp Reg or if non free a Saved Reg */
1386 if (reg->tmp_top > 0) {
1388 reg_index = reg->tmp_reg[--reg->tmp_top];
1391 if (reg->sav_top > 0)
1392 reg_index = reg->sav_reg[--reg->sav_top];
1394 if (reg_index == -1) /* no reg is available anymore... -> spill */
1395 spill_at_intervall(m, ls, lt);
1397 lt->reg = reg_index;
1399 lsra_add_active(lt, &(ls->active_tmp));
1401 if (reg->sav_top<*reg_use) *reg_use=reg->sav_top;
1402 lsra_add_active(lt, &(ls->active_sav));
1408 void lsra_add_active(struct lifetime *lt, struct active_lt **active)
1410 struct active_lt *alt,*alt1,*alt2;
1411 alt=DNEW(struct active_lt);
1414 for(alt1=alt2=*active; alt1 != NULL; alt2=alt1, alt1=alt1->next)
1415 if (alt1->lt->i_end > lt->i_end) break;
1417 if (alt1 == *active) {
1418 alt->next = *active;
1421 alt->next = alt2->next;
1427 void lsra_expire_old_intervalls(methodinfo *m, lsradata *ls, struct lifetime *lt, struct lsra_register *reg)
1429 _lsra_expire_old_intervalls(m, lt, reg, &(ls->active_tmp));
1430 _lsra_expire_old_intervalls(m, lt, reg, &(ls->active_sav));
1433 void _lsra_expire_old_intervalls(methodinfo *m, struct lifetime *lt, struct lsra_register *reg, struct active_lt **active)
1435 struct active_lt *alt,*alt1;
1438 for (alt1=alt=*active; alt != NULL; alt1=alt, alt=alt->next) {
1439 if (alt->lt->i_end > lt->i_start) return;
1441 *active = (*active)->next;
1443 alt1->next=alt->next;
1445 /* make alt->lt->reg available again */
1446 if (m->isleafmethod) {
1447 /* leafmethod -> don't care about type -> put all again into reg->sav_reg */
1448 reg->sav_reg[reg->sav_top++] = alt->lt->reg;
1450 /* no leafmethod -> distinguish between temp and saved register */
1451 if ( reg->nregdesc[alt->lt->reg] == REG_SAV)
1452 reg->sav_reg[reg->sav_top++] = alt->lt->reg;
1454 reg->tmp_reg[reg->tmp_top++] = alt->lt->reg;
1459 void spill_at_intervall(methodinfo *m, lsradata *ls, struct lifetime *lt )
1461 if (lt->savedvar || m->isleafmethod)
1462 _spill_at_intervall(lt, &(ls->active_sav));
1464 _spill_at_intervall(lt, &(ls->active_tmp));
1465 if (lt->reg == -1) /* kein tmp mehr frei gewesen */
1466 _spill_at_intervall(lt, &(ls->active_sav));
1468 /* if (lt->reg == -2) { log_text("spill_at_intervall: Keine Register mehr frei gewesen!\n"); assert(0); } */
1471 void _spill_at_intervall(struct lifetime *lt, struct active_lt **active)
1473 struct active_lt *alt,*alt1;
1474 if (*active == NULL) {
1478 /* get last intervall from active */
1479 for (alt1=alt=*active; alt->next != NULL; alt1=alt, alt=alt->next);
1482 if ((alt->lt->i_end > lt->i_end) || (alt->lt->usagecount < lt->usagecount)) {
1484 if (alt->lt->i_end > lt->i_end) {
1486 lt->reg=alt->lt->reg;
1490 *active=(*active)->next;
1492 alt1->next=alt->next;
1493 lsra_add_active(lt, active);
1500 void lsra_calc_lifetime_length(methodinfo *m, lsradata *ls, codegendata *cd)
1502 struct lifetime *lt;
1505 /* struct stackslot *ss; */
1506 int *icount_block, icount;
1510 int cum_local_ss,local_ss_count;
1514 icount_block = DMNEW(int, m->basicblockcount);
1515 icount_block[0] = icount = 0;
1516 for (i=1; i < m->basicblockcount; i++) {
1517 if (ls->sorted[i-1] != -1)
1518 icount += m->basicblocks[ ls->sorted[i-1] ].icount;
1519 if (ls->sorted[i] != -1)
1520 icount_block[i] = icount;
1524 printf("icount_block: ");
1525 for (i=0; i < m->basicblockcount; i++)
1526 printf("(%3i-%3i) ",i, icount_block[i]);
1530 /* extend lifetime over backedges */
1531 /* now iterate through lifetimes and expand them */
1534 max_local_ss = cum_local_ss = 0;
1537 for(lt_index = 0 ;lt_index < ls->lifetimecount; lt_index++) {
1538 if ( ls->lifetime[lt_index].type != -1) { /* used lifetime */
1539 ls->lt_used[lifetimecount ++] = lt_index; /* remember lt_index in lt_sorted */
1540 lt = &(ls->lifetime[lt_index]);
1543 for (ss=lt->local_ss; ss != 0; ss = ss->next, local_ss_count++);
1544 if (local_ss_count > max_local_ss) max_local_ss = local_ss_count;
1545 cum_local_ss+=local_ss_count;
1548 if (lt->bb_first_def == -1) {
1549 /* printf("--------- Warning: variable not defined!------------------vi: %i start: %i end: %i\n", lt->v_index, lt->i_start, lt->i_end); */
1550 lt->bb_first_def = 0;
1551 lt->i_first_def = 0;
1554 /* lt->i_start =lt->bb_first_def * ls->icount_max + lt->i_first_def; */
1555 lt->i_start = icount_block[lt->bb_first_def] + lt->i_first_def;
1557 if (lt->bb_last_use == -1) {
1558 /* printf("--------- Warning: variable not used! --------------------vi: %i start: %i end: %i\n", lt->v_index, lt->i_start, lt->i_end); */
1559 lt->bb_last_use = lt->bb_first_def;
1560 lt->i_last_use = lt->i_first_def;
1563 /* lt->i_end = lt->bb_last_use * ls->icount_max + lt->i_last_use; */
1564 lt->i_end = icount_block[lt->bb_last_use] + lt->i_last_use;
1566 if (lt->i_start > lt->i_end)
1567 printf("--------- Warning: last use before first def! ------------vi: %i start: %i end: %i\n", lt->v_index, lt->i_start, lt->i_end);
1570 /* expand lifetimes in a exceptionhandler to at least the whole handler */
1571 /* TODO do a loop analyze for the exceptionhandler*/
1573 /* every lifetime of a guarded area, which is used in the exc. handler, */
1574 /* has to be expanded to at least the whole guarded area */
1575 for (i=0; i < cd->exceptiontablelength; i++) {
1576 if ( !((bfirst > ls->ex[i].handler_max) || ( blast < ls->ex[i].handler_min)) ) {
1577 /* lifetime lt lies within the exceptionhandler */
1578 /* expand to at least the extends of this exceptionhandler */
1580 /* -> Lifetime start has to be at minimum the start of the exceptionhandler */
1581 if (bfirst >= ls->ex[i].handler_min) {
1582 bfirst=ls->ex[i].handler_min;
1585 /* -> Lifetime end has to be at minimum the end of the exceptionhandler */
1586 if (blast <= ls->ex[i].handler_max) {
1587 blast=ls->ex[i].handler_max;
1588 ilast= m->basicblocks[ls->ex[i].handler_max].icount-1;
1594 if (lt->bb_first_def != lt->bb_last_use) {
1595 /* Lifetime goes over more than one Basic Block -> */
1596 /* check for necessary extension over backedges */
1597 /* see lsra_get_backedges */
1599 for (i=0; i < ls->backedge_count; i++) {
1600 if (!( (lt->bb_first_def > ls->backedge[i]->start) ||
1601 (lt->bb_last_use < ls->backedge[i]->end) )) {
1602 /* Live intervall intersects with a backedge */
1603 /* if (lt->bb_first_def <= ls->backedge[i]->start) */
1604 /* lt->i_start = (m->basicblockcount - ls->backedge[i]->start) * ls->icount_max; */
1605 if (lt->bb_last_use <= ls->backedge[i]->start)
1606 /* lt->i_end = ls->backedge[i]->start * ls->icount_max + m->basicblocks[ls->sorted[ls->backedge[i]->start]].icount-1; */
1607 lt->i_end = icount_block[ls->backedge[i]->start] + m->basicblocks[ls->sorted[ls->backedge[i]->start]].icount;
1611 #ifdef USAGE_PER_INSTR
1612 lt->usagecount = lt->usagecount / ( lt->i_end - lt->i_start + 1);
1616 /* printf("%5i %5i ====== \n", ls->lifetimecount, lifetimecount); */
1617 ls->lifetimecount = lifetimecount;
1620 for (i=0; i<m->basicblockcount; i++)
1621 if (m->basicblocks[i].flags >= BBREACHED)
1622 i_count+=m->basicblocks[i].icount;
1623 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);
1627 #ifdef LSRA_PRINTLIFETIMES
1628 void print_lifetimes(registerdata *rd, lsradata *ls, int *lt, int lifetimecount)
1632 int type,flags,regoff,varkind;
1634 for (lt_index = 0; lt_index < lifetimecount; lt_index++) {
1635 n = &(ls->lifetime[lt[lt_index]]);
1636 if (n->v_index < 0) { /* stackslot */
1637 type = n->local_ss->s->type;
1638 flags=n->local_ss->s->flags;
1639 regoff=n->local_ss->s->regoff;
1640 varkind=n->local_ss->s->varkind;
1641 } else { /* local var */
1642 if (rd->locals[n->v_index][n->type].type>=0) {
1643 type = rd->locals[n->v_index][n->type].type;
1644 flags=rd->locals[n->v_index][n->type].flags;
1645 regoff=rd->locals[n->v_index][n->type].regoff;
1648 { log_text("Type Data mismatch 3\n"); assert(0); }
1650 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);
1652 printf( "%3i Lifetimes printed \n",lt_index);
1656 struct stackslot *lsra_make_ss(stackptr s, int bb_index)
1658 struct stackslot *ss;
1660 ss=DNEW(struct stackslot);
1666 void lsra_add_ss(struct lifetime *lt, stackptr s) {
1667 struct stackslot *ss;
1668 /* Stackslot noch nicht eingetragen? */
1670 if (s->varnum != lt->v_index) {
1671 ss = DNEW(struct stackslot);
1673 ss->s->varnum = lt->v_index;
1674 ss->next = lt->local_ss;
1676 if (s != NULL) lt->savedvar |= s->flags & SAVEDVAR;
1677 if (s != NULL) lt->type = s->type;
1681 struct lifetime *get_ss_lifetime(lsradata *ls, stackptr s) {
1684 if (s->varnum >= 0) { /* new Lifetime *//* existiert noch nicht -> neue anlegen */
1685 n = &(ls->lifetime[-ls->v_index - 1]);
1687 n->v_index = ls->v_index--;
1690 n->bb_last_use = -1;
1691 n->bb_first_def = -1;
1696 n = &(ls->lifetime[-s->varnum - 1]);
1702 #define IS_TEMP_VAR(s) ( ((s)->varkind != ARGVAR) && ((s)->varkind != LOCALVAR) )
1704 #define lsra_join_3_stack(ls, dst, src1, src2, join_type) \
1705 if ( IS_TEMP_VAR(dst) ) { \
1707 if ( IS_TEMP_VAR(src1) && ((src1)->type == (dst)->type)) { \
1708 join_ret = lsra_join_ss(ls, dst, src1, join_type); \
1710 if ( (!join_ret) && IS_TEMP_VAR(src2) && ((src2)->type == (dst)->type)) { \
1711 lsra_join_ss(ls, dst, src2, join_type); \
1715 #define lsra_join_2_stack(ls, dst, src, join_type) \
1716 if ( IS_TEMP_VAR(dst) ) { \
1717 if ( (IS_TEMP_VAR(src)) && ((src)->type == (dst)->type)) { \
1718 lsra_join_ss(ls, dst, src, join_type); \
1722 #define lsra_join_dup(ls, s1, s2, s3) { \
1723 if (IS_TEMP_VAR(s1)) { \
1725 if (IS_TEMP_VAR(s2)) \
1726 join_ret = lsra_join_ss(ls, s1, s2, JOIN); /* undangerous join! */ \
1727 if (IS_TEMP_VAR(s3)) { \
1728 if (join_ret) /* first join succesfull -> second of type JOIN_DUP */ \
1729 lsra_join_ss(ls, s1, s3, JOIN_DUP); \
1731 lsra_join_ss(ls, s1, s3, JOIN); /* first join did not happen -> second undangerous */ \
1734 if (IS_TEMP_VAR(s2) && IS_TEMP_VAR(s3)) \
1735 lsra_join_ss(ls, s2, s3, JOIN_DUP); \
1739 #ifdef JOIN_DEST_STACK
1740 #define lsra_join_dup(ls, s1, s2, s3) { \
1741 if (IS_TEMP_VAR(s1)) { \
1742 if (IS_TEMP_VAR(s2)) \
1743 lsra_join_ss(ls, s1, s2, JOIN_DUP); \
1745 if (IS_TEMP_VAR(s3)) \
1746 lsra_join_ss(ls, s1, s3, JOIN_DUP); \
1750 #define lsra_join_dup(ls, s1, s2, s3) { \
1751 if (IS_TEMP_VAR(s1)) { \
1752 if (IS_TEMP_VAR(s2)) \
1753 lsra_join_ss(ls, s1, s2, JOIN_DUP); \
1754 if (IS_TEMP_VAR(s3)) \
1755 lsra_join_ss(ls, s1, s3, JOIN_DUP); \
1757 if (IS_TEMP_VAR(s2) && IS_TEMP_VAR(s3)) \
1758 lsra_join_ss(ls, s2, s3, JOIN_DUP); \
1763 #define lsra_new_stack(ls, s, block, instr) if ((s)->varkind != ARGVAR) _lsra_new_stack(ls, s, block, instr, LSRA_STORE)
1764 void _lsra_new_stack(lsradata *ls, stackptr s, int block, int instr, int store)
1768 if (s->varkind == LOCALVAR) {
1769 lsra_usage_local(ls, s->varnum, s->type, block, instr, LSRA_STORE);
1770 } else /* if (s->varkind != ARGVAR) */ {
1772 n=get_ss_lifetime( ls, s );
1774 if (store == LSRA_BB_IN)
1775 n->flags |= JOIN_BB;
1776 /* remember first def -> overwrite everytime */
1777 n->bb_first_def = ls->sorted_rev[block];
1778 n->i_first_def = instr;
1780 n->usagecount+=ls->nesting[ls->sorted_rev[block]];
1784 #define lsra_from_stack(ls, s, block, instr) if ((s)->varkind != ARGVAR) _lsra_from_stack(ls, s, block, instr, LSRA_LOAD)
1785 #define lsra_pop_from_stack(ls, s, block, instr) if ((s)->varkind != ARGVAR) _lsra_from_stack(ls, s, block, instr, LSRA_POP)
1786 void _lsra_from_stack(lsradata *ls, stackptr s, int block, int instr, int store)
1790 if (s->varkind == LOCALVAR) {
1791 lsra_usage_local(ls, s->varnum, s->type, block, instr, LSRA_LOAD);
1792 } else /* if (s->varkind != ARGVAR) */ {
1794 n=get_ss_lifetime( ls, s );
1796 if (store == LSRA_BB_OUT)
1797 n->flags |= JOIN_BB;
1798 if (n->flags & JOINING)
1799 n->flags &= ~JOINING;
1800 n->usagecount+=ls->nesting[ls->sorted_rev[block]];
1802 /* remember last USE, so only write, if USE Field is undefined (==-1) */
1803 if (n->bb_last_use == -1) {
1804 n->bb_last_use = ls->sorted_rev[block];
1805 n->i_last_use = instr;
1810 void lsra_usage_local(lsradata *ls, s4 v_index, int type, int block, int instr, int store)
1814 n = &(ls->lifetime[ ls->maxlifetimes + v_index * (TYPE_ADR+1) + type]);
1816 if (n->type == -1) { /* new local lifetime */
1818 /* if (store != LSRA_STORE) printf("lsra_local_store: Read before write Local var: %i paramcount: ?\n", v_index); */
1823 n->savedvar = SAVEDVAR;
1827 n->bb_last_use = -1;
1828 n->bb_first_def = -1;
1830 n->usagecount+=ls->nesting[ls->sorted_rev[block]];
1831 /* add access at (block, instr) to intruction list */
1832 /* if (store == LSRA_LOAD) { */
1833 /* remember last USE, so only write, if USE Field is undefined (==-1) */
1834 /* count store as use, too -> defined and not used vars would overwrite */
1836 if (n->bb_last_use == -1) {
1837 n->bb_last_use = ls->sorted_rev[block];
1838 n->i_last_use = instr;
1840 if (store == LSRA_STORE) {
1841 /* store == LSRA_STORE, remember first def -> overwrite everytime */
1842 n->bb_first_def = ls->sorted_rev[block];
1843 n->i_first_def = instr;
1848 void lsra_dump_stack(stackptr s)
1851 printf("%p(R%3i N%3i K%3i T%3i F%3i) ",(void *)s,s->regoff, s->varnum, s->varkind, s->type, s->flags);
1859 void lsra_scan_registers_canditates(methodinfo *m, lsradata *ls, int b_index)
1867 bool join_ret; /* for lsra_join* Macros */
1868 #if defined(LSRA_USES_REG_RES)
1869 int v_index_min_before_instruction;
1870 int v_index_min[REG_RES_CNT];
1872 for (i=0; i < REG_RES_CNT; i++) {
1873 ls->reg_res_free[i] = -1;
1874 v_index_min[i] = ls->v_index;
1878 /* prevent compiler warnings */
1882 src = m->basicblocks[b_index].instack;
1883 if (m->basicblocks[b_index].type != BBTYPE_STD) {
1886 { log_text("No Incoming Stackslot for Exception or Subroutine Basic Block\n"); assert(0); }
1888 lsra_new_stack(ls, src, b_index, 0);
1889 if (src->varkind == STACKVAR)
1890 src->varkind = TEMPVAR;
1893 for (;src != NULL; src=src->prev) {
1894 if (src->varkind == ARGVAR ) /* no ARGVAR possible at BB Boundaries with LSRA! -> change to TEMPVAR */
1895 src->varkind = TEMPVAR;
1896 else if (src->varkind == LOCALVAR )
1897 { log_text("LOCALVAR at basicblock instack\n"); assert(0); } /* only allowed for top most ss at sbr or exh entries! */
1899 if (src->varkind == STACKVAR ) /* no Interfaces at BB Boundaries with LSRA! -> change to TEMPVAR */
1900 src->varkind = TEMPVAR;
1901 _lsra_new_stack(ls, src, b_index, iindex, LSRA_BB_IN);
1904 src = m->basicblocks[b_index].outstack;
1905 for (;src != NULL; src=src->prev) {
1906 if (src->varkind == ARGVAR )
1907 { log_text("ARGVAR at basicblock outstack\n"); assert(0); }
1908 else if (src->varkind == LOCALVAR )
1909 { log_text("LOCALVAR at basicblock outstack\n"); assert(0); }
1911 if (src->varkind == STACKVAR ) /* no Interfaces at BB Boundaries with LSRA! -> change to TEMPVAR */
1912 src->varkind = TEMPVAR;
1913 _lsra_from_stack(ls, src, b_index, iindex, LSRA_BB_OUT);
1917 iptr = m->basicblocks[b_index].iinstr;
1918 iindex = m->basicblocks[b_index].icount - 1;
1921 if ((iindex+1) > ls->icount_max)
1922 ls->icount_max = iindex+1;
1925 for (;iindex >= 0; iindex--, iptr--) {
1928 if (iindex) /* > 0 */
1931 src=m->basicblocks[b_index].instack;
1932 #if defined(LSRA_USES_REG_RES)
1933 v_index_min_before_instruction = ls->v_index;
1936 /* printf("bb: %3i bcount: %3i iindex: %3i ilen: %3i opcode: %3i %s\n",b_index,m->basicblockcount,iindex,len,opcode,icmd_names[opcode]); */
1937 /* lsra_dump_stack(src); */
1938 /* lsra_dump_stack(dst); */
1944 lsra_usage_local(ls,iptr->op1,TYPE_ADR, b_index,iindex,LSRA_LOAD); /* local read (return adress) */
1949 case ICMD_ELSE_ICONST:
1950 case ICMD_CHECKNULL:
1951 case ICMD_CHECKEXCEPTION:
1952 case ICMD_CHECKASIZE:
1953 case ICMD_PUTSTATICCONST:
1954 case ICMD_INLINE_START:
1955 case ICMD_INLINE_END:
1960 lsra_usage_local(ls,iptr->op1,TYPE_INT, b_index,iindex,LSRA_LOAD); /* local */
1961 lsra_usage_local(ls,iptr->op1,TYPE_INT, b_index,iindex,LSRA_STORE); /* local = local+<const> */
1964 /* pop 0 push 1 const */
1972 /* new stack slot */
1973 lsra_new_stack(ls,dst,b_index,iindex); /* const->stack */
1976 /* pop 0 push 1 load */
1984 if (dst->varkind != LOCALVAR) {
1985 lsra_usage_local(ls,iptr->op1,opcode-ICMD_ILOAD, b_index,iindex,LSRA_LOAD); /* local->value */
1986 lsra_new_stack(ls,dst,b_index,iindex); /* value->stack */
1987 } else if (dst->varnum != iptr->op1) {
1988 lsra_usage_local(ls,iptr->op1,opcode-ICMD_ILOAD, b_index,iindex,LSRA_LOAD); /* local->value */
1989 lsra_usage_local(ls,dst->varnum,opcode-ICMD_ILOAD, b_index,iindex,LSRA_STORE); /* local->value */
1995 /* Stack(arrayref,index)->stack */
2007 lsra_from_stack(ls, src,b_index,iindex); /* stack->index */
2008 lsra_from_stack(ls, src->prev,b_index,iindex); /* stack->arrayref */
2009 lsra_new_stack(ls,dst,b_index,iindex); /* arrayref[index]->stack */
2013 /* stack(arrayref,index,value)->arrayref[index]=value */
2025 lsra_from_stack(ls, src,b_index,iindex); /* stack -> value */
2026 lsra_from_stack(ls, src->prev,b_index,iindex); /* stack -> index */
2027 lsra_from_stack(ls, src->prev->prev,b_index,iindex); /* stack -> arrayref */
2030 case ICMD_POP: /* throw away a stackslot -> check if used anyway! */
2031 lsra_pop_from_stack(ls,src,b_index,iindex);
2034 /* pop 1 push 0 store */
2035 /* stack -> local */
2042 if (src->varkind != LOCALVAR) {
2043 lsra_from_stack(ls, src,b_index,iindex); /* stack -> value */
2044 lsra_usage_local(ls,iptr->op1,opcode-ICMD_ISTORE, b_index,iindex,LSRA_STORE); /* local->value */
2045 } else if (src->varnum != iptr->op1) {
2046 lsra_usage_local(ls,iptr->op1,opcode-ICMD_ISTORE, b_index,iindex,LSRA_STORE); /* local->value */
2047 lsra_usage_local(ls,src->varnum,opcode-ICMD_ISTORE, b_index,iindex,LSRA_LOAD); /* local->value */
2057 case ICMD_ARETURN: /* stack(value) -> [empty] */
2058 case ICMD_ATHROW: /* stack(objref) -> undefined */
2059 lsra_from_stack(ls, src,b_index,iindex); /* stack -> value */
2061 case ICMD_PUTSTATIC: /* stack(value) -> static_field */
2062 case ICMD_PUTFIELDCONST:
2063 /* pop 1 push 0 branch */
2064 case ICMD_MONITORENTER:
2065 case ICMD_MONITOREXIT:
2066 lsra_from_stack(ls, src,b_index,iindex); /* stack -> value */
2069 case ICMD_IFNULL: /* stack(value) -> branch? */
2070 case ICMD_IFNONNULL:
2083 lsra_from_stack(ls, src,b_index,iindex); /* stack -> value */
2086 /* pop 1 push 0 table branch */
2088 case ICMD_TABLESWITCH:
2089 lsra_from_stack(ls, src,b_index,iindex); /* stack -> value */
2091 case ICMD_LOOKUPSWITCH:
2092 lsra_from_stack(ls, src,b_index,iindex); /* stack -> value */
2097 case ICMD_POP2: /* throw away 2 stackslots -> check if used anyway! */
2098 lsra_pop_from_stack(ls,src,b_index,iindex);
2099 lsra_pop_from_stack(ls,src->prev,b_index,iindex);
2102 /* pop 2 push 0 branch */
2104 case ICMD_IF_ICMPEQ: /* stack (v1,v2) -> branch(v1,v2) */
2105 case ICMD_IF_ICMPNE:
2106 case ICMD_IF_ICMPLT:
2107 case ICMD_IF_ICMPGE:
2108 case ICMD_IF_ICMPGT:
2109 case ICMD_IF_ICMPLE:
2111 case ICMD_IF_LCMPEQ:
2112 case ICMD_IF_LCMPNE:
2113 case ICMD_IF_LCMPLT:
2114 case ICMD_IF_LCMPGE:
2115 case ICMD_IF_LCMPGT:
2116 case ICMD_IF_LCMPLE:
2118 case ICMD_IF_ACMPEQ:
2119 case ICMD_IF_ACMPNE:
2120 lsra_from_stack(ls, src,b_index,iindex); /* stack -> value*/
2121 lsra_from_stack(ls, src->prev,b_index,iindex); /* stack -> objref*/
2126 case ICMD_PUTFIELD: /* stack(objref,value) -> objref->method=value */
2128 case ICMD_IASTORECONST:
2129 case ICMD_LASTORECONST:
2130 case ICMD_AASTORECONST:
2131 case ICMD_BASTORECONST:
2132 case ICMD_CASTORECONST:
2133 case ICMD_SASTORECONST:
2134 lsra_from_stack(ls, src,b_index,iindex); /* stack -> value*/
2135 lsra_from_stack(ls, src->prev,b_index,iindex); /* stack -> objref*/
2138 /* pop 0 push 1 dup */
2139 /* merge dupped vars??? */
2140 case ICMD_DUP: /* src == dst->prev, src -> dst */
2141 /* lsra_from_stack(ls, src,b_index,iindex);*/ /* just inc usage count? */
2142 lsra_new_stack(ls,dst,b_index,iindex);
2144 /* #if (defined(JOIN_DUP_STACK) && !defined(JOIN_DEST_STACK)) */
2145 #ifdef JOIN_DUP_STACK
2146 /* src is identical to dst->prev */
2147 lsra_join_2_stack(ls, src, dst, JOIN_DUP);
2151 /* pop 0 push 2 dup */
2154 /* lsra_from_stack(ls, src,b_index,iindex); */ /* just inc usage count? */
2155 /* lsra_from_stack(ls, src->prev,b_index,iindex); */ /* just inc usage count? */
2156 lsra_new_stack(ls,dst->prev,b_index,iindex);
2157 lsra_new_stack(ls,dst,b_index,iindex);
2159 /* #if (defined(JOIN_DUP_STACK) && !defined(JOIN_DEST_STACK)) */
2160 #ifdef JOIN_DUP_STACK
2161 lsra_join_2_stack(ls, src, dst, JOIN_DUP);
2162 lsra_join_2_stack(ls, src->prev, dst->prev, JOIN_DUP);
2163 /* src is identical to dst->prev->prev */
2164 /* src->prev is identical to dst->prev->prev->prev */
2168 /* pop 2 push 3 dup */
2171 lsra_from_stack(ls, src, b_index, iindex);
2172 lsra_from_stack(ls, src->prev, b_index, iindex);
2173 lsra_new_stack(ls, dst->prev->prev, b_index, iindex);
2174 lsra_new_stack(ls, dst->prev, b_index, iindex);
2175 lsra_new_stack(ls, dst, b_index, iindex);
2176 #ifdef JOIN_DUP_STACK
2177 lsra_join_dup(ls, src, dst, dst->prev->prev);
2178 lsra_join_2_stack(ls, src->prev, dst->prev, JOIN);
2182 /* pop 3 push 4 dup */
2185 lsra_from_stack(ls, src,b_index,iindex);
2186 lsra_from_stack(ls, src->prev,b_index,iindex);
2187 lsra_from_stack(ls, src->prev->prev,b_index,iindex);
2188 lsra_new_stack(ls,dst->prev->prev->prev,b_index,iindex);
2189 lsra_new_stack(ls,dst->prev->prev,b_index,iindex);
2190 lsra_new_stack(ls,dst->prev,b_index,iindex);
2191 lsra_new_stack(ls,dst,b_index,iindex);
2193 #ifdef JOIN_DUP_STACK
2194 lsra_join_dup(ls, src, dst, dst->prev->prev->prev);
2195 lsra_join_2_stack(ls, src->prev, dst->prev, JOIN);
2196 lsra_join_2_stack(ls, src->prev->prev, dst->prev->prev, JOIN);
2200 /* pop 3 push 5 dup */
2203 lsra_from_stack(ls, src,b_index,iindex);
2204 lsra_from_stack(ls, src->prev,b_index,iindex);
2205 lsra_from_stack(ls, src->prev->prev,b_index,iindex);
2206 lsra_new_stack(ls,dst->prev->prev->prev->prev,b_index,iindex);
2207 lsra_new_stack(ls,dst->prev->prev->prev,b_index,iindex);
2208 lsra_new_stack(ls,dst->prev->prev,b_index,iindex);
2209 lsra_new_stack(ls,dst->prev,b_index,iindex);
2210 lsra_new_stack(ls,dst,b_index,iindex);
2212 #ifdef JOIN_DUP_STACK
2213 lsra_join_dup(ls, src, dst, dst->prev->prev->prev);
2214 lsra_join_dup(ls, src->prev, dst->prev, dst->prev->prev->prev->prev);
2215 lsra_join_2_stack(ls, src->prev->prev, dst->prev->prev, JOIN);
2219 /* pop 4 push 6 dup */
2222 lsra_from_stack(ls, src,b_index,iindex);
2223 lsra_from_stack(ls, src->prev,b_index,iindex);
2224 lsra_from_stack(ls, src->prev->prev,b_index,iindex);
2225 lsra_from_stack(ls, src->prev->prev->prev,b_index,iindex);
2226 lsra_new_stack(ls,dst->prev->prev->prev->prev->prev,b_index,iindex);
2227 lsra_new_stack(ls,dst->prev->prev->prev->prev,b_index,iindex);
2228 lsra_new_stack(ls,dst->prev->prev->prev,b_index,iindex);
2229 lsra_new_stack(ls,dst->prev->prev,b_index,iindex);
2230 lsra_new_stack(ls,dst->prev,b_index,iindex);
2231 lsra_new_stack(ls,dst,b_index,iindex);
2233 #ifdef JOIN_DUP_STACK
2234 lsra_join_dup(ls, src, dst, dst->prev->prev->prev->prev);
2235 lsra_join_dup(ls, src->prev, dst->prev, dst->prev->prev->prev->prev->prev);
2236 lsra_join_2_stack(ls, src->prev->prev, dst->prev->prev, JOIN);
2237 lsra_join_2_stack(ls, src->prev->prev->prev, dst->prev->prev->prev, JOIN);
2241 /* pop 2 push 2 swap */
2244 lsra_from_stack(ls, src,b_index,iindex);
2245 lsra_from_stack(ls, src->prev,b_index,iindex);
2246 lsra_new_stack(ls,dst->prev,b_index,iindex);
2247 lsra_new_stack(ls,dst,b_index,iindex);
2249 lsra_join_2_stack(ls, src->prev, dst, JOIN);
2250 lsra_join_2_stack(ls, src, dst->prev, JOIN);
2287 lsra_from_stack(ls, src, b_index, iindex);
2288 lsra_from_stack(ls, src->prev, b_index, iindex);
2289 lsra_new_stack(ls, dst, b_index, iindex);
2290 #ifdef JOIN_DEST_STACK
2291 lsra_join_3_stack(ls, dst, src->prev, src, JOIN_OP);
2296 lsra_from_stack(ls, src, b_index, iindex);
2297 lsra_from_stack(ls, src->prev,b_index,iindex);
2298 lsra_new_stack(ls, dst, b_index, iindex);
2299 #ifdef JOIN_DEST_STACK
2300 lsra_join_2_stack(ls, src, dst, JOIN_OP);
2317 lsra_from_stack(ls, src,b_index,iindex);
2318 lsra_from_stack(ls, src->prev,b_index,iindex);
2319 lsra_new_stack(ls,dst,b_index,iindex);
2323 case ICMD_IADDCONST:
2324 case ICMD_ISUBCONST:
2325 case ICMD_IMULCONST:
2329 case ICMD_IANDCONST:
2331 case ICMD_IXORCONST:
2332 case ICMD_ISHLCONST:
2333 case ICMD_ISHRCONST:
2334 case ICMD_IUSHRCONST:
2336 case ICMD_LADDCONST:
2337 case ICMD_LSUBCONST:
2338 case ICMD_LMULCONST:
2342 case ICMD_LANDCONST:
2344 case ICMD_LXORCONST:
2345 case ICMD_LSHLCONST:
2346 case ICMD_LSHRCONST:
2347 case ICMD_LUSHRCONST:
2349 case ICMD_IFEQ_ICONST:
2350 case ICMD_IFNE_ICONST:
2351 case ICMD_IFLT_ICONST:
2352 case ICMD_IFGE_ICONST:
2353 case ICMD_IFGT_ICONST:
2354 case ICMD_IFLE_ICONST:
2359 case ICMD_INT2SHORT:
2377 case ICMD_CHECKCAST:
2378 lsra_from_stack(ls, src, b_index, iindex);
2379 lsra_new_stack(ls, dst, b_index, iindex);
2380 #ifdef JOIN_DEST_STACK
2381 lsra_join_2_stack(ls, src, dst, JOIN_OP);
2385 case ICMD_ARRAYLENGTH:
2386 case ICMD_INSTANCEOF:
2389 case ICMD_ANEWARRAY:
2392 lsra_from_stack(ls, src,b_index,iindex);
2393 lsra_new_stack(ls,dst,b_index,iindex);
2398 case ICMD_GETSTATIC:
2400 lsra_new_stack(ls,dst,b_index,iindex);
2403 /* pop many push any */
2404 case ICMD_INVOKEVIRTUAL:
2405 case ICMD_INVOKESPECIAL:
2406 case ICMD_INVOKESTATIC:
2407 case ICMD_INVOKEINTERFACE:
2410 lsra_from_stack(ls, src,b_index,iindex);
2413 #if defined(__X86_64__) || defined(__I386__) || defined(__ALPHA__)
2414 if (((unresolved_method *) iptr->target)->methodref->parseddesc.md->returntype.type != TYPE_VOID)
2416 if (((methodinfo*)iptr->val.a)->returntype != TYPE_VOID)
2418 lsra_new_stack(ls,dst,b_index,iindex);
2423 lsra_from_stack(ls, src,b_index,iindex);
2426 lsra_from_stack(ls, src,b_index,iindex);
2429 lsra_from_stack(ls, src,b_index,iindex);
2430 src = src->prev; /* ??????????? */
2431 if (iptr->op1 != TYPE_VOID)
2432 lsra_new_stack(ls,dst,b_index,iindex);
2436 case ICMD_MULTIANEWARRAY:
2439 lsra_from_stack(ls, src,b_index,iindex);
2442 lsra_new_stack(ls,dst,b_index,iindex);
2446 printf("ICMD %d at %d\n", iptr->opc, (int)(iptr - m->instructions));
2447 { log_text("Missing ICMD code during register allocation"); assert(0); }
2450 #if defined(LSRA_USES_REG_RES)
2453 int length, maxlength, j;
2454 int index, reg_res,start_iindex;
2455 struct stackslot * ss;
2459 for (j=0, reg_res = icmd_uses_reg_res[opcode][REG_RES_CNT]; j < REG_RES_CNT; j++, reg_res=(reg_res+1)%REG_RES_CNT) {
2460 if (reg_res == -1) reg_res = EDX; /* patch because icmd_uses_reg_res [][REG_RES_CNT] ist defaulting to -1 */
2463 if ((iindex == 0) || (icmd_uses_reg_res[opcode][reg_res])) {
2464 if (ls->reg_res_free[reg_res] != -1) {
2465 /* reg_res is free from ls->reg_res_free[] til here (iindex) */
2466 /* now search for the longest lifetime, which fits in this intervall */
2467 /* and if found assign edx to it */
2468 if (icmd_uses_reg_res[opcode][reg_res] & D) /* ICMD destroys REG_RES as destination operand */
2469 start_iindex = iindex +1;
2471 start_iindex = iindex;
2472 for (i = (-v_index_min[reg_res] - 1); i < (-ls->v_index -1); i++) {
2474 n = &(ls->lifetime[i]);
2475 if (!(n->flags & (JOINING || JOIN_BB))) { /* do not assign reserved Regs to lifetimes not fully seen till now */
2476 if ((n->type == TYPE_INT) || (n->type == TYPE_ADR)) {
2477 if (n->savedvar == 0) {
2478 if ((n->bb_last_use == n->bb_first_def) && (n->bb_last_use == ls->sorted_rev[b_index])) {
2479 if ((n->i_last_use <= ls->reg_res_free[reg_res]) && (n->i_first_def >= start_iindex)) {
2481 length = n->i_last_use - n->i_first_def;
2482 if (length > maxlength) {
2493 if (icmd_uses_reg_res[opcode][reg_res] & S) /* ICMD destroys REG_RES as source operand */
2494 ls->reg_res_free[reg_res] = -1;
2496 ls->reg_res_free[reg_res] = iindex;
2498 if (index != -1) { /* there is a lifetime, which a reserved register can be assigned to */
2502 n=&(ls->lifetime[index]);
2503 printf("------ SS Index %i in REG_RES %i bb %3i instr %3i - bb %3i instr %3i\n", lsra_reg_res[reg_res], n->v_index, ls->sorted[n->bb_first_def], n->i_first_def, ls->sorted[n->bb_last_use], n->i_last_use);
2506 ls->lifetime[index].reg = lsra_reg_res[reg_res];
2507 for (ss = ls->lifetime[index].local_ss; ss != NULL; ss=ss->next) {
2508 ss->s->regoff = lsra_reg_res[reg_res];
2510 ls->lifetime[index].type = -1; /* drop lifetime, no further processing required */
2513 v_index_min[reg_res] = v_index_min_before_instruction;
2515 if (ls->reg_res_free[reg_res] == -1)
2516 ls->reg_res_free[reg_res] = iindex;
2528 int lsra_test_lt(registerdata *rd, struct lifetime *n, int store, int *values, bool inmemory) {
2532 value_index = n->reg;
2534 if (IS_FLT_DBL_TYPE(n->type)) {
2535 value_index = rd->memuse + INT_REG_CNT + n->reg;
2537 value_index = rd->memuse + n->reg;
2541 if ((store == LSRA_LOAD) || (store == LSRA_POP)) {
2542 if (values[value_index] == VS) {
2543 if (n->i_start != -1) { /* not a parameter */
2544 printf("lsra_test: Warning: v_index %3i type %3i reg %3i", n->v_index, n->type, n->reg);
2547 printf(" not initialized\n");
2549 } else if (values[value_index] != n->v_index) {
2550 printf("lsra_test: Error: v_index %3i type %3i reg %3i", n->v_index, n->type, n->reg);
2553 printf("Conflict: %3i \n", values[value_index]);
2557 } else { /* LSRA_STORE */
2558 values[value_index] = n->v_index;
2563 int lsra_test_local( lsradata *ls, registerdata *rd, int v_index, int type, int store, int *values) {
2566 n = &(ls->lifetime[ ls->maxlifetimes + v_index * (TYPE_ADR+1) + type]);
2568 { log_text("lsra_test: Local Var Lifetime not initialized!\n"); assert(0); }
2570 return lsra_test_lt(rd, n, store, values, rd->locals[v_index][type].flags & INMEMORY);
2573 #define lsra_test_new_stack( ls, rd, s, values) lsra_test_stack(ls, rd, s, values, LSRA_STORE)
2574 #define lsra_test_from_stack( ls, rd, s, values) lsra_test_stack(ls, rd, s, values,LSRA_LOAD)
2575 #define lsra_test_pop_from_stack( ls, rd, s, values) lsra_test_stack(ls, rd, s, values, LSRA_LOAD)
2576 int lsra_test_stack( lsradata *ls, registerdata *rd, stackptr s, int *values, int store)
2581 if (s->varkind == LOCALVAR) {
2582 return lsra_test_local(ls, rd, s->varnum, s->type, store, values);
2584 if (s->varkind != ARGVAR) {
2586 { log_text("lsra_test: Stackslot not initialized!\n"); assert(0); }
2587 n = &(ls->lifetime[-s->varnum - 1]);
2589 { log_text("lsra_test: Stackslot Lifetime not initialized!\n"); assert(0); }
2591 return lsra_test_lt(rd, n, store, values, s->flags & INMEMORY);
2596 int _test_lifetimes(methodinfo *m, lsradata *ls, registerdata *rd, int b_index, int *values)
2598 struct stackslot *ss;
2615 iptr = m->basicblocks[b_index].iinstr;
2617 dst = m->basicblocks[b_index].instack;
2619 for (iindex =0 ;(iindex < m->basicblocks[b_index].icount) && (ret == -1) ; iindex++, iptr++) {
2628 ret = lsra_test_local(ls, rd, iptr->op1, TYPE_ADR, LSRA_LOAD, values); /* local read (return adress) */
2633 case ICMD_ELSE_ICONST:
2634 case ICMD_CHECK_NULL:
2635 case ICMD_CHECKEXCEPTION:
2636 case ICMD_CHECKASIZE:
2637 case ICMD_PUTSTATICCONST:
2638 case ICMD_INLINE_START:
2639 case ICMD_INLINE_END:
2644 ret = lsra_test_local(ls, rd,iptr->op1,TYPE_INT, LSRA_LOAD, values); /* local */
2645 ret = lsra_test_local(ls, rd,iptr->op1,TYPE_INT, LSRA_STORE, values); /* local = local+<const> */
2648 /* pop 0 push 1 const */
2656 /* new stack slot */
2657 ret = lsra_test_new_stack(ls, rd,dst, values); /* const->stack */
2660 /* pop 0 push 1 load */
2668 if (dst->varkind != LOCALVAR) {
2669 ret = lsra_test_local(ls, rd,iptr->op1,opcode-ICMD_ILOAD, LSRA_LOAD, values); /* local->value */
2670 ret = lsra_test_new_stack(ls, rd,dst, values); /* value->stack */
2671 } else if (dst->varnum != iptr->op1) {
2672 ret = lsra_test_local(ls, rd,iptr->op1,opcode-ICMD_ILOAD, LSRA_LOAD, values); /* local->value */
2673 ret = lsra_test_local(ls, rd,dst->varnum,opcode-ICMD_ILOAD, LSRA_STORE, values); /* local->value */
2679 /* Stack(arrayref,index)->stack */
2690 ret = lsra_test_from_stack(ls, rd, src, values); /* stack->index */
2691 ret = lsra_test_from_stack(ls, rd, src->prev, values); /* stack->arrayref */
2692 ret = lsra_test_new_stack(ls, rd, dst, values); /* arrayref[index]->stack */
2696 /* stack(arrayref,index,value)->arrayref[index]=value */
2708 ret = lsra_test_from_stack(ls, rd, src, values); /* stack -> value */
2709 ret = lsra_test_from_stack(ls, rd, src->prev, values); /* stack -> index */
2710 ret = lsra_test_from_stack(ls, rd, src->prev->prev, values); /* stack -> arrayref */
2713 case ICMD_POP: /* throw away a stackslot -> check if used anyway! */
2714 ret = lsra_test_pop_from_stack(ls, rd,src, values);
2717 /* pop 1 push 0 store */
2718 /* stack -> local */
2725 if (src->varkind != LOCALVAR) {
2726 ret = lsra_test_from_stack(ls, rd, src, values); /* stack -> value */
2727 ret = lsra_test_local(ls, rd,iptr->op1,opcode-ICMD_ISTORE, LSRA_STORE, values); /* local->value */
2728 } else if (src->varnum != iptr->op1) {
2729 ret = lsra_test_local(ls, rd,iptr->op1,opcode-ICMD_ISTORE, LSRA_STORE, values); /* local->value */
2730 ret = lsra_test_local(ls, rd,src->varnum,opcode-ICMD_ISTORE, LSRA_LOAD, values); /* local->value */
2740 case ICMD_ARETURN: /* stack(value) -> [empty] */
2741 case ICMD_ATHROW: /* stack(objref) -> undefined */
2742 ret = lsra_test_from_stack(ls, rd, src, values); /* stack -> value */
2744 case ICMD_PUTSTATIC: /* stack(value) -> static_field */
2745 case ICMD_PUTFIELDCONST:
2746 /* pop 1 push 0 branch */
2747 case ICMD_MONITORENTER:
2748 case ICMD_MONITOREXIT:
2749 ret = lsra_test_from_stack(ls, rd, src, values); /* stack -> value */
2752 case ICMD_IFNULL: /* stack(value) -> branch? */
2753 case ICMD_IFNONNULL:
2766 ret = lsra_test_from_stack(ls, rd, src, values); /* stack -> value */
2769 /* pop 1 push 0 table branch */
2771 case ICMD_TABLESWITCH:
2772 ret = lsra_test_from_stack(ls, rd, src, values); /* stack -> value */
2774 case ICMD_LOOKUPSWITCH:
2775 ret = lsra_test_from_stack(ls, rd, src, values); /* stack -> value */
2780 case ICMD_POP2: /* throw away 2 stackslots -> check if used anyway! */
2781 ret = lsra_test_pop_from_stack(ls, rd,src, values);
2782 ret = lsra_test_pop_from_stack(ls, rd,src->prev, values);
2785 /* pop 2 push 0 branch */
2787 case ICMD_IF_ICMPEQ: /* stack (v1,v2) -> branch(v1,v2) */
2788 case ICMD_IF_ICMPNE:
2789 case ICMD_IF_ICMPLT:
2790 case ICMD_IF_ICMPGE:
2791 case ICMD_IF_ICMPGT:
2792 case ICMD_IF_ICMPLE:
2794 case ICMD_IF_LCMPEQ:
2795 case ICMD_IF_LCMPNE:
2796 case ICMD_IF_LCMPLT:
2797 case ICMD_IF_LCMPGE:
2798 case ICMD_IF_LCMPGT:
2799 case ICMD_IF_LCMPLE:
2801 case ICMD_IF_ACMPEQ:
2802 case ICMD_IF_ACMPNE:
2803 ret = lsra_test_from_stack(ls, rd, src, values); /* stack -> value*/
2804 ret = lsra_test_from_stack(ls, rd, src->prev, values); /* stack -> objref*/
2809 case ICMD_PUTFIELD: /* stack(objref,value) -> objref->method=value */
2811 case ICMD_IASTORECONST:
2812 case ICMD_LASTORECONST:
2813 case ICMD_AASTORECONST:
2814 case ICMD_BASTORECONST:
2815 case ICMD_CASTORECONST:
2816 case ICMD_SASTORECONST:
2817 ret = lsra_test_from_stack(ls, rd, src, values); /* stack -> value*/
2818 ret = lsra_test_from_stack(ls, rd, src->prev, values); /* stack -> objref*/
2821 /* pop 0 push 1 dup */
2822 /* merge dupped vars??? */
2823 case ICMD_DUP: /* src == dst->prev, src -> dst */
2824 /* ret = lsra_test_from_stack(ls, rd, src,b_index,iindex);*/ /* just inc usage count? */
2825 ret = lsra_test_new_stack(ls, rd,dst, values);
2828 /* pop 0 push 2 dup */
2831 /* ret = lsra_test_from_stack(ls, rd, src,b_index,iindex); */ /* just inc usage count? */
2832 /* ret = lsra_test_from_stack(ls, rd, src->prev,b_index,iindex); */ /* just inc usage count? */
2833 ret = lsra_test_new_stack(ls, rd,dst->prev, values);
2834 ret = lsra_test_new_stack(ls, rd,dst, values);
2837 /* pop 2 push 3 dup */
2840 ret = lsra_test_from_stack(ls, rd, src, values);
2841 ret = lsra_test_from_stack(ls, rd, src->prev, values);
2842 ret = lsra_test_new_stack(ls, rd,dst->prev->prev, values);
2843 ret = lsra_test_new_stack(ls, rd,dst->prev, values);
2844 ret = lsra_test_new_stack(ls, rd,dst, values);
2847 /* pop 3 push 4 dup */
2850 ret = lsra_test_from_stack(ls, rd, src, values);
2851 ret = lsra_test_from_stack(ls, rd, src->prev, values);
2852 ret = lsra_test_from_stack(ls, rd, src->prev->prev, values);
2853 ret = lsra_test_new_stack(ls, rd,dst->prev->prev->prev, values);
2854 ret = lsra_test_new_stack(ls, rd,dst->prev->prev, values);
2855 ret = lsra_test_new_stack(ls, rd,dst->prev, values);
2856 ret = lsra_test_new_stack(ls, rd,dst, values);
2859 /* pop 3 push 5 dup */
2862 ret = lsra_test_from_stack(ls, rd, src, values);
2863 ret = lsra_test_from_stack(ls, rd, src->prev, values);
2864 ret = lsra_test_from_stack(ls, rd, src->prev->prev, values);
2865 ret = lsra_test_new_stack(ls, rd,dst->prev->prev->prev->prev, values);
2866 ret = lsra_test_new_stack(ls, rd,dst->prev->prev->prev, values);
2867 ret = lsra_test_new_stack(ls, rd,dst->prev->prev, values);
2868 ret = lsra_test_new_stack(ls, rd,dst->prev, values);
2869 ret = lsra_test_new_stack(ls, rd,dst, values);
2872 /* pop 4 push 6 dup */
2875 ret = lsra_test_from_stack(ls, rd, src, values);
2876 ret = lsra_test_from_stack(ls, rd, src->prev, values);
2877 ret = lsra_test_from_stack(ls, rd, src->prev->prev, values);
2878 ret = lsra_test_from_stack(ls, rd, src->prev->prev->prev, values);
2879 ret = lsra_test_new_stack(ls, rd,dst->prev->prev->prev->prev->prev, values);
2880 ret = lsra_test_new_stack(ls, rd,dst->prev->prev->prev->prev, values);
2881 ret = lsra_test_new_stack(ls, rd,dst->prev->prev->prev, values);
2882 ret = lsra_test_new_stack(ls, rd,dst->prev->prev, values);
2883 ret = lsra_test_new_stack(ls, rd,dst->prev, values);
2884 ret = lsra_test_new_stack(ls, rd,dst, values);
2888 /* pop 2 push 2 swap */
2891 ret = lsra_test_from_stack(ls, rd, src, values);
2892 ret = lsra_test_from_stack(ls, rd, src->prev, values);
2893 ret = lsra_test_new_stack(ls, rd,dst->prev, values);
2894 ret = lsra_test_new_stack(ls, rd,dst, values);
2944 ret = lsra_test_from_stack(ls, rd, src, values);
2945 ret = lsra_test_from_stack(ls, rd, src->prev, values);
2946 ret = lsra_test_new_stack(ls, rd,dst, values);
2950 case ICMD_IADDCONST:
2951 case ICMD_ISUBCONST:
2952 case ICMD_IMULCONST:
2956 case ICMD_IANDCONST:
2958 case ICMD_IXORCONST:
2959 case ICMD_ISHLCONST:
2960 case ICMD_ISHRCONST:
2961 case ICMD_IUSHRCONST:
2963 case ICMD_LADDCONST:
2964 case ICMD_LSUBCONST:
2965 case ICMD_LMULCONST:
2969 case ICMD_LANDCONST:
2971 case ICMD_LXORCONST:
2972 case ICMD_LSHLCONST:
2973 case ICMD_LSHRCONST:
2974 case ICMD_LUSHRCONST:
2976 case ICMD_IFEQ_ICONST:
2977 case ICMD_IFNE_ICONST:
2978 case ICMD_IFLT_ICONST:
2979 case ICMD_IFGE_ICONST:
2980 case ICMD_IFGT_ICONST:
2981 case ICMD_IFLE_ICONST:
2986 case ICMD_INT2SHORT:
3004 case ICMD_CHECKCAST:
3006 case ICMD_ARRAYLENGTH:
3007 case ICMD_INSTANCEOF:
3010 case ICMD_ANEWARRAY:
3013 ret = lsra_test_from_stack(ls, rd, src, values);
3014 ret = lsra_test_new_stack(ls, rd,dst, values);
3019 case ICMD_GETSTATIC:
3021 ret = lsra_test_new_stack(ls, rd,dst, values);
3024 /* pop many push any */
3025 case ICMD_INVOKEVIRTUAL:
3026 case ICMD_INVOKESPECIAL:
3027 case ICMD_INVOKESTATIC:
3028 case ICMD_INVOKEINTERFACE:
3031 ret = lsra_test_from_stack(ls, rd, src, values);
3034 #if defined(__X86_64__) || defined(__I386__) || defined(__ALPHA__)
3035 if (((unresolved_method *) iptr->target)->methodref->parseddesc.md->returntype.type != TYPE_VOID)
3037 if (((methodinfo*)iptr->val.a)->returntype != TYPE_VOID)
3039 ret = lsra_test_new_stack(ls, rd,dst, values);
3043 ret = lsra_test_from_stack(ls, rd, src, values);
3046 ret = lsra_test_from_stack(ls, rd, src, values);
3049 ret = lsra_test_from_stack(ls, rd, src, values);
3050 src = src->prev; /* ??????????? */
3051 if (iptr->op1 != TYPE_VOID)
3052 ret = lsra_test_new_stack(ls, rd, dst, values);
3055 case ICMD_MULTIANEWARRAY:
3058 ret = lsra_test_from_stack(ls, rd, src, values);
3061 ret = lsra_test_new_stack(ls, rd, dst, values);
3065 printf("ICMD %d at %d\n", iptr->opc, (int)(iptr - m->instructions));
3066 { log_text("Missing ICMD code during register allocation"); assert(0); }
3070 printf("BB: %i IIndex %i \n", b_index, iindex);
3075 for (succ = ls->succ[b_index]; succ != NULL; succ = succ->next)
3081 for (i=0, succ = ls->succ[b_index]; i!=j; i++, succ=succ->next);
3083 if ( (ret=_test_lifetimes(m, ls, rd, succ->value, values)) != -1) {
3084 printf("[BB %3i IIndex %3i]",b_index, iindex);
3091 void test_lifetimes( methodinfo *m, lsradata *ls, registerdata *rd)
3093 int *values, i, j, p, t;
3096 v_max = rd->memuse + INT_REG_CNT + FLT_REG_CNT;
3098 if ( (values = calloc( v_max, sizeof(int))) == NULL )
3099 { log_text("test_lifetimes: out of memory\n"); assert(0); }
3102 for (j=0; (j < 100) && (ret == -1); j++ ) {
3103 for (i=0; i < v_max; i++) values[i]=VS;
3105 for (p = 0, i = 0; p < m->paramcount; p++) {
3106 t = m->paramtypes[p];
3108 if (rd->locals[i][t].type >= 0)
3109 lsra_test_local( ls, rd, i, t, LSRA_STORE, values);
3112 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
3116 if ((ret=_test_lifetimes(m, ls, rd, 0, values)) != -1) {
3128 * These are local overrides for various environment variables in Emacs.
3129 * Please do not remove this and leave it at the end of the file, where
3130 * Emacs will automagically detect them.
3131 * ---------------------------------------------------------------------
3134 * indent-tabs-mode: t