From: Matthias Braun Date: Sun, 29 May 2011 11:33:26 +0000 (+0200) Subject: localopt/lower_dw opt: a==b && c==d => (a^b)|(c^d)==0 X-Git-Url: http://nsz.repo.hu/git/?a=commitdiff_plain;h=82c2309e384c5e9d7e3bbbe5bf2eebb8723b486d;p=libfirm localopt/lower_dw opt: a==b && c==d => (a^b)|(c^d)==0 --- diff --git a/ir/ir/iropt.c b/ir/ir/iropt.c index 541e40694..111d1b32f 100644 --- a/ir/ir/iropt.c +++ b/ir/ir/iropt.c @@ -2951,20 +2951,21 @@ static ir_node *transform_node_And(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) 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); + /* Cmp(a==b) and Cmp(c==d) can be optimized to Cmp((a^b)|(c^d)==0) */ + if (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)) + && values_in_mode(get_irn_mode(a_left), get_irn_mode(b_left))) { + dbg_info *dbgi = get_irn_dbg_info(n); + ir_node *block = get_nodes_block(n); + ir_mode *a_mode = get_irn_mode(a_left); + ir_mode *b_mode = get_irn_mode(b_left); + ir_node *xora = new_rd_Eor(dbgi, block, a_left, a_right, a_mode); + ir_node *xorb = new_rd_Eor(dbgi, block, b_left, b_right, b_mode); + ir_node *conv = new_rd_Conv(dbgi, block, xorb, a_mode); + ir_node *or = new_rd_Or(dbgi, block, xora, conv, a_mode); + ir_graph *irg = get_irn_irg(n); + ir_node *zero = create_zero_const(irg, a_mode); return new_rd_Cmp(dbgi, block, or, zero, ir_relation_equal); } } @@ -4659,20 +4660,19 @@ 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) +static bool is_cmp_unequal(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 { + if (relation == ir_relation_less_greater) + return true; + + if (!mode_is_signed(mode) && is_Const(right) && is_Const_null(right)) return relation == ir_relation_greater; - } + return false; } /** @@ -4712,18 +4712,21 @@ 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); + /* Cmp(a!=b) or Cmp(c!=d) => Cmp((a^b)|(c^d) != 0) */ + if (is_cmp_unequal(a) && is_cmp_unequal(b) + && !mode_is_float(get_irn_mode(a_left)) + && !mode_is_float(get_irn_mode(b_left)) + && values_in_mode(get_irn_mode(a_left), 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 *a_mode = get_irn_mode(a_left); + ir_mode *b_mode = get_irn_mode(b_left); + ir_node *xora = new_rd_Eor(dbgi, block, a_left, a_right, a_mode); + ir_node *xorb = new_rd_Eor(dbgi, block, b_left, b_right, b_mode); + ir_node *conv = new_rd_Conv(dbgi, block, xorb, a_mode); + ir_node *or = new_rd_Or(dbgi, block, xora, conv, a_mode); + ir_node *zero = create_zero_const(irg, a_mode); return new_rd_Cmp(dbgi, block, or, zero, ir_relation_less_greater); } } diff --git a/ir/lower/lower_dw.c b/ir/lower/lower_dw.c index 217bc0f29..484f9da4c 100644 --- a/ir/lower/lower_dw.c +++ b/ir/lower/lower_dw.c @@ -1168,7 +1168,7 @@ static void lower_Not(ir_node *node, ir_mode *mode) ir_set_dw_lowered(node, res_low, res_high); } -static bool is_equality_cmp_0(const ir_node *node) +static bool is_equality_cmp(const ir_node *node) { ir_relation relation = get_Cmp_relation(node); ir_node *left = get_Cmp_left(node); @@ -1178,10 +1178,11 @@ static bool is_equality_cmp_0(const ir_node *node) /* this probably makes no sense if unordered is involved */ assert(!mode_is_float(mode)); + if (relation == ir_relation_equal || relation == ir_relation_less_greater) + return true; + 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 { @@ -1272,12 +1273,16 @@ static void lower_Cond(ir_node *node, ir_mode *mode) dbg = get_irn_dbg_info(sel); relation = get_Cmp_relation(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); - ir_node *high = new_r_Conv(block, lentry->high_word, mode); - ir_node *ornode = new_rd_Or(dbg, block, low, high, mode); + if (is_equality_cmp(sel)) { + /* x ==/!= y ==> or(x_low^y_low,x_high^y_high) ==/!= 0 */ + ir_mode *mode = env->low_unsigned; + ir_node *low_left = new_rd_Conv(dbg, block, lentry->low_word, mode); + ir_node *high_left = new_rd_Conv(dbg, block, lentry->high_word, mode); + ir_node *low_right = new_rd_Conv(dbg, block, rentry->low_word, mode); + ir_node *high_right = new_rd_Conv(dbg, block, rentry->high_word, mode); + ir_node *xor_low = new_rd_Eor(dbg, block, low_left, low_right, mode); + ir_node *xor_high = new_rd_Eor(dbg, block, high_left, high_right, mode); + ir_node *ornode = new_rd_Or(dbg, block, xor_low, xor_high, mode); ir_node *cmp = new_rd_Cmp(dbg, block, ornode, new_r_Const_long(irg, mode, 0), relation); set_Cond_selector(node, cmp); return; @@ -1530,13 +1535,17 @@ static void lower_Cmp(ir_node *cmp, ir_mode *m) dbg = get_irn_dbg_info(cmp); /* easy case for x ==/!= 0 (see lower_Cond for details) */ - 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); - ir_node *high = new_r_Conv(block, lentry->high_word, mode); - ir_node *ornode = new_rd_Or(dbg, block, low, high, mode); - ir_node *new_cmp = new_rd_Cmp(dbg, block, ornode, new_r_Const_long(irg, mode, 0), relation); + if (is_equality_cmp(cmp)) { + ir_graph *irg = get_irn_irg(cmp); + ir_mode *mode = env->low_unsigned; + ir_node *low_left = new_rd_Conv(dbg, block, lentry->low_word, mode); + ir_node *high_left = new_rd_Conv(dbg, block, lentry->high_word, mode); + ir_node *low_right = new_rd_Conv(dbg, block, rentry->low_word, mode); + ir_node *high_right = new_rd_Conv(dbg, block, rentry->high_word, mode); + ir_node *xor_low = new_rd_Eor(dbg, block, low_left, low_right, mode); + ir_node *xor_high = new_rd_Eor(dbg, block, high_left, high_right, mode); + ir_node *ornode = new_rd_Or(dbg, block, xor_low, xor_high, mode); + ir_node *new_cmp = new_rd_Cmp(dbg, block, ornode, new_r_Const_long(irg, mode, 0), relation); exchange(cmp, new_cmp); return; }