Commit 231dd1fa authored by Matthias Braun's avatar Matthias Braun
Browse files

amd64: Transform x87 cmp -> fucomi

parent 1cc6e57b
...@@ -820,6 +820,16 @@ fchs => { ...@@ -820,6 +820,16 @@ fchs => {
emit => "fchs", emit => "fchs",
}, },
fucomi => {
irn_flags => [ "rematerializable" ],
in_reqs => [ "x87", "x87" ],
out_reqs => [ "flags" ],
ins => [ "left", "right" ],
outs => [ "flags" ],
attr_type => "amd64_x87_attr_t",
emit => "fucom%FPi %F0",
},
fdup => { fdup => {
in_reqs => [ "x87" ], in_reqs => [ "x87" ],
out_reqs => [ "x87" ], out_reqs => [ "x87" ],
......
...@@ -1893,6 +1893,16 @@ static ir_node *gen_Proj_Proj(ir_node *const node) ...@@ -1893,6 +1893,16 @@ static ir_node *gen_Proj_Proj(ir_node *const node)
panic("amd64: unexpected Proj(Proj) after %+F", pred_pred); panic("amd64: unexpected Proj(Proj) after %+F", pred_pred);
} }
static ir_node *match_cmp_x87(ir_node *const node, ir_node *const op0,
ir_node *op1)
{
dbg_info *const dbgi = get_irn_dbg_info(node);
ir_node *const new_block = be_transform_node(get_nodes_block(node));
ir_node *const new_op0 = be_transform_node(op0);
ir_node *const new_op1 = be_transform_node(op1);
return new_bd_amd64_fucomi(dbgi, new_block, new_op0, new_op1);
}
static ir_node *gen_Cmp(ir_node *const node) static ir_node *gen_Cmp(ir_node *const node)
{ {
ir_node *const op1 = get_Cmp_left(node); ir_node *const op1 = get_Cmp_left(node);
...@@ -1905,6 +1915,8 @@ static ir_node *gen_Cmp(ir_node *const node) ...@@ -1905,6 +1915,8 @@ static ir_node *gen_Cmp(ir_node *const node)
ir_node *new_node; ir_node *new_node;
amd64_args_t args; amd64_args_t args;
if (mode_is_float(cmp_mode)) { if (mode_is_float(cmp_mode)) {
if (cmp_mode == x86_mode_E)
return match_cmp_x87(node, op1, op2);
match_binop(&args, block, cmp_mode, op1, op2, match_am); match_binop(&args, block, cmp_mode, op1, op2, match_am);
new_node = new_bd_amd64_ucomis(dbgi, new_block, args.arity, args.in, args.reqs, &args.attr); new_node = new_bd_amd64_ucomis(dbgi, new_block, args.arity, args.in, args.reqs, &args.attr);
} else { } else {
......
...@@ -75,21 +75,37 @@ static void sim_amd64_fdiv(x87_state *const state, ir_node *const node) ...@@ -75,21 +75,37 @@ static void sim_amd64_fdiv(x87_state *const state, ir_node *const node)
x86_sim_x87_binop(state, node, n_amd64_fdiv_left, n_amd64_fdiv_right, out); x86_sim_x87_binop(state, node, n_amd64_fdiv_left, n_amd64_fdiv_right, out);
} }
static void sim_amd64_fucomi(x87_state *const state, ir_node *const node)
{
ir_node *const op0 = get_irn_n(node, n_amd64_fucomi_left);
ir_node *const op1 = get_irn_n(node, n_amd64_fucomi_right);
unsigned const additional_pop = x86_sim_x87_fucom(state, node, op0, op1);
if (additional_pop != ~0u)
x86_x87_create_fpop(state, node, additional_pop);
/* TODO remove the following check once all emitters that test flags
* check the predecessor nodes for reverse condition */
x87_attr_t const *const x87 = amd64_get_x87_attr(node);
if (x87->reverse)
panic("reverse not handled yet");
}
static void prepare_callbacks(void) static void prepare_callbacks(void)
{ {
x86_prepare_x87_callbacks(); x86_prepare_x87_callbacks();
x86_register_x87_sim(op_amd64_call, sim_amd64_call); x86_register_x87_sim(op_amd64_call, sim_amd64_call);
x86_register_x87_sim(op_amd64_fadd, sim_amd64_fadd); x86_register_x87_sim(op_amd64_fadd, sim_amd64_fadd);
x86_register_x87_sim(op_amd64_fchs, x86_sim_x87_unop); x86_register_x87_sim(op_amd64_fchs, x86_sim_x87_unop);
x86_register_x87_sim(op_amd64_fdiv, sim_amd64_fdiv); x86_register_x87_sim(op_amd64_fdiv, sim_amd64_fdiv);
x86_register_x87_sim(op_amd64_fld, sim_amd64_fld); x86_register_x87_sim(op_amd64_fld, sim_amd64_fld);
x86_register_x87_sim(op_amd64_fld1, x86_x87_push); x86_register_x87_sim(op_amd64_fld1, x86_x87_push);
x86_register_x87_sim(op_amd64_fldz, x86_x87_push); x86_register_x87_sim(op_amd64_fldz, x86_x87_push);
x86_register_x87_sim(op_amd64_fmul, sim_amd64_fmul); x86_register_x87_sim(op_amd64_fmul, sim_amd64_fmul);
x86_register_x87_sim(op_amd64_fst, sim_amd64_fst); x86_register_x87_sim(op_amd64_fst, sim_amd64_fst);
x86_register_x87_sim(op_amd64_fstp, sim_amd64_fstp); x86_register_x87_sim(op_amd64_fstp, sim_amd64_fstp);
x86_register_x87_sim(op_amd64_fsub, sim_amd64_fsub); x86_register_x87_sim(op_amd64_fsub, sim_amd64_fsub);
x86_register_x87_sim(op_amd64_ret, x86_sim_x87_ret); x86_register_x87_sim(op_amd64_fucomi, sim_amd64_fucomi);
x86_register_x87_sim(op_amd64_ret, x86_sim_x87_ret);
} }
void amd64_simulate_graph_x87(ir_graph *irg) void amd64_simulate_graph_x87(ir_graph *irg)
......
...@@ -474,17 +474,8 @@ static ir_node *x87_dup_operand(x87_state *const state, ir_node *const n, unsign ...@@ -474,17 +474,8 @@ static ir_node *x87_dup_operand(x87_state *const state, ir_node *const n, unsign
return fdup; return fdup;
} }
/** ir_node *x86_x87_create_fpop(x87_state *const state, ir_node *const n,
* Create a fpop before node n. unsigned const pos)
* This overwrites st(pos) with st(0) and pops st(0).
*
* @param state the x87 state
* @param n the node after which to schedule the fpop
* @param pos the index of the entry to remove the register stack
* @return the fpop node
*/
static ir_node *x87_create_fpop(x87_state *const state, ir_node *const n,
unsigned const pos)
{ {
if (pos != 0) { if (pos != 0) {
st_entry *const dst = x87_get_entry(state, pos); st_entry *const dst = x87_get_entry(state, pos);
...@@ -940,7 +931,7 @@ static void sim_FtstFnstsw(x87_state *state, ir_node *n) ...@@ -940,7 +931,7 @@ static void sim_FtstFnstsw(x87_state *state, ir_node *n)
move_to_tos(state, n, val); move_to_tos(state, n, val);
if (!is_fp_live(val, live)) if (!is_fp_live(val, live))
x87_create_fpop(state, n, 0); x86_x87_create_fpop(state, n, 0);
} }
unsigned x86_sim_x87_fucom(x87_state *const state, ir_node *const node, unsigned x86_sim_x87_fucom(x87_state *const state, ir_node *const node,
...@@ -1045,7 +1036,7 @@ static void sim_ia32_FucomFnstsw(x87_state *const state, ir_node *const node) ...@@ -1045,7 +1036,7 @@ static void sim_ia32_FucomFnstsw(x87_state *const state, ir_node *const node)
set_irn_op(node, op_ia32_FucomppFnstsw); set_irn_op(node, op_ia32_FucomppFnstsw);
x87_pop(state); x87_pop(state);
} else { } else {
x87_create_fpop(state, node, additional_pop); x86_x87_create_fpop(state, node, additional_pop);
} }
} }
} }
...@@ -1059,7 +1050,7 @@ static void sim_ia32_Fucomi(x87_state *const state, ir_node *const node) ...@@ -1059,7 +1050,7 @@ static void sim_ia32_Fucomi(x87_state *const state, ir_node *const node)
ia32_x87_attr_t *const attr = get_ia32_x87_attr(node); ia32_x87_attr_t *const attr = get_ia32_x87_attr(node);
attr->attr.ins_permuted ^= attr->x87.reverse; attr->attr.ins_permuted ^= attr->x87.reverse;
if (additional_pop != ~0u) if (additional_pop != ~0u)
x87_create_fpop(state, node, additional_pop); x86_x87_create_fpop(state, node, additional_pop);
} }
/** /**
...@@ -1261,7 +1252,7 @@ free_all:; ...@@ -1261,7 +1252,7 @@ free_all:;
} }
} }
} }
insert = x87_create_fpop(state, insert, i); insert = x86_x87_create_fpop(state, insert, i);
depth -= 1; depth -= 1;
kill_mask >>= 1; kill_mask >>= 1;
} }
......
...@@ -73,6 +73,18 @@ unsigned x86_sim_x87_fucom(x87_state *state, ir_node *node, ...@@ -73,6 +73,18 @@ unsigned x86_sim_x87_fucom(x87_state *state, ir_node *node,
/** Push a value on the x87 stack. Intended to be used in sim functions. */ /** Push a value on the x87 stack. Intended to be used in sim functions. */
void x86_x87_push(x87_state *state, ir_node *value); void x86_x87_push(x87_state *state, ir_node *value);
/**
* Create a fpop before node n.
* This overwrites st(pos) with st(0) and pops st(0).
*
* @param state the x87 state
* @param n the node after which to schedule the fpop
* @param pos the index of the entry to remove the register stack
* @return the fpop node
*/
ir_node *x86_x87_create_fpop(x87_state *const state, ir_node *const n,
unsigned const pos);
/** /**
* Register a simulator function. * Register a simulator function.
* *
......
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