1 /* src/vm/jit/allocator/simplereg.c - 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
34 $Id: simplereg.c 4080 2006-01-02 21:01:58Z christian $
47 #include "vm/builtin.h"
48 #include "vm/exceptions.h"
49 #include "mm/memory.h"
50 #include "vm/method.h"
51 #include "vm/options.h"
52 #include "vm/resolve.h"
53 #include "vm/stringlocal.h"
54 #include "vm/jit/reg.h"
55 #include "vm/jit/allocator/simplereg.h"
57 /* function prototypes for this file */
59 static void interface_regalloc(methodinfo *m, codegendata *cd, registerdata *rd);
60 static void local_regalloc(methodinfo *m, codegendata *cd, registerdata *rd);
61 static void allocate_scratch_registers(methodinfo *m, registerdata *rd);
64 /* function interface_regalloc *************************************************
66 allocates registers for all interface variables
68 *******************************************************************************/
70 void regalloc(methodinfo *m, codegendata *cd, registerdata *rd)
72 interface_regalloc(m, cd, rd);
73 allocate_scratch_registers(m, rd);
74 local_regalloc(m, cd, rd);
78 /* function interface_regalloc *************************************************
80 allocates registers for all interface variables
82 *******************************************************************************/
84 static void interface_regalloc(methodinfo *m, codegendata *cd, registerdata *rd)
87 int intalloc, fltalloc; /* Remember allocated Register/Memory offset */
88 /* in case a more vars are packed into this interface slot */
90 int intregsneeded = 0;
92 /* allocate LNG and DBL Types first to ensure 2 memory slots or registers */
93 /* on HAS_4BYTE_STACKSLOT architectures */
94 int typeloop[] = { TYPE_LNG, TYPE_DBL, TYPE_INT, TYPE_FLT, TYPE_ADR };
96 /* rd->memuse was already set in stack.c to allocate stack space for */
97 /* passing arguments to called methods */
99 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
100 /* reserve 0(%esp) for Monitorenter/exit Argument on i386 */
106 for (s = 0; s < cd->maxstack; s++) {
107 intalloc = -1; fltalloc = -1;
108 saved = (rd->interfaces[s][TYPE_INT].flags |
109 rd->interfaces[s][TYPE_LNG].flags |
110 rd->interfaces[s][TYPE_FLT].flags |
111 rd->interfaces[s][TYPE_DBL].flags |
112 rd->interfaces[s][TYPE_ADR].flags) & SAVEDVAR;
114 for (tt = 0; tt <= 4; tt++) {
116 v = &rd->interfaces[s][t];
118 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
119 intregsneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
121 #if defined(HAS_4BYTE_STACKSLOT)
122 memneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
125 #if defined(HAS_ADDRESS_REGISTER_FILE)
126 if (IS_ADR_TYPE(t)) {
128 &&(rd->argadrreguse < ADR_ARG_CNT)) {
129 v->regoff = rd->argadrregs[rd->argadrreguse++];
130 } else if (rd->tmpadrreguse > 0) {
131 v->regoff = rd->tmpadrregs[--rd->tmpadrreguse];
132 } else if (rd->savadrreguse > 0) {
133 v->regoff = rd->savadrregs[--rd->savadrreguse];
135 v->flags |= INMEMORY;
136 v->regoff = rd->memuse++;
138 } else /* !IS_ADR_TYPE */
139 #endif /* defined(HAS_ADDRESS_REGISTER_FILE) */
141 if (IS_FLT_DBL_TYPE(t)) {
143 /* Reuse memory slot(s)/register(s) for shared interface slots */
144 v->flags |= rd->interfaces[s][fltalloc].flags
146 v->regoff = rd->interfaces[s][fltalloc].regoff;
147 } else if (!m->isleafmethod
148 && (rd->argfltreguse < FLT_ARG_CNT)) {
149 v->regoff = rd->argfltregs[rd->argfltreguse++];
150 } else if (rd->tmpfltreguse > 0) {
151 v->regoff = rd->tmpfltregs[--rd->tmpfltreguse];
152 } else if (rd->savfltreguse > 0) {
153 v->regoff = rd->savfltregs[--rd->savfltreguse];
155 v->flags |= INMEMORY;
156 v->regoff = rd->memuse;
157 rd->memuse += memneeded + 1;
160 } else { /* !IS_FLT_DBL_TYPE(t) */
161 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
163 * for i386 put all longs in memory
165 if (IS_2_WORD_TYPE(t)) {
166 v->flags |= INMEMORY;
167 v->regoff = rd->memuse;
168 rd->memuse += memneeded + 1;
170 #endif /* defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE...GISTERS) */
171 /* #if !defined(HAS_4BYTE_STACKSLOT) */
173 /* Reuse memory slot(s)/register(s) for shared interface slots */
175 rd->interfaces[s][intalloc].flags
177 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
178 if (!(v->flags & INMEMORY)
179 && IS_2_WORD_TYPE(intalloc))
180 v->regoff = GET_LOW_REG(
181 rd->interfaces[s][intalloc].regoff);
185 rd->interfaces[s][intalloc].regoff;
187 /* #endif *//* !defined(HAS_4BYTE_STACKSLOT) */
188 if (!m->isleafmethod &&
190 + intregsneeded < INT_ARG_CNT)) {
191 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
194 rd->argintregs[rd->argintreguse],
195 rd->argintregs[rd->argintreguse + 1]);
199 rd->argintregs[rd->argintreguse];
200 rd->argintreguse += intregsneeded + 1;
202 else if (rd->tmpintreguse > intregsneeded) {
203 rd->tmpintreguse -= intregsneeded + 1;
204 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
207 rd->tmpintregs[rd->tmpintreguse],
208 rd->tmpintregs[rd->tmpintreguse + 1]);
212 rd->tmpintregs[rd->tmpintreguse];
214 else if (rd->savintreguse > intregsneeded) {
215 rd->savintreguse -= intregsneeded + 1;
217 rd->savintregs[rd->savintreguse];
218 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
221 rd->savintregs[rd->savintreguse],
222 rd->savintregs[rd->savintreguse + 1]);
226 rd->savintregs[rd->savintreguse];
229 v->flags |= INMEMORY;
230 v->regoff = rd->memuse;
231 rd->memuse += memneeded + 1;
235 } /* if (IS_FLT_DBL_TYPE(t)) */
237 } else { /* (saved) */
238 /* now the same like above, but without a chance to take a temporary register */
239 #ifdef HAS_ADDRESS_REGISTER_FILE
240 if (IS_ADR_TYPE(t)) {
241 if (rd->savadrreguse > 0) {
242 v->regoff = rd->savadrregs[--rd->savadrreguse];
245 v->flags |= INMEMORY;
246 v->regoff = rd->memuse++;
251 if (IS_FLT_DBL_TYPE(t)) {
253 v->flags |= rd->interfaces[s][fltalloc].flags
255 v->regoff = rd->interfaces[s][fltalloc].regoff;
257 if (rd->savfltreguse > 0) {
258 v->regoff = rd->savfltregs[--rd->savfltreguse];
261 v->flags |= INMEMORY;
262 v->regoff = rd->memuse;
263 rd->memuse += memneeded + 1;
267 else { /* IS_INT_LNG */
268 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
270 * for i386 put all longs in memory
272 if (IS_2_WORD_TYPE(t)) {
273 v->flags |= INMEMORY;
274 v->regoff = rd->memuse;
275 rd->memuse += memneeded + 1;
279 /* #if !defined(HAS_4BYTE_STACKSLOT) */
282 rd->interfaces[s][intalloc].flags & INMEMORY;
283 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
284 if (!(v->flags & INMEMORY)
285 && IS_2_WORD_TYPE(intalloc))
288 rd->interfaces[s][intalloc].regoff);
292 rd->interfaces[s][intalloc].regoff;
296 if (rd->savintreguse > intregsneeded) {
297 rd->savintreguse -= intregsneeded + 1;
298 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
300 v->regoff = PACK_REGS(
301 rd->savintregs[rd->savintreguse],
302 rd->savintregs[rd->savintreguse + 1]);
306 rd->savintregs[rd->savintreguse];
308 v->flags |= INMEMORY;
309 v->regoff = rd->memuse;
310 rd->memuse += memneeded + 1;
315 } /* if (IS_FLT_DBL_TYPE(t) else */
316 } /* if (IS_ADR_TYPE(t)) else */
317 } /* if (saved) else */
318 } /* if (type >= 0) */
325 /* function local_regalloc *****************************************************
327 allocates registers for all local variables
329 *******************************************************************************/
331 static void local_regalloc(methodinfo *m, codegendata *cd, registerdata *rd)
334 int intalloc, fltalloc;
336 int intregsneeded = 0;
338 int typeloop[] = { TYPE_LNG, TYPE_DBL, TYPE_INT, TYPE_FLT, TYPE_ADR };
339 int fargcnt, iargcnt;
340 #ifdef HAS_ADDRESS_REGISTER_FILE
344 if (m->isleafmethod) {
345 methoddesc *md = m->parseddesc;
347 iargcnt = md->argintreguse;
348 fargcnt = md->argfltreguse;
349 #ifdef HAS_ADDRESS_REGISTER_FILE
350 aargcnt = md->argadrreguse;
352 for (p = 0, s = 0; s < cd->maxlocals; s++, p++) {
353 intalloc = -1; fltalloc = -1;
354 for (tt = 0; tt <= 4; tt++) {
356 v = &rd->locals[s][t];
361 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
362 intregsneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
364 #if defined(HAS_4BYTE_STACKSLOT)
365 memneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
371 * #ifdef HAS_ADDRESS_REGISTER_FILE
378 * } else { / int & lng
382 * must not to be changed!
385 #ifdef HAS_ADDRESS_REGISTER_FILE
386 if (IS_ADR_TYPE(t)) {
387 if ((p < md->paramcount) && !md->params[p].inmemory) {
389 v->regoff = rd->argadrregs[md->params[p].regoff];
391 if (rd->tmpadrreguse > 0) {
393 v->regoff = rd->tmpadrregs[--rd->tmpadrreguse];
395 else if (rd->savadrreguse > 0) {
397 v->regoff = rd->savadrregs[--rd->savadrreguse];
399 /* use unused argument registers as local registers */
400 else if ((p >= md->paramcount) &&
401 (aargcnt < ADR_ARG_CNT)) {
403 v->regoff = rd->argadrregs[aargcnt++];
406 v->flags |= INMEMORY;
407 v->regoff = rd->memuse++;
411 if (IS_FLT_DBL_TYPE(t)) {
413 v->flags = rd->locals[s][fltalloc].flags;
414 v->regoff = rd->locals[s][fltalloc].regoff;
416 #if !defined(SUPPORT_PASS_FLOATARGS_IN_INTREGS)
417 /* We can only use float arguments as local variables,
418 * if we do not pass them in integer registers. */
419 else if ((p < md->paramcount) &&
420 !md->params[p].inmemory) {
422 v->regoff = rd->argfltregs[md->params[p].regoff];
425 else if (rd->tmpfltreguse > 0) {
427 v->regoff = rd->tmpfltregs[--rd->tmpfltreguse];
429 else if (rd->savfltreguse > 0) {
431 v->regoff = rd->savfltregs[--rd->savfltreguse];
433 /* use unused argument registers as local registers */
434 else if ((p >= m->paramcount) &&
435 (fargcnt < FLT_ARG_CNT)) {
437 v->regoff = rd->argfltregs[fargcnt];
442 v->regoff = rd->memuse;
443 rd->memuse += memneeded + 1;
448 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
450 * for i386 put all longs in memory
452 if (IS_2_WORD_TYPE(t)) {
454 v->regoff = rd->memuse;
455 rd->memuse += memneeded + 1;
460 v->flags = rd->locals[s][intalloc].flags;
461 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
462 if (!(v->flags & INMEMORY)
463 && IS_2_WORD_TYPE(intalloc))
464 v->regoff = GET_LOW_REG(
465 rd->locals[s][intalloc].regoff);
468 v->regoff = rd->locals[s][intalloc].regoff;
470 else if ((p < md->paramcount) &&
471 !md->params[p].inmemory) {
473 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
474 if (IS_2_WORD_TYPE(t))
475 /* For ARM: - if GET_LOW_REG(md->params[p].regoff) == R4, prevent here that */
476 /* rd->argintregs[GET_HIGH_REG(md->...)) is used! */
477 v->regoff = PACK_REGS(
478 rd->argintregs[GET_LOW_REG(md->params[p].regoff)],
479 rd->argintregs[GET_HIGH_REG(md->params[p].regoff)]);
483 rd->argintregs[md->params[p].regoff];
485 else if (rd->tmpintreguse > intregsneeded) {
486 rd->tmpintreguse -= intregsneeded + 1;
488 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
490 v->regoff = PACK_REGS(
491 rd->tmpintregs[rd->tmpintreguse],
492 rd->tmpintregs[rd->tmpintreguse + 1]);
496 rd->tmpintregs[rd->tmpintreguse];
498 else if (rd->savintreguse > intregsneeded) {
499 rd->savintreguse -= intregsneeded + 1;
501 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
503 v->regoff = PACK_REGS(
504 rd->savintregs[rd->savintreguse],
505 rd->savintregs[rd->savintreguse + 1]);
508 v->regoff =rd->savintregs[rd->savintreguse];
511 * use unused argument registers as local registers
513 else if ((p >= m->paramcount) &&
514 (iargcnt < INT_ARG_CNT)) {
516 v->regoff = rd->argintregs[iargcnt];
521 v->regoff = rd->memuse;
522 rd->memuse += memneeded + 1;
527 #ifdef HAS_ADDRESS_REGISTER_FILE
530 } /* for (tt=0;...) */
532 /* If the current parameter is a 2-word type, the next local slot */
535 if (p < md->paramcount)
536 if (IS_2_WORD_TYPE(md->paramtypes[p].type))
542 for (s = 0; s < cd->maxlocals; s++) {
543 intalloc = -1; fltalloc = -1;
544 for (tt=0; tt<=4; tt++) {
546 v = &rd->locals[s][t];
549 #ifdef SUPPORT_COMBINE_INTEGER_REGISTERS
550 intregsneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
552 #if defined(HAS_4BYTE_STACKSLOT)
553 memneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
555 #ifdef HAS_ADDRESS_REGISTER_FILE
556 if ( IS_ADR_TYPE(t) ) {
557 if (rd->savadrreguse > 0) {
559 v->regoff = rd->savadrregs[--rd->savadrreguse];
563 v->regoff = rd->memuse++;
567 if (IS_FLT_DBL_TYPE(t)) {
569 v->flags = rd->locals[s][fltalloc].flags;
570 v->regoff = rd->locals[s][fltalloc].regoff;
572 else if (rd->savfltreguse > 0) {
574 v->regoff = rd->savfltregs[--rd->savfltreguse];
578 /* Align doubles in Memory */
579 if ( (memneeded) && (rd->memuse & 1))
581 v->regoff = rd->memuse;
582 rd->memuse += memneeded + 1;
587 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
589 * for i386 put all longs in memory
591 if (IS_2_WORD_TYPE(t)) {
593 v->regoff = rd->memuse;
594 rd->memuse += memneeded + 1;
598 v->flags = rd->locals[s][intalloc].flags;
599 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
600 if (!(v->flags & INMEMORY)
601 && IS_2_WORD_TYPE(intalloc))
602 v->regoff = GET_LOW_REG(
603 rd->locals[s][intalloc].regoff);
606 v->regoff = rd->locals[s][intalloc].regoff;
608 else if (rd->savintreguse > intregsneeded) {
609 rd->savintreguse -= intregsneeded+1;
611 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
613 v->regoff = PACK_REGS(
614 rd->savintregs[rd->savintreguse],
615 rd->savintregs[rd->savintreguse + 1]);
618 v->regoff =rd->savintregs[rd->savintreguse];
622 v->regoff = rd->memuse;
623 rd->memuse += memneeded + 1;
625 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
630 #ifdef HAS_ADDRESS_REGISTER_FILE
639 static void reg_init_temp(methodinfo *m, registerdata *rd)
642 #if defined(HAS_4BYTE_STACKSLOT)
643 rd->freememtop_2 = 0;
646 rd->freetmpinttop = 0;
647 rd->freesavinttop = 0;
648 rd->freetmpflttop = 0;
649 rd->freesavflttop = 0;
650 #ifdef HAS_ADDRESS_REGISTER_FILE
651 rd->freetmpadrtop = 0;
652 rd->freesavadrtop = 0;
655 rd->freearginttop = 0;
656 rd->freeargflttop = 0;
657 #ifdef HAS_ADDRESS_REGISTER_FILE
658 rd->freeargadrtop = 0;
661 if (m->isleafmethod) {
662 /* Don't use not used Argument Registers in Leafmethods -> they could */
663 /* already be in use for Locals passed as parameter to this Method */
664 rd->argintreguse = INT_ARG_CNT;
665 rd->argfltreguse = FLT_ARG_CNT;
666 #ifdef HAS_ADDRESS_REGISTER_FILE
667 rd->argadrreguse = ADR_ARG_CNT;
673 #define reg_new_temp(rd,s) if (s->varkind == TEMPVAR) reg_new_temp_func(rd, s)
675 static void reg_new_temp_func(registerdata *rd, stackptr s)
681 /* Try to allocate a saved register if there is no temporary one */
682 /* available. This is what happens during the second run. */
683 tryagain = (s->flags & SAVEDVAR) ? 1 : 2;
685 #ifdef SUPPORT_COMBINE_INTEGER_REGISTERS
686 intregsneeded = (IS_2_WORD_TYPE(s->type)) ? 1 : 0;
690 #if defined(HAS_4BYTE_STACKSLOT)
691 memneeded = (IS_2_WORD_TYPE(s->type)) ? 1 : 0;
696 for(; tryagain; --tryagain) {
698 if (!(s->flags & SAVEDVAR))
699 s->flags |= SAVEDTMP;
700 #ifdef HAS_ADDRESS_REGISTER_FILE
701 if (IS_ADR_TYPE(s->type)) {
702 if (rd->freesavadrtop > 0) {
703 s->regoff = rd->freesavadrregs[--rd->freesavadrtop];
705 } else if (rd->savadrreguse > 0) {
706 s->regoff = rd->savadrregs[--rd->savadrreguse];
712 if (IS_FLT_DBL_TYPE(s->type)) {
713 if (rd->freesavflttop > 0) {
714 s->regoff = rd->freesavfltregs[--rd->freesavflttop];
716 } else if (rd->savfltreguse > 0) {
717 s->regoff = rd->savfltregs[--rd->savfltreguse];
721 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
723 * for i386 put all longs in memory
725 if (!IS_2_WORD_TYPE(s->type))
728 if (rd->freesavinttop > intregsneeded) {
729 rd->freesavinttop -= intregsneeded + 1;
730 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
732 s->regoff = PACK_REGS(
733 rd->freesavintregs[rd->freesavinttop],
734 rd->freesavintregs[rd->freesavinttop + 1]);
738 rd->freesavintregs[rd->freesavinttop];
740 } else if (rd->savintreguse > intregsneeded) {
741 rd->savintreguse -= intregsneeded + 1;
742 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
744 s->regoff = PACK_REGS(
745 rd->savintregs[rd->savintreguse],
746 rd->savintregs[rd->savintreguse + 1]);
749 s->regoff = rd->savintregs[rd->savintreguse];
755 } else { /* tryagain == 2 */
756 #ifdef HAS_ADDRESS_REGISTER_FILE
757 if (IS_ADR_TYPE(s->type)) {
758 if (rd->freetmpadrtop > 0) {
759 s->regoff = rd->freetmpadrregs[--rd->freetmpadrtop];
761 } else if (rd->tmpadrreguse > 0) {
762 s->regoff = rd->tmpadrregs[--rd->tmpadrreguse];
768 if (IS_FLT_DBL_TYPE(s->type)) {
769 if (rd->freeargflttop > 0) {
770 s->regoff = rd->freeargfltregs[--rd->freeargflttop];
773 } else if (rd->argfltreguse < FLT_ARG_CNT) {
774 s->regoff = rd->argfltregs[rd->argfltreguse++];
777 } else if (rd->freetmpflttop > 0) {
778 s->regoff = rd->freetmpfltregs[--rd->freetmpflttop];
780 } else if (rd->tmpfltreguse > 0) {
781 s->regoff = rd->tmpfltregs[--rd->tmpfltreguse];
786 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
788 * for i386 put all longs in memory
790 if (!IS_2_WORD_TYPE(s->type))
793 if (rd->freearginttop > intregsneeded) {
794 rd->freearginttop -= intregsneeded + 1;
796 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
798 s->regoff = PACK_REGS(
799 rd->freeargintregs[rd->freearginttop],
800 rd->freeargintregs[rd->freearginttop + 1]);
804 rd->freeargintregs[rd->freearginttop];
806 } else if (rd->argintreguse
807 < INT_ARG_CNT - intregsneeded) {
808 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
810 s->regoff = PACK_REGS(
811 rd->argintregs[rd->argintreguse],
812 rd->argintregs[rd->argintreguse + 1]);
815 s->regoff = rd->argintregs[rd->argintreguse];
817 rd->argintreguse += intregsneeded + 1;
819 } else if (rd->freetmpinttop > intregsneeded) {
820 rd->freetmpinttop -= intregsneeded + 1;
821 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
823 s->regoff = PACK_REGS(
824 rd->freetmpintregs[rd->freetmpinttop],
825 rd->freetmpintregs[rd->freetmpinttop + 1]);
828 s->regoff = rd->freetmpintregs[rd->freetmpinttop];
830 } else if (rd->tmpintreguse > intregsneeded) {
831 rd->tmpintreguse -= intregsneeded + 1;
832 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
834 s->regoff = PACK_REGS(
835 rd->tmpintregs[rd->tmpintreguse],
836 rd->tmpintregs[rd->tmpintreguse + 1]);
839 s->regoff = rd->tmpintregs[rd->tmpintreguse];
842 } /* if (!IS_2_WORD_TYPE(s->type)) */
843 } /* if (IS_FLT_DBL_TYPE(s->type)) */
844 } /* if (IS_ADR_TYPE(s->type)) */
845 } /* if (tryagain == 1) else */
846 } /* for(; tryagain; --tryagain) */
848 #if defined(HAS_4BYTE_STACKSLOT)
849 if ((memneeded == 1) && (rd->freememtop_2 > 0)) {
851 s->regoff = rd->freemem_2[rd->freememtop_2];
853 #endif /*defined(HAS_4BYTE_STACKSLOT) */
854 if ((memneeded == 0) && (rd->freememtop > 0)) {
856 s->regoff = rd->freemem[rd->freememtop];
858 #if defined(HAS_4BYTE_STACKSLOT)
859 /* align 2 Word Types */
860 if ((memneeded) && ((rd->memuse & 1) == 1)) {
861 /* Put patched memory slot on freemem */
862 rd->freemem[rd->freememtop++] = rd->memuse;
865 #endif /*defined(HAS_4BYTE_STACKSLOT) */
866 s->regoff = rd->memuse;
867 rd->memuse += memneeded + 1;
869 s->flags |= INMEMORY;
873 #define reg_free_temp(rd,s) if (s->varkind == TEMPVAR) reg_free_temp_func(rd, s)
875 static void reg_free_temp_func(registerdata *rd, stackptr s)
880 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
881 intregsneeded = (IS_2_WORD_TYPE(s->type)) ? 1 : 0;
886 #if defined(HAS_4BYTE_STACKSLOT)
887 memneeded = (IS_2_WORD_TYPE(s->type)) ? 1 : 0;
892 if (s->flags & INMEMORY) {
893 #if defined(HAS_4BYTE_STACKSLOT)
895 rd->freemem_2[rd->freememtop_2] = s->regoff;
900 rd->freemem[rd->freememtop] = s->regoff;
904 #ifdef HAS_ADDRESS_REGISTER_FILE
905 } else if (IS_ADR_TYPE(s->type)) {
906 if (s->flags & (SAVEDVAR | SAVEDTMP)) {
907 s->flags &= ~SAVEDTMP;
908 rd->freesavadrregs[rd->freesavadrtop++] = s->regoff;
910 rd->freetmpadrregs[rd->freetmpadrtop++] = s->regoff;
912 } else if (IS_FLT_DBL_TYPE(s->type)) {
913 if (s->flags & (SAVEDVAR | SAVEDTMP)) {
914 s->flags &= ~SAVEDTMP;
915 rd->freesavfltregs[rd->freesavflttop++] = s->regoff;
916 } else if (s->flags & TMPARG) {
918 rd->freeargfltregs[rd->freeargflttop++] = s->regoff;
920 rd->freetmpfltregs[rd->freetmpflttop++] = s->regoff;
921 } else { /* IS_INT_LNG_TYPE */
922 if (s->flags & (SAVEDVAR | SAVEDTMP)) {
923 s->flags &= ~SAVEDTMP;
924 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
926 rd->freesavintregs[rd->freesavinttop] =
927 GET_LOW_REG(s->regoff);
928 rd->freesavintregs[rd->freesavinttop + 1] =
929 GET_HIGH_REG(s->regoff);
932 rd->freesavintregs[rd->freesavinttop] = s->regoff;
933 rd->freesavinttop += intregsneeded + 1;
935 } else if (s->flags & TMPARG) {
937 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
939 rd->freeargintregs[rd->freearginttop] =
940 GET_LOW_REG(s->regoff);
941 rd->freeargintregs[rd->freearginttop + 1] =
942 GET_HIGH_REG(s->regoff);
945 rd->freeargintregs[rd->freearginttop] = s->regoff;
946 rd->freearginttop += intregsneeded + 1;
948 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
950 rd->freetmpintregs[rd->freetmpinttop] =
951 GET_LOW_REG(s->regoff);
952 rd->freetmpintregs[rd->freetmpinttop + 1] =
953 GET_HIGH_REG(s->regoff);
956 rd->freetmpintregs[rd->freetmpinttop] = s->regoff;
957 rd->freetmpinttop += intregsneeded + 1;
964 static void allocate_scratch_registers(methodinfo *m, registerdata *rd)
974 builtintable_entry *bte;
977 /* initialize temp registers */
978 reg_init_temp(m, rd);
980 bptr = m->basicblocks;
982 while (bptr != NULL) {
983 if (bptr->flags >= BBREACHED) {
1000 case ICMD_ELSE_ICONST:
1001 case ICMD_CHECKNULL:
1007 case ICMD_PUTSTATICCONST:
1008 case ICMD_INLINE_START:
1009 case ICMD_INLINE_END:
1012 /* pop 0 push 1 const */
1020 /* pop 0 push 1 load */
1027 reg_new_temp(rd, dst);
1041 reg_free_temp(rd, src);
1042 reg_free_temp(rd, src->prev);
1043 reg_new_temp(rd, dst);
1057 reg_free_temp(rd, src);
1058 reg_free_temp(rd, src->prev);
1059 reg_free_temp(rd, src->prev->prev);
1062 /* pop 1 push 0 store */
1082 case ICMD_PUTSTATIC:
1083 case ICMD_PUTFIELDCONST:
1085 /* pop 1 push 0 branch */
1088 case ICMD_IFNONNULL:
1104 /* pop 1 push 0 table branch */
1106 case ICMD_TABLESWITCH:
1107 case ICMD_LOOKUPSWITCH:
1109 case ICMD_MONITORENTER:
1110 case ICMD_MONITOREXIT:
1111 reg_free_temp(rd, src);
1114 /* pop 2 push 0 branch */
1116 case ICMD_IF_ICMPEQ:
1117 case ICMD_IF_ICMPNE:
1118 case ICMD_IF_ICMPLT:
1119 case ICMD_IF_ICMPGE:
1120 case ICMD_IF_ICMPGT:
1121 case ICMD_IF_ICMPLE:
1123 case ICMD_IF_LCMPEQ:
1124 case ICMD_IF_LCMPNE:
1125 case ICMD_IF_LCMPLT:
1126 case ICMD_IF_LCMPGE:
1127 case ICMD_IF_LCMPGT:
1128 case ICMD_IF_LCMPLE:
1130 case ICMD_IF_ACMPEQ:
1131 case ICMD_IF_ACMPNE:
1139 case ICMD_IASTORECONST:
1140 case ICMD_LASTORECONST:
1141 case ICMD_AASTORECONST:
1142 case ICMD_BASTORECONST:
1143 case ICMD_CASTORECONST:
1144 case ICMD_SASTORECONST:
1145 reg_free_temp(rd, src);
1146 reg_free_temp(rd, src->prev);
1149 /* pop 0 push 1 dup */
1152 reg_new_temp(rd, dst);
1155 /* pop 0 push 2 dup */
1158 reg_new_temp(rd, dst->prev);
1159 reg_new_temp(rd, dst);
1162 /* pop 2 push 3 dup */
1165 reg_free_temp(rd, src);
1166 reg_new_temp(rd, dst);
1167 reg_free_temp(rd, src->prev);
1168 reg_new_temp(rd, dst->prev);
1169 reg_new_temp(rd, dst->prev->prev);
1172 /* pop 3 push 4 dup */
1175 reg_free_temp(rd, src);
1176 reg_new_temp(rd, dst);
1177 reg_free_temp(rd, src->prev);
1178 reg_new_temp(rd, dst->prev);
1179 reg_free_temp(rd, src->prev->prev);
1180 reg_new_temp(rd, dst->prev->prev);
1181 reg_new_temp(rd, dst->prev->prev->prev);
1184 /* pop 3 push 5 dup */
1187 reg_free_temp(rd, src);
1188 reg_new_temp(rd, dst);
1189 reg_free_temp(rd, src->prev);
1190 reg_new_temp(rd, dst->prev);
1191 reg_free_temp(rd, src->prev->prev);
1192 reg_new_temp(rd, dst->prev->prev);
1193 reg_new_temp(rd, dst->prev->prev->prev);
1194 reg_new_temp(rd, dst->prev->prev->prev->prev);
1197 /* pop 4 push 6 dup */
1200 reg_free_temp(rd, src);
1201 reg_new_temp(rd, dst);
1202 reg_free_temp(rd, src->prev);
1203 reg_new_temp(rd, dst->prev);
1204 reg_free_temp(rd, src->prev->prev);
1205 reg_new_temp(rd, dst->prev->prev);
1206 reg_free_temp(rd, src->prev->prev->prev);
1207 reg_new_temp(rd, dst->prev->prev->prev);
1208 reg_new_temp(rd, dst->prev->prev->prev->prev);
1209 reg_new_temp(rd, dst->prev->prev->prev->prev->prev);
1212 /* pop 2 push 2 swap */
1215 reg_free_temp(rd, src);
1216 reg_new_temp(rd, dst->prev);
1217 reg_free_temp(rd, src->prev);
1218 reg_new_temp(rd, dst);
1267 reg_free_temp(rd, src);
1268 reg_free_temp(rd, src->prev);
1269 reg_new_temp(rd, dst);
1274 case ICMD_IADDCONST:
1275 case ICMD_ISUBCONST:
1276 case ICMD_IMULCONST:
1280 case ICMD_IANDCONST:
1282 case ICMD_IXORCONST:
1283 case ICMD_ISHLCONST:
1284 case ICMD_ISHRCONST:
1285 case ICMD_IUSHRCONST:
1287 case ICMD_LADDCONST:
1288 case ICMD_LSUBCONST:
1289 case ICMD_LMULCONST:
1293 case ICMD_LANDCONST:
1295 case ICMD_LXORCONST:
1296 case ICMD_LSHLCONST:
1297 case ICMD_LSHRCONST:
1298 case ICMD_LUSHRCONST:
1300 case ICMD_IFEQ_ICONST:
1301 case ICMD_IFNE_ICONST:
1302 case ICMD_IFLT_ICONST:
1303 case ICMD_IFGE_ICONST:
1304 case ICMD_IFGT_ICONST:
1305 case ICMD_IFLE_ICONST:
1310 case ICMD_INT2SHORT:
1328 case ICMD_CHECKCAST:
1330 case ICMD_ARRAYLENGTH:
1331 case ICMD_INSTANCEOF:
1334 case ICMD_ANEWARRAY:
1337 reg_free_temp(rd, src);
1338 reg_new_temp(rd, dst);
1343 case ICMD_GETSTATIC:
1346 reg_new_temp(rd, dst);
1349 /* pop many push any */
1351 case ICMD_INVOKESTATIC:
1352 case ICMD_INVOKESPECIAL:
1353 case ICMD_INVOKEVIRTUAL:
1354 case ICMD_INVOKEINTERFACE:
1358 md = lm->parseddesc;
1360 unresolved_method *um = iptr->target;
1361 md = um->methodref->parseddesc.md;
1365 reg_free_temp(rd, src);
1368 if (md->returntype.type != TYPE_VOID)
1369 reg_new_temp(rd, dst);
1377 reg_free_temp(rd, src);
1380 if (md->returntype.type != TYPE_VOID)
1381 reg_new_temp(rd, dst);
1384 case ICMD_MULTIANEWARRAY:
1387 reg_free_temp(rd, src);
1390 reg_new_temp(rd, dst);
1394 throw_cacao_exception_exit(string_java_lang_InternalError,
1395 "Unknown ICMD %d during register allocation",
1399 } /* while instructions */
1402 } /* while blocks */
1406 #if defined(ENABLE_STATISTICS)
1407 void reg_make_statistics( methodinfo *m, codegendata *cd, registerdata *rd) {
1410 stackptr src, src_old;
1414 int size_interface; /* == maximum size of in/out stack at basic block boundaries */
1421 /* count how many local variables are held in memory or register */
1422 for(i=0; i < cd->maxlocals; i++)
1423 for (type=0; type <=4; type++)
1424 if (rd->locals[i][type].type != -1) { /* valid local */
1425 if (rd->locals[i][type].flags & INMEMORY) {
1426 count_locals_spilled++;
1430 count_locals_register++;
1432 /* count how many stack slots are held in memory or register */
1434 bptr = m->basicblocks;
1435 while (bptr != NULL) {
1436 if (bptr->flags >= BBREACHED) {
1438 #if defined(ENABLE_LSRA)
1441 /* check for memory moves from interface to BB instack */
1442 dst = bptr->instack;
1443 len = bptr->indepth;
1445 if (len > size_interface) size_interface = len;
1447 while (dst != NULL) {
1449 if (dst->varkind != STACKVAR) {
1450 if ( (dst->flags & INMEMORY) ||
1451 (rd->interfaces[len][dst->type].flags & INMEMORY) ||
1452 ( (dst->flags & INMEMORY) &&
1453 (rd->interfaces[len][dst->type].flags & INMEMORY) &&
1454 (dst->regoff != rd->interfaces[len][dst->type].regoff) ))
1456 /* one in memory or both inmemory at different offsets */
1457 count_mem_move_bb++;
1465 /* check for memory moves from BB outstack to interface */
1466 dst = bptr->outstack;
1467 len = bptr->outdepth;
1468 if (len > size_interface) size_interface = len;
1472 if (dst->varkind != STACKVAR) {
1473 if ( (dst->flags & INMEMORY) || \
1474 (rd->interfaces[len][dst->type].flags & INMEMORY) || \
1475 ( (dst->flags & INMEMORY) && \
1476 (rd->interfaces[len][dst->type].flags & INMEMORY) && \
1477 (dst->regoff != rd->interfaces[len][dst->type].regoff) ))
1479 /* one in memory or both inmemory at different offsets */
1480 count_mem_move_bb++;
1487 #if defined(ENABLE_LSRA)
1492 dst = bptr->instack;
1493 iptr = bptr->iinstr;
1497 while (--len >= 0) {
1501 if ((src!= NULL) && (src != src_old)) { /* new stackslot */
1502 switch (src->varkind) {
1505 if (!(src->flags & INMEMORY))
1506 count_ss_register++;
1512 /* case LOCALVAR: */
1513 /* if (!(rd->locals[src->varnum][src->type].flags & INMEMORY)) */
1514 /* count_ss_register++; */
1516 /* count_ss_spilled++; */
1519 if (!(src->flags & INMEMORY))
1520 count_argument_mem_ss++;
1522 count_argument_reg_ss++;
1526 /* if (IS_FLT_DBL_TYPE(src->type)) { */
1527 /* if (src->varnum < FLT_ARG_CNT) { */
1528 /* count_ss_register++; */
1532 /* #if defined(__POWERPC__) */
1533 /* if (src->varnum < INT_ARG_CNT - (IS_2_WORD_TYPE(src->type) != 0)) { */
1535 /* if (src->varnum < INT_ARG_CNT) { */
1537 /* count_ss_register++; */
1541 /* count_ss_spilled++; */
1548 } /* while instructions */
1551 } /* while blocks */
1552 count_interface_size += size_interface; /* accummulate the size of the interface (between bb boundaries) */
1553 if (in_register) count_method_in_register++;
1555 #endif /* defined(ENABLE_STATISTICS) */
1559 * These are local overrides for various environment variables in Emacs.
1560 * Please do not remove this and leave it at the end of the file, where
1561 * Emacs will automagically detect them.
1562 * ---------------------------------------------------------------------
1565 * indent-tabs-mode: t