Commit e599bf38 authored by Matthias Braun's avatar Matthias Braun
Browse files

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.
parent 4483fd16
......@@ -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))
......
......@@ -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);
}
}
......
......@@ -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);
}
/**
......
......@@ -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);
......
......@@ -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
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment