X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Fmini-codegen.c;h=57c1c9bbccbb78a9b05974fbc0702e141d99216d;hb=eb28197c2ac3141c730eb4d37585ee4f44bcb820;hp=ed26c542677336d309fb091b9adcf6532aa5a7b8;hpb=d14de3c8507d6fce97cbd71b6bbd7aacc060cc38;p=mono.git diff --git a/mono/mini/mini-codegen.c b/mono/mini/mini-codegen.c index ed26c542677..57c1c9bbccb 100644 --- a/mono/mini/mini-codegen.c +++ b/mono/mini/mini-codegen.c @@ -19,7 +19,7 @@ #include "inssel.h" #include "mini-arch.h" -#define DEBUG(a) if (cfg->verbose_level > 1) a +#define DEBUG(a) MINI_DEBUG(cfg->verbose_level, 2, a;) #if defined(__x86_64__) const char * const amd64_desc [OP_LAST]; @@ -27,25 +27,168 @@ static const char*const * ins_spec = amd64_desc; #elif defined(__sparc__) || defined(sparc) const char * const sparc_desc [OP_LAST]; static const char*const * ins_spec = sparc_desc; +#elif defined(__mips__) || defined(mips) +const char * const mips_desc [OP_LAST]; +static const char*const * ins_spec = mips_desc; #elif defined(__i386__) -#ifdef _MSC_VER -extern const char * const pentium_desc [OP_LAST]; -#else -const char * const pentium_desc [OP_LAST]; -#endif -static const char*const * ins_spec = pentium_desc; +extern const char * const x86_desc [OP_LAST]; +static const char*const * ins_spec = x86_desc; #elif defined(__ia64__) const char * const ia64_desc [OP_LAST]; static const char*const * ins_spec = ia64_desc; #elif defined(__arm__) const char * const arm_cpu_desc [OP_LAST]; static const char*const * ins_spec = arm_cpu_desc; +#elif defined(__s390x__) +const char * const s390x_cpu_desc [OP_LAST]; +static const char*const * ins_spec = s390x_cpu_desc; +#elif defined(__s390__) +const char * const s390_cpu_desc [OP_LAST]; +static const char*const * ins_spec = s390_cpu_desc; +#elif defined(__alpha__) +const char * const alpha_desc [OP_LAST]; +static const char*const * ins_spec = alpha_desc; +#elif defined(__ppc__) || defined(__powerpc__) +extern const char * const ppcg4 [OP_LAST]; +static const char*const * ins_spec = ppcg4; #else #error "Not implemented" #endif #define use_fpstack MONO_ARCH_USE_FPSTACK +static inline GSList* +g_slist_append_mempool (MonoMemPool *mp, GSList *list, gpointer data) +{ + GSList *new_list; + GSList *last; + + new_list = mono_mempool_alloc (mp, sizeof (GSList)); + new_list->data = data; + new_list->next = NULL; + + if (list) { + last = list; + while (last->next) + last = last->next; + last->next = new_list; + + return list; + } else + return new_list; +} + +/** + * Duplicated here from regalloc.c so they can be inlined + * FIXME: Remove the old one after the new JIT is done + */ + +static inline void +mono_regstate2_reset (MonoRegState *rs) { + rs->next_vireg = MONO_MAX_IREGS; + rs->next_vfreg = MONO_MAX_FREGS; +} + +static inline MonoRegState* +mono_regstate2_new (void) +{ + MonoRegState* rs = g_new0 (MonoRegState, 1); + + mono_regstate2_reset (rs); + + return rs; +} + +static inline void +mono_regstate2_free (MonoRegState *rs) { + g_free (rs->iassign); + if (rs->iassign != rs->fassign) + g_free (rs->fassign); + g_free (rs); +} + +static inline void +mono_regstate2_assign (MonoRegState *rs) { + rs->max_ireg = -1; + + if (rs->next_vireg > rs->iassign_size) { + g_free (rs->iassign); + rs->iassign_size = MAX (rs->next_vireg, 256); + rs->iassign = g_malloc (rs->iassign_size * sizeof (int)); + } + + memset (rs->isymbolic, 0, MONO_MAX_IREGS * sizeof (rs->isymbolic [0])); + memset (rs->iassign, -1, sizeof (rs->iassign [0]) * rs->next_vireg); + + if (rs->next_vfreg > rs->fassign_size) { + g_free (rs->fassign); + rs->fassign = g_malloc (MAX (MONO_MAX_FREGS, rs->next_vfreg) * sizeof (int)); + rs->fassign_size = rs->next_vfreg; + } + + if (rs->next_vfreg > MONO_MAX_FREGS) { + memset (rs->fsymbolic, 0, MONO_MAX_IREGS * sizeof (rs->fsymbolic [0])); + memset (rs->fassign, -1, sizeof (rs->fassign [0]) * rs->next_vfreg); + } +} + +static inline int +mono_regstate2_alloc_int (MonoRegState *rs, regmask_t allow) +{ + int i; + regmask_t mask = allow & rs->ifree_mask; + for (i = 0; i < MONO_MAX_IREGS; ++i) { + if (mask & ((regmask_t)1 << i)) { + rs->ifree_mask &= ~ ((regmask_t)1 << i); + rs->max_ireg = MAX (rs->max_ireg, i); + return i; + } + } + return -1; +} + +static inline void +mono_regstate2_free_int (MonoRegState *rs, int reg) +{ + if (reg >= 0) { + rs->ifree_mask |= (regmask_t)1 << reg; + rs->isymbolic [reg] = 0; + } +} + +static inline int +mono_regstate2_alloc_float (MonoRegState *rs, regmask_t allow) +{ + int i; + regmask_t mask = allow & rs->ffree_mask; + for (i = 0; i < MONO_MAX_FREGS; ++i) { + if (mask & ((regmask_t)1 << i)) { + rs->ffree_mask &= ~ ((regmask_t)1 << i); + return i; + } + } + return -1; +} + +static inline void +mono_regstate2_free_float (MonoRegState *rs, int reg) +{ + if (reg >= 0) { + rs->ffree_mask |= (regmask_t)1 << reg; + rs->fsymbolic [reg] = 0; + } +} + +static inline int +mono_regstate2_next_long (MonoRegState *rs) +{ + int rval = rs->next_vireg; + + rs->next_vireg += 2; + + return rval; +} + const char* mono_regname_full (int reg, gboolean fp) { @@ -56,93 +199,117 @@ mono_regname_full (int reg, gboolean fp) } void -mono_call_inst_add_outarg_reg (MonoCallInst *call, int vreg, int hreg, gboolean fp) +mono_call_inst_add_outarg_reg (MonoCompile *cfg, MonoCallInst *call, int vreg, int hreg, gboolean fp) { guint32 regpair; regpair = (((guint32)hreg) << 24) + vreg; - if (fp) - call->out_freg_args = g_slist_append (call->out_freg_args, (gpointer)(gssize)(regpair)); - else - call->out_ireg_args = g_slist_append (call->out_ireg_args, (gpointer)(gssize)(regpair)); + if (fp) { + g_assert (vreg >= MONO_MAX_FREGS); + g_assert (hreg < MONO_MAX_FREGS); + call->used_fregs |= 1 << hreg; + call->out_freg_args = g_slist_append_mempool (cfg->mempool, call->out_freg_args, (gpointer)(gssize)(regpair)); + } else { + g_assert (vreg >= MONO_MAX_IREGS); + g_assert (hreg < MONO_MAX_IREGS); + call->used_iregs |= 1 << hreg; + call->out_ireg_args = g_slist_append_mempool (cfg->mempool, call->out_ireg_args, (gpointer)(gssize)(regpair)); + } +} + +static void +resize_spill_info (MonoCompile *cfg, gboolean fp) +{ + MonoSpillInfo *orig_info = fp ? cfg->spill_info_float : cfg->spill_info; + int orig_len = fp ? cfg->spill_info_float_len : cfg->spill_info_len; + int new_len = orig_len ? orig_len * 2 : 16; + MonoSpillInfo *new_info; + int i; + + new_info = mono_mempool_alloc (cfg->mempool, sizeof (MonoSpillInfo) * new_len); + if (orig_info) + memcpy (new_info, orig_info, sizeof (MonoSpillInfo) * orig_len); + for (i = orig_len; i < new_len; ++i) + new_info [i].offset = -1; + + if (!fp) { + cfg->spill_info = new_info; + cfg->spill_info_len = new_len; + } else { + cfg->spill_info_float = new_info; + cfg->spill_info_float_len = new_len; + } } /* * returns the offset used by spillvar. It allocates a new * spill variable if necessary. */ -static int +static inline int mono_spillvar_offset (MonoCompile *cfg, int spillvar) { - MonoSpillInfo **si, *info; - int i = 0; + MonoSpillInfo *info; - si = &cfg->spill_info; - - while (i <= spillvar) { - - if (!*si) { - *si = info = mono_mempool_alloc (cfg->mempool, sizeof (MonoSpillInfo)); - info->next = NULL; - if (cfg->flags & MONO_CFG_HAS_SPILLUP) { - info->offset = cfg->stack_offset; - cfg->stack_offset += sizeof (gpointer); - } else { - cfg->stack_offset += sizeof (gpointer); - info->offset = - cfg->stack_offset; - } - } +#if defined (__mips__) + g_assert_not_reached(); +#endif + if (G_UNLIKELY (spillvar >= cfg->spill_info_len)) { + resize_spill_info (cfg, FALSE); + g_assert (spillvar < cfg->spill_info_len); + } - if (i == spillvar) - return (*si)->offset; + info = &cfg->spill_info [spillvar]; + if (info->offset == -1) { + cfg->stack_offset += sizeof (gpointer) - 1; + cfg->stack_offset &= ~(sizeof (gpointer) - 1); - i++; - si = &(*si)->next; + if (cfg->flags & MONO_CFG_HAS_SPILLUP) { + info->offset = cfg->stack_offset; + cfg->stack_offset += sizeof (gpointer); + } else { + cfg->stack_offset += sizeof (gpointer); + info->offset = - cfg->stack_offset; + } } - g_assert_not_reached (); - return 0; + return info->offset; } +#if MONO_ARCH_USE_FPSTACK + /* * returns the offset used by spillvar. It allocates a new * spill float variable if necessary. * (same as mono_spillvar_offset but for float) */ -static int +static inline int mono_spillvar_offset_float (MonoCompile *cfg, int spillvar) { - MonoSpillInfo **si, *info; - int i = 0; + MonoSpillInfo *info; - si = &cfg->spill_info_float; - - while (i <= spillvar) { - - if (!*si) { - *si = info = mono_mempool_alloc (cfg->mempool, sizeof (MonoSpillInfo)); - info->next = NULL; - if (cfg->flags & MONO_CFG_HAS_SPILLUP) { - cfg->stack_offset += 7; - cfg->stack_offset &= ~7; - info->offset = cfg->stack_offset; - cfg->stack_offset += sizeof (double); - } else { - /* FIXME: align */ - cfg->stack_offset += sizeof (double); - info->offset = - cfg->stack_offset; - } - } +#if defined (__mips__) + g_assert_not_reached(); +#endif + if (G_UNLIKELY (spillvar >= cfg->spill_info_float_len)) { + resize_spill_info (cfg, TRUE); + g_assert (spillvar < cfg->spill_info_float_len); + } - if (i == spillvar) - return (*si)->offset; + info = &cfg->spill_info_float [spillvar]; + if (info->offset == -1) { + cfg->stack_offset += sizeof (double) - 1; + cfg->stack_offset &= ~(sizeof (double) - 1); - i++; - si = &(*si)->next; + if (cfg->flags & MONO_CFG_HAS_SPILLUP) { + info->offset = cfg->stack_offset; + cfg->stack_offset += sizeof (double); + } else { + cfg->stack_offset += sizeof (double); + info->offset = - cfg->stack_offset; + } } - g_assert_not_reached (); - return 0; + return info->offset; } /* @@ -157,7 +324,7 @@ create_spilled_store_float (MonoCompile *cfg, int spill, int reg, MonoInst *ins) store->inst_destbasereg = cfg->frame_reg; store->inst_offset = mono_spillvar_offset_float (cfg, spill); - DEBUG (g_print ("SPILLED FLOAT STORE (%d at 0x%08lx(%%sp)) (from %d)\n", spill, (long)store->inst_offset, reg)); + DEBUG (printf ("SPILLED FLOAT STORE (%d at 0x%08lx(%%sp)) (from %d)\n", spill, (long)store->inst_offset, reg)); return store; } @@ -173,16 +340,20 @@ create_spilled_load_float (MonoCompile *cfg, int spill, int reg, MonoInst *ins) load->inst_basereg = cfg->frame_reg; load->inst_offset = mono_spillvar_offset_float (cfg, spill); - DEBUG (g_print ("SPILLED FLOAT LOAD (%d at 0x%08lx(%%sp)) (from %d)\n", spill, (long)load->inst_offset, reg)); + DEBUG (printf ("SPILLED FLOAT LOAD (%d at 0x%08lx(%%sp)) (from %d)\n", spill, (long)load->inst_offset, reg)); return load; } +#endif /* MONO_ARCH_USE_FPSTACK */ + +#define regmask(reg) (((regmask_t)1) << (reg)) + #define is_hard_ireg(r) ((r) >= 0 && (r) < MONO_MAX_IREGS) #define is_hard_freg(r) ((r) >= 0 && (r) < MONO_MAX_FREGS) -#define is_global_ireg(r) (is_hard_ireg ((r)) && (MONO_ARCH_CALLEE_SAVED_REGS & (1 << (r)))) -#define is_local_ireg(r) (is_hard_ireg ((r)) && (MONO_ARCH_CALLEE_REGS & (1 << (r)))) -#define is_global_freg(r) (is_hard_freg ((r)) && (MONO_ARCH_CALLEE_SAVED_FREGS & (1 << (r)))) -#define is_local_freg(r) (is_hard_ireg ((r)) && (MONO_ARCH_CALLEE_FREGS & (1 << (r)))) +#define is_global_ireg(r) (is_hard_ireg ((r)) && (MONO_ARCH_CALLEE_SAVED_REGS & (regmask (r)))) +#define is_local_ireg(r) (is_hard_ireg ((r)) && (MONO_ARCH_CALLEE_REGS & (regmask (r)))) +#define is_global_freg(r) (is_hard_freg ((r)) && (MONO_ARCH_CALLEE_SAVED_FREGS & (regmask (r)))) +#define is_local_freg(r) (is_hard_ireg ((r)) && (MONO_ARCH_CALLEE_FREGS & (regmask (r)))) #define ireg_is_freeable(r) is_local_ireg ((r)) #define freg_is_freeable(r) is_hard_freg ((r)) @@ -190,65 +361,87 @@ create_spilled_load_float (MonoCompile *cfg, int spill, int reg, MonoInst *ins) #define is_hard_reg(r,fp) ((fp) ? ((r) < MONO_MAX_FREGS) : ((r) < MONO_MAX_IREGS)) #define is_soft_reg(r,fp) (!is_hard_reg((r),(fp))) #define rassign(cfg,reg,fp) ((fp) ? (cfg)->rs->fassign [(reg)] : (cfg)->rs->iassign [(reg)]) -#define sreg1_is_fp(ins) (ins_spec [(ins)->opcode] [MONO_INST_SRC1] == 'f') -#define sreg2_is_fp(ins) (ins_spec [(ins)->opcode] [MONO_INST_SRC2] == 'f') #ifdef MONO_ARCH_INST_IS_FLOAT -#define dreg_is_fp(ins) (MONO_ARCH_INST_IS_FLOAT (ins_spec [(ins)->opcode] [MONO_INST_DEST])) +#define dreg_is_fp(spec) (MONO_ARCH_INST_IS_FLOAT (spec [MONO_INST_DEST])) +#define sreg1_is_fp(spec) (MONO_ARCH_INST_IS_FLOAT (spec [MONO_INST_SRC1])) +#define sreg2_is_fp(spec) (MONO_ARCH_INST_IS_FLOAT (spec [MONO_INST_SRC2])) #else -#define dreg_is_fp(ins) (ins_spec [(ins)->opcode] [MONO_INST_DEST] == 'f') +#define sreg1_is_fp(spec) (spec [MONO_INST_SRC1] == 'f') +#define sreg2_is_fp(spec) (spec [MONO_INST_SRC2] == 'f') +#define dreg_is_fp(spec) (spec [MONO_INST_DEST] == 'f') #endif -#define regpair_reg2_mask(desc,hreg1) ((MONO_ARCH_INST_REGPAIR_REG2 (desc,hreg1) != -1) ? (1 << MONO_ARCH_INST_REGPAIR_REG2 (desc,hreg1)) : MONO_ARCH_CALLEE_REGS) +#define sreg1_is_fp_ins(ins) (sreg1_is_fp (ins_spec [(ins)->opcode])) +#define sreg2_is_fp_ins(ins) (sreg2_is_fp (ins_spec [(ins)->opcode])) +#define dreg_is_fp_ins(ins) (dreg_is_fp (ins_spec [(ins)->opcode])) + +#define regpair_reg2_mask(desc,hreg1) ((MONO_ARCH_INST_REGPAIR_REG2 (desc,hreg1) != -1) ? (regmask (MONO_ARCH_INST_REGPAIR_REG2 (desc,hreg1))) : MONO_ARCH_CALLEE_REGS) + +#ifdef MONO_ARCH_IS_GLOBAL_IREG +#undef is_global_ireg +#define is_global_ireg(reg) MONO_ARCH_IS_GLOBAL_IREG ((reg)) +#endif typedef struct { int born_in; int killed_in; - int last_use; - int prev_use; + /* Not (yet) used */ + //int last_use; + //int prev_use; +#if MONO_ARCH_USE_FPSTACK int flags; /* used to track fp spill/load */ - guint32 preferred_mask; /* the hreg where the register should be allocated, or 0 */ +#endif + regmask_t preferred_mask; /* the hreg where the register should be allocated, or 0 */ } RegTrack; -static void -print_ins (int i, MonoInst *ins) +#ifndef DISABLE_LOGGING +void +mono_print_ins (int i, MonoInst *ins) { const char *spec = ins_spec [ins->opcode]; - g_print ("\t%-2d %s", i, mono_inst_name (ins->opcode)); + printf ("\t%-2d %s", i, mono_inst_name (ins->opcode)); if (!spec) g_error ("Unknown opcode: %s\n", mono_inst_name (ins->opcode)); if (spec [MONO_INST_DEST]) { - gboolean fp = dreg_is_fp (ins); - if (is_soft_reg (ins->dreg, fp)) - g_print (" R%d <-", ins->dreg); - else if (spec [MONO_INST_DEST] == 'b') { + gboolean fp = dreg_is_fp_ins (ins); + if (is_soft_reg (ins->dreg, fp)) { + if (spec [MONO_INST_DEST] == 'b') { + if (ins->inst_offset == 0) + printf (" [R%d] <-", ins->dreg); + else + printf (" [R%d + 0x%lx] <-", ins->dreg, (long)ins->inst_offset); + } + else + printf (" R%d <-", ins->dreg); + } else if (spec [MONO_INST_DEST] == 'b') { if (ins->inst_offset == 0) - g_print (" [%s] <-", mono_arch_regname (ins->dreg)); + printf (" [%s] <-", mono_arch_regname (ins->dreg)); else - g_print (" [%s + 0x%lx] <-", mono_arch_regname (ins->dreg), (long)ins->inst_offset); + printf (" [%s + 0x%lx] <-", mono_arch_regname (ins->dreg), (long)ins->inst_offset); } else - g_print (" %s <-", mono_regname_full (ins->dreg, fp)); + printf (" %s <-", mono_regname_full (ins->dreg, fp)); } if (spec [MONO_INST_SRC1]) { gboolean fp = (spec [MONO_INST_SRC1] == 'f'); if (is_soft_reg (ins->sreg1, fp)) - g_print (" R%d", ins->sreg1); + printf (" R%d", ins->sreg1); else if (spec [MONO_INST_SRC1] == 'b') - g_print (" [%s + 0x%lx]", mono_arch_regname (ins->sreg1), (long)ins->inst_offset); + printf (" [%s + 0x%lx]", mono_arch_regname (ins->sreg1), (long)ins->inst_offset); else - g_print (" %s", mono_regname_full (ins->sreg1, fp)); + printf (" %s", mono_regname_full (ins->sreg1, fp)); } if (spec [MONO_INST_SRC2]) { gboolean fp = (spec [MONO_INST_SRC2] == 'f'); if (is_soft_reg (ins->sreg2, fp)) - g_print (" R%d", ins->sreg2); + printf (" R%d", ins->sreg2); else - g_print (" %s", mono_regname_full (ins->sreg2, fp)); + printf (" %s", mono_regname_full (ins->sreg2, fp)); } if (spec [MONO_INST_CLOB]) - g_print (" clobbers: %c", spec [MONO_INST_CLOB]); - g_print ("\n"); + printf (" clobbers: %c", spec [MONO_INST_CLOB]); + printf ("\n"); } static void @@ -266,9 +459,10 @@ print_regtrack (RegTrack *t, int num) r = buf; } else r = mono_arch_regname (i); - g_print ("liveness: %s [%d - %d]\n", r, t [i].born_in, t[i].last_use); + printf ("liveness: %s [%d - %d]\n", r, t [i].born_in, t[i].killed_in); } } +#endif /* DISABLE_LOGGING */ typedef struct InstList InstList; @@ -279,9 +473,9 @@ struct InstList { }; static inline InstList* -inst_list_prepend (MonoMemPool *pool, InstList *list, MonoInst *data) +inst_list_prepend (guint8 *mem, InstList *list, MonoInst *data) { - InstList *item = mono_mempool_alloc (pool, sizeof (InstList)); + InstList *item = (InstList*)mem; item->data = data; item->prev = NULL; item->next = list; @@ -290,6 +484,46 @@ inst_list_prepend (MonoMemPool *pool, InstList *list, MonoInst *data) return item; } +static inline void +insert_before_ins (MonoInst *ins, InstList *item, MonoInst* to_insert) +{ + MonoInst *prev; + + /* + * If this function is called multiple times, the new instructions are inserted + * in the proper order. + */ + + if (item->next) { + prev = item->next->data; + + while (prev->next != ins) + prev = prev->next; + to_insert->next = ins; + prev->next = to_insert; + } else { + to_insert->next = ins; + } + + /* + * insert_after_ins insert the new instruction before item->data, so + * we have to modify it to point to the first of the prepended instructions. + */ + if (item->data == ins) + item->data = to_insert; +} + +static inline void +insert_after_ins (MonoInst *ins, InstList *item, MonoInst* to_insert) +{ + if (item->prev) { + while (ins->next != item->prev->data) + ins = ins->next; + } + to_insert->next = ins->next; + ins->next = to_insert; +} + /* * Force the spilling of the variable in the symbolic register 'reg'. */ @@ -316,9 +550,9 @@ get_register_force_spilling (MonoCompile *cfg, InstList *item, MonoInst *ins, in spill = ++cfg->spill_count; assign [i] = -spill - 1; if (fp) - mono_regstate_free_float (cfg->rs, sel); + mono_regstate2_free_float (cfg->rs, sel); else - mono_regstate_free_int (cfg->rs, sel); + mono_regstate2_free_int (cfg->rs, sel); /* we need to create a spill var and insert a load to sel after the current instruction */ if (fp) MONO_INST_NEW (cfg, load, OP_LOADR8_MEMBASE); @@ -327,24 +561,24 @@ get_register_force_spilling (MonoCompile *cfg, InstList *item, MonoInst *ins, in load->dreg = sel; load->inst_basereg = cfg->frame_reg; load->inst_offset = mono_spillvar_offset (cfg, spill); - if (item->prev) { - while (ins->next != item->prev->data) - ins = ins->next; - } - load->next = ins->next; - ins->next = load; - DEBUG (g_print ("SPILLED LOAD (%d at 0x%08lx(%%ebp)) R%d (freed %s)\n", spill, (long)load->inst_offset, i, mono_regname_full (sel, fp))); + insert_after_ins (ins, item, load); + DEBUG (printf ("SPILLED LOAD (%d at 0x%08lx(%%ebp)) R%d (freed %s)\n", spill, (long)load->inst_offset, i, mono_regname_full (sel, fp))); if (fp) - i = mono_regstate_alloc_float (cfg->rs, 1 << sel); + i = mono_regstate2_alloc_float (cfg->rs, regmask (sel)); else - i = mono_regstate_alloc_int (cfg->rs, 1 << sel); + i = mono_regstate2_alloc_int (cfg->rs, regmask (sel)); g_assert (i == sel); return sel; } +/* This isn't defined on older glib versions and on some platforms */ +#ifndef G_GUINT64_FORMAT +#define G_GUINT64_FORMAT "ul" +#endif + static int -get_register_spilling (MonoCompile *cfg, InstList *item, MonoInst *ins, guint32 regmask, int reg, gboolean fp) +get_register_spilling (MonoCompile *cfg, InstList *item, MonoInst *ins, regmask_t regmask, int reg, gboolean fp) { MonoInst *load; int i, sel, spill; @@ -359,36 +593,36 @@ get_register_spilling (MonoCompile *cfg, InstList *item, MonoInst *ins, guint32 symbolic = cfg->rs->isymbolic; } - DEBUG (g_print ("\tstart regmask to assign R%d: 0x%08x (R%d <- R%d R%d)\n", reg, regmask, ins->dreg, ins->sreg1, ins->sreg2)); + DEBUG (printf ("\tstart regmask to assign R%d: 0x%08" G_GUINT64_FORMAT " (R%d <- R%d R%d)\n", reg, (guint64)regmask, ins->dreg, ins->sreg1, ins->sreg2)); /* exclude the registers in the current instruction */ - if ((sreg1_is_fp (ins) == fp) && (reg != ins->sreg1) && (reg_is_freeable (ins->sreg1, fp) || (is_soft_reg (ins->sreg1, fp) && rassign (cfg, ins->sreg1, fp) >= 0))) { + if ((sreg1_is_fp_ins (ins) == fp) && (reg != ins->sreg1) && (reg_is_freeable (ins->sreg1, fp) || (is_soft_reg (ins->sreg1, fp) && rassign (cfg, ins->sreg1, fp) >= 0))) { if (is_soft_reg (ins->sreg1, fp)) - regmask &= ~ (1 << rassign (cfg, ins->sreg1, fp)); + regmask &= ~ (regmask (rassign (cfg, ins->sreg1, fp))); else - regmask &= ~ (1 << ins->sreg1); - DEBUG (g_print ("\t\texcluding sreg1 %s\n", mono_regname_full (ins->sreg1, fp))); + regmask &= ~ (regmask (ins->sreg1)); + DEBUG (printf ("\t\texcluding sreg1 %s\n", mono_regname_full (ins->sreg1, fp))); } - if ((sreg2_is_fp (ins) == fp) && (reg != ins->sreg2) && (reg_is_freeable (ins->sreg2, fp) || (is_soft_reg (ins->sreg2, fp) && rassign (cfg, ins->sreg2, fp) >= 0))) { + if ((sreg2_is_fp_ins (ins) == fp) && (reg != ins->sreg2) && (reg_is_freeable (ins->sreg2, fp) || (is_soft_reg (ins->sreg2, fp) && rassign (cfg, ins->sreg2, fp) >= 0))) { if (is_soft_reg (ins->sreg2, fp)) - regmask &= ~ (1 << rassign (cfg, ins->sreg2, fp)); + regmask &= ~ (regmask (rassign (cfg, ins->sreg2, fp))); else - regmask &= ~ (1 << ins->sreg2); - DEBUG (g_print ("\t\texcluding sreg2 %s %d\n", mono_regname_full (ins->sreg2, fp), ins->sreg2)); + regmask &= ~ (regmask (ins->sreg2)); + DEBUG (printf ("\t\texcluding sreg2 %s %d\n", mono_regname_full (ins->sreg2, fp), ins->sreg2)); } - if ((dreg_is_fp (ins) == fp) && (reg != ins->dreg) && reg_is_freeable (ins->dreg, fp)) { - regmask &= ~ (1 << ins->dreg); - DEBUG (g_print ("\t\texcluding dreg %s\n", mono_regname_full (ins->dreg, fp))); + if ((dreg_is_fp_ins (ins) == fp) && (reg != ins->dreg) && reg_is_freeable (ins->dreg, fp)) { + regmask &= ~ (regmask (ins->dreg)); + DEBUG (printf ("\t\texcluding dreg %s\n", mono_regname_full (ins->dreg, fp))); } - DEBUG (g_print ("\t\tavailable regmask: 0x%08x\n", regmask)); + DEBUG (printf ("\t\tavailable regmask: 0x%08" G_GUINT64_FORMAT "\n", (guint64)regmask)); g_assert (regmask); /* need at least a register we can free */ sel = -1; /* we should track prev_use and spill the register that's farther */ if (fp) { for (i = 0; i < MONO_MAX_FREGS; ++i) { - if (regmask & (1 << i)) { + if (regmask & (regmask (i))) { sel = i; - DEBUG (g_print ("\t\tselected register %s has assignment %d\n", mono_arch_fregname (sel), cfg->rs->fsymbolic [sel])); + DEBUG (printf ("\t\tselected register %s has assignment %d\n", mono_arch_fregname (sel), cfg->rs->fsymbolic [sel])); break; } } @@ -396,13 +630,13 @@ get_register_spilling (MonoCompile *cfg, InstList *item, MonoInst *ins, guint32 i = cfg->rs->fsymbolic [sel]; spill = ++cfg->spill_count; cfg->rs->fassign [i] = -spill - 1; - mono_regstate_free_float (cfg->rs, sel); + mono_regstate2_free_float (cfg->rs, sel); } else { for (i = 0; i < MONO_MAX_IREGS; ++i) { - if (regmask & (1 << i)) { + if (regmask & (regmask (i))) { sel = i; - DEBUG (g_print ("\t\tselected register %s has assignment %d\n", mono_arch_regname (sel), cfg->rs->isymbolic [sel])); + DEBUG (printf ("\t\tselected register %s has assignment %d\n", mono_arch_regname (sel), cfg->rs->isymbolic [sel])); break; } } @@ -410,7 +644,7 @@ get_register_spilling (MonoCompile *cfg, InstList *item, MonoInst *ins, guint32 i = cfg->rs->isymbolic [sel]; spill = ++cfg->spill_count; cfg->rs->iassign [i] = -spill - 1; - mono_regstate_free_int (cfg->rs, sel); + mono_regstate2_free_int (cfg->rs, sel); } /* we need to create a spill var and insert a load to sel after the current instruction */ @@ -418,17 +652,12 @@ get_register_spilling (MonoCompile *cfg, InstList *item, MonoInst *ins, guint32 load->dreg = sel; load->inst_basereg = cfg->frame_reg; load->inst_offset = mono_spillvar_offset (cfg, spill); - if (item->prev) { - while (ins->next != item->prev->data) - ins = ins->next; - } - load->next = ins->next; - ins->next = load; - DEBUG (g_print ("\tSPILLED LOAD (%d at 0x%08lx(%%ebp)) R%d (freed %s)\n", spill, (long)load->inst_offset, i, mono_regname_full (sel, fp))); + insert_after_ins (ins, item, load); + DEBUG (printf ("\tSPILLED LOAD (%d at 0x%08lx(%%ebp)) R%d (freed %s)\n", spill, (long)load->inst_offset, i, mono_regname_full (sel, fp))); if (fp) - i = mono_regstate_alloc_float (cfg->rs, 1 << sel); + i = mono_regstate2_alloc_float (cfg->rs, regmask (sel)); else - i = mono_regstate_alloc_int (cfg->rs, 1 << sel); + i = mono_regstate2_alloc_int (cfg->rs, regmask (sel)); g_assert (i == sel); return sel; @@ -437,10 +666,10 @@ get_register_spilling (MonoCompile *cfg, InstList *item, MonoInst *ins, guint32 static void free_up_ireg (MonoCompile *cfg, InstList *item, MonoInst *ins, int hreg) { - if (!(cfg->rs->ifree_mask & (1 << hreg))) { - DEBUG (g_print ("\tforced spill of R%d\n", cfg->rs->isymbolic [hreg])); + if (!(cfg->rs->ifree_mask & (regmask (hreg)))) { + DEBUG (printf ("\tforced spill of R%d\n", cfg->rs->isymbolic [hreg])); get_register_force_spilling (cfg, item, ins, cfg->rs->isymbolic [hreg], FALSE); - mono_regstate_free_int (cfg->rs, hreg); + mono_regstate2_free_int (cfg->rs, hreg); } } @@ -448,17 +677,17 @@ static void free_up_reg (MonoCompile *cfg, InstList *item, MonoInst *ins, int hreg, gboolean fp) { if (fp) { - if (!(cfg->rs->ffree_mask & (1 << hreg))) { - DEBUG (g_print ("\tforced spill of R%d\n", cfg->rs->isymbolic [hreg])); + if (!(cfg->rs->ffree_mask & (regmask (hreg)))) { + DEBUG (printf ("\tforced spill of R%d\n", cfg->rs->isymbolic [hreg])); get_register_force_spilling (cfg, item, ins, cfg->rs->isymbolic [hreg], fp); - mono_regstate_free_float (cfg->rs, hreg); + mono_regstate2_free_float (cfg->rs, hreg); } } else { - if (!(cfg->rs->ifree_mask & (1 << hreg))) { - DEBUG (g_print ("\tforced spill of R%d\n", cfg->rs->isymbolic [hreg])); + if (!(cfg->rs->ifree_mask & (regmask (hreg)))) { + DEBUG (printf ("\tforced spill of R%d\n", cfg->rs->isymbolic [hreg])); get_register_force_spilling (cfg, item, ins, cfg->rs->isymbolic [hreg], fp); - mono_regstate_free_int (cfg->rs, hreg); + mono_regstate2_free_int (cfg->rs, hreg); } } } @@ -481,7 +710,7 @@ create_copy_ins (MonoCompile *cfg, int dest, int src, MonoInst *ins, const unsig copy->cil_code = ins->cil_code; ins->next = copy; } - DEBUG (g_print ("\tforced copy from %s to %s\n", mono_regname_full (src, fp), mono_regname_full (dest, fp))); + DEBUG (printf ("\tforced copy from %s to %s\n", mono_regname_full (src, fp), mono_regname_full (dest, fp))); return copy; } @@ -497,64 +726,43 @@ create_spilled_store (MonoCompile *cfg, int spill, int reg, int prev_reg, MonoIn store->next = ins->next; ins->next = store; } - DEBUG (g_print ("\tSPILLED STORE (%d at 0x%08lx(%%ebp)) R%d (from %s)\n", spill, (long)store->inst_offset, prev_reg, mono_regname_full (reg, fp))); + DEBUG (printf ("\tSPILLED STORE (%d at 0x%08lx(%%ebp)) R%d (from %s)\n", spill, (long)store->inst_offset, prev_reg, mono_regname_full (reg, fp))); return store; } -static void -insert_before_ins (MonoInst *ins, InstList *item, MonoInst* to_insert) -{ - MonoInst *prev; - if (item->next) { - prev = item->next->data; - - while (prev->next != ins) - prev = prev->next; - to_insert->next = ins; - prev->next = to_insert; - } else { - to_insert->next = ins; - } - /* - * needed otherwise in the next instruction we can add an ins to the - * end and that would get past this instruction. - */ - item->data = to_insert; -} - /* flags used in reginfo->flags */ enum { - MONO_FP_NEEDS_LOAD_SPILL = 1 << 0, - MONO_FP_NEEDS_SPILL = 1 << 1, - MONO_FP_NEEDS_LOAD = 1 << 2 + MONO_FP_NEEDS_LOAD_SPILL = regmask (0), + MONO_FP_NEEDS_SPILL = regmask (1), + MONO_FP_NEEDS_LOAD = regmask (2) }; -static int -alloc_int_reg (MonoCompile *cfg, InstList *tmp, MonoInst *ins, guint32 dest_mask, int sym_reg, RegTrack *info) +static inline int +alloc_int_reg (MonoCompile *cfg, InstList *tmp, MonoInst *ins, regmask_t dest_mask, int sym_reg, RegTrack *info) { int val; if (info && info->preferred_mask) { - val = mono_regstate_alloc_int (cfg->rs, info->preferred_mask & dest_mask); + val = mono_regstate2_alloc_int (cfg->rs, info->preferred_mask & dest_mask); if (val >= 0) { - DEBUG (g_print ("\tallocated preferred reg R%d to %s\n", sym_reg, mono_arch_regname (val))); + DEBUG (printf ("\tallocated preferred reg R%d to %s\n", sym_reg, mono_arch_regname (val))); return val; } } - val = mono_regstate_alloc_int (cfg->rs, dest_mask); + val = mono_regstate2_alloc_int (cfg->rs, dest_mask); if (val < 0) val = get_register_spilling (cfg, tmp, ins, dest_mask, sym_reg, FALSE); return val; } -static int -alloc_float_reg (MonoCompile *cfg, InstList *tmp, MonoInst *ins, guint32 dest_mask, int sym_reg) +static inline int +alloc_float_reg (MonoCompile *cfg, InstList *tmp, MonoInst *ins, regmask_t dest_mask, int sym_reg) { int val; - val = mono_regstate_alloc_float (cfg->rs, dest_mask); + val = mono_regstate2_alloc_float (cfg->rs, dest_mask); if (val < 0) { val = get_register_spilling (cfg, tmp, ins, dest_mask, sym_reg, TRUE); @@ -563,8 +771,8 @@ alloc_float_reg (MonoCompile *cfg, InstList *tmp, MonoInst *ins, guint32 dest_ma return val; } -static int -alloc_reg (MonoCompile *cfg, InstList *tmp, MonoInst *ins, guint32 dest_mask, int sym_reg, RegTrack *info, gboolean fp) +static inline int +alloc_reg (MonoCompile *cfg, InstList *tmp, MonoInst *ins, regmask_t dest_mask, int sym_reg, RegTrack *info, gboolean fp) { if (fp) return alloc_float_reg (cfg, tmp, ins, dest_mask, sym_reg); @@ -573,7 +781,7 @@ alloc_reg (MonoCompile *cfg, InstList *tmp, MonoInst *ins, guint32 dest_mask, in } static inline void -assign_reg (MonoRegState *rs, int reg, int hreg, gboolean fp) +assign_reg (MonoCompile *cfg, MonoRegState *rs, int reg, int hreg, gboolean fp) { if (fp) { g_assert (reg >= MONO_MAX_FREGS); @@ -582,7 +790,7 @@ assign_reg (MonoRegState *rs, int reg, int hreg, gboolean fp) rs->fassign [reg] = hreg; rs->fsymbolic [hreg] = reg; - rs->ffree_mask &= ~ (1 << hreg); + rs->ffree_mask &= ~ (regmask (hreg)); } else { g_assert (reg >= MONO_MAX_IREGS); @@ -591,14 +799,14 @@ assign_reg (MonoRegState *rs, int reg, int hreg, gboolean fp) rs->iassign [reg] = hreg; rs->isymbolic [hreg] = reg; - rs->ifree_mask &= ~ (1 << hreg); + rs->ifree_mask &= ~ (regmask (hreg)); } } static inline void -assign_ireg (MonoRegState *rs, int reg, int hreg) +assign_ireg (MonoCompile *cfg, MonoRegState *rs, int reg, int hreg) { - assign_reg (rs, reg, hreg, FALSE); + assign_reg (cfg, rs, reg, hreg, FALSE); } /* @@ -613,7 +821,7 @@ mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb) { MonoInst *ins; MonoRegState *rs = cfg->rs; - int i, val, fpcount; + int i, val, fpcount, ins_count; RegTrack *reginfo, *reginfof; RegTrack *reginfo1, *reginfo2, *reginfod; InstList *tmp, *reversed = NULL; @@ -621,43 +829,90 @@ mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb) GList *fspill_list = NULL; gboolean fp; int fspill = 0; + guint8 *inst_list, *mem; +#if MONO_ARCH_USE_FPSTACK + gboolean need_fpstack = (use_fpstack && bb->max_freg > MONO_MAX_FREGS); +#endif if (!bb->code) return; rs->next_vireg = bb->max_ireg; rs->next_vfreg = bb->max_freg; - mono_regstate_assign (rs); - reginfo = g_malloc0 (sizeof (RegTrack) * rs->next_vireg); - reginfof = g_malloc0 (sizeof (RegTrack) * rs->next_vfreg); + mono_regstate2_assign (rs); + rs->ifree_mask = MONO_ARCH_CALLEE_REGS; rs->ffree_mask = MONO_ARCH_CALLEE_FREGS; if (use_fpstack) - rs->ffree_mask = 0xff & ~(1 << MONO_ARCH_FPSTACK_SIZE); + rs->ffree_mask = 0xff & ~(regmask (MONO_ARCH_FPSTACK_SIZE)); ins = bb->code; /*if (cfg->opt & MONO_OPT_COPYPROP) local_copy_prop (cfg, ins);*/ + if (cfg->reginfo && cfg->reginfo_len < rs->next_vireg) { + cfg->reginfo = NULL; + } + reginfo = cfg->reginfo; + if (!reginfo) { + cfg->reginfo_len = MAX (256, rs->next_vireg * 2); + reginfo = cfg->reginfo = mono_mempool_alloc (cfg->mempool, sizeof (RegTrack) * cfg->reginfo_len); + } + else + g_assert (cfg->reginfo_len >= rs->next_vireg); + + if (cfg->reginfof && cfg->reginfof_len < rs->next_vfreg) { + cfg->reginfof = NULL; + } + reginfof = cfg->reginfof; + if (!reginfof) { + cfg->reginfof_len = MAX (256, rs->next_vfreg * 2); + reginfof = cfg->reginfof = mono_mempool_alloc (cfg->mempool, sizeof (RegTrack) * cfg->reginfof_len); + } + else + g_assert (cfg->reginfof_len >= rs->next_vfreg); + + memset (reginfo, 0, rs->next_vireg * sizeof (RegTrack)); + memset (reginfof, 0, rs->next_vfreg * sizeof (RegTrack)); + + ins_count = 0; + for (ins = bb->code; ins; ins = ins->next) { + spec = ins_spec [ins->opcode]; + + ins_count ++; + } + + if (cfg->reverse_inst_list && (cfg->reverse_inst_list_len < ins_count)) { + cfg->reverse_inst_list = NULL; + } + + inst_list = cfg->reverse_inst_list; + if (!inst_list) { + cfg->reverse_inst_list_len = MAX (ins_count, 1024); + inst_list = cfg->reverse_inst_list = mono_mempool_alloc (cfg->mempool, cfg->reverse_inst_list_len * sizeof (InstList)); + } + mem = inst_list; + i = 1; fpcount = 0; - DEBUG (g_print ("LOCAL regalloc: basic block: %d\n", bb->block_num)); + DEBUG (printf ("\nLOCAL REGALLOC: BASIC BLOCK: %d\n", bb->block_num)); /* forward pass on the instructions to collect register liveness info */ - while (ins) { + for (ins = bb->code; ins; ins = ins->next) { spec = ins_spec [ins->opcode]; - if (!spec) { + if (G_UNLIKELY (!spec)) { g_error ("Opcode '%s' missing from machine description file.", mono_inst_name (ins->opcode)); } - DEBUG (print_ins (i, ins)); + DEBUG (mono_print_ins (i, ins)); /* * TRACK FP STACK */ - if (use_fpstack) { +#if MONO_ARCH_USE_FPSTACK + if (need_fpstack) { GList *spill; if (spec [MONO_INST_SRC1] == 'f') { @@ -683,7 +938,7 @@ mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb) fpcount--; } - if (dreg_is_fp (ins)) { + if (dreg_is_fp (spec)) { if (use_fpstack && (spec [MONO_INST_CLOB] != 'm')) { if (fpcount >= MONO_ARCH_FPSTACK_SIZE) { reginfof [ins->dreg].flags |= MONO_FP_NEEDS_SPILL; @@ -695,18 +950,19 @@ mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb) } } } +#endif if (spec [MONO_INST_SRC1]) { if (spec [MONO_INST_SRC1] == 'f') reginfo1 = reginfof; else reginfo1 = reginfo; - reginfo1 [ins->sreg1].prev_use = reginfo1 [ins->sreg1].last_use; - reginfo1 [ins->sreg1].last_use = i; + //reginfo1 [ins->sreg1].prev_use = reginfo1 [ins->sreg1].last_use; + //reginfo1 [ins->sreg1].last_use = i; if (MONO_ARCH_INST_IS_REGPAIR (spec [MONO_INST_SRC2])) { /* The virtual register is allocated sequentially */ - reginfo1 [ins->sreg1 + 1].prev_use = reginfo1 [ins->sreg1 + 1].last_use; - reginfo1 [ins->sreg1 + 1].last_use = i; + //reginfo1 [ins->sreg1 + 1].prev_use = reginfo1 [ins->sreg1 + 1].last_use; + //reginfo1 [ins->sreg1 + 1].last_use = i; if (reginfo1 [ins->sreg1 + 1].born_in == 0 || reginfo1 [ins->sreg1 + 1].born_in > i) reginfo1 [ins->sreg1 + 1].born_in = i; } @@ -718,12 +974,12 @@ mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb) reginfo2 = reginfof; else reginfo2 = reginfo; - reginfo2 [ins->sreg2].prev_use = reginfo2 [ins->sreg2].last_use; - reginfo2 [ins->sreg2].last_use = i; + //reginfo2 [ins->sreg2].prev_use = reginfo2 [ins->sreg2].last_use; + //reginfo2 [ins->sreg2].last_use = i; if (MONO_ARCH_INST_IS_REGPAIR (spec [MONO_INST_SRC2])) { /* The virtual register is allocated sequentially */ - reginfo2 [ins->sreg2 + 1].prev_use = reginfo2 [ins->sreg2 + 1].last_use; - reginfo2 [ins->sreg2 + 1].last_use = i; + //reginfo2 [ins->sreg2 + 1].prev_use = reginfo2 [ins->sreg2 + 1].last_use; + //reginfo2 [ins->sreg2 + 1].last_use = i; if (reginfo2 [ins->sreg2 + 1].born_in == 0 || reginfo2 [ins->sreg2 + 1].born_in > i) reginfo2 [ins->sreg2 + 1].born_in = i; } @@ -733,25 +989,25 @@ mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb) if (spec [MONO_INST_DEST]) { int dest_dreg; - if (dreg_is_fp (ins)) + if (dreg_is_fp (spec)) reginfod = reginfof; else reginfod = reginfo; if (spec [MONO_INST_DEST] != 'b') /* it's not just a base register */ reginfod [ins->dreg].killed_in = i; - reginfod [ins->dreg].prev_use = reginfod [ins->dreg].last_use; - reginfod [ins->dreg].last_use = i; + //reginfod [ins->dreg].prev_use = reginfod [ins->dreg].last_use; + //reginfod [ins->dreg].last_use = i; if (reginfod [ins->dreg].born_in == 0 || reginfod [ins->dreg].born_in > i) reginfod [ins->dreg].born_in = i; dest_dreg = MONO_ARCH_INST_FIXED_REG (spec [MONO_INST_DEST]); if (dest_dreg != -1) - reginfod [ins->dreg].preferred_mask = (1 << dest_dreg); + reginfod [ins->dreg].preferred_mask = (regmask (dest_dreg)); if (MONO_ARCH_INST_IS_REGPAIR (spec [MONO_INST_DEST])) { /* The virtual register is allocated sequentially */ - reginfod [ins->dreg + 1].prev_use = reginfod [ins->dreg + 1].last_use; - reginfod [ins->dreg + 1].last_use = i; + //reginfod [ins->dreg + 1].prev_use = reginfod [ins->dreg + 1].last_use; + //reginfod [ins->dreg + 1].last_use = i; if (reginfod [ins->dreg + 1].born_in == 0 || reginfod [ins->dreg + 1].born_in > i) reginfod [ins->dreg + 1].born_in = i; if (MONO_ARCH_INST_REGPAIR_REG2 (spec [MONO_INST_DEST], -1) != -1) @@ -777,8 +1033,8 @@ mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb) hreg = regpair >> 24; reg = regpair & 0xffffff; - reginfo [reg].prev_use = reginfo [reg].last_use; - reginfo [reg].last_use = i; + //reginfo [reg].prev_use = reginfo [reg].last_use; + //reginfo [reg].last_use = i; list = g_slist_next (list); } @@ -794,17 +1050,17 @@ mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb) hreg = regpair >> 24; reg = regpair & 0xffffff; - reginfof [reg].prev_use = reginfof [reg].last_use; - reginfof [reg].last_use = i; + //reginfof [reg].prev_use = reginfof [reg].last_use; + //reginfof [reg].last_use = i; list = g_slist_next (list); } } } - reversed = inst_list_prepend (cfg->mempool, reversed, ins); + reversed = inst_list_prepend (mem, reversed, ins); + mem += sizeof (InstList); ++i; - ins = ins->next; } // todo: check if we have anything left on fp stack, in verify mode? @@ -817,7 +1073,8 @@ mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb) int prev_dreg, prev_sreg1, prev_sreg2, clob_dreg; int dest_dreg, dest_sreg1, dest_sreg2, clob_reg; int dreg_high, sreg1_high; - guint32 dreg_mask, sreg1_mask, sreg2_mask, mask; + regmask_t dreg_mask, sreg1_mask, sreg2_mask, mask; + regmask_t dreg_fixed_mask, sreg1_fixed_mask, sreg2_fixed_mask; const unsigned char *ip; --i; ins = tmp->data; @@ -829,12 +1086,12 @@ mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb) dest_dreg = -1; dest_sreg1 = -1; dest_sreg2 = -1; - dreg_mask = dreg_is_fp (ins) ? MONO_ARCH_CALLEE_FREGS : MONO_ARCH_CALLEE_REGS; - sreg1_mask = sreg1_is_fp (ins) ? MONO_ARCH_CALLEE_FREGS : MONO_ARCH_CALLEE_REGS; - sreg2_mask = sreg2_is_fp (ins) ? MONO_ARCH_CALLEE_FREGS : MONO_ARCH_CALLEE_REGS; + dreg_mask = dreg_is_fp (spec) ? MONO_ARCH_CALLEE_FREGS : MONO_ARCH_CALLEE_REGS; + sreg1_mask = sreg1_is_fp (spec) ? MONO_ARCH_CALLEE_FREGS : MONO_ARCH_CALLEE_REGS; + sreg2_mask = sreg2_is_fp (spec) ? MONO_ARCH_CALLEE_FREGS : MONO_ARCH_CALLEE_REGS; - DEBUG (g_print ("processing:")); - DEBUG (print_ins (i, ins)); + DEBUG (printf ("processing:")); + DEBUG (mono_print_ins (i, ins)); ip = ins->cil_code; @@ -847,11 +1104,20 @@ mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb) clob_reg = MONO_ARCH_INST_FIXED_REG (spec [MONO_INST_CLOB]); sreg2_mask &= ~ (MONO_ARCH_INST_SREG2_MASK (spec)); +#ifdef MONO_ARCH_INST_FIXED_MASK + sreg1_fixed_mask = MONO_ARCH_INST_FIXED_MASK (spec [MONO_INST_SRC1]); + sreg2_fixed_mask = MONO_ARCH_INST_FIXED_MASK (spec [MONO_INST_SRC2]); + dreg_fixed_mask = MONO_ARCH_INST_FIXED_MASK (spec [MONO_INST_DEST]); +#else + sreg1_fixed_mask = sreg2_fixed_mask = dreg_fixed_mask = 0; +#endif + /* * TRACK FP STACK */ - if (use_fpstack && (spec [MONO_INST_CLOB] != 'm')) { - if (dreg_is_fp (ins)) { +#if MONO_ARCH_USE_FPSTACK + if (need_fpstack && (spec [MONO_INST_CLOB] != 'm')) { + if (dreg_is_fp (spec)) { if (reginfof [ins->dreg].flags & MONO_FP_NEEDS_SPILL) { GList *spill_node; MonoInst *store; @@ -914,26 +1180,27 @@ mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb) } } } +#endif /* * TRACK FIXED SREG2 */ if (dest_sreg2 != -1) { - if (rs->ifree_mask & (1 << dest_sreg2)) { + if (rs->ifree_mask & (regmask (dest_sreg2))) { if (is_global_ireg (ins->sreg2)) { /* Argument already in hard reg, need to copy */ MonoInst *copy = create_copy_ins (cfg, dest_sreg2, ins->sreg2, NULL, ip, FALSE); insert_before_ins (ins, tmp, copy); } else { - DEBUG (g_print ("\tshortcut assignment of R%d to %s\n", ins->sreg2, mono_arch_regname (dest_sreg2))); - assign_ireg (rs, ins->sreg2, dest_sreg2); + DEBUG (printf ("\tshortcut assignment of R%d to %s\n", ins->sreg2, mono_arch_regname (dest_sreg2))); + assign_ireg (cfg, rs, ins->sreg2, dest_sreg2); } } else { int need_spill = TRUE; - dreg_mask &= ~ (1 << dest_sreg2); - sreg1_mask &= ~ (1 << dest_sreg2); + dreg_mask &= ~ (regmask (dest_sreg2)); + sreg1_mask &= ~ (regmask (dest_sreg2)); /* * First check if dreg is assigned to dest_sreg2, since we @@ -949,12 +1216,13 @@ mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb) int new_dest; new_dest = alloc_int_reg (cfg, tmp, ins, dreg_mask, ins->dreg, ®info [ins->dreg]); g_assert (new_dest >= 0); - DEBUG (g_print ("\tchanging dreg R%d to %s from %s\n", ins->dreg, mono_arch_regname (new_dest), mono_arch_regname (dest_sreg2))); + DEBUG (printf ("\tchanging dreg R%d to %s from %s\n", ins->dreg, mono_arch_regname (new_dest), mono_arch_regname (dest_sreg2))); prev_dreg = ins->dreg; - assign_ireg (rs, ins->dreg, new_dest); + assign_ireg (cfg, rs, ins->dreg, new_dest); clob_dreg = ins->dreg; create_copy_ins (cfg, dest_sreg2, new_dest, ins, ip, FALSE); + mono_regstate_free_int (rs, dest_sreg2); need_spill = FALSE; } @@ -975,14 +1243,14 @@ mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb) } if (need_spill) { - DEBUG (g_print ("\tforced spill of R%d\n", rs->isymbolic [dest_sreg2])); + DEBUG (printf ("\tforced spill of R%d\n", rs->isymbolic [dest_sreg2])); get_register_force_spilling (cfg, tmp, ins, rs->isymbolic [dest_sreg2], FALSE); - mono_regstate_free_int (rs, dest_sreg2); + mono_regstate2_free_int (rs, dest_sreg2); } if (!is_global_ireg (ins->sreg2)) /* force-set sreg2 */ - assign_ireg (rs, ins->sreg2, dest_sreg2); + assign_ireg (cfg, rs, ins->sreg2, dest_sreg2); } ins->sreg2 = dest_sreg2; } @@ -990,10 +1258,28 @@ mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb) /* * TRACK DREG */ - fp = dreg_is_fp (ins); + fp = dreg_is_fp (spec); if (spec [MONO_INST_DEST] && (!fp || (fp && !use_fpstack)) && is_soft_reg (ins->dreg, fp)) prev_dreg = ins->dreg; + if (spec [MONO_INST_DEST] == 'b') { + /* + * The dest reg is read by the instruction, not written, so + * avoid allocating sreg1/sreg2 to the same reg. + */ + if (dest_sreg1 != -1) + dreg_mask &= ~ (regmask (dest_sreg1)); + if (dest_sreg2 != -1) + dreg_mask &= ~ (regmask (dest_sreg2)); + + val = rassign (cfg, ins->dreg, fp); + if (is_soft_reg (ins->dreg, fp) && (val >= 0) && (!(regmask (val) & dreg_mask))) { + /* DREG is already allocated to a register needed for sreg1 */ + get_register_force_spilling (cfg, tmp, ins, ins->dreg, FALSE); + mono_regstate2_free_int (rs, val); + } + } + /* * If dreg is a fixed regpair, free up both of the needed hregs to avoid * various complex situations. @@ -1016,9 +1302,28 @@ mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb) } } + if (dreg_fixed_mask) { + g_assert (!fp); + if (is_global_ireg (ins->dreg)) { + /* + * The argument is already in a hard reg, but that reg is + * not usable by this instruction, so allocate a new one. + */ + val = mono_regstate2_alloc_int (rs, dreg_fixed_mask); + if (val < 0) + val = get_register_spilling (cfg, tmp, ins, dreg_fixed_mask, -1, fp); + mono_regstate2_free_int (rs, val); + dest_dreg = val; + + /* Fall through */ + } + else + dreg_mask &= dreg_fixed_mask; + } + if ((!fp || (fp && !use_fpstack)) && (is_soft_reg (ins->dreg, fp))) { if (dest_dreg != -1) - dreg_mask = (1 << dest_dreg); + dreg_mask = (regmask (dest_dreg)); val = rassign (cfg, ins->dreg, fp); @@ -1029,12 +1334,12 @@ mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb) spill = -val -1; } val = alloc_reg (cfg, tmp, ins, dreg_mask, ins->dreg, ®info [ins->dreg], fp); - assign_reg (rs, ins->dreg, val, fp); + assign_reg (cfg, rs, ins->dreg, val, fp); if (spill) create_spilled_store (cfg, spill, val, prev_dreg, ins, fp); } - DEBUG (g_print ("\tassigned dreg %s to dest R%d\n", mono_regname_full (val, fp), ins->dreg)); + DEBUG (printf ("\tassigned dreg %s to dest R%d\n", mono_regname_full (val, fp), ins->dreg)); ins->dreg = val; } @@ -1053,34 +1358,34 @@ mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb) /* the register gets spilled after this inst */ spill = -val -1; } - val = mono_regstate_alloc_int (rs, mask); + val = mono_regstate2_alloc_int (rs, mask); if (val < 0) val = get_register_spilling (cfg, tmp, ins, mask, reg2, fp); if (spill) create_spilled_store (cfg, spill, val, reg2, ins, fp); } else { - if (! (mask & (1 << val))) { - val = mono_regstate_alloc_int (rs, mask); + if (! (mask & (regmask (val)))) { + val = mono_regstate2_alloc_int (rs, mask); if (val < 0) val = get_register_spilling (cfg, tmp, ins, mask, reg2, fp); /* Reallocate hreg to the correct register */ create_copy_ins (cfg, rs->iassign [reg2], val, ins, ip, fp); - mono_regstate_free_int (rs, rs->iassign [reg2]); + mono_regstate2_free_int (rs, rs->iassign [reg2]); } } - DEBUG (g_print ("\tassigned dreg-high %s to dest R%d\n", mono_arch_regname (val), reg2)); - assign_reg (rs, reg2, val, fp); + DEBUG (printf ("\tassigned dreg-high %s to dest R%d\n", mono_arch_regname (val), reg2)); + assign_reg (cfg, rs, reg2, val, fp); dreg_high = val; - ins->unused = val; + ins->backend.reg3 = val; if (reg_is_freeable (val, fp) && reg2 >= 0 && (reginfo [reg2].born_in >= i)) { - DEBUG (g_print ("\tfreeable %s (R%d)\n", mono_arch_regname (val), reg2)); - mono_regstate_free_int (rs, val); + DEBUG (printf ("\tfreeable %s (R%d)\n", mono_arch_regname (val), reg2)); + mono_regstate2_free_int (rs, val); } } @@ -1092,11 +1397,11 @@ mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb) */ int dreg = rassign (cfg, prev_dreg, fp); g_assert (dreg >= 0); - DEBUG (g_print ("\tfreeable %s (R%d) (born in %d)\n", mono_regname_full (dreg, fp), prev_dreg, (fp ? reginfof : reginfo) [prev_dreg].born_in)); + DEBUG (printf ("\tfreeable %s (R%d) (born in %d)\n", mono_regname_full (dreg, fp), prev_dreg, (fp ? reginfof : reginfo) [prev_dreg].born_in)); if (fp) - mono_regstate_free_float (rs, dreg); + mono_regstate2_free_float (rs, dreg); else - mono_regstate_free_int (rs, dreg); + mono_regstate2_free_int (rs, dreg); } if ((dest_dreg != -1) && (ins->dreg != dest_dreg)) { @@ -1114,13 +1419,22 @@ mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb) } } + if (spec [MONO_INST_DEST] == 'b') { + /* + * The dest reg is read by the instruction, not written, so + * avoid allocating sreg1/sreg2 to the same reg. + */ + sreg1_mask &= ~ (regmask (ins->dreg)); + sreg2_mask &= ~ (regmask (ins->dreg)); + } + /* * TRACK CLOBBERING */ - if ((clob_reg != -1) && (!(rs->ifree_mask & (1 << clob_reg)))) { - DEBUG (g_print ("\tforced spill of clobbered reg R%d\n", rs->isymbolic [clob_reg])); + if ((clob_reg != -1) && (!(rs->ifree_mask & (regmask (clob_reg))))) { + DEBUG (printf ("\tforced spill of clobbered reg R%d\n", rs->isymbolic [clob_reg])); get_register_force_spilling (cfg, tmp, ins, rs->isymbolic [clob_reg], FALSE); - mono_regstate_free_int (rs, clob_reg); + mono_regstate2_free_int (rs, clob_reg); } if (spec [MONO_INST_CLOB] == 'c') { @@ -1133,36 +1447,36 @@ mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb) * Need to avoid spilling the dreg since the dreg is not really * clobbered by the call. */ - if ((prev_dreg != -1) && !dreg_is_fp (ins)) - dreg = rassign (cfg, prev_dreg, dreg_is_fp (ins)); + if ((prev_dreg != -1) && !dreg_is_fp (spec)) + dreg = rassign (cfg, prev_dreg, dreg_is_fp (spec)); else dreg = -1; if (MONO_ARCH_INST_IS_REGPAIR (spec [MONO_INST_DEST])) - dreg2 = rassign (cfg, prev_dreg + 1, dreg_is_fp (ins)); + dreg2 = rassign (cfg, prev_dreg + 1, dreg_is_fp (spec)); else dreg2 = -1; for (j = 0; j < MONO_MAX_IREGS; ++j) { - s = 1 << j; + s = regmask (j); if ((clob_mask & s) && !(rs->ifree_mask & s) && (j != ins->sreg1) && (j != dreg) && (j != dreg2)) { get_register_force_spilling (cfg, tmp, ins, rs->isymbolic [j], FALSE); - mono_regstate_free_int (rs, j); + mono_regstate2_free_int (rs, j); } } if (!use_fpstack) { clob_mask = MONO_ARCH_CALLEE_FREGS; - if ((prev_dreg != -1) && dreg_is_fp (ins)) - dreg = rassign (cfg, prev_dreg, dreg_is_fp (ins)); + if ((prev_dreg != -1) && dreg_is_fp (spec)) + dreg = rassign (cfg, prev_dreg, dreg_is_fp (spec)); else dreg = -1; for (j = 0; j < MONO_MAX_FREGS; ++j) { - s = 1 << j; + s = regmask (j); if ((clob_mask & s) && !(rs->ffree_mask & s) && (j != ins->sreg1) && (j != dreg)) { get_register_force_spilling (cfg, tmp, ins, rs->fsymbolic [j], TRUE); - mono_regstate_free_float (rs, j); + mono_regstate2_free_float (rs, j); } } } @@ -1195,15 +1509,14 @@ mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb) hreg = regpair >> 24; reg = regpair & 0xffffff; - assign_reg (rs, reg, hreg, FALSE); + assign_reg (cfg, rs, reg, hreg, FALSE); - sreg1_mask &= ~(1 << hreg); + sreg1_mask &= ~(regmask (hreg)); - DEBUG (g_print ("\tassigned arg reg %s to R%d\n", mono_arch_regname (hreg), reg)); + DEBUG (printf ("\tassigned arg reg %s to R%d\n", mono_arch_regname (hreg), reg)); list = g_slist_next (list); } - g_slist_free (call->out_ireg_args); } list = call->out_freg_args; @@ -1216,21 +1529,19 @@ mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb) hreg = regpair >> 24; reg = regpair & 0xffffff; - assign_reg (rs, reg, hreg, TRUE); + assign_reg (cfg, rs, reg, hreg, TRUE); - DEBUG (g_print ("\tassigned arg reg %s to R%d\n", mono_arch_fregname (hreg), reg)); + DEBUG (printf ("\tassigned arg reg %s to R%d\n", mono_arch_fregname (hreg), reg)); list = g_slist_next (list); } } - if (call->out_freg_args) - g_slist_free (call->out_freg_args); } /* * TRACK SREG1 */ - fp = sreg1_is_fp (ins); + fp = sreg1_is_fp (spec); if ((!fp || (fp && !use_fpstack))) { if (MONO_ARCH_INST_IS_REGPAIR (spec [MONO_INST_DEST]) && (spec [MONO_INST_CLOB] == '1')) { g_assert (is_soft_reg (ins->sreg1, fp)); @@ -1238,30 +1549,49 @@ mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb) /* To simplify things, we allocate the same regpair to sreg1 and dreg */ if (dest_sreg1 != -1) g_assert (dest_sreg1 == ins->dreg); - val = mono_regstate_alloc_int (rs, 1 << ins->dreg); + val = mono_regstate2_alloc_int (rs, regmask (ins->dreg)); g_assert (val >= 0); - assign_reg (rs, ins->sreg1, val, fp); + assign_reg (cfg, rs, ins->sreg1, val, fp); - DEBUG (g_print ("\tassigned sreg1-low %s to R%d\n", mono_regname_full (val, fp), ins->sreg1)); + DEBUG (printf ("\tassigned sreg1-low %s to R%d\n", mono_regname_full (val, fp), ins->sreg1)); - g_assert ((1 << dreg_high) & regpair_reg2_mask (spec [MONO_INST_SRC1], ins->dreg)); - val = mono_regstate_alloc_int (rs, 1 << dreg_high); + g_assert ((regmask (dreg_high)) & regpair_reg2_mask (spec [MONO_INST_SRC1], ins->dreg)); + val = mono_regstate2_alloc_int (rs, regmask (dreg_high)); g_assert (val >= 0); - assign_reg (rs, ins->sreg1 + 1, val, fp); + assign_reg (cfg, rs, ins->sreg1 + 1, val, fp); - DEBUG (g_print ("\tassigned sreg1-high %s to R%d\n", mono_regname_full (val, fp), ins->sreg1 + 1)); + DEBUG (printf ("\tassigned sreg1-high %s to R%d\n", mono_regname_full (val, fp), ins->sreg1 + 1)); /* Skip rest of this section */ dest_sreg1 = -1; } + if (sreg1_fixed_mask) { + g_assert (!fp); + if (is_global_ireg (ins->sreg1)) { + /* + * The argument is already in a hard reg, but that reg is + * not usable by this instruction, so allocate a new one. + */ + val = mono_regstate2_alloc_int (rs, sreg1_fixed_mask); + if (val < 0) + val = get_register_spilling (cfg, tmp, ins, sreg1_fixed_mask, -1, fp); + mono_regstate2_free_int (rs, val); + dest_sreg1 = val; + + /* Fall through to the dest_sreg1 != -1 case */ + } + else + sreg1_mask &= sreg1_fixed_mask; + } + if (dest_sreg1 != -1) { - sreg1_mask = 1 << dest_sreg1; + sreg1_mask = regmask (dest_sreg1); - if (!(rs->ifree_mask & (1 << dest_sreg1))) { - DEBUG (g_print ("\tforced spill of R%d\n", rs->isymbolic [dest_sreg1])); + if (!(rs->ifree_mask & (regmask (dest_sreg1)))) { + DEBUG (printf ("\tforced spill of R%d\n", rs->isymbolic [dest_sreg1])); get_register_force_spilling (cfg, tmp, ins, rs->isymbolic [dest_sreg1], FALSE); - mono_regstate_free_int (rs, dest_sreg1); + mono_regstate2_free_int (rs, dest_sreg1); } if (is_global_ireg (ins->sreg1)) { /* The argument is already in a hard reg, need to copy */ @@ -1281,17 +1611,17 @@ mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb) spill = -val -1; } - if (((ins->opcode == OP_MOVE) || (ins->opcode == OP_SETREG)) && !spill && !fp && (!is_global_ireg (ins->dreg) && (rs->ifree_mask & (1 << ins->dreg)))) { + if (((ins->opcode == OP_MOVE) || (ins->opcode == OP_SETREG)) && !spill && !fp && (is_local_ireg (ins->dreg) && (rs->ifree_mask & (regmask (ins->dreg))))) { /* * Allocate the same hreg to sreg1 as well so the * peephole can get rid of the move. */ - sreg1_mask = 1 << ins->dreg; + sreg1_mask = regmask (ins->dreg); } val = alloc_reg (cfg, tmp, ins, sreg1_mask, ins->sreg1, ®info [ins->sreg1], fp); - assign_reg (rs, ins->sreg1, val, fp); - DEBUG (g_print ("\tassigned sreg1 %s to R%d\n", mono_regname_full (val, fp), ins->sreg1)); + assign_reg (cfg, rs, ins->sreg1, val, fp); + DEBUG (printf ("\tassigned sreg1 %s to R%d\n", mono_regname_full (val, fp), ins->sreg1)); if (spill) { MonoInst *store = create_spilled_store (cfg, spill, val, prev_sreg1, NULL, fp); @@ -1303,7 +1633,7 @@ mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb) } } else if ((dest_sreg1 != -1) && (dest_sreg1 != val)) { - g_assert_not_reached (); + create_copy_ins (cfg, dest_sreg1, val, ins, ip, fp); } ins->sreg1 = val; @@ -1311,7 +1641,7 @@ mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb) else { prev_sreg1 = -1; } - sreg2_mask &= ~(1 << ins->sreg1); + sreg2_mask &= ~(regmask (ins->sreg1)); } /* Handle the case when sreg1 is a regpair but dreg is not */ @@ -1329,37 +1659,37 @@ mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb) /* the register gets spilled after this inst */ spill = -val -1; } - val = mono_regstate_alloc_int (rs, mask); + val = mono_regstate2_alloc_int (rs, mask); if (val < 0) val = get_register_spilling (cfg, tmp, ins, mask, reg2, fp); if (spill) g_assert_not_reached (); } else { - if (! (mask & (1 << val))) { + if (! (mask & (regmask (val)))) { /* The vreg is already allocated to a wrong hreg */ /* FIXME: */ g_assert_not_reached (); #if 0 - val = mono_regstate_alloc_int (rs, mask); + val = mono_regstate2_alloc_int (rs, mask); if (val < 0) val = get_register_spilling (cfg, tmp, ins, mask, reg2, fp); /* Reallocate hreg to the correct register */ create_copy_ins (cfg, rs->iassign [reg2], val, ins, ip, fp); - mono_regstate_free_int (rs, rs->iassign [reg2]); + mono_regstate2_free_int (rs, rs->iassign [reg2]); #endif } } sreg1_high = val; - DEBUG (g_print ("\tassigned sreg1 hreg %s to dest R%d\n", mono_arch_regname (val), reg2)); - assign_reg (rs, reg2, val, fp); + DEBUG (printf ("\tassigned sreg1 hreg %s to dest R%d\n", mono_arch_regname (val), reg2)); + assign_reg (cfg, rs, reg2, val, fp); } /* Handle dreg==sreg1 */ - if (((dreg_is_fp (ins) && spec [MONO_INST_SRC1] == 'f' && !use_fpstack) || spec [MONO_INST_CLOB] == '1') && ins->dreg != ins->sreg1) { + if (((dreg_is_fp (spec) && spec [MONO_INST_SRC1] == 'f' && !use_fpstack) || spec [MONO_INST_CLOB] == '1') && ins->dreg != ins->sreg1) { MonoInst *sreg2_copy = NULL; MonoInst *copy; gboolean fp = (spec [MONO_INST_SRC1] == 'f'); @@ -1371,14 +1701,14 @@ mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb) */ int reg2 = alloc_reg (cfg, tmp, ins, dreg_mask, ins->sreg2, NULL, fp); - DEBUG (g_print ("\tneed to copy sreg2 %s to reg %s\n", mono_regname_full (ins->sreg2, fp), mono_regname_full (reg2, fp))); + DEBUG (printf ("\tneed to copy sreg2 %s to reg %s\n", mono_regname_full (ins->sreg2, fp), mono_regname_full (reg2, fp))); sreg2_copy = create_copy_ins (cfg, reg2, ins->sreg2, NULL, ip, fp); prev_sreg2 = ins->sreg2 = reg2; if (fp) - mono_regstate_free_float (rs, reg2); + mono_regstate2_free_float (rs, reg2); else - mono_regstate_free_int (rs, reg2); + mono_regstate2_free_int (rs, reg2); } if (MONO_ARCH_INST_IS_REGPAIR (spec [MONO_INST_SRC1])) { @@ -1395,7 +1725,7 @@ mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb) g_assert (dreg_high == sreg1_high); } - DEBUG (g_print ("\tneed to copy sreg1 %s to dreg %s\n", mono_regname_full (ins->sreg1, fp), mono_regname_full (ins->dreg, fp))); + DEBUG (printf ("\tneed to copy sreg1 %s to dreg %s\n", mono_regname_full (ins->sreg1, fp), mono_regname_full (ins->dreg, fp))); copy = create_copy_ins (cfg, ins->dreg, ins->sreg1, NULL, ip, fp); insert_before_ins (ins, tmp, copy); @@ -1406,16 +1736,16 @@ mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb) * Need to prevent sreg2 to be allocated to sreg1, since that * would screw up the previous copy. */ - sreg2_mask &= ~ (1 << ins->sreg1); + sreg2_mask &= ~ (regmask (ins->sreg1)); /* we set sreg1 to dest as well */ prev_sreg1 = ins->sreg1 = ins->dreg; - sreg2_mask &= ~ (1 << ins->dreg); + sreg2_mask &= ~ (regmask (ins->dreg)); } /* * TRACK SREG2 */ - fp = sreg2_is_fp (ins); + fp = sreg2_is_fp (spec); if (MONO_ARCH_INST_IS_REGPAIR (spec [MONO_INST_SRC2])) g_assert_not_reached (); if ((!fp || (fp && !use_fpstack)) && (is_soft_reg (ins->sreg2, fp))) { @@ -1428,10 +1758,16 @@ mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb) spill = -val -1; } val = alloc_reg (cfg, tmp, ins, sreg2_mask, ins->sreg2, ®info [ins->sreg2], fp); - assign_reg (rs, ins->sreg2, val, fp); - DEBUG (g_print ("\tassigned sreg2 %s to R%d\n", mono_regname_full (val, fp), ins->sreg2)); - if (spill) - create_spilled_store (cfg, spill, val, prev_sreg2, ins, fp); + assign_reg (cfg, rs, ins->sreg2, val, fp); + DEBUG (printf ("\tassigned sreg2 %s to R%d\n", mono_regname_full (val, fp), ins->sreg2)); + if (spill) { + MonoInst *store = create_spilled_store (cfg, spill, val, prev_sreg2, NULL, fp); + /* + * Need to insert before the instruction since it can + * overwrite sreg2. + */ + insert_before_ins (ins, tmp, store); + } } ins->sreg2 = val; } @@ -1440,22 +1776,20 @@ mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb) } /*if (reg_is_freeable (ins->sreg1) && prev_sreg1 >= 0 && reginfo [prev_sreg1].born_in >= i) { - DEBUG (g_print ("freeable %s\n", mono_arch_regname (ins->sreg1))); - mono_regstate_free_int (rs, ins->sreg1); + DEBUG (printf ("freeable %s\n", mono_arch_regname (ins->sreg1))); + mono_regstate2_free_int (rs, ins->sreg1); } if (reg_is_freeable (ins->sreg2) && prev_sreg2 >= 0 && reginfo [prev_sreg2].born_in >= i) { - DEBUG (g_print ("freeable %s\n", mono_arch_regname (ins->sreg2))); - mono_regstate_free_int (rs, ins->sreg2); + DEBUG (printf ("freeable %s\n", mono_arch_regname (ins->sreg2))); + mono_regstate2_free_int (rs, ins->sreg2); }*/ - DEBUG (print_ins (i, ins)); + DEBUG (mono_print_ins (i, ins)); /* this may result from a insert_before call */ if (!tmp->next) bb->code = tmp->data; tmp = tmp->next; } - g_free (reginfo); - g_free (reginfof); g_list_free (fspill_list); }