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
35 $Id: simplereg.c 4524 2006-02-16 19:39:36Z christian $
48 #include "vm/builtin.h"
49 #include "vm/exceptions.h"
50 #include "mm/memory.h"
51 #include "vm/method.h"
52 #include "vm/options.h"
53 #include "vm/resolve.h"
54 #include "vm/stringlocal.h"
55 #include "vm/jit/reg.h"
56 #include "vm/jit/allocator/simplereg.h"
58 /* function prototypes for this file */
60 static void interface_regalloc(methodinfo *m, codegendata *cd, registerdata *rd);
61 static void local_regalloc(methodinfo *m, codegendata *cd, registerdata *rd);
62 static void allocate_scratch_registers(methodinfo *m, registerdata *rd);
65 /* function interface_regalloc *************************************************
67 allocates registers for all interface variables
69 *******************************************************************************/
71 void regalloc(methodinfo *m, codegendata *cd, registerdata *rd)
73 /* There is a problem with the use of unused float argument registers in */
74 /* leafmethods for stackslots on c7 (3* Dual Core AMD Opteron(tm) */
75 /* Processor 270) - runtime for the jvm98 _mtrt benchmark is heaviliy */
76 /* increased. This could be prevented by setting rd->argfltreguse to */
77 /* FLT_ARG_CNT before calling allocate_scratch_registers and setting it */
78 /* back to the original value before calling local_regalloc. */
80 interface_regalloc(m, cd, rd);
81 allocate_scratch_registers(m, rd);
82 local_regalloc(m, cd, rd);
86 /* function interface_regalloc *************************************************
88 allocates registers for all interface variables
90 *******************************************************************************/
92 static void interface_regalloc(methodinfo *m, codegendata *cd, registerdata *rd)
95 int intalloc, fltalloc; /* Remember allocated Register/Memory offset */
96 /* in case a more vars are packed into this interface slot */
98 int intregsneeded = 0;
100 /* allocate LNG and DBL Types first to ensure 2 memory slots or registers */
101 /* on HAS_4BYTE_STACKSLOT architectures */
102 int typeloop[] = { TYPE_LNG, TYPE_DBL, TYPE_INT, TYPE_FLT, TYPE_ADR };
104 /* rd->memuse was already set in stack.c to allocate stack space for */
105 /* passing arguments to called methods */
106 #if defined(__I386__)
107 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
108 /* reserve 0(%esp) for Monitorenter/exit Argument on i386 */
114 if (m->isleafmethod) {
115 /* Reserve argument register, which will be used for Locals acting */
117 if (rd->argintreguse < m->parseddesc->argintreguse)
118 rd->argintreguse = m->parseddesc->argintreguse;
119 if (rd->argfltreguse < m->parseddesc->argfltreguse)
120 rd->argfltreguse = m->parseddesc->argfltreguse;
121 #ifdef HAS_ADDRESS_REGISTER_FILE
122 if (rd->argadrreguse < m->parseddesc->argadrreguse)
123 rd->argadrreguse = m->parseddesc->argadrreguse;
128 for (s = 0; s < cd->maxstack; s++) {
129 intalloc = -1; fltalloc = -1;
130 saved = (rd->interfaces[s][TYPE_INT].flags |
131 rd->interfaces[s][TYPE_LNG].flags |
132 rd->interfaces[s][TYPE_FLT].flags |
133 rd->interfaces[s][TYPE_DBL].flags |
134 rd->interfaces[s][TYPE_ADR].flags) & SAVEDVAR;
136 for (tt = 0; tt <= 4; tt++) {
138 v = &rd->interfaces[s][t];
140 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
141 intregsneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
143 #if defined(HAS_4BYTE_STACKSLOT)
144 memneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
147 #if defined(HAS_ADDRESS_REGISTER_FILE)
148 if (IS_ADR_TYPE(t)) {
150 &&(rd->argadrreguse < ADR_ARG_CNT)) {
151 v->regoff = rd->argadrregs[rd->argadrreguse++];
152 } else if (rd->tmpadrreguse > 0) {
153 v->regoff = rd->tmpadrregs[--rd->tmpadrreguse];
154 } else if (rd->savadrreguse > 0) {
155 v->regoff = rd->savadrregs[--rd->savadrreguse];
157 v->flags |= INMEMORY;
158 v->regoff = rd->memuse++;
160 } else /* !IS_ADR_TYPE */
161 #endif /* defined(HAS_ADDRESS_REGISTER_FILE) */
163 if (IS_FLT_DBL_TYPE(t)) {
165 /* Reuse memory slot(s)/register(s) for shared interface slots */
166 v->flags |= rd->interfaces[s][fltalloc].flags
168 v->regoff = rd->interfaces[s][fltalloc].regoff;
169 } else if (rd->argfltreguse < FLT_ARG_CNT) {
170 v->regoff = rd->argfltregs[rd->argfltreguse++];
171 } else if (rd->tmpfltreguse > 0) {
172 v->regoff = rd->tmpfltregs[--rd->tmpfltreguse];
173 } else if (rd->savfltreguse > 0) {
174 v->regoff = rd->savfltregs[--rd->savfltreguse];
176 v->flags |= INMEMORY;
177 #if defined(ALIGN_DOUBLES_IN_MEMORY)
178 /* Align doubles in Memory */
179 if ( (memneeded) && (rd->memuse & 1))
182 v->regoff = rd->memuse;
183 rd->memuse += memneeded + 1;
186 } else { /* !IS_FLT_DBL_TYPE(t) */
187 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
189 * for i386 put all longs in memory
191 if (IS_2_WORD_TYPE(t)) {
192 v->flags |= INMEMORY;
193 #if defined(ALIGN_LONGS_IN_MEMORY)
194 /* Align longs in Memory */
198 v->regoff = rd->memuse;
199 rd->memuse += memneeded + 1;
201 #endif /* defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE...GISTERS) */
203 /* Reuse memory slot(s)/register(s) for shared interface slots */
205 rd->interfaces[s][intalloc].flags
207 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
208 if (!(v->flags & INMEMORY)
209 && IS_2_WORD_TYPE(intalloc))
210 v->regoff = GET_LOW_REG(
211 rd->interfaces[s][intalloc].regoff);
215 rd->interfaces[s][intalloc].regoff;
217 if (rd->argintreguse + intregsneeded
219 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
222 rd->argintregs[rd->argintreguse],
223 rd->argintregs[rd->argintreguse + 1]);
227 rd->argintregs[rd->argintreguse];
228 rd->argintreguse += intregsneeded + 1;
230 else if (rd->tmpintreguse > intregsneeded) {
231 rd->tmpintreguse -= intregsneeded + 1;
232 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
235 rd->tmpintregs[rd->tmpintreguse],
236 rd->tmpintregs[rd->tmpintreguse + 1]);
240 rd->tmpintregs[rd->tmpintreguse];
242 else if (rd->savintreguse > intregsneeded) {
243 rd->savintreguse -= intregsneeded + 1;
245 rd->savintregs[rd->savintreguse];
246 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
249 rd->savintregs[rd->savintreguse],
250 rd->savintregs[rd->savintreguse + 1]);
254 rd->savintregs[rd->savintreguse];
257 v->flags |= INMEMORY;
258 #if defined(ALIGN_LONGS_IN_MEMORY)
259 /* Align longs in Memory */
260 if ( (memneeded) && (rd->memuse & 1))
263 v->regoff = rd->memuse;
264 rd->memuse += memneeded + 1;
268 } /* if (IS_FLT_DBL_TYPE(t)) */
270 } else { /* (saved) */
271 /* now the same like above, but without a chance to take a temporary register */
272 #ifdef HAS_ADDRESS_REGISTER_FILE
273 if (IS_ADR_TYPE(t)) {
274 if (rd->savadrreguse > 0) {
275 v->regoff = rd->savadrregs[--rd->savadrreguse];
278 v->flags |= INMEMORY;
279 v->regoff = rd->memuse++;
284 if (IS_FLT_DBL_TYPE(t)) {
286 v->flags |= rd->interfaces[s][fltalloc].flags
288 v->regoff = rd->interfaces[s][fltalloc].regoff;
290 if (rd->savfltreguse > 0) {
291 v->regoff = rd->savfltregs[--rd->savfltreguse];
294 v->flags |= INMEMORY;
295 #if defined(ALIGN_DOUBLES_IN_MEMORY)
296 /* Align doubles in Memory */
297 if ( (memneeded) && (rd->memuse & 1))
300 v->regoff = rd->memuse;
301 rd->memuse += memneeded + 1;
305 else { /* IS_INT_LNG */
306 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
308 * for i386 put all longs in memory
310 if (IS_2_WORD_TYPE(t)) {
311 v->flags |= INMEMORY;
312 #if defined(ALIGN_LONGS_IN_MEMORY)
313 /* Align longs in Memory */
317 v->regoff = rd->memuse;
318 rd->memuse += memneeded + 1;
324 rd->interfaces[s][intalloc].flags & INMEMORY;
325 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
326 if (!(v->flags & INMEMORY)
327 && IS_2_WORD_TYPE(intalloc))
330 rd->interfaces[s][intalloc].regoff);
334 rd->interfaces[s][intalloc].regoff;
336 if (rd->savintreguse > intregsneeded) {
337 rd->savintreguse -= intregsneeded + 1;
338 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
340 v->regoff = PACK_REGS(
341 rd->savintregs[rd->savintreguse],
342 rd->savintregs[rd->savintreguse + 1]);
346 rd->savintregs[rd->savintreguse];
348 v->flags |= INMEMORY;
349 #if defined(ALIGN_LONGS_IN_MEMORY)
350 /* Align longs in Memory */
351 if ( (memneeded) && (rd->memuse & 1))
354 v->regoff = rd->memuse;
355 rd->memuse += memneeded + 1;
360 } /* if (IS_FLT_DBL_TYPE(t) else */
361 } /* if (IS_ADR_TYPE(t)) else */
362 } /* if (saved) else */
363 } /* if (type >= 0) */
370 /* function local_regalloc *****************************************************
372 allocates registers for all local variables
374 *******************************************************************************/
376 static void local_regalloc(methodinfo *m, codegendata *cd, registerdata *rd)
379 int intalloc, fltalloc;
381 int intregsneeded = 0;
383 int typeloop[] = { TYPE_LNG, TYPE_DBL, TYPE_INT, TYPE_FLT, TYPE_ADR };
384 int fargcnt, iargcnt;
385 #ifdef HAS_ADDRESS_REGISTER_FILE
389 if (m->isleafmethod) {
390 methoddesc *md = m->parseddesc;
392 iargcnt = rd->argintreguse;
393 fargcnt = rd->argfltreguse;
394 #ifdef HAS_ADDRESS_REGISTER_FILE
395 aargcnt = rd->argadrreguse;
397 for (p = 0, s = 0; s < cd->maxlocals; s++, p++) {
398 intalloc = -1; fltalloc = -1;
399 for (tt = 0; tt <= 4; tt++) {
401 v = &rd->locals[s][t];
406 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
407 intregsneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
409 #if defined(HAS_4BYTE_STACKSLOT)
410 memneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
416 * #ifdef HAS_ADDRESS_REGISTER_FILE
423 * } else { / int & lng
427 * must not to be changed!
430 #ifdef HAS_ADDRESS_REGISTER_FILE
431 if (IS_ADR_TYPE(t)) {
432 if ((p < md->paramcount) && !md->params[p].inmemory) {
434 v->regoff = rd->argadrregs[md->params[p].regoff];
436 else if (rd->tmpadrreguse > 0) {
438 v->regoff = rd->tmpadrregs[--rd->tmpadrreguse];
440 /* use unused argument registers as local registers */
441 else if ((p >= md->paramcount) &&
442 (aargcnt < ADR_ARG_CNT)) {
444 v->regoff = rd->argadrregs[aargcnt++];
446 else if (rd->savadrreguse > 0) {
448 v->regoff = rd->savadrregs[--rd->savadrreguse];
451 v->flags |= INMEMORY;
452 v->regoff = rd->memuse++;
456 if (IS_FLT_DBL_TYPE(t)) {
458 v->flags = rd->locals[s][fltalloc].flags;
459 v->regoff = rd->locals[s][fltalloc].regoff;
461 #if !defined(SUPPORT_PASS_FLOATARGS_IN_INTREGS)
462 /* We can only use float arguments as local variables,
463 * if we do not pass them in integer registers. */
464 else if ((p < md->paramcount) &&
465 !md->params[p].inmemory) {
467 v->regoff = rd->argfltregs[md->params[p].regoff];
470 else if (rd->tmpfltreguse > 0) {
472 v->regoff = rd->tmpfltregs[--rd->tmpfltreguse];
474 /* use unused argument registers as local registers */
475 else if ((p >= md->paramcount) &&
476 (fargcnt < FLT_ARG_CNT)) {
478 v->regoff = rd->argfltregs[fargcnt];
481 else if (rd->savfltreguse > 0) {
483 v->regoff = rd->savfltregs[--rd->savfltreguse];
487 #if defined(ALIGN_DOUBLES_IN_MEMORY)
488 /* Align doubles in Memory */
489 if ( (memneeded) && (rd->memuse & 1))
492 v->regoff = rd->memuse;
493 rd->memuse += memneeded + 1;
498 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
500 * for i386 put all longs in memory
502 if (IS_2_WORD_TYPE(t)) {
504 #if defined(ALIGN_LONGS_IN_MEMORY)
505 /* Align longs in Memory */
509 v->regoff = rd->memuse;
510 rd->memuse += memneeded + 1;
515 v->flags = rd->locals[s][intalloc].flags;
516 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
517 if (!(v->flags & INMEMORY)
518 && IS_2_WORD_TYPE(intalloc))
519 v->regoff = GET_LOW_REG(
520 rd->locals[s][intalloc].regoff);
523 v->regoff = rd->locals[s][intalloc].regoff;
525 else if ((p < md->paramcount) &&
526 !md->params[p].inmemory) {
528 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
529 if (IS_2_WORD_TYPE(t))
530 v->regoff = PACK_REGS(
531 rd->argintregs[GET_LOW_REG(md->params[p].regoff)],
532 rd->argintregs[GET_HIGH_REG(md->params[p].regoff)]);
536 rd->argintregs[md->params[p].regoff];
538 else if (rd->tmpintreguse > intregsneeded) {
539 rd->tmpintreguse -= intregsneeded + 1;
541 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
543 v->regoff = PACK_REGS(
544 rd->tmpintregs[rd->tmpintreguse],
545 rd->tmpintregs[rd->tmpintreguse + 1]);
549 rd->tmpintregs[rd->tmpintreguse];
552 * use unused argument registers as local registers
554 else if ((p >= m->parseddesc->paramcount) &&
555 (iargcnt + intregsneeded < INT_ARG_CNT)) {
557 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
560 rd->argintregs[iargcnt],
561 rd->argintregs[iargcnt + 1]);
564 v->regoff = rd->argintregs[iargcnt];
565 iargcnt += intregsneeded + 1;
567 else if (rd->savintreguse > intregsneeded) {
568 rd->savintreguse -= intregsneeded + 1;
570 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
572 v->regoff = PACK_REGS(
573 rd->savintregs[rd->savintreguse],
574 rd->savintregs[rd->savintreguse + 1]);
577 v->regoff =rd->savintregs[rd->savintreguse];
581 #if defined(ALIGN_LONGS_IN_MEMORY)
582 /* Align longs in Memory */
583 if ( (memneeded) && (rd->memuse & 1))
586 v->regoff = rd->memuse;
587 rd->memuse += memneeded + 1;
592 #ifdef HAS_ADDRESS_REGISTER_FILE
595 } /* for (tt=0;...) */
597 /* If the current parameter is a 2-word type, the next local slot */
600 if (p < md->paramcount)
601 if (IS_2_WORD_TYPE(md->paramtypes[p].type))
607 for (s = 0; s < cd->maxlocals; s++) {
608 intalloc = -1; fltalloc = -1;
609 for (tt=0; tt<=4; tt++) {
611 v = &rd->locals[s][t];
614 #ifdef SUPPORT_COMBINE_INTEGER_REGISTERS
615 intregsneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
617 #if defined(HAS_4BYTE_STACKSLOT)
618 memneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
620 #ifdef HAS_ADDRESS_REGISTER_FILE
621 if ( IS_ADR_TYPE(t) ) {
622 if (rd->savadrreguse > 0) {
624 v->regoff = rd->savadrregs[--rd->savadrreguse];
628 v->regoff = rd->memuse++;
632 if (IS_FLT_DBL_TYPE(t)) {
634 v->flags = rd->locals[s][fltalloc].flags;
635 v->regoff = rd->locals[s][fltalloc].regoff;
637 else if (rd->savfltreguse > 0) {
639 v->regoff = rd->savfltregs[--rd->savfltreguse];
643 #if defined(ALIGN_DOUBLES_IN_MEMORY)
644 /* Align doubles in Memory */
645 if ( (memneeded) && (rd->memuse & 1))
648 v->regoff = rd->memuse;
649 rd->memuse += memneeded + 1;
654 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
656 * for i386 put all longs in memory
658 if (IS_2_WORD_TYPE(t)) {
660 #if defined(ALIGN_LONGS_IN_MEMORY)
661 /* Align longs in Memory */
665 v->regoff = rd->memuse;
666 rd->memuse += memneeded + 1;
670 v->flags = rd->locals[s][intalloc].flags;
671 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
672 if (!(v->flags & INMEMORY)
673 && IS_2_WORD_TYPE(intalloc))
674 v->regoff = GET_LOW_REG(
675 rd->locals[s][intalloc].regoff);
678 v->regoff = rd->locals[s][intalloc].regoff;
680 else if (rd->savintreguse > intregsneeded) {
681 rd->savintreguse -= intregsneeded+1;
683 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
685 v->regoff = PACK_REGS(
686 rd->savintregs[rd->savintreguse],
687 rd->savintregs[rd->savintreguse + 1]);
690 v->regoff =rd->savintregs[rd->savintreguse];
694 #if defined(ALIGN_LONGS_IN_MEMORY)
695 /* Align longs in Memory */
696 if ( (memneeded) && (rd->memuse & 1))
699 v->regoff = rd->memuse;
700 rd->memuse += memneeded + 1;
702 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
707 #ifdef HAS_ADDRESS_REGISTER_FILE
716 static void reg_init_temp(methodinfo *m, registerdata *rd)
719 #if defined(HAS_4BYTE_STACKSLOT)
720 rd->freememtop_2 = 0;
723 rd->freetmpinttop = 0;
724 rd->freesavinttop = 0;
725 rd->freetmpflttop = 0;
726 rd->freesavflttop = 0;
727 #ifdef HAS_ADDRESS_REGISTER_FILE
728 rd->freetmpadrtop = 0;
729 rd->freesavadrtop = 0;
732 rd->freearginttop = 0;
733 rd->freeargflttop = 0;
734 #ifdef HAS_ADDRESS_REGISTER_FILE
735 rd->freeargadrtop = 0;
740 #define reg_new_temp(rd,s) if (s->varkind == TEMPVAR) reg_new_temp_func(rd, s)
742 static void reg_new_temp_func(registerdata *rd, stackptr s)
748 /* Try to allocate a saved register if there is no temporary one */
749 /* available. This is what happens during the second run. */
750 tryagain = (s->flags & SAVEDVAR) ? 1 : 2;
752 #ifdef SUPPORT_COMBINE_INTEGER_REGISTERS
753 intregsneeded = (IS_2_WORD_TYPE(s->type)) ? 1 : 0;
757 #if defined(HAS_4BYTE_STACKSLOT)
758 memneeded = (IS_2_WORD_TYPE(s->type)) ? 1 : 0;
763 for(; tryagain; --tryagain) {
765 if (!(s->flags & SAVEDVAR))
766 s->flags |= SAVEDTMP;
767 #ifdef HAS_ADDRESS_REGISTER_FILE
768 if (IS_ADR_TYPE(s->type)) {
769 if (rd->freesavadrtop > 0) {
770 s->regoff = rd->freesavadrregs[--rd->freesavadrtop];
772 } else if (rd->savadrreguse > 0) {
773 s->regoff = rd->savadrregs[--rd->savadrreguse];
779 if (IS_FLT_DBL_TYPE(s->type)) {
780 if (rd->freesavflttop > 0) {
781 s->regoff = rd->freesavfltregs[--rd->freesavflttop];
783 } else if (rd->savfltreguse > 0) {
784 s->regoff = rd->savfltregs[--rd->savfltreguse];
788 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
790 * for i386 put all longs in memory
792 if (!IS_2_WORD_TYPE(s->type))
795 if (rd->freesavinttop > intregsneeded) {
796 rd->freesavinttop -= intregsneeded + 1;
797 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
799 s->regoff = PACK_REGS(
800 rd->freesavintregs[rd->freesavinttop],
801 rd->freesavintregs[rd->freesavinttop + 1]);
805 rd->freesavintregs[rd->freesavinttop];
807 } else if (rd->savintreguse > intregsneeded) {
808 rd->savintreguse -= intregsneeded + 1;
809 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
811 s->regoff = PACK_REGS(
812 rd->savintregs[rd->savintreguse],
813 rd->savintregs[rd->savintreguse + 1]);
816 s->regoff = rd->savintregs[rd->savintreguse];
822 } else { /* tryagain == 2 */
823 #ifdef HAS_ADDRESS_REGISTER_FILE
824 if (IS_ADR_TYPE(s->type)) {
825 if (rd->freetmpadrtop > 0) {
826 s->regoff = rd->freetmpadrregs[--rd->freetmpadrtop];
828 } else if (rd->tmpadrreguse > 0) {
829 s->regoff = rd->tmpadrregs[--rd->tmpadrreguse];
835 if (IS_FLT_DBL_TYPE(s->type)) {
836 if (rd->freeargflttop > 0) {
837 s->regoff = rd->freeargfltregs[--rd->freeargflttop];
840 } else if (rd->argfltreguse < FLT_ARG_CNT) {
841 s->regoff = rd->argfltregs[rd->argfltreguse++];
844 } else if (rd->freetmpflttop > 0) {
845 s->regoff = rd->freetmpfltregs[--rd->freetmpflttop];
847 } else if (rd->tmpfltreguse > 0) {
848 s->regoff = rd->tmpfltregs[--rd->tmpfltreguse];
853 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
855 * for i386 put all longs in memory
857 if (!IS_2_WORD_TYPE(s->type))
860 if (rd->freearginttop > intregsneeded) {
861 rd->freearginttop -= intregsneeded + 1;
863 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
865 s->regoff = PACK_REGS(
866 rd->freeargintregs[rd->freearginttop],
867 rd->freeargintregs[rd->freearginttop + 1]);
871 rd->freeargintregs[rd->freearginttop];
873 } else if (rd->argintreguse
874 < INT_ARG_CNT - intregsneeded) {
875 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
877 s->regoff = PACK_REGS(
878 rd->argintregs[rd->argintreguse],
879 rd->argintregs[rd->argintreguse + 1]);
882 s->regoff = rd->argintregs[rd->argintreguse];
884 rd->argintreguse += intregsneeded + 1;
886 } else if (rd->freetmpinttop > intregsneeded) {
887 rd->freetmpinttop -= intregsneeded + 1;
888 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
890 s->regoff = PACK_REGS(
891 rd->freetmpintregs[rd->freetmpinttop],
892 rd->freetmpintregs[rd->freetmpinttop + 1]);
895 s->regoff = rd->freetmpintregs[rd->freetmpinttop];
897 } else if (rd->tmpintreguse > intregsneeded) {
898 rd->tmpintreguse -= intregsneeded + 1;
899 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
901 s->regoff = PACK_REGS(
902 rd->tmpintregs[rd->tmpintreguse],
903 rd->tmpintregs[rd->tmpintreguse + 1]);
906 s->regoff = rd->tmpintregs[rd->tmpintreguse];
909 } /* if (!IS_2_WORD_TYPE(s->type)) */
910 } /* if (IS_FLT_DBL_TYPE(s->type)) */
911 } /* if (IS_ADR_TYPE(s->type)) */
912 } /* if (tryagain == 1) else */
913 } /* for(; tryagain; --tryagain) */
915 #if defined(HAS_4BYTE_STACKSLOT)
916 if ((memneeded == 1) && (rd->freememtop_2 > 0)) {
918 s->regoff = rd->freemem_2[rd->freememtop_2];
920 #endif /*defined(HAS_4BYTE_STACKSLOT) */
921 if ((memneeded == 0) && (rd->freememtop > 0)) {
923 s->regoff = rd->freemem[rd->freememtop];
925 #if defined(ALIGN_LONGS_IN_MEMORY) || defined(ALIGN_DOUBLES_IN_MEMORY)
926 /* align 2 Word Types */
927 if ((memneeded) && ((rd->memuse & 1) == 1)) {
928 /* Put patched memory slot on freemem */
929 rd->freemem[rd->freememtop++] = rd->memuse;
932 #endif /* defined(ALIGN_LONGS_IN_MEMORY) || defined(ALIGN_DOUBLES_IN_MEMORY) */
933 s->regoff = rd->memuse;
934 rd->memuse += memneeded + 1;
936 s->flags |= INMEMORY;
940 #define reg_free_temp(rd,s) if ((s->varkind == TEMPVAR) && (!(s->flags & STCOPY))) reg_free_temp_func(rd, s)
942 /* Do not free regs/memory locations used by Stackslots flagged STCOPY! There is still another Stackslot */
943 /* alive using this reg/memory location */
945 static void reg_free_temp_func(registerdata *rd, stackptr s)
950 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
951 intregsneeded = (IS_2_WORD_TYPE(s->type)) ? 1 : 0;
956 #if defined(HAS_4BYTE_STACKSLOT)
957 memneeded = (IS_2_WORD_TYPE(s->type)) ? 1 : 0;
962 if (s->flags & INMEMORY) {
963 #if defined(HAS_4BYTE_STACKSLOT)
965 rd->freemem_2[rd->freememtop_2] = s->regoff;
970 rd->freemem[rd->freememtop] = s->regoff;
974 #ifdef HAS_ADDRESS_REGISTER_FILE
975 } else if (IS_ADR_TYPE(s->type)) {
976 if (s->flags & (SAVEDVAR | SAVEDTMP)) {
977 s->flags &= ~SAVEDTMP;
978 rd->freesavadrregs[rd->freesavadrtop++] = s->regoff;
980 rd->freetmpadrregs[rd->freetmpadrtop++] = s->regoff;
982 } else if (IS_FLT_DBL_TYPE(s->type)) {
983 if (s->flags & (SAVEDVAR | SAVEDTMP)) {
984 s->flags &= ~SAVEDTMP;
985 rd->freesavfltregs[rd->freesavflttop++] = s->regoff;
986 } else if (s->flags & TMPARG) {
988 rd->freeargfltregs[rd->freeargflttop++] = s->regoff;
990 rd->freetmpfltregs[rd->freetmpflttop++] = s->regoff;
991 } else { /* IS_INT_LNG_TYPE */
992 if (s->flags & (SAVEDVAR | SAVEDTMP)) {
993 s->flags &= ~SAVEDTMP;
994 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
996 rd->freesavintregs[rd->freesavinttop] =
997 GET_LOW_REG(s->regoff);
998 rd->freesavintregs[rd->freesavinttop + 1] =
999 GET_HIGH_REG(s->regoff);
1002 rd->freesavintregs[rd->freesavinttop] = s->regoff;
1003 rd->freesavinttop += intregsneeded + 1;
1005 } else if (s->flags & TMPARG) {
1006 s->flags &= ~TMPARG;
1007 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
1008 if (intregsneeded) {
1009 rd->freeargintregs[rd->freearginttop] =
1010 GET_LOW_REG(s->regoff);
1011 rd->freeargintregs[rd->freearginttop + 1] =
1012 GET_HIGH_REG(s->regoff);
1015 rd->freeargintregs[rd->freearginttop] = s->regoff;
1016 rd->freearginttop += intregsneeded + 1;
1018 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
1019 if (intregsneeded) {
1020 rd->freetmpintregs[rd->freetmpinttop] =
1021 GET_LOW_REG(s->regoff);
1022 rd->freetmpintregs[rd->freetmpinttop + 1] =
1023 GET_HIGH_REG(s->regoff);
1026 rd->freetmpintregs[rd->freetmpinttop] = s->regoff;
1027 rd->freetmpinttop += intregsneeded + 1;
1032 static bool reg_alloc_dup(stackptr src, stackptr dst) {
1033 /* only copy TEMPVARS, do not mess with STACKVAR, */
1034 /* LOCALVAR, or ARGVAR */
1035 if ((src->varkind == TEMPVAR) && (dst->varkind == TEMPVAR)) {
1036 /* can not allocate a REG_TMP to a REG_SAV Slot */
1037 if (src->flags & INMEMORY) {
1038 dst->regoff = src->regoff;
1039 dst->flags |= INMEMORY;
1041 } else if ((src->flags & SAVEDVAR) == (dst->flags & SAVEDVAR)) {
1042 dst->regoff = src->regoff;
1043 dst->flags |= src->flags & SAVEDTMP;
1044 dst->flags |= src->flags & TMPARG;
1046 } else if ((dst->flags & SAVEDVAR) == 0) {
1047 /* can only use a REG_SAV as REG_TMP! */
1048 dst->regoff = src->regoff;
1049 dst->flags |= SAVEDTMP;
1053 /* no copy possible - allocate a new reg/memory location*/
1057 static void allocate_scratch_registers(methodinfo *m, registerdata *rd)
1067 builtintable_entry *bte;
1070 /* initialize temp registers */
1071 reg_init_temp(m, rd);
1073 bptr = m->basicblocks;
1075 while (bptr != NULL) {
1076 if (bptr->flags >= BBREACHED) {
1077 dst = bptr->instack;
1080 iptr = bptr->iinstr;
1083 while (--len >= 0) {
1093 case ICMD_ELSE_ICONST:
1094 case ICMD_CHECKNULL:
1100 case ICMD_PUTSTATICCONST:
1101 case ICMD_INLINE_START:
1102 case ICMD_INLINE_END:
1103 case ICMD_INLINE_GOTO:
1106 /* pop 0 push 1 const */
1114 /* pop 0 push 1 load */
1121 reg_new_temp(rd, dst);
1135 reg_free_temp(rd, src);
1136 reg_free_temp(rd, src->prev);
1137 reg_new_temp(rd, dst);
1151 reg_free_temp(rd, src);
1152 reg_free_temp(rd, src->prev);
1153 reg_free_temp(rd, src->prev->prev);
1156 /* pop 1 push 0 store */
1176 case ICMD_PUTSTATIC:
1177 case ICMD_PUTFIELDCONST:
1179 /* pop 1 push 0 branch */
1182 case ICMD_IFNONNULL:
1198 /* pop 1 push 0 table branch */
1200 case ICMD_TABLESWITCH:
1201 case ICMD_LOOKUPSWITCH:
1203 case ICMD_MONITORENTER:
1204 case ICMD_MONITOREXIT:
1205 reg_free_temp(rd, src);
1208 /* pop 2 push 0 branch */
1210 case ICMD_IF_ICMPEQ:
1211 case ICMD_IF_ICMPNE:
1212 case ICMD_IF_ICMPLT:
1213 case ICMD_IF_ICMPGE:
1214 case ICMD_IF_ICMPGT:
1215 case ICMD_IF_ICMPLE:
1217 case ICMD_IF_LCMPEQ:
1218 case ICMD_IF_LCMPNE:
1219 case ICMD_IF_LCMPLT:
1220 case ICMD_IF_LCMPGE:
1221 case ICMD_IF_LCMPGT:
1222 case ICMD_IF_LCMPLE:
1224 case ICMD_IF_ACMPEQ:
1225 case ICMD_IF_ACMPNE:
1233 case ICMD_IASTORECONST:
1234 case ICMD_LASTORECONST:
1235 case ICMD_AASTORECONST:
1236 case ICMD_BASTORECONST:
1237 case ICMD_CASTORECONST:
1238 case ICMD_SASTORECONST:
1239 reg_free_temp(rd, src);
1240 reg_free_temp(rd, src->prev);
1243 /* pop 0 push 1 dup */
1246 /* src === dst->prev (identical Stackslot Element) */
1247 /* src --> dst (copied value, take same reg/mem) */
1249 if (!reg_alloc_dup(src, dst)) {
1250 reg_new_temp(rd, dst);
1252 dst->flags |= STCOPY;
1256 /* pop 0 push 2 dup */
1259 /* src->prev === dst->prev->prev->prev (identical Stackslot Element) */
1260 /* src === dst->prev->prev (identical Stackslot Element) */
1261 /* src->prev --> dst->prev (copied value, take same reg/mem) */
1262 /* src --> dst (copied value, take same reg/mem) */
1264 if (!reg_alloc_dup(src->prev, dst->prev)) {
1265 reg_new_temp(rd, dst->prev);
1267 dst->prev->flags |= STCOPY;
1269 if (!reg_alloc_dup(src, dst)) {
1270 reg_new_temp(rd, dst);
1272 dst->flags |= STCOPY;
1276 /* pop 2 push 3 dup */
1279 /* src->prev --> dst->prev (copied value, take same reg/mem) */
1280 /* src --> dst (copied value, take same reg/mem) */
1281 /* src --> dst->prev->prev (copied value, take same reg/mem) */
1285 if (!(ret = reg_alloc_dup(src, dst->prev->prev))) {
1286 reg_new_temp(rd, dst->prev->prev);
1288 if (!(ret1 = reg_alloc_dup(src, dst))) {
1289 reg_new_temp(rd, dst);
1291 if (!(ret || ret1)) {
1292 /* no reallocation was possible -> free src */
1293 reg_free_temp(rd, src);
1296 dst->flags |= STCOPY;
1298 if (!reg_alloc_dup(src->prev, dst->prev)) {
1299 reg_free_temp(rd, src->prev);
1300 reg_new_temp(rd, dst->prev);
1305 /* pop 3 push 4 dup */
1308 /* src->prev->prev --> dst->prev->prev */
1309 /* src->prev --> dst->prev */
1311 /* src --> dst->prev->prev->prev */
1315 if (!(ret = reg_alloc_dup(src, dst->prev->prev->prev))) {
1316 reg_new_temp(rd, dst->prev->prev->prev);
1318 if (!(ret1 = reg_alloc_dup(src, dst))) {
1319 reg_new_temp(rd, dst);
1321 if (!(ret || ret1)) {
1322 /* no reallocation was possible -> free src */
1323 reg_free_temp(rd, src);
1326 dst->flags |= STCOPY;
1328 if (!reg_alloc_dup(src->prev, dst->prev)) {
1329 reg_free_temp(rd, src->prev);
1330 reg_new_temp(rd, dst->prev);
1332 if (!reg_alloc_dup(src->prev->prev, dst->prev->prev)) {
1333 reg_free_temp(rd, src->prev->prev);
1334 reg_new_temp(rd, dst->prev->prev);
1339 /* pop 3 push 5 dup */
1342 /* src->prev->prev --> dst->prev->prev */
1343 /* src->prev --> dst->prev */
1345 /* src->prev --> dst->prev->prev->prev->prev */
1346 /* src --> dst->prev->prev->prev */
1350 if (!(ret = reg_alloc_dup(src, dst->prev->prev->prev))) {
1351 reg_new_temp(rd, dst->prev->prev->prev);
1353 if (!(ret1 = reg_alloc_dup(src, dst))) {
1354 reg_new_temp(rd, dst);
1356 if (!(ret || ret1)) {
1357 /* no reallocation was possible -> free src */
1358 reg_free_temp(rd, src);
1361 dst->flags |= STCOPY;
1364 if (!(ret = reg_alloc_dup(src->prev, dst->prev->prev->prev->prev))) {
1365 reg_new_temp(rd, dst->prev->prev->prev->prev);
1367 if (!(ret1 = reg_alloc_dup(src->prev, dst->prev))) {
1368 reg_new_temp(rd, dst->prev);
1370 if (!(ret || ret1)) {
1371 /* no reallocation was possible -> free src->prev */
1372 reg_free_temp(rd, src->prev);
1375 dst->prev->flags |= STCOPY;
1378 if (!reg_alloc_dup(src->prev->prev, dst->prev->prev)) {
1379 reg_free_temp(rd, src->prev->prev);
1380 reg_new_temp(rd, dst->prev->prev);
1385 /* pop 4 push 6 dup */
1388 /* src->prev->prev->prev --> dst->prev->prev->prev */
1389 /* src->prev->prev --> dst->prev->prev */
1390 /* src->prev --> dst->prev */
1392 /* src->prev --> dst->prev->prev->prev->prev->prev */
1393 /* src --> dst->prev->prev->prev->prev */
1397 if (!(ret = reg_alloc_dup(src, dst->prev->prev->prev->prev))) {
1398 reg_new_temp(rd, dst->prev->prev->prev->prev);
1400 if (!(ret1 = reg_alloc_dup(src, dst))) {
1401 reg_new_temp(rd, dst);
1403 if (!(ret || ret1)) {
1404 /* no reallocation was possible -> free src */
1405 reg_free_temp(rd, src);
1408 dst->flags |= STCOPY;
1411 if (!(ret = reg_alloc_dup(src->prev, dst->prev->prev->prev->prev->prev))) {
1412 reg_new_temp(rd, dst->prev->prev->prev->prev->prev);
1414 if (!(ret1 = reg_alloc_dup(src->prev, dst->prev))) {
1415 reg_new_temp(rd, dst->prev);
1417 if (!(ret || ret1)) {
1418 /* no reallocation was possible -> free src->prev */
1419 reg_free_temp(rd, src->prev);
1422 dst->prev->flags |= STCOPY;
1425 if (!reg_alloc_dup(src->prev->prev, dst->prev->prev)) {
1426 reg_free_temp(rd, src->prev->prev);
1427 reg_new_temp(rd, dst->prev->prev);
1429 if (!reg_alloc_dup(src->prev->prev->prev, dst->prev->prev->prev)) {
1430 reg_free_temp(rd, src->prev->prev->prev);
1431 reg_new_temp(rd, dst->prev->prev->prev);
1436 /* pop 2 push 2 swap */
1439 /* src --> dst->prev (copy) */
1440 /* src->prev --> dst (copy) */
1442 if (!reg_alloc_dup(src, dst->prev)) {
1443 reg_free_temp(rd, src);
1444 reg_new_temp(rd, dst->prev);
1446 if (!reg_alloc_dup(src->prev, dst->prev)) {
1447 reg_free_temp(rd, src->prev);
1448 reg_new_temp(rd, dst);
1498 reg_free_temp(rd, src);
1499 reg_free_temp(rd, src->prev);
1500 reg_new_temp(rd, dst);
1505 case ICMD_IADDCONST:
1506 case ICMD_ISUBCONST:
1507 case ICMD_IMULCONST:
1511 case ICMD_IANDCONST:
1513 case ICMD_IXORCONST:
1514 case ICMD_ISHLCONST:
1515 case ICMD_ISHRCONST:
1516 case ICMD_IUSHRCONST:
1518 case ICMD_LADDCONST:
1519 case ICMD_LSUBCONST:
1520 case ICMD_LMULCONST:
1524 case ICMD_LANDCONST:
1526 case ICMD_LXORCONST:
1527 case ICMD_LSHLCONST:
1528 case ICMD_LSHRCONST:
1529 case ICMD_LUSHRCONST:
1531 case ICMD_IFEQ_ICONST:
1532 case ICMD_IFNE_ICONST:
1533 case ICMD_IFLT_ICONST:
1534 case ICMD_IFGE_ICONST:
1535 case ICMD_IFGT_ICONST:
1536 case ICMD_IFLE_ICONST:
1541 case ICMD_INT2SHORT:
1559 case ICMD_CHECKCAST:
1561 case ICMD_ARRAYLENGTH:
1562 case ICMD_INSTANCEOF:
1565 case ICMD_ANEWARRAY:
1568 reg_free_temp(rd, src);
1569 reg_new_temp(rd, dst);
1574 case ICMD_GETSTATIC:
1577 reg_new_temp(rd, dst);
1580 /* pop many push any */
1582 case ICMD_INVOKESTATIC:
1583 case ICMD_INVOKESPECIAL:
1584 case ICMD_INVOKEVIRTUAL:
1585 case ICMD_INVOKEINTERFACE:
1589 md = lm->parseddesc;
1591 unresolved_method *um = iptr->target;
1592 md = um->methodref->parseddesc.md;
1596 reg_free_temp(rd, src);
1599 if (md->returntype.type != TYPE_VOID)
1600 reg_new_temp(rd, dst);
1608 reg_free_temp(rd, src);
1611 if (md->returntype.type != TYPE_VOID)
1612 reg_new_temp(rd, dst);
1615 case ICMD_MULTIANEWARRAY:
1618 reg_free_temp(rd, src);
1621 reg_new_temp(rd, dst);
1626 new_internalerror("Unknown ICMD %d during register allocation",
1631 } /* while instructions */
1634 } /* while blocks */
1638 #if defined(ENABLE_STATISTICS)
1639 void reg_make_statistics( methodinfo *m, codegendata *cd, registerdata *rd) {
1642 stackptr src, src_old;
1646 int size_interface; /* == maximum size of in/out stack at basic block boundaries */
1653 /* count how many local variables are held in memory or register */
1654 for(i=0; i < cd->maxlocals; i++)
1655 for (type=0; type <=4; type++)
1656 if (rd->locals[i][type].type != -1) { /* valid local */
1657 if (rd->locals[i][type].flags & INMEMORY) {
1658 count_locals_spilled++;
1662 count_locals_register++;
1664 /* count how many stack slots are held in memory or register */
1666 bptr = m->basicblocks;
1667 while (bptr != NULL) {
1668 if (bptr->flags >= BBREACHED) {
1670 #if defined(ENABLE_LSRA)
1673 /* check for memory moves from interface to BB instack */
1674 dst = bptr->instack;
1675 len = bptr->indepth;
1677 if (len > size_interface) size_interface = len;
1679 while (dst != NULL) {
1681 if (dst->varkind != STACKVAR) {
1682 if ( (dst->flags & INMEMORY) ||
1683 (rd->interfaces[len][dst->type].flags & INMEMORY) ||
1684 ( (dst->flags & INMEMORY) &&
1685 (rd->interfaces[len][dst->type].flags & INMEMORY) &&
1686 (dst->regoff != rd->interfaces[len][dst->type].regoff) ))
1688 /* one in memory or both inmemory at different offsets */
1689 count_mem_move_bb++;
1697 /* check for memory moves from BB outstack to interface */
1698 dst = bptr->outstack;
1699 len = bptr->outdepth;
1700 if (len > size_interface) size_interface = len;
1704 if (dst->varkind != STACKVAR) {
1705 if ( (dst->flags & INMEMORY) || \
1706 (rd->interfaces[len][dst->type].flags & INMEMORY) || \
1707 ( (dst->flags & INMEMORY) && \
1708 (rd->interfaces[len][dst->type].flags & INMEMORY) && \
1709 (dst->regoff != rd->interfaces[len][dst->type].regoff) ))
1711 /* one in memory or both inmemory at different offsets */
1712 count_mem_move_bb++;
1719 #if defined(ENABLE_LSRA)
1724 dst = bptr->instack;
1725 iptr = bptr->iinstr;
1729 while (--len >= 0) {
1733 if ((src!= NULL) && (src != src_old)) { /* new stackslot */
1734 switch (src->varkind) {
1737 if (!(src->flags & INMEMORY))
1738 count_ss_register++;
1744 /* case LOCALVAR: */
1745 /* if (!(rd->locals[src->varnum][src->type].flags & INMEMORY)) */
1746 /* count_ss_register++; */
1748 /* count_ss_spilled++; */
1751 if (!(src->flags & INMEMORY))
1752 count_argument_mem_ss++;
1754 count_argument_reg_ss++;
1758 /* if (IS_FLT_DBL_TYPE(src->type)) { */
1759 /* if (src->varnum < FLT_ARG_CNT) { */
1760 /* count_ss_register++; */
1764 /* #if defined(__POWERPC__) */
1765 /* if (src->varnum < INT_ARG_CNT - (IS_2_WORD_TYPE(src->type) != 0)) { */
1767 /* if (src->varnum < INT_ARG_CNT) { */
1769 /* count_ss_register++; */
1773 /* count_ss_spilled++; */
1780 } /* while instructions */
1783 } /* while blocks */
1784 count_interface_size += size_interface; /* accummulate the size of the interface (between bb boundaries) */
1785 if (in_register) count_method_in_register++;
1787 #endif /* defined(ENABLE_STATISTICS) */
1791 * These are local overrides for various environment variables in Emacs.
1792 * Please do not remove this and leave it at the end of the file, where
1793 * Emacs will automagically detect them.
1794 * ---------------------------------------------------------------------
1797 * indent-tabs-mode: t
1801 * vim:noexpandtab:sw=4:ts=4: