[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-re...
From: |
Aleksey Demakov |
Subject: |
[dotgnu-pnet-commits] libjit ChangeLog jit/jit-reg-alloc.h jit/jit-re... |
Date: |
Fri, 16 Jun 2006 17:53:52 +0000 |
CVSROOT: /sources/dotgnu-pnet
Module name: libjit
Changes by: Aleksey Demakov <avd> 06/06/16 17:53:52
Modified files:
. : ChangeLog
jit : jit-reg-alloc.h jit-reg-alloc.c
jit-rules-x86.ins
tools : gen-rules-parser.y
Log message:
Extend register allocator to allow separate specification of the
destination
register. Take advantage of this for some x86 rules. Tweak the
allocator's
API.
CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/libjit/ChangeLog?cvsroot=dotgnu-pnet&r1=1.236&r2=1.237
http://cvs.savannah.gnu.org/viewcvs/libjit/jit/jit-reg-alloc.h?cvsroot=dotgnu-pnet&r1=1.15&r2=1.16
http://cvs.savannah.gnu.org/viewcvs/libjit/jit/jit-reg-alloc.c?cvsroot=dotgnu-pnet&r1=1.33&r2=1.34
http://cvs.savannah.gnu.org/viewcvs/libjit/jit/jit-rules-x86.ins?cvsroot=dotgnu-pnet&r1=1.7&r2=1.8
http://cvs.savannah.gnu.org/viewcvs/libjit/tools/gen-rules-parser.y?cvsroot=dotgnu-pnet&r1=1.8&r2=1.9
Patches:
Index: ChangeLog
===================================================================
RCS file: /sources/dotgnu-pnet/libjit/ChangeLog,v
retrieving revision 1.236
retrieving revision 1.237
diff -u -b -r1.236 -r1.237
--- ChangeLog 16 Jun 2006 02:35:16 -0000 1.236
+++ ChangeLog 16 Jun 2006 17:53:51 -0000 1.237
@@ -1,3 +1,19 @@
+2006-06-17 Aleksey Demakov <address@hidden>
+
+ * jit/jit-reg-alloc.h, jit/jit-reg-alloc.c: implement support of the
+ JIT_REGS_FREE_DEST flag for 3-argument instructions. Tweak reg alloc
+ API.
+
+ * tools/gen-rules-parser.y: adjust for reg alloc API changes. Use
+ '$0' pattern element to refer to destination register in 3-argument
+ instructions.
+
+ * jit/jit-rules-x86.ins: rewrite JIT_OP_IDIV, JIT_OP_IDIV_UN,
+ JIT_OP_IREM, JIT_OP_IREM_UN, JIT_OP_ADDRESS_OF_LABEL,
+ JIT_OP_LOAD_RELATIVE_FLOAT32, JIT_OP_LOAD_RELATIVE_FLOAT32,
+ JIT_OP_LOAD_RELATIVE_NFLOAT, JIT_OP_LOAD_ELEMENT_FLOAT32,
+ JIT_OP_LOAD_ELEMENT_FLOAT64, JIT_OP_LOAD_ELEMENT_NFLOAT rules.
+
2006-06-16 Aleksey Demakov <address@hidden>
* jit/jit-rules-x86.sel, jit/jit-rules-x86.ins: fix JIT_OP_IDIV and
Index: jit/jit-reg-alloc.h
===================================================================
RCS file: /sources/dotgnu-pnet/libjit/jit/jit-reg-alloc.h,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -b -r1.15 -r1.16
--- jit/jit-reg-alloc.h 3 Jun 2006 13:39:53 -0000 1.15
+++ jit/jit-reg-alloc.h 16 Jun 2006 17:53:51 -0000 1.16
@@ -116,6 +116,7 @@
unsigned clobber : 1;
unsigned early_clobber : 1;
unsigned duplicate : 1;
+ unsigned thrash : 1;
unsigned save : 1;
unsigned load : 1;
unsigned copy : 1;
@@ -158,7 +159,6 @@
jit_regused_t assigned;
jit_regused_t clobber;
- jit_regused_t spill;
int stack_start;
int current_stack_top;
@@ -166,16 +166,16 @@
int loaded_stack_count;
} _jit_regs_t;
-void _jit_regs_init(_jit_regs_t *regs, int flags);
+void _jit_regs_init(jit_gencode_t gen, _jit_regs_t *regs, int flags);
void _jit_regs_init_dest(_jit_regs_t *regs, jit_insn_t insn, int flags);
void _jit_regs_init_value1(_jit_regs_t *regs, jit_insn_t insn, int flags);
void _jit_regs_init_value2(_jit_regs_t *regs, jit_insn_t insn, int flags);
-void _jit_regs_set_dest(_jit_regs_t *regs, int reg, int other_reg);
-void _jit_regs_set_value1(_jit_regs_t *regs, int reg, int other_reg);
-void _jit_regs_set_value2(_jit_regs_t *regs, int reg, int other_reg);
-void _jit_regs_add_scratch(_jit_regs_t *regs, int reg);
-void _jit_regs_set_clobber(_jit_regs_t *regs, int reg);
+void _jit_regs_set_dest(jit_gencode_t gen, _jit_regs_t *regs, int reg, int
other_reg);
+void _jit_regs_set_value1(jit_gencode_t gen, _jit_regs_t *regs, int reg, int
other_reg);
+void _jit_regs_set_value2(jit_gencode_t gen, _jit_regs_t *regs, int reg, int
other_reg);
+void _jit_regs_add_scratch(jit_gencode_t gen, _jit_regs_t *regs, int reg);
+void _jit_regs_set_clobber(jit_gencode_t gen, _jit_regs_t *regs, int reg);
void _jit_regs_set_dest_from(_jit_regs_t *regs, jit_regused_t regset);
void _jit_regs_set_value1_from(_jit_regs_t *regs, jit_regused_t regset);
@@ -187,6 +187,7 @@
int _jit_regs_select(_jit_regs_t *regs);
void _jit_regs_commit(jit_gencode_t gen, _jit_regs_t *regs);
void _jit_regs_abort(jit_gencode_t gen, _jit_regs_t *regs);
+
unsigned char *_jit_regs_inst_ptr(jit_gencode_t gen, int space);
unsigned char *_jit_regs_begin(jit_gencode_t gen, _jit_regs_t *regs, int
space);
void _jit_regs_end(jit_gencode_t gen, _jit_regs_t *regs, unsigned char *inst);
Index: jit/jit-reg-alloc.c
===================================================================
RCS file: /sources/dotgnu-pnet/libjit/jit/jit-reg-alloc.c,v
retrieving revision 1.33
retrieving revision 1.34
diff -u -b -r1.33 -r1.34
--- jit/jit-reg-alloc.c 3 Jun 2006 13:39:53 -0000 1.33
+++ jit/jit-reg-alloc.c 16 Jun 2006 17:53:51 -0000 1.34
@@ -1662,9 +1662,15 @@
#define COST_SPILL_DIRTY_GLOBAL 2
#define COST_SPILL_CLEAN 1
#define COST_SPILL_CLEAN_GLOBAL 1
+#define COST_GLOBAL_BIAS 1
+#define COST_THRASH 32
#define COST_CLOBBER_GLOBAL 1000
-#define ALLOW_CLOBBER_GLOBAL 1
+#ifdef JIT_BACKEND_X86
+# define ALLOW_CLOBBER_GLOBAL 1
+#else
+# define ALLOW_CLOBBER_GLOBAL 0
+#endif
/* Value usage flags. */
#define VALUE_INPUT 1
@@ -1750,7 +1756,7 @@
static int
are_values_equal(_jit_regdesc_t *desc1, _jit_regdesc_t *desc2)
{
- if(desc1->value && desc2->value)
+ if(desc1 && desc2 && desc1->value && desc2->value)
{
if(desc1->value == desc2->value)
{
@@ -1766,11 +1772,40 @@
/*
- * Check if the value is used in and after the current instruction.
+ * Get value usage and liveness information. The accurate liveness data is
+ * only available for values used by the current instruction.
+ *
+ * VALUE_INPUT flag is set if the value is one of the instruction's inputs.
+ *
+ * VALUE_LIVE and VALUE_USED flags are set for input values only according
+ * to the liveness flags provided along with the instruction.
+ *
+ * VALUE_DEAD flag is set in two cases. First, it is always set for output
+ * values. Second, it is set for input values that are neither live nor used.
+ *
+ * These flags are used when spilling a register. In this case we generally
+ * do not know if the values in the register are used by the instruction. If
+ * the VALUE_INPUT flag is present then it is so and the value has to be held
+ * in the register for the instruction to succeed. If the VALUE_DEAD flag is
+ * present then there is no need to spill the value and it may be discarded.
+ * Otherwise the value must be spilled.
*
- * 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.
+ * The VALUE_LIVE and VALUE_USED flags may only be set for input values of
+ * the instruction. For other values these flags are not set even if they are
+ * perfectly alive. These flags are used as a hint for spill cost calculation.
+ *
+ * NOTE: The output value is considered to be dead because the instruction is
+ * just about to recompute it so there is no point to save it.
+ *
+ * Generally, a value becomes dead just after the instruction that used it
+ * last time. The allocator frees dead values after each instruction so it
+ * might seem that there is no chance to find any dead value on the current
+ * instruction. However if the value is used by the current instruction both
+ * as the input and output then it was alive after the last instruction and
+ * hence was not freed. Also the old allocator might sometimes leave a dead
+ * value in the register and as of this writing the old allocator is still
+ * used by some rules. And just in case if some dead value may creep through
+ * the new allocator...
*/
static int
value_usage(_jit_regs_t *regs, jit_value_t value)
@@ -1867,9 +1902,14 @@
}
/*
- * 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.
+ * Determine the effect of assigning a value to a register on the values
+ * the register contains. The following factors are taken into account:
+ for
+ * the instruction
+ *. It
+ * checks if the register contains any other values that might be clobbered
+ * by using the register or if the value in question is clobbered itself by
+ * the instruction.
*/
static int
clobbers_register(jit_gencode_t gen, _jit_regs_t *regs, int index, int reg,
int other_reg)
@@ -1903,7 +1943,11 @@
else
{
/* find out the input value that is going to be overwritten by
the output */
- if(!regs->descs[2].value)
+ if(regs->free_dest)
+ {
+ out_index = 0;
+ }
+ else if(!regs->descs[2].value)
{
/* a unary op */
out_index = 1;
@@ -1953,13 +1997,17 @@
}
}
- /* does input value clobber the register? */
+ /* is input value clobbered? */
if(regs->descs[index].clobber)
{
clobber = 1;
}
- if(!clobber)
+ if(clobber)
+ {
+ flags = CLOBBER_INPUT_VALUE;
+ }
+ else
{
if(regs->descs[index].value->has_global_register
&& regs->descs[index].value->global_reg == reg)
@@ -1971,12 +2019,7 @@
{
return CLOBBER_NONE;
}
- }
-
flags = CLOBBER_NONE;
- if(clobber)
- {
- flags |= CLOBBER_INPUT_VALUE;
}
if(is_alive)
{
@@ -1990,31 +2033,24 @@
}
/*
- * Set assigned and clobber flags for a register.
+ * Assign scratch register.
*/
static void
-set_register_flags(
- jit_gencode_t gen,
- _jit_regs_t *regs,
- int reg,
- int clobber_reg,
- int clobber_input)
+set_scratch_register(jit_gencode_t gen, _jit_regs_t *regs, int index, int reg)
{
if(reg >= 0)
{
+ regs->scratch[index].reg = reg;
+
jit_reg_set_used(gen->touched, reg);
- 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);
- }
+ jit_reg_set_used(regs->assigned, reg);
}
}
+/*
+ * Initialize value descriptor.
+ */
static void
init_regdesc(_jit_regs_t *regs, int index)
{
@@ -2031,6 +2067,7 @@
desc->clobber = 0;
desc->early_clobber = 0;
desc->duplicate = 0;
+ desc->thrash = 0;
desc->save = 0;
desc->load = 0;
desc->copy = 0;
@@ -2038,7 +2075,7 @@
}
/*
- * Initialize register descriptor.
+ * Set value information.
*/
static void
set_regdesc_value(_jit_regs_t *regs, int index, jit_value_t value, int flags,
int live, int used)
@@ -2064,40 +2101,38 @@
}
/*
- * Set assigned and clobber flags for the register descriptor.
+ * Assign register to a value.
*/
static void
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(gen, regs, reg,
- (clobber & CLOBBER_REG),
- (clobber & CLOBBER_INPUT_VALUE));
+ jit_reg_set_used(gen->touched, reg);
+ jit_reg_set_used(regs->assigned, reg);
if(other_reg >= 0)
{
- set_register_flags(gen, regs, other_reg,
- (clobber & CLOBBER_OTHER_REG),
- (clobber & CLOBBER_INPUT_VALUE));
+ jit_reg_set_used(gen->touched, other_reg);
+ jit_reg_set_used(regs->assigned, other_reg);
}
}
}
+/*
+ * Determine value flags.
+ */
static int
-collect_register_info(jit_gencode_t gen, _jit_regs_t *regs, int index)
+set_regdesc_flags(jit_gencode_t gen, _jit_regs_t *regs, int index)
{
_jit_regdesc_t *desc;
int reg, other_reg;
- int stack_start;
+ int clobber, stack_start;
#ifdef JIT_REG_DEBUG
- printf("collect_register_info(index = %d)\n", index);
+ printf("set_regdesc_flags(index = %d)\n", index);
#endif
desc = ®s->descs[index];
@@ -2106,6 +2141,7 @@
return 1;
}
+ /* Find the registers the value is already in (if any). */
if(desc->value->in_register)
{
reg = desc->value->reg;
@@ -2124,20 +2160,94 @@
other_reg = -1;
}
+ /* See if the value clobbers the register it is assigned to. */
+ clobber = clobbers_register(gen, regs, index, desc->reg,
desc->other_reg);
+ if((clobber & CLOBBER_REG) != 0)
+ {
+ jit_reg_set_used(regs->clobber, desc->reg);
+ }
+ if((clobber & CLOBBER_OTHER_REG) != 0)
+ {
+ jit_reg_set_used(regs->clobber, desc->other_reg);
+ }
+
+ /* See if the input value is thrashed by other inputs or clobbered
+ by the output. The allocator tries to avoid thrashing so it may
+ only take place if the register is assigned explicitly. For x87
+ registers the problem of thrashing may be best solved with fxch
+ but as the stack registers are never assigned explicitely there
+ is no such problem for them at all. */
+ if(reg >= 0 && (index > 0 || regs->ternary))
+ {
+ if(index != 0)
+ {
+ if(reg == regs->descs[0].reg
+ || reg == regs->descs[0].other_reg
+ || (other_reg >= 0
+ && (other_reg == regs->descs[0].reg
+ || other_reg == regs->descs[0].other_reg)))
+ {
+ if(regs->ternary)
+ {
+ if(!are_values_equal(desc,
®s->descs[0]))
+ {
+ desc->thrash = 1;
+ }
+ }
+ else
+ {
+ if(desc->value != regs->descs[0].value)
+ {
+ clobber |= CLOBBER_INPUT_VALUE;
+ }
+ }
+ }
+ }
+ if(index != 1 && !are_values_equal(desc, ®s->descs[1]))
+ {
+ if(reg == regs->descs[1].reg
+ || reg == regs->descs[1].other_reg
+ || (other_reg >= 0
+ && (other_reg == regs->descs[1].reg
+ || other_reg == regs->descs[1].other_reg)))
+ {
+ desc->thrash = 1;
+ }
+ }
+ if(index != 2 && !are_values_equal(desc, ®s->descs[2]))
+ {
+ if(reg == regs->descs[2].reg
+ || reg == regs->descs[2].other_reg
+ || (other_reg >= 0
+ && (other_reg == regs->descs[2].reg
+ || other_reg == regs->descs[2].other_reg)))
+ {
+ desc->thrash = 1;
+ }
+ }
+
+ if(desc->thrash)
+ {
+ reg = -1;
+ other_reg = -1;
+ desc->save = 1;
+ }
+ }
+
if(index > 0 || regs->ternary)
{
/* See if the value needs to be loaded or copied or none. */
if(desc->value->has_global_register)
{
if(desc->value->global_reg != desc->reg
- && !(desc->value->in_register && reg == desc->reg))
+ && !(reg >= 0 && reg == desc->reg))
{
desc->copy = 1;
}
}
else
{
- if(!desc->value->in_register)
+ if(reg < 0)
{
desc->load = 1;
}
@@ -2154,13 +2264,11 @@
{
desc->kill = 1;
}
- else if(desc->value->in_register)
+ else if(reg >= 0)
{
if(desc->used)
{
- if(jit_reg_is_used(regs->clobber, reg)
- || (other_reg >= 0
- && jit_reg_is_used(regs->clobber,
other_reg)))
+ if(!desc->copy && (clobber &
CLOBBER_INPUT_VALUE) != 0)
{
desc->save = 1;
desc->kill = 1;
@@ -2179,9 +2287,7 @@
{
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)))
+ if((clobber & CLOBBER_INPUT_VALUE) != 0)
{
desc->kill = 1;
}
@@ -2231,6 +2337,7 @@
printf("\n");
printf("value->in_register = %d\n", desc->value->in_register);
printf("value->reg = %d\n", desc->value->reg);
+ printf("value->has_global_register = %d\n",
desc->value->has_global_register);
printf("value->in_global_register = %d\n",
desc->value->in_global_register);
printf("value->global_reg = %d\n", desc->value->global_reg);
printf("value->in_frame = %d\n", desc->value->in_frame);
@@ -2241,6 +2348,7 @@
printf("clobber = %d\n", desc->clobber);
printf("early_clobber = %d\n", desc->early_clobber);
printf("duplicate = %d\n", desc->duplicate);
+ printf("thrash = %d\n", desc->thrash);
printf("save = %d\n", desc->save);
printf("load = %d\n", desc->load);
printf("copy = %d\n", desc->copy);
@@ -2251,16 +2359,42 @@
}
/*
- * To avoid circular movements of input values in place of each other
- * check if the current value overwrites any of the others.
+ * Check to see if loading one input value into the given register
+ * clobbers any other input values.
*/
static int
-thrashes_register(jit_gencode_t gen, _jit_regs_t *regs,
- _jit_regdesc_t *desc, int reg, int other_reg)
+thrashes_register(jit_gencode_t gen, _jit_regs_t *regs, int index, int reg,
int other_reg)
{
+ _jit_regdesc_t *desc;
int reg2, other_reg2;
- if(regs->ternary && regs->descs[0].value &&
regs->descs[0].value->in_register
- && !(desc && are_values_equal(®s->descs[0], desc)))
+
+ if(index < 0)
+ {
+ desc = 0;
+ }
+ else
+ {
+ if(index == 0 && !regs->ternary)
+ {
+ return 0;
+ }
+ desc = ®s->descs[index];
+ if(!desc->value)
+ {
+ return 0;
+ }
+ }
+
+ if(index != 0 && regs->ternary && regs->descs[0].value)
+ {
+ if(!(desc && regs->descs[0].value == desc->value)
+ && regs->descs[0].value->has_global_register
+ && regs->descs[0].value->global_reg == reg)
+ {
+ return 1;
+ }
+ if(regs->descs[0].value->in_register
+ && !are_values_equal(®s->descs[0], desc))
{
reg2 = regs->descs[0].value->reg;
if(reg2 == reg || reg2 == other_reg)
@@ -2276,8 +2410,17 @@
}
}
}
- if(regs->descs[1].value && regs->descs[1].value->in_register
- && !(desc && are_values_equal(®s->descs[1], desc)))
+ }
+ if(index != 1 && regs->descs[1].value)
+ {
+ if(!(desc && regs->descs[1].value == desc->value)
+ && regs->descs[1].value->has_global_register
+ && regs->descs[1].value->global_reg == reg)
+ {
+ return 1;
+ }
+ if(regs->descs[1].value->in_register
+ && !are_values_equal(®s->descs[1], desc))
{
reg2 = regs->descs[1].value->reg;
if(reg2 == reg || reg2 == other_reg)
@@ -2293,8 +2436,17 @@
}
}
}
- if(regs->descs[2].value && regs->descs[2].value->in_register
- && !(desc && are_values_equal(®s->descs[2], desc)))
+ }
+ if(index != 2 && regs->descs[2].value)
+ {
+ if(!(desc && regs->descs[2].value == desc->value)
+ && regs->descs[2].value->has_global_register
+ && regs->descs[2].value->global_reg == reg)
+ {
+ return 1;
+ }
+ if(regs->descs[2].value->in_register
+ && !are_values_equal(®s->descs[2], desc))
{
reg2 = regs->descs[2].value->reg;
if(reg2 == reg || reg2 == other_reg)
@@ -2310,9 +2462,31 @@
}
}
}
+ }
return 0;
}
+/*
+ * Compute the register spill cost. The register spill cost is computed as
+ * the sum of spill costs of individual values the register contains. The
+ * spill cost of a value depends on the following factors:
+ *
+ * 1. Values that are not used after the current instruction may be safely
+ * discareded so their spill cost is taken to be zero.
+ * 2. Values that are spilled to global registers are cheaper than values
+ * that are spilled into stack frame.
+ * 3. Clean values are cheaper than dirty values.
+ *
+ * NOTE: A value is clean if it was loaded from the stack frame or from a
+ * global register and has not changed since then. Otherwise it is dirty.
+ * There is no need to spill clean values. However their spill cost is
+ * considered to be non-zero so that the register allocator will choose
+ * those registers that do not contain live values over those that contain
+ * live albeit clean values.
+ *
+ * For global registers this function returns the cost of zero. So global
+ * registers have to be handled separately.
+ */
static int
compute_spill_cost(jit_gencode_t gen, _jit_regs_t *regs, int reg, int
other_reg)
{
@@ -2379,16 +2553,24 @@
}
if(value->has_global_register)
{
- if(!value->in_global_register)
+ if(value->in_global_register)
+ {
+ cost += COST_SPILL_CLEAN_GLOBAL;
+ }
+ else
{
- cost += 1;
+ cost += COST_SPILL_DIRTY_GLOBAL;
}
}
else
{
- if(!value->in_frame)
+ if(value->in_frame)
+ {
+ cost += COST_SPILL_CLEAN;
+ }
+ else
{
- cost += 10;
+ cost += COST_SPILL_DIRTY;
}
}
}
@@ -2445,17 +2627,19 @@
*
*/
static int
-use_cheapest_register(jit_gencode_t gen, _jit_regs_t *regs, int index,
jit_regused_t regset)
+use_cheapest_register(jit_gencode_t gen, _jit_regs_t *regs, int index,
jit_regused_t allowed)
{
_jit_regdesc_t *desc;
- int output;
- int type;
- int need_pair;
+ _jit_regdesc_t *desc2;
+ _jit_regdesc_t *desc3;
+ int is_output, output_index;
+ int type, need_pair;
int reg, other_reg;
int cost, copy_cost;
int suitable_reg;
int suitable_cost;
int suitable_age;
+ int clobber;
if(index >= 0)
{
@@ -2464,7 +2648,25 @@
{
return -1;
}
- output = (index == 0 && !regs->ternary);
+
+ if(regs->ternary || regs->descs[0].value == 0)
+ {
+ is_output = 0;
+ output_index = 0;
+ }
+ else
+ {
+ is_output = (index == 0);
+ if(regs->free_dest)
+ {
+ output_index = 0;
+ }
+ else
+ {
+ output_index = 1 + (regs->reverse_dest ^
regs->reverse_args);
+ }
+ }
+
need_pair = _jit_regs_needs_long_pair(desc->value->type);
type = get_register_type(desc->value, need_pair);
if(!type)
@@ -2475,7 +2677,8 @@
else
{
desc = 0;
- output = 0;
+ is_output = 0;
+ output_index = 0;
need_pair = 0;
type = JIT_REG_WORD;
}
@@ -2489,8 +2692,7 @@
{
continue;
}
-
- if(!jit_reg_is_used(regset, reg)
+ if(!jit_reg_is_used(allowed, reg)
|| jit_reg_is_used(gen->inhibit, reg)
|| jit_reg_is_used(regs->assigned, reg))
{
@@ -2503,125 +2705,122 @@
{
continue;
}
- else if(thrashes_register(gen, regs, desc, reg, -1))
+ else if(thrashes_register(gen, regs, index, reg, -1))
{
continue;
}
- copy_cost = 0;
cost = compute_spill_cost(gen, regs, reg, -1);
+ copy_cost = 0;
}
- else if(desc->value->has_global_register)
+ else
{
- if(reg == desc->value->global_reg)
+ if(need_pair)
{
- if(clobbers_register(gen, regs, index, reg, -1))
+ other_reg = OTHER_REG(reg);
+ if(jit_reg_is_used(gen->inhibit, other_reg)
+ || jit_reg_is_used(regs->assigned,
other_reg))
{
continue;
}
- copy_cost = ((output |
desc->value->in_global_register) == 0);
- cost = 0;
}
- else if(jit_reg_is_used(gen->permanent, reg))
+ else
{
- continue;
+ other_reg = -1;
}
- else if(thrashes_register(gen, regs, desc, reg, -1))
+
+ clobber = clobbers_register(gen, regs, index, reg,
other_reg);
+ if((clobber & ~CLOBBER_INPUT_VALUE) != 0)
+ {
+ if(jit_reg_is_used(gen->permanent, reg))
{
continue;
}
- else if(desc->value->in_register && reg ==
desc->value->reg)
- {
- copy_cost = ((output |
desc->value->in_global_register) != 0);
- if(clobbers_register(gen, regs, index, reg, -1))
+#if !ALLOW_LONGS_USE_GLOBAL
+ if(other_reg >= 0 &&
jit_reg_is_used(gen->permanent, other_reg))
{
- cost = compute_spill_cost(gen, regs,
reg, -1);
+ continue;
}
- else
+#endif
+ if(jit_reg_is_used(regs->clobber, reg)
+ || (other_reg >= 0 &&
jit_reg_is_used(regs->clobber, other_reg)))
{
cost = 0;
}
- }
else
{
- copy_cost = 1;
- cost = compute_spill_cost(gen, regs, reg, -1);
+ cost = compute_spill_cost(gen, regs,
reg, other_reg);
+ }
+#if ALLOW_LONGS_USE_GLOBAL
+ if(other_reg >= 0 &&
jit_reg_is_used(gen->permanent, other_reg))
+ {
+ cost += COST_CLOBBER_GLOBAL;
}
+#endif
}
else
{
- if(jit_reg_is_used(gen->permanent, reg))
- {
- continue;
+ cost = 0;
}
- if(need_pair)
+ if(thrashes_register(gen, regs,
+ is_output ? output_index : index,
+ reg, other_reg))
{
- other_reg = OTHER_REG(reg);
-
- if(jit_reg_is_used(gen->inhibit, other_reg)
- || jit_reg_is_used(regs->assigned,
other_reg))
+ if(jit_reg_is_used(gen->permanent, reg))
{
continue;
}
-#if !ALLOW_CLOBBER_GLOBAL
- if(jit_reg_is_used(gen->permanent, other_reg))
+ if(other_reg >= 0 &&
jit_reg_is_used(gen->permanent, other_reg))
{
continue;
}
-#endif
- }
- else
+ cost += COST_THRASH;
+ if(other_reg >= 0)
{
- other_reg = -1;
+ cost += COST_THRASH;
+ }
}
- if(thrashes_register(gen, regs, desc, reg, other_reg))
+ if(is_output)
{
- continue;
+ if(output_index &&
regs->descs[output_index].value)
+ {
+ desc2 = ®s->descs[output_index];
}
- if(desc->value->in_register)
+ else
{
- if(reg == desc->value->reg)
+ desc2 = 0;
+ }
+ desc3 = ®s->descs[0];
+ }
+ else
{
- 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))))
+ desc2 = desc;
+ if(output_index && index == output_index)
{
- copy_cost = 0;
- cost = compute_spill_cost(gen,
regs, reg, other_reg);
+ desc3 = ®s->descs[0];
}
else
{
- copy_cost = 0;
- cost = 0;
+ desc3 = desc;
}
}
- else
+ if(!desc2
+ || (desc2->value->in_global_register &&
desc2->value->global_reg == reg)
+ || (desc2->value->in_register && desc2->value->reg
== reg))
{
- copy_cost = 1;
- cost = compute_spill_cost(gen, regs,
reg, other_reg);
- }
+ copy_cost = 0;
}
else
{
- copy_cost = 0;
- cost = compute_spill_cost(gen, regs, reg,
other_reg);
+ copy_cost = COST_COPY;
}
-#if ALLOW_CLOBBER_GLOBAL
- if(other_reg >= 0 && jit_reg_is_used(gen->permanent,
other_reg))
+ if(desc3->value->has_global_register &&
desc3->value->global_reg != reg)
{
- cost += COST_CLOBBER_GLOBAL;
+ cost += COST_GLOBAL_BIAS;
}
-#endif
}
-#if COST_COPY != 1
- if(copy_cost)
- {
- copy_cost = COST_COPY;
- }
-#endif
if((cost + copy_cost) < suitable_cost
|| (cost > 0 && (cost + copy_cost) == suitable_cost
&& gen->contents[reg].age < suitable_age))
@@ -2634,9 +2833,7 @@
}
reg = suitable_reg;
- if(reg >= 0)
- {
- if(desc)
+ if(desc && reg >= 0)
{
if(need_pair)
{
@@ -2648,11 +2845,6 @@
}
set_regdesc_register(gen, regs, index, reg, other_reg);
}
- else
- {
- set_register_flags(gen, regs, reg, 1, 0);
- }
- }
return reg;
}
@@ -2694,7 +2886,7 @@
int keep1, keep2;
int out_index;
- if(regs->ternary || !(regs->commutative || regs->x87_arith))
+ if(regs->ternary || regs->free_dest || !(regs->commutative ||
regs->x87_arith))
{
/* Bail out on ternary or non-commutative and non-x87
instruction. */
return;
@@ -2711,7 +2903,7 @@
}
/* Determine if we might want to keep either of input values
- in registers after the operation completion. */
+ in registers after the instruction completion. */
if(regs->clobber_all)
{
keep1 = 0;
@@ -3003,6 +3195,11 @@
return;
}
+ if(value->is_constant)
+ {
+ still_in_frame = 0;
+ }
+
gen->contents[reg].values[0] = value;
gen->contents[reg].num_values = 1;
gen->contents[reg].age = gen->current_age;
@@ -3397,7 +3594,14 @@
other_reg = -1;
}
+ if(desc->thrash)
+ {
+ save_value(gen, desc->value, reg, other_reg, 1);
+ }
+ else
+ {
save_value(gen, desc->value, reg, other_reg, 0);
+ }
}
static void
@@ -3721,7 +3925,7 @@
}
void
-_jit_regs_init(_jit_regs_t *regs, int flags)
+_jit_regs_init(jit_gencode_t gen, _jit_regs_t *regs, int flags)
{
int index;
@@ -3750,9 +3954,22 @@
}
regs->num_scratch = 0;
- regs->assigned = jit_regused_init;
+ /* Set clobber flags. */
regs->clobber = jit_regused_init;
- regs->spill = jit_regused_init;
+ 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);
+ }
+ }
+
+ regs->assigned = jit_regused_init;
regs->stack_start = -1;
regs->current_stack_top = 0;
@@ -3794,39 +4011,55 @@
}
void
-_jit_regs_set_dest(_jit_regs_t *regs, int reg, int other_reg)
+_jit_regs_set_dest(jit_gencode_t gen, _jit_regs_t *regs, int reg, int
other_reg)
{
- regs->descs[0].reg = reg;
- regs->descs[0].other_reg = other_reg;
+ if(reg >= 0 && !IS_STACK_REG(reg))
+ {
+ set_regdesc_register(gen, regs, 0, reg, other_reg);
+ }
}
void
-_jit_regs_set_value1(_jit_regs_t *regs, int reg, int other_reg)
+_jit_regs_set_value1(jit_gencode_t gen, _jit_regs_t *regs, int reg, int
other_reg)
{
- regs->descs[1].reg = reg;
- regs->descs[1].other_reg = other_reg;
+ if(reg >= 0 && !IS_STACK_REG(reg))
+ {
+ set_regdesc_register(gen, regs, 1, reg, other_reg);
+ }
}
void
-_jit_regs_set_value2(_jit_regs_t *regs, int reg, int other_reg)
+_jit_regs_set_value2(jit_gencode_t gen, _jit_regs_t *regs, int reg, int
other_reg)
{
- regs->descs[2].reg = reg;
- regs->descs[2].other_reg = other_reg;
+ if(reg >= 0 && !IS_STACK_REG(reg))
+ {
+ set_regdesc_register(gen, regs, 2, reg, other_reg);
+ }
}
void
-_jit_regs_add_scratch(_jit_regs_t *regs, int reg)
+_jit_regs_add_scratch(jit_gencode_t gen, _jit_regs_t *regs, int reg)
{
if(regs->num_scratch < _JIT_REGS_SCRATCH_MAX)
{
- regs->scratch[regs->num_scratch++].reg = reg;
+ if(reg < 0)
+ {
+ ++regs->num_scratch;
+ }
+ else if(!IS_STACK_REG(reg))
+ {
+ set_scratch_register(gen, regs, regs->num_scratch++,
reg);
+ }
}
}
void
-_jit_regs_set_clobber(_jit_regs_t *regs, int reg)
+_jit_regs_set_clobber(jit_gencode_t gen, _jit_regs_t *regs, int reg)
{
+ if(reg >= 0)
+ {
jit_reg_set_used(regs->clobber, reg);
+ }
}
void
@@ -3905,84 +4138,25 @@
int
_jit_regs_assign(jit_gencode_t gen, _jit_regs_t *regs)
{
- int index, out_index;
+ int reg, index, out_index;
#ifdef JIT_REG_DEBUG
printf("_jit_regs_assign()\n");
#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)
- {
- if(IS_STACK_REG(regs->descs[0].reg))
- {
- return 0;
- }
- set_regdesc_register(gen, regs, 0,
- regs->descs[0].reg,
- regs->descs[0].other_reg);
- }
- if(regs->descs[1].reg >= 0)
- {
- if(IS_STACK_REG(regs->descs[1].reg))
- {
- return 0;
- }
- set_regdesc_register(gen, regs, 1,
- regs->descs[1].reg,
- regs->descs[1].other_reg);
- }
- if(regs->descs[2].reg >= 0)
- {
- if(IS_STACK_REG(regs->descs[2].reg))
- {
- return 0;
- }
- set_regdesc_register(gen, regs, 2,
- regs->descs[2].reg,
- regs->descs[2].other_reg);
- }
-
- for(index = 0; index < regs->num_scratch; index++)
- {
- if(regs->scratch[index].reg >= 0)
- {
- if(IS_STACK_REG(regs->scratch[index].reg))
- {
- return 0;
- }
- set_register_flags(gen, regs, regs->scratch[index].reg,
1, 0);
- }
- }
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);
- if(regs->scratch[index].reg < 0)
+ reg = use_cheapest_register(gen, regs, -1,
regs->scratch[index].regset);
+ if(reg < 0)
{
return 0;
}
+ set_scratch_register(gen, regs, index, reg);
}
}
@@ -4006,41 +4180,12 @@
check_duplicate_value(regs, ®s->descs[0], ®s->descs[1]);
check_duplicate_value(regs, ®s->descs[0], ®s->descs[2]);
}
- else if(regs->descs[0].value && regs->descs[out_index].value)
- {
- if(regs->descs[0].reg < 0 && regs->descs[out_index].reg < 0)
- {
- 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))
- {
- /* 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)
- {
- return 0;
- }
- }
- else if(regs->descs[0].value->has_global_register
- || (regs->descs[0].value->in_register
- &&
gen->contents[regs->descs[0].value->reg].num_values == 1))
- {
- use_cheapest_register(gen, regs, 0,
regs->descs[0].regset);
- if(regs->descs[0].reg < 0)
- {
- return 0;
- }
- }
- }
- if(regs->descs[0].reg >= 0)
+ else if(!regs->free_dest && regs->descs[0].reg >= 0 &&
regs->descs[out_index].value)
{
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)
{
use_cheapest_register(gen, regs, 1, regs->descs[1].regset);
@@ -4060,7 +4205,7 @@
}
if(regs->descs[0].value && regs->descs[0].reg < 0)
{
- if(regs->descs[out_index].reg < 0)
+ if(regs->free_dest || regs->descs[out_index].reg < 0)
{
use_cheapest_register(gen, regs, 0,
regs->descs[0].regset);
if(regs->descs[0].reg < 0)
@@ -4080,25 +4225,25 @@
{
if(regs->scratch[index].reg < 0)
{
- regs->scratch[index].reg = use_cheapest_register(
- gen, regs, -1, jit_regused_init_used);
- if(regs->scratch[index].reg < 0)
+ reg = use_cheapest_register(gen, regs, -1,
jit_regused_init_used);
+ if(reg < 0)
{
return 0;
}
+ set_scratch_register(gen, regs, index, reg);
}
}
/* Collect information about registers. */
- if(!collect_register_info(gen, regs, 0))
+ if(!set_regdesc_flags(gen, regs, 0))
{
return 0;
}
- if(!collect_register_info(gen, regs, 1))
+ if(!set_regdesc_flags(gen, regs, 1))
{
return 0;
}
- if(!collect_register_info(gen, regs, 2))
+ if(!set_regdesc_flags(gen, regs, 2))
{
return 0;
}
@@ -4130,7 +4275,7 @@
stack_start = reg;
}
- if(!jit_reg_is_used(regs->spill, reg))
+ if(!jit_reg_is_used(regs->clobber, reg))
{
continue;
}
@@ -4143,7 +4288,7 @@
if(regs->branch)
{
/* After the branch is taken there is no way
- to load global register back. */
+ to load the global register back. */
return 0;
}
_jit_gen_spill_global(gen, reg, 0);
@@ -4157,7 +4302,7 @@
if(IS_STACK_REG(reg))
{
top = get_stack_top(gen, stack_start);
- while(top > reg && jit_reg_is_used(regs->spill, top))
+ while(top > reg && jit_reg_is_used(regs->clobber, top))
{
spill_reg(gen, regs, top);
/* If one of the input values is on the top
@@ -4311,7 +4456,7 @@
/* Load clobbered global registers. */
for(reg = JIT_NUM_REGS - 1; reg >= 0; reg--)
{
- if(jit_reg_is_used(regs->spill, reg) &&
jit_reg_is_used(gen->permanent, reg))
+ if(jit_reg_is_used(regs->clobber, reg) &&
jit_reg_is_used(gen->permanent, reg))
{
_jit_gen_load_global(gen, reg, 0);
}
Index: jit/jit-rules-x86.ins
===================================================================
RCS file: /sources/dotgnu-pnet/libjit/jit/jit-rules-x86.ins,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -b -r1.7 -r1.8
--- jit/jit-rules-x86.ins 16 Jun 2006 02:35:16 -0000 1.7
+++ jit/jit-rules-x86.ins 16 Jun 2006 17:53:51 -0000 1.8
@@ -431,22 +431,13 @@
x86_imul_reg_reg(inst, $1, $2);
}
-/* Spill before division to ensure that the arguments end up in
- EAX and ECX, and that EDX is free */
-JIT_OP_IDIV: binary, spill_before, more_space
- [reg, imm] -> {
- switch($2)
- {
- case 0:
- {
+JIT_OP_IDIV: more_space
+ [any, immzero] -> {
inst = throw_builtin(inst, func,
JIT_RESULT_DIVISION_BY_ZERO);
}
- break;
-
- case 1: break;
-
- case -1:
- {
+ [reg, imm, if("$2 == 1")] -> {
+ }
+ [reg, imm, if("$2 == -1")] -> {
/* Dividing by -1 gives an exception if the
argument
is minint, or simply negates for other
values */
unsigned char *patch;
@@ -457,204 +448,21 @@
x86_patch(patch, inst);
x86_neg_reg(inst, $1);
}
- break;
-
- case 2:
- {
- x86_shift_reg_imm(inst, X86_SAR, $1, 1);
- }
- break;
-
- case 4:
- {
- x86_shift_reg_imm(inst, X86_SAR, $1, 2);
- }
- break;
-
- case 8:
- {
- x86_shift_reg_imm(inst, X86_SAR, $1, 3);
- }
- break;
-
- case 16:
- {
- x86_shift_reg_imm(inst, X86_SAR, $1, 4);
- }
- break;
-
- case 32:
- {
- x86_shift_reg_imm(inst, X86_SAR, $1, 5);
- }
- break;
-
- case 64:
- {
- x86_shift_reg_imm(inst, X86_SAR, $1, 6);
- }
- break;
-
- case 128:
- {
- x86_shift_reg_imm(inst, X86_SAR, $1, 7);
- }
- break;
-
- case 256:
- {
- x86_shift_reg_imm(inst, X86_SAR, $1, 8);
- }
- break;
-
- case 512:
- {
- x86_shift_reg_imm(inst, X86_SAR, $1, 9);
- }
- break;
-
- case 1024:
+ [reg, imm, if("(((jit_nuint)$2) & (((jit_nuint)$2) - 1)) == 0")] -> {
+ /* x & (x - 1) is equal to zero if x is a power of 2 */
+ jit_nuint shift, value;
+ for(shift = 0, value = $2; value; value >>= 1)
{
- x86_shift_reg_imm(inst, X86_SAR, $1, 10);
+ ++shift;
}
- break;
-
- case 2048:
- {
- x86_shift_reg_imm(inst, X86_SAR, $1, 11);
+ x86_shift_reg_imm(inst, X86_SAR, $1, shift);
}
- break;
-
- case 4096:
- {
- x86_shift_reg_imm(inst, X86_SAR, $1, 12);
- }
- break;
-
- case 8192:
- {
- x86_shift_reg_imm(inst, X86_SAR, $1, 13);
- }
- break;
-
- case 16384:
- {
- x86_shift_reg_imm(inst, X86_SAR, $1, 14);
- }
- break;
-
- case 32768:
- {
- x86_shift_reg_imm(inst, X86_SAR, $1, 15);
- }
- break;
-
- case 65536:
- {
- x86_shift_reg_imm(inst, X86_SAR, $1, 16);
- }
- break;
-
- case 0x00020000:
- {
- x86_shift_reg_imm(inst, X86_SAR, $1, 17);
- }
- break;
-
- case 0x00040000:
- {
- x86_shift_reg_imm(inst, X86_SAR, $1, 18);
- }
- break;
-
- case 0x00080000:
- {
- x86_shift_reg_imm(inst, X86_SAR, $1, 19);
- }
- break;
-
- case 0x00100000:
- {
- x86_shift_reg_imm(inst, X86_SAR, $1, 20);
- }
- break;
-
- case 0x00200000:
- {
- x86_shift_reg_imm(inst, X86_SAR, $1, 21);
- }
- break;
-
- case 0x00400000:
- {
- x86_shift_reg_imm(inst, X86_SAR, $1, 22);
- }
- break;
-
- case 0x00800000:
- {
- x86_shift_reg_imm(inst, X86_SAR, $1, 23);
- }
- break;
-
- case 0x01000000:
- {
- x86_shift_reg_imm(inst, X86_SAR, $1, 24);
- }
- break;
-
- case 0x02000000:
- {
- x86_shift_reg_imm(inst, X86_SAR, $1, 25);
- }
- break;
-
- case 0x04000000:
- {
- x86_shift_reg_imm(inst, X86_SAR, $1, 26);
- }
- break;
-
- case 0x08000000:
- {
- x86_shift_reg_imm(inst, X86_SAR, $1, 27);
- }
- break;
-
- case 0x10000000:
- {
- x86_shift_reg_imm(inst, X86_SAR, $1, 28);
- }
- break;
-
- case 0x20000000:
- {
- x86_shift_reg_imm(inst, X86_SAR, $1, 29);
- }
- break;
-
- case 0x40000000:
- {
- x86_shift_reg_imm(inst, X86_SAR, $1, 30);
- }
- break;
-
- case (jit_nint)0x80000000:
- {
- x86_shift_reg_imm(inst, X86_SAR, $1, 31);
- }
- break;
-
- default:
- {
- x86_mov_reg_imm(inst, X86_ECX, $2);
+ [reg("eax"), imm, scratch("?", "edx")] -> {
+ x86_mov_reg_imm(inst, $3, $2);
x86_cdq(inst);
- x86_div_reg(inst, X86_ECX, 1);
- }
- break;
- }
+ x86_div_reg(inst, $3, 1);
}
- [reg, reg] -> {
+ [reg("eax"), reg, scratch("edx")] -> {
unsigned char *patch, *patch2;
x86_alu_reg_reg(inst, X86_OR, $2, $2);
patch = inst;
@@ -674,214 +482,27 @@
x86_div_reg(inst, $2, 1);
}
-JIT_OP_IDIV_UN: binary, spill_before, more_space
- [reg, imm] -> {
- switch($2)
- {
- case 0:
- {
+JIT_OP_IDIV_UN: more_space
+ [any, immzero] -> {
inst = throw_builtin(inst, func,
JIT_RESULT_DIVISION_BY_ZERO);
}
- break;
-
- case 1: break;
-
- case 2:
- {
- x86_shift_reg_imm(inst, X86_SHR, $1, 1);
- }
- break;
-
- case 4:
- {
- x86_shift_reg_imm(inst, X86_SHR, $1, 2);
- }
- break;
-
- case 8:
- {
- x86_shift_reg_imm(inst, X86_SHR, $1, 3);
- }
- break;
-
- case 16:
- {
- x86_shift_reg_imm(inst, X86_SHR, $1, 4);
- }
- break;
-
- case 32:
- {
- x86_shift_reg_imm(inst, X86_SHR, $1, 5);
- }
- break;
-
- case 64:
- {
- x86_shift_reg_imm(inst, X86_SHR, $1, 6);
- }
- break;
-
- case 128:
- {
- x86_shift_reg_imm(inst, X86_SHR, $1, 7);
- }
- break;
-
- case 256:
- {
- x86_shift_reg_imm(inst, X86_SHR, $1, 8);
- }
- break;
-
- case 512:
- {
- x86_shift_reg_imm(inst, X86_SHR, $1, 9);
- }
- break;
-
- case 1024:
- {
- x86_shift_reg_imm(inst, X86_SHR, $1, 10);
- }
- break;
-
- case 2048:
- {
- x86_shift_reg_imm(inst, X86_SHR, $1, 11);
- }
- break;
-
- case 4096:
- {
- x86_shift_reg_imm(inst, X86_SHR, $1, 12);
- }
- break;
-
- case 8192:
- {
- x86_shift_reg_imm(inst, X86_SHR, $1, 13);
- }
- break;
-
- case 16384:
- {
- x86_shift_reg_imm(inst, X86_SHR, $1, 14);
- }
- break;
-
- case 32768:
- {
- x86_shift_reg_imm(inst, X86_SHR, $1, 15);
- }
- break;
-
- case 65536:
- {
- x86_shift_reg_imm(inst, X86_SHR, $1, 16);
- }
- break;
-
- case 0x00020000:
- {
- x86_shift_reg_imm(inst, X86_SHR, $1, 17);
- }
- break;
-
- case 0x00040000:
- {
- x86_shift_reg_imm(inst, X86_SHR, $1, 18);
- }
- break;
-
- case 0x00080000:
- {
- x86_shift_reg_imm(inst, X86_SHR, $1, 19);
- }
- break;
-
- case 0x00100000:
- {
- x86_shift_reg_imm(inst, X86_SHR, $1, 20);
- }
- break;
-
- case 0x00200000:
- {
- x86_shift_reg_imm(inst, X86_SHR, $1, 21);
- }
- break;
-
- case 0x00400000:
- {
- x86_shift_reg_imm(inst, X86_SHR, $1, 22);
- }
- break;
-
- case 0x00800000:
- {
- x86_shift_reg_imm(inst, X86_SHR, $1, 23);
- }
- break;
-
- case 0x01000000:
- {
- x86_shift_reg_imm(inst, X86_SHR, $1, 24);
- }
- break;
-
- case 0x02000000:
- {
- x86_shift_reg_imm(inst, X86_SHR, $1, 25);
- }
- break;
-
- case 0x04000000:
- {
- x86_shift_reg_imm(inst, X86_SHR, $1, 26);
- }
- break;
-
- case 0x08000000:
- {
- x86_shift_reg_imm(inst, X86_SHR, $1, 27);
- }
- break;
-
- case 0x10000000:
- {
- x86_shift_reg_imm(inst, X86_SHR, $1, 28);
+ [reg, imm, if("$2 == 1")] -> {
}
- break;
-
- case 0x20000000:
+ [reg, imm, if("(((jit_nuint)$2) & (((jit_nuint)$2) - 1)) == 0")] -> {
+ /* x & (x - 1) is equal to zero if x is a power of 2 */
+ jit_nuint shift, value;
+ for(shift = 0, value = $2; value; value >>= 1)
{
- x86_shift_reg_imm(inst, X86_SHR, $1, 29);
+ ++shift;
}
- break;
-
- case 0x40000000:
- {
- x86_shift_reg_imm(inst, X86_SHR, $1, 30);
- }
- break;
-
- case (jit_nint)0x80000000:
- {
- x86_shift_reg_imm(inst, X86_SHR, $1, 31);
+ x86_shift_reg_imm(inst, X86_SAR, $1, shift);
}
- break;
-
- default:
- {
- x86_mov_reg_imm(inst, X86_ECX, $2);
+ [reg("eax"), imm, scratch("?", "edx")] -> {
+ x86_mov_reg_imm(inst, $3, $2);
x86_clear_reg(inst, X86_EDX);
- x86_div_reg(inst, X86_ECX, 0);
- }
- break;
+ x86_div_reg(inst, $3, 0);
}
- }
- [reg, reg] -> {
+ [reg("eax"), reg, scratch("edx")] -> {
unsigned char *patch;
x86_alu_reg_reg(inst, X86_OR, $2, $2);
patch = inst;
@@ -892,24 +513,14 @@
x86_div_reg(inst, $2, 0);
}
-JIT_OP_IREM: binary, spill_before, more_space
- [reg, imm] -> {
- switch($2)
- {
- case 0:
- {
+JIT_OP_IREM: more_space
+ [any, immzero] -> {
inst = throw_builtin(inst, func,
JIT_RESULT_DIVISION_BY_ZERO);
}
- break;
-
- case 1:
- {
+ [reg, imm, if("$2 == 1")] -> {
x86_clear_reg(inst, $1);
}
- break;
-
- case -1:
- {
+ [reg, imm, if("$2 == -1")] -> {
/* Dividing by -1 gives an exception if the
argument
is minint, or simply gives a remainder of
zero */
unsigned char *patch;
@@ -920,20 +531,12 @@
x86_patch(patch, inst);
x86_clear_reg(inst, $1);
}
- break;
-
- default:
- {
- x86_mov_reg_imm(inst, X86_ECX, $2);
+ [=reg("edx"), *reg("eax"), imm, scratch("?")] -> {
+ x86_mov_reg_imm(inst, $3, $2);
x86_cdq(inst);
- x86_div_reg(inst, X86_ECX, 1);
- /* TODO: rearrange register assignments to
avoid the move */
- x86_mov_reg_reg(inst, X86_EAX, X86_EDX, 4);
+ x86_div_reg(inst, $3, 1);
}
- break;
- }
- }
- [reg, reg] -> {
+ [=reg("edx"), *reg("eax"), reg] -> {
unsigned char *patch, *patch2;
x86_alu_reg_reg(inst, X86_OR, $2, $2);
patch = inst;
@@ -951,72 +554,25 @@
x86_patch(patch2, inst);
x86_cdq(inst);
x86_div_reg(inst, $2, 1);
- x86_mov_reg_reg(inst, X86_EAX, X86_EDX, 4);
}
-JIT_OP_IREM_UN: binary, spill_before, more_space
- [reg, imm] -> {
- switch($2)
- {
- case 0:
- {
+JIT_OP_IREM_UN: more_space
+ [any, immzero] -> {
inst = throw_builtin(inst, func,
JIT_RESULT_DIVISION_BY_ZERO);
}
- break;
-
- case 1:
- {
+ [reg, imm, if("$2 == 1")] -> {
x86_clear_reg(inst, $1);
}
- break;
-
- case 2:
- case 4:
- case 8:
- case 16:
- case 32:
- case 64:
- case 128:
- case 256:
- case 512:
- case 1024:
- case 2048:
- case 4096:
- case 8192:
- case 16384:
- case 32768:
- case 65536:
- case 0x00020000:
- case 0x00040000:
- case 0x00080000:
- case 0x00100000:
- case 0x00200000:
- case 0x00400000:
- case 0x00800000:
- case 0x01000000:
- case 0x02000000:
- case 0x04000000:
- case 0x08000000:
- case 0x10000000:
- case 0x20000000:
- case 0x40000000:
- case (jit_nint)0x80000000:
- {
+ [reg, imm, if("(((jit_nuint)$2) & (((jit_nuint)$2) - 1)) == 0")] -> {
+ /* x & (x - 1) is equal to zero if x is a power of 2 */
x86_alu_reg_imm(inst, X86_AND, $1, $2 - 1);
}
- break;
-
- default:
- {
- x86_mov_reg_imm(inst, X86_ECX, $2);
+ [=reg("edx"), *reg("eax"), imm, scratch("?")] -> {
+ x86_mov_reg_imm(inst, $3, $2);
x86_clear_reg(inst, X86_EDX);
- x86_div_reg(inst, X86_ECX, 0);
- x86_mov_reg_reg(inst, X86_EAX, X86_EDX, 4);
- }
- break;
- }
+ x86_div_reg(inst, $3, 0);
}
- [reg, reg] -> {
+ [=reg("edx"), *reg("eax"), reg] -> {
unsigned char *patch;
x86_alu_reg_reg(inst, X86_OR, $2, $2);
patch = inst;
@@ -1025,7 +581,6 @@
x86_patch(patch, inst);
x86_clear_reg(inst, X86_EDX);
x86_div_reg(inst, $2, 0);
- x86_mov_reg_reg(inst, X86_EAX, X86_EDX, 4);
}
JIT_OP_INEG: unary
@@ -1916,35 +1471,19 @@
TODO();
}
-JIT_OP_ADDRESS_OF_LABEL: manual
- [] -> {
- unsigned char *inst;
- jit_block_t block;
- int reg;
-
- reg = _jit_regs_dest_value(gen, insn->dest);
-
- inst = gen->posn.ptr;
- if(!jit_cache_check_for_n(&(gen->posn), 32))
- {
- jit_cache_mark_full(&(gen->posn));
- return;
- }
- reg = _jit_reg_info[reg].cpu_reg;
-
+JIT_OP_ADDRESS_OF_LABEL:
+ [=reg] -> {
block = jit_block_from_label(func, (jit_label_t)(insn->value1));
if(block->address)
{
- x86_mov_reg_imm(inst, reg, block->address);
+ x86_mov_reg_imm(inst, $0, block->address);
}
else
{
/* Output a placeholder and record on the block's fixup
list */
- x86_mov_reg_imm(inst, reg,
(int)(block->fixup_absolute_list));
+ x86_mov_reg_imm(inst, $0,
(int)(block->fixup_absolute_list));
block->fixup_absolute_list = (void *)(inst - 4);
}
-
- gen->posn.ptr = inst;
}
/*
@@ -2289,68 +1828,22 @@
gen->posn.ptr = inst;
}
-JIT_OP_LOAD_RELATIVE_FLOAT32: manual
- [] -> {
- unsigned char *inst;
- int reg = _jit_regs_load_value
- (gen, insn->value1, 0,
- (insn->flags & (JIT_INSN_VALUE1_NEXT_USE |
-
JIT_INSN_VALUE1_LIVE)));
- _jit_regs_new_top(gen, insn->dest, 8);
- inst = gen->posn.ptr;
- if(!jit_cache_check_for_n(&(gen->posn), 32))
- {
- jit_cache_mark_full(&(gen->posn));
- return;
- }
- reg = _jit_reg_info[reg].cpu_reg;
- x86_fld_membase(inst, reg, insn->value2->address, 0);
- gen->posn.ptr = inst;
+JIT_OP_LOAD_RELATIVE_FLOAT32:
+ [=freg, reg, imm] -> {
+ x86_fld_membase(inst, $1, $2, 0);
}
-JIT_OP_LOAD_RELATIVE_FLOAT64: manual
- [] -> {
- unsigned char *inst;
- int reg = _jit_regs_load_value
- (gen, insn->value1, 0,
- (insn->flags & (JIT_INSN_VALUE1_NEXT_USE |
-
JIT_INSN_VALUE1_LIVE)));
- _jit_regs_new_top(gen, insn->dest, 8);
- inst = gen->posn.ptr;
- if(!jit_cache_check_for_n(&(gen->posn), 32))
- {
- jit_cache_mark_full(&(gen->posn));
- return;
- }
- reg = _jit_reg_info[reg].cpu_reg;
- x86_fld_membase(inst, reg, insn->value2->address, 1);
- gen->posn.ptr = inst;
+JIT_OP_LOAD_RELATIVE_FLOAT64:
+ [=freg, reg, imm] -> {
+ x86_fld_membase(inst, $1, $2, 1);
}
-JIT_OP_LOAD_RELATIVE_NFLOAT: manual
- [] -> {
- unsigned char *inst;
- int reg = _jit_regs_load_value
- (gen, insn->value1, 0,
- (insn->flags & (JIT_INSN_VALUE1_NEXT_USE |
-
JIT_INSN_VALUE1_LIVE)));
- _jit_regs_new_top(gen, insn->dest, 8);
- inst = gen->posn.ptr;
- if(!jit_cache_check_for_n(&(gen->posn), 32))
- {
- jit_cache_mark_full(&(gen->posn));
- return;
+JIT_OP_LOAD_RELATIVE_NFLOAT:
+ [=freg, reg, imm, if("sizeof(jit_nfloat) != sizeof(jit_float64)")] -> {
+ x86_fld80_membase(inst, $1, $2);
}
- reg = _jit_reg_info[reg].cpu_reg;
- if(sizeof(jit_nfloat) != sizeof(jit_float64))
- {
- x86_fld80_membase(inst, reg, insn->value2->address);
- }
- else
- {
- x86_fld_membase(inst, reg, insn->value2->address, 1);
- }
- gen->posn.ptr = inst;
+ [=freg, reg, imm, if("sizeof(jit_nfloat) == sizeof(jit_float64)")] -> {
+ x86_fld_membase(inst, $1, $2, 1);
}
JIT_OP_LOAD_RELATIVE_STRUCT: unary_branch, more_space
@@ -2547,94 +2040,25 @@
gen->posn.ptr = inst;
}
-JIT_OP_LOAD_ELEMENT_FLOAT32: manual
- [] -> {
- unsigned char *inst;
- int reg, reg2;
-
- reg = _jit_regs_load_value(gen, insn->value1, 0,
- (insn->flags & (JIT_INSN_VALUE1_NEXT_USE |
JIT_INSN_VALUE1_LIVE)));
- reg2 = _jit_regs_load_value(gen, insn->value2, 0,
- (insn->flags & (JIT_INSN_VALUE2_NEXT_USE |
JIT_INSN_VALUE2_LIVE)));
- _jit_regs_new_top(gen, insn->dest, 8);
-
- inst = gen->posn.ptr;
- if(!jit_cache_check_for_n(&(gen->posn), 32))
- {
- jit_cache_mark_full(&(gen->posn));
- return;
- }
-
- reg = _jit_reg_info[reg].cpu_reg;
- reg2 = _jit_reg_info[reg2].cpu_reg;
-
- x86_fld_memindex(inst, reg, 0, reg2, 2, 0);
-
- gen->posn.ptr = inst;
- }
-
-JIT_OP_LOAD_ELEMENT_FLOAT64: manual
- [] -> {
- unsigned char *inst;
- int reg, reg2, reg3;
-
- reg = _jit_regs_load_value(gen, insn->value1, 0,
- (insn->flags & (JIT_INSN_VALUE1_NEXT_USE |
JIT_INSN_VALUE1_LIVE)));
- reg2 = _jit_regs_load_value(gen, insn->value2, 0,
- (insn->flags & (JIT_INSN_VALUE2_NEXT_USE |
JIT_INSN_VALUE2_LIVE)));
- reg3 = _jit_regs_new_top(gen, insn->dest, 8);
-
- inst = gen->posn.ptr;
- if(!jit_cache_check_for_n(&(gen->posn), 32))
- {
- jit_cache_mark_full(&(gen->posn));
- return;
+JIT_OP_LOAD_ELEMENT_FLOAT32:
+ [=freg, reg, reg] -> {
+ x86_fld_memindex(inst, $1, 0, $2, 2, 0);
}
- reg = _jit_reg_info[reg].cpu_reg;
- reg2 = _jit_reg_info[reg2].cpu_reg;
-
- x86_fld_memindex(inst, reg, 0, reg2, 3, 1);
-
- gen->posn.ptr = inst;
+JIT_OP_LOAD_ELEMENT_FLOAT64:
+ [=freg, reg, reg] -> {
+ x86_fld_memindex(inst, $1, 0, $2, 3, 1);
}
-JIT_OP_LOAD_ELEMENT_NFLOAT: manual
- [] -> {
- unsigned char *inst;
- int reg, reg2, reg3;
-
- reg = _jit_regs_load_value
- (gen, insn->value1, 0,
- (insn->flags & (JIT_INSN_VALUE1_NEXT_USE |
JIT_INSN_VALUE1_LIVE)));
- reg2 = _jit_regs_load_value
- (gen, insn->value2, sizeof(jit_nfloat) !=
sizeof(jit_float64),
- (insn->flags & (JIT_INSN_VALUE2_NEXT_USE |
JIT_INSN_VALUE2_LIVE)));
- reg3 = _jit_regs_new_top(gen, insn->dest, 8);
-
- inst = gen->posn.ptr;
- if(!jit_cache_check_for_n(&(gen->posn), 32))
- {
- jit_cache_mark_full(&(gen->posn));
- return;
- }
-
- reg = _jit_reg_info[reg].cpu_reg;
- reg2 = _jit_reg_info[reg2].cpu_reg;
-
- if(sizeof(jit_nfloat) != sizeof(jit_float64))
- {
- /* lea reg2, [reg2 + reg2 * 2] */
- x86_lea_memindex(inst, reg2, reg2, 0, reg2, 1);
- /* fld [reg2 * 4] */
- x86_fld80_memindex(inst, reg, 0, reg2, 2);
- }
- else
- {
- x86_fld_memindex(inst, reg, 0, reg2, 3, 1);
+JIT_OP_LOAD_ELEMENT_NFLOAT:
+ [=freg, reg, +reg, if("sizeof(jit_nfloat) != sizeof(jit_float64)")] -> {
+ /* lea $2, [$2 + $2 * 2] */
+ x86_lea_memindex(inst, $2, $2, 0, $2, 1);
+ /* fld [$2 * 4] */
+ x86_fld80_memindex(inst, $1, 0, $2, 2);
}
-
- gen->posn.ptr = inst;
+ [=freg, reg, reg, if("sizeof(jit_nfloat) == sizeof(jit_float64)")] -> {
+ x86_fld_memindex(inst, $1, 0, $2, 3, 1);
}
JIT_OP_STORE_ELEMENT_BYTE: ternary
Index: tools/gen-rules-parser.y
===================================================================
RCS file: /sources/dotgnu-pnet/libjit/tools/gen-rules-parser.y,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -b -r1.8 -r1.9
--- tools/gen-rules-parser.y 3 Jun 2006 13:39:53 -0000 1.8
+++ tools/gen-rules-parser.y 16 Jun 2006 17:53:52 -0000 1.9
@@ -822,8 +822,10 @@
char *code,
char *names[MAX_PATTERN],
char *other_names[MAX_PATTERN],
+ int free_dest,
int in_line)
{
+ char first;
int index;
/* Output the clause code */
@@ -833,15 +835,16 @@
}
while(*code != '\0')
{
- if(*code == '$' && code[1] >= '1' && code[1] <= '9')
+ first = free_dest ? '0' : '1';
+ if(*code == '$' && code[1] >= first && code[1] <= (first +
MAX_PATTERN))
{
- index = code[1] - '1';
+ index = code[1] - first;
printf(names[index]);
code += 2;
}
- else if(*code == '%' && code[1] >= '1' && code[1] <= '9')
+ else if(*code == '%' && code[1] >= first && code[1] <= (first +
MAX_PATTERN))
{
- index = code[1] - '1';
+ index = code[1] - first;
printf(other_names[index]);
code += 2;
}
@@ -870,14 +873,15 @@
gensel_output_clause_code(
gensel_clause_t clause,
char *names[MAX_PATTERN],
- char *other_names[MAX_PATTERN])
+ char *other_names[MAX_PATTERN],
+ int free_dest)
{
/* Output the line number information from the original file */
#if 0
printf("#line %ld \"%s\"\n", clause->linenum, clause->filename);
#endif
- gensel_output_code(clause->pattern, clause->code, names, other_names,
0);
+ gensel_output_code(clause->pattern, clause->code, names, other_names,
free_dest, 0);
}
/*
@@ -905,7 +909,7 @@
printf("\t_jit_regs_spill_all(gen);\n");
}
gensel_init_names(MAX_PATTERN, names, other_names);
- gensel_output_clause_code(clauses, names, other_names);
+ gensel_output_clause_code(clauses, names, other_names, 0);
return;
}
@@ -1087,7 +1091,7 @@
gensel_output_code(
clause->pattern,
pattern->values->value,
- names, other_names, 1);
+ names, other_names, free_dest,
1);
printf(")");
seen_option = 1;
break;
@@ -1137,7 +1141,7 @@
if(contains_registers)
{
seen_option = 0;
- printf("\t\t_jit_regs_init(®s, ");
+ printf("\t\t_jit_regs_init(gen, ®s, ");
if(clobber_all)
{
seen_option = 1;
@@ -1275,7 +1279,7 @@
{
if(pattern->values->type ==
GENSEL_VALUE_STRING)
{
-
printf("\t\t_jit_regs_set_%s(®s, _jit_regs_lookup(\"%s\"), -1);\n",
+
printf("\t\t_jit_regs_set_%s(gen, ®s, _jit_regs_lookup(\"%s\"), -1);\n",
args[index],
pattern->values->value);
}
else
@@ -1308,12 +1312,12 @@
{
if(pattern->values->next &&
pattern->values->next->value)
{
-
printf("\t\t_jit_regs_set_%s(®s, _jit_regs_lookup(\"%s\"),
_jit_regs_lookup(\"%s\"));\n",
+
printf("\t\t_jit_regs_set_%s(gen, ®s, _jit_regs_lookup(\"%s\"),
_jit_regs_lookup(\"%s\"));\n",
args[index],
pattern->values->value, pattern->values->next->value);
}
else
{
-
printf("\t\t_jit_regs_set_%s(®s, _jit_regs_lookup(\"%s\"), -1);\n",
+
printf("\t\t_jit_regs_set_%s(gen, ®s, _jit_regs_lookup(\"%s\"), -1);\n",
args[index],
pattern->values->value);
}
}
@@ -1358,7 +1362,7 @@
{
if(values->type ==
GENSEL_VALUE_STRING)
{
-
printf("\t\t_jit_regs_add_scratch(®s, _jit_regs_lookup(\"%s\"));\n",
+
printf("\t\t_jit_regs_add_scratch(gen, ®s, _jit_regs_lookup(\"%s\"));\n",
values->value);
}
else
@@ -1379,7 +1383,7 @@
}
else
{
-
printf("\t\t_jit_regs_add_scratch(®s, -1);\n");
+
printf("\t\t_jit_regs_add_scratch(gen, ®s, -1);\n");
}
++regs;
++index;
@@ -1393,7 +1397,7 @@
{
if(values->value &&
strcmp(values->value, "*") != 0)
{
-
printf("\t\t_jit_regs_set_clobber(®s, _jit_regs_lookup(\"%s\"));\n",
+
printf("\t\t_jit_regs_set_clobber(gen, ®s, _jit_regs_lookup(\"%s\"));\n",
values->value);
}
values = values->next;
@@ -1441,7 +1445,7 @@
gensel_output_code(
clause->pattern,
space->values->value,
- names, other_names, 1);
+ names, other_names, free_dest, 1);
printf(")");
}
else
@@ -1538,7 +1542,7 @@
}
gensel_build_var_index(clause->pattern, names, other_names);
- gensel_output_clause_code(clause, names, other_names);
+ gensel_output_clause_code(clause, names, other_names,
free_dest);
/* Copy "inst" back into the generation context */
if(gensel_new_inst_type)
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [dotgnu-pnet-commits] libjit ChangeLog jit/jit-reg-alloc.h jit/jit-re...,
Aleksey Demakov <=