Commit 3f57d89f authored by Matthias Braun's avatar Matthias Braun
Browse files

remove Abs node, backends can match the abs patterns themselfes

[r27968]
parent 5e24c17a
......@@ -96,7 +96,6 @@ enum firmstat_optimizations_t {
FS_OPT_MUX_TRANSFORM, /**< Mux(t ==/!= f, t, f) = f/t, Mux(t ==/!= 0, -t, t) = -t/t */
FS_OPT_MUX_TO_MIN, /**< Mux(a < b, a, b) = Min(a,b) */
FS_OPT_MUX_TO_MAX, /**< Mux(a > b, a, b) = Max(a,b) */
FS_OPT_MUX_TO_ABS, /**< Mux(a > 0, a, -a) = Abs(a) */
FS_OPT_MUX_TO_BITOP, /**< Mux((a & 2^x) ==/!= 0, 2^x, 0) = (a & 2^x) (xor 2^x) */
FS_OPT_IDEM_UNARY, /**< Idempotent unary operation */
FS_OPT_MINUS_NOT, /**< -(~x) = x + 1 */
......@@ -104,7 +103,6 @@ enum firmstat_optimizations_t {
FS_OPT_NOT_PLUS_1, /**< ~x + 1 = -x */
FS_OPT_ADD_X_NOT_X, /**< ~x + x = -1 */
FS_OPT_FP_INV_MUL, /**< x / y = x * (1.0/y) */
FS_OPT_ABS_MINUS_X, /**< Abs(-x) = Abs(x) */
FS_OPT_CONST_PHI, /**< Constant evaluation on Phi */
FS_OPT_PREDICATE, /**< Predicate optimization */
FS_OPT_DEMORGAN, /**< optimization using DeMorgan's law */
......
......@@ -272,7 +272,6 @@
* ir_node *new_DivMod (ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode, op_pin_state state);
* ir_node *new_Div (ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode, op_pin_state state);
* ir_node *new_Mod (ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode, op_pin_state state;
* ir_node *new_Abs (ir_node *op, ir_mode *mode);
* ir_node *new_And (ir_node *op1, ir_node *op2, ir_mode *mode);
* ir_node *new_Or (ir_node *op1, ir_node *op2, ir_mode *mode);
* ir_node *new_Eor (ir_node *op1, ir_node *op2, ir_mode *mode);
......@@ -720,11 +719,6 @@
*
* Trivial.
*
* ir_node *new_Abs (ir_node *op, ir_mode *mode)
* ---------------------------------------------
*
* Trivial.
*
* ir_node *new_And (ir_node *op1, ir_node *op2, ir_mode *mode)
* ------------------------------------------------------------
*
......@@ -1555,16 +1549,6 @@ FIRM_API ir_node *new_rd_Mod(dbg_info *db, ir_node *block, ir_node *memop,
ir_node *op1, ir_node *op2, ir_mode *mode,
op_pin_state state);
/** Constructor for a Abs node.
*
* @param *db A pointer for debug information.
* @param *block The IR block the node belongs to.
* @param *op The operand
* @param *mode The mode of the operands and the result.
*/
FIRM_API ir_node *new_rd_Abs(dbg_info *db, ir_node *block, ir_node *op,
ir_mode *mode);
/** Constructor for a And node.
*
* @param *db A pointer for debug information.
......@@ -2312,14 +2296,6 @@ FIRM_API ir_node *new_r_Mod(ir_node *block, ir_node *memop,
ir_node *op1, ir_node *op2, ir_mode *mode,
op_pin_state state);
/** Constructor for a Abs node.
*
* @param *block The IR block the node belongs to.
* @param *op The operand
* @param *mode The mode of the operands and the result.
*/
FIRM_API ir_node *new_r_Abs(ir_node *block, ir_node *op, ir_mode *mode);
/** Constructor for a And node.
*
* @param *block The IR block the node belongs to.
......@@ -3077,16 +3053,6 @@ FIRM_API ir_node *new_d_Mod(dbg_info *db, ir_node *memop,
ir_node *op1, ir_node *op2, ir_mode *mode,
op_pin_state state);
/** Constructor for a Abs node.
*
* Adds the node to the block in current_ir_block.
*
* @param *db A pointer for debug information.
* @param *op The operand
* @param *mode The mode of the operands and the result.
*/
FIRM_API ir_node *new_d_Abs(dbg_info *db, ir_node *op, ir_mode *mode);
/** Constructor for a And node.
*
* Adds the node to the block in current_ir_block.
......@@ -3833,15 +3799,6 @@ FIRM_API ir_node *new_DivRL(ir_node *memop, ir_node *op1, ir_node *op2,
FIRM_API ir_node *new_Mod(ir_node *memop, ir_node *op1, ir_node *op2,
ir_mode *mode, op_pin_state state);
/** Constructor for a Abs node.
*
* Adds the node to the block in current_ir_block.
*
* @param *op The operand
* @param *mode The mode of the operands and the result.
*/
FIRM_API ir_node *new_Abs(ir_node *op, ir_mode *mode);
/** Constructor for a And node.
*
* Adds the node to the block in current_ir_block.
......
......@@ -198,8 +198,6 @@ typedef enum {
/** Return true of the node is a ASM node. */
FIRM_API int is_ASM(const ir_node *node);
/** Return true of the node is a Abs node. */
FIRM_API int is_Abs(const ir_node *node);
/** Return true of the node is a Add node. */
FIRM_API int is_Add(const ir_node *node);
/** Return true of the node is a Alloc node. */
......@@ -321,9 +319,6 @@ FIRM_API void set_ASM_clobbers(ir_node *node, ident** clobbers);
FIRM_API ident* get_ASM_text(const ir_node *node);
FIRM_API void set_ASM_text(ir_node *node, ident* text);
FIRM_API ir_node *get_Abs_op(const ir_node *node);
void set_Abs_op(ir_node *node, ir_node *op);
FIRM_API ir_node *get_Add_left(const ir_node *node);
void set_Add_left(ir_node *node, ir_node *left);
FIRM_API ir_node *get_Add_right(const ir_node *node);
......
......@@ -6,7 +6,6 @@
/** The opcodes of the libFirm predefined operations. */
typedef enum ir_opcode {
iro_ASM,
iro_Abs,
iro_Add,
iro_Alloc,
iro_Anchor,
......@@ -89,7 +88,6 @@ typedef enum ir_opcode {
FIRM_API ir_op *op_ASM;
FIRM_API ir_op *op_Abs;
FIRM_API ir_op *op_Add;
FIRM_API ir_op *op_Alloc;
FIRM_API ir_op *op_Anchor;
......@@ -148,7 +146,6 @@ FIRM_API ir_op *op_Unknown;
FIRM_API ir_op *get_op_ASM(void);
FIRM_API ir_op *get_op_Abs(void);
FIRM_API ir_op *get_op_Add(void);
FIRM_API ir_op *get_op_Alloc(void);
FIRM_API ir_op *get_op_Anchor(void);
......
......@@ -476,3 +476,78 @@ void be_transform_graph(ir_graph *irg, arch_pretrans_nodes *func)
edges_deactivate(irg);
edges_activate(irg);
}
int be_mux_is_abs(ir_node *sel, ir_node *mux_true, ir_node *mux_false)
{
ir_node *cmp_left;
ir_node *cmp_right;
ir_node *cmp;
ir_mode *mode;
pn_Cmp pnc;
if (!is_Proj(sel))
return 0;
cmp = get_Proj_pred(sel);
if (!is_Cmp(cmp))
return 0;
/**
* Note further that these optimization work even for floating point
* with NaN's because -NaN == NaN.
* However, if +0 and -0 is handled differently, we cannot use the Abs/-Abs
* transformations.
*/
mode = get_irn_mode(mux_true);
if (mode_honor_signed_zeros(mode))
return 0;
/* must be <, <=, >=, > */
pnc = get_Proj_proj(sel);
switch (pnc) {
case pn_Cmp_Ge:
case pn_Cmp_Gt:
case pn_Cmp_Le:
case pn_Cmp_Lt:
case pn_Cmp_Uge:
case pn_Cmp_Ug:
case pn_Cmp_Ul:
case pn_Cmp_Ule:
break;
default:
return 0;
}
if (!is_negated_value(mux_true, mux_false))
return 0;
/* must be x cmp 0 */
cmp_right = get_Cmp_right(cmp);
if (!is_Const(cmp_right) || !is_Const_null(cmp_right))
return 0;
cmp_left = get_Cmp_left(cmp);
if (cmp_left == mux_false) {
if (pnc & pn_Cmp_Lt) {
return 1;
} else {
assert(pnc & pn_Cmp_Gt);
return -1;
}
} else if (cmp_left == mux_true) {
if (pnc & pn_Cmp_Lt) {
return -1;
} else {
assert(pnc & pn_Cmp_Gt);
return 1;
}
}
return 0;
}
ir_node *be_get_abs_op(ir_node *sel)
{
ir_node *cmp = get_Proj_pred(sel);
ir_node *cmp_left = get_Cmp_left(cmp);
return cmp_left;
}
......@@ -91,4 +91,12 @@ void be_enqueue_preds(ir_node *node);
*/
void be_transform_graph(ir_graph *irg, arch_pretrans_nodes *func);
/**
* If Mux(sel, t, f) represents an Abs return 1, if it represents -Abs return
* -1, otherwise 0
*/
int be_mux_is_abs(ir_node *sel, ir_node *mux_true, ir_node *mux_false);
ir_node *be_get_abs_op(ir_node *sel);
#endif
......@@ -2060,53 +2060,6 @@ static void ia32_mark_remat(ir_node *node)
}
}
/**
* Check if Mux(sel, t, f) would represent an Abs (or -Abs).
*/
static bool mux_is_abs(ir_node *sel, ir_node *mux_true, ir_node *mux_false)
{
ir_node *cmp_left;
ir_node *cmp_right;
ir_node *cmp;
pn_Cmp pnc;
if (!is_Proj(sel))
return false;
cmp = get_Proj_pred(sel);
if (!is_Cmp(cmp))
return false;
/* must be <, <=, >=, > */
pnc = get_Proj_proj(sel);
switch (pnc) {
case pn_Cmp_Ge:
case pn_Cmp_Gt:
case pn_Cmp_Le:
case pn_Cmp_Lt:
case pn_Cmp_Uge:
case pn_Cmp_Ug:
case pn_Cmp_Ul:
case pn_Cmp_Ule:
break;
default:
return false;
}
if (!is_negated_value(mux_true, mux_false))
return false;
/* must be x cmp 0 */
cmp_right = get_Cmp_right(cmp);
if (!is_Const(cmp_right) || !is_Const_null(cmp_right))
return 0;
cmp_left = get_Cmp_left(cmp);
if (cmp_left != mux_true && cmp_left != mux_false)
return false;
return true;
}
/**
* Check if Mux(sel, mux_true, mux_false) would represent a Max or Min operation
*/
......@@ -2254,9 +2207,6 @@ static int ia32_is_mux_allowed(ir_node *sel, ir_node *mux_false,
{
ir_mode *mode;
/* we can handle Abs for all modes and compares */
if (mux_is_abs(sel, mux_true, mux_false))
return true;
/* we can handle Set for all modes and compares */
if (mux_is_set(sel, mux_true, mux_false))
return true;
......@@ -2280,6 +2230,9 @@ static int ia32_is_mux_allowed(ir_node *sel, ir_node *mux_false,
mode = get_irn_mode(mux_true);
if (get_mode_size_bits(mode) > 32)
return false;
/* we can handle Abs for all modes and compares (except 64bit) */
if (be_mux_is_abs(sel, mux_true, mux_false) != 0)
return true;
/* we can't handle MuxF yet */
if (mode_is_float(mode))
return false;
......
......@@ -622,6 +622,7 @@ static int map_Minus(ir_node *call, void *ctx)
return 1;
}
#if 0
/**
* Map a Abs (a_l, a_h)
*/
......@@ -671,6 +672,7 @@ static int map_Abs(ir_node *call, void *ctx)
return 1;
}
#endif
#define ID(x) new_id_from_chars(x, sizeof(x)-1)
......@@ -908,10 +910,6 @@ ir_entity *ia32_create_intrinsic_fkt(ir_type *method, const ir_op *op,
ent = &i_ents[iro_Minus];
mapper = map_Minus;
break;
case iro_Abs:
ent = &i_ents[iro_Abs];
mapper = map_Abs;
break;
case iro_Div:
ent = &i_ents[iro_Div];
mapper = map_Div;
......
......@@ -1842,20 +1842,11 @@ static ir_node *gen_Not(ir_node *node)
return gen_unop(node, op, new_bd_ia32_Not, match_mode_neutral);
}
/**
* Transforms an Abs node.
*
* @return The created ia32 Abs node
*/
static ir_node *gen_Abs(ir_node *node)
static ir_node *create_abs(dbg_info *dbgi, ir_node *block, ir_node *op,
bool negate, ir_node *node)
{
ir_node *block = get_nodes_block(node);
ir_node *new_block = be_transform_node(block);
ir_node *op = get_Abs_op(node);
dbg_info *dbgi = get_irn_dbg_info(node);
ir_mode *mode = get_irn_mode(node);
ir_mode *mode = get_irn_mode(op);
ir_node *new_op;
ir_node *new_node;
int size;
......@@ -1878,12 +1869,20 @@ static ir_node *gen_Abs(ir_node *node)
set_ia32_op_type(new_node, ia32_AddrModeS);
set_ia32_ls_mode(new_node, mode);
/* TODO, implement -Abs case */
assert(!negate);
} else {
new_node = new_bd_ia32_vfabs(dbgi, new_block, new_op);
SET_IA32_ORIG_NODE(new_node, node);
if (negate) {
new_node = new_bd_ia32_vfchs(dbgi, new_block, new_node);
SET_IA32_ORIG_NODE(new_node, node);
}
}
} else {
ir_node *xor, *sign_extension;
ir_node *xor;
ir_node *sign_extension;
if (get_mode_size_bits(mode) == 32) {
new_op = be_transform_node(op);
......@@ -1897,8 +1896,13 @@ static ir_node *gen_Abs(ir_node *node)
nomem, new_op, sign_extension);
SET_IA32_ORIG_NODE(xor, node);
new_node = new_bd_ia32_Sub(dbgi, new_block, noreg_GP, noreg_GP,
nomem, xor, sign_extension);
if (negate) {
new_node = new_bd_ia32_Sub(dbgi, new_block, noreg_GP, noreg_GP,
nomem, sign_extension, xor);
} else {
new_node = new_bd_ia32_Sub(dbgi, new_block, noreg_GP, noreg_GP,
nomem, xor, sign_extension);
}
SET_IA32_ORIG_NODE(new_node, node);
}
......@@ -3292,19 +3296,25 @@ static void find_const_transform(pn_Cmp pnc, tarval *t, tarval *f,
*/
static ir_node *gen_Mux(ir_node *node)
{
dbg_info *dbgi = get_irn_dbg_info(node);
ir_node *block = get_nodes_block(node);
ir_node *new_block = be_transform_node(block);
ir_node *mux_true = get_Mux_true(node);
ir_node *mux_false = get_Mux_false(node);
ir_node *cond = get_Mux_sel(node);
ir_mode *mode = get_irn_mode(node);
dbg_info *dbgi = get_irn_dbg_info(node);
ir_node *block = get_nodes_block(node);
ir_node *new_block = be_transform_node(block);
ir_node *mux_true = get_Mux_true(node);
ir_node *mux_false = get_Mux_false(node);
ir_node *cond = get_Mux_sel(node);
ir_mode *mode = get_irn_mode(node);
ir_node *flags;
ir_node *new_node;
int is_abs;
pn_Cmp pnc;
assert(get_irn_mode(cond) == mode_b);
is_abs = be_mux_is_abs(cond, mux_true, mux_false);
if (is_abs != 0) {
return create_abs(dbgi, block, be_get_abs_op(cond), is_abs < 0, node);
}
/* Note: a Mux node uses a Load two times IFF it's used in the compare AND in the result */
if (mode_is_float(mode)) {
ir_node *cmp = get_Proj_pred(cond);
......@@ -5674,7 +5684,6 @@ static void register_transformers(void)
/* first clear the generic function pointer for all ops */
be_start_transform_setup();
be_set_transform_function(op_Abs, gen_Abs);
be_set_transform_function(op_Add, gen_Add);
be_set_transform_function(op_And, gen_And);
be_set_transform_function(op_ASM, gen_ASM);
......
......@@ -676,6 +676,7 @@ static ir_node *gen_Quot(ir_node *node)
new_bd_sparc_fdiv_d, new_bd_sparc_fdiv_q);
}
#if 0
static ir_node *gen_Abs(ir_node *node)
{
ir_mode *const mode = get_irn_mode(node);
......@@ -694,6 +695,7 @@ static ir_node *gen_Abs(ir_node *node)
return sub;
}
}
#endif
/**
* Transforms a Not node.
......@@ -2018,7 +2020,6 @@ void sparc_register_transformers(void)
{
be_start_transform_setup();
be_set_transform_function(op_Abs, gen_Abs);
be_set_transform_function(op_Add, gen_Add);
be_set_transform_function(op_And, gen_And);
be_set_transform_function(op_Call, gen_Call);
......
......@@ -254,20 +254,6 @@ static tarval *computed_value_Mul(const ir_node *n)
return tarval_bad;
} /* computed_value_Mul */
/**
* Return the value of an Abs.
*/
static tarval *computed_value_Abs(const ir_node *n)
{
ir_node *a = get_Abs_op(n);
tarval *ta = value_of(a);
if (ta != tarval_bad)
return tarval_abs(ta);
return tarval_bad;
} /* computed_value_Abs */
/**
* Return the value of an And.
* Special case: a & 0, 0 & b
......@@ -737,7 +723,6 @@ static ir_op_ops *firm_set_default_computed_value(ir_opcode code, ir_op_ops *ops
CASE(Borrow);
CASE(Minus);
CASE(Mul);
CASE(Abs);
CASE(And);
CASE(Or);
CASE(Eor);
......@@ -1280,13 +1265,11 @@ restart:
if (get_Conv_strict(n)) {
ir_node *p = a;
/* neither Minus nor Abs nor Confirm change the precision,
/* neither Minus nor Confirm change the precision,
so we can "look-through" */
for (;;) {
if (is_Minus(p)) {
p = get_Minus_op(p);
} else if (is_Abs(p)) {
p = get_Abs_op(p);
} else if (is_Confirm(p)) {
p = get_Confirm_value(p);
} else {
......@@ -1296,7 +1279,7 @@ restart:
}
if (is_Conv(p) && get_Conv_strict(p)) {
/* we known already, that a_mode == n_mode, and neither
Abs nor Minus change the mode, so the second Conv
Minus change the mode, so the second Conv
can be kicked */
assert(get_irn_mode(p) == n_mode);
n = a;
......@@ -3276,54 +3259,6 @@ static ir_node *transform_node_Quot(ir_node *n)
return n;
} /* transform_node_Quot */
/**
* Optimize Abs(x) into x if x is Confirmed >= 0
* Optimize Abs(x) into -x if x is Confirmed <= 0
* Optimize Abs(-x) int Abs(x)
*/
static ir_node *transform_node_Abs(ir_node *n)
{
ir_node *c, *oldn = n;
ir_node *a = get_Abs_op(n);
ir_mode *mode;
HANDLE_UNOP_PHI(tarval_abs, a, c);
switch (classify_value_sign(a)) {
case value_classified_negative:
mode = get_irn_mode(n);
/*
* We can replace the Abs by -x here.
* We even could add a new Confirm here
* (if not twos complement)
*
* Note that -x would create a new node, so we could
* not run it in the equivalent_node() context.
*/
n = new_rd_Minus(get_irn_dbg_info(n), get_nodes_block(n), a, mode);
DBG_OPT_CONFIRM(oldn, n);
return n;
case value_classified_positive:
/* n is positive, Abs is not needed */
n = a;
DBG_OPT_CONFIRM(oldn, n);
return n;
default:
break;
}
if (is_Minus(a)) {
/* Abs(-x) = Abs(x) */
mode = get_irn_mode(n);
n = new_rd_Abs(get_irn_dbg_info(n), get_nodes_block(n), get_Minus_op(a), mode);
DBG_OPT_ALGSIM0(oldn, n, FS_OPT_ABS_MINUS_X);
return n;
}
return n;
} /* transform_node_Abs */
/**
* Optimize -a CMP -b into b CMP a.
* This works only for for modes where unary Minus
......@@ -5922,11 +5857,6 @@ static ir_node *transform_node_Mux(ir_node *n)
/*
* Note: normalization puts the constant on the right side,
* so we check only one case.
*
* Note further that these optimization work even for floating point
* with NaN's because -NaN == NaN.
* However, if +0 and -0 is handled differently, we cannot use the Abs/-Abs
* transformations.
*/
if (is_Cmp(cmp)) {
ir_node *cmp_r = get_Cmp_right(cmp);
......@@ -5934,30 +5864,6 @@ static ir_node *transform_node_Mux(ir_node *n)
ir_node *block = get_nodes_block(n);
ir_node *cmp_l = get_Cmp_left(cmp);
if (!mode_honor_signed_zeros(mode) && is_negated_value(f, t)) {
/* f = -t */
/* NaN's work fine with abs, so it is ok to remove Uo */
long pnc = pn & ~pn_Cmp_Uo;
if ( (cmp_l == t && (pnc == pn_Cmp_Ge || pnc == pn_Cmp_Gt))
|| (cmp_l == f && (pnc == pn_Cmp_Le || pnc == pn_Cmp_Lt)))
{
/* Mux(a >/>= 0, a, -a) = Mux(a </<= 0, -a, a) ==> Abs(a) */
n = new_rd_Abs(get_irn_dbg_info(n), block, cmp_l, mode);
DBG_OPT_ALGSIM1(oldn, cmp, sel, n, FS_OPT_MUX_TO_ABS);
return n;
} else if ((cmp_l == t && (pnc == pn_Cmp_Le || pnc == pn_Cmp_Lt))
|| (cmp_l == f && (pnc == pn_Cmp_Ge || pnc == pn_Cmp_Gt)))
{
/* Mux(a </<= 0, a, -a) = Mux(a >/>= 0, -a, a) ==> -Abs(a) */
n = new_rd_Abs(get_irn_dbg_info(n), block, cmp_l, mode);
n = new_rd_Minus(get_irn_dbg_info(n), block, n, mode);
DBG_OPT_ALGSIM1(oldn, cmp, sel, n, FS_OPT_MUX_TO_ABS);
return n;
}
}
if (mode_is_int(mode)) {
/* integer only */
if ((pn == pn_Cmp_Lg || pn == pn_Cmp_Eq) && is_And(cmp_l)) {
......@@ -6200,7 +6106,6 @@ static ir_op_ops *firm_set_default_transform_node(ir_opcode code, ir_op_ops *ops
CASE_PROJ_EX(Mod);
CASE_PROJ_EX(DivMod);
CASE(Quot);
CASE(Abs);
CASE_PROJ_EX(Cmp);
CASE_PROJ_EX(Cond);
CASE(And);
......
......@@ -1415,25 +1415,6 @@ static int verify_node_Mod(ir_node *n, ir_graph *irg)
return 1;
}
/**
* verify an Abs node
*/
static int verify_node_Abs(ir_node *n, ir_graph *irg)