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 4055 2006-01-02 12:59:54Z 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);
75 #ifdef INVOKE_NEW_DEBUG
77 printf("memuse after reg.inc: %3i\n",rd->memuse);
83 /* function interface_regalloc *************************************************
85 allocates registers for all interface variables
87 *******************************************************************************/
89 static void interface_regalloc(methodinfo *m, codegendata *cd, registerdata *rd)
92 int intalloc, fltalloc; /* Remember allocated Register/Memory offset */
93 /* in case a more vars are packed into this interface slot */
95 int intregsneeded = 0;
97 /* allocate LNG and DBL Types first to ensure 2 memory slots or registers */
98 /* on HAS_4BYTE_STACKSLOT architectures */
99 int typeloop[] = { TYPE_LNG, TYPE_DBL, TYPE_INT, TYPE_FLT, TYPE_ADR };
101 /* rd->memuse was already set in stack.c to allocate stack space for */
102 /* passing arguments to called methods */
103 #if defined(__I386__)
104 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
105 /* reserve 0(%esp) for Monitorenter/exit Argument on i386 */
110 #ifdef INVOKE_NEW_DEBUG
111 if (compileverbose) {
112 if (checksync && (m->flags & ACC_SYNCHRONIZED))
113 printf("ACC_SYNCHRONIZED\n");
114 printf("analyse: argintru %3i argfltru %3i memuse %3i\n",
115 rd->argintreguse, rd->argfltreguse, rd->memuse);
120 for (s = 0; s < cd->maxstack; s++) {
121 intalloc = -1; fltalloc = -1;
122 saved = (rd->interfaces[s][TYPE_INT].flags |
123 rd->interfaces[s][TYPE_LNG].flags |
124 rd->interfaces[s][TYPE_FLT].flags |
125 rd->interfaces[s][TYPE_DBL].flags |
126 rd->interfaces[s][TYPE_ADR].flags) & SAVEDVAR;
128 for (tt = 0; tt <= 4; tt++) {
130 v = &rd->interfaces[s][t];
132 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
133 intregsneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
135 #if defined(HAS_4BYTE_STACKSLOT)
136 memneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
139 #if defined(HAS_ADDRESS_REGISTER_FILE)
140 if (IS_ADR_TYPE(t)) {
142 &&(rd->argadrreguse < ADR_ARG_CNT)) {
143 v->regoff = rd->argadrregs[rd->argadrreguset++];
144 } else if (rd->tmpadrreguse > 0) {
145 v->regoff = rd->tmpadrregs[--rd->tmpadrreguse];
146 } else if (rd->savadrreguse > 0) {
147 v->regoff = rd->savadrregs[--rd->savadrreguse];
149 v->flags |= INMEMORY;
150 v->regoff = rd->memuse++;
152 } else /* !IS_ADR_TYPE */
153 #endif /* defined(HAS_ADDRESS_REGISTER_FILE) */
155 if (IS_FLT_DBL_TYPE(t)) {
157 /* Reuse memory slot(s)/register(s) for shared interface slots */
158 v->flags |= rd->interfaces[s][fltalloc].flags
160 v->regoff = rd->interfaces[s][fltalloc].regoff;
161 } else if (!m->isleafmethod
162 && (rd->argfltreguse < FLT_ARG_CNT)) {
163 v->regoff = rd->argfltregs[rd->argfltreguse++];
164 } else if (rd->tmpfltreguse > 0) {
165 v->regoff = rd->tmpfltregs[--rd->tmpfltreguse];
166 } else if (rd->savfltreguse > 0) {
167 v->regoff = rd->savfltregs[--rd->savfltreguse];
169 v->flags |= INMEMORY;
170 v->regoff = rd->memuse;
171 rd->memuse += memneeded + 1;
174 } else { /* !IS_FLT_DBL_TYPE(t) */
175 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
177 * for i386 put all longs in memory
179 if (IS_2_WORD_TYPE(t)) {
180 v->flags |= INMEMORY;
181 v->regoff = rd->memuse;
182 rd->memuse += memneeded + 1;
184 #endif /* defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE...GISTERS) */
185 /* #if !defined(HAS_4BYTE_STACKSLOT) */
187 /* Reuse memory slot(s)/register(s) for shared interface slots */
189 rd->interfaces[s][intalloc].flags
191 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
192 if (!(v->flags & INMEMORY)
193 && IS_2_WORD_TYPE(intalloc))
194 v->regoff = GET_LOW_REG(
195 rd->interfaces[s][intalloc].regoff);
199 rd->interfaces[s][intalloc].regoff;
201 /* #endif *//* !defined(HAS_4BYTE_STACKSLOT) */
202 if (!m->isleafmethod &&
204 + intregsneeded < INT_ARG_CNT)) {
205 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
208 rd->argintregs[rd->argintreguse],
209 rd->argintregs[rd->argintreguse + 1]);
213 rd->argintregs[rd->argintreguse];
214 rd->argintreguse += intregsneeded + 1;
216 else if (rd->tmpintreguse > intregsneeded) {
217 rd->tmpintreguse -= intregsneeded + 1;
218 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
221 rd->tmpintregs[rd->tmpintreguse],
222 rd->tmpintregs[rd->tmpintreguse + 1]);
226 rd->tmpintregs[rd->tmpintreguse];
228 else if (rd->savintreguse > intregsneeded) {
229 rd->savintreguse -= intregsneeded + 1;
231 rd->savintregs[rd->savintreguse];
232 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
235 rd->savintregs[rd->savintreguse],
236 rd->savintregs[rd->savintreguse + 1]);
240 rd->savintregs[rd->savintreguse];
243 v->flags |= INMEMORY;
244 v->regoff = rd->memuse;
245 rd->memuse += memneeded + 1;
249 } /* if (IS_FLT_DBL_TYPE(t)) */
251 } else { /* (saved) */
252 /* now the same like above, but without a chance to take a temporary register */
253 #ifdef HAS_ADDRESS_REGISTER_FILE
254 if (IS_ADR_TYPE(t)) {
255 if (rd->savadrreguse > 0) {
256 v->regoff = rd->savadrregs[--rd->savadrreguse];
259 v->flags |= INMEMORY;
260 v->regoff = rd->memuse++;
265 if (IS_FLT_DBL_TYPE(t)) {
267 v->flags |= rd->interfaces[s][fltalloc].flags
269 v->regoff = rd->interfaces[s][fltalloc].regoff;
271 if (rd->savfltreguse > 0) {
272 v->regoff = rd->savfltregs[--rd->savfltreguse];
275 v->flags |= INMEMORY;
276 v->regoff = rd->memuse;
277 rd->memuse += memneeded + 1;
281 else { /* IS_INT_LNG */
282 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
284 * for i386 put all longs in memory
286 if (IS_2_WORD_TYPE(t)) {
287 v->flags |= INMEMORY;
288 v->regoff = rd->memuse;
289 rd->memuse += memneeded + 1;
293 /* #if !defined(HAS_4BYTE_STACKSLOT) */
296 rd->interfaces[s][intalloc].flags & INMEMORY;
297 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
298 if (!(v->flags & INMEMORY)
299 && IS_2_WORD_TYPE(intalloc))
302 rd->interfaces[s][intalloc].regoff);
306 rd->interfaces[s][intalloc].regoff;
310 if (rd->savintreguse > intregsneeded) {
311 rd->savintreguse -= intregsneeded + 1;
312 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
314 v->regoff = PACK_REGS(
315 rd->savintregs[rd->savintreguse],
316 rd->savintregs[rd->savintreguse + 1]);
320 rd->savintregs[rd->savintreguse];
322 v->flags |= INMEMORY;
323 v->regoff = rd->memuse;
324 rd->memuse += memneeded + 1;
329 } /* if (IS_FLT_DBL_TYPE(t) else */
330 } /* if (IS_ADR_TYPE(t)) else */
331 } /* if (saved) else */
332 } /* if (type >= 0) */
339 /* function local_regalloc *****************************************************
341 allocates registers for all local variables
343 *******************************************************************************/
345 static void local_regalloc(methodinfo *m, codegendata *cd, registerdata *rd)
348 int intalloc, fltalloc;
350 int intregsneeded = 0;
352 int typeloop[] = { TYPE_LNG, TYPE_DBL, TYPE_INT, TYPE_FLT, TYPE_ADR };
353 int fargcnt, iargcnt;
354 #ifdef HAS_ADDRESS_REGISTER_FILE
358 if (m->isleafmethod) {
359 methoddesc *md = m->parseddesc;
361 iargcnt = md->argintreguse;
362 fargcnt = md->argfltreguse;
363 #ifdef HAS_ADDRESS_REGISTER_FILE
364 aargcnt = md->argadrreguse;
366 for (p = 0, s = 0; s < cd->maxlocals; s++, p++) {
367 intalloc = -1; fltalloc = -1;
368 for (tt = 0; tt <= 4; tt++) {
370 v = &rd->locals[s][t];
375 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
376 intregsneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
378 #if defined(HAS_4BYTE_STACKSLOT)
379 memneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
385 * #ifdef HAS_ADDRESS_REGISTER_FILE
392 * } else { / int & lng
396 * must not to be changed!
399 #ifdef HAS_ADDRESS_REGISTER_FILE
400 if (IS_ADR_TYPE(t)) {
401 if ((p < md->paramcount) && !md->params[p].inmemory) {
403 v->regoff = rd->argadrregs[md->params[p].regoff];
405 if (rd->tmpadrreguse > 0) {
407 v->regoff = rd->tmpadrregs[--rd->tmpadrreguse];
409 else if (rd->savadrreguse > 0) {
411 v->regoff = rd->savadrregs[--rd->savadrreguse];
413 /* use unused argument registers as local registers */
414 else if ((p >= md->paramcount) &&
415 (aargcnt < ADR_ARG_CNT)) {
417 v->regoff = rd->argadrregs[aargcnt++];
420 v->flags |= INMEMORY;
421 v->regoff = rd->memuse++;
425 if (IS_FLT_DBL_TYPE(t)) {
427 v->flags = rd->locals[s][fltalloc].flags;
428 v->regoff = rd->locals[s][fltalloc].regoff;
430 #if !defined(SUPPORT_PASS_FLOATARGS_IN_INTREGS)
431 /* We can only use float arguments as local variables,
432 * if we do not pass them in integer registers. */
433 else if ((p < md->paramcount) &&
434 !md->params[p].inmemory) {
436 v->regoff = rd->argfltregs[md->params[p].regoff];
439 else if (rd->tmpfltreguse > 0) {
441 v->regoff = rd->tmpfltregs[--rd->tmpfltreguse];
443 else if (rd->savfltreguse > 0) {
445 v->regoff = rd->savfltregs[--rd->savfltreguse];
447 /* use unused argument registers as local registers */
448 else if ((p >= m->paramcount) &&
449 (fargcnt < FLT_ARG_CNT)) {
451 v->regoff = rd->argfltregs[fargcnt];
456 v->regoff = rd->memuse;
457 rd->memuse += memneeded + 1;
462 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
464 * for i386 put all longs in memory
466 if (IS_2_WORD_TYPE(t)) {
468 v->regoff = rd->memuse;
469 rd->memuse += memneeded + 1;
474 v->flags = rd->locals[s][intalloc].flags;
475 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
476 if (!(v->flags & INMEMORY)
477 && IS_2_WORD_TYPE(intalloc))
478 v->regoff = GET_LOW_REG(
479 rd->locals[s][intalloc].regoff);
482 v->regoff = rd->locals[s][intalloc].regoff;
484 else if ((p < md->paramcount) &&
485 !md->params[p].inmemory) {
487 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
488 if (IS_2_WORD_TYPE(t))
489 /* For ARM: - if GET_LOW_REG(md->params[p].regoff) == R4, prevent here that */
490 /* rd->argintregs[GET_HIGH_REG(md->...)) is used! */
491 v->regoff = PACK_REGS(
492 rd->argintregs[GET_LOW_REG(md->params[p].regoff)],
493 rd->argintregs[GET_HIGH_REG(md->params[p].regoff)]);
497 rd->argintregs[md->params[p].regoff];
499 else if (rd->tmpintreguse > intregsneeded) {
500 rd->tmpintreguse -= intregsneeded + 1;
502 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
504 v->regoff = PACK_REGS(
505 rd->tmpintregs[rd->tmpintreguse],
506 rd->tmpintregs[rd->tmpintreguse + 1]);
510 rd->tmpintregs[rd->tmpintreguse];
512 else if (rd->savintreguse > intregsneeded) {
513 rd->savintreguse -= intregsneeded + 1;
515 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
517 v->regoff = PACK_REGS(
518 rd->savintregs[rd->savintreguse],
519 rd->savintregs[rd->savintreguse + 1]);
522 v->regoff =rd->savintregs[rd->savintreguse];
525 * use unused argument registers as local registers
527 else if ((p >= m->paramcount) &&
528 (iargcnt < INT_ARG_CNT)) {
530 v->regoff = rd->argintregs[iargcnt];
535 v->regoff = rd->memuse;
536 rd->memuse += memneeded + 1;
541 #ifdef HAS_ADDRESS_REGISTER_FILE
544 } /* for (tt=0;...) */
546 /* If the current parameter is a 2-word type, the next local slot */
549 if (p < md->paramcount)
550 if (IS_2_WORD_TYPE(md->paramtypes[p].type))
556 for (s = 0; s < cd->maxlocals; s++) {
557 intalloc = -1; fltalloc = -1;
558 for (tt=0; tt<=4; tt++) {
560 v = &rd->locals[s][t];
563 #ifdef SUPPORT_COMBINE_INTEGER_REGISTERS
564 intregsneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
566 #if defined(HAS_4BYTE_STACKSLOT)
567 memneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
569 #ifdef HAS_ADDRESS_REGISTER_FILE
570 if ( IS_ADR_TYPE(t) ) {
571 if (rd->savadrreguse > 0) {
573 v->regoff = rd->savadrregs[--rd->savadrreguse];
577 v->regoff = rd->memuse++;
581 if (IS_FLT_DBL_TYPE(t)) {
583 v->flags = rd->locals[s][fltalloc].flags;
584 v->regoff = rd->locals[s][fltalloc].regoff;
586 else if (rd->savfltreguse > 0) {
588 v->regoff = rd->savfltregs[--rd->savfltreguse];
592 /* Align doubles in Memory */
593 if ( (memneeded) && (rd->memuse & 1))
595 v->regoff = rd->memuse;
596 rd->memuse += memneeded + 1;
601 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
603 * for i386 put all longs in memory
605 if (IS_2_WORD_TYPE(t)) {
607 v->regoff = rd->memuse;
608 rd->memuse += memneeded + 1;
612 v->flags = rd->locals[s][intalloc].flags;
613 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
614 if (!(v->flags & INMEMORY)
615 && IS_2_WORD_TYPE(intalloc))
616 v->regoff = GET_LOW_REG(
617 rd->locals[s][intalloc].regoff);
620 v->regoff = rd->locals[s][intalloc].regoff;
622 else if (rd->savintreguse > intregsneeded) {
623 rd->savintreguse -= intregsneeded+1;
625 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
627 v->regoff = PACK_REGS(
628 rd->savintregs[rd->savintreguse],
629 rd->savintregs[rd->savintreguse + 1]);
632 v->regoff =rd->savintregs[rd->savintreguse];
636 v->regoff = rd->memuse;
637 rd->memuse += memneeded + 1;
639 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
644 #ifdef HAS_ADDRESS_REGISTER_FILE
653 static void reg_init_temp(methodinfo *m, registerdata *rd)
656 #if defined(HAS_4BYTE_STACKSLOT)
657 rd->freememtop_2 = 0;
660 rd->freetmpinttop = 0;
661 rd->freesavinttop = 0;
662 rd->freetmpflttop = 0;
663 rd->freesavflttop = 0;
664 #ifdef HAS_ADDRESS_REGISTER_FILE
665 rd->freetmpadrtop = 0;
666 rd->freesavadrtop = 0;
669 rd->freearginttop = 0;
670 rd->freeargflttop = 0;
671 #ifdef HAS_ADDRESS_REGISTER_FILE
672 rd->freeargadrtop = 0;
675 if (m->isleafmethod) {
676 /* Don't use not used Argument Registers in Leafmethods -> they could */
677 /* already be in use for Locals passed as parameter to this Method */
678 rd->argintreguse = INT_ARG_CNT;
679 rd->argfltreguse = FLT_ARG_CNT;
680 #ifdef HAS_ADDRESS_REGISTER_FILE
681 rd->argadrreguse = ADR_ARG_CNT;
687 #define reg_new_temp(rd,s) if (s->varkind == TEMPVAR) reg_new_temp_func(rd, s)
689 static void reg_new_temp_func(registerdata *rd, stackptr s)
695 /* Try to allocate a saved register if there is no temporary one */
696 /* available. This is what happens during the second run. */
697 tryagain = (s->flags & SAVEDVAR) ? 1 : 2;
699 #ifdef SUPPORT_COMBINE_INTEGER_REGISTERS
700 intregsneeded = (IS_2_WORD_TYPE(s->type)) ? 1 : 0;
704 #if defined(HAS_4BYTE_STACKSLOT)
705 memneeded = (IS_2_WORD_TYPE(s->type)) ? 1 : 0;
710 for(; tryagain; --tryagain) {
712 if (!(s->flags & SAVEDVAR))
713 s->flags |= SAVEDTMP;
714 #ifdef HAS_ADDRESS_REGISTER_FILE
715 if (IS_ADR_TYPE(s->type)) {
716 if (rd->freesavadrtop > 0) {
717 s->regoff = rd->freesavadrregs[--rd->freesavadrtop];
719 } else if (rd->savadrreguse > 0) {
720 s->regoff = rd->savadrregs[--rd->savadrreguse];
726 if (IS_FLT_DBL_TYPE(s->type)) {
727 if (rd->freesavflttop > 0) {
728 s->regoff = rd->freesavfltregs[--rd->freesavflttop];
730 } else if (rd->savfltreguse > 0) {
731 s->regoff = rd->savfltregs[--rd->savfltreguse];
735 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
737 * for i386 put all longs in memory
739 if (!IS_2_WORD_TYPE(s->type))
742 if (rd->freesavinttop > intregsneeded) {
743 rd->freesavinttop -= intregsneeded + 1;
744 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
746 s->regoff = PACK_REGS(
747 rd->freesavintregs[rd->freesavinttop],
748 rd->freesavintregs[rd->freesavinttop + 1]);
752 rd->freesavintregs[rd->freesavinttop];
754 } else if (rd->savintreguse > intregsneeded) {
755 rd->savintreguse -= intregsneeded + 1;
756 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
758 s->regoff = PACK_REGS(
759 rd->savintregs[rd->savintreguse],
760 rd->savintregs[rd->savintreguse + 1]);
763 s->regoff = rd->savintregs[rd->savintreguse];
769 } else { /* tryagain == 2 */
770 #ifdef HAS_ADDRESS_REGISTER_FILE
771 if (IS_ADR_TYPE(s->type)) {
772 if (rd->freetmpadrtop > 0) {
773 s->regoff = rd->freetmpadrregs[--rd->freetmpadrtop];
775 } else if (rd->tmpadrreguse > 0) {
776 s->regoff = rd->tmpadrregs[--rd->tmpadrreguse];
782 if (IS_FLT_DBL_TYPE(s->type)) {
783 if (rd->freeargflttop > 0) {
784 s->regoff = rd->freeargfltregs[--rd->freeargflttop];
787 } else if (rd->argfltreguse < FLT_ARG_CNT) {
788 s->regoff = rd->argfltregs[rd->argfltreguse++];
791 } else if (rd->freetmpflttop > 0) {
792 s->regoff = rd->freetmpfltregs[--rd->freetmpflttop];
794 } else if (rd->tmpfltreguse > 0) {
795 s->regoff = rd->tmpfltregs[--rd->tmpfltreguse];
800 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
802 * for i386 put all longs in memory
804 if (!IS_2_WORD_TYPE(s->type))
807 if (rd->freearginttop > intregsneeded) {
808 rd->freearginttop -= intregsneeded + 1;
810 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
812 s->regoff = PACK_REGS(
813 rd->freeargintregs[rd->freearginttop],
814 rd->freeargintregs[rd->freearginttop + 1]);
818 rd->freeargintregs[rd->freearginttop];
820 } else if (rd->argintreguse
821 < INT_ARG_CNT - intregsneeded) {
822 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
824 s->regoff = PACK_REGS(
825 rd->argintregs[rd->argintreguse],
826 rd->argintregs[rd->argintreguse + 1]);
829 s->regoff = rd->argintregs[rd->argintreguse];
831 rd->argintreguse += intregsneeded + 1;
833 } else if (rd->freetmpinttop > intregsneeded) {
834 rd->freetmpinttop -= intregsneeded + 1;
835 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
837 s->regoff = PACK_REGS(
838 rd->freetmpintregs[rd->freetmpinttop],
839 rd->freetmpintregs[rd->freetmpinttop + 1]);
842 s->regoff = rd->freetmpintregs[rd->freetmpinttop];
844 } else if (rd->tmpintreguse > intregsneeded) {
845 rd->tmpintreguse -= intregsneeded + 1;
846 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
848 s->regoff = PACK_REGS(
849 rd->tmpintregs[rd->tmpintreguse],
850 rd->tmpintregs[rd->tmpintreguse + 1]);
853 s->regoff = rd->tmpintregs[rd->tmpintreguse];
856 } /* if (!IS_2_WORD_TYPE(s->type)) */
857 } /* if (IS_FLT_DBL_TYPE(s->type)) */
858 } /* if (IS_ADR_TYPE(s->type)) */
859 } /* if (tryagain == 1) else */
860 } /* for(; tryagain; --tryagain) */
862 #if defined(HAS_4BYTE_STACKSLOT)
863 if ((memneeded == 1) && (rd->freememtop_2 > 0)) {
865 s->regoff = rd->freemem_2[rd->freememtop_2];
867 #endif /*defined(HAS_4BYTE_STACKSLOT) */
868 if ((memneeded == 0) && (rd->freememtop > 0)) {
870 s->regoff = rd->freemem[rd->freememtop];
872 #if defined(HAS_4BYTE_STACKSLOT)
873 /* align 2 Word Types */
874 if ((memneeded) && ((rd->memuse & 1) == 1)) {
875 /* Put patched memory slot on freemem */
876 rd->freemem[rd->freememtop++] = rd->memuse;
879 #endif /*defined(HAS_4BYTE_STACKSLOT) */
880 s->regoff = rd->memuse;
881 rd->memuse += memneeded + 1;
883 s->flags |= INMEMORY;
887 #define reg_free_temp(rd,s) if (s->varkind == TEMPVAR) reg_free_temp_func(rd, s)
889 static void reg_free_temp_func(registerdata *rd, stackptr s)
894 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
895 intregsneeded = (IS_2_WORD_TYPE(s->type)) ? 1 : 0;
900 #if defined(HAS_4BYTE_STACKSLOT)
901 memneeded = (IS_2_WORD_TYPE(s->type)) ? 1 : 0;
906 if (s->flags & INMEMORY) {
907 #if defined(HAS_4BYTE_STACKSLOT)
909 rd->freemem_2[rd->freememtop_2] = s->regoff;
914 rd->freemem[rd->freememtop] = s->regoff;
918 #ifdef HAS_ADDRESS_REGISTER_FILE
919 } else if (IS_ADR_TYPE(s->type)) {
920 if (s->flags & (SAVEDVAR | SAVEDTMP)) {
921 s->flags &= ~SAVEDTMP;
922 rd->freesavadrregs[rd->freesavadrtop++] = s->regoff;
924 rd->freetmpadrregs[rd->freetmpadrtop++] = s->regoff;
926 } else if (IS_FLT_DBL_TYPE(s->type)) {
927 if (s->flags & (SAVEDVAR | SAVEDTMP)) {
928 s->flags &= ~SAVEDTMP;
929 rd->freesavfltregs[rd->freesavflttop++] = s->regoff;
930 } else if (s->flags & TMPARG) {
932 rd->freeargfltregs[rd->freeargflttop++] = s->regoff;
934 rd->freetmpfltregs[rd->freetmpflttop++] = s->regoff;
935 } else { /* IS_INT_LNG_TYPE */
936 if (s->flags & (SAVEDVAR | SAVEDTMP)) {
937 s->flags &= ~SAVEDTMP;
938 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
940 rd->freesavintregs[rd->freesavinttop] =
941 GET_LOW_REG(s->regoff);
942 rd->freesavintregs[rd->freesavinttop + 1] =
943 GET_HIGH_REG(s->regoff);
946 rd->freesavintregs[rd->freesavinttop] = s->regoff;
947 rd->freesavinttop += intregsneeded + 1;
949 } else if (s->flags & TMPARG) {
951 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
953 rd->freeargintregs[rd->freearginttop] =
954 GET_LOW_REG(s->regoff);
955 rd->freeargintregs[rd->freearginttop + 1] =
956 GET_HIGH_REG(s->regoff);
959 rd->freeargintregs[rd->freearginttop] = s->regoff;
960 rd->freearginttop += intregsneeded + 1;
962 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
964 rd->freetmpintregs[rd->freetmpinttop] =
965 GET_LOW_REG(s->regoff);
966 rd->freetmpintregs[rd->freetmpinttop + 1] =
967 GET_HIGH_REG(s->regoff);
970 rd->freetmpintregs[rd->freetmpinttop] = s->regoff;
971 rd->freetmpinttop += intregsneeded + 1;
978 static void allocate_scratch_registers(methodinfo *m, registerdata *rd)
988 builtintable_entry *bte;
991 /* initialize temp registers */
992 reg_init_temp(m, rd);
994 bptr = m->basicblocks;
996 while (bptr != NULL) {
997 if (bptr->flags >= BBREACHED) {
1001 iptr = bptr->iinstr;
1004 while (--len >= 0) {
1014 case ICMD_ELSE_ICONST:
1015 case ICMD_CHECKNULL:
1021 case ICMD_PUTSTATICCONST:
1022 case ICMD_INLINE_START:
1023 case ICMD_INLINE_END:
1026 /* pop 0 push 1 const */
1034 /* pop 0 push 1 load */
1041 reg_new_temp(rd, dst);
1055 reg_free_temp(rd, src);
1056 reg_free_temp(rd, src->prev);
1057 reg_new_temp(rd, dst);
1071 reg_free_temp(rd, src);
1072 reg_free_temp(rd, src->prev);
1073 reg_free_temp(rd, src->prev->prev);
1076 /* pop 1 push 0 store */
1096 case ICMD_PUTSTATIC:
1097 case ICMD_PUTFIELDCONST:
1099 /* pop 1 push 0 branch */
1102 case ICMD_IFNONNULL:
1118 /* pop 1 push 0 table branch */
1120 case ICMD_TABLESWITCH:
1121 case ICMD_LOOKUPSWITCH:
1123 case ICMD_MONITORENTER:
1124 case ICMD_MONITOREXIT:
1125 reg_free_temp(rd, src);
1128 /* pop 2 push 0 branch */
1130 case ICMD_IF_ICMPEQ:
1131 case ICMD_IF_ICMPNE:
1132 case ICMD_IF_ICMPLT:
1133 case ICMD_IF_ICMPGE:
1134 case ICMD_IF_ICMPGT:
1135 case ICMD_IF_ICMPLE:
1137 case ICMD_IF_LCMPEQ:
1138 case ICMD_IF_LCMPNE:
1139 case ICMD_IF_LCMPLT:
1140 case ICMD_IF_LCMPGE:
1141 case ICMD_IF_LCMPGT:
1142 case ICMD_IF_LCMPLE:
1144 case ICMD_IF_ACMPEQ:
1145 case ICMD_IF_ACMPNE:
1153 case ICMD_IASTORECONST:
1154 case ICMD_LASTORECONST:
1155 case ICMD_AASTORECONST:
1156 case ICMD_BASTORECONST:
1157 case ICMD_CASTORECONST:
1158 case ICMD_SASTORECONST:
1159 reg_free_temp(rd, src);
1160 reg_free_temp(rd, src->prev);
1163 /* pop 0 push 1 dup */
1166 reg_new_temp(rd, dst);
1169 /* pop 0 push 2 dup */
1172 reg_new_temp(rd, dst->prev);
1173 reg_new_temp(rd, dst);
1176 /* pop 2 push 3 dup */
1179 reg_free_temp(rd, src);
1180 reg_new_temp(rd, dst);
1181 reg_free_temp(rd, src->prev);
1182 reg_new_temp(rd, dst->prev);
1183 reg_new_temp(rd, dst->prev->prev);
1186 /* pop 3 push 4 dup */
1189 reg_free_temp(rd, src);
1190 reg_new_temp(rd, dst);
1191 reg_free_temp(rd, src->prev);
1192 reg_new_temp(rd, dst->prev);
1193 reg_free_temp(rd, src->prev->prev);
1194 reg_new_temp(rd, dst->prev->prev);
1195 reg_new_temp(rd, dst->prev->prev->prev);
1198 /* pop 3 push 5 dup */
1201 reg_free_temp(rd, src);
1202 reg_new_temp(rd, dst);
1203 reg_free_temp(rd, src->prev);
1204 reg_new_temp(rd, dst->prev);
1205 reg_free_temp(rd, src->prev->prev);
1206 reg_new_temp(rd, dst->prev->prev);
1207 reg_new_temp(rd, dst->prev->prev->prev);
1208 reg_new_temp(rd, dst->prev->prev->prev->prev);
1211 /* pop 4 push 6 dup */
1214 reg_free_temp(rd, src);
1215 reg_new_temp(rd, dst);
1216 reg_free_temp(rd, src->prev);
1217 reg_new_temp(rd, dst->prev);
1218 reg_free_temp(rd, src->prev->prev);
1219 reg_new_temp(rd, dst->prev->prev);
1220 reg_free_temp(rd, src->prev->prev->prev);
1221 reg_new_temp(rd, dst->prev->prev->prev);
1222 reg_new_temp(rd, dst->prev->prev->prev->prev);
1223 reg_new_temp(rd, dst->prev->prev->prev->prev->prev);
1226 /* pop 2 push 2 swap */
1229 reg_free_temp(rd, src);
1230 reg_new_temp(rd, dst->prev);
1231 reg_free_temp(rd, src->prev);
1232 reg_new_temp(rd, dst);
1281 reg_free_temp(rd, src);
1282 reg_free_temp(rd, src->prev);
1283 reg_new_temp(rd, dst);
1288 case ICMD_IADDCONST:
1289 case ICMD_ISUBCONST:
1290 case ICMD_IMULCONST:
1294 case ICMD_IANDCONST:
1296 case ICMD_IXORCONST:
1297 case ICMD_ISHLCONST:
1298 case ICMD_ISHRCONST:
1299 case ICMD_IUSHRCONST:
1301 case ICMD_LADDCONST:
1302 case ICMD_LSUBCONST:
1303 case ICMD_LMULCONST:
1307 case ICMD_LANDCONST:
1309 case ICMD_LXORCONST:
1310 case ICMD_LSHLCONST:
1311 case ICMD_LSHRCONST:
1312 case ICMD_LUSHRCONST:
1314 case ICMD_IFEQ_ICONST:
1315 case ICMD_IFNE_ICONST:
1316 case ICMD_IFLT_ICONST:
1317 case ICMD_IFGE_ICONST:
1318 case ICMD_IFGT_ICONST:
1319 case ICMD_IFLE_ICONST:
1324 case ICMD_INT2SHORT:
1342 case ICMD_CHECKCAST:
1344 case ICMD_ARRAYLENGTH:
1345 case ICMD_INSTANCEOF:
1348 case ICMD_ANEWARRAY:
1351 reg_free_temp(rd, src);
1352 reg_new_temp(rd, dst);
1357 case ICMD_GETSTATIC:
1360 reg_new_temp(rd, dst);
1363 /* pop many push any */
1365 case ICMD_INVOKESTATIC:
1366 case ICMD_INVOKESPECIAL:
1367 case ICMD_INVOKEVIRTUAL:
1368 case ICMD_INVOKEINTERFACE:
1372 md = lm->parseddesc;
1374 unresolved_method *um = iptr->target;
1375 md = um->methodref->parseddesc.md;
1379 reg_free_temp(rd, src);
1382 if (md->returntype.type != TYPE_VOID)
1383 reg_new_temp(rd, dst);
1391 reg_free_temp(rd, src);
1394 if (md->returntype.type != TYPE_VOID)
1395 reg_new_temp(rd, dst);
1398 case ICMD_MULTIANEWARRAY:
1401 reg_free_temp(rd, src);
1404 reg_new_temp(rd, dst);
1408 throw_cacao_exception_exit(string_java_lang_InternalError,
1409 "Unknown ICMD %d during register allocation",
1413 } /* while instructions */
1416 } /* while blocks */
1420 #if defined(ENABLE_STATISTICS)
1421 void reg_make_statistics( methodinfo *m, codegendata *cd, registerdata *rd) {
1424 stackptr src, src_old;
1428 int size_interface; /* == maximum size of in/out stack at basic block boundaries */
1435 /* count how many local variables are held in memory or register */
1436 for(i=0; i < cd->maxlocals; i++)
1437 for (type=0; type <=4; type++)
1438 if (rd->locals[i][type].type != -1) { /* valid local */
1439 if (rd->locals[i][type].flags & INMEMORY) {
1440 count_locals_spilled++;
1444 count_locals_register++;
1446 /* count how many stack slots are held in memory or register */
1448 bptr = m->basicblocks;
1449 while (bptr != NULL) {
1450 if (bptr->flags >= BBREACHED) {
1452 #if defined(ENABLE_LSRA)
1455 /* check for memory moves from interface to BB instack */
1456 dst = bptr->instack;
1457 len = bptr->indepth;
1459 if (len > size_interface) size_interface = len;
1461 while (dst != NULL) {
1463 if (dst->varkind != STACKVAR) {
1464 if ( (dst->flags & INMEMORY) ||
1465 (rd->interfaces[len][dst->type].flags & INMEMORY) ||
1466 ( (dst->flags & INMEMORY) &&
1467 (rd->interfaces[len][dst->type].flags & INMEMORY) &&
1468 (dst->regoff != rd->interfaces[len][dst->type].regoff) ))
1470 /* one in memory or both inmemory at different offsets */
1471 count_mem_move_bb++;
1479 /* check for memory moves from BB outstack to interface */
1480 dst = bptr->outstack;
1481 len = bptr->outdepth;
1482 if (len > size_interface) size_interface = len;
1486 if (dst->varkind != STACKVAR) {
1487 if ( (dst->flags & INMEMORY) || \
1488 (rd->interfaces[len][dst->type].flags & INMEMORY) || \
1489 ( (dst->flags & INMEMORY) && \
1490 (rd->interfaces[len][dst->type].flags & INMEMORY) && \
1491 (dst->regoff != rd->interfaces[len][dst->type].regoff) ))
1493 /* one in memory or both inmemory at different offsets */
1494 count_mem_move_bb++;
1501 #if defined(ENABLE_LSRA)
1506 dst = bptr->instack;
1507 iptr = bptr->iinstr;
1511 while (--len >= 0) {
1515 if ((src!= NULL) && (src != src_old)) { /* new stackslot */
1516 switch (src->varkind) {
1519 if (!(src->flags & INMEMORY))
1520 count_ss_register++;
1526 /* case LOCALVAR: */
1527 /* if (!(rd->locals[src->varnum][src->type].flags & INMEMORY)) */
1528 /* count_ss_register++; */
1530 /* count_ss_spilled++; */
1533 if (!(src->flags & INMEMORY))
1534 count_argument_mem_ss++;
1536 count_argument_reg_ss++;
1540 /* if (IS_FLT_DBL_TYPE(src->type)) { */
1541 /* if (src->varnum < FLT_ARG_CNT) { */
1542 /* count_ss_register++; */
1546 /* #if defined(__POWERPC__) */
1547 /* if (src->varnum < INT_ARG_CNT - (IS_2_WORD_TYPE(src->type) != 0)) { */
1549 /* if (src->varnum < INT_ARG_CNT) { */
1551 /* count_ss_register++; */
1555 /* count_ss_spilled++; */
1562 } /* while instructions */
1565 } /* while blocks */
1566 count_interface_size += size_interface; /* accummulate the size of the interface (between bb boundaries) */
1567 if (in_register) count_method_in_register++;
1569 #endif /* defined(ENABLE_STATISTICS) */
1573 * These are local overrides for various environment variables in Emacs.
1574 * Please do not remove this and leave it at the end of the file, where
1575 * Emacs will automagically detect them.
1576 * ---------------------------------------------------------------------
1579 * indent-tabs-mode: t