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)
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)
{
bemit_fop_reg(node, 0xD9, 0xC0);
......@@ -3250,7 +3245,6 @@ static void ia32_register_binary_emitters(void)
be_set_emitter(op_ia32_fldz, bemit_fldz);
be_set_emitter(op_ia32_fmul, bemit_fmul);
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_fst, bemit_fst);
be_set_emitter(op_ia32_fsub, bemit_fsub);
......
......@@ -97,7 +97,6 @@ static bool has_ia32_x87_attr(ir_node const *const node)
case iro_ia32_fisttp:
case iro_ia32_fmul:
case iro_ia32_fpop:
case iro_ia32_fpush:
case iro_ia32_fst:
case iro_ia32_fsub:
case iro_ia32_fxch:
......
......@@ -2065,7 +2065,7 @@ Sahf => {
mode => $mode_flags,
},
# fxch, fpush, fpop
# fxch, fdup, fpop
# Note that it is NEVER allowed to do CSE on these nodes
# Moreover, note the virtual register requierements!
......@@ -2079,16 +2079,6 @@ fxch => {
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 => {
reg_req => { in => [ "fp" ], out => [ "fp" ] },
ins => [ "val" ],
......
......@@ -433,26 +433,31 @@ static x87_state *x87_shuffle(ir_node *block, x87_state *state, const x87_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 n the node after the fpush
* @param val the value to push
* @param n the node after the fdup
* @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 fpush = new_bd_ia32_fpush(NULL, get_nodes_block(n));
ia32_x87_attr_t *const attr = get_ia32_x87_attr(fpush);
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));
ir_node *const block = get_nodes_block(n);
ir_node *const fdup = x87_create_fdup(state, block, val, out);
sched_add_before(n, fdup);
set_irn_n(n, op_n, fdup);
}
/**
......@@ -636,9 +641,8 @@ static void sim_binop(x87_state *const state, ir_node *const n)
unsigned op2_idx;
unsigned out_idx;
bool pop = false;
unsigned const out_reg_idx = out->index;
ia32_x87_attr_t *const attr = get_ia32_x87_attr(n);
bool pop = false;
ia32_x87_attr_t *const attr = get_ia32_x87_attr(n);
if (reg_index_2 != REG_FP_FP_NOREG) {
/* second operand is a fp register */
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)
if (op1_live_after) {
/* Both operands are live: push the first one.
* 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) */
op1_idx = 0;
op2_idx += 1;
......@@ -707,7 +711,7 @@ static void sim_binop(x87_state *const state, ir_node *const n)
/* second operand is an address mode */
if (op1_live_after) {
/* 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 {
/* first operand is dead: bring it to tos */
if (op1_idx != 0)
......@@ -721,7 +725,7 @@ static void sim_binop(x87_state *const state, ir_node *const n)
assert(op1_idx == 0 || op2_idx == 0);
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)
x87_pop(state);
......@@ -756,10 +760,9 @@ static void sim_unop(x87_state *state, ir_node *n)
ir_node *const op1 = get_irn_n(n, 0);
arch_register_t const *const op1_reg = arch_get_irn_register(op1);
unsigned const op1_reg_idx = op1_reg->index;
unsigned const out_reg_idx = out->index;
if (is_fp_live(op1_reg_idx, live)) {
/* push the operand here */
x87_create_fpush(state, n, out_reg_idx, op1);
x87_dup_operand(state, n, 0, op1, out);
} else {
/* operand is dead, bring it to tos */
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)
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));
}
......@@ -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 (x87_get_depth(state) < N_FLOAT_REGS) {
/* 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:
x87_pop(state);
} else {
......@@ -1097,24 +1101,19 @@ static void sim_Copy(x87_state *state, ir_node *n)
DEBUG_ONLY(fp_dump_live(live);)
if (is_fp_live(op1->index, live)) {
/* Operand is still live, a real copy. We need here an fpush that can
* hold a a register, so use a fdup or recreate constants. */
/* Operand is still live, a real copy.
* Use an fdup or recreate constants. */
ir_node *copy;
ir_node *const block = get_nodes_block(n);
if (is_irn_constlike(pred)) {
/* Copy a constant. */
copy = exact_copy(pred);
set_nodes_block(copy, block);
x87_push(state, out->index, copy);
arch_set_irn_register(copy, out);
} else {
dbg_info *const dbgi = get_irn_dbg_info(n);
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);
copy = x87_create_fdup(state, block, pred, out);
}
x87_push(state, out->index, copy);
arch_set_irn_register(copy, out);
sched_replace(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