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 5427 2006-09-08 16:07:48Z edwin $
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"
59 /* function prototypes for this file ******************************************/
61 static void interface_regalloc(jitdata *jd);
62 static void local_regalloc(jitdata *jd);
63 static void new_allocate_scratch_registers(jitdata *jd);
64 static void allocate_scratch_registers(jitdata *jd);
67 /* regalloc ********************************************************************
69 Does a simple register allocation.
71 *******************************************************************************/
73 bool new_regalloc(jitdata *jd)
75 /* There is a problem with the use of unused float argument
76 registers in leafmethods for stackslots on c7 (2 * Dual Core
77 AMD Opteron(tm) Processor 270) - runtime for the jvm98 _mtrt
78 benchmark is heaviliy increased. This could be prevented by
79 setting rd->argfltreguse to FLT_ARG_CNT before calling
80 allocate_scratch_registers and setting it back to the original
81 value before calling local_regalloc. */
83 interface_regalloc(jd);
84 new_allocate_scratch_registers(jd);
92 /* interface_regalloc **********************************************************
94 Allocates registers for all interface variables.
96 *******************************************************************************/
98 static void interface_regalloc(jitdata *jd)
105 int intalloc, fltalloc; /* Remember allocated Register/Memory offset */
106 /* in case more vars are packed into this interface slot */
107 int intregsneeded = 0;
109 /* allocate LNG and DBL Types first to ensure 2 memory slots or registers */
110 /* on HAS_4BYTE_STACKSLOT architectures */
111 int typeloop[] = { TYPE_LNG, TYPE_DBL, TYPE_INT, TYPE_FLT, TYPE_ADR };
114 /* get required compiler data */
120 /* rd->memuse was already set in stack.c to allocate stack space
121 for passing arguments to called methods. */
123 #if defined(__I386__)
124 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
125 /* reserve 0(%esp) for Monitorenter/exit Argument on i386 */
131 if (jd->isleafmethod) {
132 /* Reserve argument register, which will be used for Locals acting */
134 if (rd->argintreguse < m->parseddesc->argintreguse)
135 rd->argintreguse = m->parseddesc->argintreguse;
136 if (rd->argfltreguse < m->parseddesc->argfltreguse)
137 rd->argfltreguse = m->parseddesc->argfltreguse;
138 #ifdef HAS_ADDRESS_REGISTER_FILE
139 if (rd->argadrreguse < m->parseddesc->argadrreguse)
140 rd->argadrreguse = m->parseddesc->argadrreguse;
145 for (s = 0; s < cd->maxstack; s++) {
146 intalloc = -1; fltalloc = -1;
150 for (tt = 0; tt <=4; tt++) {
151 if ((t = jd->interface_map[s * 5 + tt].flags) != UNUSED) {
152 saved |= t & SAVEDVAR;
156 for (tt = 0; tt <= 4; tt++) {
158 if (jd->interface_map[s * 5 + t].flags == UNUSED)
162 regoff = -1; /* XXX for debugging */
164 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
165 intregsneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
167 #if defined(HAS_4BYTE_STACKSLOT)
168 memneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
171 #if defined(HAS_ADDRESS_REGISTER_FILE)
172 if (IS_ADR_TYPE(t)) {
173 if (!jd->isleafmethod
174 &&(rd->argadrreguse < ADR_ARG_CNT)) {
175 regoff = rd->argadrregs[rd->argadrreguse++];
176 } else if (rd->tmpadrreguse > 0) {
177 regoff = rd->tmpadrregs[--rd->tmpadrreguse];
178 } else if (rd->savadrreguse > 0) {
179 regoff = rd->savadrregs[--rd->savadrreguse];
182 regoff = rd->memuse++;
184 } else /* !IS_ADR_TYPE */
185 #endif /* defined(HAS_ADDRESS_REGISTER_FILE) */
187 if (IS_FLT_DBL_TYPE(t)) {
189 /* Reuse memory slot(s)/register(s) for shared interface slots */
190 flags |= jd->interface_map[fltalloc].flags & INMEMORY;
191 regoff = jd->interface_map[fltalloc].regoff;
192 } else if (rd->argfltreguse < FLT_ARG_CNT) {
193 regoff = rd->argfltregs[rd->argfltreguse++];
194 } else if (rd->tmpfltreguse > 0) {
195 regoff = rd->tmpfltregs[--rd->tmpfltreguse];
196 } else if (rd->savfltreguse > 0) {
197 regoff = rd->savfltregs[--rd->savfltreguse];
200 #if defined(ALIGN_DOUBLES_IN_MEMORY)
201 /* Align doubles in Memory */
202 if ( (memneeded) && (rd->memuse & 1))
206 rd->memuse += memneeded + 1;
208 fltalloc = s * 5 + t;
209 } else { /* !IS_FLT_DBL_TYPE(t) */
210 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
212 * for i386 put all longs in memory
214 if (IS_2_WORD_TYPE(t)) {
216 #if defined(ALIGN_LONGS_IN_MEMORY)
217 /* Align longs in Memory */
222 rd->memuse += memneeded + 1;
224 #endif /* defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE...GISTERS) */
226 /* Reuse memory slot(s)/register(s) for shared interface slots */
227 flags |= jd->interface_map[intalloc].flags & INMEMORY;
228 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
229 if (!(flags & INMEMORY)
230 && IS_2_WORD_TYPE(intalloc % 5))
231 regoff = GET_LOW_REG(
232 jd->interface_map[intalloc].regoff);
236 jd->interface_map[intalloc].regoff;
238 if (rd->argintreguse + intregsneeded
240 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
243 rd->argintregs[rd->argintreguse],
244 rd->argintregs[rd->argintreguse + 1]);
248 rd->argintregs[rd->argintreguse];
249 rd->argintreguse += intregsneeded + 1;
251 else if (rd->tmpintreguse > intregsneeded) {
252 rd->tmpintreguse -= intregsneeded + 1;
253 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
256 rd->tmpintregs[rd->tmpintreguse],
257 rd->tmpintregs[rd->tmpintreguse + 1]);
261 rd->tmpintregs[rd->tmpintreguse];
263 else if (rd->savintreguse > intregsneeded) {
264 rd->savintreguse -= intregsneeded + 1;
266 rd->savintregs[rd->savintreguse];
267 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
270 rd->savintregs[rd->savintreguse],
271 rd->savintregs[rd->savintreguse + 1]);
275 rd->savintregs[rd->savintreguse];
279 #if defined(ALIGN_LONGS_IN_MEMORY)
280 /* Align longs in Memory */
281 if ( (memneeded) && (rd->memuse & 1))
285 rd->memuse += memneeded + 1;
288 intalloc = s * 5 + t;
289 } /* if (IS_FLT_DBL_TYPE(t)) */
291 } else { /* (saved) */
292 /* now the same like above, but without a chance to take a temporary register */
293 #ifdef HAS_ADDRESS_REGISTER_FILE
294 if (IS_ADR_TYPE(t)) {
295 if (rd->savadrreguse > 0) {
296 regoff = rd->savadrregs[--rd->savadrreguse];
300 regoff = rd->memuse++;
305 if (IS_FLT_DBL_TYPE(t)) {
307 flags |= jd->interface_map[fltalloc].flags & INMEMORY;
308 regoff = jd->interface_map[fltalloc].regoff;
310 if (rd->savfltreguse > 0) {
312 rd->savfltregs[--rd->savfltreguse];
316 #if defined(ALIGN_DOUBLES_IN_MEMORY)
317 /* Align doubles in Memory */
318 if ( (memneeded) && (rd->memuse & 1))
322 rd->memuse += memneeded + 1;
324 fltalloc = s * 5 + t;
326 else { /* IS_INT_LNG */
327 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
329 * for i386 put all longs in memory
331 if (IS_2_WORD_TYPE(t)) {
333 #if defined(ALIGN_LONGS_IN_MEMORY)
334 /* Align longs in Memory */
339 rd->memuse += memneeded + 1;
344 flags |= jd->interface_map[intalloc].flags & INMEMORY;
345 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
346 if (!(flags & INMEMORY)
347 && IS_2_WORD_TYPE(intalloc % 5))
350 jd->interface_map[intalloc].regoff);
354 jd->interface_map[intalloc].regoff;
356 if (rd->savintreguse > intregsneeded) {
357 rd->savintreguse -= intregsneeded + 1;
358 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
361 rd->savintregs[rd->savintreguse],
362 rd->savintregs[rd->savintreguse + 1]);
366 rd->savintregs[rd->savintreguse];
369 #if defined(ALIGN_LONGS_IN_MEMORY)
370 /* Align longs in Memory */
371 if ( (memneeded) && (rd->memuse & 1))
375 rd->memuse += memneeded + 1;
380 } /* if (IS_FLT_DBL_TYPE(t) else */
381 } /* if (IS_ADR_TYPE(t)) else */
382 } /* if (saved) else */
386 jd->interface_map[5*s + t].flags = flags | OUTVAR;
387 jd->interface_map[5*s + t].regoff = regoff;
394 /* local_regalloc **************************************************************
396 Allocates registers for all local variables.
398 *******************************************************************************/
400 static void local_regalloc(jitdata *jd)
407 int intalloc, fltalloc;
409 int intregsneeded = 0;
411 int typeloop[] = { TYPE_LNG, TYPE_DBL, TYPE_INT, TYPE_FLT, TYPE_ADR };
412 int fargcnt, iargcnt;
413 #ifdef HAS_ADDRESS_REGISTER_FILE
417 /* get required compiler data */
423 if (jd->isleafmethod) {
424 methoddesc *md = m->parseddesc;
426 iargcnt = rd->argintreguse;
427 fargcnt = rd->argfltreguse;
428 #ifdef HAS_ADDRESS_REGISTER_FILE
429 aargcnt = rd->argadrreguse;
431 for (p = 0, s = 0; s < cd->maxlocals; s++, p++) {
432 intalloc = -1; fltalloc = -1;
433 for (tt = 0; tt <= 4; tt++) {
435 lm = jd->local_map[s * 5 + t];
441 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
442 intregsneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
444 #if defined(HAS_4BYTE_STACKSLOT)
445 memneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
451 * #ifdef HAS_ADDRESS_REGISTER_FILE
458 * } else { / int & lng
462 * must not to be changed!
465 #ifdef HAS_ADDRESS_REGISTER_FILE
466 if (IS_ADR_TYPE(t)) {
467 if ((p < md->paramcount) && !md->params[p].inmemory) {
469 v->regoff = rd->argadrregs[md->params[p].regoff];
471 else if (rd->tmpadrreguse > 0) {
473 v->regoff = rd->tmpadrregs[--rd->tmpadrreguse];
475 /* use unused argument registers as local registers */
476 else if ((p >= md->paramcount) &&
477 (aargcnt < ADR_ARG_CNT)) {
479 v->regoff = rd->argadrregs[aargcnt++];
481 else if (rd->savadrreguse > 0) {
483 v->regoff = rd->savadrregs[--rd->savadrreguse];
486 v->flags |= INMEMORY;
487 v->regoff = rd->memuse++;
491 if (IS_FLT_DBL_TYPE(t)) {
493 v->flags = jd->var[fltalloc].flags;
494 v->regoff = jd->var[fltalloc].regoff;
496 #if !defined(SUPPORT_PASS_FLOATARGS_IN_INTREGS)
497 /* We can only use float arguments as local variables,
498 * if we do not pass them in integer registers. */
499 else if ((p < md->paramcount) &&
500 !md->params[p].inmemory) {
502 v->regoff = rd->argfltregs[md->params[p].regoff];
505 else if (rd->tmpfltreguse > 0) {
507 v->regoff = rd->tmpfltregs[--rd->tmpfltreguse];
509 /* use unused argument registers as local registers */
510 else if ((p >= md->paramcount) &&
511 (fargcnt < FLT_ARG_CNT)) {
513 v->regoff = rd->argfltregs[fargcnt];
516 else if (rd->savfltreguse > 0) {
518 v->regoff = rd->savfltregs[--rd->savfltreguse];
522 #if defined(ALIGN_DOUBLES_IN_MEMORY)
523 /* Align doubles in Memory */
524 if ( (memneeded) && (rd->memuse & 1))
527 v->regoff = rd->memuse;
528 rd->memuse += memneeded + 1;
530 fltalloc = jd->local_map[s * 5 + t];
533 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
535 * for i386 put all longs in memory
537 if (IS_2_WORD_TYPE(t)) {
539 #if defined(ALIGN_LONGS_IN_MEMORY)
540 /* Align longs in Memory */
544 v->regoff = rd->memuse;
545 rd->memuse += memneeded + 1;
550 v->flags = jd->var[intalloc].flags;
551 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
552 if (!(v->flags & INMEMORY)
553 && IS_2_WORD_TYPE(jd->var[intalloc].type))
554 v->regoff = GET_LOW_REG(
555 jd->var[intalloc].regoff);
558 v->regoff = jd->var[intalloc].regoff;
560 else if ((p < md->paramcount) &&
561 !md->params[p].inmemory) {
563 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
564 if (IS_2_WORD_TYPE(t))
565 v->regoff = PACK_REGS(
566 rd->argintregs[GET_LOW_REG(md->params[p].regoff)],
567 rd->argintregs[GET_HIGH_REG(md->params[p].regoff)]);
571 rd->argintregs[md->params[p].regoff];
573 else if (rd->tmpintreguse > intregsneeded) {
574 rd->tmpintreguse -= intregsneeded + 1;
576 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
578 v->regoff = PACK_REGS(
579 rd->tmpintregs[rd->tmpintreguse],
580 rd->tmpintregs[rd->tmpintreguse + 1]);
584 rd->tmpintregs[rd->tmpintreguse];
587 * use unused argument registers as local registers
589 else if ((p >= m->parseddesc->paramcount) &&
590 (iargcnt + intregsneeded < INT_ARG_CNT)) {
592 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
595 rd->argintregs[iargcnt],
596 rd->argintregs[iargcnt + 1]);
599 v->regoff = rd->argintregs[iargcnt];
600 iargcnt += intregsneeded + 1;
602 else if (rd->savintreguse > intregsneeded) {
603 rd->savintreguse -= intregsneeded + 1;
605 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
607 v->regoff = PACK_REGS(
608 rd->savintregs[rd->savintreguse],
609 rd->savintregs[rd->savintreguse + 1]);
612 v->regoff =rd->savintregs[rd->savintreguse];
616 #if defined(ALIGN_LONGS_IN_MEMORY)
617 /* Align longs in Memory */
618 if ( (memneeded) && (rd->memuse & 1))
621 v->regoff = rd->memuse;
622 rd->memuse += memneeded + 1;
625 intalloc = jd->local_map[s * 5 + t];
627 #ifdef HAS_ADDRESS_REGISTER_FILE
630 } /* for (tt=0;...) */
632 /* If the current parameter is a 2-word type, the next local slot */
635 if (p < md->paramcount)
636 if (IS_2_WORD_TYPE(md->paramtypes[p].type))
642 for (s = 0; s < cd->maxlocals; s++) {
643 intalloc = -1; fltalloc = -1;
644 for (tt=0; tt<=4; tt++) {
647 lm = jd->local_map[s * 5 + t];
653 #ifdef SUPPORT_COMBINE_INTEGER_REGISTERS
654 intregsneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
656 #if defined(HAS_4BYTE_STACKSLOT)
657 memneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
659 #ifdef HAS_ADDRESS_REGISTER_FILE
660 if ( IS_ADR_TYPE(t) ) {
661 if (rd->savadrreguse > 0) {
663 v->regoff = rd->savadrregs[--rd->savadrreguse];
667 v->regoff = rd->memuse++;
671 if (IS_FLT_DBL_TYPE(t)) {
673 v->flags = jd->var[fltalloc].flags;
674 v->regoff = jd->var[fltalloc].regoff;
676 else if (rd->savfltreguse > 0) {
678 v->regoff = rd->savfltregs[--rd->savfltreguse];
682 #if defined(ALIGN_DOUBLES_IN_MEMORY)
683 /* Align doubles in Memory */
684 if ( (memneeded) && (rd->memuse & 1))
687 v->regoff = rd->memuse;
688 rd->memuse += memneeded + 1;
690 fltalloc = jd->local_map[s * 5 + t];
693 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
695 * for i386 put all longs in memory
697 if (IS_2_WORD_TYPE(t)) {
699 #if defined(ALIGN_LONGS_IN_MEMORY)
700 /* Align longs in Memory */
704 v->regoff = rd->memuse;
705 rd->memuse += memneeded + 1;
709 v->flags = jd->var[intalloc].flags;
710 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
711 if (!(v->flags & INMEMORY)
712 && IS_2_WORD_TYPE(jd->var[intalloc].type))
713 v->regoff = GET_LOW_REG(
714 jd->var[intalloc].regoff);
717 v->regoff = jd->var[intalloc].regoff;
719 else if (rd->savintreguse > intregsneeded) {
720 rd->savintreguse -= intregsneeded+1;
722 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
724 v->regoff = PACK_REGS(
725 rd->savintregs[rd->savintreguse],
726 rd->savintregs[rd->savintreguse + 1]);
729 v->regoff =rd->savintregs[rd->savintreguse];
733 #if defined(ALIGN_LONGS_IN_MEMORY)
734 /* Align longs in Memory */
735 if ( (memneeded) && (rd->memuse & 1))
738 v->regoff = rd->memuse;
739 rd->memuse += memneeded + 1;
741 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
744 intalloc = jd->local_map[s * 5 + t];
746 #ifdef HAS_ADDRESS_REGISTER_FILE
755 static void reg_init_temp(methodinfo *m, registerdata *rd)
758 #if defined(HAS_4BYTE_STACKSLOT)
759 rd->freememtop_2 = 0;
762 rd->freetmpinttop = 0;
763 rd->freesavinttop = 0;
764 rd->freetmpflttop = 0;
765 rd->freesavflttop = 0;
766 #ifdef HAS_ADDRESS_REGISTER_FILE
767 rd->freetmpadrtop = 0;
768 rd->freesavadrtop = 0;
771 rd->freearginttop = 0;
772 rd->freeargflttop = 0;
773 #ifdef HAS_ADDRESS_REGISTER_FILE
774 rd->freeargadrtop = 0;
779 #define reg_new_temp(jd,index) \
780 if ( (index >= jd->localcount) \
781 && (!(jd->var[index].flags & OUTVAR)) \
782 && (!(jd->var[index].flags & PREALLOC)) ) \
783 reg_new_temp_func(jd, index)
785 static void reg_new_temp_func(jitdata *jd, s4 index)
794 v = &(jd->var[index]);
796 /* Try to allocate a saved register if there is no temporary one */
797 /* available. This is what happens during the second run. */
798 tryagain = (v->flags & SAVEDVAR) ? 1 : 2;
800 #ifdef SUPPORT_COMBINE_INTEGER_REGISTERS
801 intregsneeded = (IS_2_WORD_TYPE(v->type)) ? 1 : 0;
805 #if defined(HAS_4BYTE_STACKSLOT)
806 memneeded = (IS_2_WORD_TYPE(v->type)) ? 1 : 0;
811 for(; tryagain; --tryagain) {
813 if (!(v->flags & SAVEDVAR))
814 v->flags |= SAVEDTMP;
815 #ifdef HAS_ADDRESS_REGISTER_FILE
816 if (IS_ADR_TYPE(v->type)) {
817 if (rd->freesavadrtop > 0) {
818 v->regoff = rd->freesavadrregs[--rd->freesavadrtop];
820 } else if (rd->savadrreguse > 0) {
821 v->regoff = rd->savadrregs[--rd->savadrreguse];
827 if (IS_FLT_DBL_TYPE(v->type)) {
828 if (rd->freesavflttop > 0) {
829 v->regoff = rd->freesavfltregs[--rd->freesavflttop];
831 } else if (rd->savfltreguse > 0) {
832 v->regoff = rd->savfltregs[--rd->savfltreguse];
836 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
838 * for i386 put all longs in memory
840 if (!IS_2_WORD_TYPE(v->type))
843 if (rd->freesavinttop > intregsneeded) {
844 rd->freesavinttop -= intregsneeded + 1;
845 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
847 v->regoff = PACK_REGS(
848 rd->freesavintregs[rd->freesavinttop],
849 rd->freesavintregs[rd->freesavinttop + 1]);
853 rd->freesavintregs[rd->freesavinttop];
855 } else if (rd->savintreguse > intregsneeded) {
856 rd->savintreguse -= intregsneeded + 1;
857 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
859 v->regoff = PACK_REGS(
860 rd->savintregs[rd->savintreguse],
861 rd->savintregs[rd->savintreguse + 1]);
864 v->regoff = rd->savintregs[rd->savintreguse];
870 } else { /* tryagain == 2 */
871 #ifdef HAS_ADDRESS_REGISTER_FILE
872 if (IS_ADR_TYPE(v->type)) {
873 if (rd->freetmpadrtop > 0) {
874 v->regoff = rd->freetmpadrregs[--rd->freetmpadrtop];
876 } else if (rd->tmpadrreguse > 0) {
877 v->regoff = rd->tmpadrregs[--rd->tmpadrreguse];
883 if (IS_FLT_DBL_TYPE(v->type)) {
884 if (rd->freeargflttop > 0) {
885 v->regoff = rd->freeargfltregs[--rd->freeargflttop];
888 } else if (rd->argfltreguse < FLT_ARG_CNT) {
889 v->regoff = rd->argfltregs[rd->argfltreguse++];
892 } else if (rd->freetmpflttop > 0) {
893 v->regoff = rd->freetmpfltregs[--rd->freetmpflttop];
895 } else if (rd->tmpfltreguse > 0) {
896 v->regoff = rd->tmpfltregs[--rd->tmpfltreguse];
901 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
903 * for i386 put all longs in memory
905 if (!IS_2_WORD_TYPE(v->type))
908 if (rd->freearginttop > intregsneeded) {
909 rd->freearginttop -= intregsneeded + 1;
911 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
913 v->regoff = PACK_REGS(
914 rd->freeargintregs[rd->freearginttop],
915 rd->freeargintregs[rd->freearginttop + 1]);
919 rd->freeargintregs[rd->freearginttop];
921 } else if (rd->argintreguse
922 < INT_ARG_CNT - intregsneeded) {
923 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
925 v->regoff = PACK_REGS(
926 rd->argintregs[rd->argintreguse],
927 rd->argintregs[rd->argintreguse + 1]);
930 v->regoff = rd->argintregs[rd->argintreguse];
932 rd->argintreguse += intregsneeded + 1;
934 } else if (rd->freetmpinttop > intregsneeded) {
935 rd->freetmpinttop -= intregsneeded + 1;
936 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
938 v->regoff = PACK_REGS(
939 rd->freetmpintregs[rd->freetmpinttop],
940 rd->freetmpintregs[rd->freetmpinttop + 1]);
943 v->regoff = rd->freetmpintregs[rd->freetmpinttop];
945 } else if (rd->tmpintreguse > intregsneeded) {
946 rd->tmpintreguse -= intregsneeded + 1;
947 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
949 v->regoff = PACK_REGS(
950 rd->tmpintregs[rd->tmpintreguse],
951 rd->tmpintregs[rd->tmpintreguse + 1]);
954 v->regoff = rd->tmpintregs[rd->tmpintreguse];
957 } /* if (!IS_2_WORD_TYPE(s->type)) */
958 } /* if (IS_FLT_DBL_TYPE(s->type)) */
959 } /* if (IS_ADR_TYPE(s->type)) */
960 } /* if (tryagain == 1) else */
961 } /* for(; tryagain; --tryagain) */
963 #if defined(HAS_4BYTE_STACKSLOT)
964 if ((memneeded == 1) && (rd->freememtop_2 > 0)) {
966 v->regoff = rd->freemem_2[rd->freememtop_2];
968 #endif /*defined(HAS_4BYTE_STACKSLOT) */
969 if ((memneeded == 0) && (rd->freememtop > 0)) {
971 v->regoff = rd->freemem[rd->freememtop];
973 #if defined(ALIGN_LONGS_IN_MEMORY) || defined(ALIGN_DOUBLES_IN_MEMORY)
974 /* align 2 Word Types */
975 if ((memneeded) && ((rd->memuse & 1) == 1)) {
976 /* Put patched memory slot on freemem */
977 rd->freemem[rd->freememtop++] = rd->memuse;
980 #endif /* defined(ALIGN_LONGS_IN_MEMORY) || defined(ALIGN_DOUBLES_IN_MEMORY) */
981 v->regoff = rd->memuse;
982 rd->memuse += memneeded + 1;
984 v->flags |= INMEMORY;
988 #define reg_free_temp(jd,index) \
989 if ((index > jd->localcount) \
990 && (!(jd->var[index].flags & OUTVAR)) \
991 && (!(jd->var[index].flags & PREALLOC)) ) \
992 reg_free_temp_func(jd, index)
994 /* Do not free regs/memory locations used by Stackslots flagged STCOPY! There is still another Stackslot */
995 /* alive using this reg/memory location */
997 static void reg_free_temp_func(jitdata *jd, s4 index)
1005 v = &(jd->var[index]);
1008 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
1009 intregsneeded = (IS_2_WORD_TYPE(v->type)) ? 1 : 0;
1014 #if defined(HAS_4BYTE_STACKSLOT)
1015 memneeded = (IS_2_WORD_TYPE(v->type)) ? 1 : 0;
1020 if (v->flags & INMEMORY) {
1021 #if defined(HAS_4BYTE_STACKSLOT)
1022 if (memneeded > 0) {
1023 rd->freemem_2[rd->freememtop_2] = v->regoff;
1028 rd->freemem[rd->freememtop] = v->regoff;
1032 #ifdef HAS_ADDRESS_REGISTER_FILE
1033 } else if (IS_ADR_TYPE(v->type)) {
1034 if (v->flags & (SAVEDVAR | SAVEDTMP)) {
1035 /* v->flags &= ~SAVEDTMP; */
1036 rd->freesavadrregs[rd->freesavadrtop++] = v->regoff;
1038 rd->freetmpadrregs[rd->freetmpadrtop++] = v->regoff;
1040 } else if (IS_FLT_DBL_TYPE(v->type)) {
1041 if (v->flags & (SAVEDVAR | SAVEDTMP)) {
1042 /* v->flags &= ~SAVEDTMP; */
1043 rd->freesavfltregs[rd->freesavflttop++] = v->regoff;
1044 } else if (v->flags & TMPARG) {
1045 /* v->flags &= ~TMPARG; */
1046 rd->freeargfltregs[rd->freeargflttop++] = v->regoff;
1048 rd->freetmpfltregs[rd->freetmpflttop++] = v->regoff;
1049 } else { /* IS_INT_LNG_TYPE */
1050 if (v->flags & (SAVEDVAR | SAVEDTMP)) {
1051 /* v->flags &= ~SAVEDTMP; */
1052 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
1053 if (intregsneeded) {
1054 rd->freesavintregs[rd->freesavinttop] =
1055 GET_LOW_REG(v->regoff);
1056 rd->freesavintregs[rd->freesavinttop + 1] =
1057 GET_HIGH_REG(v->regoff);
1060 rd->freesavintregs[rd->freesavinttop] = v->regoff;
1061 rd->freesavinttop += intregsneeded + 1;
1063 } else if (v->flags & TMPARG) {
1064 /* s->flags &= ~TMPARG; */
1065 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
1066 if (intregsneeded) {
1067 rd->freeargintregs[rd->freearginttop] =
1068 GET_LOW_REG(v->regoff);
1069 rd->freeargintregs[rd->freearginttop + 1] =
1070 GET_HIGH_REG(v->regoff);
1073 rd->freeargintregs[rd->freearginttop] = v->regoff;
1074 rd->freearginttop += intregsneeded + 1;
1076 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
1077 if (intregsneeded) {
1078 rd->freetmpintregs[rd->freetmpinttop] =
1079 GET_LOW_REG(s->regoff);
1080 rd->freetmpintregs[rd->freetmpinttop + 1] =
1081 GET_HIGH_REG(s->regoff);
1084 rd->freetmpintregs[rd->freetmpinttop] = v->regoff;
1085 rd->freetmpinttop += intregsneeded + 1;
1091 /* allocate_scratch_registers **************************************************
1093 Allocate temporary (non-interface, non-local) registers.
1095 *******************************************************************************/
1097 static void new_allocate_scratch_registers(jitdata *jd)
1105 builtintable_entry *bte;
1109 /* get required compiler data */
1114 /* initialize temp registers */
1116 reg_init_temp(m, rd);
1118 bptr = jd->new_basicblocks;
1120 while (bptr != NULL) {
1121 if (bptr->flags >= BBREACHED) {
1123 /* set allocation of invars */
1125 for (i=0; i<bptr->indepth; ++i)
1127 varinfo *v = jd->var + bptr->invars[i];
1129 v->regoff = jd->interface_map[5*i + v->type].regoff;
1130 v->flags = jd->interface_map[5*i + v->type].flags;
1133 /* set allocation of outvars */
1135 for (i=0; i<bptr->outdepth; ++i)
1137 varinfo *v = jd->var + bptr->outvars[i];
1139 v->regoff = jd->interface_map[5*i + v->type].regoff;
1140 v->flags = jd->interface_map[5*i + v->type].flags;
1143 /* iterate over ICMDS to allocate temporary variables */
1145 iptr = bptr->iinstr;
1148 while (--len >= 0) {
1149 switch (iptr->opc) {
1154 case ICMD_CHECKNULL:
1160 case ICMD_PUTSTATICCONST:
1161 case ICMD_INLINE_START:
1162 case ICMD_INLINE_END:
1163 case ICMD_INLINE_GOTO:
1166 /* pop 0 push 1 const */
1174 /* pop 0 push 1 load */
1181 reg_new_temp(jd, iptr->dst.varindex);
1195 reg_free_temp(jd, iptr->sx.s23.s2.varindex);
1196 reg_free_temp(jd, iptr->s1.varindex);
1197 reg_new_temp(jd, iptr->dst.varindex);
1211 reg_free_temp(jd, iptr->sx.s23.s3.varindex);
1212 reg_free_temp(jd, iptr->sx.s23.s2.varindex);
1213 reg_free_temp(jd, iptr->s1.varindex);
1216 /* pop 1 push 0 store */
1236 case ICMD_PUTSTATIC:
1237 case ICMD_PUTFIELDCONST:
1239 /* pop 1 push 0 branch */
1242 case ICMD_IFNONNULL:
1258 /* pop 1 push 0 table branch */
1260 case ICMD_TABLESWITCH:
1261 case ICMD_LOOKUPSWITCH:
1263 case ICMD_MONITORENTER:
1264 case ICMD_MONITOREXIT:
1265 reg_free_temp(jd, iptr->s1.varindex);
1268 /* pop 2 push 0 branch */
1270 case ICMD_IF_ICMPEQ:
1271 case ICMD_IF_ICMPNE:
1272 case ICMD_IF_ICMPLT:
1273 case ICMD_IF_ICMPGE:
1274 case ICMD_IF_ICMPGT:
1275 case ICMD_IF_ICMPLE:
1277 case ICMD_IF_LCMPEQ:
1278 case ICMD_IF_LCMPNE:
1279 case ICMD_IF_LCMPLT:
1280 case ICMD_IF_LCMPGE:
1281 case ICMD_IF_LCMPGT:
1282 case ICMD_IF_LCMPLE:
1284 case ICMD_IF_FCMPEQ:
1285 case ICMD_IF_FCMPNE:
1287 case ICMD_IF_FCMPL_LT:
1288 case ICMD_IF_FCMPL_GE:
1289 case ICMD_IF_FCMPL_GT:
1290 case ICMD_IF_FCMPL_LE:
1292 case ICMD_IF_FCMPG_LT:
1293 case ICMD_IF_FCMPG_GE:
1294 case ICMD_IF_FCMPG_GT:
1295 case ICMD_IF_FCMPG_LE:
1297 case ICMD_IF_DCMPEQ:
1298 case ICMD_IF_DCMPNE:
1300 case ICMD_IF_DCMPL_LT:
1301 case ICMD_IF_DCMPL_GE:
1302 case ICMD_IF_DCMPL_GT:
1303 case ICMD_IF_DCMPL_LE:
1305 case ICMD_IF_DCMPG_LT:
1306 case ICMD_IF_DCMPG_GE:
1307 case ICMD_IF_DCMPG_GT:
1308 case ICMD_IF_DCMPG_LE:
1310 case ICMD_IF_ACMPEQ:
1311 case ICMD_IF_ACMPNE:
1319 case ICMD_IASTORECONST:
1320 case ICMD_LASTORECONST:
1321 case ICMD_AASTORECONST:
1322 case ICMD_BASTORECONST:
1323 case ICMD_CASTORECONST:
1324 case ICMD_SASTORECONST:
1325 reg_free_temp(jd, iptr->sx.s23.s2.varindex);
1326 reg_free_temp(jd, iptr->s1.varindex);
1329 /* pop 0 push 1 copy */
1332 /* src === dst->prev (identical Stackslot Element) */
1333 /* src --> dst (copied value, take same reg/mem) */
1335 /* if (!reg_alloc_dup(iptr->s1.varindex, iptr->dst.varindex)) { */
1336 reg_new_temp(jd, iptr->dst.varindex);
1338 /* iptr->dst.varindex->flags |= STCOPY; */
1342 /* pop 1 push 1 move */
1345 reg_new_temp(jd, iptr->dst.varindex);
1346 reg_free_temp(jd, iptr->s1.varindex);
1395 reg_free_temp(jd, iptr->sx.s23.s2.varindex);
1396 reg_free_temp(jd, iptr->s1.varindex);
1397 reg_new_temp(jd, iptr->dst.varindex);
1402 case ICMD_IADDCONST:
1403 case ICMD_ISUBCONST:
1404 case ICMD_IMULCONST:
1408 case ICMD_IANDCONST:
1410 case ICMD_IXORCONST:
1411 case ICMD_ISHLCONST:
1412 case ICMD_ISHRCONST:
1413 case ICMD_IUSHRCONST:
1415 case ICMD_LADDCONST:
1416 case ICMD_LSUBCONST:
1417 case ICMD_LMULCONST:
1421 case ICMD_LANDCONST:
1423 case ICMD_LXORCONST:
1424 case ICMD_LSHLCONST:
1425 case ICMD_LSHRCONST:
1426 case ICMD_LUSHRCONST:
1431 case ICMD_INT2SHORT:
1449 case ICMD_CHECKCAST:
1451 case ICMD_ARRAYLENGTH:
1452 case ICMD_INSTANCEOF:
1455 case ICMD_ANEWARRAY:
1458 reg_free_temp(jd, iptr->s1.varindex);
1459 reg_new_temp(jd, iptr->dst.varindex);
1464 case ICMD_GETSTATIC:
1467 reg_new_temp(jd, iptr->dst.varindex);
1470 /* pop many push any */
1472 case ICMD_INVOKESTATIC:
1473 case ICMD_INVOKESPECIAL:
1474 case ICMD_INVOKEVIRTUAL:
1475 case ICMD_INVOKEINTERFACE:
1476 INSTRUCTION_GET_METHODDESC(iptr,md);
1478 argp = iptr->sx.s23.s2.args;
1480 reg_free_temp(jd, *argp);
1483 if (md->returntype.type != TYPE_VOID)
1484 reg_new_temp(jd, iptr->dst.varindex);
1488 bte = iptr->sx.s23.s3.bte;
1491 argp = iptr->sx.s23.s2.args;
1493 reg_free_temp(jd, *argp);
1496 if (md->returntype.type != TYPE_VOID)
1497 reg_new_temp(jd, iptr->dst.varindex);
1500 case ICMD_MULTIANEWARRAY:
1501 i = iptr->s1.argcount;
1502 argp = iptr->sx.s23.s2.args;
1504 reg_free_temp(jd, *argp);
1507 reg_new_temp(jd, iptr->dst.varindex);
1512 new_internalerror("Unknown ICMD %d during register allocation",
1517 } /* while instructions */
1520 } /* while blocks */
1524 #if defined(ENABLE_STATISTICS)
1525 void reg_make_statistics(jitdata *jd)
1532 stackptr src, src_old;
1536 int size_interface; /* == maximum size of in/out stack at basic block boundaries */
1539 /* get required compiler data */
1549 /* count how many local variables are held in memory or register */
1550 for(i=0; i < cd->maxlocals; i++)
1551 for (type=0; type <=4; type++)
1552 if (rd->locals[i][type].type != -1) { /* valid local */
1553 if (rd->locals[i][type].flags & INMEMORY) {
1554 count_locals_spilled++;
1558 count_locals_register++;
1561 /* count how many stack slots are held in memory or register */
1563 bptr = jd->new_basicblocks;
1565 while (bptr != NULL) {
1566 if (bptr->flags >= BBREACHED) {
1568 #if defined(ENABLE_LSRA) || defined(ENABLE_SSA)
1571 /* check for memory moves from interface to BB instack */
1572 dst = bptr->instack;
1573 len = bptr->indepth;
1575 if (len > size_interface) size_interface = len;
1577 while (dst != NULL) {
1579 if (dst->varkind != STACKVAR) {
1580 if ( (dst->flags & INMEMORY) ||
1581 (rd->interfaces[len][dst->type].flags & INMEMORY) ||
1582 ( (dst->flags & INMEMORY) &&
1583 (rd->interfaces[len][dst->type].flags & INMEMORY) &&
1584 (dst->regoff != rd->interfaces[len][dst->type].regoff) ))
1586 /* one in memory or both inmemory at different offsets */
1587 count_mem_move_bb++;
1595 /* check for memory moves from BB outstack to interface */
1596 dst = bptr->outstack;
1597 len = bptr->outdepth;
1598 if (len > size_interface) size_interface = len;
1602 if (dst->varkind != STACKVAR) {
1603 if ( (dst->flags & INMEMORY) || \
1604 (rd->interfaces[len][dst->type].flags & INMEMORY) || \
1605 ( (dst->flags & INMEMORY) && \
1606 (rd->interfaces[len][dst->type].flags & INMEMORY) && \
1607 (dst->regoff != rd->interfaces[len][dst->type].regoff) ))
1609 /* one in memory or both inmemory at different offsets */
1610 count_mem_move_bb++;
1617 #if defined(ENABLE_LSRA) || defined(ENABLE_SSA)
1622 dst = bptr->instack;
1623 iptr = bptr->iinstr;
1627 while (--len >= 0) {
1629 dst = iptr->dst.var;
1631 if ((src!= NULL) && (src != src_old)) { /* new stackslot */
1632 switch (src->varkind) {
1635 if (!(src->flags & INMEMORY))
1636 count_ss_register++;
1642 /* case LOCALVAR: */
1643 /* if (!(rd->locals[src->varnum][src->type].flags & INMEMORY)) */
1644 /* count_ss_register++; */
1646 /* count_ss_spilled++; */
1649 if (!(src->flags & INMEMORY))
1650 count_argument_mem_ss++;
1652 count_argument_reg_ss++;
1656 /* if (IS_FLT_DBL_TYPE(src->type)) { */
1657 /* if (src->varnum < FLT_ARG_CNT) { */
1658 /* count_ss_register++; */
1662 /* #if defined(__POWERPC__) */
1663 /* if (src->varnum < INT_ARG_CNT - (IS_2_WORD_TYPE(src->type) != 0)) { */
1665 /* if (src->varnum < INT_ARG_CNT) { */
1667 /* count_ss_register++; */
1671 /* count_ss_spilled++; */
1678 } /* while instructions */
1682 } /* while blocks */
1683 count_interface_size += size_interface; /* accummulate the size of the interface (between bb boundaries) */
1684 if (in_register) count_method_in_register++;
1686 printf("INREGISTER: %s%s%s\n",m->class->name->text, m->name->text, m->descriptor->text);
1689 #endif /* defined(ENABLE_STATISTICS) */
1693 * These are local overrides for various environment variables in Emacs.
1694 * Please do not remove this and leave it at the end of the file, where
1695 * Emacs will automagically detect them.
1696 * ---------------------------------------------------------------------
1699 * indent-tabs-mode: t
1703 * vim:noexpandtab:sw=4:ts=4: