From 128d686096cf3f9945d31b6bc9d36bd96ff76955 Mon Sep 17 00:00:00 2001 From: Matthias Braun Date: Wed, 13 Apr 2011 12:26:08 +0200 Subject: [PATCH] fix incorrect and(Cmp(a,0),Cmp(b,0)) localopt --- include/libfirm/iropt.h | 7 ---- ir/ir/iropt.c | 91 +++++++++++++++++++++++------------------ ir/lower/lower_dw.c | 25 ++++++++++- 3 files changed, 74 insertions(+), 49 deletions(-) diff --git a/include/libfirm/iropt.h b/include/libfirm/iropt.h index 9e25788c4..9d1f1a116 100644 --- a/include/libfirm/iropt.h +++ b/include/libfirm/iropt.h @@ -103,13 +103,6 @@ FIRM_API int ir_is_negated_value(const ir_node *a, const ir_node *b); FIRM_API ir_relation ir_get_possible_cmp_relations(const ir_node *left, const ir_node *right); -/** - * tests whether a given Cmp node is a non-floating point equal/not-equal test with 0 - * (this is a bit tricky because it has to catch x!=0 for the signed case and - * x>0 for the unsigned case) - */ -FIRM_API int ir_is_equality_cmp_0(const ir_node *node); - #include "end.h" #endif diff --git a/ir/ir/iropt.c b/ir/ir/iropt.c index ab5b63ac4..03eeb57ad 100644 --- a/ir/ir/iropt.c +++ b/ir/ir/iropt.c @@ -3107,27 +3107,6 @@ static ir_node *transform_bitwise_distributive(ir_node *n, return n; } -int ir_is_equality_cmp_0(const ir_node *node) -{ - ir_relation relation = get_Cmp_relation(node); - ir_node *left = get_Cmp_left(node); - ir_node *right = get_Cmp_right(node); - ir_mode *mode = get_irn_mode(left); - - /* this probably makes no sense if unordered is involved */ - assert(!mode_is_float(mode)); - - if (!is_Const(right) || !is_Const_null(right)) - return false; - if (relation == ir_relation_equal) - return true; - if (mode_is_signed(mode)) { - return relation == ir_relation_less_greater; - } else { - return relation == ir_relation_greater; - } -} - /** * Create a 0 constant of given mode. */ @@ -3151,33 +3130,35 @@ static ir_node *transform_node_And(ir_node *n) vrp_attr *a_vrp, *b_vrp; if (is_Cmp(a) && is_Cmp(b)) { - ir_node *a_left = get_Cmp_left(a); - ir_node *a_right = get_Cmp_left(a); - ir_node *b_left = get_Cmp_left(b); - ir_node *b_right = get_Cmp_right(b); + ir_node *a_left = get_Cmp_left(a); + ir_node *a_right = get_Cmp_right(a); + ir_node *b_left = get_Cmp_left(b); + ir_node *b_right = get_Cmp_right(b); + ir_relation a_relation = get_Cmp_relation(a); + ir_relation b_relation = get_Cmp_relation(b); /* we can combine the relations of two compares with the same * operands */ if (a_left == b_left && b_left == b_right) { dbg_info *dbgi = get_irn_dbg_info(n); ir_node *block = get_nodes_block(n); - ir_relation a_relation = get_Cmp_relation(a); - ir_relation b_relation = get_Cmp_relation(b); ir_relation new_relation = a_relation & b_relation; return new_rd_Cmp(dbgi, block, a_left, a_right, new_relation); } - /* Cmp(a, 0) and Cmp(b,0) can be optimized to Cmp(a|b, 0) */ - if (ir_is_equality_cmp_0(a) && ir_is_equality_cmp_0(b) - && (get_Cmp_relation(a) & ir_relation_equal) == (get_Cmp_relation(b) & ir_relation_equal)) { - dbg_info *dbgi = get_irn_dbg_info(n); - ir_node *block = get_nodes_block(n); - ir_relation relation = get_Cmp_relation(a); - ir_mode *mode = get_irn_mode(a_left); - ir_node *n_b_left = get_irn_mode(b_left) != mode ? - new_rd_Conv(dbgi, block, b_left, mode) : b_left; - ir_node *or = new_rd_Or(dbgi, block, a_left, n_b_left, mode); - ir_graph *irg = get_irn_irg(n); - ir_node *zero = create_zero_const(irg, mode); - return new_rd_Cmp(dbgi, block, or, zero, relation); + /* Cmp(a==0) and Cmp(b==0) can be optimized to Cmp(a|b==0) */ + if (is_Const(a_right) && is_Const_null(a_right) + && is_Const(b_right) && is_Const_null(b_right) + && a_relation == b_relation && a_relation == ir_relation_equal + && !mode_is_float(get_irn_mode(a_left)) + && !mode_is_float(get_irn_mode(b_left))) { + dbg_info *dbgi = get_irn_dbg_info(n); + ir_node *block = get_nodes_block(n); + ir_mode *mode = get_irn_mode(a_left); + ir_node *n_b_left = get_irn_mode(b_left) != mode ? + new_rd_Conv(dbgi, block, b_left, mode) : b_left; + ir_node *or = new_rd_Or(dbgi, block, a_left, n_b_left, mode); + ir_graph *irg = get_irn_irg(n); + ir_node *zero = create_zero_const(irg, mode); + return new_rd_Cmp(dbgi, block, or, zero, ir_relation_equal); } } @@ -4821,6 +4802,22 @@ static ir_node *transform_node_Or_Rotl(ir_node *irn_or) return n; } /* transform_node_Or_Rotl */ +static bool is_cmp_unequal_zero(const ir_node *node) +{ + ir_relation relation = get_Cmp_relation(node); + ir_node *left = get_Cmp_left(node); + ir_node *right = get_Cmp_right(node); + ir_mode *mode = get_irn_mode(left); + + if (!is_Const(right) || !is_Const_null(right)) + return false; + if (mode_is_signed(mode)) { + return relation == ir_relation_less_greater; + } else { + return relation == ir_relation_greater; + } +} + /** * Transform an Or. */ @@ -4858,6 +4855,20 @@ static ir_node *transform_node_Or(ir_node *n) ir_relation new_relation = a_relation | b_relation; return new_rd_Cmp(dbgi, block, a_left, a_right, new_relation); } + /* Cmp(a!=0) or Cmp(b!=0) => Cmp(a|b != 0) */ + if (is_cmp_unequal_zero(a) && is_cmp_unequal_zero(b) + && !mode_is_float(get_irn_mode(a_left)) + && !mode_is_float(get_irn_mode(b_left))) { + ir_graph *irg = get_irn_irg(n); + dbg_info *dbgi = get_irn_dbg_info(n); + ir_node *block = get_nodes_block(n); + ir_mode *mode = get_irn_mode(a_left); + ir_node *n_b_left = get_irn_mode(b_left) != mode ? + new_rd_Conv(dbgi, block, b_left, mode) : b_left; + ir_node *or = new_rd_Or(dbgi, block, a_left, n_b_left, mode); + ir_node *zero = create_zero_const(irg, mode); + return new_rd_Cmp(dbgi, block, or, zero, ir_relation_less_greater); + } } mode = get_irn_mode(n); diff --git a/ir/lower/lower_dw.c b/ir/lower/lower_dw.c index 4c4ab331e..ca5b0961c 100644 --- a/ir/lower/lower_dw.c +++ b/ir/lower/lower_dw.c @@ -982,6 +982,27 @@ static void lower_Not(ir_node *node, ir_mode *mode, lower_env_t *env) set_lowered(env, node, res_low, res_high); } +static bool is_equality_cmp_0(const ir_node *node) +{ + ir_relation relation = get_Cmp_relation(node); + ir_node *left = get_Cmp_left(node); + ir_node *right = get_Cmp_right(node); + ir_mode *mode = get_irn_mode(left); + + /* this probably makes no sense if unordered is involved */ + assert(!mode_is_float(mode)); + + if (!is_Const(right) || !is_Const_null(right)) + return false; + if (relation == ir_relation_equal) + return true; + if (mode_is_signed(mode)) { + return relation == ir_relation_less_greater; + } else { + return relation == ir_relation_greater; + } +} + /** * Translate a Cond. */ @@ -1052,7 +1073,7 @@ static void lower_Cond(ir_node *node, ir_mode *mode, lower_env_t *env) dbg = get_irn_dbg_info(sel); relation = get_Cmp_relation(sel); - if (ir_is_equality_cmp_0(sel)) { + if (is_equality_cmp_0(sel)) { /* x ==/!= 0 ==> or(low,high) ==/!= 0 */ ir_mode *mode = env->low_unsigned; ir_node *low = new_r_Conv(block, lentry->low_word, mode); @@ -1320,7 +1341,7 @@ static void lower_Cmp(ir_node *cmp, ir_mode *m, lower_env_t *env) dbg = get_irn_dbg_info(cmp); /* easy case for x ==/!= 0 (see lower_Cond for details) */ - if (ir_is_equality_cmp_0(cmp)) { + if (is_equality_cmp_0(cmp)) { ir_graph *irg = get_irn_irg(cmp); ir_mode *mode = env->low_unsigned; ir_node *low = new_r_Conv(block, lentry->low_word, mode); -- 2.20.1