fixed lowering of signed 32x32=64 multiplication
authorMichael Beck <beck@ipd.info.uni-karlsruhe.de>
Tue, 28 Aug 2007 13:07:17 +0000 (13:07 +0000)
committerMichael Beck <beck@ipd.info.uni-karlsruhe.de>
Tue, 28 Aug 2007 13:07:17 +0000 (13:07 +0000)
[r15617]

ir/be/ia32/ia32_intrinsics.c
ir/be/ia32/ia32_spec.pl
ir/be/ia32/ia32_transform.c

index 847c3d6..44f1c19 100644 (file)
@@ -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;
index bc6669e..5986d8e 100644 (file)
@@ -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
 },
 
index e346632..c6f8e02 100644 (file)
@@ -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);