Commit 540a01db authored by Michael Beck's avatar Michael Beck
Browse files

fixed lowering of signed 32x32=64 multiplication

[r15617]
parent 7ee233ad
......@@ -431,6 +431,25 @@ static int map_Mul(ir_node *call, void *ctx) {
h_res = t2 + t3
*/
if (is_Shrs(a_h) && get_Shrs_left(a_h) == a_l &&
is_Shrs(b_h) && get_Shrs_left(b_h) == b_l) {
ir_node *c1 = get_Shrs_right(a_h);
if (c1 == get_Shrs_right(b_h) && is_Const(c1)) {
tarval *tv = get_Const_tarval(c1);
if (tarval_is_long(tv) && get_tarval_long(tv) == 31) {
/* it's a 32 * 32 = 64 signed multiplication */
mul = new_rd_ia32_l_IMul(dbg, irg, block, a_l, b_l);
h_res = new_rd_Proj(dbg, irg, block, mul, l_mode, pn_ia32_l_Mul_EDX);
l_res = new_rd_Proj(dbg, irg, block, mul, l_mode, pn_ia32_l_Mul_EAX);
goto end;
}
}
}
mul = new_rd_ia32_l_Mul(dbg, irg, block, a_l, b_l);
pEDX = new_rd_Proj(dbg, irg, block, mul, l_mode, pn_ia32_l_Mul_EDX);
l_res = new_rd_Proj(dbg, irg, block, mul, l_mode, pn_ia32_l_Mul_EAX);
......@@ -440,6 +459,7 @@ static int map_Mul(ir_node *call, void *ctx) {
mul = new_rd_Mul(dbg, irg, block, a_l, b_h, l_mode);
h_res = new_rd_Add(dbg, irg, block, add, mul, l_mode);
end:
resolve_call(call, l_res, h_res, irg, block);
return 1;
......
......@@ -471,8 +471,11 @@ IMul1OP => {
},
l_IMul => {
# we should not rematrialize this node. It produces 2 results and has
# very strict constrains
op_flags => "C",
cmp_attr => "return 1;",
outs => [ "EAX", "EDX", "M" ],
arity => 2
},
......
......@@ -3380,7 +3380,6 @@ GEN_LOWERED_OP(Adc)
GEN_LOWERED_OP(Add)
GEN_LOWERED_OP(Sbb)
GEN_LOWERED_OP(Sub)
GEN_LOWERED_OP(IMul)
GEN_LOWERED_OP(Xor)
GEN_LOWERED_x87_OP(vfprem)
GEN_LOWERED_x87_OP(vfmul)
......@@ -3490,6 +3489,34 @@ static ir_node *gen_ia32_l_Mul(ir_node *node) {
return muls;
}
/**
* Transforms a l_IMulS into a "real" IMul1OPS node.
*
* @param env The transformation environment
* @return the created ia32 IMul1OP node
*/
static ir_node *gen_ia32_l_IMul(ir_node *node) {
ir_node *block = be_transform_node(get_nodes_block(node));
ir_node *left = get_binop_left(node);
ir_node *new_left = be_transform_node(left);
ir_node *right = get_binop_right(node);
ir_node *new_right = be_transform_node(right);
ir_node *noreg = ia32_new_NoReg_gp(env_cg);
ir_graph *irg = current_ir_graph;
dbg_info *dbgi = get_irn_dbg_info(node);
/* l_IMul is already a mode_T node, so we create the IMul1OP in the normal way */
/* and then skip the result Proj, because all needed Projs are already there. */
ir_node *muls = new_rd_ia32_IMul1OP(dbgi, irg, block, noreg, noreg, new_left,
new_right, new_NoMem());
clear_ia32_commutative(muls);
set_ia32_am_support(muls, ia32_am_Source, ia32_am_binary);
SET_IA32_ORIG_NODE(muls, ia32_get_old_node_name(env_cg, node));
return muls;
}
GEN_LOWERED_SHIFT_OP(l_ShlDep, Shl)
GEN_LOWERED_SHIFT_OP(l_ShrDep, Shr)
GEN_LOWERED_SHIFT_OP(l_Sar, Sar)
......@@ -4202,8 +4229,8 @@ static void register_transformers(void)
GEN(ia32_l_Sbb);
GEN(ia32_l_Neg);
GEN(ia32_l_Mul);
GEN(ia32_l_Xor);
GEN(ia32_l_IMul);
GEN(ia32_l_Xor);
GEN(ia32_l_ShlDep);
GEN(ia32_l_ShrDep);
GEN(ia32_l_Sar);
......
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