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-...


From: Aleksey Demakov
Subject: [dotgnu-pnet-commits] libjit ./ChangeLog jit/jit-reg-alloc.h jit/jit-...
Date: Fri, 19 May 2006 17:38:32 +0000

CVSROOT:        /sources/dotgnu-pnet
Module name:    libjit
Branch:         
Changes by:     Aleksey Demakov <address@hidden>        06/05/19 17:38:32

Modified files:
        .              : ChangeLog 
        jit            : jit-reg-alloc.h jit-reg-alloc.c 

Log message:
        Save input values beforehand. Clean up and refactor spill code.

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/dotgnu-pnet/libjit/ChangeLog.diff?tr1=1.226&tr2=1.227&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/dotgnu-pnet/libjit/jit/jit-reg-alloc.h.diff?tr1=1.11&tr2=1.12&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/dotgnu-pnet/libjit/jit/jit-reg-alloc.c.diff?tr1=1.27&tr2=1.28&r1=text&r2=text

Patches:
Index: libjit/ChangeLog
diff -u libjit/ChangeLog:1.226 libjit/ChangeLog:1.227
--- libjit/ChangeLog:1.226      Wed May 10 16:39:33 2006
+++ libjit/ChangeLog    Fri May 19 17:38:31 2006
@@ -1,3 +1,14 @@
+2006-05-19  Aleksey Demakov  <address@hidden>
+
+       * jit-reg-alloc.h, jit/jit-reg-alloc.c: determine if input values
+       need to be saved and evicted from registers to stack frame at the
+       _jit_regs_assign() time. Uniformly save input values that need to
+       in _jit_regs_gen(), do not save them in _jit_regs_commit(). This
+       simplifies handling of stack registers. Remove initial_stack_top,
+       exchanges, num_exchages fields from the _jit_regs_t struct. Add
+       save and kill bit fields to the _jit_regdesc_t struct. Refactor
+       and clean up code.
+
 2006-05-10  Aleksey Demakov  <address@hidden>
 
        * jit/jit-reg-alloc.c (use_cheapest_register): check if the other
Index: libjit/jit/jit-reg-alloc.c
diff -u libjit/jit/jit-reg-alloc.c:1.27 libjit/jit/jit-reg-alloc.c:1.28
--- libjit/jit/jit-reg-alloc.c:1.27     Wed May 10 16:39:33 2006
+++ libjit/jit/jit-reg-alloc.c  Fri May 19 17:38:32 2006
@@ -1643,8 +1643,9 @@
 
 /* Value usage flags. */
 #define VALUE_INPUT            1
-#define VALUE_OUTPUT           2
-#define VALUE_USED             4
+#define VALUE_USED             2
+#define VALUE_LIVE             4
+#define VALUE_DEAD             8
 
 /* Clobber flags. */
 #define CLOBBER_NONE           0
@@ -1741,33 +1742,74 @@
 
 /*
  * Check if the value is used in and after the current instruction.
+ *
+ * The value is dead if it is the output value of the instruction and hence
+ * just about to be recomputed or if it is one of the input values and its
+ * usage flags are not set. Otherwise the value is alive.
  */
 static int
 value_usage(_jit_regs_t *regs, jit_value_t value)
 {
-       int flags = 0;
+       int flags;
+
+       flags = 0;
+       if(value->is_constant)
+       {
+               flags |= VALUE_DEAD;
+       }
        if(value == regs->descs[0].value)
        {
-               flags |= regs->ternary ? VALUE_INPUT : VALUE_OUTPUT;
-               if(regs->descs[0].used || regs->descs[0].live)
+               if(regs->ternary)
+               {
+                       flags |= VALUE_INPUT;
+                       if(regs->descs[0].used)
+                       {
+                               flags |= VALUE_LIVE | VALUE_USED;
+                       }
+                       else if(regs->descs[0].live)
+                       {
+                               flags |= VALUE_LIVE;
+                       }
+                       else
+                       {
+                               flags |= VALUE_DEAD;
+                       }
+               }
+               else
                {
-                       flags |= VALUE_USED;
+                       flags |= VALUE_DEAD;
                }
        }
        if(value == regs->descs[1].value)
        {
                flags |= VALUE_INPUT;
-               if(regs->descs[1].used || regs->descs[1].live)
+               if(regs->descs[1].used)
                {
-                       flags |= VALUE_USED;
+                       flags |= VALUE_LIVE | VALUE_USED;
+               }
+               else if(regs->descs[1].live)
+               {
+                       flags |= VALUE_LIVE;
+               }
+               else
+               {
+                       flags |= VALUE_DEAD;
                }
        }
        if(value == regs->descs[2].value)
        {
                flags |= VALUE_INPUT;
-               if(regs->descs[2].used || regs->descs[2].live)
+               if(regs->descs[2].used)
+               {
+                       flags |= VALUE_LIVE | VALUE_USED;
+               }
+               else if(regs->descs[2].live)
                {
-                       flags |= VALUE_USED;
+                       flags |= VALUE_LIVE;
+               }
+               else
+               {
+                       flags |= VALUE_DEAD;
                }
        }
        return flags;
@@ -1780,31 +1822,16 @@
 is_register_alive(jit_gencode_t gen, _jit_regs_t *regs, int reg)
 {
        int index, usage;
-       jit_value_t value;
 
-       if(reg < 0)
-       {
-               return 0;
-       }
-
-       for(index = 0; index < gen->contents[reg].num_values; index++)
+       if(reg >= 0)
        {
-               value = gen->contents[reg].values[index];
-               if(value->is_constant)
+               for(index = 0; index < gen->contents[reg].num_values; index++)
                {
-                       continue;
-               }
-
-               /* The value is dead if it is the output value of the
-                  instruction and hence just about to be recomputed
-                  or if it is one of the input values and its usage
-                  flags are not set. Otherwise the value is alive. */
-               usage = value_usage(regs, value);
-               if((usage & VALUE_OUTPUT) == 0
-                  && ((usage & VALUE_INPUT) == 0
-                      || (usage & VALUE_USED) != 0))
-               {
-                       return 1;
+                       usage = value_usage(regs, 
gen->contents[reg].values[index]);
+                       if((usage & VALUE_DEAD) == 0)
+                       {
+                               return 1;
+                       }
                }
        }
        return 0;
@@ -1975,8 +2002,10 @@
        desc->clobber = 0;
        desc->early_clobber = 0;
        desc->duplicate = 0;
+       desc->save = 0;
        desc->load = 0;
        desc->copy = 0;
+       desc->kill = 0;
 }
 
 /*
@@ -2032,17 +2061,18 @@
 }
 
 static int
-collect_register_info(_jit_regs_t *regs, int index)
+collect_register_info(jit_gencode_t gen, _jit_regs_t *regs, int index)
 {
        _jit_regdesc_t *desc;
+       int reg, other_reg;
        int stack_start;
 
+#ifdef JIT_REG_DEBUG
+       printf("collect_register_info(index = %d)\n", index);
+#endif
+
        desc = &regs->descs[index];
-       if(desc->reg < 0)
-       {
-               return 1;
-       }
-       if(desc->duplicate)
+       if(desc->reg < 0 || desc->duplicate)
        {
                return 1;
        }
@@ -2067,6 +2097,61 @@
                }
        }
 
+       if(index > 0 || regs->ternary)
+       {
+               if(desc->value->is_constant)
+               {
+                       desc->kill = 1;
+               }
+               else if(desc->value->in_register)
+               {
+                       reg = desc->value->reg;
+                       if(gen->contents[reg].is_long_start)
+                       {
+                               other_reg = OTHER_REG(reg);
+                       }
+                       else
+                       {
+                               other_reg = -1;
+                       }
+
+                       if(desc->used)
+                       {
+                               if(jit_reg_is_used(regs->clobber, reg)
+                                  || (other_reg >= 0
+                                      && jit_reg_is_used(regs->clobber, 
other_reg)))
+                               {
+                                       desc->save = 1;
+                                       desc->kill = 1;
+                               }
+                       }
+                       else
+                       {
+                               if(desc->live)
+                               {
+                                       desc->save = 1;
+                               }
+                               desc->kill = 1;
+                       }
+               }
+               else if(desc->load)
+               {
+                       if(desc->used)
+                       {
+                               if(jit_reg_is_used(regs->clobber, desc->reg)
+                                  || (desc->other_reg >= 0
+                                      && jit_reg_is_used(regs->clobber, 
desc->other_reg)))
+                               {
+                                       desc->kill = 1;
+                               }
+                       }
+                       else
+                       {
+                               desc->kill = 1;
+                       }
+               }
+       }
+
        if(IS_STACK_REG(desc->reg))
        {
                stack_start = get_stack_start(desc->reg);
@@ -2089,6 +2174,23 @@
                }
        }
 
+#ifdef JIT_REG_DEBUG
+       printf("value = ");
+       jit_dump_value(stdout, jit_value_get_function(desc->value), 
desc->value, 0);
+       printf("\n");
+       printf("reg = %d\n", desc->reg);
+       printf("other_reg = %d\n", desc->other_reg);
+       printf("live = %d\n", desc->live);
+       printf("used = %d\n", desc->used);
+       printf("clobber = %d\n", desc->clobber);
+       printf("early_clobber = %d\n", desc->early_clobber);
+       printf("duplicate = %d\n", desc->duplicate);
+       printf("save = %d\n", desc->save);
+       printf("load = %d\n", desc->load);
+       printf("copy = %d\n", desc->copy);
+       printf("kill = %d\n", desc->kill);
+#endif
+
        return 1;
 }
 
@@ -2165,17 +2267,17 @@
        for(index = 0; index < gen->contents[reg].num_values; index++)
        {
                value = gen->contents[reg].values[index];
-               if(value->is_constant)
-               {
-                       continue;
-               }
                usage = value_usage(regs, value);
-               if((usage & VALUE_OUTPUT) != 0)
+               if((usage & VALUE_DEAD) != 0)
                {
+                       /* the value is not spilled */
                        continue;
                }
-               if((usage & VALUE_INPUT) != 0 && (usage & VALUE_USED) == 0)
+               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)
@@ -2198,17 +2300,17 @@
                for(index = 0; index < gen->contents[other_reg].num_values; 
index++)
                {
                        value = gen->contents[other_reg].values[index];
-                       if(value->is_constant)
-                       {
-                               continue;
-                       }
                        usage = value_usage(regs, value);
-                       if((usage & VALUE_OUTPUT) != 0)
+                       if((usage & VALUE_DEAD) != 0)
                        {
+                               /* the value is not spilled */
                                continue;
                        }
-                       if((usage & VALUE_INPUT) != 0 && (usage & VALUE_USED) 
== 0)
+                       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)
@@ -2417,17 +2519,24 @@
        }
 
        reg = suitable_reg;
-       if(desc && reg >= 0)
+       if(reg >= 0)
        {
-               if(need_pair)
+               if(desc)
                {
-                       other_reg = OTHER_REG(reg);
+                       if(need_pair)
+                       {
+                               other_reg = OTHER_REG(reg);
+                       }
+                       else
+                       {
+                               other_reg = -1;
+                       }
+                       set_regdesc_register(gen, regs, index, reg, other_reg);
                }
                else
                {
-                       other_reg = -1;
+                       set_register_flags(gen, regs, reg, 1, 0);
                }
-               set_regdesc_register(gen, regs, index, reg, other_reg);
        }
 
        return reg;
@@ -2585,32 +2694,6 @@
        return;
 }
 
-static int
-adjust_register(_jit_regs_t *regs, int reg)
-{
-       int index;
-       if(reg > regs->initial_stack_top)
-       {
-               reg -= regs->initial_stack_top;
-               reg += regs->current_stack_top;
-       }
-       else
-       {
-               for(index = 0; index < regs->num_exchanges; index++)
-               {
-                       if(reg == regs->exchanges[index][0])
-                       {
-                               reg = regs->exchanges[index][1];
-                       }
-                       else if(reg == regs->exchanges[index][1])
-                       {
-                               reg = regs->exchanges[index][0];
-                       }
-               }
-       }
-       return reg;
-}
-
 static void
 adjust_assignment(jit_gencode_t gen, _jit_regs_t *regs, int index)
 {
@@ -2630,13 +2713,16 @@
        else if(regs->wanted_stack_count == 2)
        {
                /* a binary op */
-               if(regs->x87_arith)
+
+               /* find the input value the output goes to */
+               if(index == 0)
                {
-                       desc->reg = adjust_register(regs, desc->reg);
+                       index = 1 + (regs->reverse_dest ^ regs->reverse_args);
                }
-               else if(index == 0)
+
+               if(regs->x87_arith && desc->value->in_register && !desc->copy)
                {
-                       desc->reg = regs->current_stack_top - 
regs->loaded_stack_count + 1;
+                       desc->reg = desc->value->reg;
                }
                else
                {
@@ -2664,19 +2750,30 @@
                desc1 = &regs->descs[1];
                desc2 = &regs->descs[2];
 
-               if(desc1->value->in_register && desc2->value->in_register)
+               if(desc1->value->in_register && !desc1->copy
+                  && desc2->value->in_register && !desc2->copy)
                {
-                       /* TODO: simulate spills and find out if any of the 
input
-                          values ends up on the stack top. */
-                       /* TODO: otherwise see if the next instruction wants 
output
-                          or remaining input to be on the stack top. */
-                       top_index = 2;
+                       /* Is any of the input values is on the stack top? */
+                       if(desc1->value->reg == regs->current_stack_top)
+                       {
+                               top_index = 1;
+                       }
+                       else if(desc1->value->reg == regs->current_stack_top)
+                       {
+                               top_index = 2;
+                       }
+                       else
+                       {
+                               /* TODO: See if the next instruction wants 
output
+                                  or remaining input to be on the stack top. */
+                               top_index = 2;
+                       }
                }
-               else if(desc1->value->in_register)
+               else if(desc1->value->in_register && !desc1->copy)
                {
                        top_index = 2;
                }
-               else if(desc2->value->in_register)
+               else if(desc2->value->in_register && !desc2->copy)
                {
                        top_index = 1;
                }
@@ -2746,6 +2843,9 @@
        gen->contents[reg].remap = -1;
 }
 
+/*
+ * Associate a temporary with register.
+ */
 static void
 bind_temporary(jit_gencode_t gen, int reg, int other_reg)
 {
@@ -2768,6 +2868,9 @@
        }
 }
 
+/*
+ * Associate value with register.
+ */
 static void
 bind_value(jit_gencode_t gen, jit_value_t value, int reg, int other_reg, int 
still_in_frame)
 {
@@ -2867,7 +2970,7 @@
 static void
 exch_stack_top(jit_gencode_t gen, int reg, int pop)
 {
-       int top, index;
+       int stack_start, top, index;
        int num_values, used_for_temp, age;
        jit_value_t value1, value2;
 
@@ -2881,118 +2984,166 @@
        }
 
        /* Find the top of the stack. */
-       top = gen->stack_map[get_stack_start(reg)];
+       stack_start = get_stack_start(reg);
+       top = get_stack_top(gen, stack_start);
 
        /* Generate exchange instruction. */
        _jit_gen_exch_top(gen, reg, pop);
+       if(pop)
+       {
+               remap_stack_down(gen, stack_start, top);
+       }
 
        /* Update information about the contents of the registers.  */
        for(index = 0;
            index < gen->contents[reg].num_values || index < 
gen->contents[top].num_values;
            index++)
        {
-               value1 = (index < gen->contents[reg].num_values
-                         ? gen->contents[reg].values[index] : 0);
-               value2 = (index < gen->contents[top].num_values
+               value1 = (index < gen->contents[top].num_values
                          ? gen->contents[top].values[index] : 0);
+               value2 = (index < gen->contents[reg].num_values
+                         ? gen->contents[reg].values[index] : 0);
+
+               if(value1)
+               {
+                       value1->reg = reg;
+               }
+               gen->contents[reg].values[index] = value1;
 
                if(pop)
                {
-                       if(value1)
+                       if(value2)
                        {
-                               value1->reg = -1;
+                               value2->reg = -1;
                        }
                        gen->contents[top].values[index] = 0;
                }
                else
                {
-                       if(value1)
+                       if(value2)
                        {
-                               value1->reg = top;
+                               value2->reg = top;
                        }
-                       gen->contents[top].values[index] = value1;
+                       gen->contents[top].values[index] = value2;
                }
-               if(value2)
-               {
-                       value2->reg = reg;
-               }
-               gen->contents[reg].values[index] = value2;
        }
 
-       num_values = gen->contents[top].num_values;
-       used_for_temp = gen->contents[top].used_for_temp;
-       age = gen->contents[top].age;
        if(pop)
        {
-               gen->contents[top].num_values = 0;
-               gen->contents[top].used_for_temp = 0;
-               gen->contents[top].age = 0;
+               num_values = 0;
+               used_for_temp = 0;
+               age = 0;
        }
        else
        {
-               gen->contents[top].num_values = gen->contents[reg].num_values;
-               gen->contents[top].used_for_temp = 
gen->contents[reg].used_for_temp;
-               gen->contents[top].age = gen->contents[reg].age;
-       }
-       gen->contents[reg].num_values = num_values;
-       gen->contents[reg].used_for_temp = used_for_temp;
-       gen->contents[reg].age = age;
+               num_values = gen->contents[reg].num_values;
+               used_for_temp = gen->contents[reg].used_for_temp;
+               age = gen->contents[reg].age;
+       }
+       gen->contents[reg].num_values = gen->contents[top].num_values;
+       gen->contents[reg].used_for_temp = gen->contents[top].used_for_temp;
+       gen->contents[reg].age = gen->contents[top].age;
+       gen->contents[top].num_values = num_values;
+       gen->contents[top].used_for_temp = used_for_temp;
+       gen->contents[top].age = age;
 }
 
 /*
- * Spill the top of the register stack.
+ * Drop value from register.
  */
 static void
-spill_stack_top(jit_gencode_t gen, _jit_regs_t *regs, int reg)
+free_value(jit_gencode_t gen, jit_value_t value, int reg, int other_reg)
 {
-       int stack_start, top, index;
-       jit_value_t value;
-       int usage, value_used;
-
 #ifdef JIT_REG_DEBUG
-       printf("spill_stack_top(reg = %d)\n", reg);
+       printf("free_value(value = ");
+       jit_dump_value(stdout, jit_value_get_function(value), value, 0);
+       printf(", reg = %d, other_reg = %d)\n", reg, other_reg);
 #endif
 
-       if(!IS_STACK_REG(reg))
+       /* Never free global registers. */
+       if(value->has_global_register)
        {
                return;
        }
 
-       stack_start = get_stack_start(reg);
-       top = get_stack_top(gen, stack_start);
-
-       value_used = 0;
-       for(index = gen->contents[top].num_values - 1; index >= 0; --index)
+       /* Free stack register. */
+       if(IS_STACK_REG(reg) && gen->contents[reg].num_values == 1)
        {
-               value = gen->contents[top].values[index];
+               exch_stack_top(gen, reg, 1);
+       }
 
-               usage = value_usage(regs, value);
-               if((usage & VALUE_INPUT) != 0 && (usage & VALUE_USED) == 0)
+       unbind_value(gen, value, reg, other_reg);
+}
+
+/*
+ * Save the value from the register into its frame position and optionally 
free it.
+ * If the value is already in the frame or is a constant then it is not saved 
but
+ * the free option still applies to them.
+ */
+static void
+save_value(jit_gencode_t gen, jit_value_t value, int reg, int other_reg, int 
free)
+{
+       int stack_start, top;
+
+#ifdef JIT_REG_DEBUG
+       printf("save_value(value = ");
+       jit_dump_value(stdout, jit_value_get_function(value), value, 0);
+       printf(", reg = %d, other_reg = %d)\n", reg, other_reg);
+#endif
+       /* First take care of values that reside in global registers. */
+       if(value->has_global_register)
+       {
+               if(value->global_reg != reg && !value->in_global_register)
                {
-                       continue;
+                       _jit_gen_spill_reg(gen, reg, other_reg, value);
+                       value->in_global_register = 1;
                }
+               return;
+       }
 
-               if(!(value->is_constant || value->in_frame || (usage & 
VALUE_OUTPUT) != 0))
+       /* Take care of constants and values that are already in frame. */
+       if(value->is_constant || value->in_frame)
+       {
+               if(free)
                {
-                       if((usage & VALUE_INPUT) == 0 && 
gen->contents[top].num_values == 1)
-                       {
-                               value_used = 1;
-                       }
+                       free_value(gen, value, reg, other_reg);
+               }
+               return;
+       }
 
-                       _jit_gen_spill_top(gen, top, value, value_used);
-                       value->in_frame = 1;
+       /* Now really save the value into frame. */
+       if(IS_STACK_REG(reg))
+       {
+               /* Find the top of the stack. */
+               stack_start = get_stack_start(reg);
+               top = get_stack_top(gen, stack_start);
+
+               /* Move the value on the stack top if it is already not there. 
*/
+               if(top != reg)
+               {
+                       exch_stack_top(gen, reg, 0);
                }
 
-               if((usage & VALUE_INPUT) == 0)
+               if(free && gen->contents[top].num_values == 1)
                {
-                       if(gen->contents[top].num_values == 1)
-                       {
-                               _jit_gen_free_reg(gen, top, -1, value_used);
-                               remap_stack_down(gen, stack_start, top);
-                       }
-                       unbind_value(gen, value, top, -1);
+                       _jit_gen_spill_top(gen, top, value, 1);
+                       remap_stack_down(gen, stack_start, top);
+               }
+               else
+               {
+                       _jit_gen_spill_top(gen, top, value, 0);
                }
        }
+       else
+       {
+               _jit_gen_spill_reg(gen, reg, other_reg, value);
+       }
+
+       if(free)
+       {
+               unbind_value(gen, value, reg, other_reg);
+       }
+       value->in_frame = 1;
 }
 
 /*
@@ -3029,135 +3180,121 @@
                other_reg = -1;
        }
 
+       /* Spill register contents in two passes. First free values that
+          do not reqiure spilling then spill those that do. This approach
+          is only useful in case a stack register contains both kinds of
+          values and the last value is one that does not require spilling.
+          This way we may save one free instruction. */
+       if(IS_STACK_REG(reg))
+       {
+               for(index = gen->contents[reg].num_values - 1; index >= 0; 
--index)
+               {
+                       value = gen->contents[reg].values[index];
+                       usage = value_usage(regs, value);
+                       if((usage & VALUE_INPUT) == 0
+                          && ((usage & VALUE_DEAD) != 0 || value->in_frame))
+                       {
+                               free_value(gen, value, reg, other_reg);
+                       }
+               }
+       }
        for(index = gen->contents[reg].num_values - 1; index >= 0; --index)
        {
                value = gen->contents[reg].values[index];
-
                usage = value_usage(regs, value);
-               if((usage & VALUE_INPUT) != 0 && (usage & VALUE_USED) == 0)
+               if((usage & VALUE_DEAD) == 0)
                {
-                       continue;
-               }
-
-               if((usage & VALUE_OUTPUT) == 0)
-               {
-                       if(value->has_global_register)
+                       if((usage & VALUE_INPUT) == 0)
                        {
-                               if(!value->in_global_register)
-                               {
-                                       _jit_gen_spill_reg(gen, reg, other_reg, 
value);
-                                       value->in_global_register = 1;
-                               }
+                               save_value(gen, value, reg, other_reg, 1);
                        }
                        else
                        {
-                               if(!(value->is_constant || value->in_frame))
-                               {
-                                       _jit_gen_spill_reg(gen, reg, other_reg, 
value);
-                                       value->in_frame = 1;
-                               }
+                               save_value(gen, value, reg, other_reg, 0);
                        }
                }
-
-               if((usage & VALUE_INPUT) == 0)
+               else
                {
-                       unbind_value(gen, value, reg, other_reg);
+                       if((usage & VALUE_INPUT) == 0)
+                       {
+                               free_value(gen, value, reg, other_reg);
+                       }
                }
        }
 }
 
 static void
-adjust_top_value(jit_gencode_t gen, _jit_regs_t *regs, int index, int top, int 
reg)
+update_age(jit_gencode_t gen, _jit_regdesc_t *desc)
 {
-       if(regs->descs[index].stack_reg == top)
+       int reg, other_reg;
+
+       reg = desc->value->reg;
+       if(gen->contents[reg].is_long_start)
        {
-               regs->descs[index].stack_reg = reg;
+               other_reg = OTHER_REG(reg);
+       }
+       else
+       {
+               other_reg = -1;
        }
-}
 
-static void
-adjust_top_values(jit_gencode_t gen, _jit_regs_t *regs, int top, int reg)
-{
-       if(regs->ternary)
+       gen->contents[reg].age = gen->current_age;
+       if(other_reg >= 0)
        {
-               adjust_top_value(gen, regs, 0, top, reg);
+               gen->contents[other_reg].age = gen->current_age;
        }
-       adjust_top_value(gen, regs, 1, top, reg);
-       adjust_top_value(gen, regs, 2, top, reg);
+       ++(gen->current_age);
 }
 
 static void
-spill_value(jit_gencode_t gen, _jit_regs_t *regs, jit_value_t value, int reg, 
int other_reg)
+save_input_value(jit_gencode_t gen, _jit_regs_t *regs, int index)
 {
-       int top;
+       _jit_regdesc_t *desc;
+       int reg, other_reg;
 
 #ifdef JIT_REG_DEBUG
-       printf("spill_value(value = ");
-       jit_dump_value(stdout, jit_value_get_function(value), value, 0);
-       printf(", reg = %d, other_reg = %d)\n", reg, other_reg);
+       printf("save_input_value(%d)\n", index);
 #endif
 
-       if(IS_STACK_REG(reg))
+       desc = &regs->descs[index];
+       if(!(desc->value && desc->value->in_register && desc->save))
        {
-               top = get_stack_top(gen, regs->stack_start);
-               if(top != reg)
-               {
-                       exch_stack_top(gen, reg, 0);
-                       adjust_top_values(gen, regs, top, reg);
-               }
+               return;
+       }
 
-               if(!(value->is_constant || value->in_frame))
-               {
-                       if(gen->contents[top].num_values == 1)
-                       {
-                               _jit_gen_spill_top(gen, top, value, 1);
-                       }
-                       else
-                       {
-                               _jit_gen_spill_top(gen, top, value, 0);
-                       }
-                       value->in_frame = 1;
-               }
-               else
-               {
-                       if(gen->contents[top].num_values == 1)
-                       {
-                               _jit_gen_exch_top(gen, top, 1);
-                       }
-               }
-               if(gen->contents[top].num_values == 1)
-               {
-                       remap_stack_down(gen, regs->stack_start, top);
-               }
-               unbind_value(gen, value, top, -1);
+       reg = desc->value->reg;
+       if(gen->contents[reg].is_long_start)
+       {
+               other_reg = OTHER_REG(reg);
        }
        else
        {
-               if(value->has_global_register)
-               {
-                       if(value->global_reg != reg && 
!value->in_global_register)
-                       {
-                               _jit_gen_spill_reg(gen, reg, other_reg, value);
-                               value->in_global_register = 1;
-                       }
-               }
-               else
-               {
-                       if(!value->in_frame)
-                       {
-                               _jit_gen_spill_reg(gen, reg, other_reg, value);
-                               value->in_frame = 1;
-                       }
-               }
-               unbind_value(gen, value, reg, other_reg);
+               other_reg = -1;
        }
+
+       save_value(gen, desc->value, reg, other_reg, 0);
 }
 
 static void
-update_age(jit_gencode_t gen, _jit_regdesc_t *desc)
+free_output_value(jit_gencode_t gen, _jit_regs_t *regs)
 {
+       _jit_regdesc_t *desc;
        int reg, other_reg;
 
+#ifdef JIT_REG_DEBUG
+       printf("free_output_value()\n");
+#endif
+
+       desc = &regs->descs[0];
+       if(!(desc->value && desc->value->in_register))
+       {
+               return;
+       }
+       if(desc->value == regs->descs[1].value || desc->value == 
regs->descs[2].value)
+       {
+               return;
+       }
+
        reg = desc->value->reg;
        if(gen->contents[reg].is_long_start)
        {
@@ -3168,12 +3305,7 @@
                other_reg = -1;
        }
 
-       gen->contents[reg].age = gen->current_age;
-       if(other_reg >= 0)
-       {
-               gen->contents[other_reg].age = gen->current_age;
-       }
-       ++(gen->current_age);
+       free_value(gen, desc->value, reg, other_reg);
 }
 
 static void
@@ -3181,6 +3313,10 @@
 {
        _jit_regdesc_t *desc;
 
+#ifdef JIT_REG_DEBUG
+       printf("load_input_value(%d)\n", index);
+#endif
+
        desc = &regs->descs[index];
        if(!desc->value || desc->duplicate)
        {
@@ -3248,6 +3384,10 @@
        _jit_regdesc_t *desc;
        int src_reg, dst_reg;
 
+#ifdef JIT_REG_DEBUG
+       printf("move_input_value(%d)\n", index);
+#endif
+
        desc = &regs->descs[index];
        if(!desc->value || desc->duplicate || !desc->value->in_register)
        {
@@ -3305,65 +3445,71 @@
        _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->value->in_register))
+       if(!desc->value || desc->duplicate)
        {
                return;
        }
 
-       reg = desc->value->reg;
-       if(gen->contents[reg].is_long_start)
-       {
-               other_reg = OTHER_REG(reg);
-       }
-       else
+       if(desc->copy)
        {
-               other_reg = -1;
+               if(IS_STACK_REG(desc->reg))
+               {
+                       remap_stack_down(gen, regs->stack_start, desc->reg);
+               }
+               gen->contents[desc->reg].used_for_temp = 0;
+               if(desc->other_reg >= 0)
+               {
+                       gen->contents[desc->other_reg].used_for_temp = 0;
+               }
        }
 
-       /* If the value is clobbered then it must have been spilled
-          before the operation. Simply unbind it here. */
-       if(jit_reg_is_used(regs->clobber, reg)
-          || (other_reg >= 0 && jit_reg_is_used(regs->clobber, other_reg)))
+       if(desc->kill && desc->value->in_register)
        {
-               if(IS_STACK_REG(reg))
+               reg = desc->value->reg;
+               if(gen->contents[reg].is_long_start)
                {
-                       unbind_value(gen, desc->value, reg, -1);
-                       remap_stack_down(gen, regs->stack_start, reg);
+                       other_reg = OTHER_REG(reg);
                }
                else
                {
-                       unbind_value(gen, desc->value, reg, other_reg);
-#if 0
-                       if(!(jit_reg_is_used(regs->clobber, desc->reg)
-                            || (desc->other_reg >= 0
-                                && jit_reg_is_used(regs->clobber, 
desc->other_reg))))
-                       {
-                               bind_value(gen, desc->value, desc->reg, 
desc->other_reg, 1);
-                       }
-#endif
+                       other_reg = -1;
                }
-               return;
-       }
 
-       if(!desc->used)
-       {
-               if(desc->live || (IS_STACK_REG(reg) && 
gen->contents[reg].num_values == 1))
+               if(IS_STACK_REG(reg))
                {
-                       spill_value(gen, regs, desc->value, reg, other_reg);
+                       unbind_value(gen, desc->value, reg, -1);
+                       remap_stack_down(gen, regs->stack_start, reg);
                }
                else
                {
                        unbind_value(gen, desc->value, reg, other_reg);
                }
        }
+
+#ifdef JIT_REG_DEBUG
+       printf("value = ");
+       jit_dump_value(stdout, jit_value_get_function(desc->value), 
desc->value, 0);
+       printf("\n");
+       printf("value->in_register = %d\n", desc->value->in_register);
+       printf("value->reg = %d\n", desc->value->reg);
+       printf("value->in_gloable_register = %d\n", 
desc->value->in_global_register);
+       printf("value->in_frame = %d\n", desc->value->in_frame);
+#endif
 }
 
 static void
 commit_output_value(jit_gencode_t gen, _jit_regs_t *regs)
 {
        _jit_regdesc_t *desc;
-       int reg, other_reg;
+
+#ifdef JIT_REG_DEBUG
+       printf("commit_output_value()\n");
+#endif
 
        desc = &regs->descs[0];
        if(!desc->value)
@@ -3371,42 +3517,36 @@
                return;
        }
 
-       if(desc->value->in_register)
+       if(IS_STACK_REG(desc->reg))
        {
-               reg = desc->value->reg;
-               if(gen->contents[reg].is_long_start)
-               {
-                       other_reg = OTHER_REG(reg);
-               }
-               else
-               {
-                       other_reg = -1;
-               }
-               unbind_value(gen, desc->value, reg, other_reg);
+               bind_value(gen, desc->value, desc->reg, -1, 0);
+               remap_stack_up(gen, regs->stack_start, desc->reg);
        }
-       if(desc->used || desc->live || IS_STACK_REG(desc->reg))
+       else
        {
-               if(IS_STACK_REG(desc->reg))
+               bind_value(gen, desc->value, desc->reg, desc->other_reg, 0);
+       }
+       if(!desc->used)
+       {
+               if(desc->live)
                {
-                       bind_value(gen, desc->value, desc->reg, -1, 0);
-                       remap_stack_up(gen, regs->stack_start, desc->reg);
+                       save_value(gen, desc->value, desc->reg, 
desc->other_reg, 1);
                }
                else
                {
-                       bind_value(gen, desc->value, desc->reg, 
desc->other_reg, 0);
-               }
-               if(!desc->used)
-               {
-                       if(desc->live || IS_STACK_REG(desc->reg))
-                       {
-                               spill_value(gen, regs, desc->value, desc->reg, 
desc->other_reg);
-                       }
-                       else
-                       {
-                               unbind_value(gen, desc->value, desc->reg, 
desc->other_reg);
-                       }
+                       free_value(gen, desc->value, desc->reg, 
desc->other_reg);
                }
        }
+
+#ifdef JIT_REG_DEBUG
+       printf("value = ");
+       jit_dump_value(stdout, jit_value_get_function(desc->value), 
desc->value, 0);
+       printf("\n");
+       printf("value->in_register = %d\n", desc->value->in_register);
+       printf("value->reg = %d\n", desc->value->reg);
+       printf("value->in_gloable_register = %d\n", 
desc->value->in_global_register);
+       printf("value->in_frame = %d\n", desc->value->in_frame);
+#endif
 }
 
 void
@@ -3443,11 +3583,9 @@
        regs->spill = jit_regused_init;
 
        regs->stack_start = -1;
-       regs->initial_stack_top = 0;
        regs->current_stack_top = 0;
        regs->wanted_stack_count = 0;
        regs->loaded_stack_count = 0;
-       regs->num_exchanges = 0;
 }
 
 void
@@ -3598,7 +3736,7 @@
        int index, out_index;
 
 #ifdef JIT_REG_DEBUG
-       dump_regs(gen, "enter _jit_regs_assign");
+       printf("_jit_regs_assign()\n");
 #endif
 
        /* Set clobber flags. */
@@ -3613,10 +3751,12 @@
                {
                        jit_reg_set_used(regs->clobber, index);
                }
+#if 0
                if(jit_reg_is_used(regs->clobber, index))
                {
                        jit_reg_set_used(gen->touched, index);
                }
+#endif
        }
 
        /* Spill all clobbered registers. */
@@ -3677,7 +3817,6 @@
                        {
                                return 0;
                        }
-                       set_register_flags(gen, regs, regs->scratch[index].reg, 
1, 0);
                }
        }
 
