convenience function to see if mux gets optimized away
authorMatthias Braun <matze@braunis.de>
Thu, 22 Sep 2011 14:35:56 +0000 (16:35 +0200)
committerMatthias Braun <matze@braunis.de>
Thu, 22 Sep 2011 14:49:06 +0000 (16:49 +0200)
backends can use this to allow all mux nodes which get optimized away by
the middleend anyway.
This fixes abs handling on sparc.

ir/be/ia32/bearch_ia32.c
ir/be/ia32/ia32_transform.c
ir/be/sparc/bearch_sparc.c
ir/ir/iropt.c
ir/ir/iropt_t.h

index 16eb153..56fa4f3 100644 (file)
@@ -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))
index a06ccd3..4c44d4e 100644 (file)
@@ -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);
                }
        }
index 113639f..39da8dc 100644 (file)
@@ -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);
 }
 
 /**
index ad965bd..b6958dc 100644 (file)
@@ -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);
index dd79648..349d2ae 100644 (file)
@@ -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