[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[dotgnu-pnet-commits] libjit ChangeLog tools/gen-rules-parser.y jit/j...
From: |
Aleksey Demakov |
Subject: |
[dotgnu-pnet-commits] libjit ChangeLog tools/gen-rules-parser.y jit/j... |
Date: |
Wed, 17 Jan 2007 07:38:47 +0000 |
CVSROOT: /sources/dotgnu-pnet
Module name: libjit
Changes by: Aleksey Demakov <avd> 07/01/17 07:38:47
Modified files:
. : ChangeLog
tools : gen-rules-parser.y
jit : jit-rules-x86.ins jit-reg-alloc.h
jit-reg-alloc.c
Log message:
complete regalloc support for x87
CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/libjit/ChangeLog?cvsroot=dotgnu-pnet&r1=1.293&r2=1.294
http://cvs.savannah.gnu.org/viewcvs/libjit/tools/gen-rules-parser.y?cvsroot=dotgnu-pnet&r1=1.13&r2=1.14
http://cvs.savannah.gnu.org/viewcvs/libjit/jit/jit-rules-x86.ins?cvsroot=dotgnu-pnet&r1=1.27&r2=1.28
http://cvs.savannah.gnu.org/viewcvs/libjit/jit/jit-reg-alloc.h?cvsroot=dotgnu-pnet&r1=1.20&r2=1.21
http://cvs.savannah.gnu.org/viewcvs/libjit/jit/jit-reg-alloc.c?cvsroot=dotgnu-pnet&r1=1.49&r2=1.50
Patches:
Index: ChangeLog
===================================================================
RCS file: /sources/dotgnu-pnet/libjit/ChangeLog,v
retrieving revision 1.293
retrieving revision 1.294
diff -u -b -r1.293 -r1.294
--- ChangeLog 12 Jan 2007 18:28:53 -0000 1.293
+++ ChangeLog 17 Jan 2007 07:38:47 -0000 1.294
@@ -1,7 +1,17 @@
+2007-01-17 Aleksey Demakov <address@hidden>
+
+ * jit/jit-reg-alloc.h, jit/jit-reg-alloc.c: complete special x87
+ arithmetic support, for other x87 instructions reverse the order of
+ arguments on the stack.
+
+ * jit/jit-rules-x86.ins: take advantage of regalloc's x87 arithmetic
+ support. Also do not clobber the entire x87 stack for atan, sin, and
+ cos rules.
+
2007-01-12 Heiko Weiss <address@hidden>
- * jit/jit-function.c: Fix a typo in jit_function_from_vtable_pointer
which
- breaks the build if libjit is built in interpreter mode.
+ * jit/jit-function.c: Fix a typo in jit_function_from_vtable_pointer
+ which breaks the build if libjit is built in interpreter mode.
2007-01-04 Thomas Cort <address@hidden>
Index: tools/gen-rules-parser.y
===================================================================
RCS file: /sources/dotgnu-pnet/libjit/tools/gen-rules-parser.y,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -b -r1.13 -r1.14
--- tools/gen-rules-parser.y 29 Dec 2006 23:16:15 -0000 1.13
+++ tools/gen-rules-parser.y 17 Jan 2007 07:38:47 -0000 1.14
@@ -1239,7 +1239,7 @@
{
seen_option = 1;
}
- printf("_JIT_REGS_X87_ARITH_REVERSIBLE");
+ printf("_JIT_REGS_X87_ARITH |
_JIT_REGS_REVERSIBLE");
}
if(!seen_option)
{
Index: jit/jit-rules-x86.ins
===================================================================
RCS file: /sources/dotgnu-pnet/libjit/jit/jit-rules-x86.ins,v
retrieving revision 1.27
retrieving revision 1.28
diff -u -b -r1.27 -r1.28
--- jit/jit-rules-x86.ins 2 Jan 2007 17:00:18 -0000 1.27
+++ jit/jit-rules-x86.ins 17 Jan 2007 07:38:47 -0000 1.28
@@ -749,30 +749,146 @@
#endif
}
-JIT_OP_FADD, JIT_OP_DADD, JIT_OP_NFADD: stack
+JIT_OP_FADD, JIT_OP_DADD, JIT_OP_NFADD: stack, x87_arith, commutative
[freg, freg] -> {
- x86_fp_op_reg(inst, X86_FADD, 1, 1);
+ int flags;
+
+ flags = _jit_regs_select(®s);
+
+ if((flags & _JIT_REGS_NO_POP) == 0)
+ {
+ x86_fp_op_reg(inst, X86_FADD,
+ fp_stack_index(gen, $1 + JIT_REG_STACK_START),
1);
+ }
+ else if((flags & _JIT_REGS_FLIP_ARGS) != 0)
+ {
+ x86_fp_op_reg(inst, X86_FADD,
+ fp_stack_index(gen, $1 + JIT_REG_STACK_START),
0);
+ }
+ else
+ {
+ x86_fp_op(inst, X86_FADD,
+ fp_stack_index(gen, $2 + JIT_REG_STACK_START));
+ }
}
-JIT_OP_FSUB, JIT_OP_DSUB, JIT_OP_NFSUB: stack
+JIT_OP_FSUB, JIT_OP_DSUB, JIT_OP_NFSUB: stack, x87_arith_reversible
[freg, freg] -> {
- x86_fp_op_reg(inst, X86_FSUB, 1, 1);
+ int flags;
+
+ flags = _jit_regs_select(®s);
+
+ if((flags & _JIT_REGS_NO_POP) == 0)
+ {
+ if((flags & _JIT_REGS_REVERSE) == 0)
+ {
+ x86_fp_op_reg(inst, X86_FSUB,
+ fp_stack_index(gen, $1 +
JIT_REG_STACK_START), 1);
+ }
+ else
+ {
+ x86_fp_op_reg(inst, X86_FSUBR,
+ fp_stack_index(gen, $2 +
JIT_REG_STACK_START), 1);
+ }
+ }
+ else if((flags & _JIT_REGS_FLIP_ARGS) != 0)
+ {
+ if((flags & _JIT_REGS_REVERSE) == 0)
+ {
+ x86_fp_op_reg(inst, X86_FSUB,
+ fp_stack_index(gen, $1 +
JIT_REG_STACK_START), 0);
+ }
+ else
+ {
+ x86_fp_op(inst, X86_FSUBR,
+ fp_stack_index(gen, $1 +
JIT_REG_STACK_START));
+ }
+ }
+ else
+ {
+ if((flags & _JIT_REGS_REVERSE) == 0)
+ {
+ x86_fp_op(inst, X86_FSUB,
+ fp_stack_index(gen, $2 +
JIT_REG_STACK_START));
+ }
+ else
+ {
+ x86_fp_op_reg(inst, X86_FSUBR,
+ fp_stack_index(gen, $2 +
JIT_REG_STACK_START), 0);
+ }
+ }
}
-JIT_OP_FMUL, JIT_OP_DMUL, JIT_OP_NFMUL: stack
+JIT_OP_FMUL, JIT_OP_DMUL, JIT_OP_NFMUL: stack, x87_arith, commutative
[freg, freg] -> {
- x86_fp_op_reg(inst, X86_FMUL, 1, 1);
+ int flags;
+
+ flags = _jit_regs_select(®s);
+
+ if((flags & _JIT_REGS_NO_POP) == 0)
+ {
+ x86_fp_op_reg(inst, X86_FMUL, fp_stack_index(gen, $1 +
JIT_REG_STACK_START), 1);
+ }
+ else if((flags & _JIT_REGS_FLIP_ARGS) != 0)
+ {
+ x86_fp_op_reg(inst, X86_FMUL, fp_stack_index(gen, $1 +
JIT_REG_STACK_START), 0);
+ }
+ else
+ {
+ x86_fp_op(inst, X86_FMUL, fp_stack_index(gen, $2 +
JIT_REG_STACK_START));
+ }
}
-JIT_OP_FDIV, JIT_OP_DDIV, JIT_OP_NFDIV: stack
+JIT_OP_FDIV, JIT_OP_DDIV, JIT_OP_NFDIV: stack, x87_arith_reversible
[freg, freg] -> {
- x86_fp_op_reg(inst, X86_FDIV, 1, 1);
+ int flags;
+
+ flags = _jit_regs_select(®s);
+
+ if((flags & _JIT_REGS_NO_POP) == 0)
+ {
+ if((flags & _JIT_REGS_REVERSE) == 0)
+ {
+ x86_fp_op_reg(inst, X86_FDIV,
+ fp_stack_index(gen, $1 +
JIT_REG_STACK_START), 1);
+ }
+ else
+ {
+ x86_fp_op_reg(inst, X86_FDIVR,
+ fp_stack_index(gen, $2 +
JIT_REG_STACK_START), 1);
+ }
+ }
+ else if((flags & _JIT_REGS_FLIP_ARGS) != 0)
+ {
+ if((flags & _JIT_REGS_REVERSE) == 0)
+ {
+ x86_fp_op_reg(inst, X86_FDIV,
+ fp_stack_index(gen, $1 +
JIT_REG_STACK_START), 0);
+ }
+ else
+ {
+ x86_fp_op(inst, X86_FDIVR,
+ fp_stack_index(gen, $1 +
JIT_REG_STACK_START));
+ }
+ }
+ else
+ {
+ if((flags & _JIT_REGS_REVERSE) == 0)
+ {
+ x86_fp_op(inst, X86_FDIV,
+ fp_stack_index(gen, $2 +
JIT_REG_STACK_START));
+ }
+ else
+ {
+ x86_fp_op_reg(inst, X86_FDIVR,
+ fp_stack_index(gen, $2 +
JIT_REG_STACK_START), 0);
+ }
+ }
}
JIT_OP_FREM, JIT_OP_DREM, JIT_OP_NFREM: stack
[freg, freg, scratch reg("eax")] -> {
unsigned char *label;
- x86_fxch(inst, 1);
label = inst;
x86_fprem(inst);
x86_fnstsw(inst);
@@ -1232,7 +1348,7 @@
*/
JIT_OP_FATAN, JIT_OP_DATAN, JIT_OP_NFATAN: stack
- [freg, clobber(freg)] -> {
+ [freg, scratch freg] -> {
x86_fld1(inst);
x86_fpatan(inst);
x86_fldz(inst);
@@ -1240,14 +1356,14 @@
}
JIT_OP_FCOS, JIT_OP_DCOS, JIT_OP_NFCOS: stack
- [freg, clobber(freg)] -> {
+ [freg, scratch freg] -> {
x86_fcos(inst);
x86_fldz(inst);
x86_fp_op_reg(inst, X86_FADD, 1, 1);
}
JIT_OP_FSIN, JIT_OP_DSIN, JIT_OP_NFSIN: stack
- [freg, clobber(freg)] -> {
+ [freg, scratch freg] -> {
x86_fsin(inst);
x86_fldz(inst);
x86_fp_op_reg(inst, X86_FADD, 1, 1);
@@ -2073,7 +2189,7 @@
x86_mov_membase_reg(inst, $1, $3 + 4, %2, 4);
}
-JIT_OP_STORE_RELATIVE_FLOAT32: ternary
+JIT_OP_STORE_RELATIVE_FLOAT32: ternary, stack
[reg, imm, imm] -> {
x86_mov_membase_imm(inst, $1, $3, ((int *)($2))[0], 4);
}
@@ -2081,7 +2197,7 @@
x86_fst_membase(inst, $1, $3, 0, 1);
}
-JIT_OP_STORE_RELATIVE_FLOAT64: ternary
+JIT_OP_STORE_RELATIVE_FLOAT64: ternary, stack
[reg, imm, imm] -> {
x86_mov_membase_imm(inst, $1, $3, ((int *)($2))[0], 4);
x86_mov_membase_imm(inst, $1, $3 + 4, ((int *)($2))[1], 4);
@@ -2090,7 +2206,7 @@
x86_fst_membase(inst, $1, $3, 1, 1);
}
-JIT_OP_STORE_RELATIVE_NFLOAT: ternary
+JIT_OP_STORE_RELATIVE_NFLOAT: ternary, stack
[reg, imm, imm] -> {
x86_mov_membase_imm(inst, $1, $3, ((int *)($2))[0], 4);
x86_mov_membase_imm(inst, $1, $3 + 4, ((int *)($2))[1], 4);
@@ -2235,17 +2351,17 @@
x86_mov_memindex_reg(inst, $1, 4, $2, 3, %3, 4);
}
-JIT_OP_STORE_ELEMENT_FLOAT32: ternary
+JIT_OP_STORE_ELEMENT_FLOAT32: ternary, stack
[reg, reg, freg] -> {
x86_fst_memindex(inst, $1, 0, $2, 2, 0, 1);
}
-JIT_OP_STORE_ELEMENT_FLOAT64: ternary
+JIT_OP_STORE_ELEMENT_FLOAT64: ternary, stack
[reg, reg, freg] -> {
x86_fst_memindex(inst, $1, 0, $2, 3, 1, 1);
}
-JIT_OP_STORE_ELEMENT_NFLOAT: ternary
+JIT_OP_STORE_ELEMENT_NFLOAT: ternary, stack
[reg, +reg, freg, if("sizeof(jit_nfloat) != sizeof(jit_float64)")] -> {
/* lea reg2, [reg2 + reg2 * 2] */
x86_lea_memindex(inst, $2, $2, 0, $2, 1);
Index: jit/jit-reg-alloc.h
===================================================================
RCS file: /sources/dotgnu-pnet/libjit/jit/jit-reg-alloc.h,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -b -r1.20 -r1.21
--- jit/jit-reg-alloc.h 29 Dec 2006 23:16:15 -0000 1.20
+++ jit/jit-reg-alloc.h 17 Jan 2007 07:38:47 -0000 1.21
@@ -61,8 +61,8 @@
* Flags returned by _jit_regs_select_insn().
*/
#define _JIT_REGS_NO_POP 0x0001
-#define _JIT_REGS_REVERSE_DEST 0x0002
-#define _JIT_REGS_REVERSE_ARGS 0x0004
+#define _JIT_REGS_FLIP_ARGS 0x0002
+#define _JIT_REGS_REVERSE 0x0004
/*
* Contains register assignment data for single operand.
@@ -106,8 +106,6 @@
_jit_scratch_t scratch[_JIT_REGS_SCRATCH_MAX];
int num_scratch;
- unsigned clobber_all : 1;
-
unsigned ternary : 1;
unsigned branch : 1;
unsigned copy : 1;
@@ -118,11 +116,9 @@
unsigned on_stack : 1;
unsigned x87_arith : 1;
unsigned reversible : 1;
- unsigned clobber_stack : 1;
unsigned no_pop : 1;
- unsigned reverse_dest : 1;
- unsigned reverse_args : 1;
+ unsigned flip_args : 1;
#endif
/* The input value index that is going to be overwritten
Index: jit/jit-reg-alloc.c
===================================================================
RCS file: /sources/dotgnu-pnet/libjit/jit/jit-reg-alloc.c,v
retrieving revision 1.49
retrieving revision 1.50
diff -u -b -r1.49 -r1.50
--- jit/jit-reg-alloc.c 2 Jan 2007 17:00:18 -0000 1.49
+++ jit/jit-reg-alloc.c 17 Jan 2007 07:38:47 -0000 1.50
@@ -208,6 +208,14 @@
return 0;
}
+static void
+swap_values(_jit_regdesc_t *desc1, _jit_regdesc_t *desc2)
+{
+ _jit_regdesc_t tdesc;
+ tdesc = *desc1;
+ *desc1 = *desc2;
+ *desc2 = tdesc;
+}
/*
* Get value usage and liveness information. The accurate liveness data is
@@ -869,6 +877,12 @@
}
}
}
+
+ if(gen->contents[reg].is_long_start)
+ {
+ return cost * 2;
+ }
+
if(other_reg >= 0)
{
for(index = 0; index < gen->contents[other_reg].num_values;
index++)
@@ -911,6 +925,7 @@
}
}
}
+
return cost;
}
@@ -977,6 +992,10 @@
int suitable_cost;
int suitable_age;
+#ifdef JIT_REG_DEBUG
+ printf("choose_scratch_register(%d)\n", index);
+#endif
+
regclass = regs->scratch[index].regclass;
suitable_reg = -1;
@@ -990,23 +1009,20 @@
continue;
}
-#if ALLOW_CLOBBER_GLOBAL
if(jit_reg_is_used(gen->permanent, reg))
{
+#if ALLOW_CLOBBER_GLOBAL
use_cost = COST_CLOBBER_GLOBAL;
+#else
+ continue;
+#endif
}
else
{
use_cost = 0;
}
-#else
- if(jit_reg_is_used(gen->permanent, reg))
- {
- continue;
- }
- use_cost = 0;
-#endif
+#if 0
if(regs->ternary && regs->descs[0].value
&& thrashes_value(gen, 0, reg, -1, ®s->descs[0]))
{
@@ -1022,13 +1038,22 @@
{
use_cost += COST_THRASH;
}
+#endif
+ if(!jit_reg_is_used(regs->clobber, reg))
+ {
use_cost += compute_spill_cost(gen, regs, reg, -1);
+ }
+
+#ifdef JIT_REG_DEBUG
+ printf("reg = %d, use_cost = %d\n", reg, use_cost);
+#endif
if(use_cost < suitable_cost
|| (use_cost == suitable_cost
&& gen->contents[reg].num_values > 0
- && gen->contents[reg].age < suitable_age))
+ && (IS_STACK_REG(reg)
+ || gen->contents[reg].age < suitable_age)))
{
suitable_reg = reg;
suitable_cost = use_cost;
@@ -1056,6 +1081,10 @@
int suitable_cost;
int suitable_age;
+#ifdef JIT_REG_DEBUG
+ printf("choose_output_register()\n");
+#endif
+
regclass = regs->descs[0].regclass;
need_pair = _jit_regs_needs_long_pair(regs->descs[0].value->type);
@@ -1177,7 +1206,7 @@
use_cost = 0;
}
#ifdef JIT_REG_STACK
- else if(regs->x87_arith)
+ else if(regs->reversible && regs->no_pop)
{
use_cost = 0;
}
@@ -1197,7 +1226,15 @@
}
}
+ if(!jit_reg_is_used(regs->clobber, reg)
+ && !(other_reg >= 0 && jit_reg_is_used(regs->clobber,
other_reg)))
+ {
use_cost += compute_spill_cost(gen, regs, reg, other_reg);
+ }
+
+#ifdef JIT_REG_DEBUG
+ printf("reg = %d, other_reg = %d, use_cost = %d\n", reg,
other_reg, use_cost);
+#endif
if(use_cost < suitable_cost
|| (use_cost == suitable_cost
@@ -1223,25 +1260,20 @@
/*
* Select the best argument order for binary ops. The posibility to select
* the order exists only for commutative ops and for some x87 floating point
- * instructions. Those x87 instructions have variants with reversed argument
- * order or reversed destination register. Also they have variants that
- * either do or do not pop the stack top.
+ * instructions. Those x87 instructions have variants with reversed
+ * destination register.
*/
static void
choose_input_order(jit_gencode_t gen, _jit_regs_t *regs)
{
- _jit_regdesc_t temp_desc;
-
if(regs->descs[2].value
&& regs->descs[2].value->in_register
&& regs->descs[2].value->reg == regs->descs[0].reg
&& regs->descs[2].value != regs->descs[1].value)
{
#ifdef JIT_REG_STACK
- if(regs->x87_arith)
+ if(regs->reversible && regs->no_pop)
{
- regs->no_pop = 1;
- regs->reverse_dest = 1;
regs->dest_input_index = 2;
}
else
@@ -1249,9 +1281,7 @@
{
if(regs->commutative)
{
- temp_desc = regs->descs[1];
- regs->descs[1] = regs->descs[2];
- regs->descs[2] = temp_desc;
+ swap_values(®s->descs[1], ®s->descs[2]);
}
regs->dest_input_index = 1;
}
@@ -1264,41 +1294,6 @@
{
regs->dest_input_index = 0;
}
-
-#ifdef JIT_REG_STACK
- /* Choose between pop and no-pop instructions. */
- if(!regs->no_pop && regs->x87_arith
- && !regs->clobber_all && !regs->clobber_stack
- && regs->descs[1].value && regs->descs[2].value)
- {
- int keep1, keep2;
-
- /* Determine if we might want to keep either of input values
- in registers after the instruction completion. */
- if(regs->descs[1].value->in_register)
- {
- keep1 = is_register_alive(gen, regs,
regs->descs[1].value->reg);
- }
- else
- {
- keep1 = (regs->descs[1].used
- && (regs->descs[1].value !=
regs->descs[0].value)
- && !regs->descs[1].clobber);
- }
- if(regs->descs[2].value->in_register)
- {
- keep2 = is_register_alive(gen, regs,
regs->descs[2].value->reg);
- }
- else
- {
- keep2 = (regs->descs[2].used
- && (regs->descs[2].value !=
regs->descs[0].value)
- && !regs->descs[2].clobber);
- }
-
- regs->no_pop = (keep1 || keep2);
- }
-#endif
}
static int
@@ -1315,6 +1310,10 @@
int suitable_age;
int clobber;
+#ifdef JIT_REG_DEBUG
+ printf("choose_input_register(%d)\n", index);
+#endif
+
desc = ®s->descs[index];
if(!desc->value)
{
@@ -1410,17 +1409,17 @@
continue;
#endif
}
- if(jit_reg_is_used(regs->clobber, reg)
- || (other_reg >= 0 && jit_reg_is_used(regs->clobber,
other_reg)))
- {
- /* noop */
- }
- else
+ if(!jit_reg_is_used(regs->clobber, reg)
+ && !(other_reg >= 0 &&
jit_reg_is_used(regs->clobber, other_reg)))
{
use_cost += compute_spill_cost(gen, regs, reg,
other_reg);
}
}
+#ifdef JIT_REG_DEBUG
+ printf("reg = %d, other_reg = %d, use_cost = %d\n", reg,
other_reg, use_cost);
+#endif
+
if(use_cost < suitable_cost
|| (use_cost == suitable_cost
&& gen->contents[reg].num_values > 0
@@ -1465,110 +1464,215 @@
}
#ifdef JIT_REG_STACK
+
+/*
+ * For x87 instructions choose between pop and no-pop variants.
+ */
static void
-adjust_assignment(jit_gencode_t gen, _jit_regs_t *regs, int index)
+select_nopop_or_pop(jit_gencode_t gen, _jit_regs_t *regs)
{
- _jit_regdesc_t *desc;
+ int keep1, keep2;
- desc = ®s->descs[index];
- if(!desc->value || !IS_STACK_REG(desc->reg))
+ if(!regs->x87_arith || !regs->descs[1].value || !regs->descs[2].value)
{
return;
}
- if(regs->wanted_stack_count == 1)
+ /* Equal values should be assigned to one register and this is
+ going to work only with no-pop instructions. */
+ if(are_values_equal(®s->descs[1], ®s->descs[2]))
{
- /* either a unary op or a binary op with duplicate value */
- desc->reg = gen->reg_stack_top - regs->loaded_stack_count;
+ regs->no_pop = 1;
+ return;
}
- else if(regs->wanted_stack_count == 2)
- {
- /* a binary op */
- /* find the input value the output goes to */
- if(index == 0)
+ /* Determine if we might want to keep input values in registers
+ after the instruction completion. */
+ if(regs->descs[1].value->in_register)
{
- index = regs->dest_input_index;
+ keep1 = is_register_alive(gen, regs, regs->descs[1].value->reg);
}
-
- if(desc->value->in_register && !desc->copy && regs->x87_arith)
+ else
+ {
+ keep1 = (regs->descs[1].used
+ && (regs->descs[1].value != regs->descs[0].value)
+ && !regs->descs[1].clobber);
+ }
+ if(regs->descs[2].value->in_register)
{
- desc->reg = desc->value->reg;
+ keep2 = is_register_alive(gen, regs, regs->descs[2].value->reg);
}
else
{
- desc->reg = gen->reg_stack_top -
regs->loaded_stack_count + index - 1;
- }
+ keep2 = (regs->descs[2].used
+ && (regs->descs[2].value != regs->descs[0].value)
+ && !regs->descs[2].clobber);
}
+
+ regs->no_pop = (keep1 || keep2);
}
-#endif
-#ifdef JIT_REG_STACK
static void
select_stack_order(jit_gencode_t gen, _jit_regs_t *regs)
{
_jit_regdesc_t *desc1;
_jit_regdesc_t *desc2;
- _jit_regdesc_t temp_desc;
int top_index;
- /* Choose instruction that results into fewer exchanges. */
- if(regs->wanted_stack_count > 1 && regs->no_pop
- && (regs->commutative || regs->reversible))
+#ifdef JIT_REG_DEBUG
+ printf("select_stack_order()\n");
+#endif
+
+ if(!regs->x87_arith || regs->wanted_stack_count != 2)
{
+ return;
+ }
+
desc1 = ®s->descs[1];
desc2 = ®s->descs[2];
- if(desc1->value->in_register && !desc1->copy
- && desc2->value->in_register && !desc2->copy)
+ /* Choose instruction that results into fewer exchanges. If either
+ of two arguments may be on the stack top choose the second to be
+ on top. */
+ /* TODO: See if the next instruction wants the output or remaining
+ input to be on the stack top. */
+ if(desc2->copy || desc2->load)
{
- /* Is any of the input values on the stack top? */
- if(desc1->value->reg == (gen->reg_stack_top - 1))
+ /* the second argument is going to be on the top */
+ top_index = 2;
+ }
+ else if(desc1->copy || desc1->load)
{
+ /* the first argument is going to be on the top */
top_index = 1;
}
else if(desc2->value->reg == (gen->reg_stack_top - 1))
{
+ /* the second argument is already on the top */
top_index = 2;
}
+ else if(desc1->value->reg == (gen->reg_stack_top - 1))
+ {
+ /* the first argument is already on the top */
+ top_index = 1;
+ }
else
{
- /* TODO: See if the next instruction wants
output
- or remaining input to be on the stack top. */
top_index = 2;
}
+
+ if(regs->no_pop)
+ {
+ regs->flip_args = (top_index == 2);
}
- else if(desc1->value->in_register && !desc1->copy)
+ else if(regs->reversible)
{
- top_index = 2;
+ if(top_index == 2)
+ {
+ regs->flip_args = 1;
+ regs->dest_input_index = 1;
}
- else if(desc2->value->in_register && !desc2->copy)
+ else
{
- top_index = 1;
+ regs->flip_args = 0;
+ regs->dest_input_index = 2;
+ }
+ }
+ else /*if(regs->commutative)*/
+ {
+ regs->flip_args = 1;
+ regs->dest_input_index = 1;
+
+ if(top_index != 2)
+ {
+ swap_values(®s->descs[1], ®s->descs[2]);
+ }
+ }
+
+#ifdef JIT_REG_DEBUG
+ printf("top_index = %d, flip_args = %d, dest_input_index = %d\n",
+ top_index, regs->flip_args, regs->dest_input_index);
+#endif
+}
+
+static void
+adjust_assignment(jit_gencode_t gen, _jit_regs_t *regs, int index)
+{
+ _jit_regdesc_t *desc, *desc2;
+
+#ifdef JIT_REG_DEBUG
+ printf("adjust_assignment(%d)\n", index);
+#endif
+
+ desc = ®s->descs[index];
+ if(!desc->value || !IS_STACK_REG(desc->reg))
+ {
+ return;
+ }
+
+ if(regs->wanted_stack_count == 1)
+ {
+ /* either a unary op or a binary op with duplicate value */
+ desc->reg = gen->reg_stack_top - regs->loaded_stack_count;
+ }
+ else if(regs->wanted_stack_count == 2)
+ {
+ /* a binary op */
+
+ /* find the input value the output goes to */
+ if(index == 0)
+ {
+ if(regs->x87_arith)
+ {
+ index = regs->dest_input_index;
}
else
{
- /* TODO: see if the next instruction wants output or
remaining
- input to be on the stack top. */
- top_index = 2;
+ index = 2;
+ }
+ desc2 = ®s->descs[index];
+ }
+ else
+ {
+ desc2 = desc;
}
- if(top_index == 1)
+ if(regs->flip_args)
{
- if(regs->reversible)
+ if(regs->x87_arith && index == 1
+ && desc2->value->in_register && !desc2->copy)
{
- regs->reverse_args = 1;
+ desc->reg = desc2->value->reg;
}
- else /*if(regs->commutative)*/
+ else
{
- temp_desc = *desc1;
- *desc1 = *desc2;
- *desc2 = temp_desc;
+ desc->reg = (gen->reg_stack_top
+ - regs->loaded_stack_count
+ + index - 1);
+ }
+ }
+ else
+ {
+ if(regs->x87_arith && index == 2
+ && desc2->value->in_register && !desc2->copy)
+ {
+ desc->reg = desc2->value->reg;
+ }
+ else
+ {
+ desc->reg = (gen->reg_stack_top
+ - regs->loaded_stack_count
+ + regs->wanted_stack_count
+ - index);
}
- regs->reverse_dest ^= 1;
}
}
+
+#ifdef JIT_REG_DEBUG
+ printf("reg = %d\n", desc->reg);
+#endif
}
+
#endif
/*
@@ -2281,17 +2385,14 @@
}
}
+#ifdef JIT_REG_STACK
static void
-commit_input_value(jit_gencode_t gen, _jit_regs_t *regs, int index, int
go_down_stack)
+pop_input_value(jit_gencode_t gen, _jit_regs_t *regs, int index)
{
_jit_regdesc_t *desc;
- int reg, other_reg;
-#ifdef JIT_REG_STACK
- int is_down_stack = 0;
-#endif
#ifdef JIT_REG_DEBUG
- printf("commit_input_value(%d, %d)\n", index, go_down_stack);
+ printf("pop_input_value(%d)\n", index);
#endif
desc = ®s->descs[index];
@@ -2300,20 +2401,50 @@
return;
}
- if(desc->copy)
- {
-#ifdef JIT_REG_STACK
if(IS_STACK_REG(desc->reg))
{
- if(!go_down_stack)
+ if(desc->copy)
{
- if(1/*!regs->copy*/)
+ gen->contents[desc->reg].used_for_temp = 0;
+ }
+ else
{
+ unbind_value(gen, desc->value, desc->reg, 0);
+ }
--(gen->reg_stack_top);
}
- gen->contents[desc->reg].used_for_temp = 0;
+}
+#endif
+
+static void
+commit_input_value(jit_gencode_t gen, _jit_regs_t *regs, int index, int killed)
+{
+ _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->duplicate)
+ {
+ return;
+ }
+
+#ifdef JIT_REG_STACK
+ if(!IS_STACK_REG(desc->reg))
+ {
+ killed = 0;
}
- is_down_stack = 1;
+#endif
+
+ if(desc->copy)
+ {
+#ifdef JIT_REG_STACK
+ if(killed)
+ {
+ killed = 0;
}
else
#endif
@@ -2327,7 +2458,7 @@
}
#ifdef JIT_REG_STACK
- if(desc->kill && desc->value->in_register && is_down_stack ==
go_down_stack)
+ if(!killed && desc->kill && desc->value->in_register)
#else
if(desc->kill && desc->value->in_register)
#endif
@@ -2341,23 +2472,8 @@
{
other_reg = -1;
}
-#ifdef JIT_REG_STACK
- if(is_down_stack)
- {
free_value(gen, desc->value, reg, other_reg, 0);
}
- else
- {
- unbind_value(gen, desc->value, reg, other_reg);
- if(IS_STACK_REG(reg) /*&& !regs->copy*/)
- {
- --(gen->reg_stack_top);
- }
- }
-#else
- unbind_value(gen, desc->value, reg, other_reg);
-#endif
- }
#ifdef JIT_REG_DEBUG
printf("value = ");
@@ -2372,7 +2488,7 @@
}
static void
-commit_output_value(jit_gencode_t gen, _jit_regs_t *regs)
+commit_output_value(jit_gencode_t gen, _jit_regs_t *regs, int push_stack_top)
{
_jit_regdesc_t *desc;
@@ -2386,12 +2502,10 @@
return;
}
-#ifdef JIT_REG_STACK
- if(IS_STACK_REG(desc->reg) /*&& !regs->copy*/)
+ if(IS_STACK_REG(desc->reg) && push_stack_top)
{
++(gen->reg_stack_top);
}
-#endif
bind_value(gen, desc->value, desc->reg, desc->other_reg, 0);
if(!desc->used)
@@ -3138,13 +3252,6 @@
{
int index;
-#ifdef JIT_REG_STACK
- if((regclass->flags & JIT_REG_IN_STACK) != 0)
- {
- regs->clobber_stack = 1;
- }
-#endif
-
for(index = 0; index < regclass->num_regs; index++)
{
if(jit_reg_is_used(gen->permanent, index))
@@ -3160,8 +3267,6 @@
{
int index;
- regs->clobber_all = 1;
-
for(index = 0; index < JIT_NUM_REGS; index++)
{
if((_jit_reg_info[index].flags & JIT_REG_FIXED) != 0)
@@ -3189,28 +3294,23 @@
the output always goes to the same register as the first input
value unless this is a three-address instruction. */
if(!regs->ternary && !regs->free_dest
- && regs->descs[0].value
- && regs->descs[1].value)
- {
- if(regs->descs[0].reg >= 0)
- {
- if(regs->descs[1].reg < 0)
- {
- set_regdesc_register(gen, regs, 1,
- regs->descs[0].reg,
- regs->descs[0].other_reg);
- }
- }
- else if(regs->descs[1].reg >= 0)
+ && regs->descs[0].value && regs->descs[0].reg < 0
+ && regs->descs[1].value && regs->descs[1].reg >= 0)
{
set_regdesc_register(gen, regs, 0,
regs->descs[1].reg,
regs->descs[1].other_reg);
}
- }
+
+#if JIT_REG_STACK
+ /* Choose between x87 pop and no-pop instructions. */
+ select_nopop_or_pop(gen, regs);
+#endif
/* Assign output and input registers. */
- if(regs->descs[0].value && regs->descs[0].reg < 0)
+ if(regs->descs[0].value)
+ {
+ if(regs->descs[0].reg < 0)
{
if(regs->ternary)
{
@@ -3218,8 +3318,6 @@
{
return 0;
}
- check_duplicate_value(regs, ®s->descs[0],
®s->descs[1]);
- check_duplicate_value(regs, ®s->descs[0],
®s->descs[2]);
}
else
{
@@ -3227,19 +3325,24 @@
{
return 0;
}
- if(!regs->free_dest)
+ }
+ }
+ if(regs->ternary)
+ {
+ check_duplicate_value(regs, ®s->descs[0],
®s->descs[1]);
+ check_duplicate_value(regs, ®s->descs[0],
®s->descs[2]);
+ }
+ else if(!regs->free_dest)
{
choose_input_order(gen, regs);
if(regs->dest_input_index)
{
- set_regdesc_register(gen, regs,
-
regs->dest_input_index,
+ set_regdesc_register(gen, regs,
regs->dest_input_index,
regs->descs[0].reg,
regs->descs[0].other_reg);
}
}
}
- }
if(regs->descs[1].value && regs->descs[1].reg < 0)
{
if(!choose_input_register(gen, regs, 1))
@@ -3377,38 +3480,54 @@
if(regs->wanted_stack_count > 0)
{
/* Adjust assignment of stack registers. */
- adjust_assignment(gen, regs, 0);
- adjust_assignment(gen, regs, 1);
- adjust_assignment(gen, regs, 2);
-
select_stack_order(gen, regs);
+ adjust_assignment(gen, regs, 2);
+ adjust_assignment(gen, regs, 1);
+ adjust_assignment(gen, regs, 0);
- /* Shuffle the values that are already on the register stack. */
- if(regs->loaded_stack_count > 0 && !regs->x87_arith)
+ if(regs->ternary)
+ {
+ /* Ternary ops with only one stack register are
supported. */
+ if(regs->loaded_stack_count > 0)
{
+ move_input_value(gen, regs, 0);
move_input_value(gen, regs, 1);
move_input_value(gen, regs, 2);
}
-
- /* Load and shuffle the remaining values. */
- if(regs->reverse_args)
+ else
{
+ load_input_value(gen, regs, 0);
+ load_input_value(gen, regs, 1);
load_input_value(gen, regs, 2);
+ }
+ }
+ else if(regs->flip_args)
+ {
+ /* Shuffle the values that are already on the register
stack. */
+ if(regs->loaded_stack_count > 0)
+ {
+ move_input_value(gen, regs, 1);
move_input_value(gen, regs, 2);
+ }
+
+ /* Load and shuffle the remaining values. */
load_input_value(gen, regs, 1);
move_input_value(gen, regs, 1);
+ load_input_value(gen, regs, 2);
}
else
{
- if(regs->ternary)
+ /* Shuffle the values that are already on the register
stack. */
+ if(regs->loaded_stack_count > 0)
{
- load_input_value(gen, regs, 0);
- move_input_value(gen, regs, 0);
- }
- load_input_value(gen, regs, 1);
+ move_input_value(gen, regs, 2);
move_input_value(gen, regs, 1);
+ }
+
+ /* Load and shuffle the remaining values. */
load_input_value(gen, regs, 2);
move_input_value(gen, regs, 2);
+ load_input_value(gen, regs, 1);
}
}
else
@@ -3440,15 +3559,14 @@
{
flags |= _JIT_REGS_NO_POP;
}
- if(regs->reverse_dest)
+ if(regs->flip_args)
{
- flags |= _JIT_REGS_REVERSE_DEST;
+ flags |= _JIT_REGS_FLIP_ARGS;
}
- if(regs->reverse_args)
+ if(regs->dest_input_index == 2)
{
- flags |= _JIT_REGS_REVERSE_ARGS;
+ flags |= _JIT_REGS_REVERSE;
}
-
return flags;
}
#endif
@@ -3462,73 +3580,103 @@
dump_regs(gen, "enter _jit_regs_commit");
#endif
+ if(regs->ternary)
+ {
+#ifdef JIT_REG_STACK
+ if(regs->wanted_stack_count > 0)
+ {
+ pop_input_value(gen, regs, 0);
+ pop_input_value(gen, regs, 1);
+ pop_input_value(gen, regs, 2);
+ }
+#endif
+ commit_input_value(gen, regs, 0, 1);
+ commit_input_value(gen, regs, 1, 1);
+ commit_input_value(gen, regs, 2, 1);
+ }
+ else if(!regs->descs[0].value)
+ {
#ifdef JIT_REG_STACK
if(regs->wanted_stack_count > 0)
{
+ pop_input_value(gen, regs, 1);
+ pop_input_value(gen, regs, 2);
+ }
+#endif
+ commit_input_value(gen, regs, 1, 1);
+ commit_input_value(gen, regs, 2, 1);
+ }
+#ifdef JIT_REG_STACK
+ else if(regs->wanted_stack_count > 0)
+ {
+ int pop1, pop2;
+ struct _jit_value temp;
int reg1, reg2;
- /* The stack registers has to be freed from the top down. It is
- assumed that only binary instructions may have more than one
- stack register. The unary instruction may not do that for
- obvious reasons. The practical observation is that no ternary
- instruction in libjit does that as well. */
- if(regs->reverse_args)
+ pop1 = pop2 = 0;
+ if(!regs->no_pop)
{
- commit_input_value(gen, regs, 1, 0);
- commit_input_value(gen, regs, 2, 0);
+ if(regs->x87_arith)
+ {
+ if(regs->flip_args)
+ {
+ pop_input_value(gen, regs, 2);
+ pop2 = 1;
}
else
{
- commit_input_value(gen, regs, 2, 0);
- commit_input_value(gen, regs, 1, 0);
+ pop_input_value(gen, regs, 1);
+ pop1 = 1;
}
- if(regs->ternary)
- {
- commit_input_value(gen, regs, 0, 0);
}
else
{
- commit_output_value(gen, regs);
+ pop_input_value(gen, regs, 1);
+ pop_input_value(gen, regs, 2);
+ pop1 = pop2 = 1;
+ }
+ }
+
+ if(IS_STACK_REG(regs->descs[0].reg))
+ {
+ temp = *regs->descs[0].value;
+ if(!regs->x87_arith && !regs->copy)
+ {
+ ++(gen->reg_stack_top);
+ }
+ bind_value(gen, &temp, regs->descs[0].reg, -1, 0);
}
- /* If the allocator makes a copy of a value that was already on
- the stack we might need to free the original register as
well.
- In general, the allocator makes a copy if the value is going
- to be destroyed by the instruction while it is still used
- (according to the liveness analysis). But the original value
- needs to be freed only if it is no longer used. So this extra
- code seems useless. But there were cases when the allocator
- miscalculated the cost of spilling and made a copy when it
- was not needed. So this code serves as a precaution against
- such problematic cases. */
reg1 = ((regs->descs[1].value &&
regs->descs[1].value->in_register)
? regs->descs[1].value->reg : -1);
reg2 = ((regs->descs[2].value &&
regs->descs[2].value->in_register)
? regs->descs[2].value->reg : -1);
if(reg1 > reg2)
{
- commit_input_value(gen, regs, 1, 1);
- commit_input_value(gen, regs, 2, 1);
+ commit_input_value(gen, regs, 1, pop1);
+ commit_input_value(gen, regs, 2, pop2);
}
else
{
- commit_input_value(gen, regs, 2, 1);
- commit_input_value(gen, regs, 1, 1);
+ commit_input_value(gen, regs, 2, pop2);
+ commit_input_value(gen, regs, 1, pop1);
+ }
+
+ if(IS_STACK_REG(regs->descs[0].reg))
+ {
+ reg1 = temp.reg;
+ free_value(gen, &temp, reg1, -1, 1);
+ regs->descs[0].reg = reg1;
+ regs->descs[0].other_reg = -1;
}
+ commit_output_value(gen, regs, 0);
}
else
#endif
{
commit_input_value(gen, regs, 2, 0);
commit_input_value(gen, regs, 1, 0);
- if(regs->ternary)
- {
- commit_input_value(gen, regs, 0, 0);
- }
- else
- {
- commit_output_value(gen, regs);
- }
+ commit_output_value(gen, regs, 1);
}
/* Load clobbered global registers. */
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [dotgnu-pnet-commits] libjit ChangeLog tools/gen-rules-parser.y jit/j...,
Aleksey Demakov <=