1 /* src/vm/jit/allocator/simplereg.c - register allocator
3 Copyright (C) 1996-2005, 2007 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 $Id: simplereg.c 7246 2007-01-29 18:49:05Z twisti $
39 #include "mm/memory.h"
41 #include "vm/builtin.h"
42 #include "vm/exceptions.h"
43 #include "vm/stringlocal.h"
45 #include "vm/jit/reg.h"
46 #include "vm/jit/allocator/simplereg.h"
47 #include "vm/jit/show.h"
49 #include "vmcore/method.h"
50 #include "vmcore/options.h"
51 #include "vmcore/resolve.h"
55 # define LOG(args) printf args
61 /* function prototypes for this file ******************************************/
63 static void simplereg_allocate_interfaces(jitdata *jd);
64 static void simplereg_allocate_locals(jitdata *jd);
65 static void simplereg_allocate_temporaries(jitdata *jd);
68 /* total number of registers */
70 #if defined(HAS_ADDRESS_REGISTER_FILE)
71 #define TOTAL_REG_CNT (INT_REG_CNT + FLT_REG_CNT + ADR_REG_CNT)
73 #define TOTAL_REG_CNT (INT_REG_CNT + FLT_REG_CNT)
77 /* macros for handling register stacks ****************************************/
79 #define AVAIL_FRONT(cnt, limit) ((cnt) < (limit))
80 #define AVAIL_BACK(cnt) ((cnt) > 0)
82 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
83 #define AVAIL_FRONT_INT(cnt, limit) ((cnt) < (limit) - intregsneeded)
84 #define AVAIL_BACK_INT(cnt) ((cnt) > intregsneeded)
86 #define AVAIL_FRONT_INT(cnt, limit) AVAIL_FRONT(cnt, limit)
87 #define AVAIL_BACK_INT(cnt) AVAIL_BACK(cnt)
90 #define POP_FRONT(stk, cnt, reg) do { reg = stk[cnt++]; } while (0)
91 #define POP_BACK(stk, cnt, reg) do { reg = stk[--cnt]; } while (0)
92 #define PUSH_FRONT(stk, cnt, reg) do { stk[--cnt] = (reg); } while (0)
93 #define PUSH_BACK(stk, cnt, reg) do { stk[cnt++] = (reg); } while (0)
95 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
96 #define POP_FRONT_INT(stk, cnt, reg) \
98 if (intregsneeded) { \
99 reg = PACK_REGS(stk[cnt], stk[cnt+1]); \
103 POP_FRONT(stk, cnt, reg); \
106 #define POP_FRONT_INT(stk, cnt, reg) POP_FRONT(stk, cnt, reg)
109 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
110 #define POP_BACK_INT(stk, cnt, reg) \
112 if (intregsneeded) { \
114 reg = PACK_REGS(stk[cnt], stk[cnt+1]); \
117 POP_BACK(stk, cnt, reg); \
120 #define POP_BACK_INT(stk, cnt, reg) POP_BACK(stk, cnt, reg)
123 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
124 #define PUSH_BACK_INT(stk, cnt, reg) \
126 if (intregsneeded) { \
127 stk[cnt] = GET_LOW_REG(reg); \
128 stk[cnt + 1] = GET_HIGH_REG(reg); \
132 PUSH_BACK(stk, cnt, reg); \
135 #define PUSH_BACK_INT(stk, cnt, reg) PUSH_BACK(stk, cnt, reg)
138 #define AVAIL_ARG_FLT AVAIL_FRONT(rd->argfltreguse, FLT_ARG_CNT)
139 #define AVAIL_TMP_FLT AVAIL_BACK(rd->tmpfltreguse)
140 #define AVAIL_SAV_FLT AVAIL_BACK(rd->savfltreguse)
142 #define AVAIL_ARG_ADR AVAIL_FRONT(rd->argadrreguse, ADR_ARG_CNT)
143 #define AVAIL_TMP_ADR AVAIL_BACK(rd->tmpadrreguse)
144 #define AVAIL_SAV_ADR AVAIL_BACK(rd->savadrreguse)
146 #define AVAIL_ARG_INT AVAIL_FRONT_INT(rd->argintreguse, INT_ARG_CNT)
147 #define AVAIL_TMP_INT AVAIL_BACK_INT(rd->tmpintreguse)
148 #define AVAIL_SAV_INT AVAIL_BACK_INT(rd->savintreguse)
150 #define AVAIL_FREE_ARG_FLT AVAIL_BACK(rd->freeargflttop)
151 #define AVAIL_FREE_TMP_FLT AVAIL_BACK(rd->freetmpflttop)
152 #define AVAIL_FREE_SAV_FLT AVAIL_BACK(rd->freesavflttop)
154 #define AVAIL_FREE_ARG_ADR AVAIL_BACK(rd->freeargadrtop)
155 #define AVAIL_FREE_TMP_ADR AVAIL_BACK(rd->freetmpadrtop)
156 #define AVAIL_FREE_SAV_ADR AVAIL_BACK(rd->freesavadrtop)
158 #define AVAIL_FREE_ARG_INT AVAIL_BACK_INT(rd->freearginttop)
159 #define AVAIL_FREE_TMP_INT AVAIL_BACK_INT(rd->freetmpinttop)
160 #define AVAIL_FREE_SAV_INT AVAIL_BACK_INT(rd->freesavinttop)
162 #define TAKE_ARG_FLT(r) POP_FRONT(rd->argfltregs, rd->argfltreguse, r)
163 #define TAKE_TMP_FLT(r) POP_BACK(rd->tmpfltregs, rd->tmpfltreguse, r)
164 #define TAKE_SAV_FLT(r) POP_BACK(rd->savfltregs, rd->savfltreguse, r)
166 #define TAKE_ARG_ADR(r) POP_FRONT(rd->argadrregs, rd->argadrreguse, r)
167 #define TAKE_TMP_ADR(r) POP_BACK(rd->tmpadrregs, rd->tmpadrreguse, r)
168 #define TAKE_SAV_ADR(r) POP_BACK(rd->savadrregs, rd->savadrreguse, r)
170 #define TAKE_ARG_INT(r) POP_FRONT_INT(rd->argintregs, rd->argintreguse, r)
171 #define TAKE_TMP_INT(r) POP_BACK_INT(rd->tmpintregs, rd->tmpintreguse, r)
172 #define TAKE_SAV_INT(r) POP_BACK_INT(rd->savintregs, rd->savintreguse, r)
174 #define TAKE_FREE_ARG_FLT(r) POP_BACK(rd->freeargfltregs, rd->freeargflttop, r)
175 #define TAKE_FREE_TMP_FLT(r) POP_BACK(rd->freetmpfltregs, rd->freetmpflttop, r)
176 #define TAKE_FREE_SAV_FLT(r) POP_BACK(rd->freesavfltregs, rd->freesavflttop, r)
178 #define TAKE_FREE_ARG_ADR(r) POP_BACK(rd->freeargadrregs, rd->freeargadrtop, r)
179 #define TAKE_FREE_TMP_ADR(r) POP_BACK(rd->freetmpadrregs, rd->freetmpadrtop, r)
180 #define TAKE_FREE_SAV_ADR(r) POP_BACK(rd->freesavadrregs, rd->freesavadrtop, r)
182 #define TAKE_FREE_ARG_INT(r) POP_BACK_INT(rd->freeargintregs, rd->freearginttop, r)
183 #define TAKE_FREE_TMP_INT(r) POP_BACK_INT(rd->freetmpintregs, rd->freetmpinttop, r)
184 #define TAKE_FREE_SAV_INT(r) POP_BACK_INT(rd->freesavintregs, rd->freesavinttop, r)
186 #define PUSH_FREE_ARG_FLT(r) PUSH_BACK(rd->freeargfltregs, rd->freeargflttop, r)
187 #define PUSH_FREE_TMP_FLT(r) PUSH_BACK(rd->freetmpfltregs, rd->freetmpflttop, r)
188 #define PUSH_FREE_SAV_FLT(r) PUSH_BACK(rd->freesavfltregs, rd->freesavflttop, r)
190 #define PUSH_FREE_ARG_ADR(r) PUSH_BACK(rd->freeargadrregs, rd->freeargadrtop, r)
191 #define PUSH_FREE_TMP_ADR(r) PUSH_BACK(rd->freetmpadrregs, rd->freetmpadrtop, r)
192 #define PUSH_FREE_SAV_ADR(r) PUSH_BACK(rd->freesavadrregs, rd->freesavadrtop, r)
194 #define PUSH_FREE_ARG_INT(r) PUSH_BACK_INT(rd->freeargintregs, rd->freearginttop, r)
195 #define PUSH_FREE_TMP_INT(r) PUSH_BACK_INT(rd->freetmpintregs, rd->freetmpinttop, r)
196 #define PUSH_FREE_SAV_INT(r) PUSH_BACK_INT(rd->freesavintregs, rd->freesavinttop, r)
199 /* macros for allocating memory slots ****************************************/
201 #define NEW_MEM_SLOT(r) \
204 rd->memuse += memneeded + 1; \
207 #define NEW_MEM_SLOT_ALIGNED(r) \
209 if ( (memneeded) && (rd->memuse & 1)) \
212 rd->memuse += memneeded + 1; \
215 #define NEW_MEM_SLOT_ALIGNED_REUSE_PADDING(r) \
217 if ( (memneeded) && (rd->memuse & 1)) { \
218 PUSH_BACK(rd->freemem, rd->freememtop, rd->memuse); \
222 rd->memuse += memneeded + 1; \
225 #if defined(ALIGN_LONGS_IN_MEMORY)
226 #define NEW_MEM_SLOT_INT_LNG(r) NEW_MEM_SLOT_ALIGNED(r)
228 #define NEW_MEM_SLOT_INT_LNG(r) NEW_MEM_SLOT(r)
231 #if defined(ALIGN_DOUBLES_IN_MEMORY)
232 #define NEW_MEM_SLOT_FLT_DBL(r) NEW_MEM_SLOT_ALIGNED(r)
234 #define NEW_MEM_SLOT_FLT_DBL(r) NEW_MEM_SLOT(r)
237 #if defined(ALIGN_LONGS_IN_MEMORY) || defined(ALIGN_DOUBLES_IN_MEMORY)
238 #define NEW_MEM_SLOT_REUSE_PADDING(r) NEW_MEM_SLOT_ALIGNED_REUSE_PADDING(r)
240 #define NEW_MEM_SLOT_REUSE_PADDING(r) NEW_MEM_SLOT(r)
244 /* macros for creating/freeing temporary variables ***************************/
246 #define NEW_TEMP_REG(index) \
247 if ( ((index) >= jd->localcount) \
248 && (!(VAR(index)->flags & (INOUT | PREALLOC))) ) \
249 simplereg_new_temp(jd, (index))
252 #define FREE_TEMP_REG(index) \
253 if (((index) > jd->localcount) \
254 && (!(VAR(index)->flags & (PREALLOC)))) \
255 simplereg_free_temp(jd, (index))
258 /* macro for getting a unique register index *********************************/
260 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
261 #define REG_INDEX_NON_ADR(regoff, type) \
262 (IS_FLT_DBL_TYPE(type) ? (INT_REG_CNT + (regoff)) : (GET_LOW_REG(regoff)))
264 #define REG_INDEX_NON_ADR(regoff, type) \
265 (IS_FLT_DBL_TYPE(type) ? (INT_REG_CNT + (regoff)) : (regoff))
268 #if defined(HAS_ADDRESS_REGISTER_FILE)
269 #define REG_INDEX(regoff, type) \
270 (IS_ADR_TYPE(type) ? (regoff) : (ADR_REG_CNT + REG_INDEX_NON_ADR(regoff, type)))
272 #define REG_INDEX(regoff, type) REG_INDEX_NON_ADR(regoff, type)
276 /* regalloc ********************************************************************
278 Does a simple register allocation.
280 *******************************************************************************/
282 bool regalloc(jitdata *jd)
284 /* There is a problem with the use of unused float argument
285 registers in leafmethods for stackslots on c7 (2 * Dual Core
286 AMD Opteron(tm) Processor 270) - runtime for the jvm98 _mtrt
287 benchmark is heaviliy increased. This could be prevented by
288 setting rd->argfltreguse to FLT_ARG_CNT before calling
289 simplereg_allocate_temporaries and setting it back to the original
290 value before calling simplereg_allocate_locals. */
292 simplereg_allocate_interfaces(jd);
293 simplereg_allocate_temporaries(jd);
294 simplereg_allocate_locals(jd);
302 /* simplereg_allocate_interfaces ***********************************************
304 Allocates registers for all interface variables.
306 *******************************************************************************/
308 static void simplereg_allocate_interfaces(jitdata *jd)
315 int intalloc, fltalloc; /* Remember allocated Register/Memory offset */
316 /* in case more vars are packed into this interface slot */
318 /* Allocate LNG and DBL types first to ensure 2 memory slots or */
319 /* registers on HAS_4BYTE_STACKSLOT architectures. */
320 int typeloop[] = { TYPE_LNG, TYPE_DBL, TYPE_INT, TYPE_FLT, TYPE_ADR };
322 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
326 /* get required compiler data */
332 /* rd->memuse was already set in stack.c to allocate stack space
333 for passing arguments to called methods. */
335 #if defined(__I386__)
336 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
337 /* reserve 0(%esp) for Monitorenter/exit Argument on i386 */
343 if (jd->isleafmethod) {
344 /* Reserve argument register, which will be used for Locals acting */
346 if (rd->argintreguse < m->parseddesc->argintreguse)
347 rd->argintreguse = m->parseddesc->argintreguse;
348 if (rd->argfltreguse < m->parseddesc->argfltreguse)
349 rd->argfltreguse = m->parseddesc->argfltreguse;
350 #ifdef HAS_ADDRESS_REGISTER_FILE
351 if (rd->argadrreguse < m->parseddesc->argadrreguse)
352 rd->argadrreguse = m->parseddesc->argadrreguse;
356 for (s = 0; s < jd->maxinterfaces; s++) {
357 intalloc = -1; fltalloc = -1;
359 /* check if the interface at this stack depth must be a SAVEDVAR */
363 for (tt = 0; tt <=4; tt++) {
364 if ((t = jd->interface_map[s * 5 + tt].flags) != UNUSED) {
365 saved |= t & SAVEDVAR;
369 /* allocate reg/mem for each type the interface is used as */
371 for (tt = 0; tt <= 4; tt++) {
373 if (jd->interface_map[s * 5 + t].flags == UNUSED)
377 regoff = -1; /* initialize to invalid value */
379 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
380 intregsneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
383 #if defined(HAS_4BYTE_STACKSLOT)
384 memneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
388 #if defined(HAS_ADDRESS_REGISTER_FILE)
389 if (IS_ADR_TYPE(t)) {
390 if (!jd->isleafmethod && AVAIL_ARG_ADR) {
392 TAKE_ARG_ADR(regoff);
394 else if (AVAIL_TMP_ADR) {
395 TAKE_TMP_ADR(regoff);
397 else if (AVAIL_SAV_ADR) {
399 TAKE_SAV_ADR(regoff);
403 regoff = rd->memuse++;
406 else /* !IS_ADR_TYPE */
407 #endif /* defined(HAS_ADDRESS_REGISTER_FILE) */
409 if (IS_FLT_DBL_TYPE(t)) {
411 /* Reuse memory slot(s)/register(s) for shared interface slots */
412 flags |= jd->interface_map[fltalloc].flags & ~SAVEDVAR;
413 regoff = jd->interface_map[fltalloc].regoff;
415 else if (AVAIL_ARG_FLT) {
417 TAKE_ARG_FLT(regoff);
419 else if (AVAIL_TMP_FLT) {
420 TAKE_TMP_FLT(regoff);
422 else if (AVAIL_SAV_FLT) {
424 TAKE_SAV_FLT(regoff);
428 NEW_MEM_SLOT_FLT_DBL(regoff);
430 fltalloc = s * 5 + t;
432 else { /* !IS_FLT_DBL_TYPE(t) */
433 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
435 * for i386 put all longs in memory
437 if (IS_2_WORD_TYPE(t)) {
439 NEW_MEM_SLOT_INT_LNG(regoff);
442 #endif /* defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE...GISTERS) */
444 /* Reuse memory slot(s)/register(s) for shared interface slots */
445 flags |= jd->interface_map[intalloc].flags & ~SAVEDVAR;
446 regoff = jd->interface_map[intalloc].regoff;
447 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
448 /* reuse lower half */
449 if (!(flags & INMEMORY)
450 && IS_2_WORD_TYPE(intalloc % 5))
451 regoff = GET_LOW_REG(regoff);
457 TAKE_ARG_INT(regoff);
459 else if (AVAIL_TMP_INT) {
460 TAKE_TMP_INT(regoff);
462 else if (AVAIL_SAV_INT) {
464 TAKE_SAV_INT(regoff);
468 NEW_MEM_SLOT_INT_LNG(regoff);
472 intalloc = s * 5 + t;
473 } /* if (IS_FLT_DBL_TYPE(t)) */
477 /* now the same like above, but without a chance to take a temporary register */
478 #ifdef HAS_ADDRESS_REGISTER_FILE
479 if (IS_ADR_TYPE(t)) {
481 TAKE_SAV_ADR(regoff);
485 regoff = rd->memuse++;
491 if (IS_FLT_DBL_TYPE(t)) {
493 flags |= jd->interface_map[fltalloc].flags & ~SAVEDVAR;
494 regoff = jd->interface_map[fltalloc].regoff;
498 TAKE_SAV_FLT(regoff);
502 NEW_MEM_SLOT_FLT_DBL(regoff);
505 fltalloc = s * 5 + t;
507 else { /* IS_INT_LNG */
508 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
510 * for i386 put all longs in memory
512 if (IS_2_WORD_TYPE(t)) {
514 NEW_MEM_SLOT_INT_LNG(regoff);
520 flags |= jd->interface_map[intalloc].flags & ~SAVEDVAR;
521 regoff = jd->interface_map[intalloc].regoff;
522 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
523 /* reuse lower half */
524 if (!(flags & INMEMORY)
525 && IS_2_WORD_TYPE(intalloc % 5))
526 regoff = GET_LOW_REG(regoff);
531 TAKE_SAV_INT(regoff);
535 NEW_MEM_SLOT_INT_LNG(regoff);
540 } /* if (IS_FLT_DBL_TYPE(t) else */
541 } /* if (IS_ADR_TYPE(t)) else */
542 } /* if (saved) else */
546 jd->interface_map[5*s + t].flags = flags | INOUT;
547 jd->interface_map[5*s + t].regoff = regoff;
553 /* simplereg_allocate_locals_leafmethod ****************************************
555 Allocates registers for all local variables of a leafmethod.
557 *******************************************************************************/
559 static void simplereg_allocate_locals_leafmethod(jitdata *jd)
567 int intalloc, fltalloc;
569 int intregsneeded = 0;
571 int typeloop[] = { TYPE_LNG, TYPE_DBL, TYPE_INT, TYPE_FLT, TYPE_ADR };
572 int fargcnt, iargcnt;
573 #ifdef HAS_ADDRESS_REGISTER_FILE
577 /* get required compiler data */
585 iargcnt = rd->argintreguse;
586 fargcnt = rd->argfltreguse;
587 #ifdef HAS_ADDRESS_REGISTER_FILE
588 aargcnt = rd->argadrreguse;
590 for (p = 0, s = 0; s < jd->maxlocals; s++, p++) {
591 intalloc = -1; fltalloc = -1;
592 for (tt = 0; tt <= 4; tt++) {
594 lm = jd->local_map[s * 5 + t];
600 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
601 intregsneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
603 #if defined(HAS_4BYTE_STACKSLOT)
604 memneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
610 * #ifdef HAS_ADDRESS_REGISTER_FILE
617 * } else { / int & lng
621 * must not to be changed!
624 #ifdef HAS_ADDRESS_REGISTER_FILE
625 if (IS_ADR_TYPE(t)) {
626 if ((p < md->paramcount) && !md->params[p].inmemory) {
628 v->vv.regoff = rd->argadrregs[md->params[p].regoff];
630 else if (AVAIL_TMP_ADR) {
632 TAKE_TMP_ADR(v->vv.regoff);
634 /* use unused argument registers as local registers */
635 else if ((p >= md->paramcount) &&
636 (aargcnt < ADR_ARG_CNT))
639 POP_FRONT(rd->argadrregs, aargcnt, v->vv.regoff);
641 else if (AVAIL_SAV_ADR) {
643 TAKE_SAV_ADR(v->vv.regoff);
646 v->flags |= INMEMORY;
647 v->vv.regoff = rd->memuse++;
652 if (IS_FLT_DBL_TYPE(t)) {
654 v->flags = VAR(fltalloc)->flags;
655 v->vv.regoff = VAR(fltalloc)->vv.regoff;
657 #if !defined(SUPPORT_PASS_FLOATARGS_IN_INTREGS)
658 /* We can only use float arguments as local variables,
659 * if we do not pass them in integer registers. */
660 else if ((p < md->paramcount) &&
661 !md->params[p].inmemory)
664 v->vv.regoff = rd->argfltregs[md->params[p].regoff];
667 else if (AVAIL_TMP_FLT) {
669 TAKE_TMP_FLT(v->vv.regoff);
671 /* use unused argument registers as local registers */
672 else if ((p >= md->paramcount) &&
673 (fargcnt < FLT_ARG_CNT))
676 POP_FRONT(rd->argfltregs, fargcnt, v->vv.regoff);
678 else if (AVAIL_SAV_FLT) {
680 TAKE_SAV_FLT(v->vv.regoff);
684 NEW_MEM_SLOT_FLT_DBL(v->vv.regoff);
686 fltalloc = jd->local_map[s * 5 + t];
690 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
692 * for i386 put all longs in memory
694 if (IS_2_WORD_TYPE(t)) {
696 NEW_MEM_SLOT_INT_LNG(v->vv.regoff);
702 v->flags = VAR(intalloc)->flags;
703 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
704 if (!(v->flags & INMEMORY)
705 && IS_2_WORD_TYPE(VAR(intalloc)->type))
706 v->vv.regoff = GET_LOW_REG(
707 VAR(intalloc)->vv.regoff);
710 v->vv.regoff = VAR(intalloc)->vv.regoff;
712 else if ((p < md->paramcount) &&
713 !md->params[p].inmemory)
716 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
717 if (IS_2_WORD_TYPE(t))
718 v->vv.regoff = PACK_REGS(
719 rd->argintregs[GET_LOW_REG(md->params[p].regoff)],
720 rd->argintregs[GET_HIGH_REG(md->params[p].regoff)]);
724 rd->argintregs[md->params[p].regoff];
726 else if (AVAIL_TMP_INT) {
728 TAKE_TMP_INT(v->vv.regoff);
731 * use unused argument registers as local registers
733 else if ((p >= m->parseddesc->paramcount) &&
734 (iargcnt + intregsneeded < INT_ARG_CNT))
737 POP_FRONT_INT(rd->argintregs, iargcnt, v->vv.regoff);
739 else if (AVAIL_SAV_INT) {
741 TAKE_SAV_INT(v->vv.regoff);
745 NEW_MEM_SLOT_INT_LNG(v->vv.regoff);
748 intalloc = jd->local_map[s * 5 + t];
750 #ifdef HAS_ADDRESS_REGISTER_FILE
753 } /* for (tt=0;...) */
755 /* If the current parameter is a 2-word type, the next local slot */
758 if (p < md->paramcount)
759 if (IS_2_WORD_TYPE(md->paramtypes[p].type))
764 /* simplereg_allocate_locals ***************************************************
766 Allocates registers for all local variables.
768 *******************************************************************************/
770 static void simplereg_allocate_locals(jitdata *jd)
776 int intalloc, fltalloc;
779 int typeloop[] = { TYPE_LNG, TYPE_DBL, TYPE_INT, TYPE_FLT, TYPE_ADR };
780 #ifdef SUPPORT_COMBINE_INTEGER_REGISTERS
784 /* get required compiler data */
789 if (jd->isleafmethod) {
790 simplereg_allocate_locals_leafmethod(jd);
794 for (s = 0; s < jd->maxlocals; s++) {
795 intalloc = -1; fltalloc = -1;
796 for (tt=0; tt<=4; tt++) {
799 lm = jd->local_map[s * 5 + t];
805 #ifdef SUPPORT_COMBINE_INTEGER_REGISTERS
806 intregsneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
809 #if defined(HAS_4BYTE_STACKSLOT)
810 memneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
813 #ifdef HAS_ADDRESS_REGISTER_FILE
814 if (IS_ADR_TYPE(t)) {
817 TAKE_SAV_ADR(v->vv.regoff);
821 v->vv.regoff = rd->memuse++;
826 if (IS_FLT_DBL_TYPE(t)) {
828 v->flags = VAR(fltalloc)->flags;
829 v->vv.regoff = VAR(fltalloc)->vv.regoff;
831 else if (AVAIL_SAV_FLT) {
833 TAKE_SAV_FLT(v->vv.regoff);
837 NEW_MEM_SLOT_FLT_DBL(v->vv.regoff);
839 fltalloc = jd->local_map[s * 5 + t];
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(t)) {
848 NEW_MEM_SLOT_INT_LNG(v->vv.regoff);
853 v->flags = VAR(intalloc)->flags;
854 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
855 if (!(v->flags & INMEMORY)
856 && IS_2_WORD_TYPE(VAR(intalloc)->type))
857 v->vv.regoff = GET_LOW_REG(
858 VAR(intalloc)->vv.regoff);
861 v->vv.regoff = VAR(intalloc)->vv.regoff;
863 else if (AVAIL_SAV_INT) {
865 TAKE_SAV_INT(v->vv.regoff);
869 NEW_MEM_SLOT_INT_LNG(v->vv.regoff);
871 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
874 intalloc = jd->local_map[s * 5 + t];
876 #ifdef HAS_ADDRESS_REGISTER_FILE
884 static void simplereg_init(jitdata *jd, registerdata *rd)
889 #if defined(HAS_4BYTE_STACKSLOT)
890 rd->freememtop_2 = 0;
893 rd->freetmpinttop = 0;
894 rd->freesavinttop = 0;
895 rd->freetmpflttop = 0;
896 rd->freesavflttop = 0;
897 #ifdef HAS_ADDRESS_REGISTER_FILE
898 rd->freetmpadrtop = 0;
899 rd->freesavadrtop = 0;
902 rd->freearginttop = 0;
903 rd->freeargflttop = 0;
904 #ifdef HAS_ADDRESS_REGISTER_FILE
905 rd->freeargadrtop = 0;
908 rd->regisoutvar = DMNEW(int, TOTAL_REG_CNT);
909 rd->regcopycount = DMNEW(int, TOTAL_REG_CNT);
910 MZERO(rd->regcopycount, int, TOTAL_REG_CNT);
912 /* memcopycount is dynamically allocated when needed */
914 rd->memcopycount = NULL;
915 rd->memcopycountsize = 0;
917 rd->intusedinout = DMNEW(int, INT_REG_CNT);
918 MZERO(rd->intusedinout, int, INT_REG_CNT);
919 rd->fltusedinout = DMNEW(int, FLT_REG_CNT);
920 MZERO(rd->fltusedinout, int, FLT_REG_CNT);
922 /* record the interface registers as used */
924 for (i=0; i<rd->argintreguse; ++i)
925 rd->intusedinout[rd->argintregs[i]] = 1;
926 for (i=rd->tmpintreguse; i<INT_TMP_CNT; ++i)
927 rd->intusedinout[rd->tmpintregs[i]] = 1;
928 for (i=rd->savintreguse; i<INT_SAV_CNT; ++i)
929 rd->intusedinout[rd->savintregs[i]] = 1;
931 for (i=0; i<rd->argfltreguse; ++i)
932 rd->fltusedinout[rd->argfltregs[i]] = 1;
933 for (i=rd->tmpfltreguse; i<FLT_TMP_CNT; ++i)
934 rd->fltusedinout[rd->tmpfltregs[i]] = 1;
935 for (i=rd->savfltreguse; i<FLT_SAV_CNT; ++i)
936 rd->fltusedinout[rd->savfltregs[i]] = 1;
938 #ifdef HAS_ADDRESS_REGISTER_FILE
939 rd->adrusedinout = DMNEW(int, ADR_REG_CNT);
940 MZERO(rd->adrusedinout, int, ADR_REG_CNT);
942 for (i=0; i<rd->argadrreguse; ++i)
943 rd->adrusedinout[rd->argadrregs[i]] = 1;
944 for (i=rd->tmpadrreguse; i<ADR_TMP_CNT; ++i)
945 rd->adrusedinout[rd->tmpadrregs[i]] = 1;
946 for (i=rd->savadrreguse; i<ADR_SAV_CNT; ++i)
947 rd->adrusedinout[rd->savadrregs[i]] = 1;
952 static void simplereg_init_block(registerdata *rd)
956 /* remove all interface registers from the free lists */
958 for (i=0; i<rd->freearginttop; ++i)
959 if (rd->intusedinout[rd->freeargintregs[i]]) {
960 rd->freeargintregs[i--] = rd->freeargintregs[--rd->freearginttop];
962 for (i=0; i<rd->freetmpinttop; ++i)
963 if (rd->intusedinout[rd->freetmpintregs[i]]) {
964 rd->freetmpintregs[i--] = rd->freetmpintregs[--rd->freetmpinttop];
966 for (i=0; i<rd->freesavinttop; ++i)
967 if (rd->intusedinout[rd->freesavintregs[i]]) {
968 rd->freesavintregs[i--] = rd->freesavintregs[--rd->freesavinttop];
971 for (i=0; i<rd->freeargflttop; ++i)
972 if (rd->fltusedinout[rd->freeargfltregs[i]]) {
973 rd->freeargfltregs[i--] = rd->freeargfltregs[--rd->freeargflttop];
975 for (i=0; i<rd->freetmpflttop; ++i)
976 if (rd->fltusedinout[rd->freetmpfltregs[i]]) {
977 rd->freetmpfltregs[i--] = rd->freetmpfltregs[--rd->freetmpflttop];
979 for (i=0; i<rd->freesavflttop; ++i)
980 if (rd->fltusedinout[rd->freesavfltregs[i]]) {
981 rd->freesavfltregs[i--] = rd->freesavfltregs[--rd->freesavflttop];
984 #ifdef HAS_ADDRESS_REGISTER_FILE
985 for (i=0; i<rd->freeargadrtop; ++i)
986 if (rd->adrusedinout[rd->freeargadrregs[i]]) {
987 rd->freeargadrregs[i--] = rd->freeargadrregs[--rd->freeargadrtop];
989 for (i=0; i<rd->freetmpadrtop; ++i)
990 if (rd->adrusedinout[rd->freetmpadrregs[i]]) {
991 rd->freetmpadrregs[i--] = rd->freetmpadrregs[--rd->freetmpadrtop];
993 for (i=0; i<rd->freesavadrtop; ++i)
994 if (rd->adrusedinout[rd->freesavadrregs[i]]) {
995 rd->freesavadrregs[i--] = rd->freesavadrregs[--rd->freesavadrtop];
1001 static void simplereg_new_temp(jitdata *jd, s4 index)
1003 #ifdef SUPPORT_COMBINE_INTEGER_REGISTERS
1014 /* assert that constants are not allocated */
1016 assert(v->type != TYPE_RET);
1018 /* Try to allocate a saved register if there is no temporary one */
1019 /* available. This is what happens during the second run. */
1020 tryagain = (v->flags & SAVEDVAR) ? 1 : 2;
1022 #ifdef SUPPORT_COMBINE_INTEGER_REGISTERS
1023 intregsneeded = (IS_2_WORD_TYPE(v->type)) ? 1 : 0;
1026 #if defined(HAS_4BYTE_STACKSLOT)
1027 memneeded = (IS_2_WORD_TYPE(v->type)) ? 1 : 0;
1032 for(; tryagain; --tryagain) {
1033 if (tryagain == 1) {
1034 if (!(v->flags & SAVEDVAR))
1036 #ifdef HAS_ADDRESS_REGISTER_FILE
1037 if (IS_ADR_TYPE(v->type)) {
1038 if (AVAIL_FREE_SAV_ADR) {
1039 TAKE_FREE_SAV_ADR(v->vv.regoff);
1042 else if (AVAIL_SAV_ADR) {
1043 TAKE_SAV_ADR(v->vv.regoff);
1050 if (IS_FLT_DBL_TYPE(v->type)) {
1051 if (AVAIL_FREE_SAV_FLT) {
1052 TAKE_FREE_SAV_FLT(v->vv.regoff);
1055 else if (AVAIL_SAV_FLT) {
1056 TAKE_SAV_FLT(v->vv.regoff);
1061 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
1063 * for i386 put all longs in memory
1065 if (!IS_2_WORD_TYPE(v->type))
1068 if (AVAIL_FREE_SAV_INT) {
1069 TAKE_FREE_SAV_INT(v->vv.regoff);
1072 else if (AVAIL_SAV_INT) {
1073 TAKE_SAV_INT(v->vv.regoff);
1080 else { /* tryagain == 2 */
1081 #ifdef HAS_ADDRESS_REGISTER_FILE
1082 if (IS_ADR_TYPE(v->type)) {
1083 if (AVAIL_FREE_TMP_ADR) {
1084 TAKE_FREE_TMP_ADR(v->vv.regoff);
1087 else if (AVAIL_TMP_ADR) {
1088 TAKE_TMP_ADR(v->vv.regoff);
1095 if (IS_FLT_DBL_TYPE(v->type)) {
1096 if (AVAIL_FREE_ARG_FLT) {
1098 TAKE_FREE_ARG_FLT(v->vv.regoff);
1101 else if (AVAIL_ARG_FLT) {
1103 TAKE_ARG_FLT(v->vv.regoff);
1106 else if (AVAIL_FREE_TMP_FLT) {
1107 TAKE_FREE_TMP_FLT(v->vv.regoff);
1110 else if (AVAIL_TMP_FLT) {
1111 TAKE_TMP_FLT(v->vv.regoff);
1117 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
1119 * for i386 put all longs in memory
1121 if (!IS_2_WORD_TYPE(v->type))
1124 if (AVAIL_FREE_ARG_INT) {
1126 TAKE_FREE_ARG_INT(v->vv.regoff);
1129 else if (AVAIL_ARG_INT) {
1131 TAKE_ARG_INT(v->vv.regoff);
1134 else if (AVAIL_FREE_TMP_INT) {
1135 TAKE_FREE_TMP_INT(v->vv.regoff);
1138 else if (AVAIL_TMP_INT) {
1139 TAKE_TMP_INT(v->vv.regoff);
1142 } /* if (!IS_2_WORD_TYPE(s->type)) */
1143 } /* if (IS_FLT_DBL_TYPE(s->type)) */
1144 } /* if (IS_ADR_TYPE(s->type)) */
1145 } /* if (tryagain == 1) else */
1146 } /* for(; tryagain; --tryagain) */
1148 /* spill to memory */
1150 v->flags |= INMEMORY;
1152 #if defined(HAS_4BYTE_STACKSLOT)
1153 if ((memneeded == 1) && (rd->freememtop_2 > 0))
1154 POP_BACK(rd->freemem_2, rd->freememtop_2, v->vv.regoff);
1156 #endif /*defined(HAS_4BYTE_STACKSLOT) */
1157 if ((memneeded == 0) && (rd->freememtop > 0))
1158 POP_BACK(rd->freemem, rd->freememtop, v->vv.regoff);
1160 NEW_MEM_SLOT_REUSE_PADDING(v->vv.regoff);
1164 static void simplereg_free(registerdata *rd, s4 flags, s4 regoff, s4 type)
1166 /* assert that constants are not freed */
1168 assert(type != TYPE_RET);
1170 /* if this is a copy of another variable, just decrement the copy counter */
1172 /* XXX split reg/mem variables on arm may need special handling here */
1174 if (flags & INMEMORY) {
1178 if (regoff < rd->memcopycountsize && rd->memcopycount[regoff]) {
1179 rd->memcopycount[regoff]--;
1186 regindex = REG_INDEX(regoff, type);
1188 /* do not free interface registers that are needed as outvars */
1190 if (flags & INOUT) {
1191 if (rd->regisoutvar[regindex]) {
1192 LOG(("DONT FREE f=%02x r=%d t=%d\n", flags, regoff, type));
1196 LOG(("FREEING INVAR f=%02x r=%d t=%d\n", flags, regoff, type));
1199 if (rd->regcopycount[regindex]) {
1200 rd->regcopycount[regindex]--;
1205 if (flags & INMEMORY) {
1206 #if defined(HAS_4BYTE_STACKSLOT)
1207 if (IS_2_WORD_TYPE(type))
1208 PUSH_BACK(rd->freemem_2, rd->freememtop_2, regoff);
1211 PUSH_BACK(rd->freemem, rd->freememtop, regoff);
1216 /* freeing a register */
1218 #ifdef HAS_ADDRESS_REGISTER_FILE
1219 if (IS_ADR_TYPE(type)) {
1220 if (flags & (SAVEDVAR | SAVREG))
1221 PUSH_FREE_SAV_ADR(regoff);
1223 PUSH_FREE_TMP_ADR(regoff);
1226 else if (IS_FLT_DBL_TYPE(type)) {
1227 if (flags & (SAVEDVAR | SAVREG))
1228 PUSH_FREE_SAV_FLT(regoff);
1229 else if (flags & ARGREG)
1230 PUSH_FREE_ARG_FLT(regoff);
1232 PUSH_FREE_TMP_FLT(regoff);
1234 else { /* IS_INT_LNG_TYPE */
1235 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
1236 s4 intregsneeded = (IS_2_WORD_TYPE(type)) ? 1 : 0;
1239 if (flags & (SAVEDVAR | SAVREG))
1240 PUSH_FREE_SAV_INT(regoff);
1241 else if (flags & ARGREG)
1242 PUSH_FREE_ARG_INT(regoff);
1244 PUSH_FREE_TMP_INT(regoff);
1249 static inline void simplereg_free_temp(jitdata *jd, s4 index)
1255 simplereg_free(jd->rd, v->flags, v->vv.regoff, v->type);
1259 static bool simplereg_alloc_dup(jitdata *jd, s4 srcindex, s4 dstindex)
1264 /* do not coalesce local variables here */
1266 if (srcindex <= jd->localcount || dstindex <= jd->localcount)
1272 /* do not coalesce in/out vars or preallocated variables here */
1274 if ((sv->flags | dv->flags) & (INOUT | PREALLOC))
1277 /* if the source is in memory, we can coalesce in any case */
1279 if (sv->flags & INMEMORY) {
1280 dv->flags |= INMEMORY;
1281 dv->vv.regoff = sv->vv.regoff;
1285 /* we do not allocate a REG_TMP to a REG_SAV variable */
1287 if ((sv->flags & SAVEDVAR) != (dv->flags & SAVEDVAR))
1291 dv->vv.regoff = sv->vv.regoff;
1292 dv->flags |= sv->flags & (SAVREG | ARGREG);
1298 /* simplereg_allocate_temporaries **********************************************
1300 Allocate temporary (non-interface, non-local) registers.
1302 *******************************************************************************/
1304 static void simplereg_allocate_temporaries(jitdata *jd)
1312 builtintable_entry *bte;
1321 /* get required compiler data */
1326 /* initialize temp registers */
1328 simplereg_init(jd, rd);
1330 bptr = jd->basicblocks;
1332 while (bptr != NULL) {
1333 if (bptr->flags >= BBREACHED) {
1335 LOG(("\nallocating block L%03d\n", bptr->nr));
1337 simplereg_init_block(rd);
1339 /* assert that all copy counts are zero */
1341 #if !defined(NDEBUG)
1342 for (i=0; i < TOTAL_REG_CNT; ++i)
1343 assert(rd->regcopycount[i] == 0);
1346 /* reset outvar flags */
1348 MZERO(rd->regisoutvar, int, TOTAL_REG_CNT);
1350 /* set allocation of invars */
1352 for (i=0; i<bptr->indepth; ++i)
1354 v = VAR(bptr->invars[i]);
1355 if (v->type == TYPE_RET)
1358 v->vv.regoff = jd->interface_map[5*i + v->type].regoff;
1359 v->flags = jd->interface_map[5*i + v->type].flags;
1361 if (!(v->flags & INMEMORY))
1362 rd->regcopycount[REG_INDEX(v->vv.regoff, v->type)] = 1;
1365 /* set allocation of outvars */
1367 for (i=0; i<bptr->outdepth; ++i)
1369 v = VAR(bptr->outvars[i]);
1370 if (v->type == TYPE_RET)
1373 v->vv.regoff = jd->interface_map[5*i + v->type].regoff;
1374 v->flags = jd->interface_map[5*i + v->type].flags;
1376 if (!(v->flags & INMEMORY)) {
1377 regindex = REG_INDEX(v->vv.regoff, v->type);
1378 rd->regcopycount[regindex] = 1;
1379 rd->regisoutvar[regindex] = 1;
1383 /* free interface registers not used in this block */
1385 for (i=0; i < 5 * jd->maxinterfaces; ++i) {
1387 regoff = jd->interface_map[i].regoff;
1388 flags = jd->interface_map[i].flags;
1390 if (!(flags & INMEMORY)) {
1391 if (!rd->regcopycount[REG_INDEX(regoff, type)]) {
1392 LOG(("MAY REUSE interface register f=%02x r=%d t=%d\n",
1393 flags, regoff, type));
1394 simplereg_free(rd, flags, regoff, type);
1396 /* mark it, so it is not freed again */
1397 rd->regcopycount[REG_INDEX(regoff, type)] = -1;
1402 /* reset copy counts */
1404 MZERO(rd->regcopycount, int, TOTAL_REG_CNT);
1406 /* iterate over ICMDS to allocate temporary variables */
1408 iptr = bptr->iinstr;
1411 while (--len >= 0) {
1413 switch (iptr->opc) {
1419 case ICMD_CHECKNULL:
1424 case ICMD_PUTSTATICCONST:
1425 case ICMD_INLINE_START:
1426 case ICMD_INLINE_END:
1427 case ICMD_INLINE_BODY:
1430 /* pop 0 push 1 const */
1438 /* pop 0 push 1 load */
1445 NEW_TEMP_REG(iptr->dst.varindex);
1459 FREE_TEMP_REG(iptr->sx.s23.s2.varindex);
1460 FREE_TEMP_REG(iptr->s1.varindex);
1461 NEW_TEMP_REG(iptr->dst.varindex);
1475 FREE_TEMP_REG(iptr->sx.s23.s3.varindex);
1476 FREE_TEMP_REG(iptr->sx.s23.s2.varindex);
1477 FREE_TEMP_REG(iptr->s1.varindex);
1480 /* pop 1 push 0 store */
1500 case ICMD_PUTSTATIC:
1501 case ICMD_PUTFIELDCONST:
1503 /* pop 1 push 0 branch */
1506 case ICMD_IFNONNULL:
1522 /* pop 1 push 0 table branch */
1524 case ICMD_TABLESWITCH:
1525 case ICMD_LOOKUPSWITCH:
1527 case ICMD_MONITORENTER:
1528 case ICMD_MONITOREXIT:
1529 FREE_TEMP_REG(iptr->s1.varindex);
1532 /* pop 2 push 0 branch */
1534 case ICMD_IF_ICMPEQ:
1535 case ICMD_IF_ICMPNE:
1536 case ICMD_IF_ICMPLT:
1537 case ICMD_IF_ICMPGE:
1538 case ICMD_IF_ICMPGT:
1539 case ICMD_IF_ICMPLE:
1541 case ICMD_IF_LCMPEQ:
1542 case ICMD_IF_LCMPNE:
1543 case ICMD_IF_LCMPLT:
1544 case ICMD_IF_LCMPGE:
1545 case ICMD_IF_LCMPGT:
1546 case ICMD_IF_LCMPLE:
1548 case ICMD_IF_FCMPEQ:
1549 case ICMD_IF_FCMPNE:
1551 case ICMD_IF_FCMPL_LT:
1552 case ICMD_IF_FCMPL_GE:
1553 case ICMD_IF_FCMPL_GT:
1554 case ICMD_IF_FCMPL_LE:
1556 case ICMD_IF_FCMPG_LT:
1557 case ICMD_IF_FCMPG_GE:
1558 case ICMD_IF_FCMPG_GT:
1559 case ICMD_IF_FCMPG_LE:
1561 case ICMD_IF_DCMPEQ:
1562 case ICMD_IF_DCMPNE:
1564 case ICMD_IF_DCMPL_LT:
1565 case ICMD_IF_DCMPL_GE:
1566 case ICMD_IF_DCMPL_GT:
1567 case ICMD_IF_DCMPL_LE:
1569 case ICMD_IF_DCMPG_LT:
1570 case ICMD_IF_DCMPG_GE:
1571 case ICMD_IF_DCMPG_GT:
1572 case ICMD_IF_DCMPG_LE:
1574 case ICMD_IF_ACMPEQ:
1575 case ICMD_IF_ACMPNE:
1583 case ICMD_IASTORECONST:
1584 case ICMD_LASTORECONST:
1585 case ICMD_AASTORECONST:
1586 case ICMD_BASTORECONST:
1587 case ICMD_CASTORECONST:
1588 case ICMD_SASTORECONST:
1589 FREE_TEMP_REG(iptr->sx.s23.s2.varindex);
1590 FREE_TEMP_REG(iptr->s1.varindex);
1593 /* pop 0 push 1 copy */
1596 /* src === dst->prev (identical Stackslot Element) */
1597 /* src --> dst (copied value, take same reg/mem) */
1599 if (!simplereg_alloc_dup(jd, iptr->s1.varindex, iptr->dst.varindex)) {
1600 NEW_TEMP_REG(iptr->dst.varindex);
1603 v = VAROP(iptr->dst);
1605 if (v->flags & INMEMORY) {
1606 if (v->vv.regoff >= rd->memcopycountsize) {
1607 int newsize = (v->vv.regoff + 1) * 2;
1608 i = rd->memcopycountsize;
1609 rd->memcopycount = DMREALLOC(rd->memcopycount, int, i, newsize);
1610 MZERO(rd->memcopycount + i, int, newsize - i);
1611 rd->memcopycountsize = newsize;
1613 rd->memcopycount[v->vv.regoff]++;
1616 /* XXX split reg/mem variables on arm may need special handling here */
1618 s4 regindex = REG_INDEX(v->vv.regoff, v->type);
1620 rd->regcopycount[regindex]++;
1625 /* pop 1 push 1 move */
1628 if (!simplereg_alloc_dup(jd, iptr->s1.varindex, iptr->dst.varindex)) {
1629 NEW_TEMP_REG(iptr->dst.varindex);
1630 FREE_TEMP_REG(iptr->s1.varindex);
1680 FREE_TEMP_REG(iptr->sx.s23.s2.varindex);
1681 FREE_TEMP_REG(iptr->s1.varindex);
1682 NEW_TEMP_REG(iptr->dst.varindex);
1687 case ICMD_IADDCONST:
1688 case ICMD_ISUBCONST:
1689 case ICMD_IMULCONST:
1693 case ICMD_IANDCONST:
1695 case ICMD_IXORCONST:
1696 case ICMD_ISHLCONST:
1697 case ICMD_ISHRCONST:
1698 case ICMD_IUSHRCONST:
1700 case ICMD_LADDCONST:
1701 case ICMD_LSUBCONST:
1702 case ICMD_LMULCONST:
1706 case ICMD_LANDCONST:
1708 case ICMD_LXORCONST:
1709 case ICMD_LSHLCONST:
1710 case ICMD_LSHRCONST:
1711 case ICMD_LUSHRCONST:
1716 case ICMD_INT2SHORT:
1734 case ICMD_CHECKCAST:
1736 case ICMD_ARRAYLENGTH:
1737 case ICMD_INSTANCEOF:
1740 case ICMD_ANEWARRAY:
1743 FREE_TEMP_REG(iptr->s1.varindex);
1744 NEW_TEMP_REG(iptr->dst.varindex);
1749 case ICMD_GETSTATIC:
1752 NEW_TEMP_REG(iptr->dst.varindex);
1755 /* pop many push any */
1757 case ICMD_INVOKESTATIC:
1758 case ICMD_INVOKESPECIAL:
1759 case ICMD_INVOKEVIRTUAL:
1760 case ICMD_INVOKEINTERFACE:
1761 INSTRUCTION_GET_METHODDESC(iptr,md);
1763 argp = iptr->sx.s23.s2.args;
1765 FREE_TEMP_REG(*argp);
1768 if (md->returntype.type != TYPE_VOID)
1769 NEW_TEMP_REG(iptr->dst.varindex);
1773 bte = iptr->sx.s23.s3.bte;
1776 argp = iptr->sx.s23.s2.args;
1778 FREE_TEMP_REG(*argp);
1781 if (md->returntype.type != TYPE_VOID)
1782 NEW_TEMP_REG(iptr->dst.varindex);
1785 case ICMD_MULTIANEWARRAY:
1786 i = iptr->s1.argcount;
1787 argp = iptr->sx.s23.s2.args;
1789 FREE_TEMP_REG(*argp);
1792 NEW_TEMP_REG(iptr->dst.varindex);
1796 exceptions_throw_internalerror("Unknown ICMD %d during register allocation",
1801 } /* while instructions */
1804 } /* while blocks */
1808 #if defined(ENABLE_STATISTICS)
1809 void simplereg_make_statistics(jitdata *jd)
1816 stackptr src, src_old;
1820 int size_interface; /* == maximum size of in/out stack at basic block boundaries */
1824 /* get required compiler data */
1834 /* count how many local variables are held in memory or register */
1835 for(i=0; i < jd->localcount; i++) {
1836 if (VAR(i)->flags & INMEMORY) {
1837 count_locals_spilled++;
1841 count_locals_register++;
1845 /* count how many stack slots are held in memory or register */
1847 bptr = jd->basicblocks;
1849 while (bptr != NULL) {
1850 if (bptr->flags >= BBREACHED) {
1852 #if defined(ENABLE_LSRA) || defined(ENABLE_SSA)
1855 /* check for memory moves from interface to BB instack */
1856 len = bptr->indepth;
1858 if (len > size_interface) size_interface = len;
1862 var = VAR(bptr->invars[len]);
1864 /* invars statistics (currently none) */
1867 /* check for memory moves from BB outstack to interface */
1868 len = bptr->outdepth;
1869 if (len > size_interface) size_interface = len;
1873 var = VAR(bptr->outvars[len]);
1875 /* outvars statistics (currently none) */
1877 #if defined(ENABLE_LSRA) || defined(ENABLE_SSA)
1883 dst = bptr->instack;
1884 iptr = bptr->iinstr;
1888 while (--len >= 0) {
1890 dst = iptr->dst.var;
1892 if ((src!= NULL) && (src != src_old)) { /* new stackslot */
1893 switch (src->varkind) {
1896 if (!(src->flags & INMEMORY))
1897 count_ss_register++;
1903 /* case LOCALVAR: */
1904 /* if (!(rd->locals[src->varnum][src->type].flags & INMEMORY)) */
1905 /* count_ss_register++; */
1907 /* count_ss_spilled++; */
1910 if (!(src->flags & INMEMORY))
1911 count_argument_mem_ss++;
1913 count_argument_reg_ss++;
1917 /* if (IS_FLT_DBL_TYPE(src->type)) { */
1918 /* if (src->varnum < FLT_ARG_CNT) { */
1919 /* count_ss_register++; */
1923 /* #if defined(__POWERPC__) */
1924 /* if (src->varnum < INT_ARG_CNT - (IS_2_WORD_TYPE(src->type) != 0)) { */
1926 /* if (src->varnum < INT_ARG_CNT) { */
1928 /* count_ss_register++; */
1932 /* count_ss_spilled++; */
1939 } /* while instructions */
1944 } /* while blocks */
1946 count_interface_size += size_interface; /* accummulate the size of the interface (between bb boundaries) */
1947 if (in_register) count_method_in_register++;
1949 /* printf("INREGISTER: %s%s%s\n",m->class->name->text, m->name->text, m->descriptor->text); */
1952 #endif /* defined(ENABLE_STATISTICS) */
1956 * These are local overrides for various environment variables in Emacs.
1957 * Please do not remove this and leave it at the end of the file, where
1958 * Emacs will automagically detect them.
1959 * ---------------------------------------------------------------------
1962 * indent-tabs-mode: t
1966 * vim:noexpandtab:sw=4:ts=4: