[Top][All Lists]
[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 = ®s->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 = ®s->descs[1];
desc2 = ®s->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 = ®s->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 = ®s->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 = ®s->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 = ®s->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 = ®s->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 = ®s->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);