fixed DivMods
authorChristian Würdig <chriswue@ipd.info.uni-karlsruhe.de>
Wed, 5 Apr 2006 14:50:43 +0000 (14:50 +0000)
committerChristian Würdig <chriswue@ipd.info.uni-karlsruhe.de>
Wed, 5 Apr 2006 14:50:43 +0000 (14:50 +0000)
ir/be/ia32/bearch_ia32.c
ir/be/ia32/ia32_spec.pl
ir/be/ia32/ia32_transform.c

index 9e9a513..cf9dcf1 100644 (file)
@@ -513,8 +513,6 @@ static void ia32_finish_node(ir_node *irn, void *env) {
                                        out_reg  = get_ia32_out_reg(irn, i);
                                        in_node  = get_irn_n(irn, reqs[i]->same_pos);
                                        in_reg   = arch_get_irn_register(cg->arch_env, in_node);
-                                       in2_node = get_irn_n(irn, reqs[i]->same_pos ^ 1);
-                                       in2_reg  = arch_get_irn_register(cg->arch_env, in2_node);
 
                                        /* don't copy ignore nodes */
                                        if (arch_irn_is(cg->arch_env, in_node, ignore) && is_Proj(in_node))
@@ -523,11 +521,21 @@ static void ia32_finish_node(ir_node *irn, void *env) {
                                        /* check if in and out register are equal */
                                        if (! REGS_ARE_EQUAL(out_reg, in_reg)) {
                                                /* in case of a commutative op: just exchange the in's */
-                                               if (is_ia32_commutative(irn) && REGS_ARE_EQUAL(out_reg, in2_reg)) {
-                                                       set_irn_n(irn, reqs[i]->same_pos, in2_node);
-                                                       set_irn_n(irn, reqs[i]->same_pos ^ 1, in_node);
+                                               /* beware: the current op could be everything, so test for ia32 */
+                                               /*         commutativity first before getting the second in     */
+                                               if (is_ia32_commutative(irn)) {
+                                                       in2_node = get_irn_n(irn, reqs[i]->same_pos ^ 1);
+                                                       in2_reg  = arch_get_irn_register(cg->arch_env, in2_node);
+
+                                                       if (REGS_ARE_EQUAL(out_reg, in2_reg)) {
+                                                               set_irn_n(irn, reqs[i]->same_pos, in2_node);
+                                                               set_irn_n(irn, reqs[i]->same_pos ^ 1, in_node);
+                                                       }
+                                                       else
+                                                               goto insert_copy;
                                                }
                                                else {
+insert_copy:
                                                        DBG((cg->mod, LEVEL_1, "inserting copy for %+F in_pos %d\n", irn, reqs[i]->same_pos));
                                                        /* create copy from in register */
                                                        copy = be_new_Copy(arch_register_get_class(in_reg), cg->irg, block, in_node);
index b3daa20..73adc49 100644 (file)
@@ -277,10 +277,13 @@ $comment_string = "/*";
 },
 
 "DivMod" => {
-  "op_flags" => "F|L",
-  "state"    => "exc_pinned",
-  "reg_req"  => { "in" => [ "gp", "gp", "gp", "none" ], "out" => [ "eax in_r1", "edx in_r3" ] },
-  "emit"     =>
+  "op_flags"  => "F|L",
+  "state"     => "exc_pinned",
+  "reg_req"   => { "in" => [ "gp", "gp", "gp", "none" ], "out" => [ "eax in_r1", "edx in_r3" ] },
+  "attr"      => "ia32_op_flavour_t dm_flav",
+  "init_attr" => "  attr->data.op_flav = dm_flav;",
+  "cmp_attr"  => "  return attr_a->data.op_flav != attr_b->data.op_flav;\n",
+  "emit"      =>
 '  if (mode_is_signed(get_irn_mode(n))) {
 4.  idiv %S2 /* signed DivMod(%S1, %S2) -> %D1, (%A1, %A2, %A3) */
   }
index c440df3..c3b6984 100644 (file)
@@ -888,9 +888,8 @@ static ir_node *generate_DivMod(ia32_transform_env_t *env, ir_node *dividend, ir
                set_ia32_Immop_tarval(edx_node, get_tarval_null(mode_Iu));
        }
 
-       res = new_rd_ia32_DivMod(dbg, irg, block, dividend, divisor, edx_node, mem, mode_T);
+       res = new_rd_ia32_DivMod(dbg, irg, block, dividend, divisor, edx_node, mem, mode_T, dm_flav);
 
-       set_ia32_flavour(res, dm_flav);
        set_ia32_n_res(res, 2);
 
        /* Only one proj is used -> We must add a second proj and */