@@ -3707,8 +3846,10 @@
                {
                        if(regs->descs[out_index].value->in_register
                           && 
gen->contents[regs->descs[out_index].value->reg].num_values == 1
-                          && !(regs->descs[out_index].live || 
regs->descs[out_index].used))
+                          && !(/*regs->descs[out_index].live 
||*/regs->descs[out_index].used))
                        {
+                               /* NOTE: The last condition makes sense for 
local register
+                                  allocation, review it for future global 
allocator. */
                                use_cheapest_register(
                                        gen, regs, out_index, 
regs->descs[out_index].regset);
                                if(regs->descs[out_index].reg < 0)
@@ -3779,27 +3920,23 @@
                        {
                                return 0;
                        }
-                       set_register_flags(gen, regs, regs->scratch[index].reg, 
1, 0);
                }
        }
 
        /* Collect information about registers. */
-       if(!collect_register_info(regs, 0))
+       if(!collect_register_info(gen, regs, 0))
        {
                return 0;
        }
-       if(!collect_register_info(regs, 1))
+       if(!collect_register_info(gen, regs, 1))
        {
                return 0;
        }
-       if(!collect_register_info(regs, 2))
+       if(!collect_register_info(gen, regs, 2))
        {
                return 0;
        }
 
-#ifdef JIT_REG_DEBUG
-       dump_regs(gen, "leave _jit_regs_assign");
-#endif
        return 1;
 }
 
@@ -3812,12 +3949,6 @@
        dump_regs(gen, "enter _jit_regs_gen");
 #endif
 
-       /* Remember initial stack size. */
-       if(regs->wanted_stack_count > 0)
-       {
-               regs->initial_stack_top = get_stack_top(gen, regs->stack_start);
-       }
-
        /* Spill clobbered registers. */
        stack_start = 0;
        for(reg = 0; reg < JIT_NUM_REGS; reg++)
@@ -3856,40 +3987,26 @@
                   As we spill each one, something else will become the top */
                if(IS_STACK_REG(reg))
                {
-                       top = gen->stack_map[stack_start];
+                       top = get_stack_top(gen, stack_start);
                        while(top > reg && jit_reg_is_used(regs->spill, top))
                        {
-                               spill_stack_top(gen, regs, stack_start);
+                               spill_reg(gen, regs, top);
+                               /* If one of the input values is on the top
+                                  spill_reg() will not pop it. */
                                if(gen->contents[top].num_values > 0)
                                {
-                                       /* If one of the input values is on the 
top
-                                          spill_stack_top() does not pop it. */
                                        break;
                                }
-                               top = gen->stack_map[stack_start];
+                               top = get_stack_top(gen, stack_start);
                        }
                        if(top > reg)
                        {
                                exch_stack_top(gen, reg, 0);
-                               if(regs->num_exchanges >= 
_JIT_REGS_MAX_EXCHANGES)
-                               {
-                                       return 0;
-                               }
-                               regs->exchanges[regs->num_exchanges][0] = top;
-                               regs->exchanges[regs->num_exchanges][1] = reg;
-                               ++(regs->num_exchanges);
-
-                               if(jit_reg_is_used(regs->spill, top))
-                               {
-                                       jit_reg_set_used(regs->spill, reg);
-                               }
-                               else
-                               {
-                                       jit_reg_clear_used(regs->spill, reg);
-                               }
-                               jit_reg_set_used(regs->spill, top);
                        }
-                       spill_stack_top(gen, regs, stack_start);
+                       if(top >= stack_start)
+                       {
+                               spill_reg(gen, regs, top);
+                       }
                }
                else
                {
@@ -3897,6 +4014,18 @@
                }
        }
 
+       /* Save input values if necessary and free output value if it is in a 
register */
+       if(regs->ternary)
+       {
+               save_input_value(gen, regs, 0);
+       }
+       else
+       {
+               free_output_value(gen, regs);
+       }
+       save_input_value(gen, regs, 1);
+       save_input_value(gen, regs, 2);
+
        /* Adjust assignment of stack registers. */
        if(regs->wanted_stack_count > 0)
        {
Index: libjit/jit/jit-reg-alloc.h
diff -u libjit/jit/jit-reg-alloc.h:1.11 libjit/jit/jit-reg-alloc.h:1.12
--- libjit/jit/jit-reg-alloc.h:1.11     Wed May 10 16:39:33 2006
+++ libjit/jit/jit-reg-alloc.h  Fri May 19 17:38:31 2006
@@ -120,8 +120,10 @@
        unsigned        clobber : 1;
        unsigned        early_clobber : 1;
        unsigned        duplicate : 1;
+       unsigned        save : 1;
        unsigned        load : 1;
        unsigned        copy : 1;
+       unsigned        kill : 1;
 
 } _jit_regdesc_t;
 
@@ -162,12 +164,9 @@
        jit_regused_t   spill;
 
        int             stack_start;
-       int             initial_stack_top;
        int             current_stack_top;
        int             wanted_stack_count;
        int             loaded_stack_count;
-       int             exchanges[_JIT_REGS_MAX_EXCHANGES][2];
-       int             num_exchanges;
 } _jit_regs_t;
 
 void _jit_regs_init(_jit_regs_t *regs, int flags);




reply via email to

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