Commit a5ccc803 authored by Christoph Mallon's avatar Christoph Mallon
Browse files

ia32: Split IMul into IMul and IMulImm.

parent a1461bd2
......@@ -687,18 +687,6 @@ unknown:
va_end(ap);
}
static void emit_ia32_IMul(const ir_node *node)
{
/* do we need the 3-address form? */
arch_register_t const *const in_reg = arch_get_irn_register_in(node, n_ia32_IMul_left);
arch_register_t const *const out_reg = arch_get_irn_register_out(node, pn_ia32_IMul_res);
if (in_reg != out_reg) {
ia32_emitf(node, "imul%M %#S4, %#AS3, %#D0");
} else {
ia32_emitf(node, "imul%M %#AS4, %#S3");
}
}
/**
* walks up a tree of copies/perms/spills/reloads to find the original value
* that is moved around
......@@ -1327,7 +1315,6 @@ static void ia32_register_emitters(void)
be_set_emitter(op_ia32_CopyB, emit_ia32_CopyB);
be_set_emitter(op_ia32_CopyB_i, emit_ia32_CopyB_i);
be_set_emitter(op_ia32_GetEIP, emit_ia32_GetEIP);
be_set_emitter(op_ia32_IMul, emit_ia32_IMul);
be_set_emitter(op_ia32_Jcc, emit_ia32_Jcc);
be_set_emitter(op_ia32_Jmp, emit_ia32_Jmp);
be_set_emitter(op_ia32_Minus64, emit_ia32_Minus64);
......@@ -2350,16 +2337,16 @@ static void bemit_test(ir_node const *const node)
static void bemit_imul(const ir_node *node)
{
ir_node *right = get_irn_n(node, n_ia32_IMul_right);
/* Do we need the immediate form? */
if (is_ia32_Immediate(right)) {
ia32_immediate_attr_t const *const attr = get_ia32_immediate_attr_const(right);
bool const imm8 = ia32_is_8bit_imm(attr);
bemit_unop_reg(node, 0x69 | (imm8 ? OP_IMM8 : 0), n_ia32_IMul_left);
bemit_imm(attr, imm8 ? 8 : 32);
} else {
bemit_0f_unop_reg(node, 0xAF, n_ia32_IMul_right);
}
bemit_0f_unop_reg(node, 0xAF, n_ia32_IMul_right);
}
static void bemit_imulimm(const ir_node *node)
{
ir_node const *const right = get_irn_n(node, n_ia32_IMul_right);
ia32_immediate_attr_t const *const attr = get_ia32_immediate_attr_const(right);
bool const imm8 = ia32_is_8bit_imm(attr);
bemit_unop_reg(node, 0x69 | (imm8 ? OP_IMM8 : 0), n_ia32_IMul_left);
bemit_imm(attr, imm8 ? 8 : 32);
}
static void bemit_dec(const ir_node *node)
......@@ -3096,6 +3083,7 @@ static void ia32_register_binary_emitters(void)
be_set_emitter(op_ia32_IJmp, bemit_ijmp);
be_set_emitter(op_ia32_IMul, bemit_imul);
be_set_emitter(op_ia32_IMul1OP, bemit_imul1op);
be_set_emitter(op_ia32_IMulImm, bemit_imulimm);
be_set_emitter(op_ia32_Inc, bemit_inc);
be_set_emitter(op_ia32_IncMem, bemit_incmem);
be_set_emitter(op_ia32_Jcc, bemit_ia32_jcc);
......
......@@ -186,12 +186,6 @@ static inline int need_constraint_copy(ir_node *irn)
{
/* TODO this should be determined from the node specification */
switch (get_ia32_irn_opcode(irn)) {
case iro_ia32_IMul: {
/* the 3 operand form of IMul needs no constraint copy */
ir_node *right = get_irn_n(irn, n_ia32_IMul_right);
return !is_ia32_Immediate(right);
}
case iro_ia32_Lea:
case iro_ia32_Minus64:
return 0;
......
......@@ -837,14 +837,11 @@ exchange:
/**
* Split a Imul mem, imm into a Load mem and Imul reg, imm if possible.
*/
static void peephole_ia32_Imul_split(ir_node *imul)
static void peephole_ia32_ImulImm_split(ir_node *imul)
{
const ir_node *right = get_irn_n(imul, n_ia32_IMul_right);
if (!is_ia32_Immediate(right) || get_ia32_op_type(imul) != ia32_AddrModeS) {
/* no memory, imm form ignore */
/* Ignore, if no memory, imm form. */
if (get_ia32_op_type(imul) != ia32_AddrModeS)
return;
}
/* we need a free register */
const arch_register_t *reg = get_free_gp_reg(get_irn_irg(imul));
if (reg == NULL)
......@@ -910,8 +907,8 @@ void ia32_peephole_optimization(ir_graph *irg)
register_peephole_optimization(op_ia32_Conv_I2I, peephole_ia32_Conv_I2I);
if (ia32_cg_config.use_pxor)
register_peephole_optimization(op_ia32_xZero, peephole_ia32_xZero);
if (! ia32_cg_config.use_imul_mem_imm32)
register_peephole_optimization(op_ia32_IMul, peephole_ia32_Imul_split);
if (!ia32_cg_config.use_imul_mem_imm32)
register_peephole_optimization(op_ia32_IMulImm, peephole_ia32_ImulImm_split);
be_peephole_opt(irg);
/* pass 2 */
......
......@@ -266,13 +266,26 @@ l_Mul => {
IMul => {
irn_flags => [ "rematerializable" ],
state => "exc_pinned",
# TODO: adjust out requirements for the 3 operand form
# (no need for should_be_same then)
reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ],
out => [ "in_r4 in_r5", "flags", "none" ] },
ins => [ "base", "index", "mem", "left", "right" ],
outs => [ "res", "flags", "M" ],
am => "source,binary",
emit => "imul%M %B",
latency => 5,
mode => $mode_gp,
modified_flags => $status_flags
},
IMulImm => {
irn_flags => [ "rematerializable" ],
state => "exc_pinned",
reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ],
out => [ "gp", "flags", "none" ] },
ins => [ "base", "index", "mem", "left", "right" ],
outs => [ "res", "flags", "M" ],
am => "source,binary",
emit => "imul%M %#S4, %#AS3, %#D0",
latency => 5,
mode => $mode_gp,
modified_flags => $status_flags
......
......@@ -1504,9 +1504,13 @@ static ir_node *gen_Mul(ir_node *node)
else
return gen_binop_x87_float(node, op1, op2, new_bd_ia32_fmul);
}
return gen_binop(node, op1, op2, new_bd_ia32_IMul,
match_commutative | match_am | match_mode_neutral |
match_immediate | match_am_and_immediates);
ir_node *const block = get_nodes_block(node);
ia32_address_mode_t am;
match_arguments(&am, block, op1, op2, NULL, match_commutative | match_am | match_mode_neutral | match_immediate | match_am_and_immediates);
construct_binop_func *const func = is_ia32_Immediate(am.new_op2) ? new_bd_ia32_IMulImm : new_bd_ia32_IMul;
return make_binop(node, &am, func);
}
/**
......
Supports Markdown
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