From fe3c81727251945fa818d22165b3afc33ea2019f Mon Sep 17 00:00:00 2001 From: Matthias Braun Date: Tue, 2 Oct 2007 07:50:01 +0000 Subject: [PATCH] - workaround and document ShrD/ShlD problems correctly this time - some cleanups [r16030] --- ir/be/ia32/ia32_new_nodes.c | 19 +-------------- ir/be/ia32/ia32_new_nodes.h | 10 -------- ir/be/ia32/ia32_nodes_attr.h | 5 ---- ir/be/ia32/ia32_spec.pl | 47 ++++++++++++++---------------------- ir/be/ia32/ia32_transform.c | 10 ++++---- 5 files changed, 24 insertions(+), 67 deletions(-) diff --git a/ir/be/ia32/ia32_new_nodes.c b/ir/be/ia32/ia32_new_nodes.c index c067ac37c..f0e77c65a 100644 --- a/ir/be/ia32/ia32_new_nodes.c +++ b/ir/be/ia32/ia32_new_nodes.c @@ -791,22 +791,6 @@ int get_ia32_n_res(const ir_node *node) { return ARR_LEN(attr->slots); } -/** - * Returns the flavour of an ia32 node, - */ -ia32_op_flavour_t get_ia32_flavour(const ir_node *node) { - const ia32_attr_t *attr = get_ia32_attr_const(node); - return attr->data.op_flav; -} - -/** - * Sets the flavour of an ia32 node to flavour_Div/Mod/DivMod/Mul/Mulh. - */ -void set_ia32_flavour(ir_node *node, ia32_op_flavour_t op_flav) { - ia32_attr_t *attr = get_ia32_attr(node); - attr->data.op_flav = op_flav; -} - /** * Returns the projnum code. */ @@ -1118,8 +1102,7 @@ int ia32_compare_attr(const ia32_attr_t *a, const ia32_attr_t *b) { if(a->pn_code != b->pn_code) return 1; - if (a->data.tp != b->data.tp - || a->data.op_flav != b->data.op_flav) + if (a->data.tp != b->data.tp) return 1; if (a->data.except_label != b->data.except_label) diff --git a/ir/be/ia32/ia32_new_nodes.h b/ir/be/ia32/ia32_new_nodes.h index c6d684355..98a2d7b85 100644 --- a/ir/be/ia32/ia32_new_nodes.h +++ b/ir/be/ia32/ia32_new_nodes.h @@ -307,16 +307,6 @@ const arch_register_t *get_ia32_out_reg(const ir_node *node, int pos); */ int get_ia32_n_res(const ir_node *node); -/** - * Returns the flavour of an ia32 node, - */ -ia32_op_flavour_t get_ia32_flavour(const ir_node *node); - -/** - * Sets the flavour of an ia32 node to flavour_Div/Mod/DivMod/Mul/Mulh. - */ -void set_ia32_flavour(ir_node *node, ia32_op_flavour_t op_flav); - /** * Returns the projnum code. */ diff --git a/ir/be/ia32/ia32_nodes_attr.h b/ir/be/ia32/ia32_nodes_attr.h index 372df0a61..0a1d15a58 100644 --- a/ir/be/ia32/ia32_nodes_attr.h +++ b/ir/be/ia32/ia32_nodes_attr.h @@ -33,9 +33,6 @@ #include "../bemachine.h" #include "irnode_t.h" -typedef enum { flavour_Div = 1, flavour_Mod, flavour_DivMod } ia32_op_flavour_t; -typedef enum { pn_EAX, pn_EDX } pn_ia32_Register; - typedef enum { ia32_Normal, ia32_AddrModeD, @@ -94,8 +91,6 @@ struct ia32_attr_t { unsigned use_frame:1; /**< Indicates whether the operation uses the frame pointer or not. */ unsigned except_label:1; /**< Set if this node needs a label because of possible exception. */ - ia32_op_flavour_t op_flav:2;/**< Flavour of an op (flavour_Div/Mod/DivMod). */ - unsigned is_commutative:1; /**< Indicates whether op is commutative or not. */ unsigned got_lea:1; /**< Indicates whether or not this node already consumed a LEA. */ diff --git a/ir/be/ia32/ia32_spec.pl b/ir/be/ia32/ia32_spec.pl index 7dab8bd4b..fff766033 100644 --- a/ir/be/ia32/ia32_spec.pl +++ b/ir/be/ia32/ia32_spec.pl @@ -609,9 +609,7 @@ IDiv => { reg_req => { in => [ "gp", "gp", "none", "eax", "edx", "gp" ], out => [ "eax", "edx", "none" ] }, ins => [ "base", "index", "mem", "left_low", "left_high", "right" ], outs => [ "div_res", "mod_res", "M" ], - attr => "ia32_op_flavour_t dm_flav", am => "source,ternary", - init_attr => "attr->data.op_flav = dm_flav;", emit => ". idiv%M %unop5", latency => 25, units => [ "GP" ], @@ -624,9 +622,7 @@ Div => { reg_req => { in => [ "gp", "gp", "none", "eax", "edx", "gp" ], out => [ "eax", "edx", "none" ] }, ins => [ "base", "index", "mem", "left_low", "left_high", "right" ], outs => [ "div_res", "mod_res", "M" ], - attr => "ia32_op_flavour_t dm_flav", am => "source,ternary", - init_attr => "attr->data.op_flav = dm_flav;", emit => ". div%M %unop5", latency => 25, units => [ "GP" ], @@ -661,23 +657,13 @@ l_ShlDep => { }, ShlD => { - # FIXME: WHY? the right requirement is in_r3 !in_r5, especially this is the same as in Shl - # - # Out requirements is: different from all in - # This is because, out must be different from LowPart and ShiftCount. - # We could say "!ecx !in_r4" but it can occur, that all values live through - # this Shift and the only value dying is the ShiftCount. Then there would be a - # register missing, as result must not be ecx and all other registers are - # occupied. What we should write is "!in_r4 !in_r5", but this is not supported - # (and probably never will). So we create artificial interferences of the result - # with all inputs, so the spiller can always assure a free register. - # reg_req => { in => [ "gp", "gp", "gp", "gp", "ecx", "none" ], out => [ "!in" ] }, - irn_flags => "R", + # see ShrD about the strange out constraint reg_req => { in => [ "gp", "gp", "ecx" ], out => [ "!in" ] }, ins => [ "left_high", "left_low", "right" ], am => "dest,ternary", - emit => '. shld%M %SB2, %S1, %S0', + emit => ". shld%M %SB2, %S1, %S0\n". + ". movl %S0, %D0", latency => 6, units => [ "GP" ], mode => $mode_gp, @@ -717,23 +703,26 @@ l_ShrDep => { }, ShrD => { - # FIXME: WHY? the right requirement is in_r3 !in_r5, especially this is the same as in Shr + # What's going on with the out constraint here? We would like to write + # "in_r2" and be done. However in firm we only support should_be_same + # constraints at the moment. Which means they could be non-fullfilled in + # some cases. Now when all values happen to live through the node, out + # is ecx and in_r2 not ecx, then we're screwed. Because in this case we + # need a 4th Register. # - # Out requirements is: different from all in - # This is because, out must be different from LowPart and ShiftCount. - # We could say "!ecx !in_r4" but it can occur, that all values live through - # this Shift and the only value dying is the ShiftCount. Then there would be a - # register missing, as result must not be ecx and all other registers are - # occupied. What we should write is "!in_r4 !in_r5", but this is not supported - # (and probably never will). So we create artificial interferences of the result - # with all inputs, so the spiller can always assure a free register. - # reg_req => { in => [ "gp", "gp", "gp", "gp", "ecx", "none" ], out => [ "!in" ] }, - + # The best solution for this is extending the register allocator to support + # must_be_same constraints which create a copy when the in_r2 value + # lives through (this ensures that we have the 4th register in the cases + # when we need it and can always fix the situation). + # + # For now I'm doing this ultra ugly !in hack which allocates 4 registers + # and creates an extra mov irn_flags => "R", reg_req => { in => [ "gp", "gp", "ecx" ], out => [ "!in" ] }, ins => [ "left_high", "left_low", "right" ], am => "dest,ternary", - emit => '. shrd%M %SB2, %S1, %S0', + emit => ". shrd%M %SB2, %S1, %S0\n". + ". movl %S0, %D0", latency => 6, units => [ "GP" ], mode => $mode_gp, diff --git a/ir/be/ia32/ia32_transform.c b/ir/be/ia32/ia32_transform.c index a1ec055f3..4a9d264f2 100644 --- a/ir/be/ia32/ia32_transform.c +++ b/ir/be/ia32/ia32_transform.c @@ -1063,7 +1063,7 @@ static ir_node *gen_Mulh(ir_node *node) { set_ia32_commutative(res); - proj_EDX = new_rd_Proj(dbgi, irg, block, res, mode_Iu, pn_EDX); + proj_EDX = new_rd_Proj(dbgi, irg, block, res, mode_Iu, pn_ia32_IMul1OP_EDX); return proj_EDX; } @@ -1162,7 +1162,7 @@ static ir_node *gen_Sub(ir_node *node) { return gen_binop(node, op1, op2, new_rd_ia32_Sub, 0); } - +typedef enum { flavour_Div = 1, flavour_Mod, flavour_DivMod } ia32_op_flavour_t; /** * Generates an ia32 DivMod with additional infrastructure for the @@ -1229,10 +1229,10 @@ static ir_node *generate_DivMod(ir_node *node, ir_node *dividend, if (mode_is_signed(mode)) { res = new_rd_ia32_IDiv(dbgi, irg, block, noreg, noreg, new_mem, - new_dividend, sign_extension, new_divisor, dm_flav); + new_dividend, sign_extension, new_divisor); } else { - res = new_rd_ia32_Div(dbgi, irg, block, noreg, noreg, new_mem, new_dividend, - sign_extension, new_divisor, dm_flav); + res = new_rd_ia32_Div(dbgi, irg, block, noreg, noreg, new_mem, + new_dividend, sign_extension, new_divisor); } set_ia32_exc_label(res, has_exc); -- 2.20.1