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 5647 2006-10-03 18:09:26Z 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 | INOUT;
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->vv.regoff = rd->argadrregs[md->params[p].regoff];
471 else if (rd->tmpadrreguse > 0) {
473 v->vv.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->vv.regoff = rd->argadrregs[aargcnt++];
481 else if (rd->savadrreguse > 0) {
483 v->vv.regoff = rd->savadrregs[--rd->savadrreguse];
486 v->flags |= INMEMORY;
487 v->vv.regoff = rd->memuse++;
491 if (IS_FLT_DBL_TYPE(t)) {
493 v->flags = VAR(fltalloc)->flags;
494 v->vv.regoff = VAR(fltalloc)->vv.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->vv.regoff = rd->argfltregs[md->params[p].regoff];
505 else if (rd->tmpfltreguse > 0) {
507 v->vv.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->vv.regoff = rd->argfltregs[fargcnt];
516 else if (rd->savfltreguse > 0) {
518 v->vv.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->vv.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->vv.regoff = rd->memuse;
545 rd->memuse += memneeded + 1;
550 v->flags = VAR(intalloc)->flags;
551 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
552 if (!(v->flags & INMEMORY)
553 && IS_2_WORD_TYPE(VAR(intalloc)->type))
554 v->vv.regoff = GET_LOW_REG(
555 VAR(intalloc)->vv.regoff);
558 v->vv.regoff = VAR(intalloc)->vv.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->vv.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->vv.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)
594 v->vv.regoff=PACK_REGS(
595 rd->argintregs[iargcnt],
596 rd->argintregs[iargcnt + 1]);
599 v->vv.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->vv.regoff = PACK_REGS(
608 rd->savintregs[rd->savintreguse],
609 rd->savintregs[rd->savintreguse + 1]);
612 v->vv.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->vv.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->vv.regoff = rd->savadrregs[--rd->savadrreguse];
667 v->vv.regoff = rd->memuse++;
671 if (IS_FLT_DBL_TYPE(t)) {
673 v->flags = VAR(fltalloc)->flags;
674 v->vv.regoff = VAR(fltalloc)->vv.regoff;
676 else if (rd->savfltreguse > 0) {
678 v->vv.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->vv.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->vv.regoff = rd->memuse;
705 rd->memuse += memneeded + 1;
709 v->flags = VAR(intalloc)->flags;
710 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
711 if (!(v->flags & INMEMORY)
712 && IS_2_WORD_TYPE(VAR(intalloc)->type))
713 v->vv.regoff = GET_LOW_REG(
714 VAR(intalloc)->vv.regoff);
717 v->vv.regoff = VAR(intalloc)->vv.regoff;
719 else if (rd->savintreguse > intregsneeded) {
720 rd->savintreguse -= intregsneeded+1;
722 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
724 v->vv.regoff = PACK_REGS(
725 rd->savintregs[rd->savintreguse],
726 rd->savintregs[rd->savintreguse + 1]);
729 v->vv.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->vv.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(jitdata *jd, 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;
777 rd->regcopycount = DMNEW(int, INT_REG_CNT + FLT_REG_CNT);
778 MZERO(rd->regcopycount, int, INT_REG_CNT + FLT_REG_CNT);
780 /* memcopycount is dynamically allocated when needed */
782 rd->memcopycount = NULL;
783 rd->memcopycountsize = 0;
787 #define reg_new_temp(jd,index) \
788 if ( (index >= jd->localcount) \
789 && (!(VAR(index)->flags & (INOUT | PREALLOC))) ) \
790 reg_new_temp_func(jd, index)
792 static void reg_new_temp_func(jitdata *jd, s4 index)
803 /* Try to allocate a saved register if there is no temporary one */
804 /* available. This is what happens during the second run. */
805 tryagain = (v->flags & SAVEDVAR) ? 1 : 2;
807 #ifdef SUPPORT_COMBINE_INTEGER_REGISTERS
808 intregsneeded = (IS_2_WORD_TYPE(v->type)) ? 1 : 0;
812 #if defined(HAS_4BYTE_STACKSLOT)
813 memneeded = (IS_2_WORD_TYPE(v->type)) ? 1 : 0;
818 for(; tryagain; --tryagain) {
820 if (!(v->flags & SAVEDVAR))
821 v->flags |= SAVEDTMP;
822 #ifdef HAS_ADDRESS_REGISTER_FILE
823 if (IS_ADR_TYPE(v->type)) {
824 if (rd->freesavadrtop > 0) {
825 v->vv.regoff = rd->freesavadrregs[--rd->freesavadrtop];
827 } else if (rd->savadrreguse > 0) {
828 v->vv.regoff = rd->savadrregs[--rd->savadrreguse];
834 if (IS_FLT_DBL_TYPE(v->type)) {
835 if (rd->freesavflttop > 0) {
836 v->vv.regoff = rd->freesavfltregs[--rd->freesavflttop];
838 } else if (rd->savfltreguse > 0) {
839 v->vv.regoff = rd->savfltregs[--rd->savfltreguse];
843 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
845 * for i386 put all longs in memory
847 if (!IS_2_WORD_TYPE(v->type))
850 if (rd->freesavinttop > intregsneeded) {
851 rd->freesavinttop -= intregsneeded + 1;
852 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
854 v->vv.regoff = PACK_REGS(
855 rd->freesavintregs[rd->freesavinttop],
856 rd->freesavintregs[rd->freesavinttop + 1]);
860 rd->freesavintregs[rd->freesavinttop];
862 } else if (rd->savintreguse > intregsneeded) {
863 rd->savintreguse -= intregsneeded + 1;
864 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
866 v->vv.regoff = PACK_REGS(
867 rd->savintregs[rd->savintreguse],
868 rd->savintregs[rd->savintreguse + 1]);
871 v->vv.regoff = rd->savintregs[rd->savintreguse];
877 } else { /* tryagain == 2 */
878 #ifdef HAS_ADDRESS_REGISTER_FILE
879 if (IS_ADR_TYPE(v->type)) {
880 if (rd->freetmpadrtop > 0) {
881 v->vv.regoff = rd->freetmpadrregs[--rd->freetmpadrtop];
883 } else if (rd->tmpadrreguse > 0) {
884 v->vv.regoff = rd->tmpadrregs[--rd->tmpadrreguse];
890 if (IS_FLT_DBL_TYPE(v->type)) {
891 if (rd->freeargflttop > 0) {
892 v->vv.regoff = rd->freeargfltregs[--rd->freeargflttop];
895 } else if (rd->argfltreguse < FLT_ARG_CNT) {
896 v->vv.regoff = rd->argfltregs[rd->argfltreguse++];
899 } else if (rd->freetmpflttop > 0) {
900 v->vv.regoff = rd->freetmpfltregs[--rd->freetmpflttop];
902 } else if (rd->tmpfltreguse > 0) {
903 v->vv.regoff = rd->tmpfltregs[--rd->tmpfltreguse];
908 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
910 * for i386 put all longs in memory
912 if (!IS_2_WORD_TYPE(v->type))
915 if (rd->freearginttop > intregsneeded) {
916 rd->freearginttop -= intregsneeded + 1;
918 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
920 v->vv.regoff = PACK_REGS(
921 rd->freeargintregs[rd->freearginttop],
922 rd->freeargintregs[rd->freearginttop + 1]);
926 rd->freeargintregs[rd->freearginttop];
928 } else if (rd->argintreguse
929 < INT_ARG_CNT - intregsneeded) {
930 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
932 v->vv.regoff = PACK_REGS(
933 rd->argintregs[rd->argintreguse],
934 rd->argintregs[rd->argintreguse + 1]);
937 v->vv.regoff = rd->argintregs[rd->argintreguse];
939 rd->argintreguse += intregsneeded + 1;
941 } else if (rd->freetmpinttop > intregsneeded) {
942 rd->freetmpinttop -= intregsneeded + 1;
943 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
945 v->vv.regoff = PACK_REGS(
946 rd->freetmpintregs[rd->freetmpinttop],
947 rd->freetmpintregs[rd->freetmpinttop + 1]);
950 v->vv.regoff = rd->freetmpintregs[rd->freetmpinttop];
952 } else if (rd->tmpintreguse > intregsneeded) {
953 rd->tmpintreguse -= intregsneeded + 1;
954 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
956 v->vv.regoff = PACK_REGS(
957 rd->tmpintregs[rd->tmpintreguse],
958 rd->tmpintregs[rd->tmpintreguse + 1]);
961 v->vv.regoff = rd->tmpintregs[rd->tmpintreguse];
964 } /* if (!IS_2_WORD_TYPE(s->type)) */
965 } /* if (IS_FLT_DBL_TYPE(s->type)) */
966 } /* if (IS_ADR_TYPE(s->type)) */
967 } /* if (tryagain == 1) else */
968 } /* for(; tryagain; --tryagain) */
970 #if defined(HAS_4BYTE_STACKSLOT)
971 if ((memneeded == 1) && (rd->freememtop_2 > 0)) {
973 v->vv.regoff = rd->freemem_2[rd->freememtop_2];
975 #endif /*defined(HAS_4BYTE_STACKSLOT) */
976 if ((memneeded == 0) && (rd->freememtop > 0)) {
978 v->vv.regoff = rd->freemem[rd->freememtop];
980 #if defined(ALIGN_LONGS_IN_MEMORY) || defined(ALIGN_DOUBLES_IN_MEMORY)
981 /* align 2 Word Types */
982 if ((memneeded) && ((rd->memuse & 1) == 1)) {
983 /* Put patched memory slot on freemem */
984 rd->freemem[rd->freememtop++] = rd->memuse;
987 #endif /* defined(ALIGN_LONGS_IN_MEMORY) || defined(ALIGN_DOUBLES_IN_MEMORY) */
988 v->vv.regoff = rd->memuse;
989 rd->memuse += memneeded + 1;
991 v->flags |= INMEMORY;
995 #define reg_free_temp(jd,index) \
996 if ((index > jd->localcount) \
997 && (!(VAR(index)->flags & (INOUT | PREALLOC)))) \
998 reg_free_temp_func(jd, index)
1000 /* Do not free regs/memory locations used by Stackslots flagged STCOPY! There is still another Stackslot */
1001 /* alive using this reg/memory location */
1003 static void reg_free_temp_func(jitdata *jd, s4 index)
1013 /* if this is a copy of another variable, just decrement the copy counter */
1015 /* XXX split reg/mem variables on arm may need special handling here */
1017 if (v->flags & INMEMORY) {
1018 if (v->vv.regoff < rd->memcopycountsize && rd->memcopycount[v->vv.regoff]) {
1019 rd->memcopycount[v->vv.regoff]--;
1024 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
1025 if (rd->regcopycount[GET_LOW_REG(v->vv.regoff)]) {
1026 rd->regcopycount[GET_LOW_REG(v->vv.regoff)]--;
1030 if (rd->regcopycount[v->vv.regoff]) {
1031 rd->regcopycount[v->vv.regoff]--;
1037 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
1038 intregsneeded = (IS_2_WORD_TYPE(v->type)) ? 1 : 0;
1043 #if defined(HAS_4BYTE_STACKSLOT)
1044 memneeded = (IS_2_WORD_TYPE(v->type)) ? 1 : 0;
1049 if (v->flags & INMEMORY) {
1050 #if defined(HAS_4BYTE_STACKSLOT)
1051 if (memneeded > 0) {
1052 rd->freemem_2[rd->freememtop_2] = v->vv.regoff;
1057 rd->freemem[rd->freememtop] = v->vv.regoff;
1061 #ifdef HAS_ADDRESS_REGISTER_FILE
1062 } else if (IS_ADR_TYPE(v->type)) {
1063 if (v->flags & (SAVEDVAR | SAVEDTMP)) {
1064 /* v->flags &= ~SAVEDTMP; */
1065 rd->freesavadrregs[rd->freesavadrtop++] = v->vv.regoff;
1067 rd->freetmpadrregs[rd->freetmpadrtop++] = v->vv.regoff;
1069 } else if (IS_FLT_DBL_TYPE(v->type)) {
1070 if (v->flags & (SAVEDVAR | SAVEDTMP)) {
1071 /* v->flags &= ~SAVEDTMP; */
1072 rd->freesavfltregs[rd->freesavflttop++] = v->vv.regoff;
1073 } else if (v->flags & TMPARG) {
1074 /* v->flags &= ~TMPARG; */
1075 rd->freeargfltregs[rd->freeargflttop++] = v->vv.regoff;
1077 rd->freetmpfltregs[rd->freetmpflttop++] = v->vv.regoff;
1078 } else { /* IS_INT_LNG_TYPE */
1079 if (v->flags & (SAVEDVAR | SAVEDTMP)) {
1080 /* v->flags &= ~SAVEDTMP; */
1081 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
1082 if (intregsneeded) {
1083 rd->freesavintregs[rd->freesavinttop] =
1084 GET_LOW_REG(v->vv.regoff);
1085 rd->freesavintregs[rd->freesavinttop + 1] =
1086 GET_HIGH_REG(v->vv.regoff);
1089 rd->freesavintregs[rd->freesavinttop] = v->vv.regoff;
1090 rd->freesavinttop += intregsneeded + 1;
1092 } else if (v->flags & TMPARG) {
1093 /* s->flags &= ~TMPARG; */
1094 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
1095 if (intregsneeded) {
1096 rd->freeargintregs[rd->freearginttop] =
1097 GET_LOW_REG(v->vv.regoff);
1098 rd->freeargintregs[rd->freearginttop + 1] =
1099 GET_HIGH_REG(v->vv.regoff);
1102 rd->freeargintregs[rd->freearginttop] = v->vv.regoff;
1103 rd->freearginttop += intregsneeded + 1;
1105 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
1106 if (intregsneeded) {
1107 rd->freetmpintregs[rd->freetmpinttop] =
1108 GET_LOW_REG(v->vv.regoff);
1109 rd->freetmpintregs[rd->freetmpinttop + 1] =
1110 GET_HIGH_REG(v->vv.regoff);
1113 rd->freetmpintregs[rd->freetmpinttop] = v->vv.regoff;
1114 rd->freetmpinttop += intregsneeded + 1;
1120 static bool reg_alloc_dup(jitdata *jd, s4 srcindex, s4 dstindex)
1125 /* do not coalesce local variables here */
1127 if (srcindex <= jd->localcount || dstindex <= jd->localcount)
1133 /* do not coalesce in/out vars or preallocated variables here */
1135 if ((sv->flags | dv->flags) & (INOUT | PREALLOC))
1138 /* if the source is in memory, we can coalesce in any case */
1140 if (sv->flags & INMEMORY) {
1141 dv->flags |= INMEMORY;
1142 dv->vv.regoff = sv->vv.regoff;
1146 /* we do not allocate a REG_TMP to a REG_SAV variable */
1148 if ((sv->flags & SAVEDVAR) != (dv->flags & SAVEDVAR))
1152 dv->vv.regoff = sv->vv.regoff;
1153 dv->flags |= sv->flags & (SAVEDTMP | TMPARG);
1159 /* allocate_scratch_registers **************************************************
1161 Allocate temporary (non-interface, non-local) registers.
1163 *******************************************************************************/
1165 static void new_allocate_scratch_registers(jitdata *jd)
1173 builtintable_entry *bte;
1178 /* get required compiler data */
1183 /* initialize temp registers */
1185 reg_init_temp(jd, rd);
1187 bptr = jd->new_basicblocks;
1189 while (bptr != NULL) {
1190 if (bptr->flags >= BBREACHED) {
1192 /* set allocation of invars */
1194 for (i=0; i<bptr->indepth; ++i)
1196 v = VAR(bptr->invars[i]);
1198 v->vv.regoff = jd->interface_map[5*i + v->type].regoff;
1199 v->flags = jd->interface_map[5*i + v->type].flags;
1202 /* set allocation of outvars */
1204 for (i=0; i<bptr->outdepth; ++i)
1206 v = VAR(bptr->outvars[i]);
1208 v->vv.regoff = jd->interface_map[5*i + v->type].regoff;
1209 v->flags = jd->interface_map[5*i + v->type].flags;
1212 /* iterate over ICMDS to allocate temporary variables */
1214 iptr = bptr->iinstr;
1217 while (--len >= 0) {
1218 switch (iptr->opc) {
1223 #if !defined(NDEBUG)
1224 /* avoid problems with show_allocation */
1225 VAROP(iptr->dst)->vv.regoff = 0;
1228 case ICMD_CHECKNULL:
1233 case ICMD_PUTSTATICCONST:
1234 case ICMD_INLINE_START:
1235 case ICMD_INLINE_END:
1236 case ICMD_INLINE_GOTO:
1239 /* pop 0 push 1 const */
1247 /* pop 0 push 1 load */
1254 reg_new_temp(jd, iptr->dst.varindex);
1268 reg_free_temp(jd, iptr->sx.s23.s2.varindex);
1269 reg_free_temp(jd, iptr->s1.varindex);
1270 reg_new_temp(jd, iptr->dst.varindex);
1284 reg_free_temp(jd, iptr->sx.s23.s3.varindex);
1285 reg_free_temp(jd, iptr->sx.s23.s2.varindex);
1286 reg_free_temp(jd, iptr->s1.varindex);
1289 /* pop 1 push 0 store */
1309 case ICMD_PUTSTATIC:
1310 case ICMD_PUTFIELDCONST:
1312 /* pop 1 push 0 branch */
1315 case ICMD_IFNONNULL:
1331 /* pop 1 push 0 table branch */
1333 case ICMD_TABLESWITCH:
1334 case ICMD_LOOKUPSWITCH:
1336 case ICMD_MONITORENTER:
1337 case ICMD_MONITOREXIT:
1338 reg_free_temp(jd, iptr->s1.varindex);
1341 /* pop 2 push 0 branch */
1343 case ICMD_IF_ICMPEQ:
1344 case ICMD_IF_ICMPNE:
1345 case ICMD_IF_ICMPLT:
1346 case ICMD_IF_ICMPGE:
1347 case ICMD_IF_ICMPGT:
1348 case ICMD_IF_ICMPLE:
1350 case ICMD_IF_LCMPEQ:
1351 case ICMD_IF_LCMPNE:
1352 case ICMD_IF_LCMPLT:
1353 case ICMD_IF_LCMPGE:
1354 case ICMD_IF_LCMPGT:
1355 case ICMD_IF_LCMPLE:
1357 case ICMD_IF_FCMPEQ:
1358 case ICMD_IF_FCMPNE:
1360 case ICMD_IF_FCMPL_LT:
1361 case ICMD_IF_FCMPL_GE:
1362 case ICMD_IF_FCMPL_GT:
1363 case ICMD_IF_FCMPL_LE:
1365 case ICMD_IF_FCMPG_LT:
1366 case ICMD_IF_FCMPG_GE:
1367 case ICMD_IF_FCMPG_GT:
1368 case ICMD_IF_FCMPG_LE:
1370 case ICMD_IF_DCMPEQ:
1371 case ICMD_IF_DCMPNE:
1373 case ICMD_IF_DCMPL_LT:
1374 case ICMD_IF_DCMPL_GE:
1375 case ICMD_IF_DCMPL_GT:
1376 case ICMD_IF_DCMPL_LE:
1378 case ICMD_IF_DCMPG_LT:
1379 case ICMD_IF_DCMPG_GE:
1380 case ICMD_IF_DCMPG_GT:
1381 case ICMD_IF_DCMPG_LE:
1383 case ICMD_IF_ACMPEQ:
1384 case ICMD_IF_ACMPNE:
1392 case ICMD_IASTORECONST:
1393 case ICMD_LASTORECONST:
1394 case ICMD_AASTORECONST:
1395 case ICMD_BASTORECONST:
1396 case ICMD_CASTORECONST:
1397 case ICMD_SASTORECONST:
1398 reg_free_temp(jd, iptr->sx.s23.s2.varindex);
1399 reg_free_temp(jd, iptr->s1.varindex);
1402 /* pop 0 push 1 copy */
1405 /* src === dst->prev (identical Stackslot Element) */
1406 /* src --> dst (copied value, take same reg/mem) */
1408 if (!reg_alloc_dup(jd, iptr->s1.varindex, iptr->dst.varindex)) {
1409 reg_new_temp(jd, iptr->dst.varindex);
1411 v = VAROP(iptr->dst);
1413 if (v->flags & INMEMORY) {
1414 if (v->vv.regoff >= rd->memcopycountsize) {
1415 int newsize = (v->vv.regoff + 1) * 2;
1416 i = rd->memcopycountsize;
1417 rd->memcopycount = DMREALLOC(rd->memcopycount, int, i, newsize);
1418 MZERO(rd->memcopycount + i, int, newsize - i);
1419 rd->memcopycountsize = newsize;
1421 rd->memcopycount[v->vv.regoff]++;
1424 /* XXX split reg/mem variables on arm may need special handling here */
1426 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
1427 rd->regcopycount[GET_LOW_REG(v->vv.regoff)]++;
1429 rd->regcopycount[v->vv.regoff]++;
1435 /* pop 1 push 1 move */
1438 if (!reg_alloc_dup(jd, iptr->s1.varindex, iptr->dst.varindex)) {
1439 reg_new_temp(jd, iptr->dst.varindex);
1440 reg_free_temp(jd, iptr->s1.varindex);
1490 reg_free_temp(jd, iptr->sx.s23.s2.varindex);
1491 reg_free_temp(jd, iptr->s1.varindex);
1492 reg_new_temp(jd, iptr->dst.varindex);
1497 case ICMD_IADDCONST:
1498 case ICMD_ISUBCONST:
1499 case ICMD_IMULCONST:
1503 case ICMD_IANDCONST:
1505 case ICMD_IXORCONST:
1506 case ICMD_ISHLCONST:
1507 case ICMD_ISHRCONST:
1508 case ICMD_IUSHRCONST:
1510 case ICMD_LADDCONST:
1511 case ICMD_LSUBCONST:
1512 case ICMD_LMULCONST:
1516 case ICMD_LANDCONST:
1518 case ICMD_LXORCONST:
1519 case ICMD_LSHLCONST:
1520 case ICMD_LSHRCONST:
1521 case ICMD_LUSHRCONST:
1526 case ICMD_INT2SHORT:
1544 case ICMD_CHECKCAST:
1546 case ICMD_ARRAYLENGTH:
1547 case ICMD_INSTANCEOF:
1550 case ICMD_ANEWARRAY:
1553 reg_free_temp(jd, iptr->s1.varindex);
1554 reg_new_temp(jd, iptr->dst.varindex);
1559 case ICMD_GETSTATIC:
1562 reg_new_temp(jd, iptr->dst.varindex);
1565 /* pop many push any */
1567 case ICMD_INVOKESTATIC:
1568 case ICMD_INVOKESPECIAL:
1569 case ICMD_INVOKEVIRTUAL:
1570 case ICMD_INVOKEINTERFACE:
1571 INSTRUCTION_GET_METHODDESC(iptr,md);
1573 argp = iptr->sx.s23.s2.args;
1575 reg_free_temp(jd, *argp);
1578 if (md->returntype.type != TYPE_VOID)
1579 reg_new_temp(jd, iptr->dst.varindex);
1583 bte = iptr->sx.s23.s3.bte;
1586 argp = iptr->sx.s23.s2.args;
1588 reg_free_temp(jd, *argp);
1591 if (md->returntype.type != TYPE_VOID)
1592 reg_new_temp(jd, iptr->dst.varindex);
1595 case ICMD_MULTIANEWARRAY:
1596 i = iptr->s1.argcount;
1597 argp = iptr->sx.s23.s2.args;
1599 reg_free_temp(jd, *argp);
1602 reg_new_temp(jd, iptr->dst.varindex);
1607 new_internalerror("Unknown ICMD %d during register allocation",
1612 } /* while instructions */
1615 } /* while blocks */
1619 #if defined(ENABLE_STATISTICS)
1620 void reg_make_statistics(jitdata *jd)
1627 stackptr src, src_old;
1631 int size_interface; /* == maximum size of in/out stack at basic block boundaries */
1635 /* get required compiler data */
1645 /* count how many local variables are held in memory or register */
1646 for(i=0; i < jd->localcount; i++) {
1647 if (VAR(i)->flags & INMEMORY) {
1648 count_locals_spilled++;
1652 count_locals_register++;
1656 /* count how many stack slots are held in memory or register */
1658 bptr = jd->new_basicblocks;
1660 while (bptr != NULL) {
1661 if (bptr->flags >= BBREACHED) {
1663 #if defined(ENABLE_LSRA) || defined(ENABLE_SSA)
1666 /* check for memory moves from interface to BB instack */
1667 len = bptr->indepth;
1669 if (len > size_interface) size_interface = len;
1673 var = VAR(bptr->invars[len]);
1675 /* invars statistics (currently none) */
1678 /* check for memory moves from BB outstack to interface */
1679 len = bptr->outdepth;
1680 if (len > size_interface) size_interface = len;
1684 var = VAR(bptr->invars[len]);
1686 /* outvars statistics (currently none) */
1688 #if defined(ENABLE_LSRA) || defined(ENABLE_SSA)
1694 dst = bptr->instack;
1695 iptr = bptr->iinstr;
1699 while (--len >= 0) {
1701 dst = iptr->dst.var;
1703 if ((src!= NULL) && (src != src_old)) { /* new stackslot */
1704 switch (src->varkind) {
1707 if (!(src->flags & INMEMORY))
1708 count_ss_register++;
1714 /* case LOCALVAR: */
1715 /* if (!(rd->locals[src->varnum][src->type].flags & INMEMORY)) */
1716 /* count_ss_register++; */
1718 /* count_ss_spilled++; */
1721 if (!(src->flags & INMEMORY))
1722 count_argument_mem_ss++;
1724 count_argument_reg_ss++;
1728 /* if (IS_FLT_DBL_TYPE(src->type)) { */
1729 /* if (src->varnum < FLT_ARG_CNT) { */
1730 /* count_ss_register++; */
1734 /* #if defined(__POWERPC__) */
1735 /* if (src->varnum < INT_ARG_CNT - (IS_2_WORD_TYPE(src->type) != 0)) { */
1737 /* if (src->varnum < INT_ARG_CNT) { */
1739 /* count_ss_register++; */
1743 /* count_ss_spilled++; */
1750 } /* while instructions */
1755 } /* while blocks */
1757 count_interface_size += size_interface; /* accummulate the size of the interface (between bb boundaries) */
1758 if (in_register) count_method_in_register++;
1760 printf("INREGISTER: %s%s%s\n",m->class->name->text, m->name->text, m->descriptor->text);
1763 #endif /* defined(ENABLE_STATISTICS) */
1767 * These are local overrides for various environment variables in Emacs.
1768 * Please do not remove this and leave it at the end of the file, where
1769 * Emacs will automagically detect them.
1770 * ---------------------------------------------------------------------
1773 * indent-tabs-mode: t
1777 * vim:noexpandtab:sw=4:ts=4: