dotgnu-pnet-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[dotgnu-pnet-commits] libjit ChangeLog tools/gen-rules-parser.y jit/j...


From: Aleksey Demakov
Subject: [dotgnu-pnet-commits] libjit ChangeLog tools/gen-rules-parser.y jit/j...
Date: Wed, 17 Jan 2007 07:38:47 +0000

CVSROOT:        /sources/dotgnu-pnet
Module name:    libjit
Changes by:     Aleksey Demakov <avd>   07/01/17 07:38:47

Modified files:
        .              : ChangeLog 
        tools          : gen-rules-parser.y 
        jit            : jit-rules-x86.ins jit-reg-alloc.h 
                         jit-reg-alloc.c 

Log message:
        complete regalloc support for x87

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/libjit/ChangeLog?cvsroot=dotgnu-pnet&r1=1.293&r2=1.294
http://cvs.savannah.gnu.org/viewcvs/libjit/tools/gen-rules-parser.y?cvsroot=dotgnu-pnet&r1=1.13&r2=1.14
http://cvs.savannah.gnu.org/viewcvs/libjit/jit/jit-rules-x86.ins?cvsroot=dotgnu-pnet&r1=1.27&r2=1.28
http://cvs.savannah.gnu.org/viewcvs/libjit/jit/jit-reg-alloc.h?cvsroot=dotgnu-pnet&r1=1.20&r2=1.21
http://cvs.savannah.gnu.org/viewcvs/libjit/jit/jit-reg-alloc.c?cvsroot=dotgnu-pnet&r1=1.49&r2=1.50

Patches:
Index: ChangeLog
===================================================================
RCS file: /sources/dotgnu-pnet/libjit/ChangeLog,v
retrieving revision 1.293
retrieving revision 1.294
diff -u -b -r1.293 -r1.294
--- ChangeLog   12 Jan 2007 18:28:53 -0000      1.293
+++ ChangeLog   17 Jan 2007 07:38:47 -0000      1.294
@@ -1,7 +1,17 @@
+2007-01-17  Aleksey Demakov  <address@hidden>
+
+       * jit/jit-reg-alloc.h, jit/jit-reg-alloc.c: complete special x87
+       arithmetic support, for other x87 instructions reverse the order of
+       arguments on the stack.
+
+       * jit/jit-rules-x86.ins: take advantage of regalloc's x87 arithmetic
+       support. Also do not clobber the entire x87 stack for atan, sin, and
+       cos rules.
+
 2007-01-12  Heiko Weiss <address@hidden>
 
-       * jit/jit-function.c: Fix a typo in jit_function_from_vtable_pointer 
which
-       breaks the build if libjit is built in interpreter mode.
+       * jit/jit-function.c: Fix a typo in jit_function_from_vtable_pointer
+       which breaks the build if libjit is built in interpreter mode.
 
 2007-01-04  Thomas Cort  <address@hidden>
 

Index: tools/gen-rules-parser.y
===================================================================
RCS file: /sources/dotgnu-pnet/libjit/tools/gen-rules-parser.y,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -b -r1.13 -r1.14
--- tools/gen-rules-parser.y    29 Dec 2006 23:16:15 -0000      1.13
+++ tools/gen-rules-parser.y    17 Jan 2007 07:38:47 -0000      1.14
@@ -1239,7 +1239,7 @@
                                {
                                        seen_option = 1;
                                }
-                               printf("_JIT_REGS_X87_ARITH_REVERSIBLE");
+                               printf("_JIT_REGS_X87_ARITH | 
_JIT_REGS_REVERSIBLE");
                        }
                        if(!seen_option)
                        {

Index: jit/jit-rules-x86.ins
===================================================================
RCS file: /sources/dotgnu-pnet/libjit/jit/jit-rules-x86.ins,v
retrieving revision 1.27
retrieving revision 1.28
diff -u -b -r1.27 -r1.28
--- jit/jit-rules-x86.ins       2 Jan 2007 17:00:18 -0000       1.27
+++ jit/jit-rules-x86.ins       17 Jan 2007 07:38:47 -0000      1.28
@@ -749,30 +749,146 @@
 #endif
        }
 
-JIT_OP_FADD, JIT_OP_DADD, JIT_OP_NFADD: stack
+JIT_OP_FADD, JIT_OP_DADD, JIT_OP_NFADD: stack, x87_arith, commutative
        [freg, freg] -> {
-               x86_fp_op_reg(inst, X86_FADD, 1, 1);
+               int flags;
+
+               flags = _jit_regs_select(&regs);
+
+               if((flags & _JIT_REGS_NO_POP) == 0)
+               {
+                       x86_fp_op_reg(inst, X86_FADD,
+                               fp_stack_index(gen, $1 + JIT_REG_STACK_START), 
1);
+               }
+               else if((flags & _JIT_REGS_FLIP_ARGS) != 0)
+               {
+                       x86_fp_op_reg(inst, X86_FADD,
+                               fp_stack_index(gen, $1 + JIT_REG_STACK_START), 
0);
+               }
+               else
+               {
+                       x86_fp_op(inst, X86_FADD,
+                               fp_stack_index(gen, $2 + JIT_REG_STACK_START));
+               }
        }
 
-JIT_OP_FSUB, JIT_OP_DSUB, JIT_OP_NFSUB: stack
+JIT_OP_FSUB, JIT_OP_DSUB, JIT_OP_NFSUB: stack, x87_arith_reversible
        [freg, freg] -> {
-               x86_fp_op_reg(inst, X86_FSUB, 1, 1);
+               int flags;
+
+               flags = _jit_regs_select(&regs);
+
+               if((flags & _JIT_REGS_NO_POP) == 0)
+               {
+                       if((flags & _JIT_REGS_REVERSE) == 0)
+                       {
+                               x86_fp_op_reg(inst, X86_FSUB,
+                                       fp_stack_index(gen, $1 + 
JIT_REG_STACK_START), 1);
+                       }
+                       else
+                       {
+                               x86_fp_op_reg(inst, X86_FSUBR,
+                                       fp_stack_index(gen, $2 + 
JIT_REG_STACK_START), 1);
+                       }
+               }
+               else if((flags & _JIT_REGS_FLIP_ARGS) != 0)
+               {
+                       if((flags & _JIT_REGS_REVERSE) == 0)
+                       {
+                               x86_fp_op_reg(inst, X86_FSUB,
+                                       fp_stack_index(gen, $1 + 
JIT_REG_STACK_START), 0);
+                       }
+                       else
+                       {
+                               x86_fp_op(inst, X86_FSUBR,
+                                       fp_stack_index(gen, $1 + 
JIT_REG_STACK_START));
+                       }
+               }
+               else
+               {
+                       if((flags & _JIT_REGS_REVERSE) == 0)
+                       {
+                               x86_fp_op(inst, X86_FSUB,
+                                       fp_stack_index(gen, $2 + 
JIT_REG_STACK_START));
+                       }
+                       else
+                       {
+                               x86_fp_op_reg(inst, X86_FSUBR,
+                                       fp_stack_index(gen, $2 + 
JIT_REG_STACK_START), 0);
+                       }
+               }
        }
 
-JIT_OP_FMUL, JIT_OP_DMUL, JIT_OP_NFMUL: stack
+JIT_OP_FMUL, JIT_OP_DMUL, JIT_OP_NFMUL: stack, x87_arith, commutative
        [freg, freg] -> {
-               x86_fp_op_reg(inst, X86_FMUL, 1, 1);
+               int flags;
+
+               flags = _jit_regs_select(&regs);
+
+               if((flags & _JIT_REGS_NO_POP) == 0)
+               {
+                       x86_fp_op_reg(inst, X86_FMUL, fp_stack_index(gen, $1 + 
JIT_REG_STACK_START), 1);
+               }
+               else if((flags & _JIT_REGS_FLIP_ARGS) != 0)
+               {
+                       x86_fp_op_reg(inst, X86_FMUL, fp_stack_index(gen, $1 + 
JIT_REG_STACK_START), 0);
+               }
+               else
+               {
+                       x86_fp_op(inst, X86_FMUL, fp_stack_index(gen, $2 + 
JIT_REG_STACK_START));
+               }
        }
 
-JIT_OP_FDIV, JIT_OP_DDIV, JIT_OP_NFDIV: stack
+JIT_OP_FDIV, JIT_OP_DDIV, JIT_OP_NFDIV: stack, x87_arith_reversible
        [freg, freg] -> {
-               x86_fp_op_reg(inst, X86_FDIV, 1, 1);
+               int flags;
+
+               flags = _jit_regs_select(&regs);
+
+               if((flags & _JIT_REGS_NO_POP) == 0)
+               {
+                       if((flags & _JIT_REGS_REVERSE) == 0)
+                       {
+                               x86_fp_op_reg(inst, X86_FDIV,
+                                       fp_stack_index(gen, $1 + 
JIT_REG_STACK_START), 1);
+                       }
+                       else
+                       {
+                               x86_fp_op_reg(inst, X86_FDIVR,
+                                       fp_stack_index(gen, $2 + 
JIT_REG_STACK_START), 1);
+                       }
+               }
+               else if((flags & _JIT_REGS_FLIP_ARGS) != 0)
+               {
+                       if((flags & _JIT_REGS_REVERSE) == 0)
+                       {
+                               x86_fp_op_reg(inst, X86_FDIV,
+                                       fp_stack_index(gen, $1 + 
JIT_REG_STACK_START), 0);
+                       }
+                       else
+                       {
+                               x86_fp_op(inst, X86_FDIVR,
+                                       fp_stack_index(gen, $1 + 
JIT_REG_STACK_START));
+                       }
+               }
+               else
+               {
+                       if((flags & _JIT_REGS_REVERSE) == 0)
+                       {
+                               x86_fp_op(inst, X86_FDIV,
+                                       fp_stack_index(gen, $2 + 
JIT_REG_STACK_START));
+                       }
+                       else
+                       {
+                               x86_fp_op_reg(inst, X86_FDIVR,
+                                       fp_stack_index(gen, $2 + 
JIT_REG_STACK_START), 0);
+                       }
+               }
        }
 
 JIT_OP_FREM, JIT_OP_DREM, JIT_OP_NFREM: stack
        [freg, freg, scratch reg("eax")] -> {
                unsigned char *label;
-               x86_fxch(inst, 1);
                label = inst;
                x86_fprem(inst);
                x86_fnstsw(inst);
@@ -1232,7 +1348,7 @@
  */
 
 JIT_OP_FATAN, JIT_OP_DATAN, JIT_OP_NFATAN: stack
-       [freg, clobber(freg)] -> {
+       [freg, scratch freg] -> {
                x86_fld1(inst);
                x86_fpatan(inst);
                x86_fldz(inst);
@@ -1240,14 +1356,14 @@
        }
 
 JIT_OP_FCOS, JIT_OP_DCOS, JIT_OP_NFCOS: stack
-       [freg, clobber(freg)] -> {
+       [freg, scratch freg] -> {
                x86_fcos(inst);
                x86_fldz(inst);
                x86_fp_op_reg(inst, X86_FADD, 1, 1);
        }
 
 JIT_OP_FSIN, JIT_OP_DSIN, JIT_OP_NFSIN: stack
-       [freg, clobber(freg)] -> {
+       [freg, scratch freg] -> {
                x86_fsin(inst);
                x86_fldz(inst);
                x86_fp_op_reg(inst, X86_FADD, 1, 1);
@@ -2073,7 +2189,7 @@
                x86_mov_membase_reg(inst, $1, $3 + 4, %2, 4);
        }
 
-JIT_OP_STORE_RELATIVE_FLOAT32: ternary
+JIT_OP_STORE_RELATIVE_FLOAT32: ternary, stack
        [reg, imm, imm] -> {
                x86_mov_membase_imm(inst, $1, $3, ((int *)($2))[0], 4);
        }
@@ -2081,7 +2197,7 @@
                x86_fst_membase(inst, $1, $3, 0, 1);
        }
 
-JIT_OP_STORE_RELATIVE_FLOAT64: ternary
+JIT_OP_STORE_RELATIVE_FLOAT64: ternary, stack
        [reg, imm, imm] -> {
                x86_mov_membase_imm(inst, $1, $3, ((int *)($2))[0], 4);
                x86_mov_membase_imm(inst, $1, $3 + 4, ((int *)($2))[1], 4);
@@ -2090,7 +2206,7 @@
                x86_fst_membase(inst, $1, $3, 1, 1);
        }
 
-JIT_OP_STORE_RELATIVE_NFLOAT: ternary
+JIT_OP_STORE_RELATIVE_NFLOAT: ternary, stack
        [reg, imm, imm] -> {
                x86_mov_membase_imm(inst, $1, $3, ((int *)($2))[0], 4);
                x86_mov_membase_imm(inst, $1, $3 + 4, ((int *)($2))[1], 4);
@@ -2235,17 +2351,17 @@
                x86_mov_memindex_reg(inst, $1, 4, $2, 3, %3, 4);
        }
 
-JIT_OP_STORE_ELEMENT_FLOAT32: ternary
+JIT_OP_STORE_ELEMENT_FLOAT32: ternary, stack
        [reg, reg, freg] -> {
                x86_fst_memindex(inst, $1, 0, $2, 2, 0, 1);
        }
 
-JIT_OP_STORE_ELEMENT_FLOAT64: ternary
+JIT_OP_STORE_ELEMENT_FLOAT64: ternary, stack
        [reg, reg, freg] -> {
                x86_fst_memindex(inst, $1, 0, $2, 3, 1, 1);
        }
 
-JIT_OP_STORE_ELEMENT_NFLOAT: ternary
+JIT_OP_STORE_ELEMENT_NFLOAT: ternary, stack
        [reg, +reg, freg, if("sizeof(jit_nfloat) != sizeof(jit_float64)")] -> {
                /* lea reg2, [reg2 + reg2 * 2]  */
                x86_lea_memindex(inst, $2, $2, 0, $2, 1);

Index: jit/jit-reg-alloc.h
===================================================================
RCS file: /sources/dotgnu-pnet/libjit/jit/jit-reg-alloc.h,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -b -r1.20 -r1.21
--- jit/jit-reg-alloc.h 29 Dec 2006 23:16:15 -0000      1.20
+++ jit/jit-reg-alloc.h 17 Jan 2007 07:38:47 -0000      1.21
@@ -61,8 +61,8 @@
  * Flags returned by _jit_regs_select_insn().
  */
 #define _JIT_REGS_NO_POP               0x0001
-#define _JIT_REGS_REVERSE_DEST         0x0002
-#define _JIT_REGS_REVERSE_ARGS         0x0004
+#define _JIT_REGS_FLIP_ARGS            0x0002
+#define _JIT_REGS_REVERSE              0x0004
 
 /*
  * Contains register assignment data for single operand.
@@ -106,8 +106,6 @@
        _jit_scratch_t  scratch[_JIT_REGS_SCRATCH_MAX];
        int             num_scratch;
 
-       unsigned        clobber_all : 1;
-
        unsigned        ternary : 1;
        unsigned        branch : 1;
        unsigned        copy : 1;
@@ -118,11 +116,9 @@
        unsigned        on_stack : 1;
        unsigned        x87_arith : 1;
        unsigned        reversible : 1;
-       unsigned        clobber_stack : 1;
 
        unsigned        no_pop : 1;
-       unsigned        reverse_dest : 1;
-       unsigned        reverse_args : 1;
+       unsigned        flip_args : 1;
 #endif
 
        /* The input value index that is going to be overwritten

Index: jit/jit-reg-alloc.c
===================================================================
RCS file: /sources/dotgnu-pnet/libjit/jit/jit-reg-alloc.c,v
retrieving revision 1.49
retrieving revision 1.50
diff -u -b -r1.49 -r1.50
--- jit/jit-reg-alloc.c 2 Jan 2007 17:00:18 -0000       1.49
+++ jit/jit-reg-alloc.c 17 Jan 2007 07:38:47 -0000      1.50
@@ -208,6 +208,14 @@
        return 0;
 }
 
+static void
+swap_values(_jit_regdesc_t *desc1, _jit_regdesc_t *desc2)
+{
+       _jit_regdesc_t tdesc;
+       tdesc = *desc1;
+       *desc1 = *desc2;
+       *desc2 = tdesc;
+}
 
 /*
  * Get value usage and liveness information. The accurate liveness data is
@@ -869,6 +877,12 @@
                        }
                }
        }
+
+       if(gen->contents[reg].is_long_start)
+       {
+               return cost * 2;
+       }
+
        if(other_reg >= 0)
        {
                for(index = 0; index < gen->contents[other_reg].num_values; 
index++)
@@ -911,6 +925,7 @@
                        }
                }
        }
+
        return cost;
 }
 
@@ -977,6 +992,10 @@
        int suitable_cost;
        int suitable_age;
 
+#ifdef JIT_REG_DEBUG
+       printf("choose_scratch_register(%d)\n", index);
+#endif
+
        regclass = regs->scratch[index].regclass;
 
        suitable_reg = -1;
@@ -990,23 +1009,20 @@
                        continue;
                }
 
-#if ALLOW_CLOBBER_GLOBAL
                if(jit_reg_is_used(gen->permanent, reg))
                {
+#if ALLOW_CLOBBER_GLOBAL
                        use_cost = COST_CLOBBER_GLOBAL;
+#else
+                       continue;
+#endif
                }
                else
                {
                        use_cost = 0;
                }
-#else
-               if(jit_reg_is_used(gen->permanent, reg))
-               {
-                       continue;
-               }
-               use_cost = 0;
-#endif
 
+#if 0
                if(regs->ternary && regs->descs[0].value
                   && thrashes_value(gen, 0, reg, -1, &regs->descs[0]))
                {
@@ -1022,13 +1038,22 @@
                {
                        use_cost += COST_THRASH;
                }
+#endif
 
+               if(!jit_reg_is_used(regs->clobber, reg))
+               {
                use_cost += compute_spill_cost(gen, regs, reg, -1);
+               }
+
+#ifdef JIT_REG_DEBUG
+               printf("reg = %d, use_cost = %d\n", reg, use_cost);
+#endif
 
                if(use_cost < suitable_cost
                   || (use_cost == suitable_cost
                       && gen->contents[reg].num_values > 0
-                      && gen->contents[reg].age < suitable_age))
+                      && (IS_STACK_REG(reg)
+                          || gen->contents[reg].age < suitable_age)))
                {
                        suitable_reg = reg;
                        suitable_cost = use_cost;
@@ -1056,6 +1081,10 @@
        int suitable_cost;
        int suitable_age;
 
+#ifdef JIT_REG_DEBUG
+       printf("choose_output_register()\n");
+#endif
+
        regclass = regs->descs[0].regclass;
        need_pair = _jit_regs_needs_long_pair(regs->descs[0].value->type);
 
@@ -1177,7 +1206,7 @@
                                        use_cost = 0;
                                }
 #ifdef JIT_REG_STACK
-                               else if(regs->x87_arith)
+                               else if(regs->reversible && regs->no_pop)
                                {
                                        use_cost = 0;
                                }
@@ -1197,7 +1226,15 @@
                        }
                }
 
+               if(!jit_reg_is_used(regs->clobber, reg)
+                  && !(other_reg >= 0 && jit_reg_is_used(regs->clobber, 
other_reg)))
+               {
                use_cost += compute_spill_cost(gen, regs, reg, other_reg);
+               }
+
+#ifdef JIT_REG_DEBUG
+               printf("reg = %d, other_reg = %d, use_cost = %d\n", reg, 
other_reg, use_cost);
+#endif
 
                if(use_cost < suitable_cost
                   || (use_cost == suitable_cost
@@ -1223,25 +1260,20 @@
 /*
  * Select the best argument order for binary ops. The posibility to select
  * the order exists only for commutative ops and for some x87 floating point
- * instructions. Those x87 instructions have variants with reversed argument
- * order or reversed destination register. Also they have variants that
- * either do or do not pop the stack top.
+ * instructions. Those x87 instructions have variants with reversed
+ * destination register.
  */
 static void
 choose_input_order(jit_gencode_t gen, _jit_regs_t *regs)
 {
-       _jit_regdesc_t temp_desc;
-
        if(regs->descs[2].value
           && regs->descs[2].value->in_register
           && regs->descs[2].value->reg == regs->descs[0].reg
           && regs->descs[2].value != regs->descs[1].value)
        {
 #ifdef JIT_REG_STACK
-               if(regs->x87_arith)
+               if(regs->reversible && regs->no_pop)
                {
-                       regs->no_pop = 1;
-                       regs->reverse_dest = 1;
                        regs->dest_input_index = 2;
                }
                else
@@ -1249,9 +1281,7 @@
                {
                        if(regs->commutative)
                        {
-                               temp_desc = regs->descs[1];
-                               regs->descs[1] = regs->descs[2];
-                               regs->descs[2] = temp_desc;
+                               swap_values(&regs->descs[1], &regs->descs[2]);
                        }
                        regs->dest_input_index = 1;
                }
@@ -1264,41 +1294,6 @@
        {
                regs->dest_input_index = 0;
        }
-
-#ifdef JIT_REG_STACK
-       /* Choose between pop and no-pop instructions. */
-       if(!regs->no_pop && regs->x87_arith
-          && !regs->clobber_all && !regs->clobber_stack
-          && regs->descs[1].value && regs->descs[2].value)
-       {
-               int keep1, keep2;
-
-               /* Determine if we might want to keep either of input values
-                  in registers after the instruction completion. */
-               if(regs->descs[1].value->in_register)
-               {
-                       keep1 = is_register_alive(gen, regs, 
regs->descs[1].value->reg);
-               }
-               else
-               {
-                       keep1 = (regs->descs[1].used
-                                && (regs->descs[1].value != 
regs->descs[0].value)
-                                && !regs->descs[1].clobber);
-               }
-               if(regs->descs[2].value->in_register)
-               {
-                       keep2 = is_register_alive(gen, regs, 
regs->descs[2].value->reg);
-               }
-               else
-               {
-                       keep2 = (regs->descs[2].used
-                                && (regs->descs[2].value != 
regs->descs[0].value)
-                                && !regs->descs[2].clobber);
-               }
-
-               regs->no_pop = (keep1 || keep2);
-       }
-#endif
 }
 
 static int
@@ -1315,6 +1310,10 @@
        int suitable_age;
        int clobber;
 
+#ifdef JIT_REG_DEBUG
+       printf("choose_input_register(%d)\n", index);
+#endif
+
        desc = &regs->descs[index];
        if(!desc->value)
        {
@@ -1410,17 +1409,17 @@
                                continue;
 #endif
                        }
-                       if(jit_reg_is_used(regs->clobber, reg)
-                          || (other_reg >= 0 && jit_reg_is_used(regs->clobber, 
other_reg)))
-                       {
-                               /* noop */
-                       }
-                       else
+                       if(!jit_reg_is_used(regs->clobber, reg)
+                          && !(other_reg >= 0 && 
jit_reg_is_used(regs->clobber, other_reg)))
                        {
                                use_cost += compute_spill_cost(gen, regs, reg, 
other_reg);
                        }
                }
 
+#ifdef JIT_REG_DEBUG
+               printf("reg = %d, other_reg = %d, use_cost = %d\n", reg, 
other_reg, use_cost);
+#endif
+
                if(use_cost < suitable_cost
                   || (use_cost == suitable_cost
                       && gen->contents[reg].num_values > 0
@@ -1465,110 +1464,215 @@
 }
 
 #ifdef JIT_REG_STACK
+
+/*
+ * For x87 instructions choose between pop and no-pop variants.
+ */
 static void
-adjust_assignment(jit_gencode_t gen, _jit_regs_t *regs, int index)
+select_nopop_or_pop(jit_gencode_t gen, _jit_regs_t *regs)
 {
-       _jit_regdesc_t *desc;
+       int keep1, keep2;
 
-       desc = &regs->descs[index];
-       if(!desc->value || !IS_STACK_REG(desc->reg))
+       if(!regs->x87_arith || !regs->descs[1].value || !regs->descs[2].value)
        {
                return;
        }
 
-       if(regs->wanted_stack_count == 1)
+       /* Equal values should be assigned to one register and this is
+          going to work only with no-pop instructions. */
+       if(are_values_equal(&regs->descs[1], &regs->descs[2]))
        {
-               /* either a unary op or a binary op with duplicate value */
-               desc->reg = gen->reg_stack_top - regs->loaded_stack_count;
+               regs->no_pop = 1;
+               return;
        }
-       else if(regs->wanted_stack_count == 2)
-       {
-               /* a binary op */
 
-               /* find the input value the output goes to */
-               if(index == 0)
+       /* Determine if we might want to keep input values in registers
+          after the instruction completion. */
+       if(regs->descs[1].value->in_register)
                {
-                       index = regs->dest_input_index;
+               keep1 = is_register_alive(gen, regs, regs->descs[1].value->reg);
                }
-
-               if(desc->value->in_register && !desc->copy && regs->x87_arith)
+       else
+       {
+               keep1 = (regs->descs[1].used
+                        && (regs->descs[1].value != regs->descs[0].value)
+                        && !regs->descs[1].clobber);
+       }
+       if(regs->descs[2].value->in_register)
                {
-                       desc->reg = desc->value->reg;
+               keep2 = is_register_alive(gen, regs, regs->descs[2].value->reg);
                }
                else
                {
-                       desc->reg = gen->reg_stack_top - 
regs->loaded_stack_count + index - 1;
-               }
+               keep2 = (regs->descs[2].used
+                        && (regs->descs[2].value != regs->descs[0].value)
+                        && !regs->descs[2].clobber);
        }
+
+       regs->no_pop = (keep1 || keep2);
 }
-#endif
 
-#ifdef JIT_REG_STACK
 static void
 select_stack_order(jit_gencode_t gen, _jit_regs_t *regs)
 {
        _jit_regdesc_t *desc1;
        _jit_regdesc_t *desc2;
-       _jit_regdesc_t temp_desc;
        int top_index;
 
-       /* Choose instruction that results into fewer exchanges. */
-       if(regs->wanted_stack_count > 1 && regs->no_pop
-          && (regs->commutative || regs->reversible))
+#ifdef JIT_REG_DEBUG
+       printf("select_stack_order()\n");
+#endif
+
+       if(!regs->x87_arith || regs->wanted_stack_count != 2)
        {
+               return;
+       }
+
                desc1 = &regs->descs[1];
                desc2 = &regs->descs[2];
 
-               if(desc1->value->in_register && !desc1->copy
-                  && desc2->value->in_register && !desc2->copy)
+       /* Choose instruction that results into fewer exchanges. If either
+          of two arguments may be on the stack top choose the second to be
+          on top. */
+       /* TODO: See if the next instruction wants the output or remaining
+          input to be on the stack top. */
+       if(desc2->copy || desc2->load)
                {
-                       /* Is any of the input values on the stack top? */
-                       if(desc1->value->reg == (gen->reg_stack_top - 1))
+               /* the second argument is going to be on the top */
+               top_index = 2;
+       }
+       else if(desc1->copy || desc1->load)
                        {
+               /* the first argument is going to be on the top */
                                top_index = 1;
                        }
                        else if(desc2->value->reg == (gen->reg_stack_top - 1))
                        {
+               /* the second argument is already on the top */
                                top_index = 2;
                        }
+       else if(desc1->value->reg == (gen->reg_stack_top - 1))
+       {
+               /* the first argument is already on the top */
+               top_index = 1;
+       }
                        else
                        {
-                               /* TODO: See if the next instruction wants 
output
-                                  or remaining input to be on the stack top. */
                                top_index = 2;
                        }
+
+       if(regs->no_pop)
+       {
+               regs->flip_args = (top_index == 2);
                }
-               else if(desc1->value->in_register && !desc1->copy)
+       else if(regs->reversible)
                {
-                       top_index = 2;
+               if(top_index == 2)
+               {
+                       regs->flip_args = 1;
+                       regs->dest_input_index = 1;
                }
-               else if(desc2->value->in_register && !desc2->copy)
+               else
                {
-                       top_index = 1;
+                       regs->flip_args = 0;
+                       regs->dest_input_index = 2;
+               }
+       }
+       else /*if(regs->commutative)*/
+       {
+               regs->flip_args = 1;
+               regs->dest_input_index = 1;
+
+               if(top_index != 2)
+               {
+                       swap_values(&regs->descs[1], &regs->descs[2]);
+               }
+       }
+
+#ifdef JIT_REG_DEBUG
+       printf("top_index = %d, flip_args = %d, dest_input_index = %d\n",
+              top_index, regs->flip_args, regs->dest_input_index);
+#endif
+}
+
+static void
+adjust_assignment(jit_gencode_t gen, _jit_regs_t *regs, int index)
+{
+       _jit_regdesc_t *desc, *desc2;
+
+#ifdef JIT_REG_DEBUG
+       printf("adjust_assignment(%d)\n", index);
+#endif
+
+       desc = &regs->descs[index];
+       if(!desc->value || !IS_STACK_REG(desc->reg))
+       {
+               return;
+       }
+
+       if(regs->wanted_stack_count == 1)
+       {
+               /* either a unary op or a binary op with duplicate value */
+               desc->reg = gen->reg_stack_top - regs->loaded_stack_count;
+       }
+       else if(regs->wanted_stack_count == 2)
+       {
+               /* a binary op */
+
+               /* find the input value the output goes to */
+               if(index == 0)
+               {
+                       if(regs->x87_arith)
+                       {
+                               index = regs->dest_input_index;
                }
                else
                {
-                       /* TODO: see if the next instruction wants output or 
remaining
-                          input to be on the stack top. */
-                       top_index = 2;
+                               index = 2;
+                       }
+                       desc2 = &regs->descs[index];
+               }
+               else
+               {
+                       desc2 = desc;
                }
 
-               if(top_index == 1)
+               if(regs->flip_args)
                {
-                       if(regs->reversible)
+                       if(regs->x87_arith && index == 1
+                          && desc2->value->in_register && !desc2->copy)
                        {
-                               regs->reverse_args = 1;
+                               desc->reg = desc2->value->reg;
                        }
-                       else /*if(regs->commutative)*/
+                       else
                        {
-                               temp_desc = *desc1;
-                               *desc1 = *desc2;
-                               *desc2 = temp_desc;
+                               desc->reg = (gen->reg_stack_top
+                                            - regs->loaded_stack_count
+                                            + index - 1);
+                       }
+               }
+               else
+               {
+                       if(regs->x87_arith && index == 2
+                          && desc2->value->in_register && !desc2->copy)
+                       {
+                               desc->reg = desc2->value->reg;
+                       }
+                       else
+                       {
+                               desc->reg = (gen->reg_stack_top
+                                            - regs->loaded_stack_count
+                                            + regs->wanted_stack_count
+                                            - index);
                        }
-                       regs->reverse_dest ^= 1;
                }
        }
+
+#ifdef JIT_REG_DEBUG
+       printf("reg = %d\n", desc->reg);
+#endif
 }
+
 #endif
 
 /*
@@ -2281,17 +2385,14 @@
        }
 }
 
+#ifdef JIT_REG_STACK
 static void
-commit_input_value(jit_gencode_t gen, _jit_regs_t *regs, int index, int 
go_down_stack)
+pop_input_value(jit_gencode_t gen, _jit_regs_t *regs, int index)
 {
        _jit_regdesc_t *desc;
-       int reg, other_reg;
-#ifdef JIT_REG_STACK
-       int is_down_stack = 0;
-#endif
 
 #ifdef JIT_REG_DEBUG
-       printf("commit_input_value(%d, %d)\n", index, go_down_stack);
+       printf("pop_input_value(%d)\n", index);
 #endif
 
        desc = &regs->descs[index];
@@ -2300,20 +2401,50 @@
                return;
        }
 
-       if(desc->copy)
-       {
-#ifdef JIT_REG_STACK
                if(IS_STACK_REG(desc->reg))
                {
-                       if(!go_down_stack)
+               if(desc->copy)
                        {
-                               if(1/*!regs->copy*/)
+                       gen->contents[desc->reg].used_for_temp = 0;
+               }
+               else
                                {
+                       unbind_value(gen, desc->value, desc->reg, 0);
+               }
                                        --(gen->reg_stack_top);
                                }
-                               gen->contents[desc->reg].used_for_temp = 0;
+}
+#endif
+
+static void
+commit_input_value(jit_gencode_t gen, _jit_regs_t *regs, int index, int killed)
+{
+       _jit_regdesc_t *desc;
+       int reg, other_reg;
+
+#ifdef JIT_REG_DEBUG
+       printf("commit_input_value(%d)\n", index);
+#endif
+
+       desc = &regs->descs[index];
+       if(!desc->value || desc->duplicate)
+       {
+               return;
+       }
+
+#ifdef JIT_REG_STACK
+       if(!IS_STACK_REG(desc->reg))
+       {
+               killed = 0;
                        }
-                       is_down_stack = 1;
+#endif
+
+       if(desc->copy)
+       {
+#ifdef JIT_REG_STACK
+               if(killed)
+               {
+                       killed = 0;
                }
                else
 #endif
@@ -2327,7 +2458,7 @@
        }
 
 #ifdef JIT_REG_STACK
-       if(desc->kill && desc->value->in_register && is_down_stack == 
go_down_stack)
+       if(!killed && desc->kill && desc->value->in_register)
 #else
        if(desc->kill && desc->value->in_register)
 #endif
@@ -2341,23 +2472,8 @@
                {
                        other_reg = -1;
                }
-#ifdef JIT_REG_STACK
-               if(is_down_stack)
-               {
                        free_value(gen, desc->value, reg, other_reg, 0);
                }
-               else
-               {
-                       unbind_value(gen, desc->value, reg, other_reg);
-                       if(IS_STACK_REG(reg) /*&& !regs->copy*/)
-                       {
-                               --(gen->reg_stack_top);
-                       }
-               }
-#else
-               unbind_value(gen, desc->value, reg, other_reg);
-#endif
-       }
 
 #ifdef JIT_REG_DEBUG
        printf("value = ");
@@ -2372,7 +2488,7 @@
 }
 
 static void
-commit_output_value(jit_gencode_t gen, _jit_regs_t *regs)
+commit_output_value(jit_gencode_t gen, _jit_regs_t *regs, int push_stack_top)
 {
        _jit_regdesc_t *desc;
 
@@ -2386,12 +2502,10 @@
                return;
        }
 
-#ifdef JIT_REG_STACK
-       if(IS_STACK_REG(desc->reg) /*&& !regs->copy*/)
+       if(IS_STACK_REG(desc->reg) && push_stack_top)
        {
                ++(gen->reg_stack_top);
        }
-#endif
        bind_value(gen, desc->value, desc->reg, desc->other_reg, 0);
 
        if(!desc->used)
@@ -3138,13 +3252,6 @@
 {
        int index;
 
-#ifdef JIT_REG_STACK
-       if((regclass->flags & JIT_REG_IN_STACK) != 0)
-       {
-               regs->clobber_stack = 1;
-       }
-#endif
-
        for(index = 0; index < regclass->num_regs; index++)
        {
                if(jit_reg_is_used(gen->permanent, index))
@@ -3160,8 +3267,6 @@
 {
        int index;
 
-       regs->clobber_all = 1;
-
        for(index = 0; index < JIT_NUM_REGS; index++)
        {
                if((_jit_reg_info[index].flags & JIT_REG_FIXED) != 0)
@@ -3189,28 +3294,23 @@
           the output always goes to the same register as the first input
           value unless this is a three-address instruction. */
        if(!regs->ternary && !regs->free_dest
-          && regs->descs[0].value
-          && regs->descs[1].value)
-       {
-               if(regs->descs[0].reg >= 0)
-               {
-                       if(regs->descs[1].reg < 0)
-                       {
-                               set_regdesc_register(gen, regs, 1,
-                                                    regs->descs[0].reg,
-                                                    regs->descs[0].other_reg);
-                       }
-               }
-               else if(regs->descs[1].reg >= 0)
+          && regs->descs[0].value && regs->descs[0].reg < 0
+          && regs->descs[1].value && regs->descs[1].reg >= 0)
                {
                        set_regdesc_register(gen, regs, 0,
                                             regs->descs[1].reg,
                                             regs->descs[1].other_reg);
                }
-       }
+
+#if JIT_REG_STACK
+       /* Choose between x87 pop and no-pop instructions.  */
+       select_nopop_or_pop(gen, regs);
+#endif
 
        /* Assign output and input registers. */
-       if(regs->descs[0].value && regs->descs[0].reg < 0)
+       if(regs->descs[0].value)
+       {
+               if(regs->descs[0].reg < 0)
        {
                if(regs->ternary)
                {
@@ -3218,8 +3318,6 @@
                        {
                                return 0;
                        }
-                       check_duplicate_value(regs, &regs->descs[0], 
&regs->descs[1]);
-                       check_duplicate_value(regs, &regs->descs[0], 
&regs->descs[2]);
                }
                else
                {
@@ -3227,19 +3325,24 @@
                        {
                                return 0;
                        }
-                       if(!regs->free_dest)
+                       }
+               }
+               if(regs->ternary)
+               {
+                       check_duplicate_value(regs, &regs->descs[0], 
&regs->descs[1]);
+                       check_duplicate_value(regs, &regs->descs[0], 
&regs->descs[2]);
+               }
+               else if(!regs->free_dest)
                        {
                                choose_input_order(gen, regs);
                                if(regs->dest_input_index)
                                {
-                                       set_regdesc_register(gen, regs,
-                                                            
regs->dest_input_index,
+                               set_regdesc_register(gen, regs, 
regs->dest_input_index,
                                                             regs->descs[0].reg,
                                                             
regs->descs[0].other_reg);
                                }
                        }
                }
-       }
        if(regs->descs[1].value && regs->descs[1].reg < 0)
        {
                if(!choose_input_register(gen, regs, 1))
@@ -3377,38 +3480,54 @@
        if(regs->wanted_stack_count > 0)
        {
                /* Adjust assignment of stack registers. */
-               adjust_assignment(gen, regs, 0);
-               adjust_assignment(gen, regs, 1);
-               adjust_assignment(gen, regs, 2);
-
                select_stack_order(gen, regs);
+               adjust_assignment(gen, regs, 2);
+               adjust_assignment(gen, regs, 1);
+               adjust_assignment(gen, regs, 0);
 
-               /* Shuffle the values that are already on the register stack. */
-               if(regs->loaded_stack_count > 0 && !regs->x87_arith)
+               if(regs->ternary)
+               {
+                       /* Ternary ops with only one stack register are 
supported. */
+                       if(regs->loaded_stack_count > 0)
                {
+                               move_input_value(gen, regs, 0);
                        move_input_value(gen, regs, 1);
                        move_input_value(gen, regs, 2);
                }
-
-               /* Load and shuffle the remaining values. */
-               if(regs->reverse_args)
+                       else
                {
+                               load_input_value(gen, regs, 0);
+                               load_input_value(gen, regs, 1);
                        load_input_value(gen, regs, 2);
+                       }
+               }
+               else if(regs->flip_args)
+               {
+                       /* Shuffle the values that are already on the register 
stack. */
+                       if(regs->loaded_stack_count > 0)
+                       {
+                               move_input_value(gen, regs, 1);
                        move_input_value(gen, regs, 2);
+                       }
+
+                       /* Load and shuffle the remaining values. */
                        load_input_value(gen, regs, 1);
                        move_input_value(gen, regs, 1);
+                       load_input_value(gen, regs, 2);
                }
                else
                {
-                       if(regs->ternary)
+                       /* Shuffle the values that are already on the register 
stack. */
+                       if(regs->loaded_stack_count > 0)
                        {
-                               load_input_value(gen, regs, 0);
-                               move_input_value(gen, regs, 0);
-                       }
-                       load_input_value(gen, regs, 1);
+                               move_input_value(gen, regs, 2);
                        move_input_value(gen, regs, 1);
+                       }
+
+                       /* Load and shuffle the remaining values. */
                        load_input_value(gen, regs, 2);
                        move_input_value(gen, regs, 2);
+                       load_input_value(gen, regs, 1);
                }
        }
        else
@@ -3440,15 +3559,14 @@
        {
                flags |= _JIT_REGS_NO_POP;
        }
-       if(regs->reverse_dest)
+       if(regs->flip_args)
        {
-               flags |= _JIT_REGS_REVERSE_DEST;
+               flags |= _JIT_REGS_FLIP_ARGS;
        }
-       if(regs->reverse_args)
+       if(regs->dest_input_index == 2)
        {
-               flags |= _JIT_REGS_REVERSE_ARGS;
+               flags |= _JIT_REGS_REVERSE;
        }
-
        return flags;
 }
 #endif
@@ -3462,73 +3580,103 @@
        dump_regs(gen, "enter _jit_regs_commit");
 #endif
 
+       if(regs->ternary)
+       {
+#ifdef JIT_REG_STACK
+               if(regs->wanted_stack_count > 0)
+               {
+                       pop_input_value(gen, regs, 0);
+                       pop_input_value(gen, regs, 1);
+                       pop_input_value(gen, regs, 2);
+               }
+#endif
+               commit_input_value(gen, regs, 0, 1);
+               commit_input_value(gen, regs, 1, 1);
+               commit_input_value(gen, regs, 2, 1);
+       }
+       else if(!regs->descs[0].value)
+       {
 #ifdef JIT_REG_STACK
        if(regs->wanted_stack_count > 0)
        {
+                       pop_input_value(gen, regs, 1);
+                       pop_input_value(gen, regs, 2);
+               }
+#endif
+               commit_input_value(gen, regs, 1, 1);
+               commit_input_value(gen, regs, 2, 1);
+       }
+#ifdef JIT_REG_STACK
+       else if(regs->wanted_stack_count > 0)
+       {
+               int pop1, pop2;
+               struct _jit_value temp;
                int reg1, reg2;
 
-               /* The stack registers has to be freed from the top down. It is
-                  assumed that only binary instructions may have more than one
-                  stack register. The unary instruction may not do that for
-                  obvious reasons. The practical observation is that no ternary
-                  instruction in libjit does that as well. */
-               if(regs->reverse_args)
+               pop1 = pop2 = 0;
+               if(!regs->no_pop)
                {
-                       commit_input_value(gen, regs, 1, 0);
-                       commit_input_value(gen, regs, 2, 0);
+                       if(regs->x87_arith)
+                       {
+                               if(regs->flip_args)
+                               {
+                                       pop_input_value(gen, regs, 2);
+                                       pop2 = 1;
                }
                else
                {
-                       commit_input_value(gen, regs, 2, 0);
-                       commit_input_value(gen, regs, 1, 0);
+                                       pop_input_value(gen, regs, 1);
+                                       pop1 = 1;
                }
-               if(regs->ternary)
-               {
-                       commit_input_value(gen, regs, 0, 0);
                }
                else
                {
-                       commit_output_value(gen, regs);
+                               pop_input_value(gen, regs, 1);
+                               pop_input_value(gen, regs, 2);
+                               pop1 = pop2 = 1;
+                       }
+               }
+
+               if(IS_STACK_REG(regs->descs[0].reg))
+               {
+                       temp = *regs->descs[0].value;
+                       if(!regs->x87_arith && !regs->copy)
+                       {
+                               ++(gen->reg_stack_top);
+                       }
+                       bind_value(gen, &temp, regs->descs[0].reg, -1, 0);
                }
 
-               /* If the allocator makes a copy of a value that was already on
-                  the stack we might need to free the original register as 
well.
-                  In general, the allocator makes a copy if the value is going
-                  to be destroyed by the instruction while it is still used
-                  (according to the liveness analysis). But the original value
-                  needs to be freed only if it is no longer used. So this extra
-                  code seems useless. But there were cases when the allocator
-                  miscalculated the cost of spilling and made a copy when it
-                  was not needed. So this code serves as a precaution against
-                  such problematic cases. */
                reg1 = ((regs->descs[1].value && 
regs->descs[1].value->in_register)
                        ? regs->descs[1].value->reg : -1);
                reg2 = ((regs->descs[2].value && 
regs->descs[2].value->in_register)
                        ? regs->descs[2].value->reg : -1);
                if(reg1 > reg2)
                {
-                       commit_input_value(gen, regs, 1, 1);
-                       commit_input_value(gen, regs, 2, 1);
+                       commit_input_value(gen, regs, 1, pop1);
+                       commit_input_value(gen, regs, 2, pop2);
                }
                else
                {
-                       commit_input_value(gen, regs, 2, 1);
-                       commit_input_value(gen, regs, 1, 1);
+                       commit_input_value(gen, regs, 2, pop2);
+                       commit_input_value(gen, regs, 1, pop1);
+               }
+
+               if(IS_STACK_REG(regs->descs[0].reg))
+               {
+                       reg1 = temp.reg;
+                       free_value(gen, &temp, reg1, -1, 1);
+                       regs->descs[0].reg = reg1;
+                       regs->descs[0].other_reg = -1;
                }
+               commit_output_value(gen, regs, 0);
        }
        else
 #endif
        {
                commit_input_value(gen, regs, 2, 0);
                commit_input_value(gen, regs, 1, 0);
-               if(regs->ternary)
-               {
-                       commit_input_value(gen, regs, 0, 0);
-               }
-               else
-               {
-                       commit_output_value(gen, regs);
-               }
+               commit_output_value(gen, regs, 1);
        }
 
        /* Load clobbered global registers. */




reply via email to

[Prev in Thread] Current Thread [Next in Thread]