Commit 4908bfb8 authored by Christoph Mallon's avatar Christoph Mallon
Browse files

ia32: Use fdup instead of fpush.

This properly models the data dependencies and avoids keep edges.
parent 9a8dd92f
...@@ -3065,11 +3065,6 @@ static void bemit_fpop(const ir_node *node) ...@@ -3065,11 +3065,6 @@ static void bemit_fpop(const ir_node *node)
bemit_fop_reg(node, 0xDD, 0xD8); bemit_fop_reg(node, 0xDD, 0xD8);
} }
static void bemit_fpush(const ir_node *node)
{
bemit_fop_reg(node, 0xD9, 0xC0);
}
static void bemit_fdup(const ir_node *node) static void bemit_fdup(const ir_node *node)
{ {
bemit_fop_reg(node, 0xD9, 0xC0); bemit_fop_reg(node, 0xD9, 0xC0);
...@@ -3250,7 +3245,6 @@ static void ia32_register_binary_emitters(void) ...@@ -3250,7 +3245,6 @@ static void ia32_register_binary_emitters(void)
be_set_emitter(op_ia32_fldz, bemit_fldz); be_set_emitter(op_ia32_fldz, bemit_fldz);
be_set_emitter(op_ia32_fmul, bemit_fmul); be_set_emitter(op_ia32_fmul, bemit_fmul);
be_set_emitter(op_ia32_fpop, bemit_fpop); be_set_emitter(op_ia32_fpop, bemit_fpop);
be_set_emitter(op_ia32_fpush, bemit_fpush);
be_set_emitter(op_ia32_fdup, bemit_fdup); be_set_emitter(op_ia32_fdup, bemit_fdup);
be_set_emitter(op_ia32_fst, bemit_fst); be_set_emitter(op_ia32_fst, bemit_fst);
be_set_emitter(op_ia32_fsub, bemit_fsub); be_set_emitter(op_ia32_fsub, bemit_fsub);
......
...@@ -97,7 +97,6 @@ static bool has_ia32_x87_attr(ir_node const *const node) ...@@ -97,7 +97,6 @@ static bool has_ia32_x87_attr(ir_node const *const node)
case iro_ia32_fisttp: case iro_ia32_fisttp:
case iro_ia32_fmul: case iro_ia32_fmul:
case iro_ia32_fpop: case iro_ia32_fpop:
case iro_ia32_fpush:
case iro_ia32_fst: case iro_ia32_fst:
case iro_ia32_fsub: case iro_ia32_fsub:
case iro_ia32_fxch: case iro_ia32_fxch:
......
...@@ -2065,7 +2065,7 @@ Sahf => { ...@@ -2065,7 +2065,7 @@ Sahf => {
mode => $mode_flags, mode => $mode_flags,
}, },
# fxch, fpush, fpop # fxch, fdup, fpop
# Note that it is NEVER allowed to do CSE on these nodes # Note that it is NEVER allowed to do CSE on these nodes
# Moreover, note the virtual register requierements! # Moreover, note the virtual register requierements!
...@@ -2079,16 +2079,6 @@ fxch => { ...@@ -2079,16 +2079,6 @@ fxch => {
latency => 1, latency => 1,
}, },
fpush => {
op_flags => [ "keep" ],
reg_req => { out => [ "none" ] },
attrs_equal => "attrs_equal_false",
emit => "fld %F0",
attr_type => "ia32_x87_attr_t",
mode => "mode_ANY",
latency => 1,
},
fdup => { fdup => {
reg_req => { in => [ "fp" ], out => [ "fp" ] }, reg_req => { in => [ "fp" ], out => [ "fp" ] },
ins => [ "val" ], ins => [ "val" ],
......
...@@ -433,26 +433,31 @@ static x87_state *x87_shuffle(ir_node *block, x87_state *state, const x87_state ...@@ -433,26 +433,31 @@ static x87_state *x87_shuffle(ir_node *block, x87_state *state, const x87_state
return state; return state;
} }
static ir_node *x87_create_fdup(x87_state *const state, ir_node *const block, ir_node *const val, arch_register_t const *const out)
{
ir_node *const fdup = new_bd_ia32_fdup(NULL, block, val);
ia32_x87_attr_t *const attr = get_ia32_x87_attr(fdup);
unsigned const pos = x87_on_stack_val(state, val);
attr->reg = get_st_reg(pos);
arch_set_irn_register(fdup, out);
x87_push(state, out->index, fdup);
DB((dbg, LEVEL_1, "<<< %s %s\n", get_irn_opname(fdup), attr->reg->name));
return fdup;
}
/** /**
* Create a fpush before node n. * Create an fdup before node @p n replacing operand @p op_n.
* *
* @param state the x87 state * @param state the x87 state
* @param n the node after the fpush * @param n the node after the fdup
* @param val the value to push * @param val the value to duplicate
*/ */
static void x87_create_fpush(x87_state *const state, ir_node *const n, unsigned const out_reg_idx, ir_node *const val) static void x87_dup_operand(x87_state *const state, ir_node *const n, unsigned const op_n, ir_node *const val, arch_register_t const *const out)
{ {
x87_push(state, out_reg_idx, val); ir_node *const block = get_nodes_block(n);
ir_node *const fdup = x87_create_fdup(state, block, val, out);
ir_node *const fpush = new_bd_ia32_fpush(NULL, get_nodes_block(n)); sched_add_before(n, fdup);
ia32_x87_attr_t *const attr = get_ia32_x87_attr(fpush); set_irn_n(n, op_n, fdup);
unsigned const pos = x87_on_stack_val(state, val);
attr->reg = get_st_reg(pos);
keep_alive(fpush);
sched_add_before(n, fpush);
DB((dbg, LEVEL_1, "<<< %s %s\n", get_irn_opname(fpush), attr->reg->name));
} }
/** /**
...@@ -636,9 +641,8 @@ static void sim_binop(x87_state *const state, ir_node *const n) ...@@ -636,9 +641,8 @@ static void sim_binop(x87_state *const state, ir_node *const n)
unsigned op2_idx; unsigned op2_idx;
unsigned out_idx; unsigned out_idx;
bool pop = false; bool pop = false;
unsigned const out_reg_idx = out->index; ia32_x87_attr_t *const attr = get_ia32_x87_attr(n);
ia32_x87_attr_t *const attr = get_ia32_x87_attr(n);
if (reg_index_2 != REG_FP_FP_NOREG) { if (reg_index_2 != REG_FP_FP_NOREG) {
/* second operand is a fp register */ /* second operand is a fp register */
op2_idx = x87_on_stack(state, reg_index_2); op2_idx = x87_on_stack(state, reg_index_2);
...@@ -651,7 +655,7 @@ static void sim_binop(x87_state *const state, ir_node *const n) ...@@ -651,7 +655,7 @@ static void sim_binop(x87_state *const state, ir_node *const n)
if (op1_live_after) { if (op1_live_after) {
/* Both operands are live: push the first one. /* Both operands are live: push the first one.
* This works even for op1 == op2. */ * This works even for op1 == op2. */
x87_create_fpush(state, n, out_reg_idx, op1); x87_dup_operand(state, n, n_ia32_binary_left, op1, out);
/* now do fxxx (tos=tos X op) */ /* now do fxxx (tos=tos X op) */
op1_idx = 0; op1_idx = 0;
op2_idx += 1; op2_idx += 1;
...@@ -707,7 +711,7 @@ static void sim_binop(x87_state *const state, ir_node *const n) ...@@ -707,7 +711,7 @@ static void sim_binop(x87_state *const state, ir_node *const n)
/* second operand is an address mode */ /* second operand is an address mode */
if (op1_live_after) { if (op1_live_after) {
/* first operand is live: push it here */ /* first operand is live: push it here */
x87_create_fpush(state, n, out_reg_idx, op1); x87_dup_operand(state, n, n_ia32_binary_left, op1, out);
} else { } else {
/* first operand is dead: bring it to tos */ /* first operand is dead: bring it to tos */
if (op1_idx != 0) if (op1_idx != 0)
...@@ -721,7 +725,7 @@ static void sim_binop(x87_state *const state, ir_node *const n) ...@@ -721,7 +725,7 @@ static void sim_binop(x87_state *const state, ir_node *const n)
assert(op1_idx == 0 || op2_idx == 0); assert(op1_idx == 0 || op2_idx == 0);
assert(out_idx == op1_idx || out_idx == op2_idx); assert(out_idx == op1_idx || out_idx == op2_idx);
x87_set_st(state, out_reg_idx, n, out_idx); x87_set_st(state, out->index, n, out_idx);
if (pop) if (pop)
x87_pop(state); x87_pop(state);
...@@ -756,10 +760,9 @@ static void sim_unop(x87_state *state, ir_node *n) ...@@ -756,10 +760,9 @@ static void sim_unop(x87_state *state, ir_node *n)
ir_node *const op1 = get_irn_n(n, 0); ir_node *const op1 = get_irn_n(n, 0);
arch_register_t const *const op1_reg = arch_get_irn_register(op1); arch_register_t const *const op1_reg = arch_get_irn_register(op1);
unsigned const op1_reg_idx = op1_reg->index; unsigned const op1_reg_idx = op1_reg->index;
unsigned const out_reg_idx = out->index;
if (is_fp_live(op1_reg_idx, live)) { if (is_fp_live(op1_reg_idx, live)) {
/* push the operand here */ /* push the operand here */
x87_create_fpush(state, n, out_reg_idx, op1); x87_dup_operand(state, n, 0, op1, out);
} else { } else {
/* operand is dead, bring it to tos */ /* operand is dead, bring it to tos */
unsigned const op1_idx = x87_on_stack(state, op1_reg_idx); unsigned const op1_idx = x87_on_stack(state, op1_reg_idx);
...@@ -767,7 +770,7 @@ static void sim_unop(x87_state *state, ir_node *n) ...@@ -767,7 +770,7 @@ static void sim_unop(x87_state *state, ir_node *n)
x87_create_fxch(state, n, op1_idx); x87_create_fxch(state, n, op1_idx);
} }
x87_set_st(state, out_reg_idx, n, 0); x87_set_st(state, out->index, n, 0);
DB((dbg, LEVEL_1, "<<< %s -> %s\n", get_irn_opname(n), get_st_reg(0)->name)); DB((dbg, LEVEL_1, "<<< %s -> %s\n", get_irn_opname(n), get_st_reg(0)->name));
} }
...@@ -820,7 +823,8 @@ static void sim_store(x87_state *state, ir_node *n) ...@@ -820,7 +823,8 @@ static void sim_store(x87_state *state, ir_node *n)
if (get_mode_size_bits(mode) > (mode_is_int(mode) ? 32U : 64U)) { if (get_mode_size_bits(mode) > (mode_is_int(mode) ? 32U : 64U)) {
if (x87_get_depth(state) < N_FLOAT_REGS) { if (x87_get_depth(state) < N_FLOAT_REGS) {
/* ok, we have a free register: push + fstp */ /* ok, we have a free register: push + fstp */
x87_create_fpush(state, n, REG_FP_FP_NOREG, val); arch_register_t const *const out = get_st_reg(REG_FP_FP_NOREG);
x87_dup_operand(state, n, n_ia32_fst_val, val, out);
do_pop: do_pop:
x87_pop(state); x87_pop(state);
} else { } else {
...@@ -1097,24 +1101,19 @@ static void sim_Copy(x87_state *state, ir_node *n) ...@@ -1097,24 +1101,19 @@ static void sim_Copy(x87_state *state, ir_node *n)
DEBUG_ONLY(fp_dump_live(live);) DEBUG_ONLY(fp_dump_live(live);)
if (is_fp_live(op1->index, live)) { if (is_fp_live(op1->index, live)) {
/* Operand is still live, a real copy. We need here an fpush that can /* Operand is still live, a real copy.
* hold a a register, so use a fdup or recreate constants. */ * Use an fdup or recreate constants. */
ir_node *copy; ir_node *copy;
ir_node *const block = get_nodes_block(n); ir_node *const block = get_nodes_block(n);
if (is_irn_constlike(pred)) { if (is_irn_constlike(pred)) {
/* Copy a constant. */ /* Copy a constant. */
copy = exact_copy(pred); copy = exact_copy(pred);
set_nodes_block(copy, block); set_nodes_block(copy, block);
x87_push(state, out->index, copy);
arch_set_irn_register(copy, out);
} else { } else {
dbg_info *const dbgi = get_irn_dbg_info(n); copy = x87_create_fdup(state, block, pred, out);
copy = new_bd_ia32_fdup(dbgi, block, pred);
ia32_x87_attr_t *const attr = get_ia32_x87_attr(copy);
unsigned const op1_idx = x87_on_stack_val(state, pred);
attr->reg = get_st_reg(op1_idx);
} }
x87_push(state, out->index, copy);
arch_set_irn_register(copy, out);
sched_replace(n, copy); sched_replace(n, copy);
exchange(n, copy); exchange(n, copy);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment