/* 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 5584 2006-09-29 14:02:39Z 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);
+
+
+/* size of a stackslot used by the internal ABI */
+
+#define SIZE_OF_STACKSLOT 8
+
+
+/* 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
+
+
+/* macros for handling register stacks ****************************************/
+
+#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 new_regalloc(jitdata *jd)
+
+bool regalloc(jitdata *jd)
{
/* 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. */
+ simplereg_allocate_temporaries and setting it back to the original
+ value before calling simplereg_allocate_locals. */
- interface_regalloc(jd);
- new_allocate_scratch_registers(jd);
- local_regalloc(jd);
+ simplereg_allocate_interfaces(jd);
+ simplereg_allocate_temporaries(jd);
+ simplereg_allocate_locals(jd);
/* everthing's ok */
return true;
}
-/* 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 more vars are packed into this interface slot */
- int intregsneeded = 0;
- int memneeded = 0;
- /* allocate LNG and DBL Types first to ensure 2 memory slots or registers */
- /* on HAS_4BYTE_STACKSLOT architectures */
+ /* 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;
+ 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;
+ /* check if the interface at this stack depth must be a SAVEDVAR */
+
saved = 0;
for (tt = 0; tt <=4; tt++) {
}
}
+ /* allocate reg/mem for each type the interface is used as */
+
for (tt = 0; tt <= 4; tt++) {
t = typeloop[tt];
if (jd->interface_map[s * 5 + t].flags == UNUSED)
continue;
flags = saved;
- regoff = -1; /* XXX for debugging */
+ regoff = -1; /* initialize to invalid value */
#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
- if (!saved) {
-#if defined(HAS_ADDRESS_REGISTER_FILE)
- if (IS_ADR_TYPE(t)) {
- if (!jd->isleafmethod
- &&(rd->argadrreguse < ADR_ARG_CNT)) {
- regoff = rd->argadrregs[rd->argadrreguse++];
- } else if (rd->tmpadrreguse > 0) {
- regoff = rd->tmpadrregs[--rd->tmpadrreguse];
- } else if (rd->savadrreguse > 0) {
- regoff = rd->savadrregs[--rd->savadrreguse];
- } else {
- flags |= INMEMORY;
- regoff = rd->memuse++;
- }
- } 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 */
- flags |= jd->interface_map[fltalloc].flags & INMEMORY;
- regoff = jd->interface_map[fltalloc].regoff;
- } else if (rd->argfltreguse < FLT_ARG_CNT) {
- regoff = rd->argfltregs[rd->argfltreguse++];
- } else if (rd->tmpfltreguse > 0) {
- regoff = rd->tmpfltregs[--rd->tmpfltreguse];
- } else if (rd->savfltreguse > 0) {
- regoff = rd->savfltregs[--rd->savfltreguse];
- } else {
- flags |= INMEMORY;
-#if defined(ALIGN_DOUBLES_IN_MEMORY)
- /* Align doubles in Memory */
- if ( (memneeded) && (rd->memuse & 1))
- rd->memuse++;
-#endif
- regoff = rd->memuse;
- rd->memuse += memneeded + 1;
- }
- fltalloc = s * 5 + 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)) {
- flags |= INMEMORY;
-#if defined(ALIGN_LONGS_IN_MEMORY)
- /* Align longs in Memory */
- if (rd->memuse & 1)
- rd->memuse++;
-#endif
- 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 */
- flags |= jd->interface_map[intalloc].flags & INMEMORY;
-#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
- if (!(flags & INMEMORY)
- && IS_2_WORD_TYPE(intalloc % 5))
- regoff = GET_LOW_REG(
- jd->interface_map[intalloc].regoff);
- else
-#endif
- regoff =
- jd->interface_map[intalloc].regoff;
- } else
- if (rd->argintreguse + intregsneeded
- < INT_ARG_CNT) {
-#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
- if (intregsneeded)
- regoff=PACK_REGS(
- rd->argintregs[rd->argintreguse],
- rd->argintregs[rd->argintreguse + 1]);
- else
-#endif
- 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)
- regoff=PACK_REGS(
- rd->tmpintregs[rd->tmpintreguse],
- rd->tmpintregs[rd->tmpintreguse + 1]);
- else
+ intregsneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
#endif
- regoff =
- rd->tmpintregs[rd->tmpintreguse];
- }
- else if (rd->savintreguse > intregsneeded) {
- rd->savintreguse -= intregsneeded + 1;
- regoff =
- rd->savintregs[rd->savintreguse];
-#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
- if (intregsneeded)
- regoff=PACK_REGS(
- rd->savintregs[rd->savintreguse],
- rd->savintregs[rd->savintreguse + 1]);
- else
-#endif
- regoff =
- rd->savintregs[rd->savintreguse];
- }
- else {
- flags |= INMEMORY;
-#if defined(ALIGN_LONGS_IN_MEMORY)
- /* Align longs in Memory */
- if ( (memneeded) && (rd->memuse & 1))
- rd->memuse++;
-#endif
- regoff = rd->memuse;
- rd->memuse += memneeded + 1;
- }
- intalloc = s * 5 + t;
- } /* if (IS_FLT_DBL_TYPE(t)) */
+ if (!saved) {
+#if defined(HAS_ADDRESS_REGISTER_FILE)
+ if (IS_ADR_TYPE(t)) {
+ if (!code_is_leafmethod(code) && AVAIL_ARG_ADR) {
+ flags |= ARGREG;
+ TAKE_ARG_ADR(regoff);
}
- } 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) {
- regoff = rd->savadrregs[--rd->savadrreguse];
- }
+ 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 */
+ 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;
- regoff = rd->memuse++;
- }
- } else
+ 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
- {
- if (IS_FLT_DBL_TYPE(t)) {
- if (fltalloc >= 0) {
- flags |= jd->interface_map[fltalloc].flags & INMEMORY;
- regoff = jd->interface_map[fltalloc].regoff;
- } else
- if (rd->savfltreguse > 0) {
- regoff =
- rd->savfltregs[--rd->savfltreguse];
+ 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)
+ /* reuse lower half */
+ if (!(flags & INMEMORY)
+ && IS_2_WORD_TYPE(intalloc % 5))
+ regoff = GET_LOW_REG(regoff);
+#endif
+ }
+ 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 {
flags |= INMEMORY;
-#if defined(ALIGN_DOUBLES_IN_MEMORY)
- /* Align doubles in Memory */
- if ( (memneeded) && (rd->memuse & 1))
- rd->memuse++;
-#endif
- regoff = rd->memuse;
- rd->memuse += memneeded + 1;
+ NEW_MEM_SLOT_INT_LNG(regoff);
}
- fltalloc = s * 5 + 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)) {
- flags |= INMEMORY;
-#if defined(ALIGN_LONGS_IN_MEMORY)
- /* Align longs in Memory */
- if (rd->memuse & 1)
- rd->memuse++;
-#endif
- 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) {
- flags |= jd->interface_map[intalloc].flags & INMEMORY;
-#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
- if (!(flags & INMEMORY)
- && IS_2_WORD_TYPE(intalloc % 5))
- regoff =
- GET_LOW_REG(
- jd->interface_map[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
- regoff =
- jd->interface_map[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)
- regoff = PACK_REGS(
- rd->savintregs[rd->savintreguse],
- rd->savintregs[rd->savintreguse + 1]);
- else
-#endif
- regoff =
- rd->savintregs[rd->savintreguse];
- } else {
- 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
- 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 = s*5 + t;
}
- } /* if (IS_FLT_DBL_TYPE(t) else */
- } /* if (IS_ADR_TYPE(t)) else */
- } /* if (saved) else */
+ 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 | OUTVAR;
+ jd->interface_map[5*s + t].flags = flags | INOUT;
jd->interface_map[5*s + t].regoff = regoff;
} /* for t */
} /* for s */
}
+/* simplereg_allocate_locals_leafmethod ****************************************
-/* local_regalloc **************************************************************
+ 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,lm;
+ 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];
- lm = jd->local_map[s * 5 + t];
- if (lm == UNUSED)
- continue;
+ 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;
- v = &(jd->var[lm]);
+ 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->vv.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->vv.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->vv.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->vv.regoff = rd->savadrregs[--rd->savadrreguse];
+ TAKE_SAV_FLT(v->vv.regoff);
}
else {
- v->flags |= INMEMORY;
- v->vv.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 = jd->var[fltalloc].flags;
- v->vv.regoff = jd->var[fltalloc].vv.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->vv.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->vv.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->vv.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->vv.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->vv.regoff = rd->memuse;
- rd->memuse += memneeded + 1;
- }
- fltalloc = jd->local_map[s * 5 + 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->vv.regoff = rd->memuse;
- rd->memuse += memneeded + 1;
- } else
-#endif
- {
- if (intalloc >= 0) {
- v->flags = jd->var[intalloc].flags;
-#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
- if (!(v->flags & INMEMORY)
- && IS_2_WORD_TYPE(jd->var[intalloc].type))
- v->vv.regoff = GET_LOW_REG(
- jd->var[intalloc].vv.regoff);
- else
-#endif
- v->vv.regoff = jd->var[intalloc].vv.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->vv.regoff = PACK_REGS(
- rd->argintregs[GET_LOW_REG(md->params[p].regoff)],
- rd->argintregs[GET_HIGH_REG(md->params[p].regoff)]);
- else
-#endif
- v->vv.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->vv.regoff = PACK_REGS(
- rd->tmpintregs[rd->tmpintreguse],
- rd->tmpintregs[rd->tmpintreguse + 1]);
- else
-#endif
- v->vv.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->vv.regoff=PACK_REGS(
- rd->argintregs[iargcnt],
- rd->argintregs[iargcnt + 1]);
- else
-#endif
- v->vv.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->vv.regoff = PACK_REGS(
- rd->savintregs[rd->savintreguse],
- rd->savintregs[rd->savintreguse + 1]);
- else
-#endif
- v->vv.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->vv.regoff = rd->memuse;
- rd->memuse += memneeded + 1;
- }
+ NEW_MEM_SLOT_INT_LNG(v->vv.regoff);
}
- intalloc = jd->local_map[s * 5 + t];
}
-#ifdef HAS_ADDRESS_REGISTER_FILE
+ intalloc = jd->local_map[s * 5 + t];
}
+#ifdef HAS_ADDRESS_REGISTER_FILE
+ }
#endif
- } /* for (tt=0;...) */
+ } /* for (tt=0;...) */
- /* If the current parameter is a 2-word type, the next local slot */
- /* is skipped. */
+ /* 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++;
- }
+ 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
+
+ /* get required compiler data */
+
+ 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];
- lm = jd->local_map[s * 5 + t];
- if (lm == UNUSED)
+ varindex = jd->local_map[s * 5 + t];
+ if (varindex == UNUSED)
continue;
- v = &(jd->var[lm]);
+ 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->vv.regoff = rd->savadrregs[--rd->savadrreguse];
+ TAKE_SAV_ADR(v->vv.regoff);
}
else {
v->flags = INMEMORY;
- v->vv.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 = jd->var[fltalloc].flags;
- v->vv.regoff = jd->var[fltalloc].vv.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->vv.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->vv.regoff = rd->memuse;
- rd->memuse += memneeded + 1;
+ NEW_MEM_SLOT_FLT_DBL(v->vv.regoff);
}
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->vv.regoff = rd->memuse;
- rd->memuse += memneeded + 1;
- } else {
+ NEW_MEM_SLOT_INT_LNG(v->vv.regoff);
+ }
+ else {
#endif
if (intalloc >= 0) {
- v->flags = jd->var[intalloc].flags;
+ v->flags = VAR(intalloc)->flags;
#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
if (!(v->flags & INMEMORY)
- && IS_2_WORD_TYPE(jd->var[intalloc].type))
+ && IS_2_WORD_TYPE(VAR(intalloc)->type))
v->vv.regoff = GET_LOW_REG(
- jd->var[intalloc].vv.regoff);
+ VAR(intalloc)->vv.regoff);
else
#endif
- v->vv.regoff = jd->var[intalloc].vv.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->vv.regoff = PACK_REGS(
- rd->savintregs[rd->savintreguse],
- rd->savintregs[rd->savintreguse + 1]);
- else
-#endif
- v->vv.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->vv.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 = jd->local_map[s * 5 + t];
#ifdef HAS_ADDRESS_REGISTER_FILE
}
#endif
-
}
}
}
-static void reg_init_temp(jitdata *jd, 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;
rd->freeargadrtop = 0;
#endif
- rd->regcopycount = DMNEW(int, INT_REG_CNT + FLT_REG_CNT);
- MZERO(rd->regcopycount, int, INT_REG_CNT + FLT_REG_CNT);
+ 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(jd,index) \
- if ( (index >= jd->localcount) \
- && (!(jd->var[index].flags & OUTVAR)) \
- && (!(jd->var[index].flags & PREALLOC)) ) \
- reg_new_temp_func(jd, index)
+static void simplereg_init_block(registerdata *rd)
+{
+ int i;
+
+ /* remove all interface registers from the free lists */
-static void reg_new_temp_func(jitdata *jd, s4 index)
+ 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 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 = &(jd->var[index]);
+ 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. */
#ifdef SUPPORT_COMBINE_INTEGER_REGISTERS
intregsneeded = (IS_2_WORD_TYPE(v->type)) ? 1 : 0;
-#else
- intregsneeded = 0;
-#endif
-#if defined(HAS_4BYTE_STACKSLOT)
- memneeded = (IS_2_WORD_TYPE(v->type)) ? 1 : 0;
-#else
- memneeded = 0;
#endif
for(; tryagain; --tryagain) {
if (tryagain == 1) {
if (!(v->flags & SAVEDVAR))
- v->flags |= SAVEDTMP;
+ v->flags |= SAVREG;
#ifdef HAS_ADDRESS_REGISTER_FILE
if (IS_ADR_TYPE(v->type)) {
- if (rd->freesavadrtop > 0) {
- v->vv.regoff = rd->freesavadrregs[--rd->freesavadrtop];
+ if (AVAIL_FREE_SAV_ADR) {
+ TAKE_FREE_SAV_ADR(v->vv.regoff);
return;
- } else if (rd->savadrreguse > 0) {
- v->vv.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(v->type)) {
- if (rd->freesavflttop > 0) {
- v->vv.regoff = rd->freesavfltregs[--rd->freesavflttop];
+ if (AVAIL_FREE_SAV_FLT) {
+ TAKE_FREE_SAV_FLT(v->vv.regoff);
return;
- } else if (rd->savfltreguse > 0) {
- v->vv.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(v->type))
#endif
{
- if (rd->freesavinttop > intregsneeded) {
- rd->freesavinttop -= intregsneeded + 1;
-#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
- if (intregsneeded)
- v->vv.regoff = PACK_REGS(
- rd->freesavintregs[rd->freesavinttop],
- rd->freesavintregs[rd->freesavinttop + 1]);
- else
-#endif
- v->vv.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)
- v->vv.regoff = PACK_REGS(
- rd->savintregs[rd->savintreguse],
- rd->savintregs[rd->savintreguse + 1]);
- else
-#endif
- v->vv.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(v->type)) {
- if (rd->freetmpadrtop > 0) {
- v->vv.regoff = rd->freetmpadrregs[--rd->freetmpadrtop];
+ if (AVAIL_FREE_TMP_ADR) {
+ TAKE_FREE_TMP_ADR(v->vv.regoff);
return;
- } else if (rd->tmpadrreguse > 0) {
- v->vv.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(v->type)) {
- if (rd->freeargflttop > 0) {
- v->vv.regoff = rd->freeargfltregs[--rd->freeargflttop];
- v->flags |= TMPARG;
+ if (AVAIL_FREE_ARG_FLT) {
+ v->flags |= ARGREG;
+ TAKE_FREE_ARG_FLT(v->vv.regoff);
return;
- } else if (rd->argfltreguse < FLT_ARG_CNT) {
- v->vv.regoff = rd->argfltregs[rd->argfltreguse++];
- v->flags |= TMPARG;
+ }
+ else if (AVAIL_ARG_FLT) {
+ v->flags |= ARGREG;
+ TAKE_ARG_FLT(v->vv.regoff);
return;
- } else if (rd->freetmpflttop > 0) {
- v->vv.regoff = rd->freetmpfltregs[--rd->freetmpflttop];
+ }
+ else if (AVAIL_FREE_TMP_FLT) {
+ TAKE_FREE_TMP_FLT(v->vv.regoff);
return;
- } else if (rd->tmpfltreguse > 0) {
- v->vv.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(v->type))
#endif
{
- if (rd->freearginttop > intregsneeded) {
- rd->freearginttop -= intregsneeded + 1;
- v->flags |= TMPARG;
-#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
- if (intregsneeded)
- v->vv.regoff = PACK_REGS(
- rd->freeargintregs[rd->freearginttop],
- rd->freeargintregs[rd->freearginttop + 1]);
- else
-#endif
- v->vv.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)
- v->vv.regoff = PACK_REGS(
- rd->argintregs[rd->argintreguse],
- rd->argintregs[rd->argintreguse + 1]);
- else
-#endif
- v->vv.regoff = rd->argintregs[rd->argintreguse];
- v->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)
- v->vv.regoff = PACK_REGS(
- rd->freetmpintregs[rd->freetmpinttop],
- rd->freetmpintregs[rd->freetmpinttop + 1]);
- else
-#endif
- v->vv.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)
- v->vv.regoff = PACK_REGS(
- rd->tmpintregs[rd->tmpintreguse],
- rd->tmpintregs[rd->tmpintreguse + 1]);
- else
-#endif
- v->vv.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--;
- v->vv.regoff = rd->freemem_2[rd->freememtop_2];
- } else
-#endif /*defined(HAS_4BYTE_STACKSLOT) */
- if ((memneeded == 0) && (rd->freememtop > 0)) {
- rd->freememtop--;;
- v->vv.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) */
- v->vv.regoff = rd->memuse;
- rd->memuse += memneeded + 1;
- }
- v->flags |= INMEMORY;
-}
+ /* spill to memory */
+ v->flags |= INMEMORY;
-#define reg_free_temp(jd,index) \
- if ((index > jd->localcount) \
- && (!(jd->var[index].flags & (OUTVAR | PREALLOC)))) \
- reg_free_temp_func(jd, index)
+ if (rd->freememtop > 0)
+ POP_BACK(rd->freemem, rd->freememtop, v->vv.regoff);
+ else
+ NEW_MEM_SLOT_REUSE_PADDING(v->vv.regoff);
+}
-/* 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(jitdata *jd, s4 index)
+static void simplereg_free(registerdata *rd, s4 flags, s4 regoff, s4 type)
{
- s4 intregsneeded;
- s4 memneeded;
- registerdata *rd;
- varinfo *v;
+ /* assert that constants are not freed */
- rd = jd->rd;
- v = &(jd->var[index]);
+ assert(type != TYPE_RET);
/* if this is a copy of another variable, just decrement the copy counter */
- /* XXX split reg/mem variables on arm may need special handling here */
+ if (flags & INMEMORY) {
+ int32_t memindex;
- if (v->flags & INMEMORY) {
- if (v->vv.regoff < rd->memcopycountsize && rd->memcopycount[v->vv.regoff]) {
- rd->memcopycount[v->vv.regoff]--;
+ if (flags & INOUT)
+ return;
+
+ memindex = regoff / SIZE_OF_STACKSLOT;
+
+ if (memindex < rd->memcopycountsize && rd->memcopycount[memindex]) {
+ rd->memcopycount[memindex]--;
return;
}
}
else {
-#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
- if (rd->regcopycount[GET_LOW_REG(v->vv.regoff)]) {
- rd->regcopycount[GET_LOW_REG(v->vv.regoff)]--;
- return;
+ s4 regindex;
+
+ regindex = REG_INDEX(regoff, type);
+
+ /* do not free interface registers that are needed as outvars */
+
+ if (flags & INOUT) {
+ if (rd->regisoutvar[regindex]) {
+ LOG(("DONT FREE f=%02x r=%d t=%d\n", flags, regoff, type));
+ return;
+ }
+
+ LOG(("FREEING INVAR f=%02x r=%d t=%d\n", flags, regoff, type));
}
-#else
- if (rd->regcopycount[v->vv.regoff]) {
- rd->regcopycount[v->vv.regoff]--;
+
+ if (rd->regcopycount[regindex]) {
+ rd->regcopycount[regindex]--;
return;
}
-#endif
}
-#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
- intregsneeded = (IS_2_WORD_TYPE(v->type)) ? 1 : 0;
-#else
- intregsneeded = 0;
-#endif
-
-#if defined(HAS_4BYTE_STACKSLOT)
- memneeded = (IS_2_WORD_TYPE(v->type)) ? 1 : 0;
-#else
- memneeded = 0;
-#endif
+ if (flags & INMEMORY) {
+ PUSH_BACK(rd->freemem, rd->freememtop, regoff);
+ return;
+ }
- if (v->flags & INMEMORY) {
-#if defined(HAS_4BYTE_STACKSLOT)
- if (memneeded > 0) {
- rd->freemem_2[rd->freememtop_2] = v->vv.regoff;
- rd->freememtop_2++;
- } else
-#endif
- {
- rd->freemem[rd->freememtop] = v->vv.regoff;
- rd->freememtop++;
- }
+ /* freeing a register */
#ifdef HAS_ADDRESS_REGISTER_FILE
- } else if (IS_ADR_TYPE(v->type)) {
- if (v->flags & (SAVEDVAR | SAVEDTMP)) {
-/* v->flags &= ~SAVEDTMP; */
- rd->freesavadrregs[rd->freesavadrtop++] = v->vv.regoff;
- } else
- rd->freetmpadrregs[rd->freetmpadrtop++] = v->vv.regoff;
-#endif
- } else if (IS_FLT_DBL_TYPE(v->type)) {
- if (v->flags & (SAVEDVAR | SAVEDTMP)) {
-/* v->flags &= ~SAVEDTMP; */
- rd->freesavfltregs[rd->freesavflttop++] = v->vv.regoff;
- } else if (v->flags & TMPARG) {
-/* v->flags &= ~TMPARG; */
- rd->freeargfltregs[rd->freeargflttop++] = v->vv.regoff;
- } else
- rd->freetmpfltregs[rd->freetmpflttop++] = v->vv.regoff;
- } else { /* IS_INT_LNG_TYPE */
- if (v->flags & (SAVEDVAR | SAVEDTMP)) {
-/* v->flags &= ~SAVEDTMP; */
+ 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)
- if (intregsneeded) {
- rd->freesavintregs[rd->freesavinttop] =
- GET_LOW_REG(v->vv.regoff);
- rd->freesavintregs[rd->freesavinttop + 1] =
- GET_HIGH_REG(v->vv.regoff);
- } else
+ s4 intregsneeded = (IS_2_WORD_TYPE(type)) ? 1 : 0;
#endif
- rd->freesavintregs[rd->freesavinttop] = v->vv.regoff;
- rd->freesavinttop += intregsneeded + 1;
- } else if (v->flags & TMPARG) {
-/* s->flags &= ~TMPARG; */
-#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
- if (intregsneeded) {
- rd->freeargintregs[rd->freearginttop] =
- GET_LOW_REG(v->vv.regoff);
- rd->freeargintregs[rd->freearginttop + 1] =
- GET_HIGH_REG(v->vv.regoff);
- } else
-#endif
- rd->freeargintregs[rd->freearginttop] = v->vv.regoff;
- rd->freearginttop += intregsneeded + 1;
- } else {
-#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
- if (intregsneeded) {
- rd->freetmpintregs[rd->freetmpinttop] =
- GET_LOW_REG(v->vv.regoff);
- rd->freetmpintregs[rd->freetmpinttop + 1] =
- GET_HIGH_REG(v->vv.regoff);
- } else
-#endif
- rd->freetmpintregs[rd->freetmpinttop] = v->vv.regoff;
- rd->freetmpinttop += intregsneeded + 1;
- }
+ if (flags & (SAVEDVAR | SAVREG))
+ PUSH_FREE_SAV_INT(regoff);
+ else if (flags & ARGREG)
+ PUSH_FREE_ARG_INT(regoff);
+ else
+ PUSH_FREE_TMP_INT(regoff);
}
}
-static bool reg_alloc_dup(jitdata *jd, s4 srcindex, s4 dstindex)
+static inline void simplereg_free_temp(jitdata *jd, s4 index)
+{
+ varinfo *v;
+
+ v = VAR(index);
+
+ simplereg_free(jd->rd, v->flags, v->vv.regoff, v->type);
+}
+
+
+static bool simplereg_alloc_dup(jitdata *jd, s4 srcindex, s4 dstindex)
{
varinfo *sv;
varinfo *dv;
/* do not coalesce in/out vars or preallocated variables here */
- if ((sv->flags | dv->flags) & (OUTVAR | PREALLOC))
+ if ((sv->flags | dv->flags) & (INOUT | PREALLOC))
return false;
/* if the source is in memory, we can coalesce in any case */
/* coalesce */
dv->vv.regoff = sv->vv.regoff;
- dv->flags |= sv->flags & (SAVEDTMP | TMPARG);
+ dv->flags |= sv->flags & (SAVREG | ARGREG);
return true;
}
-/* allocate_scratch_registers **************************************************
+/* simplereg_allocate_temporaries **********************************************
Allocate temporary (non-interface, non-local) registers.
*******************************************************************************/
-static void new_allocate_scratch_registers(jitdata *jd)
+static void simplereg_allocate_temporaries(jitdata *jd)
{
methodinfo *m;
registerdata *rd;
methoddesc *md;
s4 *argp;
varinfo *v;
+ s4 flags;
+ s4 regoff;
+ s4 type;
+ s4 regindex;
/* get required compiler data */
/* initialize temp registers */
- reg_init_temp(jd, rd);
+ simplereg_init(jd, rd);
- bptr = jd->new_basicblocks;
+ bptr = jd->basicblocks;
while (bptr != NULL) {
if (bptr->flags >= BBREACHED) {
+ 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 = jd->var + bptr->invars[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 = jd->var + bptr->outvars[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) {
+
switch (iptr->opc) {
/* pop 0 push 0 */
case ICMD_JSR:
-#if !defined(NDEBUG)
- /* avoid problems with show_allocation */
- jd->var[iptr->dst.varindex].vv.regoff = 0;
-#endif
case ICMD_NOP:
case ICMD_CHECKNULL:
case ICMD_IINC:
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(jd, iptr->dst.varindex);
+ NEW_TEMP_REG(iptr->dst.varindex);
break;
/* pop 2 push 1 */
case ICMD_BALOAD:
case ICMD_CALOAD:
case ICMD_SALOAD:
- reg_free_temp(jd, iptr->sx.s23.s2.varindex);
- reg_free_temp(jd, iptr->s1.varindex);
- reg_new_temp(jd, iptr->dst.varindex);
+ 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(jd, iptr->sx.s23.s3.varindex);
- reg_free_temp(jd, iptr->sx.s23.s2.varindex);
- reg_free_temp(jd, iptr->s1.varindex);
+ 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(jd, iptr->s1.varindex);
+ 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(jd, iptr->sx.s23.s2.varindex);
- reg_free_temp(jd, iptr->s1.varindex);
+ FREE_TEMP_REG(iptr->sx.s23.s2.varindex);
+ FREE_TEMP_REG(iptr->s1.varindex);
break;
/* pop 0 push 1 copy */
/* src === dst->prev (identical Stackslot Element) */
/* src --> dst (copied value, take same reg/mem) */
- if (!reg_alloc_dup(jd, iptr->s1.varindex, iptr->dst.varindex)) {
- reg_new_temp(jd, iptr->dst.varindex);
- } else {
+ 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) {
- if (v->vv.regoff >= rd->memcopycountsize) {
- int newsize = (v->vv.regoff + 1) * 2;
+ 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[v->vv.regoff]++;
+ rd->memcopycount[memindex]++;
}
else {
/* XXX split reg/mem variables on arm may need special handling here */
-#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
- rd->regcopycount[GET_LOW_REG(v->vv.regoff)]++;
-#else
- rd->regcopycount[v->vv.regoff]++;
-#endif
+ s4 regindex = REG_INDEX(v->vv.regoff, v->type);
+
+ rd->regcopycount[regindex]++;
}
}
break;
/* pop 1 push 1 move */
case ICMD_MOVE:
- if (!reg_alloc_dup(jd, iptr->s1.varindex, iptr->dst.varindex)) {
- reg_new_temp(jd, iptr->dst.varindex);
- reg_free_temp(jd, iptr->s1.varindex);
+ if (!simplereg_alloc_dup(jd, iptr->s1.varindex, iptr->dst.varindex)) {
+ NEW_TEMP_REG(iptr->dst.varindex);
+ FREE_TEMP_REG(iptr->s1.varindex);
}
break;
case ICMD_FCMPG:
case ICMD_DCMPL:
case ICMD_DCMPG:
- reg_free_temp(jd, iptr->sx.s23.s2.varindex);
- reg_free_temp(jd, iptr->s1.varindex);
- reg_new_temp(jd, iptr->dst.varindex);
+ 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_ANEWARRAY:
case ICMD_GETFIELD:
- reg_free_temp(jd, iptr->s1.varindex);
- reg_new_temp(jd, iptr->dst.varindex);
+ 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(jd, iptr->dst.varindex);
+ NEW_TEMP_REG(iptr->dst.varindex);
break;
/* pop many push any */
i = md->paramcount;
argp = iptr->sx.s23.s2.args;
while (--i >= 0) {
- reg_free_temp(jd, *argp);
+ FREE_TEMP_REG(*argp);
argp++;
}
if (md->returntype.type != TYPE_VOID)
- reg_new_temp(jd, iptr->dst.varindex);
+ NEW_TEMP_REG(iptr->dst.varindex);
break;
case ICMD_BUILTIN:
i = md->paramcount;
argp = iptr->sx.s23.s2.args;
while (--i >= 0) {
- reg_free_temp(jd, *argp);
+ FREE_TEMP_REG(*argp);
argp++;
}
if (md->returntype.type != TYPE_VOID)
- reg_new_temp(jd, iptr->dst.varindex);
+ NEW_TEMP_REG(iptr->dst.varindex);
break;
case ICMD_MULTIANEWARRAY:
i = iptr->s1.argcount;
argp = iptr->sx.s23.s2.args;
while (--i >= 0) {
- reg_free_temp(jd, *argp);
+ FREE_TEMP_REG(*argp);
argp++;
}
- reg_new_temp(jd, iptr->dst.varindex);
+ 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 = jd->new_basicblocks;
+ bptr = jd->basicblocks;
while (bptr != NULL) {
if (bptr->flags >= BBREACHED) {
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->vv.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->vv.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) || defined(ENABLE_SSA)
}
#endif
+#if 0
dst = bptr->instack;
iptr = bptr->iinstr;
len = bptr->icount;
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);
+/* printf("INREGISTER: %s%s%s\n",m->class->name->text, m->name->text, m->descriptor->text); */
}
}
#endif /* defined(ENABLE_STATISTICS) */