* @param phi the Phi node
* @param other the other operand
* @param eval an evaluator function
+ * @param mode the mode of the result, may be different from the mode of the Phi!
* @param left if non-zero, other is the left operand, else the right
*
* @return a new Phi node if the conversion was successful, NULL else
*/
-static ir_node *apply_binop_on_phi(ir_node *phi, tarval *other, tarval *(*eval)(tarval *, tarval *), int left) {
+static ir_node *apply_binop_on_phi(ir_node *phi, tarval *other, tarval *(*eval)(tarval *, tarval *), ir_mode *mode, int left) {
tarval *tv;
void **res;
ir_node *pred;
- ir_mode *mode;
ir_graph *irg;
int i, n = get_irn_arity(phi);
res[i] = tv;
}
}
- mode = get_irn_mode(phi);
irg = current_ir_graph;
for (i = 0; i < n; ++i) {
pred = get_irn_n(phi, i);
return new_r_Phi(irg, get_nodes_block(phi), n, (ir_node **)res, mode);
} /* apply_unop_on_phi */
+/**
+ * Apply a conversion on a constant operator (a Phi).
+ *
+ * @param phi the Phi node
+ *
+ * @return a new Phi node if the conversion was successful, NULL else
+ */
+static ir_node *apply_conv_on_phi(ir_node *phi, ir_mode *mode) {
+ tarval *tv;
+ void **res;
+ ir_node *pred;
+ ir_graph *irg;
+ int i, n = get_irn_arity(phi);
+
+ NEW_ARR_A(void *, res, n);
+ for (i = 0; i < n; ++i) {
+ pred = get_irn_n(phi, i);
+ tv = get_Const_tarval(pred);
+ tv = tarval_convert_to(tv, mode);
+
+ if (tv == tarval_bad) {
+ /* folding failed, bad */
+ return 0;
+ }
+ res[i] = tv;
+ }
+ irg = current_ir_graph;
+ for (i = 0; i < n; ++i) {
+ pred = get_irn_n(phi, i);
+ res[i] = new_r_Const_type(irg, get_irg_start_block(irg),
+ mode, res[i], get_Const_type(pred));
+ }
+ return new_r_Phi(irg, get_nodes_block(phi), n, (ir_node **)res, mode);
+} /* apply_conv_on_phi */
+
/**
* Transform AddP(P, ConvIs(Iu)), AddP(P, ConvIu(Is)) and
* SubP(P, ConvIs(Iu)), SubP(P, ConvIu(Is)).
return n;
} /* transform_node_AddSub */
-#define HANDLE_BINOP_PHI(op,a,b,c) \
- c = NULL; \
- if (is_Const(b) && is_const_Phi(a)) { \
- /* check for Op(Phi, Const) */ \
- c = apply_binop_on_phi(a, get_Const_tarval(b), op, 0); \
- } \
- else if (is_Const(a) && is_const_Phi(b)) { \
- /* check for Op(Const, Phi) */ \
- c = apply_binop_on_phi(b, get_Const_tarval(a), op, 1); \
- } \
- if (c) { \
- DBG_OPT_ALGSIM0(oldn, c, FS_OPT_CONST_PHI); \
- return c; \
+#define HANDLE_BINOP_PHI(eval, a, b, c, mode) \
+ c = NULL; \
+ if (is_Const(b) && is_const_Phi(a)) { \
+ /* check for Op(Phi, Const) */ \
+ c = apply_binop_on_phi(a, get_Const_tarval(b), eval, mode, 0);\
+ } \
+ else if (is_Const(a) && is_const_Phi(b)) { \
+ /* check for Op(Const, Phi) */ \
+ c = apply_binop_on_phi(b, get_Const_tarval(a), eval, mode, 1);\
+ } \
+ if (c) { \
+ DBG_OPT_ALGSIM0(oldn, c, FS_OPT_CONST_PHI); \
+ return c; \
}
-#define HANDLE_UNOP_PHI(op,a,c) \
+#define HANDLE_UNOP_PHI(eval, a, c) \
c = NULL; \
if (is_const_Phi(a)) { \
/* check for Op(Phi) */ \
- c = apply_unop_on_phi(a, op); \
+ c = apply_unop_on_phi(a, eval); \
if (c) { \
DBG_OPT_ALGSIM0(oldn, c, FS_OPT_CONST_PHI); \
return c; \
a = get_Add_left(n);
b = get_Add_right(n);
- HANDLE_BINOP_PHI(tarval_add, a,b,c);
-
mode = get_irn_mode(n);
+ HANDLE_BINOP_PHI(tarval_add, a, b, c, mode);
/* for FP these optimizations are only allowed if fp_strict_algebraic is disabled */
if (mode_is_float(mode) && (get_irg_fp_model(current_ir_graph) & fp_strict_algebraic))
mode = get_irn_mode(n);
restart:
- HANDLE_BINOP_PHI(tarval_sub, a,b,c);
+ HANDLE_BINOP_PHI(tarval_sub, a, b, c, mode);
/* for FP these optimizations are only allowed if fp_strict_algebraic is disabled */
if (mode_is_float(mode) && (get_irg_fp_model(current_ir_graph) & fp_strict_algebraic))
dbg_info *dbg = get_irn_dbg_info(n);
ir_node *block = get_nodes_block(n);
ir_node *left = get_Minus_op(a);
- ir_mode *mode = get_irn_mode(n);
ir_node *add = new_rd_Add(dbg, irg, block, left, b, mode);
n = new_rd_Minus(dbg, irg, block, add, mode);
dbg_info *dbg = get_irn_dbg_info(n);
ir_node *block = get_nodes_block(n);
ir_node *right = get_Minus_op(b);
- ir_mode *mode = get_irn_mode(n);
n = new_rd_Add(dbg, irg, block, a, right, mode);
DBG_OPT_ALGSIM0(oldn, n, FS_OPT_SUB_MINUS);
ir_node *sub = new_rd_Sub(s_dbg, irg, s_block, s_left, s_right, s_mode);
dbg_info *a_dbg = get_irn_dbg_info(n);
ir_node *a_block = get_nodes_block(n);
- ir_mode *a_mode = get_irn_mode(n);
- n = new_rd_Add(a_dbg, irg, a_block, a, sub, a_mode);
+ n = new_rd_Add(a_dbg, irg, a_block, a, sub, mode);
DBG_OPT_ALGSIM0(oldn, n, FS_OPT_SUB_TO_ADD);
return n;
} else if (is_Mul(b)) { /* a - (b * C) -> a + (b * -C) */
ir_node *mul = new_rd_Mul(m_dbg, irg, m_block, m_left, cnst2, m_mode);
dbg_info *a_dbg = get_irn_dbg_info(n);
ir_node *a_block = get_nodes_block(n);
- ir_mode *a_mode = get_irn_mode(n);
- n = new_rd_Add(a_dbg, irg, a_block, a, mul, a_mode);
+ n = new_rd_Add(a_dbg, irg, a_block, a, mul, mode);
DBG_OPT_ALGSIM0(oldn, n, FS_OPT_SUB_TO_ADD);
return n;
}
if (mode != get_irn_mode(a))
return transform_node_Mul2n(n, mode);
- HANDLE_BINOP_PHI(tarval_mul, a,b,c);
+ HANDLE_BINOP_PHI(tarval_mul, a, b, c, mode);
if (mode_is_signed(mode)) {
ir_node *r = NULL;
* Optimize Abs(x) into -x if x is Confirmed <= 0
*/
static ir_node *transform_node_Abs(ir_node *n) {
- ir_node *oldn = n;
- ir_node *a = get_Abs_op(n);
- value_classify_sign sign = classify_value_sign(a);
+ ir_node *c, *oldn = n;
+ ir_node *a = get_Abs_op(n);
+ ir_mode *mode;
- if (sign == value_classified_negative) {
- ir_mode *mode = get_irn_mode(n);
+ 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.
get_irn_n(n, -1), a, mode);
DBG_OPT_CONFIRM(oldn, n);
- } else if (sign == value_classified_positive) {
+ return n;
+ case value_classified_positive:
/* n is positive, Abs is not needed */
n = a;
DBG_OPT_CONFIRM(oldn, n);
+ return n;
+ default:
+ return n;
}
-
- return n;
} /* transform_node_Abs */
/**
ir_node *b = get_And_right(n);
ir_mode *mode;
- HANDLE_BINOP_PHI(tarval_and, a,b,c);
-
mode = get_irn_mode(n);
+ HANDLE_BINOP_PHI(tarval_and, a, b, c, mode);
/* we can evaluate 2 Projs of the same Cmp */
if (mode == mode_b && is_Proj(a) && is_Proj(b)) {
ir_node *b = get_Eor_right(n);
ir_mode *mode = get_irn_mode(n);
- HANDLE_BINOP_PHI(tarval_eor, a,b,c);
+ HANDLE_BINOP_PHI(tarval_eor, a, b, c, mode);
/* we can evaluate 2 Projs of the same Cmp */
if (mode == mode_b && is_Proj(a) && is_Proj(b)) {
ir_node *c, *oldn = n;
ir_node *a = get_Or_left(n);
ir_node *b = get_Or_right(n);
+ ir_mode *mode;
if (is_Not(a) && is_Not(b)) {
/* ~a | ~b = ~(a&b) */
ir_node *block = get_nodes_block(n);
- ir_mode *mode = get_irn_mode(n);
+ mode = get_irn_mode(n);
a = get_Not_op(a);
b = get_Not_op(b);
n = new_rd_And(get_irn_dbg_info(n), current_ir_graph, block, a, b, mode);
}
}
- HANDLE_BINOP_PHI(tarval_or, a,b,c);
+ mode = get_irn_mode(n);
+ HANDLE_BINOP_PHI(tarval_or, a, b, c, mode);
n = transform_node_Or_bf_store(n);
n = transform_node_Or_Rot(n);
static ir_node *transform_node(ir_node *n);
/**
- * Optimize (a >> c1) >> c2), works for Shr, Shrs, Shl.
+ * Optimize (a >> c1) >> c2), works for Shr, Shrs, Shl, Rot.
*
* Should be moved to reassociation?
*/
*/
static ir_node *transform_node_Shr(ir_node *n) {
ir_node *c, *oldn = n;
- ir_node *a = get_Shr_left(n);
- ir_node *b = get_Shr_right(n);
+ ir_node *a = get_Shr_left(n);
+ ir_node *b = get_Shr_right(n);
+ ir_mode *mode = get_irn_mode(n);
- HANDLE_BINOP_PHI(tarval_shr, a, b, c);
+ HANDLE_BINOP_PHI(tarval_shr, a, b, c, mode);
return transform_node_shift(n);
} /* transform_node_Shr */
*/
static ir_node *transform_node_Shrs(ir_node *n) {
ir_node *c, *oldn = n;
- ir_node *a = get_Shrs_left(n);
- ir_node *b = get_Shrs_right(n);
+ ir_node *a = get_Shrs_left(n);
+ ir_node *b = get_Shrs_right(n);
+ ir_mode *mode = get_irn_mode(n);
- HANDLE_BINOP_PHI(tarval_shrs, a, b, c);
+ HANDLE_BINOP_PHI(tarval_shrs, a, b, c, mode);
return transform_node_shift(n);
} /* transform_node_Shrs */
*/
static ir_node *transform_node_Shl(ir_node *n) {
ir_node *c, *oldn = n;
- ir_node *a = get_Shl_left(n);
- ir_node *b = get_Shl_right(n);
+ ir_node *a = get_Shl_left(n);
+ ir_node *b = get_Shl_right(n);
+ ir_mode *mode = get_irn_mode(n);
- HANDLE_BINOP_PHI(tarval_shl, a, b, c);
+ HANDLE_BINOP_PHI(tarval_shl, a, b, c, mode);
return transform_node_shift(n);
} /* transform_node_Shl */
+/**
+ * Transform a Rot.
+ */
+static ir_node *transform_node_Rot(ir_node *n) {
+ ir_node *c, *oldn = n;
+ ir_node *a = get_Rot_left(n);
+ ir_node *b = get_Rot_right(n);
+ ir_mode *mode = get_irn_mode(n);
+
+ HANDLE_BINOP_PHI(tarval_rot, a, b, c, mode);
+ return transform_node_shift(n);
+} /* transform_node_Rot */
+
+/**
+ * Transform a Conv.
+ */
+static ir_node *transform_node_Conv(ir_node *n) {
+ ir_node *c, *oldn = n;
+ ir_node *a = get_Conv_op(n);
+
+ if (is_const_Phi(a)) {
+ c = apply_conv_on_phi(a, get_irn_mode(n));
+ if (c) {
+ DBG_OPT_ALGSIM0(oldn, c, FS_OPT_CONST_PHI);
+ return c;
+ }
+ }
+ return n;
+} /* transform_node_Conv */
+
/**
* Remove dead blocks and nodes in dead blocks
* in keep alive list. We do not generate a new End node.
CASE(Shr);
CASE(Shrs);
CASE(Shl);
+ CASE(Rot);
+ CASE(Conv);
CASE(End);
CASE(Mux);
CASE(Psi);