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 5654 2006-10-03 20:27:47Z 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);
66 /* regalloc ********************************************************************
68 Does a simple register allocation.
70 *******************************************************************************/
72 bool new_regalloc(jitdata *jd)
74 /* There is a problem with the use of unused float argument
75 registers in leafmethods for stackslots on c7 (2 * Dual Core
76 AMD Opteron(tm) Processor 270) - runtime for the jvm98 _mtrt
77 benchmark is heaviliy increased. This could be prevented by
78 setting rd->argfltreguse to FLT_ARG_CNT before calling
79 allocate_scratch_registers and setting it back to the original
80 value before calling local_regalloc. */
82 interface_regalloc(jd);
83 new_allocate_scratch_registers(jd);
91 /* interface_regalloc **********************************************************
93 Allocates registers for all interface variables.
95 *******************************************************************************/
97 static void interface_regalloc(jitdata *jd)
104 int intalloc, fltalloc; /* Remember allocated Register/Memory offset */
105 /* in case more vars are packed into this interface slot */
106 int intregsneeded = 0;
108 /* allocate LNG and DBL Types first to ensure 2 memory slots or registers */
109 /* on HAS_4BYTE_STACKSLOT architectures */
110 int typeloop[] = { TYPE_LNG, TYPE_DBL, TYPE_INT, TYPE_FLT, TYPE_ADR };
113 /* get required compiler data */
119 /* rd->memuse was already set in stack.c to allocate stack space
120 for passing arguments to called methods. */
122 #if defined(__I386__)
123 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
124 /* reserve 0(%esp) for Monitorenter/exit Argument on i386 */
130 if (jd->isleafmethod) {
131 /* Reserve argument register, which will be used for Locals acting */
133 if (rd->argintreguse < m->parseddesc->argintreguse)
134 rd->argintreguse = m->parseddesc->argintreguse;
135 if (rd->argfltreguse < m->parseddesc->argfltreguse)
136 rd->argfltreguse = m->parseddesc->argfltreguse;
137 #ifdef HAS_ADDRESS_REGISTER_FILE
138 if (rd->argadrreguse < m->parseddesc->argadrreguse)
139 rd->argadrreguse = m->parseddesc->argadrreguse;
144 for (s = 0; s < cd->maxstack; s++) {
145 intalloc = -1; fltalloc = -1;
149 for (tt = 0; tt <=4; tt++) {
150 if ((t = jd->interface_map[s * 5 + tt].flags) != UNUSED) {
151 saved |= t & SAVEDVAR;
155 for (tt = 0; tt <= 4; tt++) {
157 if (jd->interface_map[s * 5 + t].flags == UNUSED)
161 regoff = -1; /* XXX for debugging */
163 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
164 intregsneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
166 #if defined(HAS_4BYTE_STACKSLOT)
167 memneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
170 #if defined(HAS_ADDRESS_REGISTER_FILE)
171 if (IS_ADR_TYPE(t)) {
172 if (!jd->isleafmethod
173 &&(rd->argadrreguse < ADR_ARG_CNT)) {
174 regoff = rd->argadrregs[rd->argadrreguse++];
175 } else if (rd->tmpadrreguse > 0) {
176 regoff = rd->tmpadrregs[--rd->tmpadrreguse];
177 } else if (rd->savadrreguse > 0) {
178 regoff = rd->savadrregs[--rd->savadrreguse];
181 regoff = rd->memuse++;
183 } else /* !IS_ADR_TYPE */
184 #endif /* defined(HAS_ADDRESS_REGISTER_FILE) */
186 if (IS_FLT_DBL_TYPE(t)) {
188 /* Reuse memory slot(s)/register(s) for shared interface slots */
189 flags |= jd->interface_map[fltalloc].flags & INMEMORY;
190 regoff = jd->interface_map[fltalloc].regoff;
191 } else if (rd->argfltreguse < FLT_ARG_CNT) {
192 regoff = rd->argfltregs[rd->argfltreguse++];
193 } else if (rd->tmpfltreguse > 0) {
194 regoff = rd->tmpfltregs[--rd->tmpfltreguse];
195 } else if (rd->savfltreguse > 0) {
196 regoff = rd->savfltregs[--rd->savfltreguse];
199 #if defined(ALIGN_DOUBLES_IN_MEMORY)
200 /* Align doubles in Memory */
201 if ( (memneeded) && (rd->memuse & 1))
205 rd->memuse += memneeded + 1;
207 fltalloc = s * 5 + t;
208 } else { /* !IS_FLT_DBL_TYPE(t) */
209 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
211 * for i386 put all longs in memory
213 if (IS_2_WORD_TYPE(t)) {
215 #if defined(ALIGN_LONGS_IN_MEMORY)
216 /* Align longs in Memory */
221 rd->memuse += memneeded + 1;
223 #endif /* defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE...GISTERS) */
225 /* Reuse memory slot(s)/register(s) for shared interface slots */
226 flags |= jd->interface_map[intalloc].flags & INMEMORY;
227 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
228 if (!(flags & INMEMORY)
229 && IS_2_WORD_TYPE(intalloc % 5))
230 regoff = GET_LOW_REG(
231 jd->interface_map[intalloc].regoff);
235 jd->interface_map[intalloc].regoff;
237 if (rd->argintreguse + intregsneeded
239 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
242 rd->argintregs[rd->argintreguse],
243 rd->argintregs[rd->argintreguse + 1]);
247 rd->argintregs[rd->argintreguse];
248 rd->argintreguse += intregsneeded + 1;
250 else if (rd->tmpintreguse > intregsneeded) {
251 rd->tmpintreguse -= intregsneeded + 1;
252 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
255 rd->tmpintregs[rd->tmpintreguse],
256 rd->tmpintregs[rd->tmpintreguse + 1]);
260 rd->tmpintregs[rd->tmpintreguse];
262 else if (rd->savintreguse > intregsneeded) {
263 rd->savintreguse -= intregsneeded + 1;
265 rd->savintregs[rd->savintreguse];
266 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
269 rd->savintregs[rd->savintreguse],
270 rd->savintregs[rd->savintreguse + 1]);
274 rd->savintregs[rd->savintreguse];
278 #if defined(ALIGN_LONGS_IN_MEMORY)
279 /* Align longs in Memory */
280 if ( (memneeded) && (rd->memuse & 1))
284 rd->memuse += memneeded + 1;
287 intalloc = s * 5 + t;
288 } /* if (IS_FLT_DBL_TYPE(t)) */
290 } else { /* (saved) */
291 /* now the same like above, but without a chance to take a temporary register */
292 #ifdef HAS_ADDRESS_REGISTER_FILE
293 if (IS_ADR_TYPE(t)) {
294 if (rd->savadrreguse > 0) {
295 regoff = rd->savadrregs[--rd->savadrreguse];
299 regoff = rd->memuse++;
304 if (IS_FLT_DBL_TYPE(t)) {
306 flags |= jd->interface_map[fltalloc].flags & INMEMORY;
307 regoff = jd->interface_map[fltalloc].regoff;
309 if (rd->savfltreguse > 0) {
311 rd->savfltregs[--rd->savfltreguse];
315 #if defined(ALIGN_DOUBLES_IN_MEMORY)
316 /* Align doubles in Memory */
317 if ( (memneeded) && (rd->memuse & 1))
321 rd->memuse += memneeded + 1;
323 fltalloc = s * 5 + t;
325 else { /* IS_INT_LNG */
326 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
328 * for i386 put all longs in memory
330 if (IS_2_WORD_TYPE(t)) {
332 #if defined(ALIGN_LONGS_IN_MEMORY)
333 /* Align longs in Memory */
338 rd->memuse += memneeded + 1;
343 flags |= jd->interface_map[intalloc].flags & INMEMORY;
344 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
345 if (!(flags & INMEMORY)
346 && IS_2_WORD_TYPE(intalloc % 5))
349 jd->interface_map[intalloc].regoff);
353 jd->interface_map[intalloc].regoff;
355 if (rd->savintreguse > intregsneeded) {
356 rd->savintreguse -= intregsneeded + 1;
357 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
360 rd->savintregs[rd->savintreguse],
361 rd->savintregs[rd->savintreguse + 1]);
365 rd->savintregs[rd->savintreguse];
368 #if defined(ALIGN_LONGS_IN_MEMORY)
369 /* Align longs in Memory */
370 if ( (memneeded) && (rd->memuse & 1))
374 rd->memuse += memneeded + 1;
379 } /* if (IS_FLT_DBL_TYPE(t) else */
380 } /* if (IS_ADR_TYPE(t)) else */
381 } /* if (saved) else */
385 jd->interface_map[5*s + t].flags = flags | INOUT;
386 jd->interface_map[5*s + t].regoff = regoff;
393 /* local_regalloc **************************************************************
395 Allocates registers for all local variables.
397 *******************************************************************************/
399 static void local_regalloc(jitdata *jd)
406 int intalloc, fltalloc;
408 int intregsneeded = 0;
410 int typeloop[] = { TYPE_LNG, TYPE_DBL, TYPE_INT, TYPE_FLT, TYPE_ADR };
411 int fargcnt, iargcnt;
412 #ifdef HAS_ADDRESS_REGISTER_FILE
416 /* get required compiler data */
422 if (jd->isleafmethod) {
423 methoddesc *md = m->parseddesc;
425 iargcnt = rd->argintreguse;
426 fargcnt = rd->argfltreguse;
427 #ifdef HAS_ADDRESS_REGISTER_FILE
428 aargcnt = rd->argadrreguse;
430 for (p = 0, s = 0; s < cd->maxlocals; s++, p++) {
431 intalloc = -1; fltalloc = -1;
432 for (tt = 0; tt <= 4; tt++) {
434 lm = jd->local_map[s * 5 + t];
440 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
441 intregsneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
443 #if defined(HAS_4BYTE_STACKSLOT)
444 memneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
450 * #ifdef HAS_ADDRESS_REGISTER_FILE
457 * } else { / int & lng
461 * must not to be changed!
464 #ifdef HAS_ADDRESS_REGISTER_FILE
465 if (IS_ADR_TYPE(t)) {
466 if ((p < md->paramcount) && !md->params[p].inmemory) {
468 v->vv.regoff = rd->argadrregs[md->params[p].regoff];
470 else if (rd->tmpadrreguse > 0) {
472 v->vv.regoff = rd->tmpadrregs[--rd->tmpadrreguse];
474 /* use unused argument registers as local registers */
475 else if ((p >= md->paramcount) &&
476 (aargcnt < ADR_ARG_CNT)) {
478 v->vv.regoff = rd->argadrregs[aargcnt++];
480 else if (rd->savadrreguse > 0) {
482 v->vv.regoff = rd->savadrregs[--rd->savadrreguse];
485 v->flags |= INMEMORY;
486 v->vv.regoff = rd->memuse++;
490 if (IS_FLT_DBL_TYPE(t)) {
492 v->flags = VAR(fltalloc)->flags;
493 v->vv.regoff = VAR(fltalloc)->vv.regoff;
495 #if !defined(SUPPORT_PASS_FLOATARGS_IN_INTREGS)
496 /* We can only use float arguments as local variables,
497 * if we do not pass them in integer registers. */
498 else if ((p < md->paramcount) &&
499 !md->params[p].inmemory) {
501 v->vv.regoff = rd->argfltregs[md->params[p].regoff];
504 else if (rd->tmpfltreguse > 0) {
506 v->vv.regoff = rd->tmpfltregs[--rd->tmpfltreguse];
508 /* use unused argument registers as local registers */
509 else if ((p >= md->paramcount) &&
510 (fargcnt < FLT_ARG_CNT)) {
512 v->vv.regoff = rd->argfltregs[fargcnt];
515 else if (rd->savfltreguse > 0) {
517 v->vv.regoff = rd->savfltregs[--rd->savfltreguse];
521 #if defined(ALIGN_DOUBLES_IN_MEMORY)
522 /* Align doubles in Memory */
523 if ( (memneeded) && (rd->memuse & 1))
526 v->vv.regoff = rd->memuse;
527 rd->memuse += memneeded + 1;
529 fltalloc = jd->local_map[s * 5 + t];
532 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
534 * for i386 put all longs in memory
536 if (IS_2_WORD_TYPE(t)) {
538 #if defined(ALIGN_LONGS_IN_MEMORY)
539 /* Align longs in Memory */
543 v->vv.regoff = rd->memuse;
544 rd->memuse += memneeded + 1;
549 v->flags = VAR(intalloc)->flags;
550 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
551 if (!(v->flags & INMEMORY)
552 && IS_2_WORD_TYPE(VAR(intalloc)->type))
553 v->vv.regoff = GET_LOW_REG(
554 VAR(intalloc)->vv.regoff);
557 v->vv.regoff = VAR(intalloc)->vv.regoff;
559 else if ((p < md->paramcount) &&
560 !md->params[p].inmemory) {
562 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
563 if (IS_2_WORD_TYPE(t))
564 v->vv.regoff = PACK_REGS(
565 rd->argintregs[GET_LOW_REG(md->params[p].regoff)],
566 rd->argintregs[GET_HIGH_REG(md->params[p].regoff)]);
570 rd->argintregs[md->params[p].regoff];
572 else if (rd->tmpintreguse > intregsneeded) {
573 rd->tmpintreguse -= intregsneeded + 1;
575 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
577 v->vv.regoff = PACK_REGS(
578 rd->tmpintregs[rd->tmpintreguse],
579 rd->tmpintregs[rd->tmpintreguse + 1]);
583 rd->tmpintregs[rd->tmpintreguse];
586 * use unused argument registers as local registers
588 else if ((p >= m->parseddesc->paramcount) &&
589 (iargcnt + intregsneeded < INT_ARG_CNT)) {
591 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
593 v->vv.regoff=PACK_REGS(
594 rd->argintregs[iargcnt],
595 rd->argintregs[iargcnt + 1]);
598 v->vv.regoff = rd->argintregs[iargcnt];
599 iargcnt += intregsneeded + 1;
601 else if (rd->savintreguse > intregsneeded) {
602 rd->savintreguse -= intregsneeded + 1;
604 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
606 v->vv.regoff = PACK_REGS(
607 rd->savintregs[rd->savintreguse],
608 rd->savintregs[rd->savintreguse + 1]);
611 v->vv.regoff =rd->savintregs[rd->savintreguse];
615 #if defined(ALIGN_LONGS_IN_MEMORY)
616 /* Align longs in Memory */
617 if ( (memneeded) && (rd->memuse & 1))
620 v->vv.regoff = rd->memuse;
621 rd->memuse += memneeded + 1;
624 intalloc = jd->local_map[s * 5 + t];
626 #ifdef HAS_ADDRESS_REGISTER_FILE
629 } /* for (tt=0;...) */
631 /* If the current parameter is a 2-word type, the next local slot */
634 if (p < md->paramcount)
635 if (IS_2_WORD_TYPE(md->paramtypes[p].type))
641 for (s = 0; s < cd->maxlocals; s++) {
642 intalloc = -1; fltalloc = -1;
643 for (tt=0; tt<=4; tt++) {
646 lm = jd->local_map[s * 5 + t];
652 #ifdef SUPPORT_COMBINE_INTEGER_REGISTERS
653 intregsneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
655 #if defined(HAS_4BYTE_STACKSLOT)
656 memneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
658 #ifdef HAS_ADDRESS_REGISTER_FILE
659 if ( IS_ADR_TYPE(t) ) {
660 if (rd->savadrreguse > 0) {
662 v->vv.regoff = rd->savadrregs[--rd->savadrreguse];
666 v->vv.regoff = rd->memuse++;
670 if (IS_FLT_DBL_TYPE(t)) {
672 v->flags = VAR(fltalloc)->flags;
673 v->vv.regoff = VAR(fltalloc)->vv.regoff;
675 else if (rd->savfltreguse > 0) {
677 v->vv.regoff = rd->savfltregs[--rd->savfltreguse];
681 #if defined(ALIGN_DOUBLES_IN_MEMORY)
682 /* Align doubles in Memory */
683 if ( (memneeded) && (rd->memuse & 1))
686 v->vv.regoff = rd->memuse;
687 rd->memuse += memneeded + 1;
689 fltalloc = jd->local_map[s * 5 + t];
692 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
694 * for i386 put all longs in memory
696 if (IS_2_WORD_TYPE(t)) {
698 #if defined(ALIGN_LONGS_IN_MEMORY)
699 /* Align longs in Memory */
703 v->vv.regoff = rd->memuse;
704 rd->memuse += memneeded + 1;
708 v->flags = VAR(intalloc)->flags;
709 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
710 if (!(v->flags & INMEMORY)
711 && IS_2_WORD_TYPE(VAR(intalloc)->type))
712 v->vv.regoff = GET_LOW_REG(
713 VAR(intalloc)->vv.regoff);
716 v->vv.regoff = VAR(intalloc)->vv.regoff;
718 else if (rd->savintreguse > intregsneeded) {
719 rd->savintreguse -= intregsneeded+1;
721 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
723 v->vv.regoff = PACK_REGS(
724 rd->savintregs[rd->savintreguse],
725 rd->savintregs[rd->savintreguse + 1]);
728 v->vv.regoff =rd->savintregs[rd->savintreguse];
732 #if defined(ALIGN_LONGS_IN_MEMORY)
733 /* Align longs in Memory */
734 if ( (memneeded) && (rd->memuse & 1))
737 v->vv.regoff = rd->memuse;
738 rd->memuse += memneeded + 1;
740 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
743 intalloc = jd->local_map[s * 5 + t];
745 #ifdef HAS_ADDRESS_REGISTER_FILE
754 static void reg_init_temp(jitdata *jd, registerdata *rd)
757 #if defined(HAS_4BYTE_STACKSLOT)
758 rd->freememtop_2 = 0;
761 rd->freetmpinttop = 0;
762 rd->freesavinttop = 0;
763 rd->freetmpflttop = 0;
764 rd->freesavflttop = 0;
765 #ifdef HAS_ADDRESS_REGISTER_FILE
766 rd->freetmpadrtop = 0;
767 rd->freesavadrtop = 0;
770 rd->freearginttop = 0;
771 rd->freeargflttop = 0;
772 #ifdef HAS_ADDRESS_REGISTER_FILE
773 rd->freeargadrtop = 0;
776 rd->regcopycount = DMNEW(int, INT_REG_CNT + FLT_REG_CNT);
777 MZERO(rd->regcopycount, int, INT_REG_CNT + FLT_REG_CNT);
779 /* memcopycount is dynamically allocated when needed */
781 rd->memcopycount = NULL;
782 rd->memcopycountsize = 0;
786 #define reg_new_temp(jd,index) \
787 if ( (index >= jd->localcount) \
788 && (!(VAR(index)->flags & (INOUT | PREALLOC))) ) \
789 reg_new_temp_func(jd, index)
791 static void reg_new_temp_func(jitdata *jd, s4 index)
802 /* Try to allocate a saved register if there is no temporary one */
803 /* available. This is what happens during the second run. */
804 tryagain = (v->flags & SAVEDVAR) ? 1 : 2;
806 #ifdef SUPPORT_COMBINE_INTEGER_REGISTERS
807 intregsneeded = (IS_2_WORD_TYPE(v->type)) ? 1 : 0;
811 #if defined(HAS_4BYTE_STACKSLOT)
812 memneeded = (IS_2_WORD_TYPE(v->type)) ? 1 : 0;
817 for(; tryagain; --tryagain) {
819 if (!(v->flags & SAVEDVAR))
820 v->flags |= SAVEDTMP;
821 #ifdef HAS_ADDRESS_REGISTER_FILE
822 if (IS_ADR_TYPE(v->type)) {
823 if (rd->freesavadrtop > 0) {
824 v->vv.regoff = rd->freesavadrregs[--rd->freesavadrtop];
826 } else if (rd->savadrreguse > 0) {
827 v->vv.regoff = rd->savadrregs[--rd->savadrreguse];
833 if (IS_FLT_DBL_TYPE(v->type)) {
834 if (rd->freesavflttop > 0) {
835 v->vv.regoff = rd->freesavfltregs[--rd->freesavflttop];
837 } else if (rd->savfltreguse > 0) {
838 v->vv.regoff = rd->savfltregs[--rd->savfltreguse];
842 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
844 * for i386 put all longs in memory
846 if (!IS_2_WORD_TYPE(v->type))
849 if (rd->freesavinttop > intregsneeded) {
850 rd->freesavinttop -= intregsneeded + 1;
851 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
853 v->vv.regoff = PACK_REGS(
854 rd->freesavintregs[rd->freesavinttop],
855 rd->freesavintregs[rd->freesavinttop + 1]);
859 rd->freesavintregs[rd->freesavinttop];
861 } else if (rd->savintreguse > intregsneeded) {
862 rd->savintreguse -= intregsneeded + 1;
863 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
865 v->vv.regoff = PACK_REGS(
866 rd->savintregs[rd->savintreguse],
867 rd->savintregs[rd->savintreguse + 1]);
870 v->vv.regoff = rd->savintregs[rd->savintreguse];
876 } else { /* tryagain == 2 */
877 #ifdef HAS_ADDRESS_REGISTER_FILE
878 if (IS_ADR_TYPE(v->type)) {
879 if (rd->freetmpadrtop > 0) {
880 v->vv.regoff = rd->freetmpadrregs[--rd->freetmpadrtop];
882 } else if (rd->tmpadrreguse > 0) {
883 v->vv.regoff = rd->tmpadrregs[--rd->tmpadrreguse];
889 if (IS_FLT_DBL_TYPE(v->type)) {
890 if (rd->freeargflttop > 0) {
891 v->vv.regoff = rd->freeargfltregs[--rd->freeargflttop];
894 } else if (rd->argfltreguse < FLT_ARG_CNT) {
895 v->vv.regoff = rd->argfltregs[rd->argfltreguse++];
898 } else if (rd->freetmpflttop > 0) {
899 v->vv.regoff = rd->freetmpfltregs[--rd->freetmpflttop];
901 } else if (rd->tmpfltreguse > 0) {
902 v->vv.regoff = rd->tmpfltregs[--rd->tmpfltreguse];
907 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
909 * for i386 put all longs in memory
911 if (!IS_2_WORD_TYPE(v->type))
914 if (rd->freearginttop > intregsneeded) {
915 rd->freearginttop -= intregsneeded + 1;
917 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
919 v->vv.regoff = PACK_REGS(
920 rd->freeargintregs[rd->freearginttop],
921 rd->freeargintregs[rd->freearginttop + 1]);
925 rd->freeargintregs[rd->freearginttop];
927 } else if (rd->argintreguse
928 < INT_ARG_CNT - intregsneeded) {
929 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
931 v->vv.regoff = PACK_REGS(
932 rd->argintregs[rd->argintreguse],
933 rd->argintregs[rd->argintreguse + 1]);
936 v->vv.regoff = rd->argintregs[rd->argintreguse];
938 rd->argintreguse += intregsneeded + 1;
940 } else if (rd->freetmpinttop > intregsneeded) {
941 rd->freetmpinttop -= intregsneeded + 1;
942 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
944 v->vv.regoff = PACK_REGS(
945 rd->freetmpintregs[rd->freetmpinttop],
946 rd->freetmpintregs[rd->freetmpinttop + 1]);
949 v->vv.regoff = rd->freetmpintregs[rd->freetmpinttop];
951 } else if (rd->tmpintreguse > intregsneeded) {
952 rd->tmpintreguse -= intregsneeded + 1;
953 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
955 v->vv.regoff = PACK_REGS(
956 rd->tmpintregs[rd->tmpintreguse],
957 rd->tmpintregs[rd->tmpintreguse + 1]);
960 v->vv.regoff = rd->tmpintregs[rd->tmpintreguse];
963 } /* if (!IS_2_WORD_TYPE(s->type)) */
964 } /* if (IS_FLT_DBL_TYPE(s->type)) */
965 } /* if (IS_ADR_TYPE(s->type)) */
966 } /* if (tryagain == 1) else */
967 } /* for(; tryagain; --tryagain) */
969 #if defined(HAS_4BYTE_STACKSLOT)
970 if ((memneeded == 1) && (rd->freememtop_2 > 0)) {
972 v->vv.regoff = rd->freemem_2[rd->freememtop_2];
974 #endif /*defined(HAS_4BYTE_STACKSLOT) */
975 if ((memneeded == 0) && (rd->freememtop > 0)) {
977 v->vv.regoff = rd->freemem[rd->freememtop];
979 #if defined(ALIGN_LONGS_IN_MEMORY) || defined(ALIGN_DOUBLES_IN_MEMORY)
980 /* align 2 Word Types */
981 if ((memneeded) && ((rd->memuse & 1) == 1)) {
982 /* Put patched memory slot on freemem */
983 rd->freemem[rd->freememtop++] = rd->memuse;
986 #endif /* defined(ALIGN_LONGS_IN_MEMORY) || defined(ALIGN_DOUBLES_IN_MEMORY) */
987 v->vv.regoff = rd->memuse;
988 rd->memuse += memneeded + 1;
990 v->flags |= INMEMORY;
994 #define reg_free_temp(jd,index) \
995 if ((index > jd->localcount) \
996 && (!(VAR(index)->flags & (INOUT | PREALLOC)))) \
997 reg_free_temp_func(jd, index)
999 /* Do not free regs/memory locations used by Stackslots flagged STCOPY! There is still another Stackslot */
1000 /* alive using this reg/memory location */
1002 static void reg_free_temp_func(jitdata *jd, s4 index)
1012 /* if this is a copy of another variable, just decrement the copy counter */
1014 /* XXX split reg/mem variables on arm may need special handling here */
1016 if (v->flags & INMEMORY) {
1017 if (v->vv.regoff < rd->memcopycountsize && rd->memcopycount[v->vv.regoff]) {
1018 rd->memcopycount[v->vv.regoff]--;
1023 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
1024 if (rd->regcopycount[GET_LOW_REG(v->vv.regoff)]) {
1025 rd->regcopycount[GET_LOW_REG(v->vv.regoff)]--;
1029 if (rd->regcopycount[v->vv.regoff]) {
1030 rd->regcopycount[v->vv.regoff]--;
1036 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
1037 intregsneeded = (IS_2_WORD_TYPE(v->type)) ? 1 : 0;
1042 #if defined(HAS_4BYTE_STACKSLOT)
1043 memneeded = (IS_2_WORD_TYPE(v->type)) ? 1 : 0;
1048 if (v->flags & INMEMORY) {
1049 #if defined(HAS_4BYTE_STACKSLOT)
1050 if (memneeded > 0) {
1051 rd->freemem_2[rd->freememtop_2] = v->vv.regoff;
1056 rd->freemem[rd->freememtop] = v->vv.regoff;
1060 #ifdef HAS_ADDRESS_REGISTER_FILE
1061 } else if (IS_ADR_TYPE(v->type)) {
1062 if (v->flags & (SAVEDVAR | SAVEDTMP)) {
1063 /* v->flags &= ~SAVEDTMP; */
1064 rd->freesavadrregs[rd->freesavadrtop++] = v->vv.regoff;
1066 rd->freetmpadrregs[rd->freetmpadrtop++] = v->vv.regoff;
1068 } else if (IS_FLT_DBL_TYPE(v->type)) {
1069 if (v->flags & (SAVEDVAR | SAVEDTMP)) {
1070 /* v->flags &= ~SAVEDTMP; */
1071 rd->freesavfltregs[rd->freesavflttop++] = v->vv.regoff;
1072 } else if (v->flags & TMPARG) {
1073 /* v->flags &= ~TMPARG; */
1074 rd->freeargfltregs[rd->freeargflttop++] = v->vv.regoff;
1076 rd->freetmpfltregs[rd->freetmpflttop++] = v->vv.regoff;
1077 } else { /* IS_INT_LNG_TYPE */
1078 if (v->flags & (SAVEDVAR | SAVEDTMP)) {
1079 /* v->flags &= ~SAVEDTMP; */
1080 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
1081 if (intregsneeded) {
1082 rd->freesavintregs[rd->freesavinttop] =
1083 GET_LOW_REG(v->vv.regoff);
1084 rd->freesavintregs[rd->freesavinttop + 1] =
1085 GET_HIGH_REG(v->vv.regoff);
1088 rd->freesavintregs[rd->freesavinttop] = v->vv.regoff;
1089 rd->freesavinttop += intregsneeded + 1;
1091 } else if (v->flags & TMPARG) {
1092 /* s->flags &= ~TMPARG; */
1093 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
1094 if (intregsneeded) {
1095 rd->freeargintregs[rd->freearginttop] =
1096 GET_LOW_REG(v->vv.regoff);
1097 rd->freeargintregs[rd->freearginttop + 1] =
1098 GET_HIGH_REG(v->vv.regoff);
1101 rd->freeargintregs[rd->freearginttop] = v->vv.regoff;
1102 rd->freearginttop += intregsneeded + 1;
1104 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
1105 if (intregsneeded) {
1106 rd->freetmpintregs[rd->freetmpinttop] =
1107 GET_LOW_REG(v->vv.regoff);
1108 rd->freetmpintregs[rd->freetmpinttop + 1] =
1109 GET_HIGH_REG(v->vv.regoff);
1112 rd->freetmpintregs[rd->freetmpinttop] = v->vv.regoff;
1113 rd->freetmpinttop += intregsneeded + 1;
1119 static bool reg_alloc_dup(jitdata *jd, s4 srcindex, s4 dstindex)
1124 /* do not coalesce local variables here */
1126 if (srcindex <= jd->localcount || dstindex <= jd->localcount)
1132 /* do not coalesce in/out vars or preallocated variables here */
1134 if ((sv->flags | dv->flags) & (INOUT | PREALLOC))
1137 /* if the source is in memory, we can coalesce in any case */
1139 if (sv->flags & INMEMORY) {
1140 dv->flags |= INMEMORY;
1141 dv->vv.regoff = sv->vv.regoff;
1145 /* we do not allocate a REG_TMP to a REG_SAV variable */
1147 if ((sv->flags & SAVEDVAR) != (dv->flags & SAVEDVAR))
1151 dv->vv.regoff = sv->vv.regoff;
1152 dv->flags |= sv->flags & (SAVEDTMP | TMPARG);
1158 /* allocate_scratch_registers **************************************************
1160 Allocate temporary (non-interface, non-local) registers.
1162 *******************************************************************************/
1164 static void new_allocate_scratch_registers(jitdata *jd)
1172 builtintable_entry *bte;
1177 /* get required compiler data */
1182 /* initialize temp registers */
1184 reg_init_temp(jd, rd);
1186 bptr = jd->new_basicblocks;
1188 while (bptr != NULL) {
1189 if (bptr->flags >= BBREACHED) {
1191 /* set allocation of invars */
1193 for (i=0; i<bptr->indepth; ++i)
1195 v = VAR(bptr->invars[i]);
1197 v->vv.regoff = jd->interface_map[5*i + v->type].regoff;
1198 v->flags = jd->interface_map[5*i + v->type].flags;
1201 /* set allocation of outvars */
1203 for (i=0; i<bptr->outdepth; ++i)
1205 v = VAR(bptr->outvars[i]);
1207 v->vv.regoff = jd->interface_map[5*i + v->type].regoff;
1208 v->flags = jd->interface_map[5*i + v->type].flags;
1211 /* iterate over ICMDS to allocate temporary variables */
1213 iptr = bptr->iinstr;
1216 while (--len >= 0) {
1217 switch (iptr->opc) {
1222 #if !defined(NDEBUG)
1223 /* avoid problems with show_allocation */
1224 VAROP(iptr->dst)->vv.regoff = 0;
1227 case ICMD_CHECKNULL:
1232 case ICMD_PUTSTATICCONST:
1233 case ICMD_INLINE_START:
1234 case ICMD_INLINE_END:
1235 case ICMD_INLINE_GOTO:
1238 /* pop 0 push 1 const */
1246 /* pop 0 push 1 load */
1253 reg_new_temp(jd, iptr->dst.varindex);
1267 reg_free_temp(jd, iptr->sx.s23.s2.varindex);
1268 reg_free_temp(jd, iptr->s1.varindex);
1269 reg_new_temp(jd, iptr->dst.varindex);
1283 reg_free_temp(jd, iptr->sx.s23.s3.varindex);
1284 reg_free_temp(jd, iptr->sx.s23.s2.varindex);
1285 reg_free_temp(jd, iptr->s1.varindex);
1288 /* pop 1 push 0 store */
1308 case ICMD_PUTSTATIC:
1309 case ICMD_PUTFIELDCONST:
1311 /* pop 1 push 0 branch */
1314 case ICMD_IFNONNULL:
1330 /* pop 1 push 0 table branch */
1332 case ICMD_TABLESWITCH:
1333 case ICMD_LOOKUPSWITCH:
1335 case ICMD_MONITORENTER:
1336 case ICMD_MONITOREXIT:
1337 reg_free_temp(jd, iptr->s1.varindex);
1340 /* pop 2 push 0 branch */
1342 case ICMD_IF_ICMPEQ:
1343 case ICMD_IF_ICMPNE:
1344 case ICMD_IF_ICMPLT:
1345 case ICMD_IF_ICMPGE:
1346 case ICMD_IF_ICMPGT:
1347 case ICMD_IF_ICMPLE:
1349 case ICMD_IF_LCMPEQ:
1350 case ICMD_IF_LCMPNE:
1351 case ICMD_IF_LCMPLT:
1352 case ICMD_IF_LCMPGE:
1353 case ICMD_IF_LCMPGT:
1354 case ICMD_IF_LCMPLE:
1356 case ICMD_IF_FCMPEQ:
1357 case ICMD_IF_FCMPNE:
1359 case ICMD_IF_FCMPL_LT:
1360 case ICMD_IF_FCMPL_GE:
1361 case ICMD_IF_FCMPL_GT:
1362 case ICMD_IF_FCMPL_LE:
1364 case ICMD_IF_FCMPG_LT:
1365 case ICMD_IF_FCMPG_GE:
1366 case ICMD_IF_FCMPG_GT:
1367 case ICMD_IF_FCMPG_LE:
1369 case ICMD_IF_DCMPEQ:
1370 case ICMD_IF_DCMPNE:
1372 case ICMD_IF_DCMPL_LT:
1373 case ICMD_IF_DCMPL_GE:
1374 case ICMD_IF_DCMPL_GT:
1375 case ICMD_IF_DCMPL_LE:
1377 case ICMD_IF_DCMPG_LT:
1378 case ICMD_IF_DCMPG_GE:
1379 case ICMD_IF_DCMPG_GT:
1380 case ICMD_IF_DCMPG_LE:
1382 case ICMD_IF_ACMPEQ:
1383 case ICMD_IF_ACMPNE:
1391 case ICMD_IASTORECONST:
1392 case ICMD_LASTORECONST:
1393 case ICMD_AASTORECONST:
1394 case ICMD_BASTORECONST:
1395 case ICMD_CASTORECONST:
1396 case ICMD_SASTORECONST:
1397 reg_free_temp(jd, iptr->sx.s23.s2.varindex);
1398 reg_free_temp(jd, iptr->s1.varindex);
1401 /* pop 0 push 1 copy */
1404 /* src === dst->prev (identical Stackslot Element) */
1405 /* src --> dst (copied value, take same reg/mem) */
1407 if (!reg_alloc_dup(jd, iptr->s1.varindex, iptr->dst.varindex)) {
1408 reg_new_temp(jd, iptr->dst.varindex);
1410 v = VAROP(iptr->dst);
1412 if (v->flags & INMEMORY) {
1413 if (v->vv.regoff >= rd->memcopycountsize) {
1414 int newsize = (v->vv.regoff + 1) * 2;
1415 i = rd->memcopycountsize;
1416 rd->memcopycount = DMREALLOC(rd->memcopycount, int, i, newsize);
1417 MZERO(rd->memcopycount + i, int, newsize - i);
1418 rd->memcopycountsize = newsize;
1420 rd->memcopycount[v->vv.regoff]++;
1423 /* XXX split reg/mem variables on arm may need special handling here */
1425 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
1426 rd->regcopycount[GET_LOW_REG(v->vv.regoff)]++;
1428 rd->regcopycount[v->vv.regoff]++;
1434 /* pop 1 push 1 move */
1437 if (!reg_alloc_dup(jd, iptr->s1.varindex, iptr->dst.varindex)) {
1438 reg_new_temp(jd, iptr->dst.varindex);
1439 reg_free_temp(jd, iptr->s1.varindex);
1489 reg_free_temp(jd, iptr->sx.s23.s2.varindex);
1490 reg_free_temp(jd, iptr->s1.varindex);
1491 reg_new_temp(jd, iptr->dst.varindex);
1496 case ICMD_IADDCONST:
1497 case ICMD_ISUBCONST:
1498 case ICMD_IMULCONST:
1502 case ICMD_IANDCONST:
1504 case ICMD_IXORCONST:
1505 case ICMD_ISHLCONST:
1506 case ICMD_ISHRCONST:
1507 case ICMD_IUSHRCONST:
1509 case ICMD_LADDCONST:
1510 case ICMD_LSUBCONST:
1511 case ICMD_LMULCONST:
1515 case ICMD_LANDCONST:
1517 case ICMD_LXORCONST:
1518 case ICMD_LSHLCONST:
1519 case ICMD_LSHRCONST:
1520 case ICMD_LUSHRCONST:
1525 case ICMD_INT2SHORT:
1543 case ICMD_CHECKCAST:
1545 case ICMD_ARRAYLENGTH:
1546 case ICMD_INSTANCEOF:
1549 case ICMD_ANEWARRAY:
1552 reg_free_temp(jd, iptr->s1.varindex);
1553 reg_new_temp(jd, iptr->dst.varindex);
1558 case ICMD_GETSTATIC:
1561 reg_new_temp(jd, iptr->dst.varindex);
1564 /* pop many push any */
1566 case ICMD_INVOKESTATIC:
1567 case ICMD_INVOKESPECIAL:
1568 case ICMD_INVOKEVIRTUAL:
1569 case ICMD_INVOKEINTERFACE:
1570 INSTRUCTION_GET_METHODDESC(iptr,md);
1572 argp = iptr->sx.s23.s2.args;
1574 reg_free_temp(jd, *argp);
1577 if (md->returntype.type != TYPE_VOID)
1578 reg_new_temp(jd, iptr->dst.varindex);
1582 bte = iptr->sx.s23.s3.bte;
1585 argp = iptr->sx.s23.s2.args;
1587 reg_free_temp(jd, *argp);
1590 if (md->returntype.type != TYPE_VOID)
1591 reg_new_temp(jd, iptr->dst.varindex);
1594 case ICMD_MULTIANEWARRAY:
1595 i = iptr->s1.argcount;
1596 argp = iptr->sx.s23.s2.args;
1598 reg_free_temp(jd, *argp);
1601 reg_new_temp(jd, iptr->dst.varindex);
1606 new_internalerror("Unknown ICMD %d during register allocation",
1611 } /* while instructions */
1614 } /* while blocks */
1618 #if defined(ENABLE_STATISTICS)
1619 void reg_make_statistics(jitdata *jd)
1626 stackptr src, src_old;
1630 int size_interface; /* == maximum size of in/out stack at basic block boundaries */
1634 /* get required compiler data */
1644 /* count how many local variables are held in memory or register */
1645 for(i=0; i < jd->localcount; i++) {
1646 if (VAR(i)->flags & INMEMORY) {
1647 count_locals_spilled++;
1651 count_locals_register++;
1655 /* count how many stack slots are held in memory or register */
1657 bptr = jd->new_basicblocks;
1659 while (bptr != NULL) {
1660 if (bptr->flags >= BBREACHED) {
1662 #if defined(ENABLE_LSRA) || defined(ENABLE_SSA)
1665 /* check for memory moves from interface to BB instack */
1666 len = bptr->indepth;
1668 if (len > size_interface) size_interface = len;
1672 var = VAR(bptr->invars[len]);
1674 /* invars statistics (currently none) */
1677 /* check for memory moves from BB outstack to interface */
1678 len = bptr->outdepth;
1679 if (len > size_interface) size_interface = len;
1683 var = VAR(bptr->outvars[len]);
1685 /* outvars statistics (currently none) */
1687 #if defined(ENABLE_LSRA) || defined(ENABLE_SSA)
1693 dst = bptr->instack;
1694 iptr = bptr->iinstr;
1698 while (--len >= 0) {
1700 dst = iptr->dst.var;
1702 if ((src!= NULL) && (src != src_old)) { /* new stackslot */
1703 switch (src->varkind) {
1706 if (!(src->flags & INMEMORY))
1707 count_ss_register++;
1713 /* case LOCALVAR: */
1714 /* if (!(rd->locals[src->varnum][src->type].flags & INMEMORY)) */
1715 /* count_ss_register++; */
1717 /* count_ss_spilled++; */
1720 if (!(src->flags & INMEMORY))
1721 count_argument_mem_ss++;
1723 count_argument_reg_ss++;
1727 /* if (IS_FLT_DBL_TYPE(src->type)) { */
1728 /* if (src->varnum < FLT_ARG_CNT) { */
1729 /* count_ss_register++; */
1733 /* #if defined(__POWERPC__) */
1734 /* if (src->varnum < INT_ARG_CNT - (IS_2_WORD_TYPE(src->type) != 0)) { */
1736 /* if (src->varnum < INT_ARG_CNT) { */
1738 /* count_ss_register++; */
1742 /* count_ss_spilled++; */
1749 } /* while instructions */
1754 } /* while blocks */
1756 count_interface_size += size_interface; /* accummulate the size of the interface (between bb boundaries) */
1757 if (in_register) count_method_in_register++;
1759 printf("INREGISTER: %s%s%s\n",m->class->name->text, m->name->text, m->descriptor->text);
1762 #endif /* defined(ENABLE_STATISTICS) */
1766 * These are local overrides for various environment variables in Emacs.
1767 * Please do not remove this and leave it at the end of the file, where
1768 * Emacs will automagically detect them.
1769 * ---------------------------------------------------------------------
1772 * indent-tabs-mode: t
1776 * vim:noexpandtab:sw=4:ts=4: