From: Michael Beck Date: Tue, 28 Aug 2007 13:07:17 +0000 (+0000) Subject: fixed lowering of signed 32x32=64 multiplication X-Git-Url: http://nsz.repo.hu/git/?a=commitdiff_plain;h=540a01db65a6c602733e09185504e05232bfb0c2;p=libfirm fixed lowering of signed 32x32=64 multiplication [r15617] --- diff --git a/ir/be/ia32/ia32_intrinsics.c b/ir/be/ia32/ia32_intrinsics.c index 847c3d6f2..44f1c199f 100644 --- a/ir/be/ia32/ia32_intrinsics.c +++ b/ir/be/ia32/ia32_intrinsics.c @@ -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; diff --git a/ir/be/ia32/ia32_spec.pl b/ir/be/ia32/ia32_spec.pl index bc6669e16..5986d8e56 100644 --- a/ir/be/ia32/ia32_spec.pl +++ b/ir/be/ia32/ia32_spec.pl @@ -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 }, diff --git a/ir/be/ia32/ia32_transform.c b/ir/be/ia32/ia32_transform.c index e346632e9..c6f8e02dd 100644 --- a/ir/be/ia32/ia32_transform.c +++ b/ir/be/ia32/ia32_transform.c @@ -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);