1 /* src/vm/jit/reg.inc - 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: Andreas Krall
33 $Id: reg.inc 2811 2005-06-23 14:19:18Z christian $
39 #include "mm/memory.h"
40 #include "vm/method.h"
41 #include "vm/resolve.h"
42 #include "vm/jit/reg.h"
45 /* function prototypes for this file */
47 static void interface_regalloc(methodinfo *m, codegendata *cd, registerdata *rd);
48 static void local_regalloc(methodinfo *m, codegendata *cd, registerdata *rd);
49 static void allocate_scratch_registers(methodinfo *m, registerdata *rd);
52 /* reg_init ********************************************************************
56 *******************************************************************************/
64 /* reg_setup *******************************************************************
68 *******************************************************************************/
70 void reg_setup(methodinfo *m, registerdata *rd, t_inlining_globals *id)
75 /* setup the integer register table */
77 rd->argintregs = DMNEW(s4, INT_ARG_CNT);
78 rd->tmpintregs = DMNEW(s4, INT_TMP_CNT);
79 rd->savintregs = DMNEW(s4, INT_SAV_CNT);
80 rd->freeargintregs = DMNEW(s4, INT_ARG_CNT);
81 rd->freetmpintregs = DMNEW(s4, INT_TMP_CNT);
82 rd->freesavintregs = DMNEW(s4, INT_SAV_CNT);
88 for (i = 0; i < INT_REG_CNT; i++) {
89 switch (nregdescint[i]) {
94 rd->savintregs[rd->savintreguse++] = i;
97 rd->tmpintregs[rd->tmpintreguse++] = i;
100 rd->argintregs[rd->argintreguse++] = i;
104 assert(rd->savintreguse == INT_SAV_CNT);
105 assert(rd->tmpintreguse == INT_TMP_CNT);
106 assert(rd->argintreguse == INT_ARG_CNT);
108 #if defined(__X86_64__)
110 * on x86_64 the argument registers are not in ascending order
111 * a00 (%rdi) <-> a03 (%rcx) and a01 (%rsi) <-> a02 (%rdx)
113 i = rd->argintregs[3];
114 rd->argintregs[3] = rd->argintregs[0];
115 rd->argintregs[0] = i;
117 i = rd->argintregs[2];
118 rd->argintregs[2] = rd->argintregs[1];
119 rd->argintregs[1] = i;
122 #ifdef HAS_ADDRESS_REGISTER_FILE
123 /* setup the address register table */
125 rd->argadrregs = DMNEW(s4, ADR_ARG_CNT);
126 rd->tmpadrregs = DMNEW(s4, ADR_TMP_CNT);
127 rd->savadrregs = DMNEW(s4, ADR_SAV_CNT);
128 rd->freeargadrregs = DMNEW(s4, ADR_ARG_CNT);
129 rd->freetmpadrregs = DMNEW(s4, ADR_TMP_CNT);
130 rd->freesavadrregs = DMNEW(s4, ADR_SAV_CNT);
132 rd->adrreg_argnum = 0;
133 rd->argadrreguse = 0;
134 rd->tmpadrreguse = 0;
135 rd->savadrreguse = 0;
137 for (i = 0; i < ADR_REG_CNT; i++) {
138 switch (nregdescadr[i]) {
143 rd->savadrregs[rd->savadrreguse++] = i;
146 rd->tmpadrregs[rd->tmpadrreguse++] = i;
149 rd->argadrregs[rd->argadrreguse++] = i;
153 assert(rd->savadrreguse == ADR_SAV_CNT);
154 assert(rd->tmpadrreguse == ADR_TMP_CNT);
155 assert(rd->argadrreguse == ADR_ARG_CNT);
158 /* setup the float register table */
160 rd->argfltregs = DMNEW(s4, FLT_ARG_CNT);
161 rd->tmpfltregs = DMNEW(s4, FLT_TMP_CNT);
162 rd->savfltregs = DMNEW(s4, FLT_SAV_CNT);
163 rd->freeargfltregs = DMNEW(s4, FLT_ARG_CNT);
164 rd->freetmpfltregs = DMNEW(s4, FLT_TMP_CNT);
165 rd->freesavfltregs = DMNEW(s4, FLT_SAV_CNT);
167 rd->argfltreguse = 0;
168 rd->tmpfltreguse = 0;
169 rd->savfltreguse = 0;
171 for (i = 0; i < FLT_REG_CNT; i++) {
172 switch (nregdescfloat[i]) {
177 rd->savfltregs[rd->savfltreguse++] = i;
180 rd->tmpfltregs[rd->tmpfltreguse++] = i;
183 rd->argfltregs[rd->argfltreguse++] = i;
187 assert(rd->savfltreguse == FLT_SAV_CNT);
188 assert(rd->tmpfltreguse == FLT_TMP_CNT);
189 assert(rd->argfltreguse == FLT_ARG_CNT);
192 rd->freemem = DMNEW(s4, id->cummaxstack);
193 #if defined(HAS_4BYTE_STACKSLOT)
194 rd->freemem_2 = DMNEW(s4, id->cummaxstack);
196 rd->locals = DMNEW(varinfo5, id->cumlocals);
197 rd->interfaces = DMNEW(varinfo5, id->cummaxstack);
198 for (v = rd->locals, i = id->cumlocals; i > 0; v++, i--) {
199 v[0][TYPE_INT].type = -1;
200 v[0][TYPE_LNG].type = -1;
201 v[0][TYPE_FLT].type = -1;
202 v[0][TYPE_DBL].type = -1;
203 v[0][TYPE_ADR].type = -1;
206 for (v = rd->interfaces, i = id->cummaxstack; i > 0; v++, i--) {
207 v[0][TYPE_INT].type = -1;
208 v[0][TYPE_INT].flags = 0;
209 v[0][TYPE_LNG].type = -1;
210 v[0][TYPE_LNG].flags = 0;
211 v[0][TYPE_FLT].type = -1;
212 v[0][TYPE_FLT].flags = 0;
213 v[0][TYPE_DBL].type = -1;
214 v[0][TYPE_DBL].flags = 0;
215 v[0][TYPE_ADR].type = -1;
216 v[0][TYPE_ADR].flags = 0;
219 #if defined(SPECIALMEMUSE)
220 # if defined(__DARWIN__)
221 /* 6*4=24 byte linkage area + 8*4=32 byte minimum parameter Area */
222 rd->memuse = LA_WORD_SIZE + INT_ARG_CNT;
224 rd->memuse = LA_WORD_SIZE;
227 rd->memuse = 0; /* init to zero -> analyse_stack will set it to a higher */
228 /* value, if appropriate */
231 /* Set rd->argxxxreguse to XXX_ARG_CNBT to not use unused argument */
232 /* registers as temp registers */
233 #if defined(HAS_ADDRESS_REGISTER_FILE)
234 rd->argadrreguse = 0;
235 #endif /* defined(HAS_ADDRESS_REGISTER_FILE) */
236 rd->argintreguse = 0;
237 rd->argfltreguse = 0;
241 /* function reg_free ***********************************************************
243 releases all allocated space for registers
245 *******************************************************************************/
247 void reg_free(methodinfo *m, registerdata *rd)
253 /* reg_close *******************************************************************
257 *******************************************************************************/
265 /* function interface_regalloc *************************************************
267 allocates registers for all interface variables
269 *******************************************************************************/
271 void regalloc(methodinfo *m, codegendata *cd, registerdata *rd)
273 interface_regalloc(m, cd, rd);
274 allocate_scratch_registers(m, rd);
275 local_regalloc(m, cd, rd);
276 #ifdef INVOKE_NEW_DEBUG
277 if (compileverbose) {
278 printf("memuse after reg.inc: %3i\n",rd->memuse);
284 /* function interface_regalloc *************************************************
286 allocates registers for all interface variables
288 *******************************************************************************/
290 static void interface_regalloc(methodinfo *m, codegendata *cd, registerdata *rd)
293 int intalloc, fltalloc; /* Remember allocated Register/Memory offset */
294 /* in case a more vars are packed into this interface slot */
296 int intregsneeded = 0;
298 /* allocate LNG and DBL Types first to ensure 2 memory slots or registers */
299 /* on HAS_4BYTE_STACKSLOT architectures */
300 int typeloop[] = { TYPE_LNG, TYPE_DBL, TYPE_INT, TYPE_FLT, TYPE_ADR };
302 /* rd->memuse was already set in stack.c to allocate stack space for */
303 /* passing arguments to called methods */
304 #if defined(__I386__)
305 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
306 /* reserve 0(%esp) for Monitorenter/exit Argument on i386 */
311 #ifdef INVOKE_NEW_DEBUG
312 if (compileverbose) {
313 if (checksync && (m->flags & ACC_SYNCHRONIZED))
314 printf("ACC_SYNCHRONIZED\n");
315 printf("analyse: argintru %3i argfltru %3i memuse %3i\n",
316 rd->argintreguse, rd->argfltreguse, rd->memuse);
321 for (s = 0; s < cd->maxstack; s++) {
322 intalloc = -1; fltalloc = -1;
323 saved = (rd->interfaces[s][TYPE_INT].flags |
324 rd->interfaces[s][TYPE_LNG].flags |
325 rd->interfaces[s][TYPE_FLT].flags |
326 rd->interfaces[s][TYPE_DBL].flags |
327 rd->interfaces[s][TYPE_ADR].flags) & SAVEDVAR;
329 for (tt = 0; tt <= 4; tt++) {
331 v = &rd->interfaces[s][t];
333 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
334 intregsneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
336 #if defined(HAS_4BYTE_STACKSLOT)
337 memneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
340 #if defined(HAS_ADDRESS_REGISTER_FILE)
341 if (IS_ADR_TYPE(t)) {
343 &&(rd->argadrreguse < ADR_ARG_CNT)) {
344 v->regoff = rd->argadrregs[rd->argadrreguset++];
345 } else if (rd->tmpadrreguse > 0) {
346 v->regoff = rd->tmpadrregs[--rd->tmpadrreguse];
347 } else if (rd->savadrreguse > 0) {
348 v->regoff = rd->savadrregs[--rd->savadrreguse];
350 v->flags |= INMEMORY;
351 v->regoff = rd->memuse++;
353 } else /* !IS_ADR_TYPE */
354 #endif /* defined(HAS_ADDRESS_REGISTER_FILE) */
356 if (IS_FLT_DBL_TYPE(t)) {
358 /* Reuse memory slot(s)/register(s) for shared interface slots */
359 v->flags |= rd->interfaces[s][fltalloc].flags
361 v->regoff = rd->interfaces[s][fltalloc].regoff;
362 } else if (!m->isleafmethod
363 && (rd->argfltreguse < FLT_ARG_CNT)) {
364 v->regoff = rd->argfltregs[rd->argfltreguse++];
365 } else if (rd->tmpfltreguse > 0) {
366 v->regoff = rd->tmpfltregs[--rd->tmpfltreguse];
367 } else if (rd->savfltreguse > 0) {
368 v->regoff = rd->savfltregs[--rd->savfltreguse];
370 v->flags |= INMEMORY;
371 v->regoff = rd->memuse;
372 rd->memuse += memneeded + 1;
375 } else { /* !IS_FLT_DBL_TYPE(t) */
376 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
378 * for i386 put all longs in memory
380 if (IS_2_WORD_TYPE(t)) {
381 v->flags |= INMEMORY;
382 v->regoff = rd->memuse;
383 rd->memuse += memneeded + 1;
385 #endif /* defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE...GISTERS) */
386 /* #if !defined(HAS_4BYTE_STACKSLOT) */
388 /* Reuse memory slot(s)/register(s) for shared interface slots */
390 rd->interfaces[s][intalloc].flags
392 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
393 if (!(v->flags & INMEMORY)
394 && IS_2_WORD_TYPE(intalloc))
395 v->regoff = GET_LOW_REG(
396 rd->interfaces[s][intalloc].regoff);
400 rd->interfaces[s][intalloc].regoff;
402 /* #endif *//* !defined(HAS_4BYTE_STACKSLOT) */
403 if (!m->isleafmethod &&
405 + intregsneeded < INT_ARG_CNT)) {
406 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
409 rd->argintregs[rd->argintreguse],
410 rd->argintregs[rd->argintreguse + 1]);
414 rd->argintregs[rd->argintreguse];
415 rd->argintreguse += intregsneeded + 1;
417 else if (rd->tmpintreguse > intregsneeded) {
418 rd->tmpintreguse -= intregsneeded + 1;
419 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
422 rd->tmpintregs[rd->tmpintreguse],
423 rd->tmpintregs[rd->tmpintreguse + 1]);
427 rd->tmpintregs[rd->tmpintreguse];
429 else if (rd->savintreguse > intregsneeded) {
430 rd->savintreguse -= intregsneeded + 1;
432 rd->savintregs[rd->savintreguse];
433 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
436 rd->savintregs[rd->savintreguse],
437 rd->savintregs[rd->savintreguse + 1]);
441 rd->savintregs[rd->savintreguse];
444 v->flags |= INMEMORY;
445 v->regoff = rd->memuse;
446 rd->memuse += memneeded + 1;
450 } /* if (IS_FLT_DBL_TYPE(t)) */
452 } else { /* (saved) */
453 /* now the same like above, but without a chance to take a temporary register */
454 #ifdef HAS_ADDRESS_REGISTER_FILE
455 if (IS_ADR_TYPE(t)) {
456 if (rd->savadrreguse > 0) {
457 v->regoff = rd->savadrregs[--rd->savadrreguse];
460 v->flags |= INMEMORY;
461 v->regoff = rd->memuse++;
466 if (IS_FLT_DBL_TYPE(t)) {
468 v->flags |= rd->interfaces[s][fltalloc].flags
470 v->regoff = rd->interfaces[s][fltalloc].regoff;
472 if (rd->savfltreguse > 0) {
473 v->regoff = rd->savfltregs[--rd->savfltreguse];
476 v->flags |= INMEMORY;
477 v->regoff = rd->memuse;
478 rd->memuse += memneeded + 1;
482 else { /* IS_INT_LNG */
483 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
485 * for i386 put all longs in memory
487 if (IS_2_WORD_TYPE(t)) {
488 v->flags |= INMEMORY;
489 v->regoff = rd->memuse;
490 rd->memuse += memneeded + 1;
494 /* #if !defined(HAS_4BYTE_STACKSLOT) */
497 rd->interfaces[s][intalloc].flags & INMEMORY;
498 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
499 if (!(v->flags & INMEMORY)
500 && IS_2_WORD_TYPE(intalloc))
503 rd->interfaces[s][intalloc].regoff);
507 rd->interfaces[s][intalloc].regoff;
511 if (rd->savintreguse > intregsneeded) {
512 rd->savintreguse -= intregsneeded + 1;
513 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
515 v->regoff = PACK_REGS(
516 rd->savintregs[rd->savintreguse],
517 rd->savintregs[rd->savintreguse + 1]);
521 rd->savintregs[rd->savintreguse];
523 v->flags |= INMEMORY;
524 v->regoff = rd->memuse;
525 rd->memuse += memneeded + 1;
530 } /* if (IS_FLT_DBL_TYPE(t) else */
531 } /* if (IS_ADR_TYPE(t)) else */
532 } /* if (saved) else */
533 } /* if (type >= 0) */
540 /* function local_regalloc *****************************************************
542 allocates registers for all local variables
544 *******************************************************************************/
546 static void local_regalloc(methodinfo *m, codegendata *cd, registerdata *rd)
549 int intalloc, fltalloc;
551 int intregsneeded = 0;
553 int typeloop[] = { TYPE_LNG, TYPE_DBL, TYPE_INT, TYPE_FLT, TYPE_ADR };
554 /* int fargcnt, iargcnt; */
555 #ifdef HAS_ADDRESS_REGISTER_FILE
559 if (m->isleafmethod) {
560 methoddesc *md = m->parseddesc;
562 /* iargcnt = md->argintreguse; */
563 /* fargcnt = md->argfltreguse; */
564 #ifdef HAS_ADDRESS_REGISTER_FILE
565 aargcnt = md->argadrreguse;
567 for (p = 0, s = 0; s < cd->maxlocals; s++, p++) {
568 intalloc = -1; fltalloc = -1;
569 for (tt = 0; tt <= 4; tt++) {
571 v = &rd->locals[s][t];
576 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
577 intregsneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
579 #if defined(HAS_4BYTE_STACKSLOT)
580 memneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
586 * #ifdef HAS_ADDRESS_REGISTER_FILE
593 * } else { / int & lng
597 * must not to be changed!
600 #ifdef HAS_ADDRESS_REGISTER_FILE
601 if (IS_ADR_TYPE(t)) {
602 if ((p < md->paramcount) && !md->params[p].inmemory) {
604 v->regoff = rd->argadrregs[md->params[p].regoff];
606 if (rd->tmpadrreguse > 0) {
608 v->regoff = rd->tmpadrregs[--rd->tmpadrreguse];
610 else if (rd->savadrreguse > 0) {
612 v->regoff = rd->savadrregs[--rd->savadrreguse];
614 /* use unused argument registers as local registers */
615 /* else if ((p >= md->paramcount) && */
616 /* (aargcnt < ADR_ARG_CNT)) { */
618 /* v->regoff = rd->argadrregs[aargcnt++]; */
621 v->flags |= INMEMORY;
622 v->regoff = rd->memuse++;
626 if (IS_FLT_DBL_TYPE(t)) {
628 v->flags = rd->locals[s][fltalloc].flags;
629 v->regoff = rd->locals[s][fltalloc].regoff;
631 else if ((p < md->paramcount) &&
632 !md->params[p].inmemory) {
634 v->regoff = rd->argfltregs[md->params[p].regoff];
636 else if (rd->tmpfltreguse > 0) {
638 v->regoff = rd->tmpfltregs[--rd->tmpfltreguse];
640 else if (rd->savfltreguse > 0) {
642 v->regoff = rd->savfltregs[--rd->savfltreguse];
644 /* use unused argument registers as local registers */
645 /* else if ((p >= m->paramcount) && */
646 /* (fargcnt < rd->fltreg_argnum)) { */
648 /* v->regoff = rd->argfltregs[fargcnt]; */
653 v->regoff = rd->memuse;
654 rd->memuse += memneeded + 1;
659 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
661 * for i386 put all longs in memory
663 if (IS_2_WORD_TYPE(t)) {
665 v->regoff = rd->memuse;
666 rd->memuse += memneeded + 1;
671 v->flags = rd->locals[s][intalloc].flags;
672 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
673 if (!(v->flags & INMEMORY)
674 && IS_2_WORD_TYPE(intalloc))
675 v->regoff = GET_LOW_REG(
676 rd->locals[s][intalloc].regoff);
679 v->regoff = rd->locals[s][intalloc].regoff;
681 else if ((p < md->paramcount) &&
682 !md->params[p].inmemory) {
684 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
685 if (IS_2_WORD_TYPE(t))
686 /* For ARM: - if GET_LOW_REG(md->params[p].regoff) == R4, prevent here that */
687 /* rd->argintregs[GET_HIGH_REG(md->...)) is used! */
688 v->regoff = PACK_REGS(
689 rd->argintregs[GET_LOW_REG(md->params[p].regoff)],
690 rd->argintregs[GET_HIGH_REG(md->params[p].regoff)]);
694 rd->argintregs[md->params[p].regoff];
696 else if (rd->tmpintreguse > intregsneeded) {
697 rd->tmpintreguse -= intregsneeded + 1;
699 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
701 v->regoff = PACK_REGS(
702 rd->tmpintregs[rd->tmpintreguse],
703 rd->tmpintregs[rd->tmpintreguse + 1]);
707 rd->tmpintregs[rd->tmpintreguse];
709 else if (rd->savintreguse > intregsneeded) {
710 rd->savintreguse -= intregsneeded + 1;
712 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
714 v->regoff = PACK_REGS(
715 rd->savintregs[rd->savintreguse],
716 rd->savintregs[rd->savintreguse + 1]);
719 v->regoff =rd->savintregs[rd->savintreguse];
722 * use unused argument registers as local registers
724 /* else if ((p >= m->paramcount) && */
725 /* (iargcnt < rd->intreg_argnum)) { */
727 /* v->regoff = rd->argintregs[iargcnt]; */
732 v->regoff = rd->memuse;
733 rd->memuse += memneeded + 1;
738 #ifdef HAS_ADDRESS_REGISTER_FILE
741 } /* for (tt=0;...) */
743 /* If the current parameter is a 2-word type, the next local slot */
746 if (p < md->paramcount)
747 if (IS_2_WORD_TYPE(md->paramtypes[p].type))
753 for (s = 0; s < cd->maxlocals; s++) {
754 intalloc = -1; fltalloc = -1;
755 for (tt=0; tt<=4; tt++) {
757 v = &rd->locals[s][t];
760 #ifdef SUPPORT_COMBINE_INTEGER_REGISTERS
761 intregsneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
763 #if defined(HAS_4BYTE_STACKSLOT)
764 memneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
766 #ifdef HAS_ADDRESS_REGISTER_FILE
767 if ( IS_ADR_TYPE(t) ) {
768 if (rd->savadrreguse > 0) {
770 v->regoff = rd->savadrregs[--rd->savadrreguse];
774 v->regoff = rd->memuse++;
778 if (IS_FLT_DBL_TYPE(t)) {
780 v->flags = rd->locals[s][fltalloc].flags;
781 v->regoff = rd->locals[s][fltalloc].regoff;
783 else if (rd->savfltreguse > 0) {
785 v->regoff = rd->savfltregs[--rd->savfltreguse];
789 /* Align doubles in Memory */
790 if ( (memneeded) && (rd->memuse & 1))
792 v->regoff = rd->memuse;
793 rd->memuse += memneeded + 1;
798 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
800 * for i386 put all longs in memory
802 if (IS_2_WORD_TYPE(t)) {
804 v->regoff = rd->memuse;
805 rd->memuse += memneeded + 1;
809 v->flags = rd->locals[s][intalloc].flags;
810 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
811 if (!(v->flags & INMEMORY)
812 && IS_2_WORD_TYPE(intalloc))
813 v->regoff = GET_LOW_REG(
814 rd->locals[s][intalloc].regoff);
817 v->regoff = rd->locals[s][intalloc].regoff;
819 else if (rd->savintreguse > intregsneeded) {
820 rd->savintreguse -= intregsneeded+1;
822 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
824 v->regoff = PACK_REGS(
825 rd->savintregs[rd->savintreguse],
826 rd->savintregs[rd->savintreguse + 1]);
829 v->regoff =rd->savintregs[rd->savintreguse];
833 v->regoff = rd->memuse;
834 rd->memuse += memneeded + 1;
836 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
841 #ifdef HAS_ADDRESS_REGISTER_FILE
850 static void reg_init_temp(methodinfo *m, registerdata *rd)
853 #if defined(HAS_4BYTE_STACKSLOT)
854 rd->freememtop_2 = 0;
857 rd->freetmpinttop = 0;
858 rd->freesavinttop = 0;
859 rd->freetmpflttop = 0;
860 rd->freesavflttop = 0;
861 #ifdef HAS_ADDRESS_REGISTER_FILE
862 rd->freetmpadrtop = 0;
863 rd->freesavadrtop = 0;
866 rd->freearginttop = 0;
867 rd->freeargflttop = 0;
868 #ifdef HAS_ADDRESS_REGISTER_FILE
869 rd->freeargadrtop = 0;
873 if (m->isleafmethod) {
874 /* Don't use not used Argument Registers in Leafmethods -> they could */
875 /* already be in use for Locals passed as parameter to this Method */
877 rd->argintreguse = INT_ARG_CNT;
878 rd->argfltreguse = FLT_ARG_CNT;
879 #ifdef HAS_ADDRESS_REGISTER_FILE
880 rd->argadrreguse = ADR_ARG_CNT;
888 #define reg_new_temp(rd,s) if (s->varkind == TEMPVAR) reg_new_temp_func(rd, s)
890 static void reg_new_temp_func(registerdata *rd, stackptr s)
896 /* Try to allocate a saved register if there is no temporary one */
897 /* available. This is what happens during the second run. */
898 tryagain = (s->flags & SAVEDVAR) ? 1 : 2;
900 #ifdef SUPPORT_COMBINE_INTEGER_REGISTERS
901 intregsneeded = (IS_2_WORD_TYPE(s->type)) ? 1 : 0;
905 #if defined(HAS_4BYTE_STACKSLOT)
906 memneeded = (IS_2_WORD_TYPE(s->type)) ? 1 : 0;
911 for(; tryagain; --tryagain) {
913 if (!(s->flags & SAVEDVAR))
914 s->flags |= SAVEDTMP;
915 #ifdef HAS_ADDRESS_REGISTER_FILE
916 if (IS_ADR_TYPE(s->type)) {
917 if (rd->freesavadrtop > 0) {
918 s->regoff = rd->freesavadrregs[--rd->freesavadrtop];
920 } else if (rd->savadrreguse > 0) {
921 s->regoff = rd->savadrregs[--rd->savadrreguse];
927 if (IS_FLT_DBL_TYPE(s->type)) {
928 if (rd->freesavflttop > 0) {
929 s->regoff = rd->freesavfltregs[--rd->freesavflttop];
931 } else if (rd->savfltreguse > 0) {
932 s->regoff = rd->savfltregs[--rd->savfltreguse];
936 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
938 * for i386 put all longs in memory
940 if (!IS_2_WORD_TYPE(s->type))
943 if (rd->freesavinttop > intregsneeded) {
944 rd->freesavinttop -= intregsneeded + 1;
945 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
947 s->regoff = PACK_REGS(
948 rd->freesavintregs[rd->freesavinttop],
949 rd->freesavintregs[rd->freesavinttop + 1]);
953 rd->freesavintregs[rd->freesavinttop];
955 } else if (rd->savintreguse > intregsneeded) {
956 rd->savintreguse -= intregsneeded + 1;
957 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
959 s->regoff = PACK_REGS(
960 rd->savintregs[rd->savintreguse],
961 rd->savintregs[rd->savintreguse + 1]);
964 s->regoff = rd->savintregs[rd->savintreguse];
970 } else { /* tryagain == 2 */
971 #ifdef HAS_ADDRESS_REGISTER_FILE
972 if (IS_ADR_TYPE(s->type)) {
973 if (rd->freetmpadrtop > 0) {
974 s->regoff = rd->freetmpadrregs[--rd->freetmpadrtop];
976 } else if (rd->tmpadrreguse > 0) {
977 s->regoff = rd->tmpadrregs[--rd->tmpadrreguse];
983 if (IS_FLT_DBL_TYPE(s->type)) {
984 if (rd->freeargflttop > 0) {
985 s->regoff = rd->freeargfltregs[--rd->freeargflttop];
988 } else if (rd->argfltreguse < FLT_ARG_CNT) {
989 s->regoff = rd->argfltregs[rd->argfltreguse++];
992 } else if (rd->freetmpflttop > 0) {
993 s->regoff = rd->freetmpfltregs[--rd->freetmpflttop];
995 } else if (rd->tmpfltreguse > 0) {
996 s->regoff = rd->tmpfltregs[--rd->tmpfltreguse];
1001 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
1003 * for i386 put all longs in memory
1005 if (!IS_2_WORD_TYPE(s->type))
1008 if (rd->freearginttop > intregsneeded) {
1009 rd->freearginttop -= intregsneeded + 1;
1011 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
1013 s->regoff = PACK_REGS(
1014 rd->freeargintregs[rd->freearginttop],
1015 rd->freeargintregs[rd->freearginttop + 1]);
1019 rd->freeargintregs[rd->freearginttop];
1021 } else if (rd->argintreguse
1022 < INT_ARG_CNT - intregsneeded) {
1023 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
1025 s->regoff = PACK_REGS(
1026 rd->argintregs[rd->argintreguse],
1027 rd->argintregs[rd->argintreguse + 1]);
1030 s->regoff = rd->argintregs[rd->argintreguse];
1032 rd->argintreguse += intregsneeded + 1;
1034 } else if (rd->freetmpinttop > intregsneeded) {
1035 rd->freetmpinttop -= intregsneeded + 1;
1036 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
1038 s->regoff = PACK_REGS(
1039 rd->freetmpintregs[rd->freetmpinttop],
1040 rd->freetmpintregs[rd->freetmpinttop + 1]);
1043 s->regoff = rd->freetmpintregs[rd->freetmpinttop];
1045 } else if (rd->tmpintreguse > intregsneeded) {
1046 rd->tmpintreguse -= intregsneeded + 1;
1047 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
1049 s->regoff = PACK_REGS(
1050 rd->tmpintregs[rd->tmpintreguse],
1051 rd->tmpintregs[rd->tmpintreguse + 1]);
1054 s->regoff = rd->tmpintregs[rd->tmpintreguse];
1057 } /* if (!IS_2_WORD_TYPE(s->type)) */
1058 } /* if (IS_FLT_DBL_TYPE(s->type)) */
1059 } /* if (IS_ADR_TYPE(s->type)) */
1060 } /* if (tryagain == 1) else */
1061 } /* for(; tryagain; --tryagain) */
1063 #if defined(HAS_4BYTE_STACKSLOT)
1064 if ((memneeded == 1) && (rd->freememtop_2 > 0)) {
1066 s->regoff = rd->freemem_2[rd->freememtop_2];
1068 #endif /*defined(HAS_4BYTE_STACKSLOT) */
1069 if ((memneeded == 0) && (rd->freememtop > 0)) {
1071 s->regoff = rd->freemem[rd->freememtop];
1073 #if defined(HAS_4BYTE_STACKSLOT)
1074 /* align 2 Word Types */
1075 if ((memneeded) && ((rd->memuse & 1) == 1)) {
1076 /* Put patched memory slot on freemem */
1077 rd->freemem[rd->freememtop++] = rd->memuse;
1080 #endif /*defined(HAS_4BYTE_STACKSLOT) */
1081 s->regoff = rd->memuse;
1082 rd->memuse += memneeded + 1;
1084 s->flags |= INMEMORY;
1088 #define reg_free_temp(rd,s) if (s->varkind == TEMPVAR) reg_free_temp_func(rd, s)
1090 static void reg_free_temp_func(registerdata *rd, stackptr s)
1095 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
1096 intregsneeded = (IS_2_WORD_TYPE(s->type)) ? 1 : 0;
1101 #if defined(HAS_4BYTE_STACKSLOT)
1102 memneeded = (IS_2_WORD_TYPE(s->type)) ? 1 : 0;
1107 if (s->flags & INMEMORY) {
1108 #if defined(HAS_4BYTE_STACKSLOT)
1109 if (memneeded > 0) {
1110 rd->freemem_2[rd->freememtop_2] = s->regoff;
1115 rd->freemem[rd->freememtop] = s->regoff;
1119 #ifdef HAS_ADDRESS_REGISTER_FILE
1120 } else if (IS_ADR_TYPE(s->type)) {
1121 if (s->flags & (SAVEDVAR | SAVEDTMP)) {
1122 s->flags &= ~SAVEDTMP;
1123 rd->freesavadrregs[rd->freesavadrtop++] = s->regoff;
1125 rd->freetmpadrregs[rd->freetmpadrtop++] = s->regoff;
1127 } else if (IS_FLT_DBL_TYPE(s->type)) {
1128 if (s->flags & (SAVEDVAR | SAVEDTMP)) {
1129 s->flags &= ~SAVEDTMP;
1130 rd->freesavfltregs[rd->freesavflttop++] = s->regoff;
1131 } else if (s->flags & TMPARG) {
1132 s->flags &= ~TMPARG;
1133 rd->freeargfltregs[rd->freeargflttop++] = s->regoff;
1135 rd->freetmpfltregs[rd->freetmpflttop++] = s->regoff;
1136 } else { /* IS_INT_LNG_TYPE */
1137 if (s->flags & (SAVEDVAR | SAVEDTMP)) {
1138 s->flags &= ~SAVEDTMP;
1139 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
1140 if (intregsneeded) {
1141 rd->freesavintregs[rd->freesavinttop] =
1142 GET_LOW_REG(s->regoff);
1143 rd->freesavintregs[rd->freesavinttop + 1] =
1144 GET_HIGH_REG(s->regoff);
1147 rd->freesavintregs[rd->freesavinttop] = s->regoff;
1148 rd->freesavinttop += intregsneeded + 1;
1150 } else if (s->flags & TMPARG) {
1151 s->flags &= ~TMPARG;
1152 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
1153 if (intregsneeded) {
1154 rd->freeargintregs[rd->freearginttop] =
1155 GET_LOW_REG(s->regoff);
1156 rd->freeargintregs[rd->freearginttop + 1] =
1157 GET_HIGH_REG(s->regoff);
1160 rd->freesavintregs[rd->freearginttop] = s->regoff;
1161 rd->freearginttop += intregsneeded + 1;
1163 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
1164 if (intregsneeded) {
1165 rd->freetmpintregs[rd->freetmpinttop] =
1166 GET_LOW_REG(s->regoff);
1167 rd->freetmpintregs[rd->freetmpinttop + 1] =
1168 GET_HIGH_REG(s->regoff);
1171 rd->freetmpintregs[rd->freetmpinttop] = s->regoff;
1172 rd->freetmpinttop += intregsneeded + 1;
1179 static void allocate_scratch_registers(methodinfo *m, registerdata *rd)
1189 /* initialize temp registers */
1190 reg_init_temp(m, rd);
1192 bptr = m->basicblocks;
1194 while (bptr != NULL) {
1195 if (bptr->flags >= BBREACHED) {
1196 dst = bptr->instack;
1199 iptr = bptr->iinstr;
1202 while (--len >= 0) {
1212 case ICMD_ELSE_ICONST:
1213 case ICMD_CHECKNULL:
1214 case ICMD_CHECKASIZE:
1215 case ICMD_CHECKEXCEPTION:
1221 case ICMD_PUTSTATICCONST:
1222 case ICMD_INLINE_START:
1223 case ICMD_INLINE_END:
1226 /* pop 0 push 1 const */
1234 /* pop 0 push 1 load */
1241 reg_new_temp(rd, dst);
1255 reg_free_temp(rd, src);
1256 reg_free_temp(rd, src->prev);
1257 reg_new_temp(rd, dst);
1271 reg_free_temp(rd, src);
1272 reg_free_temp(rd, src->prev);
1273 reg_free_temp(rd, src->prev->prev);
1276 /* pop 1 push 0 store */
1296 case ICMD_PUTSTATIC:
1297 case ICMD_PUTFIELDCONST:
1299 /* pop 1 push 0 branch */
1302 case ICMD_IFNONNULL:
1318 /* pop 1 push 0 table branch */
1320 case ICMD_TABLESWITCH:
1321 case ICMD_LOOKUPSWITCH:
1323 case ICMD_MONITORENTER:
1324 case ICMD_MONITOREXIT:
1325 reg_free_temp(rd, src);
1328 /* pop 2 push 0 branch */
1330 case ICMD_IF_ICMPEQ:
1331 case ICMD_IF_ICMPNE:
1332 case ICMD_IF_ICMPLT:
1333 case ICMD_IF_ICMPGE:
1334 case ICMD_IF_ICMPGT:
1335 case ICMD_IF_ICMPLE:
1337 case ICMD_IF_LCMPEQ:
1338 case ICMD_IF_LCMPNE:
1339 case ICMD_IF_LCMPLT:
1340 case ICMD_IF_LCMPGE:
1341 case ICMD_IF_LCMPGT:
1342 case ICMD_IF_LCMPLE:
1344 case ICMD_IF_ACMPEQ:
1345 case ICMD_IF_ACMPNE:
1353 case ICMD_IASTORECONST:
1354 case ICMD_LASTORECONST:
1355 case ICMD_AASTORECONST:
1356 case ICMD_BASTORECONST:
1357 case ICMD_CASTORECONST:
1358 case ICMD_SASTORECONST:
1359 reg_free_temp(rd, src);
1360 reg_free_temp(rd, src->prev);
1363 /* pop 0 push 1 dup */
1366 reg_new_temp(rd, dst);
1369 /* pop 0 push 2 dup */
1372 reg_new_temp(rd, dst->prev);
1373 reg_new_temp(rd, dst);
1376 /* pop 2 push 3 dup */
1379 reg_free_temp(rd, src);
1380 reg_new_temp(rd, dst);
1381 reg_free_temp(rd, src->prev);
1382 reg_new_temp(rd, dst->prev);
1383 reg_new_temp(rd, dst->prev->prev);
1386 /* pop 3 push 4 dup */
1389 reg_free_temp(rd, src);
1390 reg_new_temp(rd, dst);
1391 reg_free_temp(rd, src->prev);
1392 reg_new_temp(rd, dst->prev);
1393 reg_free_temp(rd, src->prev->prev);
1394 reg_new_temp(rd, dst->prev->prev);
1395 reg_new_temp(rd, dst->prev->prev->prev);
1398 /* pop 3 push 5 dup */
1401 reg_free_temp(rd, src);
1402 reg_new_temp(rd, dst);
1403 reg_free_temp(rd, src->prev);
1404 reg_new_temp(rd, dst->prev);
1405 reg_free_temp(rd, src->prev->prev);
1406 reg_new_temp(rd, dst->prev->prev);
1407 reg_new_temp(rd, dst->prev->prev->prev);
1408 reg_new_temp(rd, dst->prev->prev->prev->prev);
1411 /* pop 4 push 6 dup */
1414 reg_free_temp(rd, src);
1415 reg_new_temp(rd, dst);
1416 reg_free_temp(rd, src->prev);
1417 reg_new_temp(rd, dst->prev);
1418 reg_free_temp(rd, src->prev->prev);
1419 reg_new_temp(rd, dst->prev->prev);
1420 reg_free_temp(rd, src->prev->prev->prev);
1421 reg_new_temp(rd, dst->prev->prev->prev);
1422 reg_new_temp(rd, dst->prev->prev->prev->prev);
1423 reg_new_temp(rd, dst->prev->prev->prev->prev->prev);
1426 /* pop 2 push 2 swap */
1429 reg_free_temp(rd, src);
1430 reg_new_temp(rd, dst->prev);
1431 reg_free_temp(rd, src->prev);
1432 reg_new_temp(rd, dst);
1481 reg_free_temp(rd, src);
1482 reg_free_temp(rd, src->prev);
1483 reg_new_temp(rd, dst);
1488 case ICMD_IADDCONST:
1489 case ICMD_ISUBCONST:
1490 case ICMD_IMULCONST:
1494 case ICMD_IANDCONST:
1496 case ICMD_IXORCONST:
1497 case ICMD_ISHLCONST:
1498 case ICMD_ISHRCONST:
1499 case ICMD_IUSHRCONST:
1501 case ICMD_LADDCONST:
1502 case ICMD_LSUBCONST:
1503 case ICMD_LMULCONST:
1507 case ICMD_LANDCONST:
1509 case ICMD_LXORCONST:
1510 case ICMD_LSHLCONST:
1511 case ICMD_LSHRCONST:
1512 case ICMD_LUSHRCONST:
1514 case ICMD_IFEQ_ICONST:
1515 case ICMD_IFNE_ICONST:
1516 case ICMD_IFLT_ICONST:
1517 case ICMD_IFGE_ICONST:
1518 case ICMD_IFGT_ICONST:
1519 case ICMD_IFLE_ICONST:
1524 case ICMD_INT2SHORT:
1542 case ICMD_CHECKCAST:
1544 case ICMD_ARRAYLENGTH:
1545 case ICMD_INSTANCEOF:
1548 case ICMD_ANEWARRAY:
1551 reg_free_temp(rd, src);
1552 reg_new_temp(rd, dst);
1557 case ICMD_GETSTATIC:
1560 reg_new_temp(rd, dst);
1563 /* pop many push any */
1565 case ICMD_INVOKESTATIC:
1566 case ICMD_INVOKESPECIAL:
1567 case ICMD_INVOKEVIRTUAL:
1568 case ICMD_INVOKEINTERFACE:
1571 reg_free_temp(rd, src);
1574 if (((unresolved_method *) iptr->target)->methodref->parseddesc.md->returntype.type != TYPE_VOID)
1575 reg_new_temp(rd, dst);
1581 reg_free_temp(rd, src);
1584 if (((builtintable_entry *) iptr->val.a)->md->returntype.type != TYPE_VOID)
1585 reg_new_temp(rd, dst);
1588 case ICMD_MULTIANEWARRAY:
1591 reg_free_temp(rd, src);
1594 reg_new_temp(rd, dst);
1598 throw_cacao_exception_exit(string_java_lang_InternalError,
1599 "Unknown ICMD %d during register allocation",
1603 } /* while instructions */
1606 } /* while blocks */
1611 void reg_make_statistics( methodinfo *m, codegendata *cd, registerdata *rd) {
1614 stackptr src, src_old;
1618 int size_interface; /* == maximum size of in/out stack at basic block boundaries */
1625 /* count how many local variables are held in memory or register */
1626 for(i=0; i < cd->maxlocals; i++)
1627 for (type=0; type <=4; type++)
1628 if (rd->locals[i][type].type != -1) { /* valid local */
1629 if (rd->locals[i][type].flags & INMEMORY) {
1630 count_locals_spilled++;
1634 count_locals_register++;
1636 /* count how many stack slots are held in memory or register */
1638 bptr = m->basicblocks;
1639 while (bptr != NULL) {
1640 if (bptr->flags >= BBREACHED) {
1645 /* check for memory moves from interface to BB instack */
1646 dst = bptr->instack;
1647 len = bptr->indepth;
1649 if (len > size_interface) size_interface = len;
1651 while (dst != NULL) {
1653 if (dst->varkind != STACKVAR) {
1654 if ( (dst->flags & INMEMORY) ||
1655 (rd->interfaces[len][dst->type].flags & INMEMORY) ||
1656 ( (dst->flags & INMEMORY) &&
1657 (rd->interfaces[len][dst->type].flags & INMEMORY) &&
1658 (dst->regoff != rd->interfaces[len][dst->type].regoff) ))
1660 /* one in memory or both inmemory at different offsets */
1661 count_mem_move_bb++;
1669 /* check for memory moves from BB outstack to interface */
1670 dst = bptr->outstack;
1671 len = bptr->outdepth;
1672 if (len > size_interface) size_interface = len;
1676 if (dst->varkind != STACKVAR) {
1677 if ( (dst->flags & INMEMORY) || \
1678 (rd->interfaces[len][dst->type].flags & INMEMORY) || \
1679 ( (dst->flags & INMEMORY) && \
1680 (rd->interfaces[len][dst->type].flags & INMEMORY) && \
1681 (dst->regoff != rd->interfaces[len][dst->type].regoff) ))
1683 /* one in memory or both inmemory at different offsets */
1684 count_mem_move_bb++;
1696 dst = bptr->instack;
1697 iptr = bptr->iinstr;
1701 while (--len >= 0) {
1705 if ((src!= NULL) && (src != src_old)) { /* new stackslot */
1706 switch (src->varkind) {
1709 if (!(src->flags & INMEMORY))
1710 count_ss_register++;
1716 /* case LOCALVAR: */
1717 /* if (!(rd->locals[src->varnum][src->type].flags & INMEMORY)) */
1718 /* count_ss_register++; */
1720 /* count_ss_spilled++; */
1723 if (!(src->flags & INMEMORY))
1724 count_argument_mem_ss++;
1726 count_argument_reg_ss++;
1730 /* if (IS_FLT_DBL_TYPE(src->type)) { */
1731 /* if (src->varnum < FLT_ARG_CNT) { */
1732 /* count_ss_register++; */
1736 /* #if defined(__POWERPC__) */
1737 /* if (src->varnum < INT_ARG_CNT - (IS_2_WORD_TYPE(src->type) != 0)) { */
1739 /* if (src->varnum < INT_ARG_CNT) { */
1741 /* count_ss_register++; */
1745 /* count_ss_spilled++; */
1752 } /* while instructions */
1755 } /* while blocks */
1756 count_interface_size += size_interface; /* accummulate the size of the interface (between bb boundaries) */
1757 if (in_register) count_method_in_register++;
1761 * These are local overrides for various environment variables in Emacs.
1762 * Please do not remove this and leave it at the end of the file, where
1763 * Emacs will automagically detect them.
1764 * ---------------------------------------------------------------------
1767 * indent-tabs-mode: t