{
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;
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))
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);
}
}
#include "iroptimize.h"
#include "irtools.h"
#include "irdump.h"
+#include "iropt_t.h"
#include "lowering.h"
#include "lower_dw.h"
#include "lower_alloc.h"
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);
}
/**
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;
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.
*/
/* 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);
*/
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