Author: zoltan
Date: 2005-03-15 15:01:54 -0500 (Tue, 15 Mar 2005)
New Revision: 41851

Modified:
   branches/vargaz/mini-xp-local-regalloc/mono/mono/mini/linear-scan.c
   branches/vargaz/mini-xp-local-regalloc/mono/mono/mini/mini-amd64.c
   branches/vargaz/mini-xp-local-regalloc/mono/mono/mini/mini.c
Log:
2005-03-15  Zoltan Varga  <[EMAIL PROTECTED]>

        * mini-amd64.c: Rework local register allocator to unify the fp+non fp
        allocation. Also add handling for more corner cases.

        * mini.c linear-scan.c: Promote local variables which are local to
        a basic block to virtual registers.


Modified: branches/vargaz/mini-xp-local-regalloc/mono/mono/mini/linear-scan.c
===================================================================
--- branches/vargaz/mini-xp-local-regalloc/mono/mono/mini/linear-scan.c 
2005-03-15 19:57:20 UTC (rev 41850)
+++ branches/vargaz/mini-xp-local-regalloc/mono/mono/mini/linear-scan.c 
2005-03-15 20:01:54 UTC (rev 41851)
@@ -196,6 +196,37 @@
                        } else
                                vmv->reg = -1;
                }
+
+               if (vmv->reg == -1) {
+                       if ((vmv->range.first_use.abs_pos >> 16) == 
(vmv->range.last_use.abs_pos >> 16)) {
+#if 0
+                               static int count = 0;
+                               count ++;
+                               /* 
+                                * This variable is local to a basic block, so 
convert it to
+                                * a virtual register.
+                                */
+                               //if (getenv ("COUNT") && 
strstr(cfg->method->name, "Emit")) {
+                               if (getenv ("COUNT")) {
+                                       if (count <= atoi (getenv ("COUNT"))) {
+                                               int reg = 
mono_regstate_next_int (cfg->rs);
+                                               printf ("HIT: %d ", reg); 
mono_print_tree_nl (cfg->varinfo [vmv->idx]);
+
+                                               cfg->varinfo [vmv->idx]->opcode 
= OP_REGVAR;
+                                               cfg->varinfo [vmv->idx]->dreg = 
reg;
+                                               vmv->reg = reg;
+                                       }
+                               }
+#else
+#if 1
+                               cfg->varinfo [vmv->idx]->opcode = OP_REGVAR;
+                               cfg->varinfo [vmv->idx]->dreg = 
mono_regstate_next_int (cfg->rs);
+
+                               //printf ("HIT!\n");
+#endif
+#endif
+                       }
+               }
        }
 
        /* Compute used regs */

Modified: branches/vargaz/mini-xp-local-regalloc/mono/mono/mini/mini-amd64.c
===================================================================
--- branches/vargaz/mini-xp-local-regalloc/mono/mono/mini/mini-amd64.c  
2005-03-15 19:57:20 UTC (rev 41850)
+++ branches/vargaz/mini-xp-local-regalloc/mono/mono/mini/mini-amd64.c  
2005-03-15 20:01:54 UTC (rev 41851)
@@ -1679,13 +1679,23 @@
        return load;
 }
 
-#define is_global_ireg(r) ((r) >= 0 && (r) <= 15 && AMD64_IS_CALLEE_SAVED_REG 
((r)))
-#define ireg_is_freeable(r) ((r) >= 0 && (r) <= 15 && AMD64_IS_CALLEE_REG 
((r)))
-#define freg_is_freeable(r) ((r) >= 0 && (r) <= AMD64_XMM_NREG)
+#define MONO_ARCH_CALLEE_REGS AMD64_CALLEE_REGS
+#define MONO_ARCH_CALLEE_FREGS 0xffff
+#define MONO_ARCH_CALLEE_SAVED_REGS AMD64_CALLEE_SAVED_REGS
+#define MONO_ARCH_CALLEE_SAVED_FREGS 0
 
+#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 ireg_is_freeable(r) is_local_ireg ((r))
+#define freg_is_freeable(r) is_hard_freg ((r))
+
 #define reg_is_freeable(r,fp) ((fp) ? freg_is_freeable ((r)) : 
ireg_is_freeable ((r)))
-#define reg_is_hard(r,fp) ((fp) ? ((r) < MONO_MAX_FREGS) : ((r) < 
MONO_MAX_IREGS))
-#define reg_is_soft(r,fp) (!reg_is_hard((r),(fp)))
+#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')
@@ -1710,21 +1720,21 @@
                g_error ("Unknown opcode: %s\n", mono_inst_name (ins->opcode));
        if (spec [MONO_INST_DEST]) {
                gboolean fp = (spec [MONO_INST_DEST] == 'f');
-               if (reg_is_soft (ins->dreg, fp))
+               if (is_soft_reg (ins->dreg, fp))
                        g_print (" R%d <-", ins->dreg);
                else
                        g_print (" %s <-", mono_amd64_regname (ins->dreg, fp));
        }
        if (spec [MONO_INST_SRC1]) {
                gboolean fp = (spec [MONO_INST_SRC1] == 'f');
-               if (reg_is_soft (ins->sreg1, fp))
+               if (is_soft_reg (ins->sreg1, fp))
                        g_print (" R%d", ins->sreg1);
                else
                        g_print (" %s", mono_amd64_regname (ins->sreg1, fp));
        }
        if (spec [MONO_INST_SRC2]) {
                gboolean fp = (spec [MONO_INST_SRC2] == 'f');
-               if (reg_is_soft (ins->sreg2, fp))
+               if (is_soft_reg (ins->sreg2, fp))
                        g_print (" R%d", ins->sreg2);
                else
                        g_print (" %s", mono_amd64_regname (ins->sreg2, fp));
@@ -1844,15 +1854,15 @@
 
        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));
        /* exclude the registers in the current instruction */
-       if ((sreg1_is_fp (ins) == fp) && (reg != ins->sreg1) && 
(reg_is_freeable (ins->sreg1, fp) || (reg_is_soft (ins->sreg1, fp) && rassign 
(cfg, ins->sreg1, fp) >= 0))) {
-               if (reg_is_soft (ins->sreg1, fp))
+       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 (is_soft_reg (ins->sreg1, fp))
                        regmask &= ~ (1 << rassign (cfg, ins->sreg1, fp));
                else
                        regmask &= ~ (1 << ins->sreg1);
                DEBUG (g_print ("\t\texcluding sreg1 %s\n", mono_amd64_regname 
(ins->sreg1, fp)));
        }
-       if ((sreg2_is_fp (ins) == fp) && (reg != ins->sreg2) && 
(reg_is_freeable (ins->sreg2, fp) || (reg_is_soft (ins->sreg2, fp) && rassign 
(cfg, ins->sreg2, fp) >= 0))) {
-               if (reg_is_soft (ins->sreg2, 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 (is_soft_reg (ins->sreg2, fp))
                        regmask &= ~ (1 << rassign (cfg, ins->sreg2, fp));
                else
                        regmask &= ~ (1 << ins->sreg2);
@@ -1871,7 +1881,7 @@
                for (i = 0; i < MONO_MAX_FREGS; ++i) {
                        if (regmask & (1 << i)) {
                                sel = i;
-                               DEBUG (g_print ("\t\tselected register %s has 
assignment %d\n", mono_arch_fregname (sel), cfg->rs->fassign [sel]));
+                               DEBUG (g_print ("\t\tselected register %s has 
assignment %d\n", mono_arch_fregname (sel), cfg->rs->fsymbolic [sel]));
                                break;
                        }
                }
@@ -1885,7 +1895,7 @@
                for (i = 0; i < MONO_MAX_IREGS; ++i) {
                        if (regmask & (1 << i)) {
                                sel = i;
-                               DEBUG (g_print ("\t\tselected register %s has 
assignment %d\n", mono_arch_regname (sel), cfg->rs->iassign [sel]));
+                               DEBUG (g_print ("\t\tselected register %s has 
assignment %d\n", mono_arch_regname (sel), cfg->rs->isymbolic [sel]));
                                break;
                        }
                }
@@ -1986,7 +1996,7 @@
 };
 
 static int
-mono_amd64_alloc_int_reg (MonoCompile *cfg, InstList *tmp, MonoInst *ins, 
guint32 dest_mask, int sym_reg, int flags)
+alloc_int_reg (MonoCompile *cfg, InstList *tmp, MonoInst *ins, guint32 
dest_mask, int sym_reg, int flags)
 {
        int val;
        int test_mask = dest_mask;
@@ -2019,7 +2029,7 @@
 }
 
 static int
-mono_amd64_alloc_float_reg (MonoCompile *cfg, InstList *tmp, MonoInst *ins, 
guint32 dest_mask, int sym_reg)
+alloc_float_reg (MonoCompile *cfg, InstList *tmp, MonoInst *ins, guint32 
dest_mask, int sym_reg)
 {
        int val;
 
@@ -2032,18 +2042,44 @@
        return val;
 }
 
+static int
+alloc_reg (MonoCompile *cfg, InstList *tmp, MonoInst *ins, guint32 dest_mask, 
int sym_reg, int flags, gboolean fp)
+{
+       if (fp)
+               return alloc_float_reg (cfg, tmp, ins, dest_mask, sym_reg);
+       else
+               return alloc_int_reg (cfg, tmp, ins, dest_mask, sym_reg, flags);
+}
+
 static inline void
-assign_ireg (MonoRegState *rs, int reg, int hreg)
+assign_reg (MonoRegState *rs, int reg, int hreg, gboolean fp)
 {
-       g_assert (reg >= MONO_MAX_IREGS);
-       g_assert (hreg < MONO_MAX_IREGS);
-       g_assert (! is_global_ireg (hreg));
+       if (fp) {
+               g_assert (reg >= MONO_MAX_FREGS);
+               g_assert (hreg < MONO_MAX_FREGS);
+               g_assert (! is_global_freg (hreg));
 
-       rs->iassign [reg] = hreg;
-       rs->isymbolic [hreg] = reg;
-       rs->ifree_mask &= ~ (1 << hreg);
+               rs->fassign [reg] = hreg;
+               rs->fsymbolic [hreg] = reg;
+               rs->ffree_mask &= ~ (1 << hreg);
+       }
+       else {
+               g_assert (reg >= MONO_MAX_IREGS);
+               g_assert (hreg < MONO_MAX_IREGS);
+               g_assert (! is_global_ireg (hreg));
+
+               rs->iassign [reg] = hreg;
+               rs->isymbolic [hreg] = reg;
+               rs->ifree_mask &= ~ (1 << hreg);
+       }
 }
 
+static inline void
+assign_ireg (MonoRegState *rs, int reg, int hreg)
+{
+       assign_reg (rs, reg, hreg, FALSE);
+}
+
 /*#include "cprop.c"*/
 
 /*
@@ -2065,6 +2101,7 @@
        const char *spec;
        guint32 src1_mask, src2_mask, dest_mask;
        GList *fspill_list = NULL;
+       gboolean fp;
        int fspill = 0;
 
        if (!bb->code)
@@ -2253,13 +2290,14 @@
        DEBUG (print_regtrack (reginfof, rs->next_vfreg));
        tmp = reversed;
        while (tmp) {
-               int prev_dreg, prev_sreg1, prev_sreg2, clob_dreg;
+               int prev_dreg, prev_sreg1, prev_sreg2, clob_dreg, sreg1_fixed;
                dest_mask = src1_mask = src2_mask = AMD64_CALLEE_REGS;
                --i;
                ins = tmp->data;
                spec = ins_spec [ins->opcode];
                prev_dreg = -1;
                clob_dreg = -1;
+               sreg1_fixed = -1;
                DEBUG (g_print ("processing:"));
                DEBUG (print_ins (i, ins));
                if (spec [MONO_INST_CLOB] == 's') {
@@ -2293,7 +2331,7 @@
                                 */
                                if (val == AMD64_RCX && ins->dreg != 
ins->sreg2) {
                                        int new_dest;
-                                       new_dest = mono_amd64_alloc_int_reg 
(cfg, tmp, ins, dest_mask, ins->dreg, reginfo [ins->dreg].flags);
+                                       new_dest = alloc_int_reg (cfg, tmp, 
ins, dest_mask, ins->dreg, reginfo [ins->dreg].flags);
                                        g_assert (new_dest >= 0);
                                        DEBUG (g_print ("\tclob:s changing dreg 
R%d to %s from ECX\n", ins->dreg, mono_arch_regname (new_dest)));
 
@@ -2423,32 +2461,10 @@
                }
 
                /*
-                * TRACK DREG
+                * TRACK FP STACK
                 */
-               if (spec [MONO_INST_DEST] == 'f') {
-                       if (use_sse2) {
-                               /* Allocate an XMM reg the same way as an int 
reg */
-                               if (reg_is_soft (ins->dreg, TRUE)) {
-                                       val = rs->fassign [ins->dreg];
-                                       prev_dreg = ins->dreg;
-                                       
-                                       if (val < 0) {
-                                               int spill = 0;
-                                               if (val < -1) {
-                                                       /* the register gets 
spilled after this inst */
-                                                       spill = -val -1;
-                                               }
-                                               val = 
mono_amd64_alloc_float_reg (cfg, tmp, ins, AMD64_CALLEE_FREGS, ins->dreg);
-                                               rs->fassign [ins->dreg] = val;
-                                               if (spill)
-                                                       create_spilled_store 
(cfg, spill, val, prev_dreg, ins, TRUE);
-                                       }
-                                       DEBUG (g_print ("\tassigned dreg %s to 
dest R%d\n", mono_amd64_regname (val, TRUE), ins->dreg));
-                                       rs->fsymbolic [val] = prev_dreg;
-                                       ins->dreg = val;
-                               }
-                       }
-                       else if (spec [MONO_INST_CLOB] != 'm') {
+               if (!use_sse2 && (spec [MONO_INST_CLOB] != 'm')) {
+                       if (spec [MONO_INST_DEST] == 'f') {
                                if (reginfof [ins->dreg].flags & 
MONO_X86_FP_NEEDS_SPILL) {
                                        GList *spill_node;
                                        MonoInst *store;
@@ -2461,7 +2477,62 @@
                                        fspill--;
                                }
                        }
-               } else if (spec [MONO_INST_DEST] == 'L') {
+
+                       if (spec [MONO_INST_SRC1] == 'f') {
+                               if (reginfof [ins->sreg1].flags & 
MONO_X86_FP_NEEDS_LOAD) {
+                                       MonoInst *load;
+                                       MonoInst *store = NULL;
+
+                                       if (reginfof [ins->sreg1].flags & 
MONO_X86_FP_NEEDS_LOAD_SPILL) {
+                                               GList *spill_node;
+                                               spill_node = g_list_first 
(fspill_list);
+                                               g_assert (spill_node);
+
+                                               store = 
create_spilled_store_float (cfg, GPOINTER_TO_INT (spill_node->data), 
ins->sreg1, ins);          
+                                               fspill_list = g_list_remove 
(fspill_list, spill_node->data);
+                                       }
+
+                                       fspill++;
+                                       fspill_list = g_list_prepend 
(fspill_list, GINT_TO_POINTER(fspill));
+                                       load = create_spilled_load_float (cfg, 
fspill, ins->sreg1, ins);
+                                       insert_before_ins (ins, tmp, load);
+                                       if (store) 
+                                               insert_before_ins (load, tmp, 
store);
+                               }
+                       }
+
+                       if (spec [MONO_INST_SRC1] == 'f') {
+                               if (reginfof [ins->sreg2].flags & 
MONO_X86_FP_NEEDS_LOAD) {
+                                       MonoInst *load;
+                                       MonoInst *store = NULL;
+
+                                       if (reginfof [ins->sreg2].flags & 
MONO_X86_FP_NEEDS_LOAD_SPILL) {
+                                               GList *spill_node;
+
+                                               spill_node = g_list_first 
(fspill_list);
+                                               g_assert (spill_node);
+                                               if (spec [MONO_INST_SRC1] == 
'f' && (reginfof [ins->sreg1].flags & MONO_X86_FP_NEEDS_LOAD_SPILL))
+                                                       spill_node = 
g_list_next (spill_node);
+       
+                                               store = 
create_spilled_store_float (cfg, GPOINTER_TO_INT (spill_node->data), 
ins->sreg2, ins);
+                                               fspill_list = g_list_remove 
(fspill_list, spill_node->data);
+                                       }
+                               
+                                       fspill++;
+                                       fspill_list = g_list_prepend 
(fspill_list, GINT_TO_POINTER(fspill));
+                                       load = create_spilled_load_float (cfg, 
fspill, ins->sreg2, ins);
+                                       insert_before_ins (ins, tmp, load);
+                                       if (store) 
+                                               insert_before_ins (load, tmp, 
store);
+                               }
+                       }
+               }
+
+               /*
+                * TRACK DREG
+                */
+               fp = dreg_is_fp (ins);
+               if (spec [MONO_INST_DEST] == 'L') {
                        int hreg;
                        val = rs->iassign [ins->dreg];
                        /* check special case when dreg have been moved from 
ecx (clob shift) */
@@ -2479,7 +2550,7 @@
                                        /* the register gets spilled after this 
inst */
                                        spill = -val -1;
                                }
-                               val = mono_amd64_alloc_int_reg (cfg, tmp, ins, 
dest_mask, ins->dreg, reginfo [ins->dreg].flags);
+                               val = alloc_int_reg (cfg, tmp, ins, dest_mask, 
ins->dreg, reginfo [ins->dreg].flags);
                                rs->iassign [ins->dreg] = val;
                                if (spill)
                                        create_spilled_store (cfg, spill, val, 
prev_dreg, ins, FALSE);
@@ -2497,7 +2568,7 @@
                                        /* the register gets spilled after this 
inst */
                                        spill = -val -1;
                                }
-                               val = mono_amd64_alloc_int_reg (cfg, tmp, ins, 
dest_mask, hreg, reginfo [hreg].flags);
+                               val = alloc_int_reg (cfg, tmp, ins, dest_mask, 
hreg, reginfo [hreg].flags);
                                rs->iassign [hreg] = val;
                                if (spill)
                                        create_spilled_store (cfg, spill, val, 
hreg, ins, FALSE);
@@ -2514,9 +2585,13 @@
                                mono_regstate_free_int (rs, val);
                        }
                }
-               else if (ins->dreg >= MONO_MAX_IREGS) {
+               else if ((!fp || (fp && use_sse2)) && (is_soft_reg (ins->dreg, 
fp))) {
                        int hreg;
-                       val = rs->iassign [ins->dreg];
+                       val = rassign (cfg, ins->dreg, fp);
+
+                       if (spec [MONO_INST_DEST] == 'a')
+                               dest_mask = (1 << AMD64_RAX);
+
                        if (spec [MONO_INST_DEST] == 'l') {
                                /* check special case when dreg have been moved 
from ecx (clob shift) */
                                if (spec [MONO_INST_CLOB] == 's' && clob_dreg 
!= -1)
@@ -2535,14 +2610,14 @@
                                        /* the register gets spilled after this 
inst */
                                        spill = -val -1;
                                }
-                               val = mono_amd64_alloc_int_reg (cfg, tmp, ins, 
dest_mask, ins->dreg, reginfo [ins->dreg].flags);
-                               rs->iassign [ins->dreg] = val;
+                               val = alloc_reg (cfg, tmp, ins, fp ? 
MONO_ARCH_CALLEE_FREGS : dest_mask, ins->dreg, reginfo [ins->dreg].flags, fp);
+                               assign_reg (rs, ins->dreg, val, fp);
                                if (spill)
-                                       create_spilled_store (cfg, spill, val, 
prev_dreg, ins, FALSE);
+                                       create_spilled_store (cfg, spill, val, 
prev_dreg, ins, fp);
                        }
-                       DEBUG (g_print ("\tassigned dreg %s to dest R%d\n", 
mono_arch_regname (val), ins->dreg));
-                       rs->isymbolic [val] = prev_dreg;
+                       DEBUG (g_print ("\tassigned dreg %s to dest R%d\n", 
mono_amd64_regname (val, fp), ins->dreg));
                        ins->dreg = val;
+
                        /* handle cases where lreg needs to be eax:edx */
                        if (spec [MONO_INST_DEST] == 'l') {
                                /* check special case when dreg have been moved 
from ecx (clob shift) */
@@ -2554,12 +2629,12 @@
                                                /* the register gets spilled 
after this inst */
                                                spill = -val -1;
                                        }
-                                       val = mono_amd64_alloc_int_reg (cfg, 
tmp, ins, dest_mask, hreg, reginfo [hreg].flags);
+                                       val = alloc_int_reg (cfg, tmp, ins, 
dest_mask, hreg, reginfo [hreg].flags);
                                        rs->iassign [hreg] = val;
                                        if (spill)
-                                               create_spilled_store (cfg, 
spill, val, hreg, ins, FALSE);
+                                               create_spilled_store (cfg, 
spill, val, hreg, ins, fp);
                                }
-                               DEBUG (g_print ("\tassigned hreg %s to dest 
R%d\n", mono_arch_regname (val), hreg));
+                               DEBUG (g_print ("\tassigned hreg %s to dest 
R%d\n", mono_amd64_regname (val,fp), hreg));
                                rs->isymbolic [val] = hreg;
                                if (ins->dreg == AMD64_RAX) {
                                        if (val != AMD64_RDX)
@@ -2603,8 +2678,90 @@
                        mono_regstate_free_int (rs, ins->dreg);
                }
 
-               /* put src1 in EAX if it needs to be */
+               if (spec [MONO_INST_CLOB] == 'c') {
+                       int j, s, dreg;
+                       MonoCallInst *call = (MonoCallInst*)ins;
+                       GSList *list;
+                       guint32 clob_mask;
+
+                       clob_mask = AMD64_CALLEE_REGS;
+                       dreg = dreg_is_fp (ins) ? -1 : ins->dreg;
+
+                       for (j = 0; j < MONO_MAX_IREGS; ++j) {
+                               s = 1 << j;
+                               if ((clob_mask & s) && !(rs->ifree_mask & s) && 
(j != ins->sreg1) && (j != dreg)) {
+                                       get_register_force_spilling (cfg, tmp, 
ins, rs->isymbolic [j], FALSE);
+                                       mono_regstate_free_int (rs, j);
+                               }
+                       }
+
+                       if (use_sse2) {
+                               clob_mask = AMD64_CALLEE_FREGS;
+                               dreg = dreg_is_fp (ins) ? ins->dreg : -1;
+
+                               for (j = 0; j < MONO_MAX_FREGS; ++j) {
+                                       s = 1 << 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);
+                                       }
+                               }
+                       }
+
+                       /* 
+                        * This needs to be done before assigning sreg1, so 
sreg1 will
+                        * not be assigned one of the argument regs.
+                        */
+
+                       /* 
+                        * Assign all registers in call->out_reg_args to the 
proper 
+                        * argument registers.
+                        */
+
+                       list = call->out_ireg_args;
+                       if (list) {
+                               while (list) {
+                                       guint64 regpair;
+                                       int reg, hreg;
+
+                                       regpair = (guint64) (list->data);
+                                       hreg = regpair >> 32;
+                                       reg = regpair & 0xffffffff;
+
+                                       assign_reg (rs, reg, hreg, FALSE);
+
+                                       DEBUG (g_print ("\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;
+                       if (list && use_sse2) {
+                               while (list) {
+                                       guint64 regpair;
+                                       int reg, hreg;
+
+                                       regpair = (guint64) (list->data);
+                                       hreg = regpair >> 32;
+                                       reg = regpair & 0xffffffff;
+
+                                       assign_reg (rs, reg, hreg, TRUE);
+
+                                       DEBUG (g_print ("\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);
+               }
+
                if (spec [MONO_INST_SRC1] == 'a') {
+                       sreg1_fixed = AMD64_RAX;
+                       src1_mask = 1 << AMD64_RAX;
+
                        if (!(rs->ifree_mask & (1 << AMD64_RAX))) {
                                DEBUG (g_print ("\tforced spill of R%d\n", 
rs->isymbolic [AMD64_RAX]));
                                get_register_force_spilling (cfg, tmp, ins, 
rs->isymbolic [AMD64_RAX], FALSE);
@@ -2615,62 +2772,27 @@
                                MonoInst *copy = create_copy_ins (cfg, 
AMD64_RAX, ins->sreg1, NULL, FALSE);
                                insert_before_ins (ins, tmp, copy);
                        }
-                       else
+                       else {
+                               val = rs->iassign [ins->sreg1];
+                               g_assert (rs->iassign [ins->sreg1] <= -1);
+                               if (val < -1) {
+                                       int spill = -val -1;
+
+                                       MonoInst *store = create_spilled_store 
(cfg, spill, AMD64_RAX, ins->sreg1, NULL, FALSE);
+                                       insert_before_ins (ins, tmp, store);
+                               }
+
                                /* force-set sreg1 */
                                assign_ireg (rs, ins->sreg1, AMD64_RAX);
+                       }
                        ins->sreg1 = AMD64_RAX;
                }
 
                /*
                 * TRACK SREG1
                 */
-               if (spec [MONO_INST_SRC1] == 'f') {
-                       if (use_sse2) {
-                               if (reg_is_soft (ins->sreg1, TRUE)) {
-                                       val = rs->fassign [ins->sreg1];
-                                       prev_sreg1 = ins->sreg1;
-                                       if (val < 0) {
-                                               int spill = 0;
-                                               if (val < -1) {
-                                                       /* the register gets 
spilled after this inst */
-                                                       spill = -val -1;
-                                               }
-                                               val = 
mono_amd64_alloc_float_reg (cfg, tmp, ins, AMD64_CALLEE_FREGS, ins->sreg1);
-                                               rs->fassign [ins->sreg1] = val;
-                                               DEBUG (g_print ("\tassigned 
sreg1 %s to R%d\n", mono_arch_fregname (val), ins->sreg1));
-                                               if (spill) {
-                                                       MonoInst *store = 
create_spilled_store (cfg, spill, val, prev_sreg1, NULL, TRUE);
-                                                       insert_before_ins (ins, 
tmp, store);
-                                               }
-                                       }
-                                       rs->fsymbolic [val] = prev_sreg1;
-                                       ins->sreg1 = val;
-                               } else {
-                                       prev_sreg1 = -1;
-                               }
-                       }
-                       else
-                               if (reginfof [ins->sreg1].flags & 
MONO_X86_FP_NEEDS_LOAD) {
-                               MonoInst *load;
-                               MonoInst *store = NULL;
-
-                               if (reginfof [ins->sreg1].flags & 
MONO_X86_FP_NEEDS_LOAD_SPILL) {
-                                       GList *spill_node;
-                                       spill_node = g_list_first (fspill_list);
-                                       g_assert (spill_node);
-
-                                       store = create_spilled_store_float 
(cfg, GPOINTER_TO_INT (spill_node->data), ins->sreg1, ins);          
-                                       fspill_list = g_list_remove 
(fspill_list, spill_node->data);
-                               }
-
-                               fspill++;
-                               fspill_list = g_list_prepend (fspill_list, 
GINT_TO_POINTER(fspill));
-                               load = create_spilled_load_float (cfg, fspill, 
ins->sreg1, ins);
-                               insert_before_ins (ins, tmp, load);
-                               if (store) 
-                                       insert_before_ins (load, tmp, store);
-                       }
-               } else if ((spec [MONO_INST_DEST] == 'L') && (spec 
[MONO_INST_SRC1] == 'L')) {
+               fp = sreg1_is_fp (ins);
+               if ((spec [MONO_INST_DEST] == 'L') && (spec [MONO_INST_SRC1] == 
'L')) {
                        /* force source to be same as dest */
                        rs->iassign [ins->sreg1] = ins->dreg;
                        rs->iassign [ins->sreg1 + 1] = ins->unused;
@@ -2688,8 +2810,8 @@
                        rs->ifree_mask &= ~ (1 << ins->dreg);
                        rs->ifree_mask &= ~ (1 << ins->unused);
                }
-               else if (ins->sreg1 >= MONO_MAX_IREGS) {
-                       val = rs->iassign [ins->sreg1];
+               else if ((!fp || (fp && use_sse2)) && (is_soft_reg (ins->sreg1, 
fp))) {
+                       val = rassign (cfg, ins->sreg1, fp);
                        prev_sreg1 = ins->sreg1;
                        if (val < 0) {
                                int spill = 0;
@@ -2697,33 +2819,24 @@
                                        /* the register gets spilled after this 
inst */
                                        spill = -val -1;
                                }
-                               if (0 && (ins->opcode == OP_MOVE)) {
-                                       /* 
-                                        * small optimization: the dest 
register is already allocated
-                                        * but the src one is not: we can 
simply assign the same register
-                                        * here and peephole will get rid of 
the instruction later.
-                                        * This optimization may interfere with 
the clobbering handling:
-                                        * it removes a mov operation that will 
be added again to handle clobbering.
-                                        * There are also some other issues 
that should with make testjit.
-                                        */
-                                       mono_regstate_alloc_int (rs, 1 << 
ins->dreg);
-                                       val = rs->iassign [ins->sreg1] = 
ins->dreg;
-                                       //g_assert (val >= 0);
-                                       DEBUG (g_print ("\tfast assigned sreg1 
%s to R%d\n", mono_arch_regname (val), ins->sreg1));
-                               } else {
-                                       //g_assert (val == -1); /* source 
cannot be spilled */
-                                       val = mono_amd64_alloc_int_reg (cfg, 
tmp, ins, src1_mask, ins->sreg1, reginfo [ins->sreg1].flags);
-                                       rs->iassign [ins->sreg1] = val;
-                                       DEBUG (g_print ("\tassigned sreg1 %s to 
R%d\n", mono_arch_regname (val), ins->sreg1));
-                               }
+
+                               val = alloc_reg (cfg, tmp, ins, fp ? 
AMD64_CALLEE_FREGS : src1_mask, ins->sreg1, reginfo [ins->sreg1].flags, fp);
+                               assign_reg (rs, ins->sreg1, val, fp);
+                               DEBUG (g_print ("\tassigned sreg1 %s to R%d\n", 
mono_amd64_regname (val, fp), ins->sreg1));
+
                                if (spill) {
-                                       MonoInst *store = create_spilled_store 
(cfg, spill, val, prev_sreg1, NULL, FALSE);
+                                       MonoInst *store = create_spilled_store 
(cfg, spill, val, prev_sreg1, NULL, fp);
+                                       /*
+                                        * Need to insert before the 
instruction since it can
+                                        * overwrite sreg1.
+                                        */
                                        insert_before_ins (ins, tmp, store);
                                }
                        }
-                       rs->isymbolic [val] = prev_sreg1;
+
                        ins->sreg1 = val;
-               } else {
+               }
+               else {
                        prev_sreg1 = -1;
                }
 
@@ -2738,13 +2851,8 @@
                                 * copying sreg1 to dreg could clobber sreg2, 
so allocate a new
                                 * register for it.
                                 */
-                               int reg2 = 0;
+                               int reg2 = alloc_reg (cfg, tmp, ins, fp ? 
MONO_ARCH_CALLEE_FREGS : dest_mask, ins->sreg2, 0, fp);
 
-                               if (fp)
-                                       reg2 = mono_amd64_alloc_float_reg (cfg, 
tmp, ins, AMD64_CALLEE_FREGS, ins->sreg2);
-                               else
-                                       reg2 = mono_amd64_alloc_int_reg (cfg, 
tmp, ins, dest_mask, ins->sreg2, 0);
-
                                DEBUG (g_print ("\tneed to copy sreg2 %s to reg 
%s\n", mono_amd64_regname (ins->sreg2, fp), mono_amd64_regname (reg2, fp)));
                                sreg2_copy = create_copy_ins (cfg, reg2, 
ins->sreg2, NULL, fp);
                                prev_sreg2 = ins->sreg2 = reg2;
@@ -2775,151 +2883,31 @@
                /*
                 * TRACK SREG2
                 */
-               if (spec [MONO_INST_SRC2] == 'f') {
-                       if (use_sse2) {
-                               if (reg_is_soft (ins->sreg2, TRUE)) {
-                                       val = rs->fassign [ins->sreg2];
-                                       prev_sreg2 = ins->sreg2;
-                                       if (val < 0) {
-                                               int spill = 0;
-                                               if (val < -1) {
-                                                       /* the register gets 
spilled after this inst */
-                                                       spill = -val -1;
-                                               }
-                                               val = 
mono_amd64_alloc_float_reg (cfg, tmp, ins, AMD64_CALLEE_FREGS, ins->sreg2);
-                                               rs->fassign [ins->sreg2] = val;
-                                               DEBUG (g_print ("\tassigned 
sreg2 %s to R%d\n", mono_arch_fregname (val), ins->sreg2));
-                                               if (spill)
-                                                       create_spilled_store 
(cfg, spill, val, prev_sreg2, ins, TRUE);
-                                       }
-                                       rs->fsymbolic [val] = prev_sreg2;
-                                       ins->sreg2 = val;
-                               } else {
-                                       prev_sreg2 = -1;
-                               }
-                       }
-                       else
-                       if (reginfof [ins->sreg2].flags & 
MONO_X86_FP_NEEDS_LOAD) {
-                               MonoInst *load;
-                               MonoInst *store = NULL;
+               fp = sreg2_is_fp (ins);
+               if ((!fp || (fp && use_sse2)) && (is_soft_reg (ins->sreg2, 
fp))) {
+                       val = rassign (cfg, ins->sreg2, fp);
 
-                               if (reginfof [ins->sreg2].flags & 
MONO_X86_FP_NEEDS_LOAD_SPILL) {
-                                       GList *spill_node;
-
-                                       spill_node = g_list_first (fspill_list);
-                                       g_assert (spill_node);
-                                       if (spec [MONO_INST_SRC1] == 'f' && 
(reginfof [ins->sreg1].flags & MONO_X86_FP_NEEDS_LOAD_SPILL))
-                                               spill_node = g_list_next 
(spill_node);
-       
-                                       store = create_spilled_store_float 
(cfg, GPOINTER_TO_INT (spill_node->data), ins->sreg2, ins);
-                                       fspill_list = g_list_remove 
(fspill_list, spill_node->data);
-                               } 
-                               
-                               fspill++;
-                               fspill_list = g_list_prepend (fspill_list, 
GINT_TO_POINTER(fspill));
-                               load = create_spilled_load_float (cfg, fspill, 
ins->sreg2, ins);
-                               insert_before_ins (ins, tmp, load);
-                               if (store) 
-                                       insert_before_ins (load, tmp, store);
-                       }
-               } 
-               else if (ins->sreg2 >= MONO_MAX_IREGS) {
-                       val = rs->iassign [ins->sreg2];
-                       prev_sreg2 = ins->sreg2;
                        if (val < 0) {
                                int spill = 0;
                                if (val < -1) {
                                        /* the register gets spilled after this 
inst */
                                        spill = -val -1;
                                }
-                               val = mono_amd64_alloc_int_reg (cfg, tmp, ins, 
src2_mask, ins->sreg2, reginfo [ins->sreg2].flags);
-                               rs->iassign [ins->sreg2] = val;
-                               DEBUG (g_print ("\tassigned sreg2 %s to R%d\n", 
mono_arch_regname (val), ins->sreg2));
+                               val = alloc_reg (cfg, tmp, ins, fp ? 
MONO_ARCH_CALLEE_FREGS : src2_mask, ins->sreg2, reginfo [ins->sreg2].flags, fp);
+                               assign_reg (rs, ins->sreg2, val, fp);
+                               DEBUG (g_print ("\tassigned sreg2 %s to R%d\n", 
mono_amd64_regname (val, fp), ins->sreg2));
                                if (spill)
-                                       create_spilled_store (cfg, spill, val, 
prev_sreg2, ins, FALSE);
+                                       create_spilled_store (cfg, spill, val, 
prev_sreg2, ins, fp);
                        }
-                       rs->isymbolic [val] = prev_sreg2;
                        ins->sreg2 = val;
                        if (spec [MONO_INST_CLOB] == 's' && ins->sreg2 != 
AMD64_RCX) {
                                DEBUG (g_print ("\tassigned sreg2 %s to R%d, 
but ECX is needed (R%d)\n", mono_arch_regname (val), ins->sreg2, rs->iassign 
[AMD64_RCX]));
                        }
-               } else {
+               }
+               else {
                        prev_sreg2 = -1;
                }
 
-               if (spec [MONO_INST_CLOB] == 'c') {
-                       int j, s;
-                       MonoCallInst *call = (MonoCallInst*)ins;
-                       GSList *list;
-                       guint32 clob_mask = AMD64_CALLEE_REGS;
-
-                       for (j = 0; j < MONO_MAX_IREGS; ++j) {
-                               s = 1 << j;
-                               if ((clob_mask & s) && !(rs->ifree_mask & s) && 
j != ins->sreg1) {
-                                       get_register_force_spilling (cfg, tmp, 
ins, rs->isymbolic [j], FALSE);
-                                       mono_regstate_free_int (rs, j);
-                                       //g_warning ("register %s busy at call 
site\n", mono_arch_regname (j));
-                               }
-                       }
-
-                       if (use_sse2) {
-                               clob_mask = AMD64_CALLEE_FREGS;
-
-                               for (j = 0; j < MONO_MAX_FREGS; ++j) {
-                                       s = 1 << j;
-                                       if ((clob_mask & s) && !(rs->ffree_mask 
& s) && j != ins->sreg1) {
-                                               get_register_force_spilling 
(cfg, tmp, ins, rs->fsymbolic [j], TRUE);
-                                               mono_regstate_free_float (rs, 
j);
-                                               //g_warning ("register %s busy 
at call site\n", mono_arch_regname (j));
-                                       }
-                               }
-                       }
-
-                       /* 
-                        * Assign all registers in call->out_reg_args to the 
proper 
-                        * argument registers.
-                        */
-
-                       list = call->out_ireg_args;
-                       if (list) {
-                               while (list) {
-                                       guint64 regpair;
-                                       int reg, hreg;
-
-                                       regpair = (guint64) (list->data);
-                                       hreg = regpair >> 32;
-                                       reg = regpair & 0xffffffff;
-
-                                       assign_ireg (rs, reg, hreg);
-
-                                       DEBUG (g_print ("\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;
-                       if (list && use_sse2) {
-                               while (list) {
-                                       guint64 regpair;
-                                       int reg, hreg;
-
-                                       regpair = (guint64) (list->data);
-                                       hreg = regpair >> 32;
-                                       reg = regpair & 0xffffffff;
-
-                                       rs->fassign [reg] = hreg;
-                                       rs->fsymbolic [hreg] = reg;
-                                       rs->ffree_mask &= ~ (1 << hreg);
-
-                                       list = g_slist_next (list);
-                               }
-                       }
-                       if (call->out_freg_args)
-                               g_slist_free (call->out_freg_args);
-               }
-
                /*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);
@@ -5892,7 +5880,7 @@
 
                lmf_tls_offset = read_tls_offset_from_method 
(mono_get_lmf_addr);
                appdomain_tls_offset = read_tls_offset_from_method 
(mono_domain_get);
-               //thread_tls_offset = read_tls_offset_from_method 
(mono_thread_current);
+               thread_tls_offset = read_tls_offset_from_method 
(mono_thread_current);
        }               
 
 #ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK

Modified: branches/vargaz/mini-xp-local-regalloc/mono/mono/mini/mini.c
===================================================================
--- branches/vargaz/mini-xp-local-regalloc/mono/mono/mini/mini.c        
2005-03-15 19:57:20 UTC (rev 41850)
+++ branches/vargaz/mini-xp-local-regalloc/mono/mono/mini/mini.c        
2005-03-15 20:01:54 UTC (rev 41851)
@@ -4744,6 +4744,8 @@
 
                        }
                        else {
+                               handle_loaded_temps (cfg, bblock, stack_start, 
sp);
+
                                MONO_INST_NEW (cfg, ins, *ip);
                                ins->type = STACK_OBJ;
                                ins->inst_left = *sp;
@@ -4799,6 +4801,8 @@
                                        inline_costs += costs;                  
        
                                }
                                else {
+                                       handle_loaded_temps (cfg, bblock, 
stack_start, sp);
+
                                        MONO_INST_NEW (cfg, ins, CEE_CASTCLASS);
                                        ins->type = STACK_OBJ;
                                        ins->inst_left = *sp;
@@ -4928,6 +4932,8 @@
                                inline_costs += costs;
                        }
                        else {
+                               handle_loaded_temps (cfg, bblock, stack_start, 
sp);
+
                                MONO_INST_NEW (cfg, ins, *ip);
                                ins->type = STACK_OBJ;
                                ins->inst_left = *sp;
@@ -5939,6 +5945,7 @@
                        case CEE_MONO_CCASTCLASS: {
                                int token;
                                CHECK_STACK (1);
+                               handle_loaded_temps (cfg, bblock, stack_start, 
sp);
                                --sp;
                                CHECK_OPSIZE (6);
                                token = read32 (ip + 2);
@@ -6545,7 +6552,10 @@
                        printf ("[0x%x(%s)]", (int)(tree->inst_offset), 
mono_arch_regname (tree->inst_basereg));
                break;
        case OP_REGVAR:
-               printf ("[%s]", mono_arch_regname (tree->dreg));
+               if (tree->dreg >= MONO_MAX_IREGS)
+                       printf ("[R%d]", tree->dreg);
+               else
+                       printf ("[%s]", mono_arch_regname (tree->dreg));
                break;
        case CEE_NEWARR:
                printf ("[%s]",  tree->inst_newa_class->name);
@@ -8335,9 +8345,9 @@
 mini_select_instructions (MonoCompile *cfg)
 {
        MonoBasicBlock *bb;
+       int first_vireg, first_vfreg;
        
        cfg->state_pool = mono_mempool_new ();
-       cfg->rs = mono_regstate_new ();
 
        for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
                if (bb->last_ins && MONO_IS_COND_BRANCH_OP (bb->last_ins) &&
@@ -8376,6 +8386,9 @@
        }
 #endif
 
+       first_vireg = cfg->rs->next_vireg;
+       first_vfreg = cfg->rs->next_vfreg;
+
        for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
                MonoInst *tree = bb->code, *next;       
                MBState *mbstate;
@@ -8386,8 +8399,11 @@
                bb->last_ins = NULL;
                
                cfg->cbb = bb;
-               mono_regstate_reset (cfg->rs);
 
+               /* Reset regstate */
+               cfg->rs->next_vireg = first_vireg;
+               cfg->rs->next_vfreg = first_vfreg;
+
 #ifdef DEBUG_SELECTION
                if (cfg->verbose_level >= 3)
                        g_print ("LABEL BLOCK %d:\n", bb->block_num);
@@ -9064,6 +9080,8 @@
                g_list_free (regs);
        }
 
+       cfg->rs = mono_regstate_new ();
+
        if (cfg->opt & MONO_OPT_LINEARS) {
                GList *vars, *regs;
 

_______________________________________________
Mono-patches maillist  -  [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches

Reply via email to