From cbe46be4d19a25b7d1aefb4ebe55bac95206a3e3 Mon Sep 17 00:00:00 2001 From: Matthias Braun Date: Sat, 5 Nov 2011 12:13:00 +0100 Subject: [PATCH] Set optimisations moved to transform_node_Mux they were in lower_mode_b but just generically apply to all Mux(c, 0, 1) --- ir/ir/iropt.c | 91 ++++++++++++++++++++++++++++++++++++++++- ir/lower/lower_mode_b.c | 60 +-------------------------- 2 files changed, 92 insertions(+), 59 deletions(-) diff --git a/ir/ir/iropt.c b/ir/ir/iropt.c index 2ca74a4ab..b945b6e9f 100644 --- a/ir/ir/iropt.c +++ b/ir/ir/iropt.c @@ -4685,7 +4685,7 @@ is_bittest: { } else { dbg_info *dbgi = get_irn_dbg_info(n); ir_node *block = get_nodes_block(n); - ir_node *notn = new_rd_Not(dbgi, block, cond, mode_b); + ir_node *notn = new_rd_Not(dbgi, block, cond, mode_b); return notn; } } @@ -5890,6 +5890,89 @@ bool ir_is_optimizable_mux(const ir_node *sel, const ir_node *mux_false, return false; } +/** + * Optimize a Mux(c, 0, 1) node (sometimes called a "set" instruction) + */ +static ir_node *transform_Mux_set(ir_node *n) +{ + ir_node *cond = get_Mux_sel(n); + ir_mode *dest_mode; + ir_mode *mode; + ir_node *left; + ir_node *right; + ir_relation relation; + bool need_not; + dbg_info *dbgi; + ir_node *block; + ir_graph *irg; + ir_node *a; + ir_node *b; + unsigned bits; + ir_tarval *tv; + ir_node *shift_cnt; + ir_node *res; + + if (!is_Cmp(cond)) + return n; + left = get_Cmp_left(cond); + mode = get_irn_mode(left); + if (!mode_is_int(mode) && !mode_is_reference(mode)) + return n; + dest_mode = get_irn_mode(n); + right = get_Cmp_right(cond); + relation = get_Cmp_relation(cond) & ~ir_relation_unordered; + if (get_mode_size_bits(mode) >= get_mode_size_bits(dest_mode) + && (!mode_is_signed(mode) || !is_Const(right) || !is_Const_null(right))) + return n; + + need_not = false; + switch (relation) { + case ir_relation_less: + /* a < b -> (a - b) >> 31 */ + a = left; + b = right; + break; + case ir_relation_less_equal: + /* a <= b -> ~(a - b) >> 31 */ + a = right; + b = left; + need_not = true; + break; + case ir_relation_greater: + /* a > b -> (b - a) >> 31 */ + a = right; + b = left; + break; + case ir_relation_greater_equal: + /* a >= b -> ~(a - b) >> 31 */ + a = left; + b = right; + need_not = true; + break; + default: + return n; + } + + dbgi = get_irn_dbg_info(n); + block = get_nodes_block(n); + irg = get_irn_irg(block); + bits = get_mode_size_bits(dest_mode); + tv = new_tarval_from_long(bits-1, mode_Iu); + shift_cnt = new_rd_Const(dbgi, irg, tv); + + if (mode != dest_mode) { + a = new_rd_Conv(dbgi, block, a, dest_mode); + b = new_rd_Conv(dbgi, block, b, dest_mode); + } + + res = new_rd_Sub(dbgi, block, a, b, dest_mode); + if (need_not) { + res = new_rd_Not(dbgi, block, res, dest_mode); + } + res = new_rd_Shr(dbgi, block, res, shift_cnt, dest_mode); + return res; +} + /** * Optimize a Mux into some simpler cases. */ @@ -5941,6 +6024,12 @@ static ir_node *transform_node_Mux(ir_node *n) n = new_rd_Mux(get_irn_dbg_info(n), get_nodes_block(n), sel, f, t, mode); } + if (is_Const(f) && is_Const_null(f) && is_Const(t) && is_Const_one(t)) { + n = transform_Mux_set(n); + if (n != oldn) + return n; + } + /* the following optimisations create new mode_b nodes, so only do them * before mode_b lowering */ if (!is_irg_state(irg, IR_GRAPH_STATE_MODEB_LOWERED)) { diff --git a/ir/lower/lower_mode_b.c b/ir/lower/lower_mode_b.c index 5030aba80..12b3cd24c 100644 --- a/ir/lower/lower_mode_b.c +++ b/ir/lower/lower_mode_b.c @@ -195,65 +195,9 @@ static ir_node *lower_node(ir_node *node) break; } - case iro_Cmp: { - ir_node *left = get_Cmp_left(node); - ir_node *right = get_Cmp_right(node); - ir_mode *cmp_mode = get_irn_mode(left); - ir_relation relation = get_Cmp_relation(node); - - if ((mode_is_int(cmp_mode) || mode_is_reference(cmp_mode)) && - (get_mode_size_bits(cmp_mode) < get_mode_size_bits(mode) || - (mode_is_signed(cmp_mode) && is_Const(right) && is_Const_null(right) && relation != ir_relation_greater))) { - int need_not = 0; - ir_node *a = NULL; - ir_node *b = NULL; - int bits; - ir_tarval *tv; - ir_node *shift_cnt; - - if (relation == ir_relation_less) { - /* a < b -> (a - b) >> 31 */ - a = left; - b = right; - } else if (relation == ir_relation_less_equal) { - /* a <= b -> ~(a - b) >> 31 */ - a = right; - b = left; - need_not = 1; - } else if (relation == ir_relation_greater) { - /* a > b -> (b - a) >> 31 */ - a = right; - b = left; - } else if (relation == ir_relation_greater_equal) { - /* a >= b -> ~(a - b) >> 31 */ - a = left; - b = right; - need_not = 1; - } else { - goto synth_zero_one; - } - - bits = get_mode_size_bits(mode); - tv = new_tarval_from_long(bits-1, mode_Iu); - shift_cnt = new_rd_Const(dbgi, irg, tv); - - if (cmp_mode != mode) { - a = new_rd_Conv(dbgi, block, a, mode); - b = new_rd_Conv(dbgi, block, b, mode); - } - - res = new_rd_Sub(dbgi, block, a, b, mode); - if (need_not) { - res = new_rd_Not(dbgi, block, res, mode); - } - res = new_rd_Shr(dbgi, block, res, shift_cnt, mode); - } else { - /* synthesize the 0/1 value */ -synth_zero_one: - res = create_cond_set(node, mode); - } + case iro_Cmp: + res = create_cond_set(node, mode); break; - } case iro_Const: { ir_tarval *tv = get_Const_tarval(node); -- 2.20.1