From df43734406c990f67928c8a095f730eb6c0c59a6 Mon Sep 17 00:00:00 2001 From: Matthias Braun Date: Tue, 27 Feb 2007 11:10:57 +0000 Subject: [PATCH] fix Mulh, Div, IDiv handling --- ir/be/ia32/ia32_emitter.c | 9 +++-- ir/be/ia32/ia32_spec.pl | 44 +++++++++++------------ ir/be/ia32/ia32_transform.c | 71 +++++++++++++++++++++++++++---------- 3 files changed, 77 insertions(+), 47 deletions(-) diff --git a/ir/be/ia32/ia32_emitter.c b/ir/be/ia32/ia32_emitter.c index 2e2f348a2..c5ec338d1 100644 --- a/ir/be/ia32/ia32_emitter.c +++ b/ir/be/ia32/ia32_emitter.c @@ -343,7 +343,7 @@ void ia32_emit_x87_name(ia32_emit_env_t *env, const ir_node *node, int pos) { ia32_attr_t *attr = get_ia32_attr(node); - assert(pos < 7); + assert(pos < 3); ia32_emit_char(env, '%'); ia32_emit_string(env, attr->x87[pos]->name); } @@ -515,11 +515,10 @@ void ia32_emit_unop(ia32_emit_env_t *env, const ir_node *node) { ia32_emit_char(env, '$'); ia32_emit_immediate(env, node); } else { - if (is_ia32_IMul(node) || is_ia32_Mulh(node)) { - /* MulS and Mulh implicitly multiply by EAX */ + if (is_ia32_Mul(node) || is_ia32_IMul1OP(node)) { ia32_emit_source_register(env, node, 3); - } else if(is_ia32_IDiv(node)) { - ia32_emit_source_register(env, node, 1); + } else if(is_ia32_IDiv(node) || is_ia32_Div(node)) { + ia32_emit_source_register(env, node, 4); } else if(is_ia32_Push(node)) { ia32_emit_source_register(env, node, 2); } else if(is_ia32_Pop(node)) { diff --git a/ir/be/ia32/ia32_spec.pl b/ir/be/ia32/ia32_spec.pl index 409b1d412..116c9b376 100644 --- a/ir/be/ia32/ia32_spec.pl +++ b/ir/be/ia32/ia32_spec.pl @@ -114,7 +114,7 @@ $arch = "ia32"; { "name" => "ebp", "type" => 2 }, { "name" => "esp", "type" => 4 }, { "name" => "gp_NOREG", "type" => 4 | 8 | 16 }, # we need a dummy register for NoReg nodes - { "name" => "gp_UKNWN", "type" => 4 | 8 | 16}, # we need a dummy register for Unknown nodes + { "name" => "gp_UKNWN", "type" => 4 | 8 | 16 }, # we need a dummy register for Unknown nodes { "mode" => "mode_Iu" } ], "xmm" => [ @@ -127,7 +127,7 @@ $arch = "ia32"; { "name" => "xmm6", "type" => 1 }, { "name" => "xmm7", "type" => 1 }, { "name" => "xmm_NOREG", "type" => 4 | 8 | 16 }, # we need a dummy register for NoReg nodes - { "name" => "xmm_UKNWN", "type" => 4 | 8 | 16}, # we need a dummy register for Unknown nodes + { "name" => "xmm_UKNWN", "type" => 4 | 8 | 16 }, # we need a dummy register for Unknown nodes { "mode" => "mode_E" } ], "vfp" => [ @@ -140,7 +140,7 @@ $arch = "ia32"; { "name" => "vf6", "type" => 1 | 16 }, { "name" => "vf7", "type" => 1 | 16 }, { "name" => "vfp_NOREG", "type" => 4 | 8 | 16 }, # we need a dummy register for NoReg nodes - { "name" => "vfp_UKNWN", "type" => 4 | 8 | 16}, # we need a dummy register for Unknown nodes + { "name" => "vfp_UKNWN", "type" => 4 | 8 | 16 }, # we need a dummy register for Unknown nodes { "mode" => "mode_E" } ], "st" => [ @@ -323,6 +323,16 @@ $default_cmp_attr = "return ia32_compare_attr(attr_a, attr_b);"; "mode" => "mode_Iu", }, +"IMul1OP" => { + "irn_flags" => "R", + "comment" => "construct Mul (1 operand format): Mul(a, b) = Mul(b, a) = a * b", + "reg_req" => { "in" => [ "gp", "gp", "eax", "gp", "none" ], "out" => [ "eax", "edx", "none" ] }, + "emit" => '. imull %unop', + "outs" => [ "EAX", "EDX", "M" ], + "latency" => 5, + "units" => [ "GP" ], +}, + "l_IMul" => { "op_flags" => "C", "cmp_attr" => "return 1;", @@ -330,20 +340,6 @@ $default_cmp_attr = "return ia32_compare_attr(attr_a, attr_b);"; "arity" => 2 }, -# Mulh is an exception from the 4 INs with AM because the target is always EAX:EDX -# Matze: It's not clear to me why we have a separate Mulh node and not just use -# the IMul node... -"Mulh" => { - # we should not rematrialize this node. It produces 2 results and has - # very strict constrains - "comment" => "construct Mul: Mul(a, b) = Mul(b, a) = a * b", - "reg_req" => { "in" => [ "gp", "gp", "eax", "gp", "none" ], "out" => [ "eax", "edx" ] }, - "emit" => '. imull %unop', - "outs" => [ "EAX", "EDX", "M" ], - "latency" => 5, - "units" => [ "GP" ], -}, - "And" => { "irn_flags" => "R", "comment" => "construct And: And(a, b) = And(b, a) = a AND b", @@ -428,7 +424,7 @@ $default_cmp_attr = "return ia32_compare_attr(attr_a, attr_b);"; "IDiv" => { "op_flags" => "F|L", "state" => "exc_pinned", - "reg_req" => { "in" => [ "eax", "gp", "edx", "none" ], "out" => [ "eax", "edx", "none" ] }, + "reg_req" => { "in" => [ "gp", "gp", "eax", "edx", "gp", "none" ], "out" => [ "eax", "edx", "none" ] }, "attr" => "ia32_op_flavour_t dm_flav", "init_attr" => "attr->data.op_flav = dm_flav;", "emit" => ". idivl %unop", @@ -440,7 +436,7 @@ $default_cmp_attr = "return ia32_compare_attr(attr_a, attr_b);"; "Div" => { "op_flags" => "F|L", "state" => "exc_pinned", - "reg_req" => { "in" => [ "eax", "gp", "edx", "none" ], "out" => [ "eax", "edx", "none" ] }, + "reg_req" => { "in" => [ "gp", "gp", "eax", "edx", "gp", "none" ], "out" => [ "eax", "edx", "none" ] }, "attr" => "ia32_op_flavour_t dm_flav", "init_attr" => "attr->data.op_flav = dm_flav;", "emit" => ". divl %unop", @@ -1125,7 +1121,7 @@ if (get_ia32_immop_type(node) == ia32_ImmNone) { "state" => "exc_pinned", "comment" => "store ST0 onto stack", "reg_req" => { "in" => [ "gp", "gp", "none" ] }, - "emit" => '. fstp%M %AM', + "emit" => '. fstp%XM %AM', "latency" => 4, "units" => [ "SSE" ], "mode" => "mode_M", @@ -1726,7 +1722,7 @@ if (get_ia32_immop_type(node) == ia32_ImmNone) { "state" => "exc_pinned", "comment" => "x87 fp Load: Load(ptr, mem) = LD ptr -> reg", "reg_req" => { }, - "emit" => '. fld%M %AM', + "emit" => '. fld%XM %AM', }, "fst" => { @@ -1735,7 +1731,7 @@ if (get_ia32_immop_type(node) == ia32_ImmNone) { "state" => "exc_pinned", "comment" => "x87 fp Store: Store(ptr, val, mem) = ST ptr,val", "reg_req" => { }, - "emit" => '. fst%M %AM', + "emit" => '. fst%XM %AM', "mode" => "mode_M", }, @@ -1745,7 +1741,7 @@ if (get_ia32_immop_type(node) == ia32_ImmNone) { "state" => "exc_pinned", "comment" => "x87 fp Store: Store(ptr, val, mem) = ST ptr,val", "reg_req" => { }, - "emit" => '. fstp%M %AM', + "emit" => '. fstp%XM %AM', "mode" => "mode_M", }, @@ -1756,7 +1752,7 @@ if (get_ia32_immop_type(node) == ia32_ImmNone) { "rd_constructor" => "NONE", "comment" => "x87 fp integer Load: Load(ptr, mem) = iLD ptr -> reg", "reg_req" => { }, - "emit" => '. fild%M %AM', + "emit" => '. fild%XM %AM', }, "fist" => { diff --git a/ir/be/ia32/ia32_transform.c b/ir/be/ia32/ia32_transform.c index 008168efd..434d6dd79 100644 --- a/ir/be/ia32/ia32_transform.c +++ b/ir/be/ia32/ia32_transform.c @@ -521,7 +521,7 @@ static ir_node *gen_binop(ia32_transform_env_t *env, ir_node *node, ir_node *new_op2 = transform_node(env, op2); new_node = func(dbg, irg, block, noreg_gp, noreg_gp, new_op1, new_op2, nomem); - if(func == new_rd_ia32_Mul) { + if(func == new_rd_ia32_IMul) { set_ia32_am_support(new_node, ia32_am_Source); } else { set_ia32_am_support(new_node, ia32_am_Full); @@ -884,18 +884,24 @@ static ir_node *gen_Mulh(ia32_transform_env_t *env, ir_node *node) { ir_node *new_op1 = transform_node(env, op1); ir_node *new_op2 = transform_node(env, op2); ir_node *noreg = ia32_new_NoReg_gp(env->cg); - ir_node *proj_EAX, *proj_EDX, *mulh; + ir_node *proj_EAX, *proj_EDX, *res; ir_mode *mode = get_irn_mode(node); ir_node *in[1]; assert(!mode_is_float(mode) && "Mulh with float not supported"); - mulh = new_rd_ia32_Mulh(dbg, irg, block, noreg, noreg, new_op1, new_op2, new_NoMem()); - set_ia32_commutative(mulh); - set_ia32_am_support(mulh, ia32_am_Source); + if(mode_is_signed(mode)) { + res = new_rd_ia32_IMul1OP(dbg, irg, block, noreg, noreg, new_op1, new_op2, new_NoMem()); + } else { + res = new_rd_ia32_Mul(dbg, irg, block, noreg, noreg, new_op1, new_op2, new_NoMem()); + } - /* imediates are not supported, so no fold_immediate */ - proj_EAX = new_rd_Proj(dbg, irg, block, mulh, mode_Iu, pn_EAX); - proj_EDX = new_rd_Proj(dbg, irg, block, mulh, mode_Iu, pn_EDX); + set_ia32_commutative(res); + set_ia32_am_support(res, ia32_am_Source); + + set_ia32_am_support(res, ia32_am_Source); + + proj_EAX = new_rd_Proj(dbg, irg, block, res, mode_Iu, pn_EAX); + proj_EDX = new_rd_Proj(dbg, irg, block, res, mode_Iu, pn_EDX); /* keep EAX */ in[0] = proj_EAX; @@ -1196,6 +1202,7 @@ static ir_node *generate_DivMod(ia32_transform_env_t *env, ir_node *node, ir_node *in_keep[1]; ir_node *mem, *new_mem; ir_node *projs[pn_DivMod_max]; + ir_node *noreg = ia32_new_NoReg_gp(env->cg); ir_node *new_dividend = transform_node(env, dividend); ir_node *new_divisor = transform_node(env, divisor); @@ -1233,10 +1240,17 @@ static ir_node *generate_DivMod(ia32_transform_env_t *env, ir_node *node, } if(mode_is_signed(mode)) { - res = new_rd_ia32_IDiv(dbg, irg, block, new_dividend, new_divisor, edx_node, new_mem, dm_flav); + res = new_rd_ia32_IDiv(dbg, irg, block, noreg, noreg, new_dividend, edx_node, new_divisor, new_mem, dm_flav); } else { - res = new_rd_ia32_Div(dbg, irg, block, new_dividend, new_divisor, edx_node, new_mem, dm_flav); + res = new_rd_ia32_Div(dbg, irg, block, noreg, noreg, new_dividend, edx_node, new_divisor, new_mem, dm_flav); } + + /* Matze: code can't handle this at the moment... */ +#if 0 + /* set AM support */ + set_ia32_am_support(res, ia32_am_Source); +#endif + set_ia32_n_res(res, 2); /* Only one proj is used -> We must add a second proj and */ @@ -3387,7 +3401,7 @@ static ir_node *gen_Proj_be_AddSP(ia32_transform_env_t *env, ir_node *node) { dbg_info *dbg = get_irn_dbg_info(node); ir_node *pred = get_Proj_pred(node); ir_node *new_pred = transform_node(env, pred); - int proj = get_Proj_proj(node); + long proj = get_Proj_proj(node); if(proj == pn_be_AddSP_res) { ir_node *res = new_rd_Proj(dbg, irg, block, new_pred, mode_Iu, pn_ia32_AddSP_stack); @@ -3407,7 +3421,7 @@ static ir_node *gen_Proj_be_SubSP(ia32_transform_env_t *env, ir_node *node) { dbg_info *dbg = get_irn_dbg_info(node); ir_node *pred = get_Proj_pred(node); ir_node *new_pred = transform_node(env, pred); - int proj = get_Proj_proj(node); + long proj = get_Proj_proj(node); if(proj == pn_be_SubSP_res) { ir_node *res = new_rd_Proj(dbg, irg, block, new_pred, mode_Iu, pn_ia32_AddSP_stack); @@ -3427,7 +3441,7 @@ static ir_node *gen_Proj_Load(ia32_transform_env_t *env, ir_node *node) { dbg_info *dbg = get_irn_dbg_info(node); ir_node *pred = get_Proj_pred(node); ir_node *new_pred = transform_node(env, pred); - int proj = get_Proj_proj(node); + long proj = get_Proj_proj(node); /* renumber the proj */ if(is_ia32_Load(new_pred)) { @@ -3462,7 +3476,7 @@ static ir_node *gen_Proj_DivMod(ia32_transform_env_t *env, ir_node *node) { ir_node *pred = get_Proj_pred(node); ir_node *new_pred = transform_node(env, pred); - int proj = get_Proj_proj(node); + long proj = get_Proj_proj(node); assert(is_ia32_Div(new_pred) || is_ia32_IDiv(new_pred)); @@ -3516,7 +3530,7 @@ static ir_node *gen_Proj_CopyB(ia32_transform_env_t *env, ir_node *node) ir_node *pred = get_Proj_pred(node); ir_node *new_pred = transform_node(env, pred); - int proj = get_Proj_proj(node); + long proj = get_Proj_proj(node); switch(proj) { case pn_CopyB_M_regular: @@ -3545,7 +3559,7 @@ static ir_node *gen_Proj_l_vfdiv(ia32_transform_env_t *env, ir_node *node) ir_node *pred = get_Proj_pred(node); ir_node *new_pred = transform_node(env, pred); - int proj = get_Proj_proj(node); + long proj = get_Proj_proj(node); switch(proj) { case pn_ia32_l_vfdiv_M: @@ -3568,7 +3582,7 @@ static ir_node *gen_Proj_Quot(ia32_transform_env_t *env, ir_node *node) ir_node *pred = get_Proj_pred(node); ir_node *new_pred = transform_node(env, pred); - int proj = get_Proj_proj(node); + long proj = get_Proj_proj(node); switch(proj) { case pn_Quot_M: @@ -3607,11 +3621,30 @@ static ir_node *gen_Proj_tls(ia32_transform_env_t *env, ir_node *node) { return res; } +static ir_node *gen_Proj_be_Call(ia32_transform_env_t *env, ir_node *node) { + ir_graph *irg = env->irg; + dbg_info *dbg = get_irn_dbg_info(node); + ir_node *pred = get_Proj_pred(node); + long proj = get_Proj_proj(node); + ir_mode *mode = get_irn_mode(node); + ir_node *block = transform_node(env, get_nodes_block(node)); + ir_node *new_pred = transform_node(env, pred); + + /* transform call modes to the mode_Iu or mode_E */ + if(mode_is_float(mode)) { + mode = mode_E; + } else if(mode != mode_M) { + mode = mode_Iu; + } + + return new_rd_Proj(dbg, irg, block, new_pred, mode, proj); +} + static ir_node *gen_Proj(ia32_transform_env_t *env, ir_node *node) { ir_graph *irg = env->irg; dbg_info *dbg = get_irn_dbg_info(node); ir_node *pred = get_Proj_pred(node); - int proj = get_Proj_proj(node); + long proj = get_Proj_proj(node); if(is_Store(pred) || be_is_FrameStore(pred)) { if(proj == pn_Store_M) { @@ -3634,6 +3667,8 @@ static ir_node *gen_Proj(ia32_transform_env_t *env, ir_node *node) { return gen_Proj_be_SubSP(env, node); } else if(be_is_AddSP(pred)) { return gen_Proj_be_AddSP(env, node); + } else if(be_is_Call(pred)) { + return gen_Proj_be_Call(env, node); } else if(get_irn_op(pred) == op_Start) { if(proj == pn_Start_X_initial_exec) { ir_node *block = get_nodes_block(pred); -- 2.20.1