1 /* src/vm/jit/optimizing/lsra.inc - linear scan register allocator
3 Copyright (C) 2005, 2006 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
40 #include "mm/memory.h"
42 #include "toolbox/bitvector.h"
44 #include "vmcore/statistics.h"
45 #include "vmcore/options.h"
46 #include "vmcore/method.h"
48 #include "vm/jit/abi.h"
49 #include "vm/jit/reg.h"
50 #include "vm/jit/jit.h"
52 #include "vm/jit/optimizing/graph.h"
53 #include "vm/jit/optimizing/lifetimes.h"
54 #include "vm/jit/optimizing/ssa.h"
56 #include "vm/jit/optimizing/lsra.h"
58 #include "toolbox/logging.h"
60 extern const char *string_java_lang_InternalError;
61 /* function prototypes */
62 void lsra_setup(jitdata *);
63 void lsra_main(jitdata *);
64 #ifdef LSRA_DEBUG_VERBOSE
65 void lsra_dump_stack(stackptr );
66 void print_lifetimes(jitdata *, int *, int);
67 void print_all_lifetimes(jitdata *);
69 void lsra_reg_setup(jitdata *,struct lsra_register *,
70 struct lsra_register *);
72 void lsra_calc_lifetime_length(jitdata *);
74 void _lsra_main( jitdata *, int *, int, struct lsra_register *,
76 void lsra_expire_old_intervalls(jitdata *, struct lifetime *,
77 struct lsra_register *);
78 void spill_at_intervall(jitdata *, struct lifetime *);
79 void lsra_add_active(struct lifetime *, struct lifetime **, int *);
80 void _lsra_expire_old_intervalls(jitdata *, struct lifetime *,
81 struct lsra_register *,
82 struct lifetime **, int *);
83 void _spill_at_intervall(struct lifetime *, struct lifetime **, int *);
84 void lsra_alloc(jitdata *, int *, int,
86 int lsra_getmem(struct lifetime *, struct freemem *, int *);
87 struct freemem *lsra_getnewmem(int *);
89 void lsra(jitdata *jd) {
94 #if defined(ENABLE_STATISTICS)
98 #if defined(LSRA_DEBUG_CHECK)
111 #if defined(LSRA_DEBUG_CHECK)
114 while (b_index < jd->basicblockcount ) {
116 if (jd->basicblocks[b_index].flags >= BBREACHED) {
118 in=m->basicblocks[b_index].instack;
119 ind=m->basicblocks[b_index].indepth;
120 for (;ind != 0;in=in->prev, ind--) {
121 /* ARGVAR or LOCALVAR in instack is ok*/
122 #if defined(LSRA_DEBUG_VERBOSE)
123 if (compileverbose) {
124 if (in->varkind == ARGVAR) printf("ARGVAR in instack: \n");
125 if (in->varkind == LOCALVAR)
126 printf("LOCALVAR in instack\n");
130 out=m->basicblocks[b_index].outstack;
131 outd=m->basicblocks[b_index].outdepth;
132 for (;outd != 0;out=out->prev, outd--) {
133 if (out->varkind == ARGVAR)
134 { log_text("ARGVAR in outstack\n"); assert(0); }
135 if (out->varkind == LOCALVAR)
136 { log_text("LOCALVAR in outstack\n"); assert(0); }
144 #if defined(LSRA_DEBUG_CHECK) || defined(LSRA_DEBUG_VERBOSE)
145 #if defined(LSRA_DEBUG_VERBOSE)
146 if (compileverbose) {
147 printf("%s %s ",m->class->name->text, m->name->text);
148 if (code_is_leafmethod(jd->code))
149 printf("**Leafmethod**");
153 if (strcmp(m->class->name->text,"java/lang/String")==0)
154 if (strcmp(m->name->text,"toLowerCase")==0)
155 #if defined(LSRA_DEBUG_VERBOSE)
157 printf("12-------------------12\n");
159 { int dummy=1; dummy++; }
165 #if defined(ENABLE_STATISTICS)
166 /* find conflicts between locals for statistics */
168 /* local Variable Lifetimes are at the end of the lifetime array and */
169 /* have v_index >= 0 */
170 for (locals_start = ls->lifetimecount-1; (locals_start >=0) &&
171 (ls->lifetime[ls->lt_used[locals_start]].v_index >= 0);
173 for (i=locals_start + 1; i < ls->lifetimecount; i++)
174 for (j=i+1; j < ls->lifetimecount; j++)
175 if ( !((ls->lifetime[ls->lt_used[i]].i_end
176 < ls->lifetime[ls->lt_used[j]].i_start)
177 || (ls->lifetime[ls->lt_used[j]].i_end <
178 ls->lifetime[ls->lt_used[i]].i_start)) )
179 count_locals_conflicts += 2;
189 void lsra_setup(jitdata *jd)
196 #if defined(ENABLE_LOOPS)
197 /* Loop optimization "destroys" the basicblock array */
198 /* TODO: work with the basicblock list */
200 log_text("lsra not possible with loop optimization\n");
210 #ifdef LSRA_DEBUG_VERBOSE
211 if (compileverbose) {
212 printf("Lifetimes after LifenessAnalyse: \n");
213 print_all_lifetimes(jd);
217 lsra_calc_lifetime_length(jd);
219 #ifdef LSRA_DEBUG_VERBOSE
220 if (compileverbose) {
221 printf("Basicblockcount: %4i\n",ls->basicblockcount);
226 void lsra_reg_setup(jitdata *jd,
227 struct lsra_register *int_reg,
228 struct lsra_register *flt_reg ) {
229 int i, j, iarg, farg;
232 bool *fltarg_used, *intarg_used;
241 int_reg->nregdesc = nregdescint;
242 flt_reg->nregdesc = nregdescfloat;
243 if (code_is_leafmethod(jd->code)) {
244 /* Temp and Argumentregister can be used as saved registers */
246 int_reg->sav_top = INT_ARG_CNT + INT_TMP_CNT + INT_SAV_CNT;
247 int_reg->sav_reg = DMNEW(int, int_reg->sav_top);
248 int_reg->tmp_reg = NULL;
249 int_reg->tmp_top = -1;
250 flt_reg->sav_top = FLT_ARG_CNT + FLT_TMP_CNT + FLT_SAV_CNT;
251 flt_reg->sav_reg = DMNEW(int, flt_reg->sav_top);
252 flt_reg->tmp_reg = NULL;
253 flt_reg->tmp_top = -1;
255 /* additionaly precolour registers for Local Variables acting as */
261 intarg_used = DMNEW(bool, INT_ARG_CNT);
262 for (i=0; i < INT_ARG_CNT; i++)
263 intarg_used[i]=false;
265 fltarg_used = DMNEW(bool, FLT_ARG_CNT);
266 for (i=0; i < FLT_ARG_CNT; i++)
267 fltarg_used[i]=false;
269 int_sav_top=int_reg->sav_top;
270 flt_sav_top=flt_reg->sav_top;
272 for (i=0; (i < md->paramcount); i++) {
273 if (!md->params[i].inmemory) {
274 if (IS_INT_LNG_TYPE(md->paramtypes[i].type)) {
275 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
276 if (IS_2_WORD_TYPE(md->paramtypes[i].type)) {
277 int_reg->sav_reg[--int_sav_top] =
278 GET_HIGH_REG(md->params[i].regoff);
279 intarg_used[GET_HIGH_REG(md->params[i].regoff)]=true;
280 /*used -> don't copy later on */
281 int_reg->sav_reg[--int_sav_top] =
282 GET_LOW_REG(md->params[i].regoff);
283 intarg_used[GET_LOW_REG(md->params[i].regoff)]=true;
284 /*used -> don't copy later on */
287 { /* !IS_2_WORD_TYPE(md->paramtypes[i].type */
288 int_reg->sav_reg[--int_sav_top] =
289 md->params[i].regoff;
290 intarg_used[md->params[i].regoff]=true;
291 /*used -> don't copy later on */
294 #if !defined(SUPPORT_PASS_FLOATARGS_IN_INTREGS)
295 /* do not precolour float arguments if they are passed in */
296 /* integer registers. But these integer argument registers */
297 /* still be used in the method! */
298 else { /* IS_FLT_DBL_TYPE(md->paramtypes[i].type */
299 flt_reg->sav_reg[--flt_sav_top] =
300 md->params[i].regoff;
301 fltarg_used[md->params[i].regoff]=true;
308 /* copy rest of argument registers to flt_reg->sav_reg and */
309 /* int_reg->sav_reg; */
310 for (i=0; i < INT_ARG_CNT; i++)
312 int_reg->sav_reg[--int_sav_top]=i;
313 for (i=0; i < FLT_ARG_CNT; i++)
315 flt_reg->sav_reg[--flt_sav_top]=i;
317 /* copy temp registers to flt_reg->sav_reg and int_reg->sav_reg */
318 for (i=0; i < INT_TMP_CNT; i++)
319 int_reg->sav_reg[--int_sav_top]=rd->tmpintregs[i];
320 for (i=0; i < FLT_TMP_CNT; i++)
321 flt_reg->sav_reg[--flt_sav_top]=rd->tmpfltregs[i];
324 /* non leaf method -> use Argument Registers [arg[int|flt]reguse */
325 /* ... [INT|FLT]_ARG_CNT[ as temp reg */
326 /* divide temp and saved registers */
328 int argintreguse, argfltreguse;
330 /* with Locals as non SAVEDVAR, the used arg[int|flt] as in params */
331 /* of the method itself have to be regarded, or mismatch before */
332 /* block 0 with parameter copy could happen! */
334 argintreguse = max(rd->argintreguse, md->argintreguse);
335 argfltreguse = max(rd->argfltreguse, md->argfltreguse);
337 int_sav_top = int_reg->sav_top = INT_SAV_CNT;
338 int_reg->sav_reg = DMNEW(int, int_reg->sav_top);
339 int_reg->tmp_top = INT_TMP_CNT +
340 max(0, (INT_ARG_CNT - argintreguse));
341 int_reg->tmp_reg = DMNEW(int, int_reg->tmp_top);
343 flt_sav_top =flt_reg->sav_top = FLT_SAV_CNT;
344 flt_reg->sav_reg = DMNEW(int, flt_reg->sav_top);
345 flt_reg->tmp_top = FLT_TMP_CNT +
346 max(0 , (FLT_ARG_CNT - argfltreguse));
347 flt_reg->tmp_reg = DMNEW(int, flt_reg->tmp_top);
349 /* copy temp and unused argument registers to flt_reg->tmp_reg and */
350 /* int_reg->tmp_reg */
352 for (i=0; i < INT_TMP_CNT; i++)
353 int_reg->tmp_reg[i]=rd->tmpintregs[i];
355 /* quick and dirty patch for the drop of rd->argxxxreg[] - but will */
356 /* work anyhow on i386, !! has to be made "real" for other archs */
358 for (j = argintreguse; j < INT_ARG_CNT; j++, i++)
359 int_reg->tmp_reg[i]=j;
360 for (i=0; i < FLT_TMP_CNT; i++)
361 flt_reg->tmp_reg[i]=rd->tmpfltregs[i];
363 /* quick and dirty patch for the drop of rd->argxxxreg[] - but will */
364 /* work anyhow on i386, !! has to be made "real" for other archs */
366 for (j = argfltreguse; j < FLT_ARG_CNT; j++, i++)
367 flt_reg->tmp_reg[i]=j;
370 /* now copy saved registers to flt_reg->sav_reg and int_reg->sav_reg */
371 for (i = INT_SAV_CNT-1; i >= 0; i--)
372 int_reg->sav_reg[--int_sav_top]=rd->savintregs[i];
373 for (i = FLT_SAV_CNT-1; i >= 0; i--)
374 flt_reg->sav_reg[--flt_sav_top]=rd->savfltregs[i];
378 void lsra_insertion( struct lsradata *ls, int *a, int lo, int hi) {
381 for (i=lo+1; i<=hi; i++) {
383 t=ls->lifetime[a[j]].i_start;
385 while ((j>lo) && (ls->lifetime[a[j-1]].i_start > t)) {
393 void lsra_qsort( struct lsradata *ls, int *a, int lo, int hi) {
399 x = ls->lifetime[a[(lo+hi)/2]].i_start;
402 while (ls->lifetime[a[i]].i_start < x) i++;
403 while (ls->lifetime[a[j]].i_start > x) j--;
405 /* exchange a[i], a[j] */
415 if (lo < j) lsra_qsort( ls, a, lo, j);
416 if (i < hi) lsra_qsort( ls, a, i, hi);
418 lsra_insertion(ls, a, lo, hi);
422 void lsra_param_sort(struct lsradata *ls, int *lifetime, int lifetime_count) {
427 /* count number of parameters ( .i_start == 0) */
428 for (param_count=0; (param_count < lifetime_count) &&
429 (ls->lifetime[lifetime[param_count]].i_start == 0); param_count++);
431 if (param_count > 0) {
432 /* now sort the parameters by v_index */
433 for (i=0; i < param_count -1; i++)
434 for (j=i+1; j < param_count; j++)
435 if ( ls->lifetime[lifetime[i]].v_index >
436 ls->lifetime[lifetime[j]].v_index) {
439 lifetime[i]=lifetime[j];
445 void lsra_main(jitdata *jd)
447 #ifdef LSRA_DEBUG_VERBOSE
452 struct lsra_register flt_reg, int_reg;
461 /* sort lifetimes by increasing start */
462 lsra_qsort( ls, ls->lt_mem, 0, ls->lt_mem_count - 1);
463 lsra_qsort( ls, ls->lt_int, 0, ls->lt_int_count - 1);
464 lsra_qsort( ls, ls->lt_flt, 0, ls->lt_flt_count - 1);
465 /* sort local vars used as parameter */
466 lsra_param_sort( ls, ls->lt_int, ls->lt_int_count);
467 lsra_param_sort( ls, ls->lt_flt, ls->lt_flt_count);
468 lsra_reg_setup(jd, &int_reg, &flt_reg);
470 #ifdef LSRA_DEBUG_VERBOSE
471 if (compileverbose) {
472 printf("INTSAV REG: ");
473 for (i=0; i<int_reg.sav_top; i++)
474 printf("%2i ",int_reg.sav_reg[i]);
475 printf("\nINTTMP REG: ");
476 for (i=0; i<int_reg.tmp_top; i++)
477 printf("%2i ",int_reg.tmp_reg[i]);
478 printf("\nFLTSAV REG: ");
479 for (i=0; i<flt_reg.sav_top; i++)
480 printf("%2i ",flt_reg.sav_reg[i]);
481 printf("\nFLTTMP REG: ");
482 for (i=0; i<flt_reg.tmp_top; i++)
483 printf("%2i ",flt_reg.tmp_reg[i]);
488 ls->active_tmp = DMNEW( struct lifetime *, max(INT_REG_CNT, FLT_REG_CNT));
489 ls->active_sav = DMNEW( struct lifetime *, max(INT_REG_CNT, FLT_REG_CNT));
491 lsra_reg_use=INT_SAV_CNT; /* init to no saved reg used... */
492 _lsra_main(jd, ls->lt_int, ls->lt_int_count, &int_reg,
494 if (lsra_reg_use > INT_SAV_CNT) lsra_reg_use=INT_SAV_CNT;
495 rd->savintreguse = lsra_reg_use;
497 lsra_reg_use = FLT_SAV_CNT; /* no saved reg used... */
499 _lsra_main(jd, ls->lt_flt, ls->lt_flt_count, &flt_reg, &lsra_reg_use);
500 if (lsra_reg_use > FLT_SAV_CNT) lsra_reg_use=FLT_SAV_CNT;
502 rd->savfltreguse=lsra_reg_use;
504 /* rd->memuse was already set in stack.c to allocate stack space for */
505 /* passing arguments to called methods */
506 #if defined(__I386__)
507 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
508 /* reserve 0(%esp) for Monitorenter/exit Argument on i386 */
514 lsra_mem_use = rd->memuse; /* Init with memuse from stack.c */
516 lsra_alloc(jd, ls->lt_mem, ls->lt_mem_count, &lsra_mem_use);
517 lsra_alloc(jd, ls->lt_int, ls->lt_int_count, &lsra_mem_use);
518 lsra_alloc(jd, ls->lt_flt, ls->lt_flt_count, &lsra_mem_use);
520 rd->memuse=lsra_mem_use;
522 #ifdef LSRA_DEBUG_VERBOSE
523 if (compileverbose) {
524 printf("Int RA complete \n");
525 printf("Lifetimes after splitting int: \n");
526 print_lifetimes(jd, ls->lt_int, ls->lt_int_count);
528 printf("Flt RA complete \n");
529 printf("Lifetimes after splitting flt:\n");
530 print_lifetimes(jd, ls->lt_flt, ls->lt_flt_count);
532 printf("Rest RA complete \n");
533 printf("Lifetimes after leftt:\n");
534 print_lifetimes(jd, ls->lt_mem, ls->lt_mem_count);
536 printf("jd->varcount: %i jd->vartop %i\n", jd->varcount, jd->vartop);
541 void lsra_alloc(jitdata *jd, int *lifet, int lifetimecount, int *mem_use)
545 struct freemem *fmem;
547 #ifdef HAS_4BYTE_STACKSLOT
548 struct freemem *fmem_2;
558 fmem=DNEW(struct freemem);
561 #ifdef HAS_4BYTE_STACKSLOT
562 fmem_2=DNEW(struct freemem);
567 for (lt_index = 0; lt_index < lifetimecount; lt_index ++) {
568 lt = ls->lifetime + lifet[lt_index];
572 if (lt->regoff == -1) {
574 #ifdef HAS_4BYTE_STACKSLOT
575 if (IS_2_WORD_TYPE(lt->type))
576 regoff = lsra_getmem(lt, fmem_2, mem_use);
579 regoff = lsra_getmem(lt, fmem, mem_use);
581 flags = lt->savedvar;
586 VAR(lt->v_index)->vv.regoff = regoff;
587 VAR(lt->v_index)->flags = flags;
591 int lsra_getmem(struct lifetime *lt, struct freemem *fmem, int *mem_use)
593 struct freemem *fm, *p;
595 /* no memmory allocated till now, or all other are still live */
596 if ((fmem->next == NULL) || (fmem->next->end > lt->i_start)) {
598 #ifdef HAS_4BYTE_STACKSLOT
599 if (IS_2_WORD_TYPE(lt->type))
600 if ( (*mem_use)&1 ) /* align memory location for 2 Word Types */
602 fm=lsra_getnewmem(mem_use);
603 if (IS_2_WORD_TYPE(lt->type))
604 /* allocate a second following Slot for 2 Word Types */
607 fm=lsra_getnewmem(mem_use);
610 /* Speicherstelle frei */
616 for (p=fmem; (p->next!=NULL) && (p->next->end < fm->end); p=p->next);
619 /* HACK: stackslots are 8 bytes on all architectures for now, I hope.
625 struct freemem *lsra_getnewmem(int *mem_use)
629 fm=DNEW(struct freemem);
636 void _lsra_main( jitdata *jd, int *lifet, int lifetimecount,
637 struct lsra_register *reg, int *reg_use)
643 bool temp; /* reg from temp registers (true) or saved registers (false) */
650 #if !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
653 if ((reg->tmp_top+reg->sav_top) == 0) {
655 /* no registers available */
656 for (lt_index = 0; lt_index < lifetimecount; lt_index++)
657 ls->lifetime[lifet[lt_index]].regoff = -1;
661 ls->active_tmp_top = 0;
662 ls->active_sav_top = 0;
664 for (lt_index = 0; lt_index < lifetimecount; lt_index++) {
665 lt = &(ls->lifetime[lifet[lt_index]]);
667 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
668 regsneeded = (lt->type == TYPE_LNG)?1:0;
671 lsra_expire_old_intervalls(jd, lt, reg);
675 lt->savedvar = SAVEDVAR;
677 if (lt->savedvar || code_is_leafmethod(jd->code)) {
678 /* use Saved Reg (in case of leafmethod all regs are saved regs) */
679 if (reg->sav_top > regsneeded) {
680 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
682 reg_index = PACK_REGS(reg->sav_reg[--reg->sav_top],
683 reg->sav_reg[--reg->sav_top]);
687 reg_index = reg->sav_reg[--reg->sav_top];
689 } else { /* use Temp Reg or if none is free a Saved Reg */
690 if (reg->tmp_top > regsneeded) {
692 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
694 reg_index = PACK_REGS(reg->tmp_reg[--reg->tmp_top],
695 reg->tmp_reg[--reg->tmp_top]);
698 reg_index = reg->tmp_reg[--reg->tmp_top];
701 if (reg->sav_top > regsneeded) {
703 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
705 reg_index = PACK_REGS(reg->sav_reg[--reg->sav_top],
706 reg->sav_reg[--reg->sav_top]);
709 reg_index = reg->sav_reg[--reg->sav_top];
712 if (reg_index == -1) /* no reg is available anymore... -> spill */
713 spill_at_intervall(jd, lt);
715 lt->regoff = reg_index;
717 lsra_add_active(lt, ls->active_tmp, &(ls->active_tmp_top));
719 if (reg->sav_top<*reg_use) *reg_use=reg->sav_top;
720 lsra_add_active(lt, ls->active_sav, &(ls->active_sav_top));
726 void lsra_add_active(struct lifetime *lt, struct lifetime **active,
731 for(i = 0; (i < *active_top) && (active[i]->i_end < lt->i_end); i++);
733 for(j = *active_top; j > i; j--) active[j] = active[j-1];
741 void lsra_expire_old_intervalls(jitdata *jd,
742 struct lifetime *lt, struct lsra_register *reg)
744 _lsra_expire_old_intervalls(jd, lt, reg, jd->ls->active_tmp,
745 &(jd->ls->active_tmp_top));
746 _lsra_expire_old_intervalls(jd, lt, reg, jd->ls->active_sav,
747 &(jd->ls->active_sav_top));
750 void _lsra_expire_old_intervalls(jitdata *jd, struct lifetime *lt,
751 struct lsra_register *reg,
752 struct lifetime **active, int *active_top)
756 for(i = 0; i < *active_top; i++) {
757 if (active[i]->i_end > lt->i_start) break;
759 /* make active[i]->reg available again */
760 if (code_is_leafmethod(jd->code)) {
761 /* leafmethod -> don't care about type -> put all again into */
763 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
764 if (active[i]->type == TYPE_LNG) {
765 reg->sav_reg[reg->sav_top++] = GET_LOW_REG(active[i]->reg);
766 reg->sav_reg[reg->sav_top++] = GET_HIGH_REG(active[i]->reg);
769 reg->sav_reg[reg->sav_top++] = active[i]->regoff;
771 /* no leafmethod -> distinguish between temp and saved register */
772 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
773 if (active[i]->type == TYPE_LNG) {
774 /* no temp and saved regs are packed together, so looking at */
775 /* LOW_REG is sufficient */
776 if ( reg->nregdesc[ GET_LOW_REG(active[i]->reg)] == REG_SAV) {
777 reg->sav_reg[reg->sav_top++] = GET_LOW_REG(active[i]->reg);
778 reg->sav_reg[reg->sav_top++] = GET_HIGH_REG(active[i]->reg);
780 reg->tmp_reg[reg->tmp_top++] = GET_LOW_REG(active[i]->reg);
781 reg->tmp_reg[reg->tmp_top++] = GET_HIGH_REG(active[i]->reg);
785 if ( reg->nregdesc[active[i]->regoff] == REG_SAV) {
786 reg->sav_reg[reg->sav_top++] = active[i]->regoff;
788 reg->tmp_reg[reg->tmp_top++] = active[i]->regoff;
793 /* active[0..i[ is to be removed */
794 /* -> move [i..*active_top[ to [0..*active_top-i[ */
795 for(k = 0, j = i; (j < *active_top); k++,j++)
796 active[k] = active[j];
802 void spill_at_intervall(jitdata *jd, struct lifetime *lt )
808 if (lt->savedvar || code_is_leafmethod(jd->code)) {
809 _spill_at_intervall(lt, ls->active_sav, &(ls->active_sav_top));
811 _spill_at_intervall(lt, ls->active_tmp, &(ls->active_tmp_top));
812 if (lt->regoff == -1) { /* kein tmp mehr frei gewesen */
813 _spill_at_intervall(lt, ls->active_sav, &(ls->active_sav_top));
818 void _spill_at_intervall(struct lifetime *lt, struct lifetime **active,
825 #endif /* USAGE_COUNT */
828 if (*active_top == 0) {
836 /* find intervall which ends later or equal than than lt and has the */
837 /* lowest usagecount lower than lt */
839 u_min = lt->usagecount;
840 for (; (i >= 0) && (active[i]->i_end >= lt->i_end); i--) {
841 if (active[i]->usagecount < u_min) {
842 u_min = active[i]->usagecount;
850 if ((active[i]->i_end >= lt->i_end) &&
851 (active[i]->usagecount < lt->usagecount)) {
852 #else /* USAGE_COUNT */
853 /* get last intervall from active */
854 if (active[i]->i_end > lt->i_end) {
855 #endif /* USAGE_COUNT */
857 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
858 /* Don't spill between one and two word int types */
859 if ((active[i]->type == TYPE_LNG) != (lt->type == TYPE_LNG))
863 lt->regoff = active[i]->regoff;
864 active[i]->regoff = -1;
867 for (j = i; j < *active_top; j++)
868 active[j] = active[j + 1];
870 lsra_add_active(lt, active, active_top);
876 void lsra_calc_lifetime_length(jitdata *jd)
882 int *icount_block, icount;
883 int flags; /* 0 INMEMORY -> ls->lt_mem */
884 /* 1 INTREG -> ls->lt_int */
885 /* 2 FLTREG -> ls->lt_flt */
891 icount_block = DMNEW(int, ls->basicblockcount);
892 icount_block[0] = icount = 0 /* + ls->max_vars_with_indices + 1 */;
893 for (i=1; i < ls->basicblockcount; i++) {
894 if (ls->sorted[i-1] != -1)
895 icount += ls->basicblocks[ls->sorted[i-1]]->icount + 1 +
896 ls->varcount_with_indices;
897 if (ls->sorted[i] != -1)
898 icount_block[i] = icount;
901 #ifdef LSRA_DEBUG_VERBOSE
902 if (compileverbose) {
903 printf("icount_block: ");
904 for (i=0; i < ls->basicblockcount; i++)
905 printf("(%3i-%3i) ",i, icount_block[i]);
911 for(lt_index = 0 ;lt_index < ls->lifetimecount; lt_index++) {
912 if ( ls->lifetime[lt_index].type != -1) { /* used lifetime */
913 /* remember lt_index in lt_sorted */
914 ls->lt_used[lifetimecount ++] = lt_index;
915 lt = &(ls->lifetime[lt_index]);
917 /* compute lt->bb_first_def, i_first_def, bb_last_use and */
920 _LSRA_ASSERT(lt->def != NULL);
921 /* _LSRA_ASSERT(lt->use != NULL);*/
925 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
926 /* prevent conflicts between lifetimes of type long by increasing */
927 /* the lifetime by one instruction */
928 /* i.e.(ri/rj) ... */
929 /* (rk/rl) ICMD_LNEG */
930 /* with i==l and/or j==k */
931 /* to resolve this during codegeneration a temporary register */
932 /* would be needed */
933 if (lt->type == TYPE_LNG)
937 /* distribute lifetimes to lt_int, lt_flt and lt_mem */
943 #if (defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)) || defined (__I386__)
956 #if defined(__I386__)
958 * for i386 put all floats in memory
966 { log_text("Unknown Type\n"); exit(1); }
970 case 0: /* lt_used[lt_used_index] -> lt_rest */
971 ls->lt_mem[ ls->lt_mem_count++ ] = lt_index;
973 case 1: /* l->lifetimes -> lt_int */
974 ls->lt_int[ ls->lt_int_count++ ] = lt_index;
976 case 2: /* l->lifetimes -> lt_flt */
977 ls->lt_flt[ ls->lt_flt_count++ ] = lt_index;
982 if (lt->bb_first_def < -1) {
983 printf("--------- Warning: variable not defined!------------------vi: %i start: %i end: %i\n", lt->v_index, lt->i_start, lt->i_end);
984 lt->bb_first_def = 0;
988 lt->i_start = icount_block[lt->bb_first_def] + lt->i_first_def;
990 if (lt->bb_last_use == -1) {
991 /* unused Vars are not regarded by lifeness_analysis! */
992 _LSRA_ASSERT(lt->def != NULL)
993 _LSRA_ASSERT(lt->def->next == NULL)
995 if (compileverbose) {
996 printf("--------- Warning: variable not used! ---------");
997 printf("vi: %i start: %i end: %i\n", lt->v_index,
998 lt->i_start, lt->i_end);
1000 lt->bb_last_use = lt->bb_first_def;
1001 lt->i_last_use = lt->i_first_def;
1004 lt->i_end = icount_block[lt->bb_last_use] + lt->i_last_use;
1006 if (lt->i_start < 0)
1007 printf("------- Error: Lt %3i Vi %4i invalid!\n",lt_index, lt->v_index);
1009 if (lt->i_start > lt->i_end)
1010 printf("--------- Warning: last use before first def! vi: %i start: %i end: %i\n", lt->v_index, lt->i_start, lt->i_end);
1012 #ifdef USAGE_PER_INSTR
1013 lt->usagecount = lt->usagecount / ( lt->i_end - lt->i_start + 1);
1017 ls->lifetimecount = lifetimecount;
1020 #ifdef LSRA_DEBUG_VERBOSE
1021 void print_lifetimes(jitdata *jd, int *lt, int lifetimecount)
1031 for (lt_index = 0; lt_index < lifetimecount; lt_index++) {
1032 n = ls->lifetime + lt[lt_index];
1033 printf("i_Start: %3i(%3i,%3i) i_stop: %3i(%3i,%3i) reg: %3i VI: %3i type: %3i flags: %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,n->regoff,n->v_index,n->type,n->flags, n->usagecount, n->flags);
1035 printf( "%3i Lifetimes printed \n",lt_index);
1038 void print_all_lifetimes(jitdata *jd)
1048 for (lt_index = 0; lt_index < ls->lifetimecount; lt_index++) {
1049 n = &(ls->lifetime[lt_index]);
1050 if (n->type != -1) {
1051 printf("i_Start: %3i(%3i,%3i) i_stop: %3i(%3i,%3i) VI: %3i type: %3i flags: %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,n->v_index,n->type,n->flags, n->usagecount, n->flags);
1054 printf( "%3i Lifetimes printed \n",lt_index);
1059 * These are local overrides for various environment variables in Emacs.
1060 * Please do not remove this and leave it at the end of the file, where
1061 * Emacs will automagically detect them.
1062 * ---------------------------------------------------------------------
1065 * indent-tabs-mode: t