From: Christian Würdig Date: Wed, 5 Apr 2006 14:50:43 +0000 (+0000) Subject: fixed DivMods X-Git-Url: http://nsz.repo.hu/git/?a=commitdiff_plain;h=ec4ce0e79bd13da8b3b0f068e78c64b21a35ffba;p=libfirm fixed DivMods --- diff --git a/ir/be/ia32/bearch_ia32.c b/ir/be/ia32/bearch_ia32.c index 9e9a513ff..cf9dcf17d 100644 --- a/ir/be/ia32/bearch_ia32.c +++ b/ir/be/ia32/bearch_ia32.c @@ -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); diff --git a/ir/be/ia32/ia32_spec.pl b/ir/be/ia32/ia32_spec.pl index b3daa2007..73adc493e 100644 --- a/ir/be/ia32/ia32_spec.pl +++ b/ir/be/ia32/ia32_spec.pl @@ -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) */ } diff --git a/ir/be/ia32/ia32_transform.c b/ir/be/ia32/ia32_transform.c index c440df344..c3b6984ed 100644 --- a/ir/be/ia32/ia32_transform.c +++ b/ir/be/ia32/ia32_transform.c @@ -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 */