/* src/vm/jit/allocator/simplereg.c - register allocator
- Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
- R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
- C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
- Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
- Contact: cacao@complang.tuwien.ac.at
-
- Authors: Andreas Krall
-
- Changes: Stefan Ring
- Christian Thalinger
- Christian Ullrich
- Michael Starzinger
- Edwin Steiner
-
- $Id: simplereg.c 5139 2006-07-14 17:08:32Z edwin $
-
*/
#include "config.h"
-#include "vm/types.h"
#include <assert.h>
+#include <stdint.h>
+
+#include "vm/types.h"
#include "arch.h"
#include "md-abi.h"
-#include "vm/builtin.h"
-#include "vm/exceptions.h"
-#include "mm/memory.h"
-#include "vm/method.h"
+#include "mm/memory.hpp"
+
+#include "vm/jit/builtin.hpp"
+#include "vm/exceptions.hpp"
+#include "vm/method.hpp"
#include "vm/options.h"
-#include "vm/resolve.h"
-#include "vm/stringlocal.h"
+#include "vm/resolve.hpp"
+#include "vm/string.hpp"
+
+#include "vm/jit/abi.h"
#include "vm/jit/reg.h"
+#include "vm/jit/show.hpp"
#include "vm/jit/allocator/simplereg.h"
+#if 0
+# define LOG(args) printf args
+#else
+# define LOG(args)
+#endif
+
+
/* function prototypes for this file ******************************************/
-static void interface_regalloc(jitdata *jd);
-static void local_regalloc(jitdata *jd);
-static void new_allocate_scratch_registers(jitdata *jd);
-static void allocate_scratch_registers(jitdata *jd);
+static void simplereg_allocate_interfaces(jitdata *jd);
+static void simplereg_allocate_locals(jitdata *jd);
+static void simplereg_allocate_temporaries(jitdata *jd);
-/* regalloc ********************************************************************
+/* size of a stackslot used by the internal ABI */
- Does a simple register allocation.
-
-*******************************************************************************/
-
-bool new_regalloc(jitdata *jd)
-{
- jitdata *newjd;
+#define SIZE_OF_STACKSLOT 8
- /* There is a problem with the use of unused float argument
- registers in leafmethods for stackslots on c7 (2 * Dual Core
- AMD Opteron(tm) Processor 270) - runtime for the jvm98 _mtrt
- benchmark is heaviliy increased. This could be prevented by
- setting rd->argfltreguse to FLT_ARG_CNT before calling
- allocate_scratch_registers and setting it back to the original
- value before calling local_regalloc. */
- newjd = DNEW(jitdata);
- *newjd = *jd;
- newjd->rd = jd->new_rd;
+/* total number of registers */
+
+#if defined(HAS_ADDRESS_REGISTER_FILE)
+#define TOTAL_REG_CNT (INT_REG_CNT + FLT_REG_CNT + ADR_REG_CNT)
+#else
+#define TOTAL_REG_CNT (INT_REG_CNT + FLT_REG_CNT)
+#endif
- interface_regalloc(newjd);
- new_allocate_scratch_registers(newjd);
- local_regalloc(newjd);
- /* everthing's ok */
+/* macros for handling register stacks ****************************************/
- return true;
-}
+#define AVAIL_FRONT(cnt, limit) ((cnt) < (limit))
+#define AVAIL_BACK(cnt) ((cnt) > 0)
+
+#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
+#define AVAIL_FRONT_INT(cnt, limit) ((cnt) < (limit) - intregsneeded)
+#define AVAIL_BACK_INT(cnt) ((cnt) > intregsneeded)
+#else
+#define AVAIL_FRONT_INT(cnt, limit) AVAIL_FRONT(cnt, limit)
+#define AVAIL_BACK_INT(cnt) AVAIL_BACK(cnt)
+#endif
+
+#define POP_FRONT(stk, cnt, reg) do { reg = stk[cnt++]; } while (0)
+#define POP_BACK(stk, cnt, reg) do { reg = stk[--cnt]; } while (0)
+#define PUSH_FRONT(stk, cnt, reg) do { stk[--cnt] = (reg); } while (0)
+#define PUSH_BACK(stk, cnt, reg) do { stk[cnt++] = (reg); } while (0)
+
+#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
+#define POP_FRONT_INT(stk, cnt, reg) \
+ do { \
+ if (intregsneeded) { \
+ reg = PACK_REGS(stk[cnt], stk[cnt+1]); \
+ cnt += 2; \
+ } \
+ else \
+ POP_FRONT(stk, cnt, reg); \
+ } while (0)
+#else
+#define POP_FRONT_INT(stk, cnt, reg) POP_FRONT(stk, cnt, reg)
+#endif
+
+#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
+#define POP_BACK_INT(stk, cnt, reg) \
+ do { \
+ if (intregsneeded) { \
+ cnt -= 2; \
+ reg = PACK_REGS(stk[cnt], stk[cnt+1]); \
+ } \
+ else \
+ POP_BACK(stk, cnt, reg); \
+ } while (0)
+#else
+#define POP_BACK_INT(stk, cnt, reg) POP_BACK(stk, cnt, reg)
+#endif
+
+#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
+#define PUSH_BACK_INT(stk, cnt, reg) \
+ do { \
+ if (intregsneeded) { \
+ stk[cnt] = GET_LOW_REG(reg); \
+ stk[cnt + 1] = GET_HIGH_REG(reg); \
+ cnt += 2; \
+ } \
+ else \
+ PUSH_BACK(stk, cnt, reg); \
+ } while (0)
+#else
+#define PUSH_BACK_INT(stk, cnt, reg) PUSH_BACK(stk, cnt, reg)
+#endif
+
+#define AVAIL_ARG_FLT AVAIL_FRONT(rd->argfltreguse, FLT_ARG_CNT)
+#define AVAIL_TMP_FLT AVAIL_BACK(rd->tmpfltreguse)
+#define AVAIL_SAV_FLT AVAIL_BACK(rd->savfltreguse)
+
+#define AVAIL_ARG_ADR AVAIL_FRONT(rd->argadrreguse, ADR_ARG_CNT)
+#define AVAIL_TMP_ADR AVAIL_BACK(rd->tmpadrreguse)
+#define AVAIL_SAV_ADR AVAIL_BACK(rd->savadrreguse)
+
+#define AVAIL_ARG_INT AVAIL_FRONT_INT(rd->argintreguse, INT_ARG_CNT)
+#define AVAIL_TMP_INT AVAIL_BACK_INT(rd->tmpintreguse)
+#define AVAIL_SAV_INT AVAIL_BACK_INT(rd->savintreguse)
+
+#define AVAIL_FREE_ARG_FLT AVAIL_BACK(rd->freeargflttop)
+#define AVAIL_FREE_TMP_FLT AVAIL_BACK(rd->freetmpflttop)
+#define AVAIL_FREE_SAV_FLT AVAIL_BACK(rd->freesavflttop)
+
+#define AVAIL_FREE_ARG_ADR AVAIL_BACK(rd->freeargadrtop)
+#define AVAIL_FREE_TMP_ADR AVAIL_BACK(rd->freetmpadrtop)
+#define AVAIL_FREE_SAV_ADR AVAIL_BACK(rd->freesavadrtop)
+
+#define AVAIL_FREE_ARG_INT AVAIL_BACK_INT(rd->freearginttop)
+#define AVAIL_FREE_TMP_INT AVAIL_BACK_INT(rd->freetmpinttop)
+#define AVAIL_FREE_SAV_INT AVAIL_BACK_INT(rd->freesavinttop)
+
+#define TAKE_ARG_FLT(r) POP_FRONT(abi_registers_float_argument, rd->argfltreguse, r)
+#define TAKE_TMP_FLT(r) POP_BACK(rd->tmpfltregs, rd->tmpfltreguse, r)
+#define TAKE_SAV_FLT(r) POP_BACK(rd->savfltregs, rd->savfltreguse, r)
+
+#define TAKE_ARG_ADR(r) POP_FRONT(rd->argadrregs, rd->argadrreguse, r)
+#define TAKE_TMP_ADR(r) POP_BACK(rd->tmpadrregs, rd->tmpadrreguse, r)
+#define TAKE_SAV_ADR(r) POP_BACK(rd->savadrregs, rd->savadrreguse, r)
+
+#define TAKE_ARG_INT(r) POP_FRONT_INT(abi_registers_integer_argument, rd->argintreguse, r)
+#define TAKE_TMP_INT(r) POP_BACK_INT(rd->tmpintregs, rd->tmpintreguse, r)
+#define TAKE_SAV_INT(r) POP_BACK_INT(rd->savintregs, rd->savintreguse, r)
+
+#define TAKE_FREE_ARG_FLT(r) POP_BACK(rd->freeargfltregs, rd->freeargflttop, r)
+#define TAKE_FREE_TMP_FLT(r) POP_BACK(rd->freetmpfltregs, rd->freetmpflttop, r)
+#define TAKE_FREE_SAV_FLT(r) POP_BACK(rd->freesavfltregs, rd->freesavflttop, r)
+
+#define TAKE_FREE_ARG_ADR(r) POP_BACK(rd->freeargadrregs, rd->freeargadrtop, r)
+#define TAKE_FREE_TMP_ADR(r) POP_BACK(rd->freetmpadrregs, rd->freetmpadrtop, r)
+#define TAKE_FREE_SAV_ADR(r) POP_BACK(rd->freesavadrregs, rd->freesavadrtop, r)
+
+#define TAKE_FREE_ARG_INT(r) POP_BACK_INT(rd->freeargintregs, rd->freearginttop, r)
+#define TAKE_FREE_TMP_INT(r) POP_BACK_INT(rd->freetmpintregs, rd->freetmpinttop, r)
+#define TAKE_FREE_SAV_INT(r) POP_BACK_INT(rd->freesavintregs, rd->freesavinttop, r)
+
+#define PUSH_FREE_ARG_FLT(r) PUSH_BACK(rd->freeargfltregs, rd->freeargflttop, r)
+#define PUSH_FREE_TMP_FLT(r) PUSH_BACK(rd->freetmpfltregs, rd->freetmpflttop, r)
+#define PUSH_FREE_SAV_FLT(r) PUSH_BACK(rd->freesavfltregs, rd->freesavflttop, r)
+
+#define PUSH_FREE_ARG_ADR(r) PUSH_BACK(rd->freeargadrregs, rd->freeargadrtop, r)
+#define PUSH_FREE_TMP_ADR(r) PUSH_BACK(rd->freetmpadrregs, rd->freetmpadrtop, r)
+#define PUSH_FREE_SAV_ADR(r) PUSH_BACK(rd->freesavadrregs, rd->freesavadrtop, r)
+
+#define PUSH_FREE_ARG_INT(r) PUSH_BACK_INT(rd->freeargintregs, rd->freearginttop, r)
+#define PUSH_FREE_TMP_INT(r) PUSH_BACK_INT(rd->freetmpintregs, rd->freetmpinttop, r)
+#define PUSH_FREE_SAV_INT(r) PUSH_BACK_INT(rd->freesavintregs, rd->freesavinttop, r)
+
+
+/* macros for allocating memory slots ****************************************/
+
+#define NEW_MEM_SLOT(r) \
+ do { \
+ (r) = rd->memuse * SIZE_OF_STACKSLOT; \
+ rd->memuse += 1; \
+ } while (0)
+
+#define NEW_MEM_SLOT_INT_LNG(r) NEW_MEM_SLOT(r)
+#define NEW_MEM_SLOT_FLT_DBL(r) NEW_MEM_SLOT(r)
+#define NEW_MEM_SLOT_REUSE_PADDING(r) NEW_MEM_SLOT(r)
+
+
+/* macros for creating/freeing temporary variables ***************************/
+
+#define NEW_TEMP_REG(index) \
+ if ( ((index) >= jd->localcount) \
+ && (!(VAR(index)->flags & (INOUT | PREALLOC))) ) \
+ simplereg_new_temp(jd, (index))
+
+
+#define FREE_TEMP_REG(index) \
+ if (((index) > jd->localcount) \
+ && (!(VAR(index)->flags & (PREALLOC)))) \
+ simplereg_free_temp(jd, (index))
+
+
+/* macro for getting a unique register index *********************************/
+
+#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
+#define REG_INDEX_NON_ADR(regoff, type) \
+ (IS_FLT_DBL_TYPE(type) ? (INT_REG_CNT + (regoff)) : (GET_LOW_REG(regoff)))
+#else
+#define REG_INDEX_NON_ADR(regoff, type) \
+ (IS_FLT_DBL_TYPE(type) ? (INT_REG_CNT + (regoff)) : (regoff))
+#endif
+
+#if defined(HAS_ADDRESS_REGISTER_FILE)
+#define REG_INDEX(regoff, type) \
+ (IS_ADR_TYPE(type) ? (regoff) : (ADR_REG_CNT + REG_INDEX_NON_ADR(regoff, type)))
+#else
+#define REG_INDEX(regoff, type) REG_INDEX_NON_ADR(regoff, type)
+#endif
+
+
+/* regalloc ********************************************************************
+
+ Does a simple register allocation.
+
+*******************************************************************************/
bool regalloc(jitdata *jd)
{
AMD Opteron(tm) Processor 270) - runtime for the jvm98 _mtrt
benchmark is heaviliy increased. This could be prevented by
setting rd->argfltreguse to FLT_ARG_CNT before calling
- allocate_scratch_registers and setting it back to the original
- value before calling local_regalloc. */
+ simplereg_allocate_temporaries and setting it back to the original
+ value before calling simplereg_allocate_locals. */
- interface_regalloc(jd);
- allocate_scratch_registers(jd);
- local_regalloc(jd);
+ simplereg_allocate_interfaces(jd);
+ simplereg_allocate_temporaries(jd);
+ simplereg_allocate_locals(jd);
/* everthing's ok */
}
-/* interface_regalloc **********************************************************
+/* simplereg_allocate_interfaces ***********************************************
Allocates registers for all interface variables.
-
+
*******************************************************************************/
-
-static void interface_regalloc(jitdata *jd)
+
+static void simplereg_allocate_interfaces(jitdata *jd)
{
methodinfo *m;
+ codeinfo *code;
codegendata *cd;
registerdata *rd;
int s, t, tt, saved;
int intalloc, fltalloc; /* Remember allocated Register/Memory offset */
- /* in case a more vars are packed into this interface slot */
- varinfo *v;
- int intregsneeded = 0;
- int memneeded = 0;
- /* allocate LNG and DBL Types first to ensure 2 memory slots or registers */
- /* on HAS_4BYTE_STACKSLOT architectures */
+ /* in case more vars are packed into this interface slot */
+ /* Allocate LNG and DBL types first to ensure 2 registers */
+ /* on some architectures. */
int typeloop[] = { TYPE_LNG, TYPE_DBL, TYPE_INT, TYPE_FLT, TYPE_ADR };
+ int flags, regoff;
+#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
+ int intregsneeded;
+#endif
/* get required compiler data */
- m = jd->m;
- cd = jd->cd;
- rd = jd->rd;
+ m = jd->m;
+ code = jd->code;
+ cd = jd->cd;
+ rd = jd->rd;
/* rd->memuse was already set in stack.c to allocate stack space
for passing arguments to called methods. */
#if defined(__I386__)
- if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
+ if (checksync && code_is_synchronized(code)) {
/* reserve 0(%esp) for Monitorenter/exit Argument on i386 */
if (rd->memuse < 1)
rd->memuse = 1;
}
#endif
- if (jd->isleafmethod) {
+ if (code_is_leafmethod(code)) {
/* Reserve argument register, which will be used for Locals acting */
/* as Parameters */
if (rd->argintreguse < m->parseddesc->argintreguse)
if (rd->argadrreguse < m->parseddesc->argadrreguse)
rd->argadrreguse = m->parseddesc->argadrreguse;
#endif
+ }
- }
-
- for (s = 0; s < cd->maxstack; s++) {
+ for (s = 0; s < jd->maxinterfaces; s++) {
intalloc = -1; fltalloc = -1;
- saved = (rd->interfaces[s][TYPE_INT].flags |
- rd->interfaces[s][TYPE_LNG].flags |
- rd->interfaces[s][TYPE_FLT].flags |
- rd->interfaces[s][TYPE_DBL].flags |
- rd->interfaces[s][TYPE_ADR].flags) & SAVEDVAR;
-
+
+ /* check if the interface at this stack depth must be a SAVEDVAR */
+
+ saved = 0;
+
+ for (tt = 0; tt <=4; tt++) {
+ if ((t = jd->interface_map[s * 5 + tt].flags) != UNUSED) {
+ saved |= t & SAVEDVAR;
+ }
+ }
+
+ /* allocate reg/mem for each type the interface is used as */
+
for (tt = 0; tt <= 4; tt++) {
t = typeloop[tt];
- v = &rd->interfaces[s][t];
- if (v->type >= 0) {
+ if (jd->interface_map[s * 5 + t].flags == UNUSED)
+ continue;
+
+ flags = saved;
+ regoff = -1; /* initialize to invalid value */
+
#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
- intregsneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
+ intregsneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
#endif
-#if defined(HAS_4BYTE_STACKSLOT)
- memneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
-#endif
- if (!saved) {
+
+ if (!saved) {
#if defined(HAS_ADDRESS_REGISTER_FILE)
- if (IS_ADR_TYPE(t)) {
- if (!jd->isleafmethod
- &&(rd->argadrreguse < ADR_ARG_CNT)) {
- v->regoff = rd->argadrregs[rd->argadrreguse++];
- } else if (rd->tmpadrreguse > 0) {
- v->regoff = rd->tmpadrregs[--rd->tmpadrreguse];
- } else if (rd->savadrreguse > 0) {
- v->regoff = rd->savadrregs[--rd->savadrreguse];
- } else {
- v->flags |= INMEMORY;
- v->regoff = rd->memuse++;
- }
- } else /* !IS_ADR_TYPE */
+ if (IS_ADR_TYPE(t)) {
+ if (!code_is_leafmethod(code) && AVAIL_ARG_ADR) {
+ flags |= ARGREG;
+ TAKE_ARG_ADR(regoff);
+ }
+ else if (AVAIL_TMP_ADR) {
+ TAKE_TMP_ADR(regoff);
+ }
+ else if (AVAIL_SAV_ADR) {
+ flags |= SAVREG;
+ TAKE_SAV_ADR(regoff);
+ }
+ else {
+ flags |= INMEMORY;
+ regoff = rd->memuse++ * SIZE_OF_STACKSLOT;
+ }
+ }
+ else /* !IS_ADR_TYPE */
#endif /* defined(HAS_ADDRESS_REGISTER_FILE) */
- {
- if (IS_FLT_DBL_TYPE(t)) {
- if (fltalloc >= 0) {
- /* Reuse memory slot(s)/register(s) for shared interface slots */
- v->flags |= rd->interfaces[s][fltalloc].flags
- & INMEMORY;
- v->regoff = rd->interfaces[s][fltalloc].regoff;
- } else if (rd->argfltreguse < FLT_ARG_CNT) {
- v->regoff = rd->argfltregs[rd->argfltreguse++];
- } else if (rd->tmpfltreguse > 0) {
- v->regoff = rd->tmpfltregs[--rd->tmpfltreguse];
- } else if (rd->savfltreguse > 0) {
- v->regoff = rd->savfltregs[--rd->savfltreguse];
- } else {
- v->flags |= INMEMORY;
-#if defined(ALIGN_DOUBLES_IN_MEMORY)
- /* Align doubles in Memory */
- if ( (memneeded) && (rd->memuse & 1))
- rd->memuse++;
-#endif
- v->regoff = rd->memuse;
- rd->memuse += memneeded + 1;
- }
- fltalloc = t;
- } else { /* !IS_FLT_DBL_TYPE(t) */
-#if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
- /*
- * for i386 put all longs in memory
- */
- if (IS_2_WORD_TYPE(t)) {
- v->flags |= INMEMORY;
-#if defined(ALIGN_LONGS_IN_MEMORY)
- /* Align longs in Memory */
- if (rd->memuse & 1)
- rd->memuse++;
-#endif
- v->regoff = rd->memuse;
- rd->memuse += memneeded + 1;
- } else
-#endif /* defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE...GISTERS) */
- if (intalloc >= 0) {
- /* Reuse memory slot(s)/register(s) for shared interface slots */
- v->flags |=
- rd->interfaces[s][intalloc].flags
- & INMEMORY;
-#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
- if (!(v->flags & INMEMORY)
- && IS_2_WORD_TYPE(intalloc))
- v->regoff = GET_LOW_REG(
- rd->interfaces[s][intalloc].regoff);
- else
-#endif
- v->regoff =
- rd->interfaces[s][intalloc].regoff;
- } else
- if (rd->argintreguse + intregsneeded
- < INT_ARG_CNT) {
-#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
- if (intregsneeded)
- v->regoff=PACK_REGS(
- rd->argintregs[rd->argintreguse],
- rd->argintregs[rd->argintreguse + 1]);
- else
-#endif
- v->regoff =
- rd->argintregs[rd->argintreguse];
- rd->argintreguse += intregsneeded + 1;
- }
- else if (rd->tmpintreguse > intregsneeded) {
- rd->tmpintreguse -= intregsneeded + 1;
-#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
- if (intregsneeded)
- v->regoff=PACK_REGS(
- rd->tmpintregs[rd->tmpintreguse],
- rd->tmpintregs[rd->tmpintreguse + 1]);
- else
+ {
+ if (IS_FLT_DBL_TYPE(t)) {
+ if (fltalloc >= 0) {
+ /* Reuse memory slot(s)/register(s) for shared interface slots */
+ flags |= jd->interface_map[fltalloc].flags & ~SAVEDVAR;
+ regoff = jd->interface_map[fltalloc].regoff;
+ }
+ else if (AVAIL_ARG_FLT) {
+ flags |= ARGREG;
+ TAKE_ARG_FLT(regoff);
+ }
+ else if (AVAIL_TMP_FLT) {
+ TAKE_TMP_FLT(regoff);
+ }
+ else if (AVAIL_SAV_FLT) {
+ flags |= SAVREG;
+ TAKE_SAV_FLT(regoff);
+ }
+ else {
+ flags |= INMEMORY;
+ NEW_MEM_SLOT_FLT_DBL(regoff);
+ }
+ fltalloc = s * 5 + t;
+ }
+ else { /* !IS_FLT_DBL_TYPE(t) */
+#if (SIZEOF_VOID_P == 4) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
+ /*
+ * for i386 put all longs in memory
+ */
+ if (IS_2_WORD_TYPE(t)) {
+ flags |= INMEMORY;
+ NEW_MEM_SLOT_INT_LNG(regoff);
+ }
+ else
#endif
- v->regoff =
- rd->tmpintregs[rd->tmpintreguse];
- }
- else if (rd->savintreguse > intregsneeded) {
- rd->savintreguse -= intregsneeded + 1;
- v->regoff =
- rd->savintregs[rd->savintreguse];
+ if (intalloc >= 0) {
+ /* Reuse memory slot(s)/register(s) for shared interface slots */
+ flags |= jd->interface_map[intalloc].flags & ~SAVEDVAR;
+ regoff = jd->interface_map[intalloc].regoff;
#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
- if (intregsneeded)
- v->regoff=PACK_REGS(
- rd->savintregs[rd->savintreguse],
- rd->savintregs[rd->savintreguse + 1]);
- else
-#endif
- v->regoff =
- rd->savintregs[rd->savintreguse];
- }
- else {
- v->flags |= INMEMORY;
-#if defined(ALIGN_LONGS_IN_MEMORY)
- /* Align longs in Memory */
- if ( (memneeded) && (rd->memuse & 1))
- rd->memuse++;
-#endif
- v->regoff = rd->memuse;
- rd->memuse += memneeded + 1;
- }
-
- intalloc = t;
- } /* if (IS_FLT_DBL_TYPE(t)) */
- }
- } else { /* (saved) */
-/* now the same like above, but without a chance to take a temporary register */
-#ifdef HAS_ADDRESS_REGISTER_FILE
- if (IS_ADR_TYPE(t)) {
- if (rd->savadrreguse > 0) {
- v->regoff = rd->savadrregs[--rd->savadrreguse];
- }
- else {
- v->flags |= INMEMORY;
- v->regoff = rd->memuse++;
- }
- } else
+ /* reuse lower half */
+ if (!(flags & INMEMORY)
+ && IS_2_WORD_TYPE(intalloc % 5))
+ regoff = GET_LOW_REG(regoff);
#endif
- {
- if (IS_FLT_DBL_TYPE(t)) {
- if (fltalloc >= 0) {
- v->flags |= rd->interfaces[s][fltalloc].flags
- & INMEMORY;
- v->regoff = rd->interfaces[s][fltalloc].regoff;
- } else
- if (rd->savfltreguse > 0) {
- v->regoff = rd->savfltregs[--rd->savfltreguse];
+ }
+ else {
+ if (AVAIL_ARG_INT) {
+ flags |= ARGREG;
+ TAKE_ARG_INT(regoff);
+ }
+ else if (AVAIL_TMP_INT) {
+ TAKE_TMP_INT(regoff);
+ }
+ else if (AVAIL_SAV_INT) {
+ flags |= SAVREG;
+ TAKE_SAV_INT(regoff);
}
else {
- v->flags |= INMEMORY;
-#if defined(ALIGN_DOUBLES_IN_MEMORY)
- /* Align doubles in Memory */
- if ( (memneeded) && (rd->memuse & 1))
- rd->memuse++;
-#endif
- v->regoff = rd->memuse;
- rd->memuse += memneeded + 1;
+ flags |= INMEMORY;
+ NEW_MEM_SLOT_INT_LNG(regoff);
}
- fltalloc = t;
- }
- else { /* IS_INT_LNG */
-#if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
- /*
- * for i386 put all longs in memory
- */
- if (IS_2_WORD_TYPE(t)) {
- v->flags |= INMEMORY;
-#if defined(ALIGN_LONGS_IN_MEMORY)
- /* Align longs in Memory */
- if (rd->memuse & 1)
- rd->memuse++;
-#endif
- v->regoff = rd->memuse;
- rd->memuse += memneeded + 1;
- } else
+ }
+
+ intalloc = s * 5 + t;
+ } /* if (IS_FLT_DBL_TYPE(t)) */
+ }
+ }
+ else { /* (saved) */
+ /* now the same like above, but without a chance to take a temporary register */
+#ifdef HAS_ADDRESS_REGISTER_FILE
+ if (IS_ADR_TYPE(t)) {
+ if (AVAIL_SAV_ADR) {
+ TAKE_SAV_ADR(regoff);
+ }
+ else {
+ flags |= INMEMORY;
+ regoff = rd->memuse++ * SIZE_OF_STACKSLOT;
+ }
+ }
+ else
#endif
- {
- if (intalloc >= 0) {
- v->flags |=
- rd->interfaces[s][intalloc].flags & INMEMORY;
-#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
- if (!(v->flags & INMEMORY)
- && IS_2_WORD_TYPE(intalloc))
- v->regoff =
- GET_LOW_REG(
- rd->interfaces[s][intalloc].regoff);
- else
+ {
+ if (IS_FLT_DBL_TYPE(t)) {
+ if (fltalloc >= 0) {
+ flags |= jd->interface_map[fltalloc].flags & ~SAVEDVAR;
+ regoff = jd->interface_map[fltalloc].regoff;
+ }
+ else {
+ if (AVAIL_SAV_FLT) {
+ TAKE_SAV_FLT(regoff);
+ }
+ else {
+ flags |= INMEMORY;
+ NEW_MEM_SLOT_FLT_DBL(regoff);
+ }
+ }
+ fltalloc = s * 5 + t;
+ }
+ else { /* IS_INT_LNG */
+#if (SIZEOF_VOID_P == 4) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
+ /*
+ * for i386 put all longs in memory
+ */
+ if (IS_2_WORD_TYPE(t)) {
+ flags |= INMEMORY;
+ NEW_MEM_SLOT_INT_LNG(regoff);
+ }
+ else
#endif
- v->regoff =
- rd->interfaces[s][intalloc].regoff;
- } else {
- if (rd->savintreguse > intregsneeded) {
- rd->savintreguse -= intregsneeded + 1;
+ {
+ if (intalloc >= 0) {
+ flags |= jd->interface_map[intalloc].flags & ~SAVEDVAR;
+ regoff = jd->interface_map[intalloc].regoff;
#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
- if (intregsneeded)
- v->regoff = PACK_REGS(
- rd->savintregs[rd->savintreguse],
- rd->savintregs[rd->savintreguse + 1]);
- else
-#endif
- v->regoff =
- rd->savintregs[rd->savintreguse];
- } else {
- v->flags |= INMEMORY;
-#if defined(ALIGN_LONGS_IN_MEMORY)
- /* Align longs in Memory */
- if ( (memneeded) && (rd->memuse & 1))
- rd->memuse++;
+ /* reuse lower half */
+ if (!(flags & INMEMORY)
+ && IS_2_WORD_TYPE(intalloc % 5))
+ regoff = GET_LOW_REG(regoff);
#endif
- v->regoff = rd->memuse;
- rd->memuse += memneeded + 1;
- }
+ }
+ else {
+ if (AVAIL_SAV_INT) {
+ TAKE_SAV_INT(regoff);
+ }
+ else {
+ flags |= INMEMORY;
+ NEW_MEM_SLOT_INT_LNG(regoff);
}
- intalloc = t;
}
- } /* if (IS_FLT_DBL_TYPE(t) else */
- } /* if (IS_ADR_TYPE(t)) else */
- } /* if (saved) else */
- } /* if (type >= 0) */
+ intalloc = s*5 + t;
+ }
+ } /* if (IS_FLT_DBL_TYPE(t) else */
+ } /* if (IS_ADR_TYPE(t)) else */
+ } /* if (saved) else */
+ /* if (type >= 0) */
+
+ assert(regoff >= 0);
+ jd->interface_map[5*s + t].flags = flags | INOUT;
+ jd->interface_map[5*s + t].regoff = regoff;
} /* for t */
} /* for s */
}
-/* local_regalloc **************************************************************
+/* simplereg_allocate_locals_leafmethod ****************************************
+
+ Allocates registers for all local variables of a leafmethod.
- Allocates registers for all local variables.
-
*******************************************************************************/
-
-static void local_regalloc(jitdata *jd)
+
+static void simplereg_allocate_locals_leafmethod(jitdata *jd)
{
methodinfo *m;
codegendata *cd;
registerdata *rd;
+ methoddesc *md;
- int p, s, t, tt;
+ int p, s, t, tt, varindex;
int intalloc, fltalloc;
varinfo *v;
int intregsneeded = 0;
- int memneeded = 0;
int typeloop[] = { TYPE_LNG, TYPE_DBL, TYPE_INT, TYPE_FLT, TYPE_ADR };
int fargcnt, iargcnt;
#ifdef HAS_ADDRESS_REGISTER_FILE
cd = jd->cd;
rd = jd->rd;
- if (jd->isleafmethod) {
- methoddesc *md = m->parseddesc;
+ md = m->parseddesc;
- iargcnt = rd->argintreguse;
- fargcnt = rd->argfltreguse;
+ iargcnt = rd->argintreguse;
+ fargcnt = rd->argfltreguse;
#ifdef HAS_ADDRESS_REGISTER_FILE
- aargcnt = rd->argadrreguse;
+ aargcnt = rd->argadrreguse;
#endif
- for (p = 0, s = 0; s < cd->maxlocals; s++, p++) {
- intalloc = -1; fltalloc = -1;
- for (tt = 0; tt <= 4; tt++) {
- t = typeloop[tt];
- v = &rd->locals[s][t];
+ for (p = 0, s = 0; s < jd->maxlocals; s++, p++) {
+ intalloc = -1; fltalloc = -1;
+ for (tt = 0; tt <= 4; tt++) {
+ t = typeloop[tt];
+ varindex = jd->local_map[s * 5 + t];
+ if (varindex == UNUSED)
+ continue;
- if (v->type < 0)
- continue;
+ v = VAR(varindex);
#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
- intregsneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
-#endif
-#if defined(HAS_4BYTE_STACKSLOT)
- memneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
-#endif
-
- /*
- * The order of
- *
- * #ifdef HAS_ADDRESS_REGISTER_FILE
- * if (IS_ADR_TYPE) {
- * ...
- * } else
- * #endif
- * if (IS_FLT_DBL) {
- * ...
- * } else { / int & lng
- * ...
- * }
- *
- * must not to be changed!
- */
+ intregsneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
+#endif
+
+ /*
+ * The order of
+ *
+ * #ifdef HAS_ADDRESS_REGISTER_FILE
+ * if (IS_ADR_TYPE) {
+ * ...
+ * } else
+ * #endif
+ * if (IS_FLT_DBL) {
+ * ...
+ * } else { / int & lng
+ * ...
+ * }
+ *
+ * must not to be changed!
+ */
#ifdef HAS_ADDRESS_REGISTER_FILE
- if (IS_ADR_TYPE(t)) {
- if ((p < md->paramcount) && !md->params[p].inmemory) {
+ if (IS_ADR_TYPE(t)) {
+ if ((p < md->paramcount) && !md->params[p].inmemory) {
+ v->flags = 0;
+ v->vv.regoff = rd->argadrregs[md->params[p].regoff];
+ }
+ else if (AVAIL_TMP_ADR) {
+ v->flags = 0;
+ TAKE_TMP_ADR(v->vv.regoff);
+ }
+ /* use unused argument registers as local registers */
+ else if ((p >= md->paramcount) &&
+ (aargcnt < ADR_ARG_CNT))
+ {
+ v->flags = 0;
+ POP_FRONT(rd->argadrregs, aargcnt, v->vv.regoff);
+ }
+ else if (AVAIL_SAV_ADR) {
+ v->flags = 0;
+ TAKE_SAV_ADR(v->vv.regoff);
+ }
+ else {
+ v->flags |= INMEMORY;
+ v->vv.regoff = rd->memuse++ * SIZE_OF_STACKSLOT;
+ }
+ }
+ else {
+#endif
+ if (IS_FLT_DBL_TYPE(t)) {
+ if (fltalloc >= 0) {
+ v->flags = VAR(fltalloc)->flags;
+ v->vv.regoff = VAR(fltalloc)->vv.regoff;
+ }
+#if !defined(SUPPORT_PASS_FLOATARGS_IN_INTREGS)
+ /* We can only use float arguments as local variables,
+ * if we do not pass them in integer registers. */
+ else if ((p < md->paramcount) && !md->params[p].inmemory) {
v->flags = 0;
- v->regoff = rd->argadrregs[md->params[p].regoff];
+ v->vv.regoff = md->params[p].regoff;
}
- else if (rd->tmpadrreguse > 0) {
+#endif
+ else if (AVAIL_TMP_FLT) {
v->flags = 0;
- v->regoff = rd->tmpadrregs[--rd->tmpadrreguse];
+ TAKE_TMP_FLT(v->vv.regoff);
}
/* use unused argument registers as local registers */
- else if ((p >= md->paramcount) &&
- (aargcnt < ADR_ARG_CNT)) {
+ else if ((p >= md->paramcount) && (fargcnt < FLT_ARG_CNT)) {
v->flags = 0;
- v->regoff = rd->argadrregs[aargcnt++];
+ POP_FRONT(abi_registers_float_argument,
+ fargcnt, v->vv.regoff);
}
- else if (rd->savadrreguse > 0) {
+ else if (AVAIL_SAV_FLT) {
v->flags = 0;
- v->regoff = rd->savadrregs[--rd->savadrreguse];
+ TAKE_SAV_FLT(v->vv.regoff);
}
else {
- v->flags |= INMEMORY;
- v->regoff = rd->memuse++;
- }
- } else {
+ v->flags = INMEMORY;
+ NEW_MEM_SLOT_FLT_DBL(v->vv.regoff);
+ }
+ fltalloc = jd->local_map[s * 5 + t];
+
+ }
+ else {
+#if (SIZEOF_VOID_P == 4) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
+ /*
+ * for i386 put all longs in memory
+ */
+ if (IS_2_WORD_TYPE(t)) {
+ v->flags = INMEMORY;
+ NEW_MEM_SLOT_INT_LNG(v->vv.regoff);
+ }
+ else
#endif
- if (IS_FLT_DBL_TYPE(t)) {
- if (fltalloc >= 0) {
- v->flags = rd->locals[s][fltalloc].flags;
- v->regoff = rd->locals[s][fltalloc].regoff;
+ {
+ if (intalloc >= 0) {
+ v->flags = VAR(intalloc)->flags;
+#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
+ if (!(v->flags & INMEMORY)
+ && IS_2_WORD_TYPE(VAR(intalloc)->type))
+ v->vv.regoff = GET_LOW_REG(
+ VAR(intalloc)->vv.regoff);
+ else
+#endif
+ v->vv.regoff = VAR(intalloc)->vv.regoff;
}
-#if !defined(SUPPORT_PASS_FLOATARGS_IN_INTREGS)
- /* We can only use float arguments as local variables,
- * if we do not pass them in integer registers. */
- else if ((p < md->paramcount) &&
- !md->params[p].inmemory) {
+ else if ((p < md->paramcount) &&
+ !md->params[p].inmemory)
+ {
v->flags = 0;
- v->regoff = rd->argfltregs[md->params[p].regoff];
- }
+#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
+ if (IS_2_WORD_TYPE(t))
+ v->vv.regoff =
+ PACK_REGS(GET_LOW_REG(md->params[p].regoff),
+ GET_HIGH_REG(md->params[p].regoff));
+ else
#endif
- else if (rd->tmpfltreguse > 0) {
+ v->vv.regoff = md->params[p].regoff;
+ }
+ else if (AVAIL_TMP_INT) {
v->flags = 0;
- v->regoff = rd->tmpfltregs[--rd->tmpfltreguse];
+ TAKE_TMP_INT(v->vv.regoff);
}
- /* use unused argument registers as local registers */
- else if ((p >= md->paramcount) &&
- (fargcnt < FLT_ARG_CNT)) {
+ /*
+ * use unused argument registers as local registers
+ */
+ else if ((p >= m->parseddesc->paramcount) &&
+ (iargcnt + intregsneeded < INT_ARG_CNT))
+ {
v->flags = 0;
- v->regoff = rd->argfltregs[fargcnt];
- fargcnt++;
+ POP_FRONT_INT(abi_registers_integer_argument,
+ iargcnt, v->vv.regoff);
}
- else if (rd->savfltreguse > 0) {
+ else if (AVAIL_SAV_INT) {
v->flags = 0;
- v->regoff = rd->savfltregs[--rd->savfltreguse];
+ TAKE_SAV_INT(v->vv.regoff);
}
else {
v->flags = INMEMORY;
-#if defined(ALIGN_DOUBLES_IN_MEMORY)
- /* Align doubles in Memory */
- if ( (memneeded) && (rd->memuse & 1))
- rd->memuse++;
-#endif
- v->regoff = rd->memuse;
- rd->memuse += memneeded + 1;
+ NEW_MEM_SLOT_INT_LNG(v->vv.regoff);
}
- fltalloc = t;
-
- } else {
-#if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
- /*
- * for i386 put all longs in memory
- */
- if (IS_2_WORD_TYPE(t)) {
- v->flags = INMEMORY;
-#if defined(ALIGN_LONGS_IN_MEMORY)
- /* Align longs in Memory */
- if (rd->memuse & 1)
- rd->memuse++;
-#endif
- v->regoff = rd->memuse;
- rd->memuse += memneeded + 1;
- } else
-#endif
- {
- if (intalloc >= 0) {
- v->flags = rd->locals[s][intalloc].flags;
-#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
- if (!(v->flags & INMEMORY)
- && IS_2_WORD_TYPE(intalloc))
- v->regoff = GET_LOW_REG(
- rd->locals[s][intalloc].regoff);
- else
-#endif
- v->regoff = rd->locals[s][intalloc].regoff;
- }
- else if ((p < md->paramcount) &&
- !md->params[p].inmemory) {
- v->flags = 0;
-#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
- if (IS_2_WORD_TYPE(t))
- v->regoff = PACK_REGS(
- rd->argintregs[GET_LOW_REG(md->params[p].regoff)],
- rd->argintregs[GET_HIGH_REG(md->params[p].regoff)]);
- else
-#endif
- v->regoff =
- rd->argintregs[md->params[p].regoff];
- }
- else if (rd->tmpintreguse > intregsneeded) {
- rd->tmpintreguse -= intregsneeded + 1;
- v->flags = 0;
-#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
- if (intregsneeded)
- v->regoff = PACK_REGS(
- rd->tmpintregs[rd->tmpintreguse],
- rd->tmpintregs[rd->tmpintreguse + 1]);
- else
+ }
+ intalloc = jd->local_map[s * 5 + t];
+ }
+#ifdef HAS_ADDRESS_REGISTER_FILE
+ }
#endif
- v->regoff =
- rd->tmpintregs[rd->tmpintreguse];
- }
- /*
- * use unused argument registers as local registers
- */
- else if ((p >= m->parseddesc->paramcount) &&
- (iargcnt + intregsneeded < INT_ARG_CNT)) {
- v->flags = 0;
-#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
- if (intregsneeded)
- v->regoff=PACK_REGS(
- rd->argintregs[iargcnt],
- rd->argintregs[iargcnt + 1]);
- else
-#endif
- v->regoff = rd->argintregs[iargcnt];
- iargcnt += intregsneeded + 1;
- }
- else if (rd->savintreguse > intregsneeded) {
- rd->savintreguse -= intregsneeded + 1;
- v->flags = 0;
-#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
- if (intregsneeded)
- v->regoff = PACK_REGS(
- rd->savintregs[rd->savintreguse],
- rd->savintregs[rd->savintreguse + 1]);
- else
-#endif
- v->regoff =rd->savintregs[rd->savintreguse];
- }
- else {
- v->flags = INMEMORY;
-#if defined(ALIGN_LONGS_IN_MEMORY)
- /* Align longs in Memory */
- if ( (memneeded) && (rd->memuse & 1))
- rd->memuse++;
-#endif
- v->regoff = rd->memuse;
- rd->memuse += memneeded + 1;
- }
- }
- intalloc = t;
- }
-#ifdef HAS_ADDRESS_REGISTER_FILE
- }
+ } /* for (tt=0;...) */
+
+ /* If the current parameter is a 2-word type, the next local slot */
+ /* is skipped. */
+
+ if (p < md->paramcount)
+ if (IS_2_WORD_TYPE(md->paramtypes[p].type))
+ s++;
+ }
+}
+
+/* simplereg_allocate_locals ***************************************************
+
+ Allocates registers for all local variables.
+
+*******************************************************************************/
+
+static void simplereg_allocate_locals(jitdata *jd)
+{
+ codeinfo *code;
+ codegendata *cd;
+ registerdata *rd;
+
+ int s, t, tt, varindex;
+ int intalloc, fltalloc;
+ varinfo *v;
+ int typeloop[] = { TYPE_LNG, TYPE_DBL, TYPE_INT, TYPE_FLT, TYPE_ADR };
+#ifdef SUPPORT_COMBINE_INTEGER_REGISTERS
+ s4 intregsneeded;
#endif
- } /* for (tt=0;...) */
- /* If the current parameter is a 2-word type, the next local slot */
- /* is skipped. */
+ /* get required compiler data */
- if (p < md->paramcount)
- if (IS_2_WORD_TYPE(md->paramtypes[p].type))
- s++;
- }
+ code = jd->code;
+ cd = jd->cd;
+ rd = jd->rd;
+
+ if (code_is_leafmethod(code)) {
+ simplereg_allocate_locals_leafmethod(jd);
return;
}
- for (s = 0; s < cd->maxlocals; s++) {
+ for (s = 0; s < jd->maxlocals; s++) {
intalloc = -1; fltalloc = -1;
for (tt=0; tt<=4; tt++) {
t = typeloop[tt];
- v = &rd->locals[s][t];
- if (v->type >= 0) {
+ varindex = jd->local_map[s * 5 + t];
+ if (varindex == UNUSED)
+ continue;
+
+ v = VAR(varindex);
+
#ifdef SUPPORT_COMBINE_INTEGER_REGISTERS
intregsneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
#endif
-#if defined(HAS_4BYTE_STACKSLOT)
- memneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
-#endif
+
#ifdef HAS_ADDRESS_REGISTER_FILE
- if ( IS_ADR_TYPE(t) ) {
- if (rd->savadrreguse > 0) {
+ if (IS_ADR_TYPE(t)) {
+ if (AVAIL_SAV_ADR) {
v->flags = 0;
- v->regoff = rd->savadrregs[--rd->savadrreguse];
+ TAKE_SAV_ADR(v->vv.regoff);
}
else {
v->flags = INMEMORY;
- v->regoff = rd->memuse++;
+ v->vv.regoff = rd->memuse++ * SIZE_OF_STACKSLOT;
}
- } else {
+ }
+ else {
#endif
if (IS_FLT_DBL_TYPE(t)) {
if (fltalloc >= 0) {
- v->flags = rd->locals[s][fltalloc].flags;
- v->regoff = rd->locals[s][fltalloc].regoff;
+ v->flags = VAR(fltalloc)->flags;
+ v->vv.regoff = VAR(fltalloc)->vv.regoff;
}
- else if (rd->savfltreguse > 0) {
+ else if (AVAIL_SAV_FLT) {
v->flags = 0;
- v->regoff = rd->savfltregs[--rd->savfltreguse];
+ TAKE_SAV_FLT(v->vv.regoff);
}
else {
v->flags = INMEMORY;
-#if defined(ALIGN_DOUBLES_IN_MEMORY)
- /* Align doubles in Memory */
- if ( (memneeded) && (rd->memuse & 1))
- rd->memuse++;
-#endif
- v->regoff = rd->memuse;
- rd->memuse += memneeded + 1;
+ NEW_MEM_SLOT_FLT_DBL(v->vv.regoff);
}
- fltalloc = t;
+ fltalloc = jd->local_map[s * 5 + t];
}
else {
-#if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
+#if (SIZEOF_VOID_P == 4) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
/*
* for i386 put all longs in memory
*/
if (IS_2_WORD_TYPE(t)) {
v->flags = INMEMORY;
-#if defined(ALIGN_LONGS_IN_MEMORY)
- /* Align longs in Memory */
- if (rd->memuse & 1)
- rd->memuse++;
-#endif
- v->regoff = rd->memuse;
- rd->memuse += memneeded + 1;
- } else {
+ NEW_MEM_SLOT_INT_LNG(v->vv.regoff);
+ }
+ else {
#endif
if (intalloc >= 0) {
- v->flags = rd->locals[s][intalloc].flags;
+ v->flags = VAR(intalloc)->flags;
#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
if (!(v->flags & INMEMORY)
- && IS_2_WORD_TYPE(intalloc))
- v->regoff = GET_LOW_REG(
- rd->locals[s][intalloc].regoff);
+ && IS_2_WORD_TYPE(VAR(intalloc)->type))
+ v->vv.regoff = GET_LOW_REG(
+ VAR(intalloc)->vv.regoff);
else
#endif
- v->regoff = rd->locals[s][intalloc].regoff;
+ v->vv.regoff = VAR(intalloc)->vv.regoff;
}
- else if (rd->savintreguse > intregsneeded) {
- rd->savintreguse -= intregsneeded+1;
+ else if (AVAIL_SAV_INT) {
v->flags = 0;
-#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
- if (intregsneeded)
- v->regoff = PACK_REGS(
- rd->savintregs[rd->savintreguse],
- rd->savintregs[rd->savintreguse + 1]);
- else
-#endif
- v->regoff =rd->savintregs[rd->savintreguse];
+ TAKE_SAV_INT(v->vv.regoff);
}
else {
v->flags = INMEMORY;
-#if defined(ALIGN_LONGS_IN_MEMORY)
- /* Align longs in Memory */
- if ( (memneeded) && (rd->memuse & 1))
- rd->memuse++;
-#endif
- v->regoff = rd->memuse;
- rd->memuse += memneeded + 1;
+ NEW_MEM_SLOT_INT_LNG(v->vv.regoff);
}
-#if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
+#if (SIZEOF_VOID_P == 4) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
}
#endif
- intalloc = t;
+ intalloc = jd->local_map[s * 5 + t];
}
#ifdef HAS_ADDRESS_REGISTER_FILE
}
#endif
-
- }
}
}
}
-static void reg_init_temp(methodinfo *m, registerdata *rd)
+
+static void simplereg_init(jitdata *jd, registerdata *rd)
{
+ int i;
+
rd->freememtop = 0;
-#if defined(HAS_4BYTE_STACKSLOT)
- rd->freememtop_2 = 0;
-#endif
rd->freetmpinttop = 0;
rd->freesavinttop = 0;
#ifdef HAS_ADDRESS_REGISTER_FILE
rd->freeargadrtop = 0;
#endif
+
+ rd->regisoutvar = DMNEW(int, TOTAL_REG_CNT);
+ rd->regcopycount = DMNEW(int, TOTAL_REG_CNT);
+ MZERO(rd->regcopycount, int, TOTAL_REG_CNT);
+
+ /* memcopycount is dynamically allocated when needed */
+
+ rd->memcopycount = NULL;
+ rd->memcopycountsize = 0;
+
+ rd->intusedinout = DMNEW(int, INT_REG_CNT);
+ MZERO(rd->intusedinout, int, INT_REG_CNT);
+ rd->fltusedinout = DMNEW(int, FLT_REG_CNT);
+ MZERO(rd->fltusedinout, int, FLT_REG_CNT);
+
+ /* record the interface registers as used */
+
+ for (i=0; i<rd->argintreguse; ++i)
+ rd->intusedinout[abi_registers_integer_argument[i]] = 1;
+ for (i=rd->tmpintreguse; i<INT_TMP_CNT; ++i)
+ rd->intusedinout[rd->tmpintregs[i]] = 1;
+ for (i=rd->savintreguse; i<INT_SAV_CNT; ++i)
+ rd->intusedinout[rd->savintregs[i]] = 1;
+
+ for (i=0; i<rd->argfltreguse; ++i)
+ rd->fltusedinout[abi_registers_float_argument[i]] = 1;
+ for (i=rd->tmpfltreguse; i<FLT_TMP_CNT; ++i)
+ rd->fltusedinout[rd->tmpfltregs[i]] = 1;
+ for (i=rd->savfltreguse; i<FLT_SAV_CNT; ++i)
+ rd->fltusedinout[rd->savfltregs[i]] = 1;
+
+#ifdef HAS_ADDRESS_REGISTER_FILE
+ rd->adrusedinout = DMNEW(int, ADR_REG_CNT);
+ MZERO(rd->adrusedinout, int, ADR_REG_CNT);
+
+ for (i=0; i<rd->argadrreguse; ++i)
+ rd->adrusedinout[rd->argadrregs[i]] = 1;
+ for (i=rd->tmpadrreguse; i<ADR_TMP_CNT; ++i)
+ rd->adrusedinout[rd->tmpadrregs[i]] = 1;
+ for (i=rd->savadrreguse; i<ADR_SAV_CNT; ++i)
+ rd->adrusedinout[rd->savadrregs[i]] = 1;
+#endif
}
-#define reg_new_temp(rd,s) if (s->varkind == TEMPVAR) reg_new_temp_func(rd, s)
+static void simplereg_init_block(registerdata *rd)
+{
+ int i;
+
+ /* remove all interface registers from the free lists */
+
+ for (i=0; i<rd->freearginttop; ++i)
+ if (rd->intusedinout[rd->freeargintregs[i]]) {
+ rd->freeargintregs[i--] = rd->freeargintregs[--rd->freearginttop];
+ }
+ for (i=0; i<rd->freetmpinttop; ++i)
+ if (rd->intusedinout[rd->freetmpintregs[i]]) {
+ rd->freetmpintregs[i--] = rd->freetmpintregs[--rd->freetmpinttop];
+ }
+ for (i=0; i<rd->freesavinttop; ++i)
+ if (rd->intusedinout[rd->freesavintregs[i]]) {
+ rd->freesavintregs[i--] = rd->freesavintregs[--rd->freesavinttop];
+ }
+
+ for (i=0; i<rd->freeargflttop; ++i)
+ if (rd->fltusedinout[rd->freeargfltregs[i]]) {
+ rd->freeargfltregs[i--] = rd->freeargfltregs[--rd->freeargflttop];
+ }
+ for (i=0; i<rd->freetmpflttop; ++i)
+ if (rd->fltusedinout[rd->freetmpfltregs[i]]) {
+ rd->freetmpfltregs[i--] = rd->freetmpfltregs[--rd->freetmpflttop];
+ }
+ for (i=0; i<rd->freesavflttop; ++i)
+ if (rd->fltusedinout[rd->freesavfltregs[i]]) {
+ rd->freesavfltregs[i--] = rd->freesavfltregs[--rd->freesavflttop];
+ }
+
+#ifdef HAS_ADDRESS_REGISTER_FILE
+ for (i=0; i<rd->freeargadrtop; ++i)
+ if (rd->adrusedinout[rd->freeargadrregs[i]]) {
+ rd->freeargadrregs[i--] = rd->freeargadrregs[--rd->freeargadrtop];
+ }
+ for (i=0; i<rd->freetmpadrtop; ++i)
+ if (rd->adrusedinout[rd->freetmpadrregs[i]]) {
+ rd->freetmpadrregs[i--] = rd->freetmpadrregs[--rd->freetmpadrtop];
+ }
+ for (i=0; i<rd->freesavadrtop; ++i)
+ if (rd->adrusedinout[rd->freesavadrregs[i]]) {
+ rd->freesavadrregs[i--] = rd->freesavadrregs[--rd->freesavadrtop];
+ }
+#endif
+}
+
-static void reg_new_temp_func(registerdata *rd, stackptr s)
+static void simplereg_new_temp(jitdata *jd, s4 index)
{
+#ifdef SUPPORT_COMBINE_INTEGER_REGISTERS
s4 intregsneeded;
- s4 memneeded;
+#endif
s4 tryagain;
+ registerdata *rd;
+ varinfo *v;
+
+ rd = jd->rd;
+ v = VAR(index);
+
+ /* assert that constants are not allocated */
+
+ assert(v->type != TYPE_RET);
/* Try to allocate a saved register if there is no temporary one */
/* available. This is what happens during the second run. */
- tryagain = (s->flags & SAVEDVAR) ? 1 : 2;
+ tryagain = (v->flags & SAVEDVAR) ? 1 : 2;
#ifdef SUPPORT_COMBINE_INTEGER_REGISTERS
- intregsneeded = (IS_2_WORD_TYPE(s->type)) ? 1 : 0;
-#else
- intregsneeded = 0;
-#endif
-#if defined(HAS_4BYTE_STACKSLOT)
- memneeded = (IS_2_WORD_TYPE(s->type)) ? 1 : 0;
-#else
- memneeded = 0;
+ intregsneeded = (IS_2_WORD_TYPE(v->type)) ? 1 : 0;
#endif
for(; tryagain; --tryagain) {
if (tryagain == 1) {
- if (!(s->flags & SAVEDVAR))
- s->flags |= SAVEDTMP;
+ if (!(v->flags & SAVEDVAR))
+ v->flags |= SAVREG;
#ifdef HAS_ADDRESS_REGISTER_FILE
- if (IS_ADR_TYPE(s->type)) {
- if (rd->freesavadrtop > 0) {
- s->regoff = rd->freesavadrregs[--rd->freesavadrtop];
+ if (IS_ADR_TYPE(v->type)) {
+ if (AVAIL_FREE_SAV_ADR) {
+ TAKE_FREE_SAV_ADR(v->vv.regoff);
return;
- } else if (rd->savadrreguse > 0) {
- s->regoff = rd->savadrregs[--rd->savadrreguse];
+ }
+ else if (AVAIL_SAV_ADR) {
+ TAKE_SAV_ADR(v->vv.regoff);
return;
}
- } else
+ }
+ else
#endif
{
- if (IS_FLT_DBL_TYPE(s->type)) {
- if (rd->freesavflttop > 0) {
- s->regoff = rd->freesavfltregs[--rd->freesavflttop];
+ if (IS_FLT_DBL_TYPE(v->type)) {
+ if (AVAIL_FREE_SAV_FLT) {
+ TAKE_FREE_SAV_FLT(v->vv.regoff);
return;
- } else if (rd->savfltreguse > 0) {
- s->regoff = rd->savfltregs[--rd->savfltreguse];
+ }
+ else if (AVAIL_SAV_FLT) {
+ TAKE_SAV_FLT(v->vv.regoff);
return;
}
- } else {
-#if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
+ }
+ else {
+#if (SIZEOF_VOID_P == 4) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
/*
* for i386 put all longs in memory
*/
- if (!IS_2_WORD_TYPE(s->type))
+ if (!IS_2_WORD_TYPE(v->type))
#endif
{
- if (rd->freesavinttop > intregsneeded) {
- rd->freesavinttop -= intregsneeded + 1;
-#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
- if (intregsneeded)
- s->regoff = PACK_REGS(
- rd->freesavintregs[rd->freesavinttop],
- rd->freesavintregs[rd->freesavinttop + 1]);
- else
-#endif
- s->regoff =
- rd->freesavintregs[rd->freesavinttop];
+ if (AVAIL_FREE_SAV_INT) {
+ TAKE_FREE_SAV_INT(v->vv.regoff);
return;
- } else if (rd->savintreguse > intregsneeded) {
- rd->savintreguse -= intregsneeded + 1;
-#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
- if (intregsneeded)
- s->regoff = PACK_REGS(
- rd->savintregs[rd->savintreguse],
- rd->savintregs[rd->savintreguse + 1]);
- else
-#endif
- s->regoff = rd->savintregs[rd->savintreguse];
+ }
+ else if (AVAIL_SAV_INT) {
+ TAKE_SAV_INT(v->vv.regoff);
return;
}
}
}
}
- } else { /* tryagain == 2 */
+ }
+ else { /* tryagain == 2 */
#ifdef HAS_ADDRESS_REGISTER_FILE
- if (IS_ADR_TYPE(s->type)) {
- if (rd->freetmpadrtop > 0) {
- s->regoff = rd->freetmpadrregs[--rd->freetmpadrtop];
+ if (IS_ADR_TYPE(v->type)) {
+ if (AVAIL_FREE_TMP_ADR) {
+ TAKE_FREE_TMP_ADR(v->vv.regoff);
return;
- } else if (rd->tmpadrreguse > 0) {
- s->regoff = rd->tmpadrregs[--rd->tmpadrreguse];
+ }
+ else if (AVAIL_TMP_ADR) {
+ TAKE_TMP_ADR(v->vv.regoff);
return;
}
- } else
+ }
+ else
#endif
{
- if (IS_FLT_DBL_TYPE(s->type)) {
- if (rd->freeargflttop > 0) {
- s->regoff = rd->freeargfltregs[--rd->freeargflttop];
- s->flags |= TMPARG;
+ if (IS_FLT_DBL_TYPE(v->type)) {
+ if (AVAIL_FREE_ARG_FLT) {
+ v->flags |= ARGREG;
+ TAKE_FREE_ARG_FLT(v->vv.regoff);
return;
- } else if (rd->argfltreguse < FLT_ARG_CNT) {
- s->regoff = rd->argfltregs[rd->argfltreguse++];
- s->flags |= TMPARG;
+ }
+ else if (AVAIL_ARG_FLT) {
+ v->flags |= ARGREG;
+ TAKE_ARG_FLT(v->vv.regoff);
return;
- } else if (rd->freetmpflttop > 0) {
- s->regoff = rd->freetmpfltregs[--rd->freetmpflttop];
+ }
+ else if (AVAIL_FREE_TMP_FLT) {
+ TAKE_FREE_TMP_FLT(v->vv.regoff);
return;
- } else if (rd->tmpfltreguse > 0) {
- s->regoff = rd->tmpfltregs[--rd->tmpfltreguse];
+ }
+ else if (AVAIL_TMP_FLT) {
+ TAKE_TMP_FLT(v->vv.regoff);
return;
}
- } else {
-#if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
+ }
+ else {
+#if (SIZEOF_VOID_P == 4) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
/*
* for i386 put all longs in memory
*/
- if (!IS_2_WORD_TYPE(s->type))
+ if (!IS_2_WORD_TYPE(v->type))
#endif
{
- if (rd->freearginttop > intregsneeded) {
- rd->freearginttop -= intregsneeded + 1;
- s->flags |= TMPARG;
-#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
- if (intregsneeded)
- s->regoff = PACK_REGS(
- rd->freeargintregs[rd->freearginttop],
- rd->freeargintregs[rd->freearginttop + 1]);
- else
-#endif
- s->regoff =
- rd->freeargintregs[rd->freearginttop];
+ if (AVAIL_FREE_ARG_INT) {
+ v->flags |= ARGREG;
+ TAKE_FREE_ARG_INT(v->vv.regoff);
return;
- } else if (rd->argintreguse
- < INT_ARG_CNT - intregsneeded) {
-#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
- if (intregsneeded)
- s->regoff = PACK_REGS(
- rd->argintregs[rd->argintreguse],
- rd->argintregs[rd->argintreguse + 1]);
- else
-#endif
- s->regoff = rd->argintregs[rd->argintreguse];
- s->flags |= TMPARG;
- rd->argintreguse += intregsneeded + 1;
+ }
+ else if (AVAIL_ARG_INT) {
+ v->flags |= ARGREG;
+ TAKE_ARG_INT(v->vv.regoff);
return;
- } else if (rd->freetmpinttop > intregsneeded) {
- rd->freetmpinttop -= intregsneeded + 1;
-#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
- if (intregsneeded)
- s->regoff = PACK_REGS(
- rd->freetmpintregs[rd->freetmpinttop],
- rd->freetmpintregs[rd->freetmpinttop + 1]);
- else
-#endif
- s->regoff = rd->freetmpintregs[rd->freetmpinttop];
+ }
+ else if (AVAIL_FREE_TMP_INT) {
+ TAKE_FREE_TMP_INT(v->vv.regoff);
return;
- } else if (rd->tmpintreguse > intregsneeded) {
- rd->tmpintreguse -= intregsneeded + 1;
-#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
- if (intregsneeded)
- s->regoff = PACK_REGS(
- rd->tmpintregs[rd->tmpintreguse],
- rd->tmpintregs[rd->tmpintreguse + 1]);
- else
-#endif
- s->regoff = rd->tmpintregs[rd->tmpintreguse];
+ }
+ else if (AVAIL_TMP_INT) {
+ TAKE_TMP_INT(v->vv.regoff);
return;
}
} /* if (!IS_2_WORD_TYPE(s->type)) */
} /* if (tryagain == 1) else */
} /* for(; tryagain; --tryagain) */
-#if defined(HAS_4BYTE_STACKSLOT)
- if ((memneeded == 1) && (rd->freememtop_2 > 0)) {
- rd->freememtop_2--;
- s->regoff = rd->freemem_2[rd->freememtop_2];
- } else
-#endif /*defined(HAS_4BYTE_STACKSLOT) */
- if ((memneeded == 0) && (rd->freememtop > 0)) {
- rd->freememtop--;;
- s->regoff = rd->freemem[rd->freememtop];
- } else {
-#if defined(ALIGN_LONGS_IN_MEMORY) || defined(ALIGN_DOUBLES_IN_MEMORY)
- /* align 2 Word Types */
- if ((memneeded) && ((rd->memuse & 1) == 1)) {
- /* Put patched memory slot on freemem */
- rd->freemem[rd->freememtop++] = rd->memuse;
- rd->memuse++;
- }
-#endif /* defined(ALIGN_LONGS_IN_MEMORY) || defined(ALIGN_DOUBLES_IN_MEMORY) */
- s->regoff = rd->memuse;
- rd->memuse += memneeded + 1;
- }
- s->flags |= INMEMORY;
-}
-
-
-#define reg_free_temp(rd,s) if (((s)->varkind == TEMPVAR) && (!((s)->flags & STCOPY))) reg_free_temp_func(rd, (s))
-
-/* Do not free regs/memory locations used by Stackslots flagged STCOPY! There is still another Stackslot */
-/* alive using this reg/memory location */
-
-static void reg_free_temp_func(registerdata *rd, stackptr s)
-{
- s4 intregsneeded;
- s4 memneeded;
-
-#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
- intregsneeded = (IS_2_WORD_TYPE(s->type)) ? 1 : 0;
-#else
- intregsneeded = 0;
-#endif
-
-#if defined(HAS_4BYTE_STACKSLOT)
- memneeded = (IS_2_WORD_TYPE(s->type)) ? 1 : 0;
-#else
- memneeded = 0;
-#endif
-
- if (s->flags & INMEMORY) {
-#if defined(HAS_4BYTE_STACKSLOT)
- if (memneeded > 0) {
- rd->freemem_2[rd->freememtop_2] = s->regoff;
- rd->freememtop_2++;
- } else
-#endif
- {
- rd->freemem[rd->freememtop] = s->regoff;
- rd->freememtop++;
- }
+ /* spill to memory */
-#ifdef HAS_ADDRESS_REGISTER_FILE
- } else if (IS_ADR_TYPE(s->type)) {
- if (s->flags & (SAVEDVAR | SAVEDTMP)) {
-/* s->flags &= ~SAVEDTMP; */
- rd->freesavadrregs[rd->freesavadrtop++] = s->regoff;
- } else
- rd->freetmpadrregs[rd->freetmpadrtop++] = s->regoff;
-#endif
- } else if (IS_FLT_DBL_TYPE(s->type)) {
- if (s->flags & (SAVEDVAR | SAVEDTMP)) {
-/* s->flags &= ~SAVEDTMP; */
- rd->freesavfltregs[rd->freesavflttop++] = s->regoff;
- } else if (s->flags & TMPARG) {
-/* s->flags &= ~TMPARG; */
- rd->freeargfltregs[rd->freeargflttop++] = s->regoff;
- } else
- rd->freetmpfltregs[rd->freetmpflttop++] = s->regoff;
- } else { /* IS_INT_LNG_TYPE */
- if (s->flags & (SAVEDVAR | SAVEDTMP)) {
-/* s->flags &= ~SAVEDTMP; */
-#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
- if (intregsneeded) {
- rd->freesavintregs[rd->freesavinttop] =
- GET_LOW_REG(s->regoff);
- rd->freesavintregs[rd->freesavinttop + 1] =
- GET_HIGH_REG(s->regoff);
- } else
-#endif
- rd->freesavintregs[rd->freesavinttop] = s->regoff;
- rd->freesavinttop += intregsneeded + 1;
+ v->flags |= INMEMORY;
- } else if (s->flags & TMPARG) {
-/* s->flags &= ~TMPARG; */
-#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
- if (intregsneeded) {
- rd->freeargintregs[rd->freearginttop] =
- GET_LOW_REG(s->regoff);
- rd->freeargintregs[rd->freearginttop + 1] =
- GET_HIGH_REG(s->regoff);
- } else
-#endif
- rd->freeargintregs[rd->freearginttop] = s->regoff;
- rd->freearginttop += intregsneeded + 1;
- } else {
-#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
- if (intregsneeded) {
- rd->freetmpintregs[rd->freetmpinttop] =
- GET_LOW_REG(s->regoff);
- rd->freetmpintregs[rd->freetmpinttop + 1] =
- GET_HIGH_REG(s->regoff);
- } else
-#endif
- rd->freetmpintregs[rd->freetmpinttop] = s->regoff;
- rd->freetmpinttop += intregsneeded + 1;
- }
- }
+ if (rd->freememtop > 0)
+ POP_BACK(rd->freemem, rd->freememtop, v->vv.regoff);
+ else
+ NEW_MEM_SLOT_REUSE_PADDING(v->vv.regoff);
}
-static bool reg_alloc_dup(stackptr src, stackptr dst) {
- /* only copy TEMPVARS, do not mess with STACKVAR, */
- /* LOCALVAR, or ARGVAR */
- if ((src->varkind == TEMPVAR) && (dst->varkind == TEMPVAR)) {
- /* can not allocate a REG_TMP to a REG_SAV Slot */
- if (src->flags & INMEMORY) {
- dst->regoff = src->regoff;
- dst->flags |= INMEMORY;
- return true;
- } else if ((src->flags & SAVEDVAR) == (dst->flags & SAVEDVAR)) {
- dst->regoff = src->regoff;
- dst->flags |= src->flags & SAVEDTMP;
- dst->flags |= src->flags & TMPARG;
- return true;
-#if 0
- } else if ((dst->flags & SAVEDVAR) == 0) {
- /* can only use a REG_SAV as REG_TMP! */
- dst->regoff = src->regoff;
- dst->flags |= src->flags & TMPARG;
- dst->flags |= SAVEDTMP;
- return true;
-#endif
- }
- }
- /* no copy possible - allocate a new reg/memory location*/
- return false;
-}
-/* Mark the copies (STCOPY) at the dst stack right for DUPx and SWAP */
-static void new_reg_mark_copy(registerdata *rd, stackptr *dupslots,
- int nin, int nout, int nthrough)
+static void simplereg_free(registerdata *rd, s4 flags, s4 regoff, s4 type)
{
- s4 src_regoff[4];
- s4 src_flags[4];
- stackptr dst_stackslots[6];
- int s_bottom, d_bottom, i, j, slots;
- bool found;
- stackptr sp;
- stackptr *argp;
-
- assert(nin <= 4 && (nout + nthrough) <= 6);
-
- /* remember all different Registers/Memory Location of used TEMPVAR */
- /* instacks in src_varnum[] and src_flags[] _uniquely_. Take the STCOPY */
- /* flag of the last (deepest) occurence */
- slots = nin;
- argp = dupslots + slots;
- for (s_bottom = 4; slots--; ) {
- sp = *--argp;
- if (sp->varkind == TEMPVAR) {
- found = false;
- for (i = 3; i >= s_bottom; i--) {
- if ((src_regoff[i] == sp->regoff) &&
- ((src_flags[i] & INMEMORY) == (sp->flags & INMEMORY)) )
- {
- src_flags[i] &= (~STCOPY | (sp->flags & STCOPY));
- found = true;
- }
- }
- if (!found) {
- s_bottom--;
- src_regoff[s_bottom] = sp->regoff;
- src_flags[s_bottom] = sp->flags;
- }
- }
- }
-
- /* Remember used TEMPVAR dst Stackslots in dst_stackslots[], since they */
- /* have to be from the "lowest" upwards, and the stackelements list is */
- /* linked from only top downwards */
-
- slots = nthrough + nout;
- argp = dupslots + nin + nout;
- for (d_bottom = 6; slots--; ) {
- sp = *--argp;
- if (sp->varkind == TEMPVAR) {
- d_bottom--;
- dst_stackslots[d_bottom] = sp;
- }
- }
+ /* assert that constants are not freed */
- /* Mark all reused reg/mem in dst stacklots with STCOPY, if the */
- /* corresponding src stackslot was marked STCOPY*/
- /* if the correspondig STCOPY from the src stackslot was not set, do not */
- /* mark the lowest occurence at dst stackslots */
- /* mark in src_flag reg/mem with STKEEP, if they where reused in the dst */
- /* stacklots, so they are not freed afterwards */
- for (i = d_bottom; i < 6; i++) {
- for (j = s_bottom; j < 4; j++) {
- if ( (src_regoff[j] == dst_stackslots[i]->regoff) &&
- ((src_flags[j] & INMEMORY) == (dst_stackslots[i]->flags & INMEMORY)) )
- {
- if (src_flags[j] & STCOPY) {
- dst_stackslots[i]->flags |= STCOPY;
- }
- else {
- src_flags[j] |= STCOPY;
- dst_stackslots[i]->flags &= ~STCOPY;
- }
- /* do not free reg/mem of src Stackslot */
- src_flags[j] |= STKEEP;
- }
- }
- }
+ assert(type != TYPE_RET);
- /* free all reg/mem of src stack, which where not marked with STKEEP */
- for (j=s_bottom; j < 4; j++) {
- if ((src_flags[j] & STKEEP)==0) {
- /* free, if STCOPY of src stackslot is not set */
- /* STCOPY is already checked in reg_free_temp macro! */
- slots = nin;
- argp = dupslots + slots;
- while (--slots) {
- sp = *--argp;
- if ((src_regoff[j] == sp->regoff) &&
- ((src_flags[j] & INMEMORY) == (sp->flags & INMEMORY)) )
- {
- reg_free_temp(rd, sp);
- }
- }
- }
- }
-}
+ /* if this is a copy of another variable, just decrement the copy counter */
-/* Mark the copies (STCOPY) at the dst stack right for DUPx and SWAP */
-static void reg_mark_copy(registerdata *rd, stackptr src_top, stackptr src_bottom, stackptr dst_top, stackptr dst_bottom) {
- s4 src_regoff[4];
- s4 src_flags[4];
- stackptr dst_stackslots[6];
- int s_bottom, d_bottom, i, j;
- bool found;
-
- stackptr sp;
-
- /* remember all different Registers/Memory Location of used TEMPVAR */
- /* instacks in src_varnum[] and src_flags[] _uniquely_. Take the STCOPY */
- /* flag of the last (deepest) occurence */
- for(s_bottom = 4, sp = src_top; sp >= src_bottom; sp = sp->prev) {
- if (sp->varkind == TEMPVAR) {
- found = false;
- for( i = 3; i >= s_bottom; i--) {
- if ((src_regoff[i] == sp->regoff) &&
- ((src_flags[i] & INMEMORY) == (sp->flags & INMEMORY)) ) {
- src_flags[i] &= (~STCOPY | (sp->flags & STCOPY));
- found = true;
- }
- }
- if (!found) {
- s_bottom--;
- src_regoff[s_bottom] = sp->regoff;
- src_flags[s_bottom] = sp->flags;
- }
- }
- }
+ if (flags & INMEMORY) {
+ int32_t memindex;
- /* Remember used TEMPVAR dst Stackslots in dst_stackslots[], since they */
- /* have to be from the "lowest" upwards, and the stackelements list is */
- /* linked from only top downwards */
-
- for(d_bottom = 6, sp =dst_top; sp >= dst_bottom; sp = sp->prev) {
- if (sp->varkind == TEMPVAR) {
- d_bottom--;
- dst_stackslots[d_bottom] = sp;
- }
- }
+ if (flags & INOUT)
+ return;
- /* Mark all reused reg/mem in dst stacklots with STCOPY, if the */
- /* corresponding src stackslot was marked STCOPY*/
- /* if the correspondig STCOPY from the src stackslot was not set, do not */
- /* mark the lowest occurence at dst stackslots */
- /* mark in src_flag reg/mem with STKEEP, if they where reused in the dst */
- /* stacklots, so they are not freed afterwards */
- for(i = d_bottom; i < 6; i++) {
- for(j = s_bottom; j < 4; j++) {
- if ( (src_regoff[j] == dst_stackslots[i]->regoff) &&
- ((src_flags[j] & INMEMORY) == (dst_stackslots[i]->flags & INMEMORY)) ) {
- if (src_flags[j] & STCOPY)
- dst_stackslots[i]->flags |= STCOPY;
- else {
- src_flags[j] |= STCOPY;
- dst_stackslots[i]->flags &= ~STCOPY;
- }
- /* do not free reg/mem of src Stackslot */
- src_flags[j] |= STKEEP;
- }
- }
- }
+ memindex = regoff / SIZE_OF_STACKSLOT;
- /* free all reg/mem of src stack, which where not marked with STKEEP */
- for(j=s_bottom; j < 4; j++) {
- if ((src_flags[j] & STKEEP)==0) {
- /* free, if STCOPY of src stackslot is not set */
- /* STCOPY is already checked in reg_free_temp macro! */
- for(sp = src_top; sp >= src_bottom; sp = sp->prev)
- if ((src_regoff[j] == sp->regoff) &&
- ((src_flags[j] & INMEMORY) == (sp->flags & INMEMORY)) ) {
- reg_free_temp(rd, sp);
- }
+ if (memindex < rd->memcopycountsize && rd->memcopycount[memindex]) {
+ rd->memcopycount[memindex]--;
+ return;
}
- }
-}
-
-
-/* allocate_scratch_registers **************************************************
-
- Allocate temporary (non-interface, non-local) registers.
-
-*******************************************************************************/
-
-static void new_allocate_scratch_registers(jitdata *jd)
-{
- methodinfo *m;
- registerdata *rd;
- s4 i;
- s4 len;
- new_instruction *iptr;
- basicblock *bptr;
- builtintable_entry *bte;
- methoddesc *md;
- stackptr *argp;
-
- /* get required compiler data */
-
- m = jd->m;
- rd = jd->rd;
-
- /* initialize temp registers */
- reg_init_temp(m, rd);
-
- bptr = jd->new_basicblocks;
-
- while (bptr != NULL) {
- if (bptr->flags >= BBREACHED) {
- iptr = /* XXX */ (new_instruction *) bptr->iinstr;
- len = bptr->icount;
-
- while (--len >= 0) {
- switch (iptr->opc) {
-
- /* pop 0 push 0 */
-
- case ICMD_NOP:
- case ICMD_ELSE_ICONST:
- case ICMD_CHECKNULL:
- case ICMD_IINC:
- case ICMD_JSR:
- case ICMD_RET:
- case ICMD_RETURN:
- case ICMD_GOTO:
- case ICMD_PUTSTATICCONST:
- case ICMD_INLINE_START:
- case ICMD_INLINE_END:
- case ICMD_INLINE_GOTO:
- break;
-
- /* pop 0 push 1 const */
-
- case ICMD_ICONST:
- case ICMD_LCONST:
- case ICMD_FCONST:
- case ICMD_DCONST:
- case ICMD_ACONST:
-
- /* pop 0 push 1 load */
-
- case ICMD_ILOAD:
- case ICMD_LLOAD:
- case ICMD_FLOAD:
- case ICMD_DLOAD:
- case ICMD_ALOAD:
- reg_new_temp(rd, iptr->dst.var);
- break;
-
- /* pop 2 push 1 */
-
- case ICMD_IALOAD:
- case ICMD_LALOAD:
- case ICMD_FALOAD:
- case ICMD_DALOAD:
- case ICMD_AALOAD:
-
- case ICMD_BALOAD:
- case ICMD_CALOAD:
- case ICMD_SALOAD:
- reg_free_temp(rd, iptr->sx.s23.s2.var);
- reg_free_temp(rd, iptr->s1.var);
- reg_new_temp(rd, iptr->dst.var);
- break;
-
- /* pop 3 push 0 */
-
- case ICMD_IASTORE:
- case ICMD_LASTORE:
- case ICMD_FASTORE:
- case ICMD_DASTORE:
- case ICMD_AASTORE:
-
- case ICMD_BASTORE:
- case ICMD_CASTORE:
- case ICMD_SASTORE:
- reg_free_temp(rd, iptr->sx.s23.s3.var);
- reg_free_temp(rd, iptr->sx.s23.s2.var);
- reg_free_temp(rd, iptr->s1.var);
- break;
-
- /* pop 1 push 0 store */
-
- case ICMD_ISTORE:
- case ICMD_LSTORE:
- case ICMD_FSTORE:
- case ICMD_DSTORE:
- case ICMD_ASTORE:
-
- /* pop 1 push 0 */
-
- case ICMD_POP:
-
- case ICMD_IRETURN:
- case ICMD_LRETURN:
- case ICMD_FRETURN:
- case ICMD_DRETURN:
- case ICMD_ARETURN:
-
- case ICMD_ATHROW:
-
- case ICMD_PUTSTATIC:
- case ICMD_PUTFIELDCONST:
-
- /* pop 1 push 0 branch */
-
- case ICMD_IFNULL:
- case ICMD_IFNONNULL:
-
- case ICMD_IFEQ:
- case ICMD_IFNE:
- case ICMD_IFLT:
- case ICMD_IFGE:
- case ICMD_IFGT:
- case ICMD_IFLE:
-
- case ICMD_IF_LEQ:
- case ICMD_IF_LNE:
- case ICMD_IF_LLT:
- case ICMD_IF_LGE:
- case ICMD_IF_LGT:
- case ICMD_IF_LLE:
-
- /* pop 1 push 0 table branch */
-
- case ICMD_TABLESWITCH:
- case ICMD_LOOKUPSWITCH:
-
- case ICMD_MONITORENTER:
- case ICMD_MONITOREXIT:
- reg_free_temp(rd, iptr->s1.var);
- break;
-
- /* pop 2 push 0 branch */
-
- case ICMD_IF_ICMPEQ:
- case ICMD_IF_ICMPNE:
- case ICMD_IF_ICMPLT:
- case ICMD_IF_ICMPGE:
- case ICMD_IF_ICMPGT:
- case ICMD_IF_ICMPLE:
-
- case ICMD_IF_LCMPEQ:
- case ICMD_IF_LCMPNE:
- case ICMD_IF_LCMPLT:
- case ICMD_IF_LCMPGE:
- case ICMD_IF_LCMPGT:
- case ICMD_IF_LCMPLE:
-
- case ICMD_IF_FCMPEQ:
- case ICMD_IF_FCMPNE:
-
- case ICMD_IF_FCMPL_LT:
- case ICMD_IF_FCMPL_GE:
- case ICMD_IF_FCMPL_GT:
- case ICMD_IF_FCMPL_LE:
-
- case ICMD_IF_FCMPG_LT:
- case ICMD_IF_FCMPG_GE:
- case ICMD_IF_FCMPG_GT:
- case ICMD_IF_FCMPG_LE:
-
- case ICMD_IF_DCMPEQ:
- case ICMD_IF_DCMPNE:
-
- case ICMD_IF_DCMPL_LT:
- case ICMD_IF_DCMPL_GE:
- case ICMD_IF_DCMPL_GT:
- case ICMD_IF_DCMPL_LE:
-
- case ICMD_IF_DCMPG_LT:
- case ICMD_IF_DCMPG_GE:
- case ICMD_IF_DCMPG_GT:
- case ICMD_IF_DCMPG_LE:
-
- case ICMD_IF_ACMPEQ:
- case ICMD_IF_ACMPNE:
-
- /* pop 2 push 0 */
-
- case ICMD_POP2:
-
- case ICMD_PUTFIELD:
-
- case ICMD_IASTORECONST:
- case ICMD_LASTORECONST:
- case ICMD_AASTORECONST:
- case ICMD_BASTORECONST:
- case ICMD_CASTORECONST:
- case ICMD_SASTORECONST:
- reg_free_temp(rd, iptr->sx.s23.s2.var);
- reg_free_temp(rd, iptr->s1.var);
- break;
-
- /* pop 0 push 1 dup */
-
- case ICMD_DUP:
- /* src === dst->prev (identical Stackslot Element) */
- /* src --> dst (copied value, take same reg/mem) */
-
- if (!reg_alloc_dup(iptr->s1.var, iptr->dst.var)) {
- reg_new_temp(rd, iptr->dst.var);
- } else {
- iptr->dst.var->flags |= STCOPY;
- }
- break;
-
- /* pop 0 push 2 dup */
-
- case ICMD_DUP2:
- /* src->prev === dst->prev->prev->prev (identical Stackslot Element) */
- /* src === dst->prev->prev (identical Stackslot Element) */
- /* src->prev --> dst->prev (copied value, take same reg/mem) */
- /* src --> dst (copied value, take same reg/mem) */
-
- if (!reg_alloc_dup(iptr->dst.dupslots[0], iptr->dst.dupslots[2+0]))
- reg_new_temp(rd, iptr->dst.dupslots[2+0]);
- if (!reg_alloc_dup(iptr->dst.dupslots[1], iptr->dst.dupslots[2+1]))
- reg_new_temp(rd, iptr->dst.dupslots[2+1]);
- new_reg_mark_copy(rd, iptr->dst.dupslots, 2, 2, 2);
- break;
-
- /* pop 2 push 3 dup */
-
- case ICMD_DUP_X1:
- /* src->prev --> dst->prev (copied value, take same reg/mem) */
- /* src --> dst (copied value, take same reg/mem) */
- /* src --> dst->prev->prev (copied value, take same reg/mem) */
-
- if (!reg_alloc_dup(iptr->dst.dupslots[1], iptr->dst.dupslots[2+0]))
- reg_new_temp(rd, iptr->dst.dupslots[2+0]);
- if (!reg_alloc_dup(iptr->dst.dupslots[1], iptr->dst.dupslots[2+2]))
- reg_new_temp(rd, iptr->dst.dupslots[2+2]);
- if (!reg_alloc_dup(iptr->dst.dupslots[0], iptr->dst.dupslots[2+1]))
- reg_new_temp(rd, iptr->dst.dupslots[2+1]);
- new_reg_mark_copy(rd, iptr->dst.dupslots, 2, 3, 0);
- break;
-
- /* pop 3 push 4 dup */
-
- case ICMD_DUP_X2:
- /* src->prev->prev --> dst->prev->prev */
- /* src->prev --> dst->prev */
- /* src --> dst */
- /* src --> dst->prev->prev->prev */
-
- if (!reg_alloc_dup(iptr->dst.dupslots[2], iptr->dst.dupslots[3+0]))
- reg_new_temp(rd, iptr->dst.dupslots[3+0]);
- if (!reg_alloc_dup(iptr->dst.dupslots[2], iptr->dst.dupslots[3+3]))
- reg_new_temp(rd, iptr->dst.dupslots[3+3]);
- if (!reg_alloc_dup(iptr->dst.dupslots[1], iptr->dst.dupslots[3+2]))
- reg_new_temp(rd, iptr->dst.dupslots[3+2]);
- if (!reg_alloc_dup(iptr->dst.dupslots[0], iptr->dst.dupslots[3+1]))
- reg_new_temp(rd, iptr->dst.dupslots[3+1]);
- new_reg_mark_copy(rd, iptr->dst.dupslots, 3, 4, 0);
- break;
+ }
+ else {
+ s4 regindex;
- /* pop 3 push 5 dup */
-
- case ICMD_DUP2_X1:
- /* src->prev->prev --> dst->prev->prev */
- /* src->prev --> dst->prev */
- /* src --> dst */
- /* src->prev --> dst->prev->prev->prev->prev */
- /* src --> dst->prev->prev->prev */
-
- if (!reg_alloc_dup(iptr->dst.dupslots[2], iptr->dst.dupslots[3+1]))
- reg_new_temp(rd, iptr->dst.dupslots[3+1]);
- if (!reg_alloc_dup(iptr->dst.dupslots[2], iptr->dst.dupslots[3+4]))
- reg_new_temp(rd, iptr->dst.dupslots[3+4]);
- if (!reg_alloc_dup(iptr->dst.dupslots[1], iptr->dst.dupslots[3+0]))
- reg_new_temp(rd, iptr->dst.dupslots[3+0]);
- if (!reg_alloc_dup(iptr->dst.dupslots[1], iptr->dst.dupslots[3+3]))
- reg_new_temp(rd, iptr->dst.dupslots[3+3]);
- if (!reg_alloc_dup(iptr->dst.dupslots[0], iptr->dst.dupslots[3+2]))
- reg_new_temp(rd, iptr->dst.dupslots[3+2]);
- new_reg_mark_copy(rd, iptr->dst.dupslots, 3, 5, 0);
- break;
+ regindex = REG_INDEX(regoff, type);
- /* pop 4 push 6 dup */
-
- case ICMD_DUP2_X2:
- /* src->prev->prev->prev --> dst->prev->prev->prev */
- /* src->prev->prev --> dst->prev->prev */
- /* src->prev --> dst->prev */
- /* src --> dst */
- /* src->prev --> dst->prev->prev->prev->prev->prev */
- /* src --> dst->prev->prev->prev->prev */
-
- if (!reg_alloc_dup(iptr->dst.dupslots[3], iptr->dst.dupslots[4+1]))
- reg_new_temp(rd, iptr->dst.dupslots[4+1]);
- if (!reg_alloc_dup(iptr->dst.dupslots[3], iptr->dst.dupslots[4+5]))
- reg_new_temp(rd, iptr->dst.dupslots[4+5]);
- if (!reg_alloc_dup(iptr->dst.dupslots[2], iptr->dst.dupslots[4+0]))
- reg_new_temp(rd, iptr->dst.dupslots[4+0]);
- if (!reg_alloc_dup(iptr->dst.dupslots[2], iptr->dst.dupslots[4+4]))
- reg_new_temp(rd, iptr->dst.dupslots[4+4]);
- if (!reg_alloc_dup(iptr->dst.dupslots[1], iptr->dst.dupslots[4+3]))
- reg_new_temp(rd, iptr->dst.dupslots[4+3]);
- if (!reg_alloc_dup(iptr->dst.dupslots[0], iptr->dst.dupslots[4+2]))
- reg_new_temp(rd, iptr->dst.dupslots[4+2]);
- new_reg_mark_copy(rd, iptr->dst.dupslots, 4, 6, 0);
- break;
+ /* do not free interface registers that are needed as outvars */
- /* pop 2 push 2 swap */
-
- case ICMD_SWAP:
- /* src --> dst->prev (copy) */
- /* src->prev --> dst (copy) */
-
- if (!reg_alloc_dup(iptr->dst.dupslots[1], iptr->dst.dupslots[2+0]))
- reg_new_temp(rd, iptr->dst.dupslots[2+0]);
- if (!reg_alloc_dup(iptr->dst.dupslots[0], iptr->dst.dupslots[2+1]))
- reg_new_temp(rd, iptr->dst.dupslots[2+1]);
- new_reg_mark_copy(rd, iptr->dst.dupslots, 2, 2, 0);
- break;
+ if (flags & INOUT) {
+ if (rd->regisoutvar[regindex]) {
+ LOG(("DONT FREE f=%02x r=%d t=%d\n", flags, regoff, type));
+ return;
+ }
- /* pop 2 push 1 */
-
- case ICMD_IADD:
- case ICMD_ISUB:
- case ICMD_IMUL:
- case ICMD_IDIV:
- case ICMD_IREM:
+ LOG(("FREEING INVAR f=%02x r=%d t=%d\n", flags, regoff, type));
+ }
- case ICMD_ISHL:
- case ICMD_ISHR:
- case ICMD_IUSHR:
- case ICMD_IAND:
- case ICMD_IOR:
- case ICMD_IXOR:
+ if (rd->regcopycount[regindex]) {
+ rd->regcopycount[regindex]--;
+ return;
+ }
+ }
- case ICMD_LADD:
- case ICMD_LSUB:
- case ICMD_LMUL:
- case ICMD_LDIV:
- case ICMD_LREM:
+ if (flags & INMEMORY) {
+ PUSH_BACK(rd->freemem, rd->freememtop, regoff);
+ return;
+ }
- case ICMD_LOR:
- case ICMD_LAND:
- case ICMD_LXOR:
+ /* freeing a register */
- case ICMD_LSHL:
- case ICMD_LSHR:
- case ICMD_LUSHR:
+#ifdef HAS_ADDRESS_REGISTER_FILE
+ if (IS_ADR_TYPE(type)) {
+ if (flags & (SAVEDVAR | SAVREG))
+ PUSH_FREE_SAV_ADR(regoff);
+ else
+ PUSH_FREE_TMP_ADR(regoff);
+ }
+#endif
+ else if (IS_FLT_DBL_TYPE(type)) {
+ if (flags & (SAVEDVAR | SAVREG))
+ PUSH_FREE_SAV_FLT(regoff);
+ else if (flags & ARGREG)
+ PUSH_FREE_ARG_FLT(regoff);
+ else
+ PUSH_FREE_TMP_FLT(regoff);
+ }
+ else { /* IS_INT_LNG_TYPE */
+#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
+ s4 intregsneeded = (IS_2_WORD_TYPE(type)) ? 1 : 0;
+#endif
- case ICMD_FADD:
- case ICMD_FSUB:
- case ICMD_FMUL:
- case ICMD_FDIV:
- case ICMD_FREM:
+ if (flags & (SAVEDVAR | SAVREG))
+ PUSH_FREE_SAV_INT(regoff);
+ else if (flags & ARGREG)
+ PUSH_FREE_ARG_INT(regoff);
+ else
+ PUSH_FREE_TMP_INT(regoff);
+ }
+}
- case ICMD_DADD:
- case ICMD_DSUB:
- case ICMD_DMUL:
- case ICMD_DDIV:
- case ICMD_DREM:
- case ICMD_LCMP:
- case ICMD_FCMPL:
- case ICMD_FCMPG:
- case ICMD_DCMPL:
- case ICMD_DCMPG:
- reg_free_temp(rd, iptr->sx.s23.s2.var);
- reg_free_temp(rd, iptr->s1.var);
- reg_new_temp(rd, iptr->dst.var);
- break;
+static inline void simplereg_free_temp(jitdata *jd, s4 index)
+{
+ varinfo *v;
- /* pop 1 push 1 */
-
- case ICMD_IADDCONST:
- case ICMD_ISUBCONST:
- case ICMD_IMULCONST:
- case ICMD_IMULPOW2:
- case ICMD_IDIVPOW2:
- case ICMD_IREMPOW2:
- case ICMD_IANDCONST:
- case ICMD_IORCONST:
- case ICMD_IXORCONST:
- case ICMD_ISHLCONST:
- case ICMD_ISHRCONST:
- case ICMD_IUSHRCONST:
+ v = VAR(index);
- case ICMD_LADDCONST:
- case ICMD_LSUBCONST:
- case ICMD_LMULCONST:
- case ICMD_LMULPOW2:
- case ICMD_LDIVPOW2:
- case ICMD_LREMPOW2:
- case ICMD_LANDCONST:
- case ICMD_LORCONST:
- case ICMD_LXORCONST:
- case ICMD_LSHLCONST:
- case ICMD_LSHRCONST:
- case ICMD_LUSHRCONST:
+ simplereg_free(jd->rd, v->flags, v->vv.regoff, v->type);
+}
- case ICMD_IFEQ_ICONST:
- case ICMD_IFNE_ICONST:
- case ICMD_IFLT_ICONST:
- case ICMD_IFGE_ICONST:
- case ICMD_IFGT_ICONST:
- case ICMD_IFLE_ICONST:
- case ICMD_INEG:
- case ICMD_INT2BYTE:
- case ICMD_INT2CHAR:
- case ICMD_INT2SHORT:
- case ICMD_LNEG:
- case ICMD_FNEG:
- case ICMD_DNEG:
+static bool simplereg_alloc_dup(jitdata *jd, s4 srcindex, s4 dstindex)
+{
+ varinfo *sv;
+ varinfo *dv;
- case ICMD_I2L:
- case ICMD_I2F:
- case ICMD_I2D:
- case ICMD_L2I:
- case ICMD_L2F:
- case ICMD_L2D:
- case ICMD_F2I:
- case ICMD_F2L:
- case ICMD_F2D:
- case ICMD_D2I:
- case ICMD_D2L:
- case ICMD_D2F:
+ /* do not coalesce local variables here */
- case ICMD_CHECKCAST:
+ if (srcindex <= jd->localcount || dstindex <= jd->localcount)
+ return false;
- case ICMD_ARRAYLENGTH:
- case ICMD_INSTANCEOF:
+ sv = VAR(srcindex);
+ dv = VAR(dstindex);
- case ICMD_NEWARRAY:
- case ICMD_ANEWARRAY:
+ /* do not coalesce in/out vars or preallocated variables here */
- case ICMD_GETFIELD:
- reg_free_temp(rd, iptr->s1.var);
- reg_new_temp(rd, iptr->dst.var);
- break;
+ if ((sv->flags | dv->flags) & (INOUT | PREALLOC))
+ return false;
- /* pop 0 push 1 */
-
- case ICMD_GETSTATIC:
+ /* if the source is in memory, we can coalesce in any case */
- case ICMD_NEW:
- reg_new_temp(rd, iptr->dst.var);
- break;
+ if (sv->flags & INMEMORY) {
+ dv->flags |= INMEMORY;
+ dv->vv.regoff = sv->vv.regoff;
+ return true;
+ }
- /* pop many push any */
-
- case ICMD_INVOKESTATIC:
- case ICMD_INVOKESPECIAL:
- case ICMD_INVOKEVIRTUAL:
- case ICMD_INVOKEINTERFACE:
- NEW_INSTRUCTION_GET_METHODDESC(iptr,md);
- i = md->paramcount;
- argp = iptr->sx.s23.s2.args;
- while (--i >= 0) {
- reg_free_temp(rd, *argp);
- argp++;
- }
- if (md->returntype.type != TYPE_VOID)
- reg_new_temp(rd, iptr->dst.var);
- break;
+ /* we do not allocate a REG_TMP to a REG_SAV variable */
- case ICMD_BUILTIN:
- bte = iptr->sx.s23.s3.bte;
- md = bte->md;
- i = md->paramcount;
- argp = iptr->sx.s23.s2.args;
- while (--i >= 0) {
- reg_free_temp(rd, *argp);
- argp++;
- }
- if (md->returntype.type != TYPE_VOID)
- reg_new_temp(rd, iptr->dst.var);
- break;
+ if ((sv->flags & SAVEDVAR) != (dv->flags & SAVEDVAR))
+ return false;
- case ICMD_MULTIANEWARRAY:
- i = iptr->s1.argcount;
- argp = iptr->sx.s23.s2.args;
- while (--i >= 0) {
- reg_free_temp(rd, *argp);
- argp++;
- }
- reg_new_temp(rd, iptr->dst.var);
- break;
+ /* coalesce */
+ dv->vv.regoff = sv->vv.regoff;
+ dv->flags |= sv->flags & (SAVREG | ARGREG);
- default:
- *exceptionptr =
- new_internalerror("Unknown ICMD %d during register allocation",
- iptr->opc);
- return;
- } /* switch */
- iptr++;
- } /* while instructions */
- } /* if */
- bptr = bptr->next;
- } /* while blocks */
+ return true;
}
-static void allocate_scratch_registers(jitdata *jd)
+
+/* simplereg_allocate_temporaries **********************************************
+
+ Allocate temporary (non-interface, non-local) registers.
+
+*******************************************************************************/
+
+static void simplereg_allocate_temporaries(jitdata *jd)
{
methodinfo *m;
registerdata *rd;
s4 i;
s4 len;
- stackptr src;
- stackptr dst;
instruction *iptr;
basicblock *bptr;
builtintable_entry *bte;
methoddesc *md;
+ s4 *argp;
+ varinfo *v;
+ s4 flags;
+ s4 regoff;
+ s4 type;
+ s4 regindex;
/* get required compiler data */
rd = jd->rd;
/* initialize temp registers */
- reg_init_temp(m, rd);
- bptr = m->basicblocks;
+ simplereg_init(jd, rd);
+
+ bptr = jd->basicblocks;
while (bptr != NULL) {
if (bptr->flags >= BBREACHED) {
- dst = bptr->instack;
+
+ LOG(("\nallocating block L%03d\n", bptr->nr));
+
+ simplereg_init_block(rd);
+
+ /* assert that all copy counts are zero */
+
+#if !defined(NDEBUG) && !defined(ENABLE_SSA)
+ for (i=0; i < TOTAL_REG_CNT; ++i)
+ assert(rd->regcopycount[i] == 0);
+#endif
+
+ /* reset outvar flags */
+
+ MZERO(rd->regisoutvar, int, TOTAL_REG_CNT);
+
+ /* set allocation of invars */
+
+ for (i=0; i<bptr->indepth; ++i)
+ {
+ v = VAR(bptr->invars[i]);
+ if (v->type == TYPE_RET)
+ continue;
+
+ v->vv.regoff = jd->interface_map[5*i + v->type].regoff;
+ v->flags = jd->interface_map[5*i + v->type].flags;
+
+ if (!(v->flags & INMEMORY))
+ rd->regcopycount[REG_INDEX(v->vv.regoff, v->type)] = 1;
+ }
+
+ /* set allocation of outvars */
+
+ for (i=0; i<bptr->outdepth; ++i)
+ {
+ v = VAR(bptr->outvars[i]);
+ if (v->type == TYPE_RET)
+ continue;
+
+ v->vv.regoff = jd->interface_map[5*i + v->type].regoff;
+ v->flags = jd->interface_map[5*i + v->type].flags;
+
+ if (!(v->flags & INMEMORY)) {
+ regindex = REG_INDEX(v->vv.regoff, v->type);
+ rd->regcopycount[regindex] = 1;
+ rd->regisoutvar[regindex] = 1;
+ }
+ }
+
+ /* free interface registers not used in this block */
+
+ for (i=0; i < 5 * jd->maxinterfaces; ++i) {
+ type = i%5;
+ regoff = jd->interface_map[i].regoff;
+ flags = jd->interface_map[i].flags;
+
+ if (!(flags & INMEMORY)) {
+ if (!rd->regcopycount[REG_INDEX(regoff, type)]) {
+ LOG(("MAY REUSE interface register f=%02x r=%d t=%d\n",
+ flags, regoff, type));
+ simplereg_free(rd, flags, regoff, type);
+
+ /* mark it, so it is not freed again */
+ rd->regcopycount[REG_INDEX(regoff, type)] = -1;
+ }
+ }
+ }
+
+ /* reset copy counts */
+
+ MZERO(rd->regcopycount, int, TOTAL_REG_CNT);
+
+ /* iterate over ICMDS to allocate temporary variables */
iptr = bptr->iinstr;
len = bptr->icount;
while (--len >= 0) {
- src = dst;
- dst = iptr->dst;
switch (iptr->opc) {
/* pop 0 push 0 */
+ case ICMD_JSR:
case ICMD_NOP:
- case ICMD_ELSE_ICONST:
case ICMD_CHECKNULL:
case ICMD_IINC:
- case ICMD_JSR:
case ICMD_RET:
case ICMD_RETURN:
case ICMD_GOTO:
case ICMD_PUTSTATICCONST:
case ICMD_INLINE_START:
case ICMD_INLINE_END:
- case ICMD_INLINE_GOTO:
+ case ICMD_INLINE_BODY:
break;
/* pop 0 push 1 const */
case ICMD_FCONST:
case ICMD_DCONST:
case ICMD_ACONST:
+ case ICMD_GETEXCEPTION:
/* pop 0 push 1 load */
case ICMD_FLOAD:
case ICMD_DLOAD:
case ICMD_ALOAD:
- reg_new_temp(rd, dst);
+ NEW_TEMP_REG(iptr->dst.varindex);
break;
/* pop 2 push 1 */
case ICMD_BALOAD:
case ICMD_CALOAD:
case ICMD_SALOAD:
- reg_free_temp(rd, src);
- reg_free_temp(rd, src->prev);
- reg_new_temp(rd, dst);
+ FREE_TEMP_REG(iptr->sx.s23.s2.varindex);
+ FREE_TEMP_REG(iptr->s1.varindex);
+ NEW_TEMP_REG(iptr->dst.varindex);
break;
/* pop 3 push 0 */
case ICMD_BASTORE:
case ICMD_CASTORE:
case ICMD_SASTORE:
- reg_free_temp(rd, src);
- reg_free_temp(rd, src->prev);
- reg_free_temp(rd, src->prev->prev);
+ FREE_TEMP_REG(iptr->sx.s23.s3.varindex);
+ FREE_TEMP_REG(iptr->sx.s23.s2.varindex);
+ FREE_TEMP_REG(iptr->s1.varindex);
break;
/* pop 1 push 0 store */
case ICMD_MONITORENTER:
case ICMD_MONITOREXIT:
- reg_free_temp(rd, src);
+ FREE_TEMP_REG(iptr->s1.varindex);
break;
/* pop 2 push 0 branch */
case ICMD_IF_LCMPGT:
case ICMD_IF_LCMPLE:
- case ICMD_IF_FCMPEQ:
- case ICMD_IF_FCMPNE:
-
- case ICMD_IF_FCMPL_LT:
- case ICMD_IF_FCMPL_GE:
- case ICMD_IF_FCMPL_GT:
- case ICMD_IF_FCMPL_LE:
-
- case ICMD_IF_FCMPG_LT:
- case ICMD_IF_FCMPG_GE:
- case ICMD_IF_FCMPG_GT:
- case ICMD_IF_FCMPG_LE:
-
- case ICMD_IF_DCMPEQ:
- case ICMD_IF_DCMPNE:
-
- case ICMD_IF_DCMPL_LT:
- case ICMD_IF_DCMPL_GE:
- case ICMD_IF_DCMPL_GT:
- case ICMD_IF_DCMPL_LE:
-
- case ICMD_IF_DCMPG_LT:
- case ICMD_IF_DCMPG_GE:
- case ICMD_IF_DCMPG_GT:
- case ICMD_IF_DCMPG_LE:
-
case ICMD_IF_ACMPEQ:
case ICMD_IF_ACMPNE:
case ICMD_BASTORECONST:
case ICMD_CASTORECONST:
case ICMD_SASTORECONST:
- reg_free_temp(rd, src);
- reg_free_temp(rd, src->prev);
+ FREE_TEMP_REG(iptr->sx.s23.s2.varindex);
+ FREE_TEMP_REG(iptr->s1.varindex);
break;
- /* pop 0 push 1 dup */
+ /* pop 0 push 1 copy */
- case ICMD_DUP:
+ case ICMD_COPY:
/* src === dst->prev (identical Stackslot Element) */
/* src --> dst (copied value, take same reg/mem) */
- if (!reg_alloc_dup(src, dst)) {
- reg_new_temp(rd, dst);
- } else {
- dst->flags |= STCOPY;
- }
- break;
-
- /* pop 0 push 2 dup */
-
- case ICMD_DUP2:
- /* src->prev === dst->prev->prev->prev (identical Stackslot Element) */
- /* src === dst->prev->prev (identical Stackslot Element) */
- /* src->prev --> dst->prev (copied value, take same reg/mem) */
- /* src --> dst (copied value, take same reg/mem) */
-
- if (!reg_alloc_dup(src->prev, dst->prev))
- reg_new_temp(rd, dst->prev);
- if (!reg_alloc_dup(src, dst))
- reg_new_temp(rd, dst);
- reg_mark_copy(rd, src, src->prev, dst, dst->prev->prev->prev);
- break;
-
- /* pop 2 push 3 dup */
-
- case ICMD_DUP_X1:
- /* src->prev --> dst->prev (copied value, take same reg/mem) */
- /* src --> dst (copied value, take same reg/mem) */
- /* src --> dst->prev->prev (copied value, take same reg/mem) */
-
- if (!reg_alloc_dup(src, dst->prev->prev))
- reg_new_temp(rd, dst->prev->prev);
- if (!reg_alloc_dup(src, dst))
- reg_new_temp(rd, dst);
- if (!reg_alloc_dup(src->prev, dst->prev))
- reg_new_temp(rd, dst->prev);
- reg_mark_copy(rd, src, src->prev, dst, dst->prev->prev);
- break;
+ if (!simplereg_alloc_dup(jd, iptr->s1.varindex, iptr->dst.varindex)) {
+ NEW_TEMP_REG(iptr->dst.varindex);
+ }
+ else {
+ v = VAROP(iptr->dst);
+
+ if (v->flags & INMEMORY) {
+ int32_t memindex = v->vv.regoff / SIZE_OF_STACKSLOT;
+ if (memindex >= rd->memcopycountsize) {
+ int newsize = (memindex + 1) * 2;
+ i = rd->memcopycountsize;
+ rd->memcopycount = DMREALLOC(rd->memcopycount, int, i, newsize);
+ MZERO(rd->memcopycount + i, int, newsize - i);
+ rd->memcopycountsize = newsize;
+ }
+ rd->memcopycount[memindex]++;
+ }
+ else {
+ /* XXX split reg/mem variables on arm may need special handling here */
- /* pop 3 push 4 dup */
-
- case ICMD_DUP_X2:
- /* src->prev->prev --> dst->prev->prev */
- /* src->prev --> dst->prev */
- /* src --> dst */
- /* src --> dst->prev->prev->prev */
-
- if (!reg_alloc_dup(src, dst->prev->prev->prev))
- reg_new_temp(rd, dst->prev->prev->prev);
- if (!reg_alloc_dup(src, dst))
- reg_new_temp(rd, dst);
- if (!reg_alloc_dup(src->prev, dst->prev))
- reg_new_temp(rd, dst->prev);
- if (!reg_alloc_dup(src->prev->prev, dst->prev->prev))
- reg_new_temp(rd, dst->prev->prev);
- reg_mark_copy(rd, src, src->prev->prev, dst, dst->prev->prev->prev);
- break;
+ s4 regindex = REG_INDEX(v->vv.regoff, v->type);
- /* pop 3 push 5 dup */
-
- case ICMD_DUP2_X1:
- /* src->prev->prev --> dst->prev->prev */
- /* src->prev --> dst->prev */
- /* src --> dst */
- /* src->prev --> dst->prev->prev->prev->prev */
- /* src --> dst->prev->prev->prev */
-
- if (!reg_alloc_dup(src, dst->prev->prev->prev))
- reg_new_temp(rd, dst->prev->prev->prev);
- if (!reg_alloc_dup(src, dst))
- reg_new_temp(rd, dst);
- if (!reg_alloc_dup(src->prev, dst->prev->prev->prev->prev))
- reg_new_temp(rd, dst->prev->prev->prev->prev);
- if (!reg_alloc_dup(src->prev, dst->prev))
- reg_new_temp(rd, dst->prev);
- if (!reg_alloc_dup(src->prev->prev, dst->prev->prev))
- reg_new_temp(rd, dst->prev->prev);
- reg_mark_copy(rd, src, src->prev->prev, dst, dst->prev->prev->prev->prev);
+ rd->regcopycount[regindex]++;
+ }
+ }
break;
- /* pop 4 push 6 dup */
-
- case ICMD_DUP2_X2:
- /* src->prev->prev->prev --> dst->prev->prev->prev */
- /* src->prev->prev --> dst->prev->prev */
- /* src->prev --> dst->prev */
- /* src --> dst */
- /* src->prev --> dst->prev->prev->prev->prev->prev */
- /* src --> dst->prev->prev->prev->prev */
-
- if (!reg_alloc_dup(src, dst->prev->prev->prev->prev))
- reg_new_temp(rd, dst->prev->prev->prev->prev);
- if (!reg_alloc_dup(src, dst))
- reg_new_temp(rd, dst);
- if (!reg_alloc_dup(src->prev, dst->prev->prev->prev->prev->prev))
- reg_new_temp(rd, dst->prev->prev->prev->prev->prev);
- if (!reg_alloc_dup(src->prev, dst->prev))
- reg_new_temp(rd, dst->prev);
- if (!reg_alloc_dup(src->prev->prev, dst->prev->prev))
- reg_new_temp(rd, dst->prev->prev);
- if (!reg_alloc_dup(src->prev->prev->prev, dst->prev->prev->prev))
- reg_new_temp(rd, dst->prev->prev->prev);
- reg_mark_copy(rd, src, src->prev->prev->prev, dst, dst->prev->prev->prev->prev->prev);
- break;
+ /* pop 1 push 1 move */
- /* pop 2 push 2 swap */
-
- case ICMD_SWAP:
- /* src --> dst->prev (copy) */
- /* src->prev --> dst (copy) */
-
- if (!reg_alloc_dup(src, dst->prev))
- reg_new_temp(rd, dst->prev);
- if (!reg_alloc_dup(src->prev, dst))
- reg_new_temp(rd, dst);
- reg_mark_copy(rd, src, src->prev, dst, dst->prev);
+ case ICMD_MOVE:
+ if (!simplereg_alloc_dup(jd, iptr->s1.varindex, iptr->dst.varindex)) {
+ NEW_TEMP_REG(iptr->dst.varindex);
+ FREE_TEMP_REG(iptr->s1.varindex);
+ }
break;
/* pop 2 push 1 */
case ICMD_FCMPG:
case ICMD_DCMPL:
case ICMD_DCMPG:
- reg_free_temp(rd, src);
- reg_free_temp(rd, src->prev);
- reg_new_temp(rd, dst);
+ FREE_TEMP_REG(iptr->sx.s23.s2.varindex);
+ FREE_TEMP_REG(iptr->s1.varindex);
+ NEW_TEMP_REG(iptr->dst.varindex);
break;
/* pop 1 push 1 */
case ICMD_LSHRCONST:
case ICMD_LUSHRCONST:
- case ICMD_IFEQ_ICONST:
- case ICMD_IFNE_ICONST:
- case ICMD_IFLT_ICONST:
- case ICMD_IFGE_ICONST:
- case ICMD_IFGT_ICONST:
- case ICMD_IFLE_ICONST:
-
case ICMD_INEG:
case ICMD_INT2BYTE:
case ICMD_INT2CHAR:
case ICMD_ANEWARRAY:
case ICMD_GETFIELD:
- reg_free_temp(rd, src);
- reg_new_temp(rd, dst);
+ FREE_TEMP_REG(iptr->s1.varindex);
+ NEW_TEMP_REG(iptr->dst.varindex);
break;
/* pop 0 push 1 */
case ICMD_GETSTATIC:
case ICMD_NEW:
- reg_new_temp(rd, dst);
+ NEW_TEMP_REG(iptr->dst.varindex);
break;
/* pop many push any */
case ICMD_INVOKEINTERFACE:
INSTRUCTION_GET_METHODDESC(iptr,md);
i = md->paramcount;
+ argp = iptr->sx.s23.s2.args;
while (--i >= 0) {
- reg_free_temp(rd, src);
- src = src->prev;
+ FREE_TEMP_REG(*argp);
+ argp++;
}
if (md->returntype.type != TYPE_VOID)
- reg_new_temp(rd, dst);
+ NEW_TEMP_REG(iptr->dst.varindex);
break;
case ICMD_BUILTIN:
- bte = iptr->val.a;
+ bte = iptr->sx.s23.s3.bte;
md = bte->md;
i = md->paramcount;
+ argp = iptr->sx.s23.s2.args;
while (--i >= 0) {
- reg_free_temp(rd, src);
- src = src->prev;
+ FREE_TEMP_REG(*argp);
+ argp++;
}
if (md->returntype.type != TYPE_VOID)
- reg_new_temp(rd, dst);
+ NEW_TEMP_REG(iptr->dst.varindex);
break;
case ICMD_MULTIANEWARRAY:
- i = iptr->op1;
+ i = iptr->s1.argcount;
+ argp = iptr->sx.s23.s2.args;
while (--i >= 0) {
- reg_free_temp(rd, src);
- src = src->prev;
+ FREE_TEMP_REG(*argp);
+ argp++;
}
- reg_new_temp(rd, dst);
+ NEW_TEMP_REG(iptr->dst.varindex);
break;
default:
- *exceptionptr =
- new_internalerror("Unknown ICMD %d during register allocation",
- iptr->opc);
+ exceptions_throw_internalerror("Unknown ICMD %d during register allocation",
+ iptr->opc);
return;
} /* switch */
iptr++;
#if defined(ENABLE_STATISTICS)
-void reg_make_statistics(jitdata *jd)
+void simplereg_make_statistics(jitdata *jd)
{
methodinfo *m;
codegendata *cd;
registerdata *rd;
- int i,type;
+ int i;
s4 len;
- stackptr src, src_old;
- stackptr dst;
+#if 0
+ stackelement_t* src, src_old;
+ stackelement_t* dst;
instruction *iptr;
+#endif
basicblock *bptr;
int size_interface; /* == maximum size of in/out stack at basic block boundaries */
bool in_register;
+ varinfo *var;
/* get required compiler data */
size_interface = 0;
/* count how many local variables are held in memory or register */
- for(i=0; i < cd->maxlocals; i++)
- for (type=0; type <=4; type++)
- if (rd->locals[i][type].type != -1) { /* valid local */
- if (rd->locals[i][type].flags & INMEMORY) {
- count_locals_spilled++;
- in_register=false;
- }
- else
- count_locals_register++;
- }
+ for(i=0; i < jd->localcount; i++) {
+ if (VAR(i)->flags & INMEMORY) {
+ count_locals_spilled++;
+ in_register=false;
+ }
+ else {
+ count_locals_register++;
+ }
+ }
+
/* count how many stack slots are held in memory or register */
- bptr = m->basicblocks;
+ bptr = jd->basicblocks;
+
while (bptr != NULL) {
if (bptr->flags >= BBREACHED) {
-#if defined(ENABLE_LSRA)
+#if defined(ENABLE_LSRA) || defined(ENABLE_SSA)
if (!opt_lsra) {
#endif
/* check for memory moves from interface to BB instack */
- dst = bptr->instack;
len = bptr->indepth;
if (len > size_interface) size_interface = len;
- while (dst != NULL) {
+ while (len) {
len--;
- if (dst->varkind != STACKVAR) {
- if ( (dst->flags & INMEMORY) ||
- (rd->interfaces[len][dst->type].flags & INMEMORY) ||
- ( (dst->flags & INMEMORY) &&
- (rd->interfaces[len][dst->type].flags & INMEMORY) &&
- (dst->regoff != rd->interfaces[len][dst->type].regoff) ))
- {
- /* one in memory or both inmemory at different offsets */
- count_mem_move_bb++;
- in_register=false;
- }
- }
+ var = VAR(bptr->invars[len]);
- dst = dst->prev;
+ /* invars statistics (currently none) */
}
/* check for memory moves from BB outstack to interface */
- dst = bptr->outstack;
len = bptr->outdepth;
if (len > size_interface) size_interface = len;
- while (dst) {
+ while (len) {
len--;
- if (dst->varkind != STACKVAR) {
- if ( (dst->flags & INMEMORY) || \
- (rd->interfaces[len][dst->type].flags & INMEMORY) || \
- ( (dst->flags & INMEMORY) && \
- (rd->interfaces[len][dst->type].flags & INMEMORY) && \
- (dst->regoff != rd->interfaces[len][dst->type].regoff) ))
- {
- /* one in memory or both inmemory at different offsets */
- count_mem_move_bb++;
- in_register=false;
- }
- }
+ var = VAR(bptr->outvars[len]);
- dst = dst->prev;
+ /* outvars statistics (currently none) */
}
-#if defined(ENABLE_LSRA)
+#if defined(ENABLE_LSRA) || defined(ENABLE_SSA)
}
#endif
+#if 0
dst = bptr->instack;
iptr = bptr->iinstr;
len = bptr->icount;
while (--len >= 0) {
src = dst;
- dst = iptr->dst;
+ dst = iptr->dst.var;
if ((src!= NULL) && (src != src_old)) { /* new stackslot */
switch (src->varkind) {
iptr++;
} /* while instructions */
+#endif
} /* if */
+
bptr = bptr->next;
} /* while blocks */
+
count_interface_size += size_interface; /* accummulate the size of the interface (between bb boundaries) */
if (in_register) count_method_in_register++;
+ if (in_register) {
+/* printf("INREGISTER: %s%s%s\n",m->class->name->text, m->name->text, m->descriptor->text); */
+ }
}
#endif /* defined(ENABLE_STATISTICS) */