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 5131 2006-07-14 16:54:11Z 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)
77 /* There is a problem with the use of unused float argument
78 registers in leafmethods for stackslots on c7 (2 * Dual Core
79 AMD Opteron(tm) Processor 270) - runtime for the jvm98 _mtrt
80 benchmark is heaviliy increased. This could be prevented by
81 setting rd->argfltreguse to FLT_ARG_CNT before calling
82 allocate_scratch_registers and setting it back to the original
83 value before calling local_regalloc. */
85 newjd = DNEW(jitdata);
87 newjd->rd = jd->new_rd;
89 interface_regalloc(newjd);
90 new_allocate_scratch_registers(newjd);
91 local_regalloc(newjd);
98 bool regalloc(jitdata *jd)
100 /* There is a problem with the use of unused float argument
101 registers in leafmethods for stackslots on c7 (2 * Dual Core
102 AMD Opteron(tm) Processor 270) - runtime for the jvm98 _mtrt
103 benchmark is heaviliy increased. This could be prevented by
104 setting rd->argfltreguse to FLT_ARG_CNT before calling
105 allocate_scratch_registers and setting it back to the original
106 value before calling local_regalloc. */
108 interface_regalloc(jd);
109 allocate_scratch_registers(jd);
118 /* interface_regalloc **********************************************************
120 Allocates registers for all interface variables.
122 *******************************************************************************/
124 static void interface_regalloc(jitdata *jd)
131 int intalloc, fltalloc; /* Remember allocated Register/Memory offset */
132 /* in case a more vars are packed into this interface slot */
134 int intregsneeded = 0;
136 /* allocate LNG and DBL Types first to ensure 2 memory slots or registers */
137 /* on HAS_4BYTE_STACKSLOT architectures */
138 int typeloop[] = { TYPE_LNG, TYPE_DBL, TYPE_INT, TYPE_FLT, TYPE_ADR };
140 /* get required compiler data */
146 /* rd->memuse was already set in stack.c to allocate stack space
147 for passing arguments to called methods. */
149 #if defined(__I386__)
150 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
151 /* reserve 0(%esp) for Monitorenter/exit Argument on i386 */
157 if (jd->isleafmethod) {
158 /* Reserve argument register, which will be used for Locals acting */
160 if (rd->argintreguse < m->parseddesc->argintreguse)
161 rd->argintreguse = m->parseddesc->argintreguse;
162 if (rd->argfltreguse < m->parseddesc->argfltreguse)
163 rd->argfltreguse = m->parseddesc->argfltreguse;
164 #ifdef HAS_ADDRESS_REGISTER_FILE
165 if (rd->argadrreguse < m->parseddesc->argadrreguse)
166 rd->argadrreguse = m->parseddesc->argadrreguse;
171 for (s = 0; s < cd->maxstack; s++) {
172 intalloc = -1; fltalloc = -1;
173 saved = (rd->interfaces[s][TYPE_INT].flags |
174 rd->interfaces[s][TYPE_LNG].flags |
175 rd->interfaces[s][TYPE_FLT].flags |
176 rd->interfaces[s][TYPE_DBL].flags |
177 rd->interfaces[s][TYPE_ADR].flags) & SAVEDVAR;
179 for (tt = 0; tt <= 4; tt++) {
181 v = &rd->interfaces[s][t];
183 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
184 intregsneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
186 #if defined(HAS_4BYTE_STACKSLOT)
187 memneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
190 #if defined(HAS_ADDRESS_REGISTER_FILE)
191 if (IS_ADR_TYPE(t)) {
192 if (!jd->isleafmethod
193 &&(rd->argadrreguse < ADR_ARG_CNT)) {
194 v->regoff = rd->argadrregs[rd->argadrreguse++];
195 } else if (rd->tmpadrreguse > 0) {
196 v->regoff = rd->tmpadrregs[--rd->tmpadrreguse];
197 } else if (rd->savadrreguse > 0) {
198 v->regoff = rd->savadrregs[--rd->savadrreguse];
200 v->flags |= INMEMORY;
201 v->regoff = rd->memuse++;
203 } else /* !IS_ADR_TYPE */
204 #endif /* defined(HAS_ADDRESS_REGISTER_FILE) */
206 if (IS_FLT_DBL_TYPE(t)) {
208 /* Reuse memory slot(s)/register(s) for shared interface slots */
209 v->flags |= rd->interfaces[s][fltalloc].flags
211 v->regoff = rd->interfaces[s][fltalloc].regoff;
212 } else if (rd->argfltreguse < FLT_ARG_CNT) {
213 v->regoff = rd->argfltregs[rd->argfltreguse++];
214 } else if (rd->tmpfltreguse > 0) {
215 v->regoff = rd->tmpfltregs[--rd->tmpfltreguse];
216 } else if (rd->savfltreguse > 0) {
217 v->regoff = rd->savfltregs[--rd->savfltreguse];
219 v->flags |= INMEMORY;
220 #if defined(ALIGN_DOUBLES_IN_MEMORY)
221 /* Align doubles in Memory */
222 if ( (memneeded) && (rd->memuse & 1))
225 v->regoff = rd->memuse;
226 rd->memuse += memneeded + 1;
229 } else { /* !IS_FLT_DBL_TYPE(t) */
230 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
232 * for i386 put all longs in memory
234 if (IS_2_WORD_TYPE(t)) {
235 v->flags |= INMEMORY;
236 #if defined(ALIGN_LONGS_IN_MEMORY)
237 /* Align longs in Memory */
241 v->regoff = rd->memuse;
242 rd->memuse += memneeded + 1;
244 #endif /* defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE...GISTERS) */
246 /* Reuse memory slot(s)/register(s) for shared interface slots */
248 rd->interfaces[s][intalloc].flags
250 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
251 if (!(v->flags & INMEMORY)
252 && IS_2_WORD_TYPE(intalloc))
253 v->regoff = GET_LOW_REG(
254 rd->interfaces[s][intalloc].regoff);
258 rd->interfaces[s][intalloc].regoff;
260 if (rd->argintreguse + intregsneeded
262 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
265 rd->argintregs[rd->argintreguse],
266 rd->argintregs[rd->argintreguse + 1]);
270 rd->argintregs[rd->argintreguse];
271 rd->argintreguse += intregsneeded + 1;
273 else if (rd->tmpintreguse > intregsneeded) {
274 rd->tmpintreguse -= intregsneeded + 1;
275 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
278 rd->tmpintregs[rd->tmpintreguse],
279 rd->tmpintregs[rd->tmpintreguse + 1]);
283 rd->tmpintregs[rd->tmpintreguse];
285 else if (rd->savintreguse > intregsneeded) {
286 rd->savintreguse -= intregsneeded + 1;
288 rd->savintregs[rd->savintreguse];
289 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
292 rd->savintregs[rd->savintreguse],
293 rd->savintregs[rd->savintreguse + 1]);
297 rd->savintregs[rd->savintreguse];
300 v->flags |= INMEMORY;
301 #if defined(ALIGN_LONGS_IN_MEMORY)
302 /* Align longs in Memory */
303 if ( (memneeded) && (rd->memuse & 1))
306 v->regoff = rd->memuse;
307 rd->memuse += memneeded + 1;
311 } /* if (IS_FLT_DBL_TYPE(t)) */
313 } else { /* (saved) */
314 /* now the same like above, but without a chance to take a temporary register */
315 #ifdef HAS_ADDRESS_REGISTER_FILE
316 if (IS_ADR_TYPE(t)) {
317 if (rd->savadrreguse > 0) {
318 v->regoff = rd->savadrregs[--rd->savadrreguse];
321 v->flags |= INMEMORY;
322 v->regoff = rd->memuse++;
327 if (IS_FLT_DBL_TYPE(t)) {
329 v->flags |= rd->interfaces[s][fltalloc].flags
331 v->regoff = rd->interfaces[s][fltalloc].regoff;
333 if (rd->savfltreguse > 0) {
334 v->regoff = rd->savfltregs[--rd->savfltreguse];
337 v->flags |= INMEMORY;
338 #if defined(ALIGN_DOUBLES_IN_MEMORY)
339 /* Align doubles in Memory */
340 if ( (memneeded) && (rd->memuse & 1))
343 v->regoff = rd->memuse;
344 rd->memuse += memneeded + 1;
348 else { /* IS_INT_LNG */
349 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
351 * for i386 put all longs in memory
353 if (IS_2_WORD_TYPE(t)) {
354 v->flags |= INMEMORY;
355 #if defined(ALIGN_LONGS_IN_MEMORY)
356 /* Align longs in Memory */
360 v->regoff = rd->memuse;
361 rd->memuse += memneeded + 1;
367 rd->interfaces[s][intalloc].flags & INMEMORY;
368 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
369 if (!(v->flags & INMEMORY)
370 && IS_2_WORD_TYPE(intalloc))
373 rd->interfaces[s][intalloc].regoff);
377 rd->interfaces[s][intalloc].regoff;
379 if (rd->savintreguse > intregsneeded) {
380 rd->savintreguse -= intregsneeded + 1;
381 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
383 v->regoff = PACK_REGS(
384 rd->savintregs[rd->savintreguse],
385 rd->savintregs[rd->savintreguse + 1]);
389 rd->savintregs[rd->savintreguse];
391 v->flags |= INMEMORY;
392 #if defined(ALIGN_LONGS_IN_MEMORY)
393 /* Align longs in Memory */
394 if ( (memneeded) && (rd->memuse & 1))
397 v->regoff = rd->memuse;
398 rd->memuse += memneeded + 1;
403 } /* if (IS_FLT_DBL_TYPE(t) else */
404 } /* if (IS_ADR_TYPE(t)) else */
405 } /* if (saved) else */
406 } /* if (type >= 0) */
412 /* local_regalloc **************************************************************
414 Allocates registers for all local variables.
416 *******************************************************************************/
418 static void local_regalloc(jitdata *jd)
425 int intalloc, fltalloc;
427 int intregsneeded = 0;
429 int typeloop[] = { TYPE_LNG, TYPE_DBL, TYPE_INT, TYPE_FLT, TYPE_ADR };
430 int fargcnt, iargcnt;
431 #ifdef HAS_ADDRESS_REGISTER_FILE
435 /* get required compiler data */
441 if (jd->isleafmethod) {
442 methoddesc *md = m->parseddesc;
444 iargcnt = rd->argintreguse;
445 fargcnt = rd->argfltreguse;
446 #ifdef HAS_ADDRESS_REGISTER_FILE
447 aargcnt = rd->argadrreguse;
449 for (p = 0, s = 0; s < cd->maxlocals; s++, p++) {
450 intalloc = -1; fltalloc = -1;
451 for (tt = 0; tt <= 4; tt++) {
453 v = &rd->locals[s][t];
458 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
459 intregsneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
461 #if defined(HAS_4BYTE_STACKSLOT)
462 memneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
468 * #ifdef HAS_ADDRESS_REGISTER_FILE
475 * } else { / int & lng
479 * must not to be changed!
482 #ifdef HAS_ADDRESS_REGISTER_FILE
483 if (IS_ADR_TYPE(t)) {
484 if ((p < md->paramcount) && !md->params[p].inmemory) {
486 v->regoff = rd->argadrregs[md->params[p].regoff];
488 else if (rd->tmpadrreguse > 0) {
490 v->regoff = rd->tmpadrregs[--rd->tmpadrreguse];
492 /* use unused argument registers as local registers */
493 else if ((p >= md->paramcount) &&
494 (aargcnt < ADR_ARG_CNT)) {
496 v->regoff = rd->argadrregs[aargcnt++];
498 else if (rd->savadrreguse > 0) {
500 v->regoff = rd->savadrregs[--rd->savadrreguse];
503 v->flags |= INMEMORY;
504 v->regoff = rd->memuse++;
508 if (IS_FLT_DBL_TYPE(t)) {
510 v->flags = rd->locals[s][fltalloc].flags;
511 v->regoff = rd->locals[s][fltalloc].regoff;
513 #if !defined(SUPPORT_PASS_FLOATARGS_IN_INTREGS)
514 /* We can only use float arguments as local variables,
515 * if we do not pass them in integer registers. */
516 else if ((p < md->paramcount) &&
517 !md->params[p].inmemory) {
519 v->regoff = rd->argfltregs[md->params[p].regoff];
522 else if (rd->tmpfltreguse > 0) {
524 v->regoff = rd->tmpfltregs[--rd->tmpfltreguse];
526 /* use unused argument registers as local registers */
527 else if ((p >= md->paramcount) &&
528 (fargcnt < FLT_ARG_CNT)) {
530 v->regoff = rd->argfltregs[fargcnt];
533 else if (rd->savfltreguse > 0) {
535 v->regoff = rd->savfltregs[--rd->savfltreguse];
539 #if defined(ALIGN_DOUBLES_IN_MEMORY)
540 /* Align doubles in Memory */
541 if ( (memneeded) && (rd->memuse & 1))
544 v->regoff = rd->memuse;
545 rd->memuse += memneeded + 1;
550 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
552 * for i386 put all longs in memory
554 if (IS_2_WORD_TYPE(t)) {
556 #if defined(ALIGN_LONGS_IN_MEMORY)
557 /* Align longs in Memory */
561 v->regoff = rd->memuse;
562 rd->memuse += memneeded + 1;
567 v->flags = rd->locals[s][intalloc].flags;
568 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
569 if (!(v->flags & INMEMORY)
570 && IS_2_WORD_TYPE(intalloc))
571 v->regoff = GET_LOW_REG(
572 rd->locals[s][intalloc].regoff);
575 v->regoff = rd->locals[s][intalloc].regoff;
577 else if ((p < md->paramcount) &&
578 !md->params[p].inmemory) {
580 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
581 if (IS_2_WORD_TYPE(t))
582 v->regoff = PACK_REGS(
583 rd->argintregs[GET_LOW_REG(md->params[p].regoff)],
584 rd->argintregs[GET_HIGH_REG(md->params[p].regoff)]);
588 rd->argintregs[md->params[p].regoff];
590 else if (rd->tmpintreguse > intregsneeded) {
591 rd->tmpintreguse -= intregsneeded + 1;
593 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
595 v->regoff = PACK_REGS(
596 rd->tmpintregs[rd->tmpintreguse],
597 rd->tmpintregs[rd->tmpintreguse + 1]);
601 rd->tmpintregs[rd->tmpintreguse];
604 * use unused argument registers as local registers
606 else if ((p >= m->parseddesc->paramcount) &&
607 (iargcnt + intregsneeded < INT_ARG_CNT)) {
609 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
612 rd->argintregs[iargcnt],
613 rd->argintregs[iargcnt + 1]);
616 v->regoff = rd->argintregs[iargcnt];
617 iargcnt += intregsneeded + 1;
619 else if (rd->savintreguse > intregsneeded) {
620 rd->savintreguse -= intregsneeded + 1;
622 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
624 v->regoff = PACK_REGS(
625 rd->savintregs[rd->savintreguse],
626 rd->savintregs[rd->savintreguse + 1]);
629 v->regoff =rd->savintregs[rd->savintreguse];
633 #if defined(ALIGN_LONGS_IN_MEMORY)
634 /* Align longs in Memory */
635 if ( (memneeded) && (rd->memuse & 1))
638 v->regoff = rd->memuse;
639 rd->memuse += memneeded + 1;
644 #ifdef HAS_ADDRESS_REGISTER_FILE
647 } /* for (tt=0;...) */
649 /* If the current parameter is a 2-word type, the next local slot */
652 if (p < md->paramcount)
653 if (IS_2_WORD_TYPE(md->paramtypes[p].type))
659 for (s = 0; s < cd->maxlocals; s++) {
660 intalloc = -1; fltalloc = -1;
661 for (tt=0; tt<=4; tt++) {
663 v = &rd->locals[s][t];
666 #ifdef SUPPORT_COMBINE_INTEGER_REGISTERS
667 intregsneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
669 #if defined(HAS_4BYTE_STACKSLOT)
670 memneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
672 #ifdef HAS_ADDRESS_REGISTER_FILE
673 if ( IS_ADR_TYPE(t) ) {
674 if (rd->savadrreguse > 0) {
676 v->regoff = rd->savadrregs[--rd->savadrreguse];
680 v->regoff = rd->memuse++;
684 if (IS_FLT_DBL_TYPE(t)) {
686 v->flags = rd->locals[s][fltalloc].flags;
687 v->regoff = rd->locals[s][fltalloc].regoff;
689 else if (rd->savfltreguse > 0) {
691 v->regoff = rd->savfltregs[--rd->savfltreguse];
695 #if defined(ALIGN_DOUBLES_IN_MEMORY)
696 /* Align doubles in Memory */
697 if ( (memneeded) && (rd->memuse & 1))
700 v->regoff = rd->memuse;
701 rd->memuse += memneeded + 1;
706 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
708 * for i386 put all longs in memory
710 if (IS_2_WORD_TYPE(t)) {
712 #if defined(ALIGN_LONGS_IN_MEMORY)
713 /* Align longs in Memory */
717 v->regoff = rd->memuse;
718 rd->memuse += memneeded + 1;
722 v->flags = rd->locals[s][intalloc].flags;
723 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
724 if (!(v->flags & INMEMORY)
725 && IS_2_WORD_TYPE(intalloc))
726 v->regoff = GET_LOW_REG(
727 rd->locals[s][intalloc].regoff);
730 v->regoff = rd->locals[s][intalloc].regoff;
732 else if (rd->savintreguse > intregsneeded) {
733 rd->savintreguse -= intregsneeded+1;
735 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
737 v->regoff = PACK_REGS(
738 rd->savintregs[rd->savintreguse],
739 rd->savintregs[rd->savintreguse + 1]);
742 v->regoff =rd->savintregs[rd->savintreguse];
746 #if defined(ALIGN_LONGS_IN_MEMORY)
747 /* Align longs in Memory */
748 if ( (memneeded) && (rd->memuse & 1))
751 v->regoff = rd->memuse;
752 rd->memuse += memneeded + 1;
754 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
759 #ifdef HAS_ADDRESS_REGISTER_FILE
768 static void reg_init_temp(methodinfo *m, registerdata *rd)
771 #if defined(HAS_4BYTE_STACKSLOT)
772 rd->freememtop_2 = 0;
775 rd->freetmpinttop = 0;
776 rd->freesavinttop = 0;
777 rd->freetmpflttop = 0;
778 rd->freesavflttop = 0;
779 #ifdef HAS_ADDRESS_REGISTER_FILE
780 rd->freetmpadrtop = 0;
781 rd->freesavadrtop = 0;
784 rd->freearginttop = 0;
785 rd->freeargflttop = 0;
786 #ifdef HAS_ADDRESS_REGISTER_FILE
787 rd->freeargadrtop = 0;
792 #define reg_new_temp(rd,s) if (s->varkind == TEMPVAR) reg_new_temp_func(rd, s)
794 static void reg_new_temp_func(registerdata *rd, stackptr s)
800 /* Try to allocate a saved register if there is no temporary one */
801 /* available. This is what happens during the second run. */
802 tryagain = (s->flags & SAVEDVAR) ? 1 : 2;
804 #ifdef SUPPORT_COMBINE_INTEGER_REGISTERS
805 intregsneeded = (IS_2_WORD_TYPE(s->type)) ? 1 : 0;
809 #if defined(HAS_4BYTE_STACKSLOT)
810 memneeded = (IS_2_WORD_TYPE(s->type)) ? 1 : 0;
815 for(; tryagain; --tryagain) {
817 if (!(s->flags & SAVEDVAR))
818 s->flags |= SAVEDTMP;
819 #ifdef HAS_ADDRESS_REGISTER_FILE
820 if (IS_ADR_TYPE(s->type)) {
821 if (rd->freesavadrtop > 0) {
822 s->regoff = rd->freesavadrregs[--rd->freesavadrtop];
824 } else if (rd->savadrreguse > 0) {
825 s->regoff = rd->savadrregs[--rd->savadrreguse];
831 if (IS_FLT_DBL_TYPE(s->type)) {
832 if (rd->freesavflttop > 0) {
833 s->regoff = rd->freesavfltregs[--rd->freesavflttop];
835 } else if (rd->savfltreguse > 0) {
836 s->regoff = rd->savfltregs[--rd->savfltreguse];
840 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
842 * for i386 put all longs in memory
844 if (!IS_2_WORD_TYPE(s->type))
847 if (rd->freesavinttop > intregsneeded) {
848 rd->freesavinttop -= intregsneeded + 1;
849 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
851 s->regoff = PACK_REGS(
852 rd->freesavintregs[rd->freesavinttop],
853 rd->freesavintregs[rd->freesavinttop + 1]);
857 rd->freesavintregs[rd->freesavinttop];
859 } else if (rd->savintreguse > intregsneeded) {
860 rd->savintreguse -= intregsneeded + 1;
861 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
863 s->regoff = PACK_REGS(
864 rd->savintregs[rd->savintreguse],
865 rd->savintregs[rd->savintreguse + 1]);
868 s->regoff = rd->savintregs[rd->savintreguse];
874 } else { /* tryagain == 2 */
875 #ifdef HAS_ADDRESS_REGISTER_FILE
876 if (IS_ADR_TYPE(s->type)) {
877 if (rd->freetmpadrtop > 0) {
878 s->regoff = rd->freetmpadrregs[--rd->freetmpadrtop];
880 } else if (rd->tmpadrreguse > 0) {
881 s->regoff = rd->tmpadrregs[--rd->tmpadrreguse];
887 if (IS_FLT_DBL_TYPE(s->type)) {
888 if (rd->freeargflttop > 0) {
889 s->regoff = rd->freeargfltregs[--rd->freeargflttop];
892 } else if (rd->argfltreguse < FLT_ARG_CNT) {
893 s->regoff = rd->argfltregs[rd->argfltreguse++];
896 } else if (rd->freetmpflttop > 0) {
897 s->regoff = rd->freetmpfltregs[--rd->freetmpflttop];
899 } else if (rd->tmpfltreguse > 0) {
900 s->regoff = rd->tmpfltregs[--rd->tmpfltreguse];
905 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
907 * for i386 put all longs in memory
909 if (!IS_2_WORD_TYPE(s->type))
912 if (rd->freearginttop > intregsneeded) {
913 rd->freearginttop -= intregsneeded + 1;
915 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
917 s->regoff = PACK_REGS(
918 rd->freeargintregs[rd->freearginttop],
919 rd->freeargintregs[rd->freearginttop + 1]);
923 rd->freeargintregs[rd->freearginttop];
925 } else if (rd->argintreguse
926 < INT_ARG_CNT - intregsneeded) {
927 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
929 s->regoff = PACK_REGS(
930 rd->argintregs[rd->argintreguse],
931 rd->argintregs[rd->argintreguse + 1]);
934 s->regoff = rd->argintregs[rd->argintreguse];
936 rd->argintreguse += intregsneeded + 1;
938 } else if (rd->freetmpinttop > intregsneeded) {
939 rd->freetmpinttop -= intregsneeded + 1;
940 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
942 s->regoff = PACK_REGS(
943 rd->freetmpintregs[rd->freetmpinttop],
944 rd->freetmpintregs[rd->freetmpinttop + 1]);
947 s->regoff = rd->freetmpintregs[rd->freetmpinttop];
949 } else if (rd->tmpintreguse > intregsneeded) {
950 rd->tmpintreguse -= intregsneeded + 1;
951 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
953 s->regoff = PACK_REGS(
954 rd->tmpintregs[rd->tmpintreguse],
955 rd->tmpintregs[rd->tmpintreguse + 1]);
958 s->regoff = rd->tmpintregs[rd->tmpintreguse];
961 } /* if (!IS_2_WORD_TYPE(s->type)) */
962 } /* if (IS_FLT_DBL_TYPE(s->type)) */
963 } /* if (IS_ADR_TYPE(s->type)) */
964 } /* if (tryagain == 1) else */
965 } /* for(; tryagain; --tryagain) */
967 #if defined(HAS_4BYTE_STACKSLOT)
968 if ((memneeded == 1) && (rd->freememtop_2 > 0)) {
970 s->regoff = rd->freemem_2[rd->freememtop_2];
972 #endif /*defined(HAS_4BYTE_STACKSLOT) */
973 if ((memneeded == 0) && (rd->freememtop > 0)) {
975 s->regoff = rd->freemem[rd->freememtop];
977 #if defined(ALIGN_LONGS_IN_MEMORY) || defined(ALIGN_DOUBLES_IN_MEMORY)
978 /* align 2 Word Types */
979 if ((memneeded) && ((rd->memuse & 1) == 1)) {
980 /* Put patched memory slot on freemem */
981 rd->freemem[rd->freememtop++] = rd->memuse;
984 #endif /* defined(ALIGN_LONGS_IN_MEMORY) || defined(ALIGN_DOUBLES_IN_MEMORY) */
985 s->regoff = rd->memuse;
986 rd->memuse += memneeded + 1;
988 s->flags |= INMEMORY;
992 #define reg_free_temp(rd,s) if (((s)->varkind == TEMPVAR) && (!((s)->flags & STCOPY))) reg_free_temp_func(rd, (s))
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(registerdata *rd, stackptr s)
1002 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
1003 intregsneeded = (IS_2_WORD_TYPE(s->type)) ? 1 : 0;
1008 #if defined(HAS_4BYTE_STACKSLOT)
1009 memneeded = (IS_2_WORD_TYPE(s->type)) ? 1 : 0;
1014 if (s->flags & INMEMORY) {
1015 #if defined(HAS_4BYTE_STACKSLOT)
1016 if (memneeded > 0) {
1017 rd->freemem_2[rd->freememtop_2] = s->regoff;
1022 rd->freemem[rd->freememtop] = s->regoff;
1026 #ifdef HAS_ADDRESS_REGISTER_FILE
1027 } else if (IS_ADR_TYPE(s->type)) {
1028 if (s->flags & (SAVEDVAR | SAVEDTMP)) {
1029 /* s->flags &= ~SAVEDTMP; */
1030 rd->freesavadrregs[rd->freesavadrtop++] = s->regoff;
1032 rd->freetmpadrregs[rd->freetmpadrtop++] = s->regoff;
1034 } else if (IS_FLT_DBL_TYPE(s->type)) {
1035 if (s->flags & (SAVEDVAR | SAVEDTMP)) {
1036 /* s->flags &= ~SAVEDTMP; */
1037 rd->freesavfltregs[rd->freesavflttop++] = s->regoff;
1038 } else if (s->flags & TMPARG) {
1039 /* s->flags &= ~TMPARG; */
1040 rd->freeargfltregs[rd->freeargflttop++] = s->regoff;
1042 rd->freetmpfltregs[rd->freetmpflttop++] = s->regoff;
1043 } else { /* IS_INT_LNG_TYPE */
1044 if (s->flags & (SAVEDVAR | SAVEDTMP)) {
1045 /* s->flags &= ~SAVEDTMP; */
1046 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
1047 if (intregsneeded) {
1048 rd->freesavintregs[rd->freesavinttop] =
1049 GET_LOW_REG(s->regoff);
1050 rd->freesavintregs[rd->freesavinttop + 1] =
1051 GET_HIGH_REG(s->regoff);
1054 rd->freesavintregs[rd->freesavinttop] = s->regoff;
1055 rd->freesavinttop += intregsneeded + 1;
1057 } else if (s->flags & TMPARG) {
1058 /* s->flags &= ~TMPARG; */
1059 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
1060 if (intregsneeded) {
1061 rd->freeargintregs[rd->freearginttop] =
1062 GET_LOW_REG(s->regoff);
1063 rd->freeargintregs[rd->freearginttop + 1] =
1064 GET_HIGH_REG(s->regoff);
1067 rd->freeargintregs[rd->freearginttop] = s->regoff;
1068 rd->freearginttop += intregsneeded + 1;
1070 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
1071 if (intregsneeded) {
1072 rd->freetmpintregs[rd->freetmpinttop] =
1073 GET_LOW_REG(s->regoff);
1074 rd->freetmpintregs[rd->freetmpinttop + 1] =
1075 GET_HIGH_REG(s->regoff);
1078 rd->freetmpintregs[rd->freetmpinttop] = s->regoff;
1079 rd->freetmpinttop += intregsneeded + 1;
1084 static bool reg_alloc_dup(stackptr src, stackptr dst) {
1085 /* only copy TEMPVARS, do not mess with STACKVAR, */
1086 /* LOCALVAR, or ARGVAR */
1087 if ((src->varkind == TEMPVAR) && (dst->varkind == TEMPVAR)) {
1088 /* can not allocate a REG_TMP to a REG_SAV Slot */
1089 if (src->flags & INMEMORY) {
1090 dst->regoff = src->regoff;
1091 dst->flags |= INMEMORY;
1093 } else if ((src->flags & SAVEDVAR) == (dst->flags & SAVEDVAR)) {
1094 dst->regoff = src->regoff;
1095 dst->flags |= src->flags & SAVEDTMP;
1096 dst->flags |= src->flags & TMPARG;
1099 } else if ((dst->flags & SAVEDVAR) == 0) {
1100 /* can only use a REG_SAV as REG_TMP! */
1101 dst->regoff = src->regoff;
1102 dst->flags |= src->flags & TMPARG;
1103 dst->flags |= SAVEDTMP;
1108 /* no copy possible - allocate a new reg/memory location*/
1112 /* Mark the copies (STCOPY) at the dst stack right for DUPx and SWAP */
1113 static void new_reg_mark_copy(registerdata *rd, stackptr *dupslots,
1114 int nin, int nout, int nthrough)
1118 stackptr dst_stackslots[6];
1119 int s_bottom, d_bottom, i, j, slots;
1124 assert(nin <= 4 && (nout + nthrough) <= 6);
1126 /* remember all different Registers/Memory Location of used TEMPVAR */
1127 /* instacks in src_varnum[] and src_flags[] _uniquely_. Take the STCOPY */
1128 /* flag of the last (deepest) occurence */
1130 argp = dupslots + slots;
1131 for (s_bottom = 4; slots--; ) {
1133 if (sp->varkind == TEMPVAR) {
1135 for (i = 3; i >= s_bottom; i--) {
1136 if ((src_regoff[i] == sp->regoff) &&
1137 ((src_flags[i] & INMEMORY) == (sp->flags & INMEMORY)) )
1139 src_flags[i] &= (~STCOPY | (sp->flags & STCOPY));
1145 src_regoff[s_bottom] = sp->regoff;
1146 src_flags[s_bottom] = sp->flags;
1151 /* Remember used TEMPVAR dst Stackslots in dst_stackslots[], since they */
1152 /* have to be from the "lowest" upwards, and the stackelements list is */
1153 /* linked from only top downwards */
1155 slots = nthrough + nout;
1156 argp = dupslots + nin + nout;
1157 for (d_bottom = 6; slots--; ) {
1159 if (sp->varkind == TEMPVAR) {
1161 dst_stackslots[d_bottom] = sp;
1165 /* Mark all reused reg/mem in dst stacklots with STCOPY, if the */
1166 /* corresponding src stackslot was marked STCOPY*/
1167 /* if the correspondig STCOPY from the src stackslot was not set, do not */
1168 /* mark the lowest occurence at dst stackslots */
1169 /* mark in src_flag reg/mem with STKEEP, if they where reused in the dst */
1170 /* stacklots, so they are not freed afterwards */
1171 for (i = d_bottom; i < 6; i++) {
1172 for (j = s_bottom; j < 4; j++) {
1173 if ( (src_regoff[j] == dst_stackslots[i]->regoff) &&
1174 ((src_flags[j] & INMEMORY) == (dst_stackslots[i]->flags & INMEMORY)) )
1176 if (src_flags[j] & STCOPY) {
1177 dst_stackslots[i]->flags |= STCOPY;
1180 src_flags[j] |= STCOPY;
1181 dst_stackslots[i]->flags &= ~STCOPY;
1183 /* do not free reg/mem of src Stackslot */
1184 src_flags[j] |= STKEEP;
1189 /* free all reg/mem of src stack, which where not marked with STKEEP */
1190 for (j=s_bottom; j < 4; j++) {
1191 if ((src_flags[j] & STKEEP)==0) {
1192 /* free, if STCOPY of src stackslot is not set */
1193 /* STCOPY is already checked in reg_free_temp macro! */
1195 argp = dupslots + slots;
1198 if ((src_regoff[j] == sp->regoff) &&
1199 ((src_flags[j] & INMEMORY) == (sp->flags & INMEMORY)) )
1201 reg_free_temp(rd, sp);
1208 /* Mark the copies (STCOPY) at the dst stack right for DUPx and SWAP */
1209 static void reg_mark_copy(registerdata *rd, stackptr src_top, stackptr src_bottom, stackptr dst_top, stackptr dst_bottom) {
1212 stackptr dst_stackslots[6];
1213 int s_bottom, d_bottom, i, j;
1218 /* remember all different Registers/Memory Location of used TEMPVAR */
1219 /* instacks in src_varnum[] and src_flags[] _uniquely_. Take the STCOPY */
1220 /* flag of the last (deepest) occurence */
1221 for(s_bottom = 4, sp = src_top; sp >= src_bottom; sp = sp->prev) {
1222 if (sp->varkind == TEMPVAR) {
1224 for( i = 3; i >= s_bottom; i--) {
1225 if ((src_regoff[i] == sp->regoff) &&
1226 ((src_flags[i] & INMEMORY) == (sp->flags & INMEMORY)) ) {
1227 src_flags[i] &= (~STCOPY | (sp->flags & STCOPY));
1233 src_regoff[s_bottom] = sp->regoff;
1234 src_flags[s_bottom] = sp->flags;
1239 /* Remember used TEMPVAR dst Stackslots in dst_stackslots[], since they */
1240 /* have to be from the "lowest" upwards, and the stackelements list is */
1241 /* linked from only top downwards */
1243 for(d_bottom = 6, sp =dst_top; sp >= dst_bottom; sp = sp->prev) {
1244 if (sp->varkind == TEMPVAR) {
1246 dst_stackslots[d_bottom] = sp;
1250 /* Mark all reused reg/mem in dst stacklots with STCOPY, if the */
1251 /* corresponding src stackslot was marked STCOPY*/
1252 /* if the correspondig STCOPY from the src stackslot was not set, do not */
1253 /* mark the lowest occurence at dst stackslots */
1254 /* mark in src_flag reg/mem with STKEEP, if they where reused in the dst */
1255 /* stacklots, so they are not freed afterwards */
1256 for(i = d_bottom; i < 6; i++) {
1257 for(j = s_bottom; j < 4; j++) {
1258 if ( (src_regoff[j] == dst_stackslots[i]->regoff) &&
1259 ((src_flags[j] & INMEMORY) == (dst_stackslots[i]->flags & INMEMORY)) ) {
1260 if (src_flags[j] & STCOPY)
1261 dst_stackslots[i]->flags |= STCOPY;
1263 src_flags[j] |= STCOPY;
1264 dst_stackslots[i]->flags &= ~STCOPY;
1266 /* do not free reg/mem of src Stackslot */
1267 src_flags[j] |= STKEEP;
1272 /* free all reg/mem of src stack, which where not marked with STKEEP */
1273 for(j=s_bottom; j < 4; j++) {
1274 if ((src_flags[j] & STKEEP)==0) {
1275 /* free, if STCOPY of src stackslot is not set */
1276 /* STCOPY is already checked in reg_free_temp macro! */
1277 for(sp = src_top; sp >= src_bottom; sp = sp->prev)
1278 if ((src_regoff[j] == sp->regoff) &&
1279 ((src_flags[j] & INMEMORY) == (sp->flags & INMEMORY)) ) {
1280 reg_free_temp(rd, sp);
1287 /* allocate_scratch_registers **************************************************
1289 Allocate temporary (non-interface, non-local) registers.
1291 *******************************************************************************/
1293 static void new_allocate_scratch_registers(jitdata *jd)
1299 new_instruction *iptr;
1301 builtintable_entry *bte;
1305 /* get required compiler data */
1310 /* initialize temp registers */
1311 reg_init_temp(m, rd);
1313 bptr = jd->new_basicblocks;
1315 while (bptr != NULL) {
1316 if (bptr->flags >= BBREACHED) {
1317 iptr = /* XXX */ (new_instruction *) bptr->iinstr;
1320 while (--len >= 0) {
1321 switch (iptr->opc) {
1326 case ICMD_ELSE_ICONST:
1327 case ICMD_CHECKNULL:
1333 case ICMD_PUTSTATICCONST:
1334 case ICMD_INLINE_START:
1335 case ICMD_INLINE_END:
1336 case ICMD_INLINE_GOTO:
1339 /* pop 0 push 1 const */
1347 /* pop 0 push 1 load */
1354 reg_new_temp(rd, iptr->dst.var);
1368 reg_free_temp(rd, iptr->sx.s23.s2.var);
1369 reg_free_temp(rd, iptr->s1.var);
1370 reg_new_temp(rd, iptr->dst.var);
1384 reg_free_temp(rd, iptr->sx.s23.s3.var);
1385 reg_free_temp(rd, iptr->sx.s23.s2.var);
1386 reg_free_temp(rd, iptr->s1.var);
1389 /* pop 1 push 0 store */
1409 case ICMD_PUTSTATIC:
1410 case ICMD_PUTFIELDCONST:
1412 /* pop 1 push 0 branch */
1415 case ICMD_IFNONNULL:
1431 /* pop 1 push 0 table branch */
1433 case ICMD_TABLESWITCH:
1434 case ICMD_LOOKUPSWITCH:
1436 case ICMD_MONITORENTER:
1437 case ICMD_MONITOREXIT:
1438 reg_free_temp(rd, iptr->s1.var);
1441 /* pop 2 push 0 branch */
1443 case ICMD_IF_ICMPEQ:
1444 case ICMD_IF_ICMPNE:
1445 case ICMD_IF_ICMPLT:
1446 case ICMD_IF_ICMPGE:
1447 case ICMD_IF_ICMPGT:
1448 case ICMD_IF_ICMPLE:
1450 case ICMD_IF_LCMPEQ:
1451 case ICMD_IF_LCMPNE:
1452 case ICMD_IF_LCMPLT:
1453 case ICMD_IF_LCMPGE:
1454 case ICMD_IF_LCMPGT:
1455 case ICMD_IF_LCMPLE:
1457 case ICMD_IF_FCMPEQ:
1458 case ICMD_IF_FCMPNE:
1460 case ICMD_IF_FCMPL_LT:
1461 case ICMD_IF_FCMPL_GE:
1462 case ICMD_IF_FCMPL_GT:
1463 case ICMD_IF_FCMPL_LE:
1465 case ICMD_IF_FCMPG_LT:
1466 case ICMD_IF_FCMPG_GE:
1467 case ICMD_IF_FCMPG_GT:
1468 case ICMD_IF_FCMPG_LE:
1470 case ICMD_IF_DCMPEQ:
1471 case ICMD_IF_DCMPNE:
1473 case ICMD_IF_DCMPL_LT:
1474 case ICMD_IF_DCMPL_GE:
1475 case ICMD_IF_DCMPL_GT:
1476 case ICMD_IF_DCMPL_LE:
1478 case ICMD_IF_DCMPG_LT:
1479 case ICMD_IF_DCMPG_GE:
1480 case ICMD_IF_DCMPG_GT:
1481 case ICMD_IF_DCMPG_LE:
1483 case ICMD_IF_ACMPEQ:
1484 case ICMD_IF_ACMPNE:
1492 case ICMD_IASTORECONST:
1493 case ICMD_LASTORECONST:
1494 case ICMD_AASTORECONST:
1495 case ICMD_BASTORECONST:
1496 case ICMD_CASTORECONST:
1497 case ICMD_SASTORECONST:
1498 reg_free_temp(rd, iptr->sx.s23.s2.var);
1499 reg_free_temp(rd, iptr->s1.var);
1502 /* pop 0 push 1 dup */
1505 /* src === dst->prev (identical Stackslot Element) */
1506 /* src --> dst (copied value, take same reg/mem) */
1508 if (!reg_alloc_dup(iptr->s1.var, iptr->dst.var)) {
1509 reg_new_temp(rd, iptr->dst.var);
1511 iptr->dst.var->flags |= STCOPY;
1515 /* pop 0 push 2 dup */
1518 /* src->prev === dst->prev->prev->prev (identical Stackslot Element) */
1519 /* src === dst->prev->prev (identical Stackslot Element) */
1520 /* src->prev --> dst->prev (copied value, take same reg/mem) */
1521 /* src --> dst (copied value, take same reg/mem) */
1523 if (!reg_alloc_dup(iptr->dst.dupslots[0], iptr->dst.dupslots[2+0]))
1524 reg_new_temp(rd, iptr->dst.dupslots[2+0]);
1525 if (!reg_alloc_dup(iptr->dst.dupslots[1], iptr->dst.dupslots[2+1]))
1526 reg_new_temp(rd, iptr->dst.dupslots[2+1]);
1527 new_reg_mark_copy(rd, iptr->dst.dupslots, 2, 2, 2);
1530 /* pop 2 push 3 dup */
1533 /* src->prev --> dst->prev (copied value, take same reg/mem) */
1534 /* src --> dst (copied value, take same reg/mem) */
1535 /* src --> dst->prev->prev (copied value, take same reg/mem) */
1537 if (!reg_alloc_dup(iptr->dst.dupslots[1], iptr->dst.dupslots[2+0]))
1538 reg_new_temp(rd, iptr->dst.dupslots[2+0]);
1539 if (!reg_alloc_dup(iptr->dst.dupslots[1], iptr->dst.dupslots[2+2]))
1540 reg_new_temp(rd, iptr->dst.dupslots[2+2]);
1541 if (!reg_alloc_dup(iptr->dst.dupslots[0], iptr->dst.dupslots[2+1]))
1542 reg_new_temp(rd, iptr->dst.dupslots[2+1]);
1543 new_reg_mark_copy(rd, iptr->dst.dupslots, 2, 3, 0);
1546 /* pop 3 push 4 dup */
1549 /* src->prev->prev --> dst->prev->prev */
1550 /* src->prev --> dst->prev */
1552 /* src --> dst->prev->prev->prev */
1554 if (!reg_alloc_dup(iptr->dst.dupslots[2], iptr->dst.dupslots[3+0]))
1555 reg_new_temp(rd, iptr->dst.dupslots[3+0]);
1556 if (!reg_alloc_dup(iptr->dst.dupslots[2], iptr->dst.dupslots[3+3]))
1557 reg_new_temp(rd, iptr->dst.dupslots[3+3]);
1558 if (!reg_alloc_dup(iptr->dst.dupslots[1], iptr->dst.dupslots[3+2]))
1559 reg_new_temp(rd, iptr->dst.dupslots[3+2]);
1560 if (!reg_alloc_dup(iptr->dst.dupslots[0], iptr->dst.dupslots[3+1]))
1561 reg_new_temp(rd, iptr->dst.dupslots[3+1]);
1562 new_reg_mark_copy(rd, iptr->dst.dupslots, 3, 4, 0);
1565 /* pop 3 push 5 dup */
1568 /* src->prev->prev --> dst->prev->prev */
1569 /* src->prev --> dst->prev */
1571 /* src->prev --> dst->prev->prev->prev->prev */
1572 /* src --> dst->prev->prev->prev */
1574 if (!reg_alloc_dup(iptr->dst.dupslots[2], iptr->dst.dupslots[3+1]))
1575 reg_new_temp(rd, iptr->dst.dupslots[3+1]);
1576 if (!reg_alloc_dup(iptr->dst.dupslots[2], iptr->dst.dupslots[3+4]))
1577 reg_new_temp(rd, iptr->dst.dupslots[3+4]);
1578 if (!reg_alloc_dup(iptr->dst.dupslots[1], iptr->dst.dupslots[3+0]))
1579 reg_new_temp(rd, iptr->dst.dupslots[3+0]);
1580 if (!reg_alloc_dup(iptr->dst.dupslots[1], iptr->dst.dupslots[3+3]))
1581 reg_new_temp(rd, iptr->dst.dupslots[3+3]);
1582 if (!reg_alloc_dup(iptr->dst.dupslots[0], iptr->dst.dupslots[3+2]))
1583 reg_new_temp(rd, iptr->dst.dupslots[3+2]);
1584 new_reg_mark_copy(rd, iptr->dst.dupslots, 3, 5, 0);
1587 /* pop 4 push 6 dup */
1590 /* src->prev->prev->prev --> dst->prev->prev->prev */
1591 /* src->prev->prev --> dst->prev->prev */
1592 /* src->prev --> dst->prev */
1594 /* src->prev --> dst->prev->prev->prev->prev->prev */
1595 /* src --> dst->prev->prev->prev->prev */
1597 if (!reg_alloc_dup(iptr->dst.dupslots[3], iptr->dst.dupslots[4+1]))
1598 reg_new_temp(rd, iptr->dst.dupslots[4+1]);
1599 if (!reg_alloc_dup(iptr->dst.dupslots[3], iptr->dst.dupslots[4+5]))
1600 reg_new_temp(rd, iptr->dst.dupslots[4+5]);
1601 if (!reg_alloc_dup(iptr->dst.dupslots[2], iptr->dst.dupslots[4+0]))
1602 reg_new_temp(rd, iptr->dst.dupslots[4+0]);
1603 if (!reg_alloc_dup(iptr->dst.dupslots[2], iptr->dst.dupslots[4+4]))
1604 reg_new_temp(rd, iptr->dst.dupslots[4+4]);
1605 if (!reg_alloc_dup(iptr->dst.dupslots[1], iptr->dst.dupslots[4+3]))
1606 reg_new_temp(rd, iptr->dst.dupslots[4+3]);
1607 if (!reg_alloc_dup(iptr->dst.dupslots[0], iptr->dst.dupslots[4+2]))
1608 reg_new_temp(rd, iptr->dst.dupslots[4+2]);
1609 new_reg_mark_copy(rd, iptr->dst.dupslots, 4, 6, 0);
1612 /* pop 2 push 2 swap */
1615 /* src --> dst->prev (copy) */
1616 /* src->prev --> dst (copy) */
1618 if (!reg_alloc_dup(iptr->dst.dupslots[1], iptr->dst.dupslots[+0]))
1619 reg_new_temp(rd, iptr->dst.dupslots[2+0]);
1620 if (!reg_alloc_dup(iptr->dst.dupslots[0], iptr->dst.dupslots[+1]))
1621 reg_new_temp(rd, iptr->dst.dupslots[2+1]);
1622 new_reg_mark_copy(rd, iptr->dst.dupslots, 2, 2, 0);
1671 reg_free_temp(rd, iptr->sx.s23.s2.var);
1672 reg_free_temp(rd, iptr->s1.var);
1673 reg_new_temp(rd, iptr->dst.var);
1678 case ICMD_IADDCONST:
1679 case ICMD_ISUBCONST:
1680 case ICMD_IMULCONST:
1684 case ICMD_IANDCONST:
1686 case ICMD_IXORCONST:
1687 case ICMD_ISHLCONST:
1688 case ICMD_ISHRCONST:
1689 case ICMD_IUSHRCONST:
1691 case ICMD_LADDCONST:
1692 case ICMD_LSUBCONST:
1693 case ICMD_LMULCONST:
1697 case ICMD_LANDCONST:
1699 case ICMD_LXORCONST:
1700 case ICMD_LSHLCONST:
1701 case ICMD_LSHRCONST:
1702 case ICMD_LUSHRCONST:
1704 case ICMD_IFEQ_ICONST:
1705 case ICMD_IFNE_ICONST:
1706 case ICMD_IFLT_ICONST:
1707 case ICMD_IFGE_ICONST:
1708 case ICMD_IFGT_ICONST:
1709 case ICMD_IFLE_ICONST:
1714 case ICMD_INT2SHORT:
1732 case ICMD_CHECKCAST:
1734 case ICMD_ARRAYLENGTH:
1735 case ICMD_INSTANCEOF:
1738 case ICMD_ANEWARRAY:
1741 reg_free_temp(rd, iptr->s1.var);
1742 reg_new_temp(rd, iptr->dst.var);
1747 case ICMD_GETSTATIC:
1750 reg_new_temp(rd, iptr->dst.var);
1753 /* pop many push any */
1755 case ICMD_INVOKESTATIC:
1756 case ICMD_INVOKESPECIAL:
1757 case ICMD_INVOKEVIRTUAL:
1758 case ICMD_INVOKEINTERFACE:
1759 NEW_INSTRUCTION_GET_METHODDESC(iptr,md);
1761 argp = iptr->sx.s23.s2.args;
1763 reg_free_temp(rd, *argp);
1766 if (md->returntype.type != TYPE_VOID)
1767 reg_new_temp(rd, iptr->dst.var);
1771 bte = iptr->sx.s23.s3.bte;
1774 argp = iptr->sx.s23.s2.args;
1776 reg_free_temp(rd, *argp);
1779 if (md->returntype.type != TYPE_VOID)
1780 reg_new_temp(rd, iptr->dst.var);
1783 case ICMD_MULTIANEWARRAY:
1784 i = iptr->s1.argcount;
1785 argp = iptr->sx.s23.s2.args;
1787 reg_free_temp(rd, *argp);
1790 reg_new_temp(rd, iptr->dst.var);
1795 new_internalerror("Unknown ICMD %d during register allocation",
1800 } /* while instructions */
1803 } /* while blocks */
1806 static void allocate_scratch_registers(jitdata *jd)
1816 builtintable_entry *bte;
1819 /* get required compiler data */
1824 /* initialize temp registers */
1825 reg_init_temp(m, rd);
1827 bptr = m->basicblocks;
1829 while (bptr != NULL) {
1830 if (bptr->flags >= BBREACHED) {
1831 dst = bptr->instack;
1833 iptr = bptr->iinstr;
1836 while (--len >= 0) {
1840 switch (iptr->opc) {
1845 case ICMD_ELSE_ICONST:
1846 case ICMD_CHECKNULL:
1852 case ICMD_PUTSTATICCONST:
1853 case ICMD_INLINE_START:
1854 case ICMD_INLINE_END:
1855 case ICMD_INLINE_GOTO:
1858 /* pop 0 push 1 const */
1866 /* pop 0 push 1 load */
1873 reg_new_temp(rd, dst);
1887 reg_free_temp(rd, src);
1888 reg_free_temp(rd, src->prev);
1889 reg_new_temp(rd, dst);
1903 reg_free_temp(rd, src);
1904 reg_free_temp(rd, src->prev);
1905 reg_free_temp(rd, src->prev->prev);
1908 /* pop 1 push 0 store */
1928 case ICMD_PUTSTATIC:
1929 case ICMD_PUTFIELDCONST:
1931 /* pop 1 push 0 branch */
1934 case ICMD_IFNONNULL:
1950 /* pop 1 push 0 table branch */
1952 case ICMD_TABLESWITCH:
1953 case ICMD_LOOKUPSWITCH:
1955 case ICMD_MONITORENTER:
1956 case ICMD_MONITOREXIT:
1957 reg_free_temp(rd, src);
1960 /* pop 2 push 0 branch */
1962 case ICMD_IF_ICMPEQ:
1963 case ICMD_IF_ICMPNE:
1964 case ICMD_IF_ICMPLT:
1965 case ICMD_IF_ICMPGE:
1966 case ICMD_IF_ICMPGT:
1967 case ICMD_IF_ICMPLE:
1969 case ICMD_IF_LCMPEQ:
1970 case ICMD_IF_LCMPNE:
1971 case ICMD_IF_LCMPLT:
1972 case ICMD_IF_LCMPGE:
1973 case ICMD_IF_LCMPGT:
1974 case ICMD_IF_LCMPLE:
1976 case ICMD_IF_FCMPEQ:
1977 case ICMD_IF_FCMPNE:
1979 case ICMD_IF_FCMPL_LT:
1980 case ICMD_IF_FCMPL_GE:
1981 case ICMD_IF_FCMPL_GT:
1982 case ICMD_IF_FCMPL_LE:
1984 case ICMD_IF_FCMPG_LT:
1985 case ICMD_IF_FCMPG_GE:
1986 case ICMD_IF_FCMPG_GT:
1987 case ICMD_IF_FCMPG_LE:
1989 case ICMD_IF_DCMPEQ:
1990 case ICMD_IF_DCMPNE:
1992 case ICMD_IF_DCMPL_LT:
1993 case ICMD_IF_DCMPL_GE:
1994 case ICMD_IF_DCMPL_GT:
1995 case ICMD_IF_DCMPL_LE:
1997 case ICMD_IF_DCMPG_LT:
1998 case ICMD_IF_DCMPG_GE:
1999 case ICMD_IF_DCMPG_GT:
2000 case ICMD_IF_DCMPG_LE:
2002 case ICMD_IF_ACMPEQ:
2003 case ICMD_IF_ACMPNE:
2011 case ICMD_IASTORECONST:
2012 case ICMD_LASTORECONST:
2013 case ICMD_AASTORECONST:
2014 case ICMD_BASTORECONST:
2015 case ICMD_CASTORECONST:
2016 case ICMD_SASTORECONST:
2017 reg_free_temp(rd, src);
2018 reg_free_temp(rd, src->prev);
2021 /* pop 0 push 1 dup */
2024 /* src === dst->prev (identical Stackslot Element) */
2025 /* src --> dst (copied value, take same reg/mem) */
2027 if (!reg_alloc_dup(src, dst)) {
2028 reg_new_temp(rd, dst);
2030 dst->flags |= STCOPY;
2034 /* pop 0 push 2 dup */
2037 /* src->prev === dst->prev->prev->prev (identical Stackslot Element) */
2038 /* src === dst->prev->prev (identical Stackslot Element) */
2039 /* src->prev --> dst->prev (copied value, take same reg/mem) */
2040 /* src --> dst (copied value, take same reg/mem) */
2042 if (!reg_alloc_dup(src->prev, dst->prev))
2043 reg_new_temp(rd, dst->prev);
2044 if (!reg_alloc_dup(src, dst))
2045 reg_new_temp(rd, dst);
2046 reg_mark_copy(rd, src, src->prev, dst, dst->prev->prev->prev);
2049 /* pop 2 push 3 dup */
2052 /* src->prev --> dst->prev (copied value, take same reg/mem) */
2053 /* src --> dst (copied value, take same reg/mem) */
2054 /* src --> dst->prev->prev (copied value, take same reg/mem) */
2056 if (!reg_alloc_dup(src, dst->prev->prev))
2057 reg_new_temp(rd, dst->prev->prev);
2058 if (!reg_alloc_dup(src, dst))
2059 reg_new_temp(rd, dst);
2060 if (!reg_alloc_dup(src->prev, dst->prev))
2061 reg_new_temp(rd, dst->prev);
2062 reg_mark_copy(rd, src, src->prev, dst, dst->prev->prev);
2065 /* pop 3 push 4 dup */
2068 /* src->prev->prev --> dst->prev->prev */
2069 /* src->prev --> dst->prev */
2071 /* src --> dst->prev->prev->prev */
2073 if (!reg_alloc_dup(src, dst->prev->prev->prev))
2074 reg_new_temp(rd, dst->prev->prev->prev);
2075 if (!reg_alloc_dup(src, dst))
2076 reg_new_temp(rd, dst);
2077 if (!reg_alloc_dup(src->prev, dst->prev))
2078 reg_new_temp(rd, dst->prev);
2079 if (!reg_alloc_dup(src->prev->prev, dst->prev->prev))
2080 reg_new_temp(rd, dst->prev->prev);
2081 reg_mark_copy(rd, src, src->prev->prev, dst, dst->prev->prev->prev);
2084 /* pop 3 push 5 dup */
2087 /* src->prev->prev --> dst->prev->prev */
2088 /* src->prev --> dst->prev */
2090 /* src->prev --> dst->prev->prev->prev->prev */
2091 /* src --> dst->prev->prev->prev */
2093 if (!reg_alloc_dup(src, dst->prev->prev->prev))
2094 reg_new_temp(rd, dst->prev->prev->prev);
2095 if (!reg_alloc_dup(src, dst))
2096 reg_new_temp(rd, dst);
2097 if (!reg_alloc_dup(src->prev, dst->prev->prev->prev->prev))
2098 reg_new_temp(rd, dst->prev->prev->prev->prev);
2099 if (!reg_alloc_dup(src->prev, dst->prev))
2100 reg_new_temp(rd, dst->prev);
2101 if (!reg_alloc_dup(src->prev->prev, dst->prev->prev))
2102 reg_new_temp(rd, dst->prev->prev);
2103 reg_mark_copy(rd, src, src->prev->prev, dst, dst->prev->prev->prev->prev);
2106 /* pop 4 push 6 dup */
2109 /* src->prev->prev->prev --> dst->prev->prev->prev */
2110 /* src->prev->prev --> dst->prev->prev */
2111 /* src->prev --> dst->prev */
2113 /* src->prev --> dst->prev->prev->prev->prev->prev */
2114 /* src --> dst->prev->prev->prev->prev */
2116 if (!reg_alloc_dup(src, dst->prev->prev->prev->prev))
2117 reg_new_temp(rd, dst->prev->prev->prev->prev);
2118 if (!reg_alloc_dup(src, dst))
2119 reg_new_temp(rd, dst);
2120 if (!reg_alloc_dup(src->prev, dst->prev->prev->prev->prev->prev))
2121 reg_new_temp(rd, dst->prev->prev->prev->prev->prev);
2122 if (!reg_alloc_dup(src->prev, dst->prev))
2123 reg_new_temp(rd, dst->prev);
2124 if (!reg_alloc_dup(src->prev->prev, dst->prev->prev))
2125 reg_new_temp(rd, dst->prev->prev);
2126 if (!reg_alloc_dup(src->prev->prev->prev, dst->prev->prev->prev))
2127 reg_new_temp(rd, dst->prev->prev->prev);
2128 reg_mark_copy(rd, src, src->prev->prev->prev, dst, dst->prev->prev->prev->prev->prev);
2131 /* pop 2 push 2 swap */
2134 /* src --> dst->prev (copy) */
2135 /* src->prev --> dst (copy) */
2137 if (!reg_alloc_dup(src, dst->prev))
2138 reg_new_temp(rd, dst->prev);
2139 if (!reg_alloc_dup(src->prev, dst))
2140 reg_new_temp(rd, dst);
2141 reg_mark_copy(rd, src, src->prev, dst, dst->prev);
2190 reg_free_temp(rd, src);
2191 reg_free_temp(rd, src->prev);
2192 reg_new_temp(rd, dst);
2197 case ICMD_IADDCONST:
2198 case ICMD_ISUBCONST:
2199 case ICMD_IMULCONST:
2203 case ICMD_IANDCONST:
2205 case ICMD_IXORCONST:
2206 case ICMD_ISHLCONST:
2207 case ICMD_ISHRCONST:
2208 case ICMD_IUSHRCONST:
2210 case ICMD_LADDCONST:
2211 case ICMD_LSUBCONST:
2212 case ICMD_LMULCONST:
2216 case ICMD_LANDCONST:
2218 case ICMD_LXORCONST:
2219 case ICMD_LSHLCONST:
2220 case ICMD_LSHRCONST:
2221 case ICMD_LUSHRCONST:
2223 case ICMD_IFEQ_ICONST:
2224 case ICMD_IFNE_ICONST:
2225 case ICMD_IFLT_ICONST:
2226 case ICMD_IFGE_ICONST:
2227 case ICMD_IFGT_ICONST:
2228 case ICMD_IFLE_ICONST:
2233 case ICMD_INT2SHORT:
2251 case ICMD_CHECKCAST:
2253 case ICMD_ARRAYLENGTH:
2254 case ICMD_INSTANCEOF:
2257 case ICMD_ANEWARRAY:
2260 reg_free_temp(rd, src);
2261 reg_new_temp(rd, dst);
2266 case ICMD_GETSTATIC:
2269 reg_new_temp(rd, dst);
2272 /* pop many push any */
2274 case ICMD_INVOKESTATIC:
2275 case ICMD_INVOKESPECIAL:
2276 case ICMD_INVOKEVIRTUAL:
2277 case ICMD_INVOKEINTERFACE:
2278 INSTRUCTION_GET_METHODDESC(iptr,md);
2281 reg_free_temp(rd, src);
2284 if (md->returntype.type != TYPE_VOID)
2285 reg_new_temp(rd, dst);
2293 reg_free_temp(rd, src);
2296 if (md->returntype.type != TYPE_VOID)
2297 reg_new_temp(rd, dst);
2300 case ICMD_MULTIANEWARRAY:
2303 reg_free_temp(rd, src);
2306 reg_new_temp(rd, dst);
2311 new_internalerror("Unknown ICMD %d during register allocation",
2316 } /* while instructions */
2319 } /* while blocks */
2323 #if defined(ENABLE_STATISTICS)
2324 void reg_make_statistics(jitdata *jd)
2331 stackptr src, src_old;
2335 int size_interface; /* == maximum size of in/out stack at basic block boundaries */
2338 /* get required compiler data */
2348 /* count how many local variables are held in memory or register */
2349 for(i=0; i < cd->maxlocals; i++)
2350 for (type=0; type <=4; type++)
2351 if (rd->locals[i][type].type != -1) { /* valid local */
2352 if (rd->locals[i][type].flags & INMEMORY) {
2353 count_locals_spilled++;
2357 count_locals_register++;
2359 /* count how many stack slots are held in memory or register */
2361 bptr = m->basicblocks;
2362 while (bptr != NULL) {
2363 if (bptr->flags >= BBREACHED) {
2365 #if defined(ENABLE_LSRA)
2368 /* check for memory moves from interface to BB instack */
2369 dst = bptr->instack;
2370 len = bptr->indepth;
2372 if (len > size_interface) size_interface = len;
2374 while (dst != NULL) {
2376 if (dst->varkind != STACKVAR) {
2377 if ( (dst->flags & INMEMORY) ||
2378 (rd->interfaces[len][dst->type].flags & INMEMORY) ||
2379 ( (dst->flags & INMEMORY) &&
2380 (rd->interfaces[len][dst->type].flags & INMEMORY) &&
2381 (dst->regoff != rd->interfaces[len][dst->type].regoff) ))
2383 /* one in memory or both inmemory at different offsets */
2384 count_mem_move_bb++;
2392 /* check for memory moves from BB outstack to interface */
2393 dst = bptr->outstack;
2394 len = bptr->outdepth;
2395 if (len > size_interface) size_interface = len;
2399 if (dst->varkind != STACKVAR) {
2400 if ( (dst->flags & INMEMORY) || \
2401 (rd->interfaces[len][dst->type].flags & INMEMORY) || \
2402 ( (dst->flags & INMEMORY) && \
2403 (rd->interfaces[len][dst->type].flags & INMEMORY) && \
2404 (dst->regoff != rd->interfaces[len][dst->type].regoff) ))
2406 /* one in memory or both inmemory at different offsets */
2407 count_mem_move_bb++;
2414 #if defined(ENABLE_LSRA)
2419 dst = bptr->instack;
2420 iptr = bptr->iinstr;
2424 while (--len >= 0) {
2428 if ((src!= NULL) && (src != src_old)) { /* new stackslot */
2429 switch (src->varkind) {
2432 if (!(src->flags & INMEMORY))
2433 count_ss_register++;
2439 /* case LOCALVAR: */
2440 /* if (!(rd->locals[src->varnum][src->type].flags & INMEMORY)) */
2441 /* count_ss_register++; */
2443 /* count_ss_spilled++; */
2446 if (!(src->flags & INMEMORY))
2447 count_argument_mem_ss++;
2449 count_argument_reg_ss++;
2453 /* if (IS_FLT_DBL_TYPE(src->type)) { */
2454 /* if (src->varnum < FLT_ARG_CNT) { */
2455 /* count_ss_register++; */
2459 /* #if defined(__POWERPC__) */
2460 /* if (src->varnum < INT_ARG_CNT - (IS_2_WORD_TYPE(src->type) != 0)) { */
2462 /* if (src->varnum < INT_ARG_CNT) { */
2464 /* count_ss_register++; */
2468 /* count_ss_spilled++; */
2475 } /* while instructions */
2478 } /* while blocks */
2479 count_interface_size += size_interface; /* accummulate the size of the interface (between bb boundaries) */
2480 if (in_register) count_method_in_register++;
2482 #endif /* defined(ENABLE_STATISTICS) */
2486 * These are local overrides for various environment variables in Emacs.
2487 * Please do not remove this and leave it at the end of the file, where
2488 * Emacs will automagically detect them.
2489 * ---------------------------------------------------------------------
2492 * indent-tabs-mode: t
2496 * vim:noexpandtab:sw=4:ts=4: