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

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

[dotgnu-pnet-commits] libjit ChangeLog jit/jit-reg-alloc.h jit/jit-re...


From: Aleksey Demakov
Subject: [dotgnu-pnet-commits] libjit ChangeLog jit/jit-reg-alloc.h jit/jit-re...
Date: Tue, 22 Aug 2006 17:30:09 +0000

CVSROOT:        /sources/dotgnu-pnet
Module name:    libjit
Changes by:     Aleksey Demakov <avd>   06/08/22 17:30:09

Modified files:
        .              : ChangeLog 
        jit            : jit-reg-alloc.h jit-reg-alloc.c 
                         jit-rules-x86.ins 

Log message:
        improve handling of three-address instructions

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/libjit/ChangeLog?cvsroot=dotgnu-pnet&r1=1.252&r2=1.253
http://cvs.savannah.gnu.org/viewcvs/libjit/jit/jit-reg-alloc.h?cvsroot=dotgnu-pnet&r1=1.16&r2=1.17
http://cvs.savannah.gnu.org/viewcvs/libjit/jit/jit-reg-alloc.c?cvsroot=dotgnu-pnet&r1=1.38&r2=1.39
http://cvs.savannah.gnu.org/viewcvs/libjit/jit/jit-rules-x86.ins?cvsroot=dotgnu-pnet&r1=1.11&r2=1.12

Patches:
Index: ChangeLog
===================================================================
RCS file: /sources/dotgnu-pnet/libjit/ChangeLog,v
retrieving revision 1.252
retrieving revision 1.253
diff -u -b -r1.252 -r1.253
--- ChangeLog   21 Aug 2006 14:23:44 -0000      1.252
+++ ChangeLog   22 Aug 2006 17:30:09 -0000      1.253
@@ -1,3 +1,16 @@
+2006-08-23  Aleksey Demakov  <address@hidden>
+
+       * jit/jit-reg-alloc.c: improve handling of three-address op codes.
+       Now the dest register may re-use one of the input registers while
+       previously it was always assigned to a separate register. Also
+       restructure the code that will be used for better selection of x87
+       instructions (this code was not used before and still is not but
+       this is about to change).
+
+       * jit/jit-rules-x86.ins: rewrite all LOAD_RELATIVE and LOAD_ELEMENT
+       ops for x86 as three-address. Adjust IREM ops so that they work
+       correctly together with the latest allocator changes.
+
 2006-08-21  Thomas Cort  <address@hidden>
        * jit/jit-rules-alpha.c jit/jit-gen-alpha.h: Add macros for
        int to fp and fp to int conversions. Use _jit_pad_bufer.

Index: jit/jit-reg-alloc.h
===================================================================
RCS file: /sources/dotgnu-pnet/libjit/jit/jit-reg-alloc.h,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -b -r1.16 -r1.17
--- jit/jit-reg-alloc.h 16 Jun 2006 17:53:51 -0000      1.16
+++ jit/jit-reg-alloc.h 22 Aug 2006 17:30:09 -0000      1.17
@@ -157,6 +157,8 @@
        _jit_scratch_t  scratch[_JIT_REGS_SCRATCH_MAX];
        int             num_scratch;
 
+       int             dest_input_index;
+
        jit_regused_t   assigned;
        jit_regused_t   clobber;
 
@@ -164,6 +166,7 @@
        int             current_stack_top;
        int             wanted_stack_count;
        int             loaded_stack_count;
+
 } _jit_regs_t;
 
 void _jit_regs_init(jit_gencode_t gen, _jit_regs_t *regs, int flags);

Index: jit/jit-reg-alloc.c
===================================================================
RCS file: /sources/dotgnu-pnet/libjit/jit/jit-reg-alloc.c,v
retrieving revision 1.38
retrieving revision 1.39
diff -u -b -r1.38 -r1.39
--- jit/jit-reg-alloc.c 18 Aug 2006 18:14:27 -0000      1.38
+++ jit/jit-reg-alloc.c 22 Aug 2006 17:30:09 -0000      1.39
@@ -1900,12 +1900,25 @@
 {
        int index, usage;
 
-       if(reg >= 0)
+       if(reg < 0)
        {
+               return 0;
+       }
+
+       /* Assume that a global register is always alive unless it is to be
+          computed right away. */
                if(jit_reg_is_used(gen->permanent, reg))
                {
+               if(!regs->ternary
+                  && regs->descs[0].value
+                  && regs->descs[0].value->has_global_register
+                  && regs->descs[0].value->global_reg == reg)
+               {
+                       return 0;
+               }
                        return 1;
                }
+
                if(gen->contents[reg].is_long_end)
                {
                        reg = get_long_pair_start(reg);
@@ -1918,7 +1931,7 @@
                                return 1;
                        }
                }
-       }
+
        return 0;
 }
 
@@ -1930,7 +1943,7 @@
  *
  * The value is clobbered by the instruction if it is used as input value
  * and the output value will go to the same register and these two values
- * are not equal. Or the instruction has a side effect that destroy the
+ * are not equal. Or the instruction has a side effect that destroys the
  * input value regardless of the output. This is indicated with the
  * CLOBBER_INPUT_VALUE flag.
  *
@@ -1947,105 +1960,69 @@
  * The flag CLOBBER_REG indicates if the previous content of the register is
  * clobbered. The flag CLOBBER_OTHER_REG indicates that the other register
  * in a long pair is clobbered.
