}
DBG_OPT_ALGSIM0(oldn, n, FS_OPT_SUB_TO_ADD);
return n;
+#if 0
} else if (is_Mul(b)) { /* a - (b * C) -> a + (b * -C) */
ir_node *m_right = get_Mul_right(b);
if (is_Const(m_right)) {
return n;
}
}
+#endif
}
/* Beware of Sub(P, P) which cannot be optimized into a simple Minus ... */
return is_Shl(n) || is_Shr(n) || is_Shrs(n) || is_Rotl(n);
}
+/**
+ * normalisation: (x & c1) >> c2 to (x >> c2) & (c1 >> c2)
+ * (we can use:
+ * - and, or, xor instead of &
+ * - Shl, Shr, Shrs, rotl instead of >>
+ * (with a special case for Or/Xor + Shrs)
+ *
+ * This normalisation is good for things like x-(x&y) esp. in 186.crafty.
+ */
+static ir_node *transform_node_shift_bitop(ir_node *n)
+{
+ ir_graph *irg = get_irn_irg(n);
+ ir_node *right = get_binop_right(n);
+ ir_mode *mode = get_irn_mode(n);
+ ir_node *left;
+ ir_node *bitop_left;
+ ir_node *bitop_right;
+ ir_op *op_left;
+ ir_node *block;
+ dbg_info *dbgi;
+ ir_node *new_shift;
+ ir_node *new_bitop;
+ ir_node *new_const;
+ ir_tarval *tv1;
+ ir_tarval *tv2;
+ ir_tarval *tv_shift;
+
+ if (is_irg_state(irg, IR_GRAPH_STATE_NORMALISATION2))
+ return n;
+
+ assert(is_Shrs(n) || is_Shr(n) || is_Shl(n) || is_Rotl(n));
+
+ if (!is_Const(right))
+ return n;
+
+ left = get_binop_left(n);
+ op_left = get_irn_op(left);
+ if (op_left != op_And && op_left != op_Or && op_left != op_Eor)
+ return n;
+
+ /* doing it with Shrs is not legal if the Or/Eor affects the topmost bit */
+ if (is_Shrs(n) && (op_left == op_Or || op_left == op_Eor)) {
+ /* TODO: test if sign bit is affectes */
+ return n;
+ }
+
+ bitop_right = get_binop_right(left);
+ if (!is_Const(bitop_right))
+ return n;
+
+ bitop_left = get_binop_left(left);
+
+ block = get_nodes_block(n);
+ dbgi = get_irn_dbg_info(n);
+ tv1 = get_Const_tarval(bitop_right);
+ tv2 = get_Const_tarval(right);
+
+ assert(get_tarval_mode(tv1) == mode);
+
+ if (is_Shl(n)) {
+ new_shift = new_rd_Shl(dbgi, block, bitop_left, right, mode);
+ tv_shift = tarval_shl(tv1, tv2);
+ } else if (is_Shr(n)) {
+ new_shift = new_rd_Shr(dbgi, block, bitop_left, right, mode);
+ tv_shift = tarval_shr(tv1, tv2);
+ } else if (is_Shrs(n)) {
+ new_shift = new_rd_Shrs(dbgi, block, bitop_left, right, mode);
+ tv_shift = tarval_shrs(tv1, tv2);
+ } else {
+ assert(is_Rotl(n));
+ new_shift = new_rd_Rotl(dbgi, block, bitop_left, right, mode);
+ tv_shift = tarval_rotl(tv1, tv2);
+ }
+
+ assert(get_tarval_mode(tv_shift) == mode);
+ irg = get_irn_irg(n);
+ new_const = new_r_Const(irg, tv_shift);
+
+ if (op_left == op_And) {
+ new_bitop = new_rd_And(dbgi, block, new_shift, new_const, mode);
+ } else if (op_left == op_Or) {
+ new_bitop = new_rd_Or(dbgi, block, new_shift, new_const, mode);
+ } else {
+ assert(op_left == op_Eor);
+ new_bitop = new_rd_Eor(dbgi, block, new_shift, new_const, mode);
+ }
+
+ return new_bitop;
+}
+
/**
* normalisation: (x >> c1) & c2 to (x & (c2<<c1)) >> c1
* (we can use:
* - and, or, xor instead of &
* - Shl, Shr, Shrs, rotl instead of >>
* (with a special case for Or/Xor + Shrs)
+ *
+ * This normalisation is usually good for the backend since << C can often be
+ * matched as address-mode.
*/
static ir_node *transform_node_bitop_shift(ir_node *n)
{
+ ir_graph *irg = get_irn_irg(n);
ir_node *left = get_binop_left(n);
ir_node *right = get_binop_right(n);
ir_mode *mode = get_irn_mode(n);
ir_node *block;
dbg_info *dbg_bitop;
dbg_info *dbg_shift;
- ir_graph *irg;
ir_node *new_bitop;
ir_node *new_shift;
ir_node *new_const;
ir_tarval *tv2;
ir_tarval *tv_bitop;
+ if (!is_irg_state(irg, IR_GRAPH_STATE_NORMALISATION2))
+ return n;
+
assert(is_And(n) || is_Or(n) || is_Eor(n));
if (!is_Const(right) || !is_shiftop(left))
return n;
n = transform_node_shift_modulo(n, new_rd_Shr);
if (is_Shr(n))
n = transform_node_shl_shr(n);
+ if (is_Shr(n))
+ n = transform_node_shift_bitop(n);
return n;
} /* transform_node_Shr */
if (is_Shrs(n))
n = transform_node_shift_modulo(n, new_rd_Shrs);
+ if (is_Shrs(n))
+ n = transform_node_shift_bitop(n);
return n;
} /* transform_node_Shrs */
n = transform_node_shift_modulo(n, new_rd_Shl);
if (is_Shl(n))
n = transform_node_shl_shr(n);
+ if (is_Shl(n))
+ n = transform_node_shift_bitop(n);
return n;
} /* transform_node_Shl */
HANDLE_BINOP_PHI((eval_func) tarval_rotl, a, b, c, mode);
n = transform_node_shift(n);
+ if (is_Rotl(n))
+ n = transform_node_shift_bitop(n);
+
return n;
} /* transform_node_Rotl */