[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, 05 May 2006 10:13:07 +0000 |
CVSROOT: /sources/dotgnu-pnet
Module name: libjit
Branch:
Changes by: Aleksey Demakov <address@hidden> 06/05/05 10:13:07
Modified files:
. : ChangeLog
jit : jit-reg-alloc.h jit-reg-alloc.c
Log message:
fix spilling and many problems with stack registers
CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/dotgnu-pnet/libjit/ChangeLog.diff?tr1=1.224&tr2=1.225&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/dotgnu-pnet/libjit/jit/jit-reg-alloc.h.diff?tr1=1.9&tr2=1.10&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/dotgnu-pnet/libjit/jit/jit-reg-alloc.c.diff?tr1=1.24&tr2=1.25&r1=text&r2=text
Patches:
Index: libjit/ChangeLog
diff -u libjit/ChangeLog:1.224 libjit/ChangeLog:1.225
--- libjit/ChangeLog:1.224 Thu May 4 06:35:45 2006
+++ libjit/ChangeLog Fri May 5 10:13:07 2006
@@ -1,3 +1,8 @@
+2006-05-05 Aleksey Demakov <address@hidden>
+
+ * jit/jit-reg-alloc.h, jit/jit-reg-alloc.c: fix spilling and
+ many problems with stack registers.
+
2006-05-04 Radek Polak <address@hidden>
* jit/jit-dump.c (dump_object_code): Now can dump to any stream
Index: libjit/jit/jit-reg-alloc.c
diff -u libjit/jit/jit-reg-alloc.c:1.24 libjit/jit/jit-reg-alloc.c:1.25
--- libjit/jit/jit-reg-alloc.c:1.24 Sun Apr 23 07:56:59 2006
+++ libjit/jit/jit-reg-alloc.c Fri May 5 10:13:07 2006
@@ -1646,6 +1646,12 @@
#define VALUE_OUTPUT 2
#define VALUE_USED 4
+/* Clobber flags. */
+#define CLOBBER_NONE 0
+#define CLOBBER_INPUT_VALUE 1
+#define CLOBBER_REG 2
+#define CLOBBER_OTHER_REG 4
+
/*
* For a stack register find the first stack register.
*/
@@ -1662,14 +1668,17 @@
return reg;
}
+/*
+ * Find the stack top given the first stack register,
+ */
static int
-get_stack_size(jit_gencode_t gen, int stack_start)
+get_stack_top(jit_gencode_t gen, int stack_start)
{
- if(gen->contents[stack_start].remap < 0)
+ if(gen->stack_map[stack_start] < 0)
{
- return 0;
+ return (stack_start - 1);
}
- return (gen->contents[stack_start].remap - stack_start + 1);
+ return (gen->stack_map[stack_start]);
}
/*
@@ -1710,7 +1719,28 @@
}
/*
- * Check if the value is one of the input values.
+ * Check if two values are known to be equal.
+ */
+static int
+are_values_equal(_jit_regdesc_t *desc1, _jit_regdesc_t *desc2)
+{
+ if(desc1->value && desc2->value)
+ {
+ if(desc1->value == desc2->value)
+ {
+ return 1;
+ }
+ if(desc1->value->in_register && desc2->value->in_register)
+ {
+ return desc1->value->reg == desc2->value->reg;
+ }
+ }
+ return 0;
+}
+
+
+/*
+ * Check if the value is used in and after the current instruction.
*/
static int
value_usage(_jit_regs_t *regs, jit_value_t value)
@@ -1744,114 +1774,215 @@
}
/*
- * Check if two values are known to be equal.
+ * Check if the register contains any live values.
*/
static int
-are_values_equal(_jit_regdesc_t *desc1, _jit_regdesc_t *desc2)
+is_register_alive(jit_gencode_t gen, _jit_regs_t *regs, int reg)
{
- if(desc1->value && desc2->value)
+ int index, usage;
+ jit_value_t value;
+
+ if(reg < 0)
{
- if(desc1->value == desc2->value)
+ return 0;
+ }
+
+ for(index = 0; index < gen->contents[reg].num_values; index++)
+ {
+ value = gen->contents[reg].values[index];
+ if(value->is_constant)
{
- return 1;
+ continue;
}
- if(desc1->value->in_register && desc2->value->in_register)
+
+ /* 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 desc1->value->reg == desc2->value->reg;
+ return 1;
}
}
return 0;
}
+/*
+ * Determine the effect of assigning the value to a register. It finds out
+ * if the old register contents is clobbered and so needs to be spilled and
+ * if the newly assigned value will be clobbered by the instruction.
+ */
static int
-output_clobbers_register(jit_gencode_t gen, jit_value_t value, int reg)
-{
- if(value->has_global_register && value->global_reg == reg)
- {
- return 0;
- }
- if(value->in_register && value->reg == reg &&
gen->contents[reg].num_values == 1)
- {
- return 0;
- }
- return 1;
-}
-
-static int
-value_clobbers_register(jit_gencode_t gen, _jit_regs_t *regs, int index, int
reg, int other_reg)
+clobbers_register(jit_gencode_t gen, _jit_regs_t *regs, int index, int reg,
int other_reg)
{
- _jit_regdesc_t *desc;
- int out_index;
+ int is_alive, is_other_alive;
+ int clobber, out_index, flags;
if(index < 0)
{
- /* scratch register */
- return 1;
+ /* this call is made for a scratch register */
+ return CLOBBER_REG;
}
-
- desc = ®s->descs[index];
- if(!desc->value)
+ if(!regs->descs[index].value)
{
- return 0;
+ 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 and
- it has only input values */
+ /* this is either a ternary op or a binary/unary note */
if(regs->on_stack)
{
- /* pop all input values */
- return 1;
+ /* all input values are popped */
+ clobber = 1;
}
- return desc->clobber;
}
-
- if(index == 0)
+ else
{
- /* output value */
- return output_clobbers_register(gen, desc->value, reg);
+ /* find out the input value that is going to be overwritten by
the output */
+ if(!regs->descs[2].value)
+ {
+ /* a unary op */
+ out_index = 1;
+ }
+ else
+ {
+ /* a binary op */
+ if(regs->on_stack)
+ {
+ 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);
+ }
+ else
+ {
+ out_index = 1;
+ }
+ }
+
+ /* does the output value clobber the register? */
+ if(index == 0 || index == out_index)
+ {
+ if(regs->descs[0].value->has_global_register
+ && regs->descs[0].value->global_reg == reg)
+ {
+ return CLOBBER_NONE;
+ }
+
+ flags = CLOBBER_NONE;
+ if(regs->descs[out_index].value != regs->descs[0].value)
+ {
+ flags |= CLOBBER_INPUT_VALUE;
+ }
+ if(is_alive)
+ {
+ flags |= CLOBBER_REG;
+ }
+ if(is_other_alive)
+ {
+ flags |= CLOBBER_OTHER_REG;
+ }
+ return flags;
+ }
}
- if(index == 1 && !regs->descs[2].value)
+
+ /* does input value clobber the register? */
+ if(regs->descs[index].clobber)
{
- /* input of a unary op */
- return 1;
+ clobber = 1;
}
- if(regs->on_stack)
+ if(!clobber)
{
- if(!regs->no_pop)
+ if(regs->descs[index].value->has_global_register
+ && regs->descs[index].value->global_reg == reg)
{
- /* one input register is popped another is cloberred by
output */
- return 1;
+ return CLOBBER_NONE;
}
+ if(regs->descs[index].value->in_register
+ && regs->descs[index].value->reg == reg)
+ {
+ return CLOBBER_NONE;
+ }
+ }
- out_index = 1 + (regs->reverse_dest ^ regs->reverse_args);
+ flags = CLOBBER_NONE;
+ if(clobber)
+ {
+ flags |= CLOBBER_INPUT_VALUE;
}
- else
+ if(is_alive)
+ {
+ flags |= CLOBBER_REG;
+ }
+ if(is_other_alive)
{
- out_index = 1;
+ flags |= CLOBBER_OTHER_REG;
}
+ return flags;
+}
- if(index == out_index)
+/*
+ * Set assigned and clobber flags for a register.
+ */
+static void
+set_register_flags(_jit_regs_t *regs, int reg, int clobber_reg, int
clobber_input)
+{
+ if(reg >= 0)
{
- /* the output of a binary op clobbers this input value */
- return 1;
+ jit_reg_set_used(regs->assigned, reg);
+ if(clobber_reg)
+ {
+ jit_reg_set_used(regs->spill, reg);
+ }
+ if(clobber_input)
+ {
+ jit_reg_set_used(regs->clobber, reg);
+ }
}
+}
- return desc->clobber;
+static void
+init_regdesc(_jit_regs_t *regs, int index)
+{
+ _jit_regdesc_t *desc;
+
+ desc = ®s->descs[index];
+ desc->value = 0;
+ desc->reg = -1;
+ desc->other_reg = -1;
+ desc->stack_reg = -1;
+ desc->regset = jit_regused_init_used;
+ desc->live = 0;
+ desc->used = 0;
+ desc->clobber = 0;
+ desc->early_clobber = 0;
+ desc->on_stack = 0;
+ desc->duplicate = 0;
+ desc->load = 0;
+ desc->copy = 0;
}
/*
* Initialize register descriptor.
*/
static void
-init_desc(_jit_regs_t *regs, int index, jit_value_t value, int flags, int
live, int used)
+set_regdesc_value(_jit_regs_t *regs, int index, jit_value_t value, int flags,
int live, int used)
{
_jit_regdesc_t *desc;
desc = ®s->descs[index];
-
desc->value = value;
if(index > 0 || regs->ternary)
{
@@ -1874,41 +2005,90 @@
}
/*
- * Set assigned and clobbered flags for register.
+ * Set assigned and clobber flags for the register descriptor.
*/
static void
-set_register_bits(jit_gencode_t gen, _jit_regs_t *regs, int index)
+set_regdesc_register(jit_gencode_t gen, _jit_regs_t *regs, int index, int reg,
int other_reg)
+{
+ int clobber;
+
+ if(reg >= 0)
+ {
+ regs->descs[index].reg = reg;
+ regs->descs[index].other_reg = other_reg;
+
+ clobber = clobbers_register(gen, regs, index, reg, other_reg);
+ set_register_flags(regs, reg,
+ (clobber & CLOBBER_REG),
+ (clobber & CLOBBER_INPUT_VALUE));
+ if(other_reg >= 0)
+ {
+ set_register_flags(regs, other_reg,
+ (clobber & CLOBBER_OTHER_REG),
+ (clobber & CLOBBER_INPUT_VALUE));
+ }
+ }
+}
+
+static int
+collect_register_info(_jit_regs_t *regs, int index)
{
_jit_regdesc_t *desc;
- int output, clobber;
+ int stack_start;
desc = ®s->descs[index];
- if(desc->reg >= 0)
+ if(desc->reg < 0)
{
- output = (index == 0 && !regs->ternary);
- if(output)
+ return 1;
+ }
+ if(desc->duplicate)
+ {
+ return 1;
+ }
+
+ if(desc->value->has_global_register)
+ {
+ if(desc->value->global_reg != desc->reg
+ && !(desc->value->in_register && desc->value->reg ==
desc->reg))
{
- clobber = output_clobbers_register(gen, desc->value,
desc->reg);
+ desc->copy = 1;
}
- else
+ }
+ else
+ {
+ if(!desc->value->in_register)
+ {
+ desc->load = 1;
+ }
+ else if(desc->value->reg != desc->reg)
{
- clobber = desc->clobber;
+ desc->copy = 1;
}
+ }
- jit_reg_set_used(regs->assigned, desc->reg);
- if(clobber)
+ if(desc->on_stack)
+ {
+ stack_start = get_stack_start(desc->reg);
+ if(regs->stack_start < 0)
{
- jit_reg_set_used(regs->clobber, desc->reg);
+ regs->stack_start = stack_start;
}
- if(desc->other_reg >= 0)
+ else if(stack_start != regs->stack_start)
{
- jit_reg_set_used(regs->assigned, desc->other_reg);
- if(clobber)
+ return 0;
+ }
+
+ if(index > 0 || regs->ternary)
+ {
+ ++(regs->wanted_stack_count);
+ if(!(desc->load || desc->copy))
{
- jit_reg_set_used(regs->clobber,
desc->other_reg);
+ ++(regs->loaded_stack_count);
}
}
}
+
+ return 1;
}
/*
@@ -2174,7 +2354,7 @@
if(desc
&& desc->value->has_global_register
&& desc->value->global_reg == reg
- && !value_clobbers_register(gen, regs, index, reg,
other_reg))
+ && !clobbers_register(gen, regs, index, reg,
other_reg))
{
if(output || desc->value->in_global_register)
{
@@ -2198,7 +2378,7 @@
{
if(reg == desc->value->reg)
{
- if(value_clobbers_register(gen, regs, index,
reg, other_reg)
+ if(clobbers_register(gen, regs, index, reg,
other_reg)
&& !(jit_reg_is_used(regs->clobber, reg)
|| (other_reg >= 0
&& jit_reg_is_used(regs->clobber,
other_reg))))
@@ -2221,7 +2401,8 @@
}
if(cost < suitable_cost
- || (cost == suitable_cost && gen->contents[reg].age <
suitable_age))
+ || (cost > 0 && cost == suitable_cost
+ && gen->contents[reg].age < suitable_age))
{
/* This is the oldest suitable register of this type */
suitable_reg = reg;
@@ -2241,10 +2422,7 @@
{
other_reg = -1;
}
-
- desc->reg = reg;
- desc->other_reg = other_reg;
- set_register_bits(gen, regs, index);
+ set_regdesc_register(gen, regs, index, reg, other_reg);
}
return reg;
@@ -2403,6 +2581,71 @@
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)
+{
+ _jit_regdesc_t *desc;
+
+ desc = ®s->descs[index];
+ if(!desc->value || !desc->on_stack)
+ {
+ return;
+ }
+
+ if(regs->wanted_stack_count == 1)
+ {
+ /* either a unary op or binary x87 op with duplicate value */
+ desc->reg = regs->current_stack_top - regs->loaded_stack_count
+ 1;
+ }
+ else if(regs->wanted_stack_count == 2)
+ {
+ /* a binary op */
+ if(regs->x87_arith)
+ {
+ desc->reg = adjust_register(regs, desc->reg);
+ }
+ else if(index == 0)
+ {
+ desc->reg = regs->current_stack_top -
regs->loaded_stack_count + 1;
+ }
+ else
+ {
+ desc->reg = regs->current_stack_top -
regs->loaded_stack_count + index;
+ }
+ }
+ else if(regs->wanted_stack_count == 3)
+ {
+ /* a ternary op */
+ desc->reg = regs->current_stack_top - regs->loaded_stack_count
+ index + 1;
+ }
+}
+
static void
select_stack_order(jit_gencode_t gen, _jit_regs_t *regs)
{
@@ -2458,9 +2701,78 @@
}
static void
+remap_stack_up(jit_gencode_t gen, int stack_start, int reg)
+{
+ int index;
+
+#ifdef JIT_REG_DEBUG
+ printf("remap_stack_up(stack_start = %d, reg = %d)\n", stack_start,
reg);
+#endif
+
+ for(index = stack_start; index < reg; index++)
+ {
+ if(gen->contents[index].remap >= 0)
+ {
+ ++(gen->contents[index].remap);
+ gen->stack_map[gen->contents[index].remap] = index;
+ }
+ }
+ gen->contents[reg].remap = stack_start;
+ gen->stack_map[stack_start] = reg;
+}
+
+static void
+remap_stack_down(jit_gencode_t gen, int stack_start, int reg)
+{
+ int index;
+
+#ifdef JIT_REG_DEBUG
+ printf("remap_stack_down(stack_start = %d, reg = %d)\n", stack_start,
reg);
+#endif
+
+ gen->stack_map[gen->contents[stack_start].remap] = -1;
+ for(index = stack_start; index < reg; index++)
+ {
+ if(gen->contents[index].remap >= 0)
+ {
+ --(gen->contents[index].remap);
+ gen->stack_map[gen->contents[index].remap] = index;
+ }
+ }
+ gen->contents[reg].remap = -1;
+}
+
+static void
+bind_temporary(jit_gencode_t gen, int reg, int other_reg)
+{
+#ifdef JIT_REG_DEBUG
+ printf("bind_temporary(reg = %d, other_reg = %d)\n", reg, other_reg);
+#endif
+
+ gen->contents[reg].num_values = 0;
+ gen->contents[reg].age = 0;
+ gen->contents[reg].used_for_temp = 1;
+ gen->contents[reg].is_long_end = 0;
+ gen->contents[reg].is_long_start = 0;
+ if(other_reg >= 0)
+ {
+ gen->contents[other_reg].num_values = 0;
+ gen->contents[other_reg].age = 0;
+ gen->contents[other_reg].used_for_temp = 1;
+ gen->contents[other_reg].is_long_end = 0;
+ gen->contents[other_reg].is_long_start = 0;
+ }
+}
+
+static void
bind_value(jit_gencode_t gen, jit_value_t value, int reg, int other_reg, int
still_in_frame)
{
- int stack_start;
+#ifdef JIT_REG_DEBUG
+ printf("bind_value(value = ");
+ jit_dump_value(stdout, jit_value_get_function(value), value, 0);
+ printf(", reg = %d, other_reg = %d, still_in_frame = %d)\n",
+ reg, other_reg, still_in_frame);
+#endif
if(value->has_global_register && value->global_reg == reg)
{
@@ -2489,14 +2801,6 @@
}
++(gen->current_age);
- /* Set the stack mappings for this register */
- if(IS_STACK_REG(reg))
- {
- stack_start = get_stack_start(reg);
- gen->contents[reg].remap = stack_start;
- gen->stack_map[stack_start] = reg;
- }
-
/* Adjust the value to reflect that it is in "reg", and maybe the frame
*/
value->in_register = 1;
if(value->has_global_register)
@@ -2518,6 +2822,12 @@
{
int index;
+#ifdef JIT_REG_DEBUG
+ printf("unbind_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(!value->in_register || value->reg != reg)
{
return;
@@ -2539,14 +2849,10 @@
}
}
- if(gen->contents[reg].num_values == 0)
+ if(gen->contents[reg].num_values == 0 && other_reg >= 0)
{
- gen->contents[reg].remap = -1;
- if(other_reg >= 0)
- {
- gen->contents[reg].is_long_start = 0;
- gen->contents[other_reg].is_long_end = 0;
- }
+ gen->contents[reg].is_long_start = 0;
+ gen->contents[other_reg].is_long_end = 0;
}
}
@@ -2557,11 +2863,13 @@
static void
exch_stack_top(jit_gencode_t gen, int reg, int pop)
{
- int top;
- int index;
- int num_values;
- jit_value_t value1;
- jit_value_t value2;
+ int top, index;
+ int num_values, used_for_temp, age;
+ jit_value_t value1, value2;
+
+#ifdef JIT_REG_DEBUG
+ printf("exch_stack_top(reg = %d, pop = %d)\n", reg, pop);
+#endif
if(!IS_STACK_REG(reg))
{
@@ -2606,16 +2914,25 @@
}
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;
}
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;
}
/*
@@ -2624,23 +2941,26 @@
static void
spill_stack_top(jit_gencode_t gen, _jit_regs_t *regs, int reg)
{
- int top, index;
+ 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);
+#endif
+
if(!IS_STACK_REG(reg))
{
return;
}
- /* Find the top of the stack. */
- reg = get_stack_start(reg);
- top = gen->stack_map[reg];
+ stack_start = get_stack_start(reg);
+ top = get_stack_top(gen, stack_start);
value_used = 0;
- for(index = gen->contents[reg].num_values - 1; index >= 0; --index)
+ for(index = gen->contents[top].num_values - 1; index >= 0; --index)
{
- value = gen->contents[reg].values[index];
+ value = gen->contents[top].values[index];
usage = value_usage(regs, value);
if((usage & VALUE_INPUT) != 0 && (usage & VALUE_USED) == 0)
@@ -2661,24 +2981,12 @@
if((usage & VALUE_INPUT) == 0)
{
- unbind_value(gen, value, top, -1);
- if(gen->contents[top].num_values == 0)
+ if(gen->contents[top].num_values == 1)
{
_jit_gen_free_reg(gen, top, -1, value_used);
-
- /* Shift everything after this register up by
one position */
- while(gen->stack_map[reg] != -1)
- {
- if(IS_STACK_END(reg))
- {
- gen->stack_map[reg] = -1;
- break;
- }
- gen->contents[gen->stack_map[reg +
1]].remap = reg;
- gen->stack_map[reg] =
gen->stack_map[reg + 1];
- ++reg;
- }
+ remap_stack_down(gen, stack_start, top);
}
+ unbind_value(gen, value, top, -1);
}
}
}
@@ -2751,10 +3059,42 @@
}
static void
-spill_value(jit_gencode_t gen, jit_value_t value, int reg, int other_reg)
+spill_value(jit_gencode_t gen, _jit_regs_t *regs, jit_value_t value, int reg,
int other_reg)
{
+ int top;
+
if(IS_STACK_REG(reg))
{
+ top = get_stack_top(gen, regs->stack_start);
+ if(top != reg)
+ {
+ exch_stack_top(gen, reg, 0);
+ }
+
+ 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);
}
else
{
@@ -2774,44 +3114,36 @@
value->in_frame = 1;
}
}
+ unbind_value(gen, value, reg, other_reg);
}
}
static void
-adjust_assignment(jit_gencode_t gen, _jit_regs_t *regs, int index)
+update_age(jit_gencode_t gen, _jit_regdesc_t *desc)
{
- _jit_regdesc_t *desc;
+ int reg, other_reg;
- desc = ®s->descs[index];
- if(!desc->value || !desc->on_stack)
+ reg = desc->value->reg;
+ if(gen->contents[reg].is_long_start)
{
- return;
+ other_reg = OTHER_REG(reg);
}
-
- if(desc->reg >= (regs->stack_start + regs->initial_stack_size))
+ else
{
- desc->reg -= regs->initial_stack_size;
- desc->reg += regs->current_stack_size;
- return;
+ other_reg = -1;
}
- for(index = 0; index < regs->num_exchanges; index++)
+ gen->contents[reg].age = gen->current_age;
+ if(other_reg >= 0)
{
- if(desc->reg == regs->exchanges[index][0])
- {
- desc->reg = regs->exchanges[index][1];
- }
- else if(desc->reg == regs->exchanges[index][1])
- {
- desc->reg = regs->exchanges[index][0];
- }
+ gen->contents[other_reg].age = gen->current_age;
}
+ ++(gen->current_age);
}
static void
load_input_value(jit_gencode_t gen, _jit_regs_t *regs, int index)
{
- int reg, other_reg;
_jit_regdesc_t *desc;
desc = ®s->descs[index];
@@ -2820,47 +3152,59 @@
return;
}
- if(desc->value->in_register)
+ if(desc->value->has_global_register)
{
- reg = desc->value->reg;
- if(reg != desc->reg)
+ if(desc->value->in_global_register && desc->value->global_reg
== desc->reg)
{
- _jit_gen_load_value(gen, desc->reg, desc->other_reg,
desc->value);
- if(gen->contents[reg].is_long_start)
- {
- other_reg = OTHER_REG(reg);
- }
- else
+ return;
+ }
+ if(desc->value->in_register && desc->value->reg == desc->reg)
+ {
+ update_age(gen, desc);
+ return;
+ }
+ _jit_gen_load_value(gen, desc->reg, desc->other_reg,
desc->value);
+ }
+ else if(desc->value->in_register)
+ {
+ if(desc->value->reg == desc->reg)
+ {
+ update_age(gen, desc);
+ if(IS_STACK_REG(desc->reg))
{
- other_reg = -1;
+ desc->stack_reg = desc->reg;
}
- spill_value(gen, desc->value, reg, other_reg);
- unbind_value(gen, desc->value, reg, other_reg);
- bind_value(gen, desc->value, desc->reg,
desc->other_reg, 1);
+ return;
+ }
+
+ if(IS_STACK_REG(desc->reg))
+ {
+ desc->stack_reg = ++(regs->current_stack_top);
+ _jit_gen_load_value(gen, desc->stack_reg, -1,
desc->value);
+ bind_temporary(gen, desc->stack_reg, -1);
+ remap_stack_up(gen, regs->stack_start, desc->stack_reg);
}
else
{
- gen->contents[desc->value->reg].age = gen->current_age;
- if(desc->other_reg >= 0)
- {
- gen->contents[OTHER_REG(desc->value->reg)].age
= gen->current_age;
- }
- ++(gen->current_age);
+ _jit_gen_load_value(gen, desc->reg, desc->other_reg,
desc->value);
+ bind_temporary(gen, desc->reg, desc->other_reg);
}
}
- else if(desc->value->in_global_register)
+ else
{
- if(desc->value->global_reg != desc->reg)
+ if(IS_STACK_REG(desc->reg))
+ {
+ desc->stack_reg = ++(regs->current_stack_top);
+ _jit_gen_load_value(gen, desc->stack_reg, -1,
desc->value);
+ bind_value(gen, desc->value, desc->stack_reg, -1, 1);
+ remap_stack_up(gen, regs->stack_start, desc->stack_reg);
+ }
+ else
{
_jit_gen_load_value(gen, desc->reg, desc->other_reg,
desc->value);
bind_value(gen, desc->value, desc->reg,
desc->other_reg, 1);
}
}
- else
- {
- _jit_gen_load_value(gen, desc->reg, desc->other_reg,
desc->value);
- bind_value(gen, desc->value, desc->reg, desc->other_reg, 1);
- }
jit_reg_set_used(gen->touched, desc->reg);
if(desc->other_reg >= 0)
@@ -2873,7 +3217,7 @@
move_input_value(jit_gencode_t gen, _jit_regs_t *regs, int index)
{
_jit_regdesc_t *desc;
- int reg, top;
+ int src_reg, dst_reg;
desc = ®s->descs[index];
if(!desc->value || desc->duplicate || !desc->value->in_register)
@@ -2881,32 +3225,43 @@
return;
}
- top = regs->stack_start + regs->current_stack_size - 1;
+ if(desc->copy)
+ {
+ src_reg = desc->stack_reg;
+ if(src_reg < 0)
+ {
+ return;
+ }
+ }
+ else
+ {
+ src_reg = desc->value->reg;
+ }
- if(desc->reg < (regs->stack_start + regs->current_stack_size))
+ if(desc->reg <= regs->current_stack_top)
{
- reg = desc->reg;
+ dst_reg = desc->reg;
}
else if(regs->ternary && index == 2
&& regs->descs[0].value && regs->descs[1].value
&& !regs->descs[0].value->in_register &&
regs->descs[1].value->in_register)
{
- reg = top - 1;
+ dst_reg = regs->current_stack_top - 1;
}
else
{
- reg = top;
+ dst_reg = regs->current_stack_top;
}
- if(desc->value->reg != reg)
+ if(src_reg != dst_reg)
{
- if(desc->value->reg != top)
+ if(src_reg != regs->current_stack_top)
{
- exch_stack_top(gen, desc->value->reg, 0);
+ exch_stack_top(gen, src_reg, 0);
}
- if(reg != top)
+ if(dst_reg != regs->current_stack_top)
{
- exch_stack_top(gen, reg, 0);
+ exch_stack_top(gen, dst_reg, 0);
}
}
}
@@ -2938,17 +3293,36 @@
if(jit_reg_is_used(regs->clobber, reg)
|| (other_reg >= 0 && jit_reg_is_used(regs->clobber, other_reg)))
{
- unbind_value(gen, desc->value, reg, other_reg);
+ if(IS_STACK_REG(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);
+#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
+ }
return;
}
if(!desc->used)
{
- if(desc->live)
+ spill_value(gen, regs, desc->value, reg, other_reg);
+ if(desc->live || (IS_STACK_REG(reg) &&
gen->contents[reg].num_values == 1))
+ {
+ unbind_value(gen, desc->value, reg, other_reg);
+ }
+ else
{
- spill_value(gen, desc->value, reg, other_reg);
}
- unbind_value(gen, desc->value, reg, other_reg);
}
}
@@ -2956,6 +3330,7 @@
commit_output_value(jit_gencode_t gen, _jit_regs_t *regs)
{
_jit_regdesc_t *desc;
+ int reg, other_reg;
desc = ®s->descs[0];
if(!desc->value)
@@ -2965,14 +3340,34 @@
if(desc->value->in_register)
{
- unbind_value(gen, desc->value, desc->value->reg,
OTHER_REG(desc->value->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);
}
- if(desc->used || desc->live)
+ if(desc->used || desc->live || IS_STACK_REG(desc->reg))
{
- bind_value(gen, desc->value, desc->reg, desc->other_reg, 0);
+ if(IS_STACK_REG(desc->reg))
+ {
+ bind_value(gen, desc->value, desc->reg, -1, 0);
+ remap_stack_up(gen, regs->stack_start, desc->reg);
+ }
+ else
+ {
+ bind_value(gen, desc->value, desc->reg,
desc->other_reg, 0);
+ }
if(!desc->used)
{
- spill_value(gen, desc->value, desc->reg,
desc->other_reg);
+ if(desc->live || IS_STACK_REG(desc->reg))
+ {
+ spill_value(gen, regs, desc->value, desc->reg,
desc->other_reg);
+ }
unbind_value(gen, desc->value, desc->reg,
desc->other_reg);
}
}
@@ -3004,18 +3399,8 @@
for(index = 0; index < _JIT_REGS_VALUE_MAX; index++)
{
- regs->descs[index].value = 0;
- regs->descs[index].reg = -1;
- regs->descs[index].other_reg = -1;
- regs->descs[index].regset = jit_regused_init_used;
- regs->descs[index].clobber = 0;
- regs->descs[index].early_clobber = 0;
- regs->descs[index].live = 0;
- regs->descs[index].used = 0;
- regs->descs[index].on_stack = 0;
- regs->descs[index].duplicate = 0;
+ init_regdesc(regs, index);
}
-
for(index = 0; index < _JIT_REGS_SCRATCH_MAX; index++)
{
regs->scratch[index].reg = -1;
@@ -3025,11 +3410,13 @@
regs->assigned = jit_regused_init;
regs->clobber = jit_regused_init;
+ regs->spill = jit_regused_init;
regs->stack_start = -1;
- regs->stack_count = 0;
- regs->initial_stack_size = 0;
- regs->current_stack_size = 0;
+ regs->initial_stack_top = 0;
+ regs->current_stack_top = 0;
+ regs->wanted_stack_count = 0;
+ regs->loaded_stack_count = 0;
regs->num_exchanges = 0;
}
@@ -3038,9 +3425,9 @@
{
if((insn->flags & JIT_INSN_DEST_OTHER_FLAGS) == 0)
{
- init_desc(regs, 0, insn->dest, flags,
- (insn->flags & JIT_INSN_DEST_LIVE) != 0,
- (insn->flags & JIT_INSN_DEST_NEXT_USE) != 0);
+ set_regdesc_value(regs, 0, insn->dest, flags,
+ (insn->flags & JIT_INSN_DEST_LIVE) != 0,
+ (insn->flags & JIT_INSN_DEST_NEXT_USE) != 0);
}
}
@@ -3049,9 +3436,9 @@
{
if((insn->flags & JIT_INSN_VALUE1_OTHER_FLAGS) == 0)
{
- init_desc(regs, 1, insn->value1, flags,
- (insn->flags & JIT_INSN_VALUE1_LIVE) != 0,
- (insn->flags & JIT_INSN_VALUE1_NEXT_USE) != 0);
+ set_regdesc_value(regs, 1, insn->value1, flags,
+ (insn->flags & JIT_INSN_VALUE1_LIVE) != 0,
+ (insn->flags & JIT_INSN_VALUE1_NEXT_USE) !=
0);
}
}
@@ -3060,9 +3447,9 @@
{
if((insn->flags & JIT_INSN_VALUE2_OTHER_FLAGS) == 0)
{
- init_desc(regs, 2, insn->value2, flags,
- (insn->flags & JIT_INSN_VALUE2_LIVE) != 0,
- (insn->flags & JIT_INSN_VALUE2_NEXT_USE) != 0);
+ set_regdesc_value(regs, 2, insn->value2, flags,
+ (insn->flags & JIT_INSN_VALUE2_LIVE) != 0,
+ (insn->flags & JIT_INSN_VALUE2_NEXT_USE) !=
0);
}
}
@@ -3180,6 +3567,27 @@
{
int index, out_index;
+#ifdef JIT_REG_DEBUG
+ dump_regs(gen, "enter _jit_regs_assign");
+#endif
+
+ /* Set clobber flags. */
+ if(regs->clobber_all)
+ {
+ for(index = 0; index < JIT_NUM_REGS; index++)
+ {
+ if((_jit_reg_info[index].flags & JIT_REG_FIXED)
+ || jit_reg_is_used(gen->permanent, index))
+ {
+ continue;
+ }
+ jit_reg_set_used(regs->clobber, index);
+ }
+ }
+
+ /* Spill all clobbered registers. */
+ regs->spill = regs->clobber;
+
/* Process pre-assigned registers. */
if(regs->descs[0].reg >= 0)
@@ -3188,7 +3596,9 @@
{
return 0;
}
- set_register_bits(gen, regs, 0);
+ set_regdesc_register(gen, regs, 0,
+ regs->descs[0].reg,
+ regs->descs[0].other_reg);
}
if(regs->descs[1].reg >= 0)
{
@@ -3196,7 +3606,9 @@
{
return 0;
}
- set_register_bits(gen, regs, 1);
+ set_regdesc_register(gen, regs, 1,
+ regs->descs[1].reg,
+ regs->descs[1].other_reg);
}
if(regs->descs[2].reg >= 0)
{
@@ -3204,7 +3616,9 @@
{
return 0;
}
- set_register_bits(gen, regs, 2);
+ set_regdesc_register(gen, regs, 2,
+ regs->descs[2].reg,
+ regs->descs[2].other_reg);
}
for(index = 0; index < regs->num_scratch; index++)
@@ -3215,10 +3629,13 @@
{
return 0;
}
- jit_reg_set_used(regs->assigned,
regs->scratch[index].reg);
- jit_reg_set_used(regs->clobber,
regs->scratch[index].reg);
+ set_register_flags(regs, regs->scratch[index].reg, 1,
0);
}
- else if(regs->scratch[index].regset != jit_regused_init_used)
+ }
+ for(index = 0; index < regs->num_scratch; index++)
+ {
+ if(regs->scratch[index].reg < 0
+ && regs->scratch[index].regset != jit_regused_init_used)
{
regs->scratch[index].reg = use_cheapest_register(
gen, regs, -1, regs->scratch[index].regset);
@@ -3226,23 +3643,11 @@
{
return 0;
}
- jit_reg_set_used(regs->assigned,
regs->scratch[index].reg);
- jit_reg_set_used(regs->clobber,
regs->scratch[index].reg);
+ set_register_flags(regs, regs->scratch[index].reg, 1,
0);
}
}
- if(regs->clobber_all)
- {
- for(index = 0; index < JIT_NUM_REGS; index++)
- {
- if((_jit_reg_info[index].flags & JIT_REG_FIXED)
- || jit_reg_is_used(gen->permanent, index))
- {
- continue;
- }
- jit_reg_set_used(regs->clobber, index);
- }
- }
+ /* Determine the argument order. */
select_order(gen, regs);
out_index = 1 + (regs->reverse_dest ^ regs->reverse_args);
@@ -3290,9 +3695,9 @@
}
if(regs->descs[0].reg >= 0)
{
- regs->descs[out_index].reg = regs->descs[0].reg;
- regs->descs[out_index].other_reg =
regs->descs[0].other_reg;
- set_register_bits(gen, regs, out_index);
+ set_regdesc_register(gen, regs, out_index,
+ regs->descs[0].reg,
+ regs->descs[0].other_reg);
}
}
if(regs->descs[1].value && regs->descs[1].reg < 0)
@@ -3324,9 +3729,9 @@
}
else
{
- regs->descs[0].reg = regs->descs[out_index].reg;
- regs->descs[0].other_reg =
regs->descs[out_index].other_reg;
- set_register_bits(gen, regs, 0);
+ set_regdesc_register(gen, regs, 0,
+ regs->descs[out_index].reg,
+ regs->descs[out_index].other_reg);
}
}
@@ -3340,11 +3745,27 @@
{
return 0;
}
- jit_reg_set_used(regs->assigned,
regs->scratch[index].reg);
- jit_reg_set_used(regs->clobber,
regs->scratch[index].reg);
+ set_register_flags(regs, regs->scratch[index].reg, 1,
0);
}
}
+ /* Collect information about registers. */
+ if(!collect_register_info(regs, 0))
+ {
+ return 0;
+ }
+ if(!collect_register_info(regs, 1))
+ {
+ return 0;
+ }
+ if(!collect_register_info(regs, 2))
+ {
+ return 0;
+ }
+
+#ifdef JIT_REG_DEBUG
+ dump_regs(gen, "leave _jit_regs_assign");
+#endif
return 1;
}
@@ -3353,44 +3774,14 @@
{
int reg, stack_start, top;
- /* Collect information about stack registers. */
- if(regs->descs[0].on_stack)
- {
- regs->stack_start = get_stack_start(regs->descs[0].reg);
- if(regs->ternary)
- {
- ++(regs->stack_count);
- }
- }
- if(regs->descs[1].on_stack && !regs->descs[1].duplicate)
- {
- stack_start = get_stack_start(regs->descs[1].reg);
- if(regs->stack_start < 0)
- {
- regs->stack_start = stack_start;
- }
- else if(stack_start != regs->stack_start)
- {
- return 0;
- }
- ++(regs->stack_count);
- }
- if(regs->descs[2].on_stack && !regs->descs[2].duplicate)
- {
- stack_start = get_stack_start(regs->descs[2].reg);
- if(regs->stack_start < 0)
- {
- regs->stack_start = stack_start;
- }
- else if(stack_start != regs->stack_start)
- {
- return 0;
- }
- ++(regs->stack_count);
- }
- if(regs->stack_count > 0)
+#ifdef JIT_REG_DEBUG
+ dump_regs(gen, "enter _jit_regs_gen");
+#endif
+
+ /* Remember initial stack size. */
+ if(regs->wanted_stack_count > 0)
{
- regs->initial_stack_size = get_stack_size(gen,
regs->stack_start);
+ regs->initial_stack_top = get_stack_top(gen, regs->stack_start);
}
/* Spill clobbered registers. */
@@ -3408,7 +3799,7 @@
stack_start = reg;
}
- if(!jit_reg_is_used(regs->clobber, reg))
+ if(!jit_reg_is_used(regs->spill, reg))
{
continue;
}
@@ -3432,7 +3823,7 @@
if(IS_STACK_REG(reg))
{
top = gen->stack_map[stack_start];
- while(top > reg && jit_reg_is_used(regs->clobber, top))
+ while(top > reg && jit_reg_is_used(regs->spill, top))
{
spill_stack_top(gen, regs, stack_start);
if(gen->contents[top].num_values > 0)
@@ -3454,15 +3845,15 @@
regs->exchanges[regs->num_exchanges][1] = reg;
++(regs->num_exchanges);
- if(jit_reg_is_used(regs->clobber, top))
+ if(jit_reg_is_used(regs->spill, top))
{
- jit_reg_set_used(regs->clobber, reg);
+ jit_reg_set_used(regs->spill, reg);
}
else
{
- jit_reg_clear_used(regs->clobber, reg);
+ jit_reg_clear_used(regs->spill, reg);
}
- jit_reg_set_used(regs->clobber, top);
+ jit_reg_set_used(regs->spill, top);
}
spill_stack_top(gen, regs, stack_start);
}
@@ -3473,13 +3864,11 @@
}
/* Adjust assignment of stack registers. */
- if(regs->stack_count > 0)
+ if(regs->wanted_stack_count > 0)
{
- regs->current_stack_size = get_stack_size(gen,
regs->stack_start);
- if(regs->ternary)
- {
- adjust_assignment(gen, regs, 0);
- }
+ regs->current_stack_top = get_stack_top(gen, regs->stack_start);
+
+ adjust_assignment(gen, regs, 0);
adjust_assignment(gen, regs, 1);
adjust_assignment(gen, regs, 2);
@@ -3489,7 +3878,7 @@
/* Load values. */
if(regs->on_stack)
{
- /* shuffle values that are already on the stack */
+ /* shuffle the values that are already on the stack */
if(regs->ternary)
{
if(regs->descs[0].value &&
regs->descs[0].value->in_register)
@@ -3541,6 +3930,9 @@
load_input_value(gen, regs, 2);
}
+#ifdef JIT_REG_DEBUG
+ dump_regs(gen, "leave _jit_regs_gen");
+#endif
return 1;
}
@@ -3571,27 +3963,41 @@
{
int reg;
- if(regs->ternary)
+#ifdef JIT_REG_DEBUG
+ dump_regs(gen, "enter _jit_regs_commit");
+#endif
+
+ if(regs->x87_arith && regs->reverse_args)
{
- commit_input_value(gen, regs, 0);
commit_input_value(gen, regs, 1);
commit_input_value(gen, regs, 2);
}
else
{
- commit_input_value(gen, regs, 1);
commit_input_value(gen, regs, 2);
+ commit_input_value(gen, regs, 1);
+ }
+ if(regs->ternary)
+ {
+ commit_input_value(gen, regs, 0);
+ }
+ else
+ {
commit_output_value(gen, regs);
}
/* Load clobbered global registers. */
for(reg = JIT_NUM_REGS - 1; reg >= 0; reg--)
{
- if(jit_reg_is_used(regs->clobber, reg) &&
jit_reg_is_used(gen->permanent, reg))
+ if(jit_reg_is_used(regs->spill, reg) &&
jit_reg_is_used(gen->permanent, reg))
{
_jit_gen_load_global(gen, reg,
gen->contents[reg].values[0]);
}
}
+
+#ifdef JIT_REG_DEBUG
+ dump_regs(gen, "enter _jit_regs_commit");
+#endif
}
/*@
Index: libjit/jit/jit-reg-alloc.h
diff -u libjit/jit/jit-reg-alloc.h:1.9 libjit/jit/jit-reg-alloc.h:1.10
--- libjit/jit/jit-reg-alloc.h:1.9 Sun Apr 23 07:56:59 2006
+++ libjit/jit/jit-reg-alloc.h Fri May 5 10:13:07 2006
@@ -113,6 +113,7 @@
jit_value_t value;
int reg;
int other_reg;
+ int stack_reg;
jit_regused_t regset;
unsigned live : 1;
unsigned used : 1;
@@ -120,6 +121,8 @@
unsigned early_clobber : 1;
unsigned on_stack : 1;
unsigned duplicate : 1;
+ unsigned load : 1;
+ unsigned copy : 1;
} _jit_regdesc_t;
@@ -157,11 +160,13 @@
jit_regused_t assigned;
jit_regused_t clobber;
+ jit_regused_t spill;
int stack_start;
- int stack_count;
- int initial_stack_size;
- int current_stack_size;
+ 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;
- [dotgnu-pnet-commits] libjit ./ChangeLog jit/jit-reg-alloc.h jit/jit-...,
Aleksey Demakov <=