/* src/vm/jit/allocator/simplereg.c - register allocator
- Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
+ Copyright (C) 1996-2005, 2007 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
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 5711 2006-10-06 23:58:35Z 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 "mm/memory.h"
+
#include "vm/builtin.h"
#include "vm/exceptions.h"
-#include "mm/memory.h"
-#include "vm/method.h"
-#include "vm/options.h"
#include "vm/resolve.h"
#include "vm/stringlocal.h"
+
+#include "vm/jit/abi.h"
#include "vm/jit/reg.h"
-#include "vm/jit/allocator/simplereg.h"
#include "vm/jit/show.h"
+#include "vm/jit/allocator/simplereg.h"
+
+#include "vmcore/method.h"
+#include "vmcore/options.h"
#if 0
static void simplereg_allocate_temporaries(jitdata *jd);
+/* size of a stackslot used by the internal ABI */
+
+#if defined(HAS_4BYTE_STACKSLOT)
+# define SIZE_OF_STACKSLOT 4
+#else
+# define SIZE_OF_STACKSLOT 8
+#endif
+
+
+/* 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_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(rd->argfltregs, rd->argfltreguse, r)
+#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_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(rd->argintregs, rd->argintreguse, 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 NEW_MEM_SLOT(r) \
do { \
- (r) = rd->memuse; \
+ (r) = rd->memuse * SIZE_OF_STACKSLOT; \
rd->memuse += memneeded + 1; \
} while (0)
do { \
if ( (memneeded) && (rd->memuse & 1)) \
rd->memuse++; \
- (r) = rd->memuse; \
+ (r) = rd->memuse * SIZE_OF_STACKSLOT; \
rd->memuse += memneeded + 1; \
} while (0)
PUSH_BACK(rd->freemem, rd->freememtop, rd->memuse); \
rd->memuse++; \
} \
- (r) = rd->memuse; \
+ (r) = rd->memuse * SIZE_OF_STACKSLOT; \
rd->memuse += memneeded + 1; \
} while (0)
/* macro for getting a unique register index *********************************/
#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
-#define SIMPLEREG_REG_INDEX(regoff, type) \
+#define REG_INDEX_NON_ADR(regoff, type) \
(IS_FLT_DBL_TYPE(type) ? (INT_REG_CNT + (regoff)) : (GET_LOW_REG(regoff)))
#else
-#define SIMPLEREG_REG_INDEX(regoff, type) \
+#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 ********************************************************************
#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 */
}
else {
flags |= INMEMORY;
- regoff = rd->memuse++;
+ regoff = rd->memuse++ * SIZE_OF_STACKSLOT;
}
}
else /* !IS_ADR_TYPE */
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;
+ flags |= jd->interface_map[fltalloc].flags & ~SAVEDVAR;
regoff = jd->interface_map[fltalloc].regoff;
}
else if (AVAIL_ARG_FLT) {
fltalloc = s * 5 + t;
}
else { /* !IS_FLT_DBL_TYPE(t) */
-#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
*/
NEW_MEM_SLOT_INT_LNG(regoff);
}
else
-#endif /* defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE...GISTERS) */
+#endif
if (intalloc >= 0) {
/* Reuse memory slot(s)/register(s) for shared interface slots */
- flags |= jd->interface_map[intalloc].flags & INMEMORY;
+ flags |= jd->interface_map[intalloc].flags & ~SAVEDVAR;
regoff = jd->interface_map[intalloc].regoff;
#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
/* reuse lower half */
}
else {
flags |= INMEMORY;
- regoff = rd->memuse++;
+ regoff = rd->memuse++ * SIZE_OF_STACKSLOT;
}
}
else
{
if (IS_FLT_DBL_TYPE(t)) {
if (fltalloc >= 0) {
- flags |= jd->interface_map[fltalloc].flags & INMEMORY;
+ flags |= jd->interface_map[fltalloc].flags & ~SAVEDVAR;
regoff = jd->interface_map[fltalloc].regoff;
}
else {
fltalloc = s * 5 + t;
}
else { /* IS_INT_LNG */
-#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
*/
#endif
{
if (intalloc >= 0) {
- flags |= jd->interface_map[intalloc].flags & INMEMORY;
+ flags |= jd->interface_map[intalloc].flags & ~SAVEDVAR;
regoff = jd->interface_map[intalloc].regoff;
#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
/* reuse lower half */
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;
cd = jd->cd;
rd = jd->rd;
- methoddesc *md = m->parseddesc;
+ md = m->parseddesc;
iargcnt = rd->argintreguse;
fargcnt = rd->argfltreguse;
#ifdef HAS_ADDRESS_REGISTER_FILE
aargcnt = rd->argadrreguse;
#endif
- for (p = 0, s = 0; s < cd->maxlocals; s++, p++) {
+ for (p = 0, s = 0; s < jd->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)
+ varindex = jd->local_map[s * 5 + t];
+ if (varindex == UNUSED)
continue;
- v = VAR(lm);
+ v = VAR(varindex);
#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
intregsneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
}
else {
v->flags |= INMEMORY;
- v->vv.regoff = rd->memuse++;
+ v->vv.regoff = rd->memuse++ * SIZE_OF_STACKSLOT;
}
}
else {
#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];
+ v->vv.regoff = md->params[p].regoff;
}
#endif
else if (AVAIL_TMP_FLT) {
TAKE_TMP_FLT(v->vv.regoff);
}
/* use unused argument registers as local registers */
- else if ((p >= md->paramcount) &&
- (fargcnt < FLT_ARG_CNT))
- {
+ else if ((p >= md->paramcount) && (fargcnt < FLT_ARG_CNT)) {
v->flags = 0;
- POP_FRONT(rd->argfltregs, fargcnt, v->vv.regoff);
+ POP_FRONT(abi_registers_float_argument,
+ fargcnt, v->vv.regoff);
}
else if (AVAIL_SAV_FLT) {
v->flags = 0;
}
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
*/
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)]);
+ v->vv.regoff =
+ PACK_REGS(GET_LOW_REG(md->params[p].regoff),
+ GET_HIGH_REG(md->params[p].regoff));
else
#endif
- v->vv.regoff =
- rd->argintregs[md->params[p].regoff];
+ v->vv.regoff = md->params[p].regoff;
}
else if (AVAIL_TMP_INT) {
v->flags = 0;
(iargcnt + intregsneeded < INT_ARG_CNT))
{
v->flags = 0;
- POP_FRONT_INT(rd->argintregs, iargcnt, v->vv.regoff);
+ POP_FRONT_INT(abi_registers_integer_argument,
+ iargcnt, v->vv.regoff);
}
else if (AVAIL_SAV_INT) {
v->flags = 0;
codegendata *cd;
registerdata *rd;
- int s, t, tt, lm;
+ int s, t, tt, varindex;
int intalloc, fltalloc;
varinfo *v;
int memneeded = 0;
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 = VAR(lm);
+ v = VAR(varindex);
#ifdef SUPPORT_COMBINE_INTEGER_REGISTERS
intregsneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
}
else {
v->flags = INMEMORY;
- v->vv.regoff = rd->memuse++;
+ v->vv.regoff = rd->memuse++ * SIZE_OF_STACKSLOT;
}
}
else {
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
*/
v->flags = INMEMORY;
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];
rd->freeargadrtop = 0;
#endif
- rd->regisoutvar = DMNEW(int, INT_REG_CNT + FLT_REG_CNT);
- 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 */
/* record the interface registers as used */
for (i=0; i<rd->argintreguse; ++i)
- rd->intusedinout[rd->argintregs[i]] = 1;
+ 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[rd->argfltregs[i]] = 1;
+ 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 = 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 = (v->flags & SAVEDVAR) ? 1 : 2;
}
}
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
*/
}
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
*/
static void simplereg_free(registerdata *rd, s4 flags, s4 regoff, s4 type)
{
- /* if this is a copy of another variable, just decrement the copy counter */
+ /* assert that constants are not freed */
+
+ assert(type != TYPE_RET);
- /* XXX split reg/mem variables on arm may need special handling here */
+ /* if this is a copy of another variable, just decrement the copy counter */
if (flags & INMEMORY) {
+ int32_t memindex;
+
if (flags & INOUT)
return;
- if (regoff < rd->memcopycountsize && rd->memcopycount[regoff]) {
- rd->memcopycount[regoff]--;
+ memindex = regoff / SIZE_OF_STACKSLOT;
+
+ if (memindex < rd->memcopycountsize && rd->memcopycount[memindex]) {
+ rd->memcopycount[memindex]--;
return;
}
}
else {
s4 regindex;
- regindex = SIMPLEREG_REG_INDEX(regoff, type);
+ regindex = REG_INDEX(regoff, type);
/* do not free interface registers that are needed as outvars */
/* assert that all copy counts are zero */
#if !defined(NDEBUG)
- for (i=0; i < INT_REG_CNT + FLT_REG_CNT; ++i)
+ for (i=0; i < TOTAL_REG_CNT; ++i)
assert(rd->regcopycount[i] == 0);
#endif
/* reset outvar flags */
- MZERO(rd->regisoutvar, int, INT_REG_CNT + FLT_REG_CNT);
+ 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[SIMPLEREG_REG_INDEX(v->vv.regoff, v->type)] = 1;
+ 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 = SIMPLEREG_REG_INDEX(v->vv.regoff, v->type);
+ 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 * m->maxstack; ++i) {
+ 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[SIMPLEREG_REG_INDEX(regoff, type)]) {
+ 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[SIMPLEREG_REG_INDEX(regoff, type)] = -1;
+ rd->regcopycount[REG_INDEX(regoff, type)] = -1;
}
}
}
/* reset copy counts */
- for (i=0; i < INT_REG_CNT + FLT_REG_CNT; ++i)
- rd->regcopycount[i] = 0;
+ MZERO(rd->regcopycount, int, TOTAL_REG_CNT);
/* iterate over ICMDS to allocate temporary variables */
/* pop 0 push 0 */
case ICMD_JSR:
-#if !defined(NDEBUG)
- /* avoid problems with show_allocation */
- VAROP(iptr->dst)->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 */
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 */
- s4 regindex = SIMPLEREG_REG_INDEX(v->vv.regoff, v->type);
+ s4 regindex = REG_INDEX(v->vv.regoff, v->type);
rd->regcopycount[regindex]++;
}
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++;
methodinfo *m;
codegendata *cd;
registerdata *rd;
- int i,type;
+ int i;
s4 len;
+#if 0
stackptr src, src_old;
stackptr dst;
instruction *iptr;
+#endif
basicblock *bptr;
int size_interface; /* == maximum size of in/out stack at basic block boundaries */
bool in_register;
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) */