From: Matthias Braun Date: Thu, 22 Sep 2011 14:35:56 +0000 (+0200) Subject: convenience function to see if mux gets optimized away X-Git-Url: http://nsz.repo.hu/git/?a=commitdiff_plain;h=e599bf38ff03a4a97e7d14fbf1e8df7a690c57b7;p=libfirm convenience function to see if mux gets optimized away backends can use this to allow all mux nodes which get optimized away by the middleend anyway. This fixes abs handling on sparc. --- diff --git a/ir/be/ia32/bearch_ia32.c b/ir/be/ia32/bearch_ia32.c index 16eb153db..56fa4f30d 100644 --- a/ir/be/ia32/bearch_ia32.c +++ b/ir/be/ia32/bearch_ia32.c @@ -1943,6 +1943,9 @@ static int ia32_is_mux_allowed(ir_node *sel, ir_node *mux_false, { ir_mode *mode; + /* middleend can handle some things */ + if (ir_is_optimizable_mux(sel, mux_false, mux_true)) + return true; /* we can handle Set for all modes and compares */ if (mux_is_set(sel, mux_true, mux_false)) return true; @@ -1967,7 +1970,7 @@ static int ia32_is_mux_allowed(ir_node *sel, ir_node *mux_false, if (get_mode_size_bits(mode) > 32) return false; /* we can handle Abs for all modes and compares (except 64bit) */ - if (ir_mux_is_abs(sel, mux_true, mux_false) != 0) + if (ir_mux_is_abs(sel, mux_false, mux_true) != 0) return true; /* we can't handle MuxF yet */ if (mode_is_float(mode)) diff --git a/ir/be/ia32/ia32_transform.c b/ir/be/ia32/ia32_transform.c index a06ccd384..4c44d4eb0 100644 --- a/ir/be/ia32/ia32_transform.c +++ b/ir/be/ia32/ia32_transform.c @@ -3433,13 +3433,13 @@ static ir_node *gen_Mux(ir_node *node) assert(get_irn_mode(sel) == mode_b); - is_abs = ir_mux_is_abs(sel, mux_true, mux_false); + is_abs = ir_mux_is_abs(sel, mux_false, mux_true); if (is_abs != 0) { if (ia32_mode_needs_gp_reg(mode)) { ir_fprintf(stderr, "Optimisation warning: Integer abs %+F not transformed\n", node); } else { - ir_node *op = ir_get_abs_op(sel, mux_true, mux_false); + ir_node *op = ir_get_abs_op(sel, mux_false, mux_true); return create_float_abs(dbgi, block, op, is_abs < 0, node); } } diff --git a/ir/be/sparc/bearch_sparc.c b/ir/be/sparc/bearch_sparc.c index 113639f1f..39da8dc73 100644 --- a/ir/be/sparc/bearch_sparc.c +++ b/ir/be/sparc/bearch_sparc.c @@ -37,6 +37,7 @@ #include "iroptimize.h" #include "irtools.h" #include "irdump.h" +#include "iropt_t.h" #include "lowering.h" #include "lower_dw.h" #include "lower_alloc.h" @@ -450,18 +451,7 @@ static void sparc_lower_for_target(void) static int sparc_is_mux_allowed(ir_node *sel, ir_node *mux_false, ir_node *mux_true) { - ir_graph *irg = get_irn_irg(sel); - ir_mode *mode = get_irn_mode(mux_true); - - if (get_irg_phase_state(irg) == phase_low) - return false; - - if (!mode_is_int(mode) && !mode_is_reference(mode) && mode != mode_b) - return false; - if (is_Const(mux_true) && is_Const_one(mux_true) && - is_Const(mux_false) && is_Const_null(mux_false)) - return true; - return false; + return ir_is_optimizable_mux(sel, mux_false, mux_true); } /** diff --git a/ir/ir/iropt.c b/ir/ir/iropt.c index ad965bd38..b6958dcc3 100644 --- a/ir/ir/iropt.c +++ b/ir/ir/iropt.c @@ -5567,8 +5567,8 @@ static const ir_node *skip_upconv(const ir_node *node) return node; } -int ir_mux_is_abs(const ir_node *sel, const ir_node *mux_true, - const ir_node *mux_false) +int ir_mux_is_abs(const ir_node *sel, const ir_node *mux_false, + const ir_node *mux_true) { ir_node *cmp_left; ir_node *cmp_right; @@ -5624,13 +5624,50 @@ int ir_mux_is_abs(const ir_node *sel, const ir_node *mux_true, return 0; } -ir_node *ir_get_abs_op(const ir_node *sel, ir_node *mux_true, - ir_node *mux_false) +ir_node *ir_get_abs_op(const ir_node *sel, ir_node *mux_false, + ir_node *mux_true) { ir_node *cmp_left = get_Cmp_left(sel); return cmp_left == skip_upconv(mux_false) ? mux_false : mux_true; } +bool ir_is_optimizable_mux(const ir_node *sel, const ir_node *mux_false, + const ir_node *mux_true) +{ + /* this code should return true each time transform_node_Mux would + * optimize the Mux completely away */ + + ir_mode *mode = get_irn_mode(mux_false); + if (get_mode_arithmetic(mode) == irma_twos_complement + && ir_mux_is_abs(sel, mux_false, mux_true)) + return true; + + if (is_Cmp(sel) && mode_is_int(mode) && is_cmp_equality_zero(sel)) { + const ir_node *cmp_r = get_Cmp_right(sel); + const ir_node *cmp_l = get_Cmp_left(sel); + const ir_node *f = mux_false; + const ir_node *t = mux_true; + + if (is_Const(t) && is_Const_null(t)) { + t = mux_false; + f = mux_true; + } + + if (is_And(cmp_l) && f == cmp_r) { + ir_node *and_r = get_And_right(cmp_l); + ir_node *and_l; + + if (and_r == t && is_single_bit(and_r)) + return true; + and_l = get_And_left(cmp_l); + if (and_l == t && is_single_bit(and_l)) + return true; + } + } + + return false; +} + /** * Optimize a Mux into some simpler cases. */ @@ -5645,11 +5682,11 @@ static ir_node *transform_node_Mux(ir_node *n) /* implement integer abs: abs(x) = x^(x >>s 31) - (x >>s 31) */ if (get_mode_arithmetic(mode) == irma_twos_complement) { - int abs = ir_mux_is_abs(sel, t, f); + int abs = ir_mux_is_abs(sel, f, t); if (abs != 0) { dbg_info *dbgi = get_irn_dbg_info(n); ir_node *block = get_nodes_block(n); - ir_node *op = ir_get_abs_op(sel, t, f); + ir_node *op = ir_get_abs_op(sel, f, t); int bits = get_mode_size_bits(mode); ir_node *shiftconst = new_r_Const_long(irg, mode_Iu, bits-1); ir_node *sext = new_rd_Shrs(dbgi, block, op, shiftconst, mode); diff --git a/ir/ir/iropt_t.h b/ir/ir/iropt_t.h index dd7964888..349d2aedd 100644 --- a/ir/ir/iropt_t.h +++ b/ir/ir/iropt_t.h @@ -136,10 +136,18 @@ bool ir_zero_when_converted(const ir_node *node, ir_mode *dest_mode); */ ir_op_ops *firm_set_default_operations(unsigned code, ir_op_ops *ops); -int ir_mux_is_abs(const ir_node *sel, const ir_node *mux_true, - const ir_node *mux_false); +int ir_mux_is_abs(const ir_node *sel, const ir_node *mux_false, + const ir_node *mux_true); -ir_node *ir_get_abs_op(const ir_node *sel, ir_node *mux_true, - ir_node *mux_false); +ir_node *ir_get_abs_op(const ir_node *sel, ir_node *mux_false, + ir_node *mux_true); + +/** + * return true if the Mux node will be optimized away. This can be used for + * the if-conversion callback. Allowing these Muxes should be always safe, even + * if the backend cannot handle them. + */ +bool ir_is_optimizable_mux(const ir_node *sel, const ir_node *mux_false, + const ir_node *mux_true); #endif