#include <mono/metadata/mempool-internals.h>
/* Disable for now to save space */
-//#undef MONO_ARCH_ENABLE_GLOBAL_RA
+#undef MONO_ARCH_ENABLE_GLOBAL_RA
#ifdef MONO_ARCH_ENABLE_GLOBAL_RA
cfg->cbb = bb;
MONO_BB_FOR_EACH_INS (bb, ins) {
const char *spec = ins_get_spec (ins->opcode);
- int dest_sreg1, dest_sreg2, dest_dreg;
+ int dest_sreg1, dest_sreg2, dest_sreg3, dest_dreg;
dest_sreg1 = MONO_ARCH_INST_FIXED_REG (spec [MONO_INST_SRC1]);
dest_sreg2 = MONO_ARCH_INST_FIXED_REG (spec [MONO_INST_SRC2]);
+ dest_sreg3 = MONO_ARCH_INST_FIXED_REG (spec [MONO_INST_SRC3]);
dest_dreg = MONO_ARCH_INST_FIXED_REG (spec [MONO_INST_DEST]);
if (MONO_ARCH_INST_IS_REGPAIR (spec [MONO_INST_DEST]) ||
- MONO_ARCH_INST_IS_REGPAIR (spec [MONO_INST_SRC1]) ||
- MONO_ARCH_INST_IS_REGPAIR (spec [MONO_INST_SRC2]))
+ MONO_ARCH_INST_IS_REGPAIR (spec [MONO_INST_SRC1]) ||
+ MONO_ARCH_INST_IS_REGPAIR (spec [MONO_INST_SRC2]) ||
+ MONO_ARCH_INST_IS_REGPAIR (spec [MONO_INST_SRC3])) {
/* FIXME: */
g_assert_not_reached ();
+ }
if (spec [MONO_INST_CLOB] == 'c') {
MonoCallInst *call = (MonoCallInst*)ins;
if (spec [MONO_INST_CLOB] == '1') {
/* Copying sreg1 to dreg could clobber sreg2 so make a copy of sreg2 */
- if (spec [MONO_INST_SRC2] && (ins->dreg == ins->sreg2)) {
+ if (spec [MONO_INST_SRC2] != ' ' && (ins->dreg == ins->sreg2)) {
int new_sreg2 = mono_alloc_preg (cfg);
MonoInst *move;
g_assert (spec [MONO_INST_DEST] != 'f');
prev = move;
ins->sreg2 = new_sreg2;
}
+ g_assert (!(spec [MONO_INST_SRC3] != ' ' && (ins->dreg == ins->sreg3)));
if (spec [MONO_INST_DEST] == 'f')
emit_fp_move (cfg, ins->dreg, ins->sreg1, prev);
else
ins->sreg2 = dest_sreg2;
}
+ if (dest_sreg3 != -1) {
+ emit_move (cfg, dest_sreg3, ins->sreg3, prev);
+ ins->sreg3 = dest_sreg3;
+ }
+
if (dest_dreg != -1) {
emit_move (cfg, ins->dreg, dest_dreg, ins);
g_assert (spec [MONO_INST_CLOB] != '1');
mono_bitset_set_fast (bb->gen_set, sreg);
}
+ /* SREG3 */
+ sreg = ins->sreg3;
+ if (spec [MONO_INST_SRC3] != ' ') {
+ if (!mono_bitset_test_fast (bb->kill_set, sreg))
+ mono_bitset_set_fast (bb->gen_set, sreg);
+ }
+
/* DREG */
if (spec [MONO_INST_DEST] != ' ') {
if (MONO_IS_STORE_MEMBASE (ins)) {
#endif
}
+static MonoLiveInterval*
+get_var_interval (MonoCompile *cfg, MonoRegallocContext *ctx, int idx)
+{
+ MonoLiveInterval *interval = ctx->varinfo [idx].interval;
+ if (interval)
+ return interval;
+ interval = mono_mempool_alloc0 (cfg->mempool, sizeof (MonoLiveInterval));
+ ctx->varinfo [idx].interval = interval;
+ return interval;
+}
+
static inline void
update_liveness (MonoCompile *cfg, MonoRegallocContext *ctx, MonoInst *ins, int inst_num, gint32 *last_use)
{
* Avoid a hole in the liveness range, since the allocation code
* could think the register is free there.
*/
- mono_linterval_add_range (ctx->cfg, ctx->varinfo [ins->dreg].interval, inst_num, last_use [ins->dreg]);
+ mono_linterval_add_range (ctx->cfg, get_var_interval (cfg, ctx, ins->dreg), inst_num, last_use [ins->dreg]);
} else {
- mono_linterval_add_range (ctx->cfg, ctx->varinfo [ins->dreg].interval, inst_num + INS_POS_DEF, last_use [ins->dreg]);
+ mono_linterval_add_range (ctx->cfg, get_var_interval (cfg, ctx, ins->dreg), inst_num + INS_POS_DEF, last_use [ins->dreg]);
}
last_use [ins->dreg] = 0;
}
spec = INS_INFO (ins->opcode);
} else {
LIVENESS_DEBUG (printf ("\tdead def of R%d, add range to R%d: [%x, %x]\n", ins->dreg, ins->dreg, inst_num + INS_POS_DEF, inst_num + INS_POS_DEF));
- mono_linterval_add_range (ctx->cfg, ctx->varinfo [ins->dreg].interval, inst_num + INS_POS_DEF, inst_num + INS_POS_DEF);
+ mono_linterval_add_range (ctx->cfg, get_var_interval (cfg, ctx, ins->dreg), inst_num + INS_POS_DEF, inst_num + INS_POS_DEF);
}
}
}
last_use [sreg] = inst_num + INS_POS_USE;
}
ctx->varinfo [sreg].use_pos = g_slist_prepend_mempool (ctx->cfg->mempool, ctx->varinfo [sreg].use_pos, GINT_TO_POINTER (inst_num));
+
+ /* SREG3 */
+ sreg = ins->sreg3;
+ if (spec [MONO_INST_SRC3] != ' ') {
+ if (last_use [sreg] == 0) {
+ LIVENESS_DEBUG (printf ("\tlast use of R%d set to %x\n", sreg, inst_num + INS_POS_USE));
+ last_use [sreg] = inst_num + INS_POS_USE;
+ }
+ ctx->varinfo [sreg].use_pos = g_slist_prepend_mempool (ctx->cfg->mempool, ctx->varinfo [sreg].use_pos, GINT_TO_POINTER (inst_num));
+
+ /*
+ if (ins->sreg3 <= MONO_MAX_IREGS)
+ mono_linterval_add_range (ctx->cfg, get_var_interval (cfg, ctx, ins->sreg3), inst_num + INS_POS_DEF, inst_num + INS_POS_DEF);
+ */
}
if (ins_get_spec (ins->opcode)[MONO_INST_CLOB] == 'c') {
if (clob == 'c') {
/* A call clobbers some int/fp registers */
for (l = mono_arch_get_iregs_clobbered_by_call ((MonoCallInst*)ins); l; l = l->next)
- mono_linterval_add_range (ctx->cfg, ctx->varinfo [GPOINTER_TO_INT (l->data)].interval, inst_num + INS_POS_CLOB, inst_num + INS_POS_CLOB);
+ mono_linterval_add_range (ctx->cfg, get_var_interval (cfg, ctx, GPOINTER_TO_INT (l->data)), inst_num + INS_POS_CLOB, inst_num + INS_POS_CLOB);
for (l = mono_arch_get_fregs_clobbered_by_call ((MonoCallInst*)ins); l; l = l->next)
- mono_linterval_add_range (ctx->cfg, ctx->varinfo [GPOINTER_TO_INT (l->data)].interval, inst_num + INS_POS_CLOB, inst_num + INS_POS_CLOB);
+ mono_linterval_add_range (ctx->cfg, get_var_interval (cfg, ctx, GPOINTER_TO_INT (l->data)), inst_num + INS_POS_CLOB, inst_num + INS_POS_CLOB);
}
else {
int clob_reg = MONO_ARCH_INST_FIXED_REG (clob);
if (clob_reg != -1)
- mono_linterval_add_range (ctx->cfg, ctx->varinfo [clob_reg].interval, inst_num + INS_POS_CLOB, inst_num + INS_POS_CLOB);
+ mono_linterval_add_range (ctx->cfg, get_var_interval (cfg, ctx, clob_reg), inst_num + INS_POS_CLOB, inst_num + INS_POS_CLOB);
}
}
}
reverse_len = 1024;
reverse = mono_mempool_alloc (cfg->mempool, sizeof (MonoInst*) * reverse_len);
- for (idx = 0; idx < max_vars; ++idx) {
- ctx->varinfo [idx].interval = mono_mempool_alloc0 (cfg->mempool, sizeof (MonoLiveInterval));
- }
-
/*
* Process bblocks in reverse order, so the addition of new live ranges
* to the intervals is faster.
if (last_use [idx] != 0) {
/* Live at exit, not written -> live on enter */
LIVENESS_DEBUG (printf ("Var R%d live at enter, add range to R%d: [%x, %x)\n", idx, idx, block_from, last_use [idx]));
- mono_linterval_add_range (cfg, ctx->varinfo [idx].interval, block_from, last_use [idx]);
+ mono_linterval_add_range (cfg, get_var_interval (cfg, ctx, idx), block_from, last_use [idx]);
}
}
}
for (i = 0; i < cfg->num_varinfo; i ++) {
MonoMethodVar *vi = MONO_VARINFO (cfg, i);
if ((cfg->varinfo [vi->idx]->opcode == OP_ARG) && (cfg->varinfo [vi->idx] != cfg->ret))
- mono_linterval_add_range (cfg, ctx->varinfo [cfg->varinfo [i]->dreg].interval, 0, 1);
+ mono_linterval_add_range (cfg, get_var_interval (cfg, ctx, cfg->varinfo [i]->dreg), 0, 1);
}
#endif
#if 0
for (idx = 0; idx < max_vars; ++idx) {
printf ("LIVENESS R%d: ", idx);
- mono_linterval_print (ctx->varinfo [idx].interval);
+ mono_linterval_print (get_var_interval (cfg, ctx, idx));
printf ("\n");
}
}
LSCAN_DEBUG (printf ("\nLINEAR SCAN 2 for %s:\n", mono_method_full_name (cfg->method, TRUE)));
- header = mono_method_get_header (cfg->method);
+ header = cfg->header;
sig = mono_method_signature (cfg->method);
/* Create list of allocatable variables */
vars = NULL;
for (i = MONO_FIRST_VREG; i < cfg->next_vreg; ++i) {
- if (ctx->varinfo [i].interval->range)
+ if (get_var_interval (cfg, ctx, i)->range)
vars = g_list_prepend (vars, &ctx->varinfo [i]);
}
/* The hard registers are assigned to themselves */
for (i = 0; i < MONO_MAX_IREGS + MONO_MAX_FREGS; ++i) {
ctx->varinfo [i].hreg = i;
- if (ctx->varinfo [i].interval->range)
+ if (get_var_interval (cfg, ctx, i)->range)
inactive = g_list_append (inactive, &ctx->varinfo [i]);
}
ins->sreg2 = l->hreg;
}
+ if (spec [MONO_INST_SRC3] != ' ') {
+ MonoRegallocInterval *l = child_at (&ctx->varinfo [ins->sreg3], pos + INS_POS_USE);
+ g_assert (l->hreg != -1);
+ ins->sreg3 = l->hreg;
+ }
+
if (cfg->verbose_level > 1)
mono_print_ins_index (1, ins);