+ *
  */
 static int
 clobbers_register(jit_gencode_t gen, _jit_regs_t *regs, int index, int reg, 
int other_reg)
 {
-       int is_alive, is_other_alive;
-       int clobber, out_index, flags;
+       int flags;
 
-       if(index < 0)
-       {
-               /* this call is made for a scratch register */
-               return CLOBBER_REG;
-       }
        if(!regs->descs[index].value)
        {
                return CLOBBER_NONE;
        }
 
-       is_alive = is_register_alive(gen, regs, reg);
-       is_other_alive = is_register_alive(gen, regs, other_reg);
-
-       clobber = 0;
        if(regs->ternary || !regs->descs[0].value)
        {
-               /* this is either a ternary op or a binary/unary note */
-               if(IS_STACK_REG(reg))
-               {
-                       /* all input values are popped */
-                       clobber = 1;
-               }
-       }
-       else
-       {
-               /* find out the input value that is going to be overwritten by 
the output */
-               if(regs->free_dest)
-               {
-                       out_index = 0;
-               }
-               else if(!regs->descs[2].value)
-               {
-                       /* a unary op */
-                       out_index = 1;
-               }
-               else
-               {
-                       /* a binary op */
-                       if(regs->on_stack)
+               /* this is either a ternary or binary or unary note */
+               if(IS_STACK_REG(reg) || regs->descs[index].clobber)
                        {
-                               if(!regs->no_pop)
-                               {
-                                       /* the input value is either overwritten
-                                          by the output or popped */
-                                       clobber = 1;
-                               }
-                               out_index = 1 + (regs->reverse_dest ^ 
regs->reverse_args);
+                       flags = CLOBBER_INPUT_VALUE;
                        }
                        else
                        {
-                               out_index = 1;
+                       flags = CLOBBER_NONE;
                        }
                }
-
-               /* does the output value clobber the register? */
-               if(index == 0 || index == out_index)
+       else if(index == 0)
                {
-                       if(regs->descs[0].value->has_global_register
-                          && regs->descs[0].value->global_reg == reg)
-                       {
-                               return CLOBBER_NONE;
-                       }
-
+               /* this is the output value of a binary or unary op */
                        flags = CLOBBER_NONE;
-                       if(regs->descs[out_index].value != regs->descs[0].value)
-                       {
-                               flags |= CLOBBER_INPUT_VALUE;
-                       }
-                       if(is_alive)
+               if(is_register_alive(gen, regs, reg))
                        {
                                flags |= CLOBBER_REG;
                        }
-                       if(is_other_alive)
+               if(is_register_alive(gen, regs, other_reg))
                        {
                                flags |= CLOBBER_OTHER_REG;
                        }
                        return flags;
                }
+       else if(regs->on_stack && !regs->no_pop)
+       {
+               /* this is a binary or unary stack op -- the input value
+                  is either popped or overwritten by the output */
+               flags = CLOBBER_INPUT_VALUE;
        }
-
-       /* is input value clobbered? */
-       if(regs->descs[index].clobber)
+       else if(reg == regs->descs[0].reg
+               || reg == regs->descs[0].other_reg
+               || other_reg == regs->descs[0].reg)
        {
-               clobber = 1;
+               /* the input value of a binary or unary op is clobbered
+                  by the output value */
+               flags = CLOBBER_INPUT_VALUE;
        }
-
-       if(clobber)
+       else if(regs->descs[index].clobber)
        {
                flags = CLOBBER_INPUT_VALUE;
        }
        else
        {
+               flags = CLOBBER_NONE;
+       }
+
+       if(flags == CLOBBER_NONE)
+       {
                if(regs->descs[index].value->has_global_register
                   && regs->descs[index].value->global_reg == reg)
                {
@@ -2056,13 +2033,13 @@
                {
                        return CLOBBER_NONE;
                }
-               flags = CLOBBER_NONE;
        }
-       if(is_alive)
+
+       if(is_register_alive(gen, regs, reg))
        {
                flags |= CLOBBER_REG;
        }
-       if(is_other_alive)
+       if(is_register_alive(gen, regs, other_reg))
        {
                flags |= CLOBBER_OTHER_REG;
        }
@@ -2143,19 +2120,29 @@
 static void
 set_regdesc_register(jit_gencode_t gen, _jit_regs_t *regs, int index, int reg, 
int other_reg)
 {
+       int is_output;
+
        if(reg >= 0)
        {
+               is_output = (index == 0 && !regs->ternary);
+
                regs->descs[index].reg = reg;
                regs->descs[index].other_reg = other_reg;
 
                jit_reg_set_used(gen->touched, reg);
+               if(!is_output)
+               {
                jit_reg_set_used(regs->assigned, reg);
+               }
                if(other_reg >= 0)
                {
                        jit_reg_set_used(gen->touched, other_reg);
+                       if(!is_output)
+                       {
                        jit_reg_set_used(regs->assigned, other_reg);
                }
        }
+       }
 }
 
 /*
@@ -2199,7 +2186,11 @@
 
        /* See if the value clobbers the register it is assigned to. */
        clobber = clobbers_register(gen, regs, index, desc->reg, 
desc->other_reg);
-       if(jit_reg_is_used(regs->clobber, desc->reg))
+       if((clobber & CLOBBER_INPUT_VALUE) != 0)
+       {
+               clobber_input = 1;
+       }
+       else if(jit_reg_is_used(regs->clobber, desc->reg))
        {
                clobber_input = 1;
        }
@@ -2209,7 +2200,7 @@
        }
        else
        {
-               clobber_input = (clobber & CLOBBER_INPUT_VALUE) != 0;
+               clobber_input = 0;
        }
        if((clobber & CLOBBER_REG) != 0)
        {
@@ -2220,6 +2211,19 @@
                jit_reg_set_used(regs->clobber, desc->other_reg);
        }
 
+#if 0
+       /* See if the input value is clobbered by the output. */
+       if(index > 0 && !regs->ternary
+          && (desc->reg == regs->descs[0].reg
+              || desc->reg == regs->descs[0].other_reg
+              || (desc->other_reg >= 0
+                  && (desc->other_reg == regs->descs[0].reg
+                      || desc->other_reg == regs->descs[0].other_reg))))
+       {
+               clobber_input = 1;
+       }
+#endif
+
        /* See if the input value is thrashed by other inputs or clobbered
           by the output. The allocator tries to avoid thrashing so it may
           only take place if the register is assigned explicitly. For x87
@@ -2228,7 +2232,7 @@
           is no such problem for them at all. */
        if(reg >= 0 && (index > 0 || regs->ternary))
        {
-               if(index != 0)
+               if(index != 0 && regs->ternary && !are_values_equal(desc, 
&regs->descs[0]))
                {
                        if(reg == regs->descs[0].reg
                           || reg == regs->descs[0].other_reg
@@ -2236,22 +2240,9 @@
                               && (other_reg == regs->descs[0].reg
                                   || other_reg == regs->descs[0].other_reg)))
                        {
-                               if(regs->ternary)
-                               {
-                                       if(!are_values_equal(desc, 
&regs->descs[0]))
-                                       {
                                                desc->thrash = 1;
                                        }
                                }
-                               else
-                               {
-                                       if(desc->value != regs->descs[0].value)
-                                       {
-                                               clobber_input = 1;
-                                       }
-                               }
-                       }
-               }
                if(index != 1 && !are_values_equal(desc, &regs->descs[1]))
                {
                        if(reg == regs->descs[1].reg
@@ -2409,71 +2400,159 @@
 }
 
 /*
- * Check to see if an input value loaded into the given register
- * clobbers any other input values.
+ * Compute the register spill cost. The register spill cost is computed as
+ * the sum of spill costs of individual values the register contains. The
+ * spill cost of a value depends on the following factors:
+ *
+ * 1. Values that are not used after the current instruction may be safely
+ *    discareded so their spill cost is taken to be zero.
+ * 2. Values that are spilled to global registers are cheaper than values
+ *    that are spilled into stack frame.
+ * 3. Clean values are cheaper than dirty values.
+ *
+ * NOTE: A value is clean if it was loaded from the stack frame or from a
+ * global register and has not changed since then. Otherwise it is dirty.
+ * There is no need to spill clean values. However their spill cost is
+ * considered to be non-zero so that the register allocator will choose
+ * those registers that do not contain live values over those that contain
+ * live albeit clean values.
+ *
+ * For global registers this function returns the cost of zero. So global
+ * registers have to be handled separately.
  */
 static int
-thrashes_register(jit_gencode_t gen, _jit_regs_t *regs, int index, int reg, 
int other_reg)
+compute_spill_cost(jit_gencode_t gen, _jit_regs_t *regs, int reg, int 
other_reg)
 {
-       _jit_regdesc_t *desc;
-       int reg2, other_reg2;
+       int cost, index, usage;
+       jit_value_t value;
 
-       if(index < 0)
+       if(gen->contents[reg].is_long_end)
        {
-               desc = 0;
+               reg = get_long_pair_start(reg);
+       }
+
+       cost = 0;
+       for(index = 0; index < gen->contents[reg].num_values; index++)
+       {
+               value = gen->contents[reg].values[index];
+               usage = value_usage(regs, value);
+               if((usage & VALUE_DEAD) != 0)
+               {
+                       /* the value is not spilled */
+                       continue;
+               }
+               if((usage & VALUE_LIVE) != 0 && (usage & VALUE_USED) == 0)
+               {
+                       /* the value has to be spilled anyway */
+                       /* NOTE: This is true for local register allocation,
+                          review for future global allocator. */
+                       continue;
+               }
+               if(value->has_global_register)
+               {
+                       if(value->in_global_register)
+                       {
+                               cost += COST_SPILL_CLEAN_GLOBAL;
+                       }
+                       else
+                       {
+                               cost += COST_SPILL_DIRTY_GLOBAL;
+                       }
        }
        else
        {
-               if(index == 0 && !regs->ternary)
+                       if(value->in_frame)
                {
-                       return 0;
+                               cost += COST_SPILL_CLEAN;
                }
-               desc = &regs->descs[index];
-               if(!desc->value)
+                       else
                {
-                       return 0;
+                               cost += COST_SPILL_DIRTY;
                }
        }
-
-       if(index != 0 && regs->ternary && regs->descs[0].value)
+       }
+       if(other_reg >= 0)
        {
-               if(!(desc && regs->descs[0].value == desc->value)
-                  && regs->descs[0].value->has_global_register
-                  && regs->descs[0].value->global_reg == reg)
+               for(index = 0; index < gen->contents[other_reg].num_values; 
index++)
                {
-                       return 1;
+                       value = gen->contents[other_reg].values[index];
+                       usage = value_usage(regs, value);
+                       if((usage & VALUE_DEAD) != 0)
+                       {
+                               /* the value is not spilled */
+                               continue;
                }
-               if(regs->descs[0].value->in_register
-                  && !are_values_equal(&regs->descs[0], desc))
+                       if((usage & VALUE_LIVE) != 0 && (usage & VALUE_USED) == 
0)
                {
-                       reg2 = regs->descs[0].value->reg;
-                       if(reg2 == reg || reg2 == other_reg)
+                               /* the value has to be spilled anyway */
+                               /* NOTE: This is true for local register 
allocation,
+                                  review for future global allocator. */
+                               continue;
+                       }
+                       if(value->has_global_register)
                        {
-                               return 1;
+                               if(value->in_global_register)
+                               {
+                                       cost += COST_SPILL_CLEAN_GLOBAL;
                        }
-                       if(gen->contents[reg2].is_long_start)
+                               else
                        {
-                               other_reg2 = OTHER_REG(reg2);
-                               if(other_reg2 == reg /*|| other_reg2 == 
other_reg*/)
+                                       cost += COST_SPILL_DIRTY_GLOBAL;
+                               }
+                       }
+                       else
                                {
-                                       return 1;
+                               if(value->in_frame)
+                               {
+                                       cost += COST_SPILL_CLEAN;
+                               }
+                               else
+                               {
+                                       cost += COST_SPILL_DIRTY;
                                }
                        }
                }
        }
-       if(index != 1 && regs->descs[1].value)
+       return cost;
+}
+
+static int
+thrashes_value(jit_gencode_t gen,
+              _jit_regdesc_t *desc, int reg, int other_reg,
+              _jit_regdesc_t *desc2)
+{
+       int reg2, other_reg2;
+
+#if ALLOW_CLOBBER_GLOBAL
+       if(desc2->value->has_global_register)
+       {
+               if(desc2->value->global_reg == reg)
        {
-               if(!(desc && regs->descs[1].value == desc->value)
-                  && regs->descs[1].value->has_global_register
-                  && regs->descs[1].value->global_reg == reg)
+                       if(desc && desc2->value == desc->value)
+                       {
+                               return 0;
+                       }
+                       return 1;
+               }
+               if(desc2->value->global_reg == other_reg)
                {
                        return 1;
                }
-               if(regs->descs[1].value->in_register
-                  && !are_values_equal(&regs->descs[1], desc))
+       }
+#endif
+
+       if(desc2->value->in_register)
+       {
+               reg2 = desc2->value->reg;
+               if(reg2 == reg)
                {
-                       reg2 = regs->descs[1].value->reg;
-                       if(reg2 == reg || reg2 == other_reg)
+                       if(are_values_equal(desc2, desc))
+                       {
+                               return 0;
+                       }
+                       return 1;
+               }
+               if(reg2 == other_reg)
                        {
                                return 1;
                        }
@@ -2486,259 +2565,342 @@
                                }
                        }
                }
+
+       return 0;
+}
+
+static int
+choose_scratch_register(jit_gencode_t gen, _jit_regs_t *regs, int index)
+{
+       int reg, type;
+       int use_cost, spill_cost;
+       int suitable_reg;
+       int suitable_cost;
+       int suitable_age;
+
+       type = JIT_REG_WORD;
+
+       suitable_reg = -1;
+       suitable_cost = COST_TOO_MUCH;
+       suitable_age = -1;
+       for(reg = 0; reg < JIT_NUM_REGS; reg++)
+       {
+               if((_jit_reg_info[reg].flags & type) == 0)
+               {
+                       continue;
        }
-       if(index != 2 && regs->descs[2].value)
+               if(jit_reg_is_used(regs->assigned, reg))
        {
-               if(!(desc && regs->descs[2].value == desc->value)
-                  && regs->descs[2].value->has_global_register
-                  && regs->descs[2].value->global_reg == reg)
+                       continue;
+               }
+               if(!jit_reg_is_used(regs->scratch[index].regset, reg))
                {
-                       return 1;
+                       continue;
                }
-               if(regs->descs[2].value->in_register
-                  && !are_values_equal(&regs->descs[2], desc))
+
+#if ALLOW_CLOBBER_GLOBAL
+               if(jit_reg_is_used(gen->permanent, reg))
                {
-                       reg2 = regs->descs[2].value->reg;
-                       if(reg2 == reg || reg2 == other_reg)
+                       use_cost = COST_CLOBBER_GLOBAL;
+               }
+               else
                        {
-                               return 1;
+                       use_cost = 0;
                        }
-                       if(gen->contents[reg2].is_long_start)
+#else
+               if(jit_reg_is_used(gen->permanent, reg))
                        {
-                               other_reg2 = OTHER_REG(reg2);
-                               if(other_reg2 == reg /*|| other_reg2 == 
other_reg*/)
+                       continue;
+               }
+               use_cost = 0;
+#endif
+
+               if(regs->ternary && regs->descs[0].value
+                  && thrashes_value(gen, 0, reg, -1, &regs->descs[0]))
                                {
-                                       return 1;
+                       use_cost += COST_THRASH;
                                }
+               else if(regs->descs[1].value
+                       && thrashes_value(gen, 0, reg, -1, &regs->descs[1]))
+               {
+                       use_cost += COST_THRASH;
                        }
+               else if(regs->descs[2].value
+                       && thrashes_value(gen, 0, reg, -1, &regs->descs[2]))
+               {
+                       use_cost += COST_THRASH;
+               }
+
+               spill_cost = compute_spill_cost(gen, regs, reg, -1);
+
+               if((use_cost + spill_cost) < suitable_cost
+                  || (spill_cost > 0 && (use_cost + spill_cost) == 
suitable_cost
+                      && gen->contents[reg].age < suitable_age))
+               {
+                       suitable_reg = reg;
+                       suitable_cost = use_cost + spill_cost;
+                       suitable_age = gen->contents[reg].age;
                }
        }
+
+       if(suitable_reg >= 0)
+       {
+               set_scratch_register(gen, regs, index, suitable_reg);
+               return 1;
+       }
+
        return 0;
 }
 
-/*
- * Compute the register spill cost. The register spill cost is computed as
- * the sum of spill costs of individual values the register contains. The
- * spill cost of a value depends on the following factors:
- *
- * 1. Values that are not used after the current instruction may be safely
- *    discareded so their spill cost is taken to be zero.
- * 2. Values that are spilled to global registers are cheaper than values
- *    that are spilled into stack frame.
- * 3. Clean values are cheaper than dirty values.
- *
- * NOTE: A value is clean if it was loaded from the stack frame or from a
- * global register and has not changed since then. Otherwise it is dirty.
- * There is no need to spill clean values. However their spill cost is
- * considered to be non-zero so that the register allocator will choose
- * those registers that do not contain live values over those that contain
- * live albeit clean values.
- *
- * For global registers this function returns the cost of zero. So global
- * registers have to be handled separately.
- */
 static int
-compute_spill_cost(jit_gencode_t gen, _jit_regs_t *regs, int reg, int 
other_reg)
+choose_output_register(jit_gencode_t gen, _jit_regs_t *regs)
 {
-       int cost, index, usage;
-       jit_value_t value;
+       int type, need_pair;
+       int reg, other_reg;
+       int use_cost, spill_cost;
+       int suitable_reg, suitable_other_reg;
+       int suitable_cost;
+       int suitable_age;
 
-       if(gen->contents[reg].is_long_end)
+       need_pair = _jit_regs_needs_long_pair(regs->descs[0].value->type);
+       type = get_register_type(regs->descs[0].value, need_pair);
+       if(!type)
        {
-               reg = get_long_pair_start(reg);
+               return 0;
        }
 
-       cost = 0;
-       for(index = 0; index < gen->contents[reg].num_values; index++)
+       suitable_reg = -1;
+       suitable_other_reg = -1;
+       suitable_cost = COST_TOO_MUCH;
+       suitable_age = -1;
+       for(reg = 0; reg < JIT_NUM_REGS; reg++)
        {
-               value = gen->contents[reg].values[index];
-               usage = value_usage(regs, value);
-               if((usage & VALUE_DEAD) != 0)
+               if((_jit_reg_info[reg].flags & type) == 0)
                {
-                       /* the value is not spilled */
                        continue;
                }
-               if((usage & VALUE_LIVE) != 0 && (usage & VALUE_USED) == 0)
+               if(jit_reg_is_used(gen->inhibit, reg))
                {
-                       /* the value has to be spilled anyway */
-                       /* NOTE: This is true for local register allocation,
-                          review for future global allocator. */
                        continue;
                }
-               if(value->has_global_register)
+               if(!jit_reg_is_used(regs->descs[0].regset, reg))
                {
-                       if(value->in_global_register)
+                       continue;
+               }
+
+               if(need_pair)
                        {
-                               cost += COST_SPILL_CLEAN_GLOBAL;
+                       other_reg = OTHER_REG(reg);
+                       if(jit_reg_is_used(gen->inhibit, other_reg))
+                       {
+                               continue;
+                       }
                        }
                        else
                        {
-                               cost += COST_SPILL_DIRTY_GLOBAL;
+                       other_reg = -1;
                        }
+
+               /* It is not allowed to assign an output value to a global 
register
+                  unless it is the very value the global register contains. */
+               if(jit_reg_is_used(gen->permanent, reg))
+               {
+                       if(regs->descs[0].value->has_global_register
+                          && regs->descs[0].value->global_reg == reg)
+                       {
+                               use_cost = 0;
                }
                else
                {
-                       if(value->in_frame)
+                               continue;
+                       }
+               }
+               else
                        {
-                               cost += COST_SPILL_CLEAN;
+                       if(other_reg >= 0 && jit_reg_is_used(gen->permanent, 
other_reg))
+                       {
+                               continue;
+                       }
+                       if(regs->descs[0].value->has_global_register)
+                       {
+                               use_cost = COST_GLOBAL_BIAS;
                        }
                        else
                        {
-                               cost += COST_SPILL_DIRTY;
+                               use_cost = 0;
                        }
                }
+
+               if(regs->free_dest)
+               {
+                       /* noop */
        }
-       if(other_reg >= 0)
+               else if(regs->descs[1].value
+                       && regs->descs[1].value->in_register
+                       && regs->descs[1].value->reg == reg)
        {
-               for(index = 0; index < gen->contents[other_reg].num_values; 
index++)
+                       /* noop */
+               }
+               else if(regs->descs[2].value
+                       && regs->descs[2].value->in_register
+                       && regs->descs[2].value->reg == reg)
                {
-                       value = gen->contents[other_reg].values[index];
-                       usage = value_usage(regs, value);
-                       if((usage & VALUE_DEAD) != 0)
+                       if(regs->commutative || regs->x87_arith)
                        {
-                               /* the value is not spilled */
-                               continue;
+                               /* noop */
                        }
-                       if((usage & VALUE_LIVE) != 0 && (usage & VALUE_USED) == 
0)
+                       else
                        {
-                               /* the value has to be spilled anyway */
-                               /* NOTE: This is true for local register 
allocation,
-                                  review for future global allocator. */
-                               continue;
+                               use_cost += COST_THRASH;
                        }
-                       if(value->has_global_register)
+               }
+               else
                        {
-                               if(value->in_global_register)
+                       use_cost += COST_COPY;
+               }
+
+               spill_cost = compute_spill_cost(gen, regs, reg, other_reg);
+
+               if((use_cost + spill_cost) < suitable_cost
+                  || (spill_cost > 0 && (use_cost + spill_cost) == 
suitable_cost
+                      && gen->contents[reg].age < suitable_age))
                                {
-                                       cost += COST_SPILL_CLEAN_GLOBAL;
+                       suitable_reg = reg;
+                       suitable_other_reg = other_reg;
+                       suitable_cost = use_cost + spill_cost;
+                       suitable_age = gen->contents[reg].age;
+               }
+       }
+
+       if(suitable_reg >= 0)
+       {
+               set_regdesc_register(gen, regs, 0, suitable_reg, 
suitable_other_reg);
+               return 1;
+       }
+
+       return 0;
+}
+
+/*
+ * 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.
+ */
+static void
+choose_input_order(jit_gencode_t gen, _jit_regs_t *regs)
+{
+       _jit_regdesc_t temp_desc;
+       int keep1, keep2;
+
+       if(regs->ternary || regs->free_dest || !regs->descs[0].value)
+       {
+               regs->dest_input_index = 0;
+               return;
+       }
+
+       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)
+       {
+               if(regs->on_stack && regs->x87_arith)
+               {
+                       regs->no_pop = 1;
+                       regs->reverse_dest = 1;
+                       regs->dest_input_index = 2;
                                }
                                else
                                {
-                                       cost += COST_SPILL_DIRTY_GLOBAL;
+                       if(regs->commutative)
+                       {
+                               temp_desc = regs->descs[1];
+                               regs->descs[1] = regs->descs[2];
+                               regs->descs[2] = temp_desc;
+                       }
+                       regs->dest_input_index = 1;
                                }
                        }
+       else if(regs->descs[1].value)
+       {
+               regs->dest_input_index = 1;
+       }
                        else
                        {
-                               if(value->in_frame)
+               regs->dest_input_index = 0;
+       }
+
+       /* Choose between pop and no-pop instructions. */
+       if(regs->on_stack && regs->x87_arith
+          && !regs->no_pop && !regs->clobber_all
+          && regs->descs[1].value
+          && regs->descs[2].value)
                                {
-                                       cost += COST_SPILL_CLEAN;
+               /* 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
                                {
-                                       cost += COST_SPILL_DIRTY;
+                       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);
        }
-       return cost;
 }
 
-/* TODO: update comments */
-/*
- * Assign value to the register it is already in if possible. This is the case
- * if the register is not already assigned to and one of the following is true:
- *  1. The value is output and it the only value in register.
- *  2. The value is input and it is not clobbered.
- *  3. The value is input and it the only value in register, it is clobbered
- *     but not used afterwards.
- *  4. The value is input and it is clobbered even if we do not use its
- *     register. This might be because the instruction clobbers all or
- *     some registers (see _jit_regs_clobber_all(), jit_regs_clobber()).
- * NOTE: In the last case it might be possible to find a not clobbered register
- * where the value could be moved to so that the original copy can be used for
- * input without spilling. However probaly this corner case is not worth the
- * effort.
- */
-/*
- * Assign value to a register that is cheapest to use. We are here either
- * because the value is not in register or it is but the register will be
- * clobbered so the reuse_register() function failed to assign the register.
- *
- * Depending on the value location and on the presence of a free register we
- * do one of the following:
- *
- * 1. The value is in register and there is a free register.
- *    In this case we will generate a reg-to-reg move.
- * 2. The value is in register and there are no free regsiters.
- *    In this case we will generate a spill if the register is dirty.
- * 3. The value is in frame and there is a free register.
- *    In this case we will generate a value load.
- * 4. The value is in frame and there are no free registers.
- *    In this case we choose a register to evict. We will generate a
- *    spill for the dirty register and load the value there.
- *
- * In the last case we choose the register using the following rules:
- *
- * 1. Choose clean registers over dirty.
- * 2. Choose registers that contain global values over those that don't.
- * 2. Choose old registers over new.
- *
- * NOTE: A register is clean if the value it contains has not changed since
- * it was loaded form the frame. Otherwise it is dirty. There is no need to
- * spill clean registers. Dirty registers has to be spilled.
- *
- * TODO: build use lists in CFG and choose the register on the basis of next
- * value use instead of the register age.
- *
- */
 static int
-use_cheapest_register(jit_gencode_t gen, _jit_regs_t *regs, int index, 
jit_regused_t allowed)
+choose_input_register(jit_gencode_t gen, _jit_regs_t *regs, int index)
 {
        _jit_regdesc_t *desc;
        _jit_regdesc_t *desc2;
-       _jit_regdesc_t *desc3;
-       int is_output, output_index;
        int type, need_pair;
        int reg, other_reg;
-       int cost, copy_cost;
-       int suitable_reg;
+       int use_cost, spill_cost;
+       int suitable_reg, suitable_other_reg;
        int suitable_cost;
        int suitable_age;
        int clobber;
 
-       if(index >= 0)
-       {
                desc = &regs->descs[index];
                if(!desc->value)
                {
-                       return -1;
-               }
-
-               if(regs->ternary || regs->descs[0].value == 0)
-               {
-                       is_output = 0;
-                       output_index = 0;
-               }
-               else
-               {
-                       is_output = (index == 0);
-                       if(regs->free_dest)
-                       {
-                               output_index = 0;
-                       }
-                       else
-                       {
-                               output_index = 1 + (regs->reverse_dest ^ 
regs->reverse_args);
-                       }
+               return 0;
                }
 
                need_pair = _jit_regs_needs_long_pair(desc->value->type);
                type = get_register_type(desc->value, need_pair);
                if(!type)
                {
-                       return -1;
+               return 0;
                }
+
+       if(index == regs->dest_input_index)
+       {
+               desc2 = &regs->descs[0];
        }
        else
        {
-               desc = 0;
-               is_output = 0;
-               output_index = 0;
-               need_pair = 0;
-               type = JIT_REG_WORD;
+               desc2 = desc;
        }
 
        suitable_reg = -1;
+       suitable_other_reg = -1;
        suitable_cost = COST_TOO_MUCH;
        suitable_age = -1;
        for(reg = 0; reg < JIT_NUM_REGS; reg++)
@@ -2747,33 +2909,19 @@
                {
                        continue;
                }
-               if(!jit_reg_is_used(allowed, reg)
-                  || jit_reg_is_used(gen->inhibit, reg)
-                  || jit_reg_is_used(regs->assigned, reg))
+               if(jit_reg_is_used(regs->assigned, reg))
                {
                        continue;
                }
-
-               if(!desc)
-               {
-                       if(jit_reg_is_used(gen->permanent, reg))
+               if(!jit_reg_is_used(desc->regset, reg))
                        {
                                continue;
                        }
-                       cost = compute_spill_cost(gen, regs, reg, -1);
-                       if(thrashes_register(gen, regs, index, reg, -1))
-                       {
-                               cost += COST_THRASH;
-                       }
-                       copy_cost = 0;
-               }
-               else
-               {
+
                        if(need_pair)
                        {
                                other_reg = OTHER_REG(reg);
-                               if(jit_reg_is_used(gen->inhibit, other_reg)
-                                  || jit_reg_is_used(regs->assigned, 
other_reg))
+                       if(jit_reg_is_used(regs->assigned, other_reg))
                                {
                                        continue;
                                }
@@ -2783,125 +2931,96 @@
                                other_reg = -1;
                        }
 
-                       clobber = clobbers_register(gen, regs, index, reg, 
other_reg);
-                       if((clobber & ~CLOBBER_INPUT_VALUE) != 0)
-                       {
-                               if(jit_reg_is_used(gen->permanent, reg))
+               if((desc->value->in_global_register && desc->value->global_reg 
== reg)
+                  || (desc->value->in_register && desc->value->reg == reg))
                                {
-                                       continue;
+                       use_cost = 0;
                                }
-#if !ALLOW_CLOBBER_GLOBAL
-                               if(other_reg >= 0 && 
jit_reg_is_used(gen->permanent, other_reg))
+               else
                                {
-                                       continue;
+                       use_cost = COST_COPY;
                                }
-#endif
-                               if(jit_reg_is_used(regs->clobber, reg)
-                                  || (other_reg >= 0 && 
jit_reg_is_used(regs->clobber, other_reg)))
+               if(desc2->value->has_global_register && 
desc2->value->global_reg != reg)
                                {
-                                       cost = 0;
+                       use_cost += COST_GLOBAL_BIAS;
                                }
-                               else
+
+               if(index != 0 && regs->ternary && regs->descs[0].value
+                  && thrashes_value(gen, desc, reg, other_reg, 
&regs->descs[0]))
                                {
-                                       cost = compute_spill_cost(gen, regs, 
reg, other_reg);
+                       use_cost += COST_THRASH;
                                }
-#if ALLOW_CLOBBER_GLOBAL
-                               if(other_reg >= 0 && 
jit_reg_is_used(gen->permanent, other_reg))
+               else if(index != 1 && regs->descs[1].value
+                       && thrashes_value(gen, desc, reg, other_reg, 
&regs->descs[1]))
                                {
-                                       cost += COST_CLOBBER_GLOBAL;
-                               }
-#endif
+                       use_cost += COST_THRASH;
                        }
-                       else
+               else if(index != 2 && regs->descs[2].value
+                       && thrashes_value(gen, desc, reg, other_reg, 
&regs->descs[2]))
                        {
-                               cost = 0;
+                       use_cost += COST_THRASH;
                        }
 
-                       if(thrashes_register(gen, regs,
-                                            is_output ? output_index : index,
-                                            reg, other_reg))
+               clobber = clobbers_register(gen, regs, index, reg, other_reg);
+               if((clobber & CLOBBER_INPUT_VALUE) != 0)
+               {
+                       if(desc->used)
+                       {
+                               use_cost += COST_SPILL_CLEAN;
+                       }
+               }
+               if((clobber & (CLOBBER_REG | CLOBBER_OTHER_REG)) != 0)
                        {
                                if(jit_reg_is_used(gen->permanent, reg))
                                {
                                        continue;
                                }
+#if !ALLOW_CLOBBER_GLOBAL
                                if(other_reg >= 0 && 
jit_reg_is_used(gen->permanent, other_reg))
                                {
                                        continue;
                                }
-                               cost += COST_THRASH;
-                               if(other_reg >= 0)
-                               {
-                                       cost += COST_THRASH;
-                               }
-                       }
-
-                       if(is_output)
-                       {
-                               if(output_index && 
regs->descs[output_index].value)
-                               {
-                                       desc2 = &regs->descs[output_index];
-                               }
-                               else
+#endif
+                       if(jit_reg_is_used(regs->clobber, reg)
+                          || (other_reg >= 0 && jit_reg_is_used(regs->clobber, 
other_reg)))
                                {
-                                       desc2 = 0;
-                               }
-                               desc3 = &regs->descs[0];
+                               spill_cost = 0;
                        }
                        else
                        {
-                               desc2 = desc;
-                               if(output_index && index == output_index)
-                               {
-                                       desc3 = &regs->descs[0];
+                               spill_cost = compute_spill_cost(gen, regs, reg, 
other_reg);
                                }
-                               else
+#if ALLOW_CLOBBER_GLOBAL
+                       if(other_reg >= 0 && jit_reg_is_used(gen->permanent, 
other_reg))
                                {
-                                       desc3 = desc;
-                               }
+                               spill_cost += COST_CLOBBER_GLOBAL;
                        }
-                       if(!desc2
-                          || (desc2->value->in_global_register && 
desc2->value->global_reg == reg)
-                          || (desc2->value->in_register && desc2->value->reg 
== reg))
-                       {
-                               copy_cost = 0;
+#endif
                        }
                        else
                        {
-                               copy_cost = COST_COPY;
-                       }
-                       if(desc3->value->has_global_register && 
desc3->value->global_reg != reg)
-                       {
-                               cost += COST_GLOBAL_BIAS;
-                       }
+                       spill_cost = 0;
                }
 
-               if((cost + copy_cost) < suitable_cost
-                  || (cost > 0 && (cost + copy_cost) == suitable_cost
+               if((use_cost + spill_cost) < suitable_cost
+                  || (spill_cost > 0 && (use_cost + spill_cost) == 
suitable_cost
                       && gen->contents[reg].age < suitable_age))
                {
                        /* This is the oldest suitable register of this type */
                        suitable_reg = reg;
-                       suitable_cost = cost + copy_cost;
+                       suitable_other_reg = other_reg;
+                       suitable_cost = use_cost + spill_cost;
                        suitable_age = gen->contents[reg].age;
                }
        }
 
-       reg = suitable_reg;
-       if(desc && reg >= 0)
-       {
-               if(need_pair)
-               {
-                       other_reg = OTHER_REG(reg);
-               }
-               else
+       if(suitable_reg >= 0)
                {
-                       other_reg = -1;
-               }
-               set_regdesc_register(gen, regs, index, reg, other_reg);
+               set_regdesc_register(gen, regs, index, suitable_reg, 
suitable_other_reg);
+               return 1;
        }
 
-       return reg;
+       return 0;
 }
 
 /*
@@ -2924,138 +3043,6 @@
        }
 }
 
-/*
- * 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.
- */
-static void
-select_order(jit_gencode_t gen, _jit_regs_t *regs)
-{
-       _jit_regdesc_t *desc0;
-       _jit_regdesc_t *desc1;
-       _jit_regdesc_t *desc2;
-       _jit_regdesc_t temp_desc;
-       int keep1, keep2;
-       int out_index;
-
-       if(regs->ternary || regs->free_dest || !(regs->commutative || 
regs->x87_arith))
-       {
-               /* Bail out on ternary or non-commutative and non-x87 
instruction. */
-               return;
-       }
-
-       desc0 = &regs->descs[0];
-       desc1 = &regs->descs[1];
-       desc2 = &regs->descs[2];
-
-       if(!desc0->value || !desc1->value || !desc2->value)
-       {
-               /* Bail out on binary notes or unary ops. */
-               return;
-       }
-
-       /* Determine if we might want to keep either of input values
-          in registers after the instruction completion. */
-       if(regs->clobber_all)
-       {
-               keep1 = 0;
-               keep2 = 0;
-       }
-       else
-       {
-               keep1 = desc1->used && (desc1->value != desc0->value) && 
!desc1->clobber;
-               keep2 = desc2->used && (desc2->value != desc0->value) && 
!desc2->clobber;
-       }
-
-       /* Choose between pop and no-pop instructions. */
-       if(regs->on_stack)
-       {
-               regs->no_pop = (regs->x87_arith && (keep1 || keep2));
-       }
-       else
-       {
-               regs->no_pop = 0;
-       }
-
-       /* Choose the input value to be clobbered by output. */
-       if(regs->on_stack ? regs->no_pop : regs->commutative)
-       {
-               if(keep1 && keep2)
-               {
-                       /* TODO: take into account that value might by copied to
-                          another register */
-                       if(desc1->value->in_register)
-                       {
-                               if(desc2->value->in_register)
-                               {
-                                       /* TODO: compare spill cost and live 
ranges  */
-                                       out_index = 1;
-                               }
-                               else
-                               {
-                                       /* TODO: compare spill cost and live 
ranges  */
-                                       out_index = 2;
-                               }
-                       }
-                       else
-                       {
-                               if(desc2->value->in_register)
-                               {
-                                       /* TODO: compare spill cost and live 
ranges  */
-                                       out_index = 1;
-                               }
-                               else
-                               {
-                                       /* TODO: use live ranges  */
-                                       out_index = 1;
-                               }
-                       }
-               }
-               else if(keep1)
-               {
-                       out_index = 2;
-               }
-               else if(keep2)
-               {
-                       out_index = 1;
-               }
-               else
-               {
-                       if(!(desc1->used || desc1->live))
-                       {
-                               out_index = 1;
-                       }
-                       else if(!(desc2->used || desc2->live))
-                       {
-                               out_index = 2;
-                       }
-                       else
-                       {
-                               out_index = 1;
-                       }
-               }
-
-               if(out_index == 2)
-               {
-                       if(regs->on_stack)
-                       {
-                               regs->reverse_dest = 1;
-                       }
-                       else if(regs->commutative)
-                       {
-                               temp_desc = *desc1;
-                               *desc1 = *desc2;
-                               *desc2 = temp_desc;
-                       }
-               }
-       }
-
-       return;
-}
-
 static void
 adjust_assignment(jit_gencode_t gen, _jit_regs_t *regs, int index)
 {
@@ -4002,6 +3989,7 @@
                regs->scratch[index].regset = jit_regused_init_used;
        }
        regs->num_scratch = 0;
+       regs->dest_input_index = 0;
 
        /* Set clobber flags. */
        regs->clobber = jit_regused_init;
@@ -4018,7 +4006,7 @@
                }
        }
 
-       regs->assigned = jit_regused_init;
+       regs->assigned = gen->inhibit;
 
        regs->stack_start = -1;
        regs->current_stack_top = 0;
@@ -4187,58 +4175,69 @@
 int
 _jit_regs_assign(jit_gencode_t gen, _jit_regs_t *regs)
 {
-       int reg, index, out_index;
+       int index;
 
 #ifdef JIT_REG_DEBUG
        printf("_jit_regs_assign()\n");
 #endif
 
-       /* Process pre-assigned registers. */
-
-       for(index = 0; index < regs->num_scratch; index++)
+       /* For binary or unary ops with explicitely assigned registers
+          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->scratch[index].reg < 0
-                  && regs->scratch[index].regset != jit_regused_init_used)
+               if(regs->descs[0].reg >= 0)
                {
-                       reg = use_cheapest_register(gen, regs, -1, 
regs->scratch[index].regset);
-                       if(reg < 0)
+                       if(regs->descs[1].reg < 0)
                        {
-                               return 0;
+                               set_regdesc_register(gen, regs, 1,
+                                                    regs->descs[0].reg,
+                                                    regs->descs[0].other_reg);
                        }
-                       set_scratch_register(gen, regs, index, reg);
+               }
+               else if(regs->descs[1].reg >= 0)
+               {
+                       set_regdesc_register(gen, regs, 0,
+                                            regs->descs[1].reg,
+                                            regs->descs[1].other_reg);
                }
        }
 
-       /* Determine the argument order. */
-
-       select_order(gen, regs);
-       out_index = 1 + (regs->reverse_dest ^ regs->reverse_args);
-
-       /* Assign the remaining registers. */
-
-       if(regs->ternary)
-       {
+       /* Assign output and input registers. */
                if(regs->descs[0].value && regs->descs[0].reg < 0)
                {
-                       use_cheapest_register(gen, regs, 0, 
regs->descs[0].regset);
-                       if(regs->descs[0].reg < 0)
+               if(regs->ternary)
+               {
+                       if(!choose_input_register(gen, regs, 0))
                        {
                                return 0;
                        }
-               }
                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 && regs->descs[0].reg >= 0 && 
regs->descs[out_index].value)
+               else
+               {
+                       if(!choose_output_register(gen, regs))
+                       {
+                               return 0;
+                       }
+                       if(!regs->free_dest)
        {
-               set_regdesc_register(gen, regs, out_index,
+                               choose_input_order(gen, regs);
+                               if(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)
        {
-               use_cheapest_register(gen, regs, 1, regs->descs[1].regset);
-               if(regs->descs[1].reg < 0)
+               if(!choose_input_register(gen, regs, 1))
                {
                        return 0;
                }
@@ -4246,40 +4245,21 @@
        check_duplicate_value(regs, &regs->descs[1], &regs->descs[2]);
        if(regs->descs[2].value && regs->descs[2].reg < 0)
        {
-               use_cheapest_register(gen, regs, 2, regs->descs[2].regset);
-               if(regs->descs[2].reg < 0)
-               {
-                       return 0;
-               }
-       }
-       if(regs->descs[0].value && regs->descs[0].reg < 0)
-       {
-               if(regs->free_dest || regs->descs[out_index].reg < 0)
-               {
-                       use_cheapest_register(gen, regs, 0, 
regs->descs[0].regset);
-                       if(regs->descs[0].reg < 0)
+               if(!choose_input_register(gen, regs, 2))
                        {
                                return 0;
                        }
                }
-               else
-               {
-                       set_regdesc_register(gen, regs, 0,
-                                            regs->descs[out_index].reg,
-                                            regs->descs[out_index].other_reg);
-               }
-       }
 
+       /* Assign scratch registers. */
        for(index = 0; index < regs->num_scratch; index++)
        {
                if(regs->scratch[index].reg < 0)
                {
-                       reg = use_cheapest_register(gen, regs, -1, 
jit_regused_init_used);
-                       if(reg < 0)
+                       if(choose_scratch_register(gen, regs, index) < 0)
                        {
                                return 0;
                        }
-                       set_scratch_register(gen, regs, index, reg);
                }
        }
 

Index: jit/jit-rules-x86.ins
===================================================================
RCS file: /sources/dotgnu-pnet/libjit/jit/jit-rules-x86.ins,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -b -r1.11 -r1.12
--- jit/jit-rules-x86.ins       6 Jul 2006 12:04:07 -0000       1.11
+++ jit/jit-rules-x86.ins       22 Aug 2006 17:30:09 -0000      1.12
@@ -635,12 +635,12 @@
                x86_patch(patch, inst);
                x86_clear_reg(inst, $1);
        }
-       [=reg("edx"), *reg("eax"), imm, scratch("?")] -> {
+       [=reg("edx"), *reg("eax"), imm, scratch("?", "edx")] -> {
                x86_mov_reg_imm(inst, $4, $3);
                x86_cdq(inst);
                x86_div_reg(inst, $4, 1);
        }
-       [=reg("edx"), *reg("eax"), reg] -> {
+       [=reg("edx"), *reg("eax"), reg, scratch("edx")] -> {
                unsigned char *patch, *patch2;
                x86_alu_reg_reg(inst, X86_OR, $3, $3);
                patch = inst;
@@ -671,12 +671,12 @@
                /* x & (x - 1) is equal to zero if x is a power of 2  */
                x86_alu_reg_imm(inst, X86_AND, $1, $2 - 1);
        }
-       [=reg("edx"), *reg("eax"), imm, scratch("?")] -> {
+       [=reg("edx"), *reg("eax"), imm, scratch("?", "edx")] -> {
                x86_mov_reg_imm(inst, $4, $3);
                x86_clear_reg(inst, X86_EDX);
                x86_div_reg(inst, $4, 0);
        }
-       [=reg("edx"), *reg("eax"), reg] -> {
+       [=reg("edx"), *reg("eax"), reg, scratch("edx")] -> {
                unsigned char *patch;
                x86_alu_reg_reg(inst, X86_OR, $3, $3);
                patch = inst;
@@ -1869,58 +1869,43 @@
  * Pointer-relative loads and stores.
  */
 
-JIT_OP_LOAD_RELATIVE_SBYTE: unary
-       [reg] -> {
-               x86_widen_membase(inst, $1, $1, insn->value2->address, 1, 0);
+JIT_OP_LOAD_RELATIVE_SBYTE:
+       [=reg, reg, imm] -> {
+               x86_widen_membase(inst, $1, $2, $3, 1, 0);
        }
 
-JIT_OP_LOAD_RELATIVE_UBYTE: unary
-       [reg] -> {
-               x86_widen_membase(inst, $1, $1, insn->value2->address, 0, 0);
+JIT_OP_LOAD_RELATIVE_UBYTE:
+       [=reg, reg, imm] -> {
+               x86_widen_membase(inst, $1, $2, $3, 0, 0);
        }
 
-JIT_OP_LOAD_RELATIVE_SHORT: unary
-       [reg] -> {
-               x86_widen_membase(inst, $1, $1, insn->value2->address, 1, 1);
+JIT_OP_LOAD_RELATIVE_SHORT:
+       [=reg, reg, imm] -> {
+               x86_widen_membase(inst, $1, $2, $3, 1, 1);
        }
 
-JIT_OP_LOAD_RELATIVE_USHORT: unary
-       [reg] -> {
-               x86_widen_membase(inst, $1, $1, insn->value2->address, 0, 1);
+JIT_OP_LOAD_RELATIVE_USHORT:
+       [=reg, reg, imm] -> {
+               x86_widen_membase(inst, $1, $2, $3, 0, 1);
        }
 
-JIT_OP_LOAD_RELATIVE_INT: unary
-       [reg] -> {
-               x86_mov_reg_membase(inst, $1, $1, insn->value2->address, 4);
+JIT_OP_LOAD_RELATIVE_INT:
+       [=reg, reg, imm] -> {
+               x86_mov_reg_membase(inst, $1, $2, $3, 4);
        }
 
-JIT_OP_LOAD_RELATIVE_LONG: manual
-       [] -> {
-               unsigned char *inst;
-               int reg = _jit_regs_load_value
-                       (gen, insn->value1, 0,
-                        (insn->flags & (JIT_INSN_VALUE1_NEXT_USE |
-                                                        
JIT_INSN_VALUE1_LIVE)));
-               int reg2, reg3;
-               int frame_offset;
-               _jit_gen_fix_value(insn->dest);
-               _jit_regs_get_reg_pair(gen, reg, -1, -1, &reg2, &reg3);
-               reg  = _jit_reg_info[reg].cpu_reg;
-               reg2 = _jit_reg_info[reg2].cpu_reg;
-               reg3 = _jit_reg_info[reg3].cpu_reg;
-               frame_offset = insn->dest->frame_offset;
-               inst = gen->posn.ptr;
-               if(!jit_cache_check_for_n(&(gen->posn), 32))
+JIT_OP_LOAD_RELATIVE_LONG:
+       [=lreg, reg, imm] -> {
+               if($1 == $2)
                {
-                       jit_cache_mark_full(&(gen->posn));
-                       return;
+                       x86_mov_reg_membase(inst, %1, $2, $3 + 4, 4);
+                       x86_mov_reg_membase(inst, $1, $2, $3, 4);
+               }
+               else
+               {
+                       x86_mov_reg_membase(inst, $1, $2, $3, 4);
+                       x86_mov_reg_membase(inst, %1, $2, $3 + 4, 4);
                }
-               x86_mov_reg_membase(inst, reg2, reg, insn->value2->address, 4);
-               x86_mov_reg_membase(inst, reg3, reg, insn->value2->address + 4, 
4);
-               x86_mov_membase_reg(inst, X86_EBP, frame_offset, reg2, 4);
-               x86_mov_membase_reg(inst, X86_EBP, frame_offset + 4, reg3, 4);
-               insn->dest->in_frame = 1;
-               gen->posn.ptr = inst;
        }
 
 JIT_OP_LOAD_RELATIVE_FLOAT32:
@@ -2078,61 +2063,43 @@
  * Array element loads and stores.
  */
 
-JIT_OP_LOAD_ELEMENT_SBYTE: binary
-       [reg, reg] -> {
-               x86_widen_memindex(inst, $1, $1, 0, $2, 0, 1, 0);
+JIT_OP_LOAD_ELEMENT_SBYTE:
+       [=reg, reg, reg] -> {
+               x86_widen_memindex(inst, $1, $2, 0, $3, 0, 1, 0);
        }
 
-JIT_OP_LOAD_ELEMENT_UBYTE: binary
-       [reg, reg] -> {
-               x86_widen_memindex(inst, $1, $1, 0, $2, 0, 0, 0);
+JIT_OP_LOAD_ELEMENT_UBYTE:
+       [=reg, reg, reg] -> {
+               x86_widen_memindex(inst, $1, $2, 0, $3, 0, 0, 0);
        }
 
-JIT_OP_LOAD_ELEMENT_SHORT: binary
-       [reg, reg] -> {
-               x86_widen_memindex(inst, $1, $1, 0, $2, 1, 1, 1);
+JIT_OP_LOAD_ELEMENT_SHORT:
+       [=reg, reg, reg] -> {
+               x86_widen_memindex(inst, $1, $2, 0, $3, 1, 1, 1);
        }
 
-JIT_OP_LOAD_ELEMENT_USHORT: binary
-       [reg, reg] -> {
-               x86_widen_memindex(inst, $1, $1, 0, $2, 1, 0, 1);
+JIT_OP_LOAD_ELEMENT_USHORT:
+       [=reg, reg, reg] -> {
+               x86_widen_memindex(inst, $1, $2, 0, $3, 1, 0, 1);
        }
 
-JIT_OP_LOAD_ELEMENT_INT: binary
-       [reg, reg] -> {
-               x86_mov_reg_memindex(inst, $1, $1, 0, $2, 2, 4);
+JIT_OP_LOAD_ELEMENT_INT:
+       [=reg, reg, reg] -> {
+               x86_mov_reg_memindex(inst, $1, $2, 0, $3, 2, 4);
        }
 
-JIT_OP_LOAD_ELEMENT_LONG: manual
-       [] -> {
-               unsigned char *inst;
-               int reg, reg2, temp_reg, offset;
-               _jit_regs_force_out(gen, insn->dest, 1);
-               _jit_gen_fix_value(insn->dest);
-               reg = _jit_regs_load_value
-                       (gen, insn->value1, 0,
-                        (insn->flags & (JIT_INSN_VALUE1_NEXT_USE |
-                                                        
JIT_INSN_VALUE1_LIVE)));
-               reg2 = _jit_regs_load_value
-                       (gen, insn->value2, 1,
-                        (insn->flags & (JIT_INSN_VALUE2_NEXT_USE |
-                                                        
JIT_INSN_VALUE2_LIVE)));
-               _jit_regs_get_reg_pair(gen, reg, reg2, -1, &temp_reg, 0);
-               offset = insn->dest->frame_offset;
-               inst = gen->posn.ptr;
-               if(!jit_cache_check_for_n(&(gen->posn), 32))
+JIT_OP_LOAD_ELEMENT_LONG:
+       [=lreg, reg, reg] -> {
+               if($1 == $2 || $1 == $3)
                {
-                       jit_cache_mark_full(&(gen->posn));
-                       return;
+                       x86_mov_reg_memindex(inst, %1, $2, 4, $3, 3, 4);
+                       x86_mov_reg_memindex(inst, $1, $2, 0, $3, 3, 4);
+               }
+               else
+               {
+                       x86_mov_reg_memindex(inst, $1, $2, 0, $3, 3, 4);
+                       x86_mov_reg_memindex(inst, %1, $2, 4, $3, 3, 4);
                }
-               reg = _jit_reg_info[reg].cpu_reg;
-               reg2 = _jit_reg_info[reg2].cpu_reg;
-               temp_reg = _jit_reg_info[temp_reg].cpu_reg;
-               x86_mov_reg_memindex(inst, temp_reg, reg, 0, reg2, 3, 4);
-               x86_mov_reg_memindex(inst, reg2, reg, 4, reg2, 3, 4);
-               x86_mov_membase_reg(inst, X86_EBP, offset, temp_reg, 4);
-               x86_mov_membase_reg(inst, X86_EBP, offset + 4, reg2, 4);
-               gen->posn.ptr = inst;
        }
 
 JIT_OP_LOAD_ELEMENT_FLOAT32:




reply via email to

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