/** Optimize Not(Not(x)) == x. */
#define equivalent_node_Not equivalent_node_idempotent_unop
-/** --x == x ??? Is this possible or can --x raise an
+/** -(-x) == x ??? Is this possible or can --x raise an
out of bounds exception if min =! max? */
#define equivalent_node_Minus equivalent_node_idempotent_unop
ir_mode *a_mode = get_irn_mode(a);
if (n_mode == a_mode) { /* No Conv necessary */
- /* leave strict floating point Conv's */
- if (get_Conv_strict(n))
- return n;
+ if (get_Conv_strict(n)) {
+ /* special case: the predecessor might be a also a Conv */
+ if (is_Conv(a)) {
+ if (! get_Conv_strict(a)) {
+ /* first one is not strict, kick it */
+ set_Conv_op(n, get_Conv_op(a));
+ return n;
+ }
+ /* else both are strict conv, second is superflous */
+ } else {
+ /* leave strict floating point Conv's */
+ return n;
+ }
+ }
n = a;
DBG_OPT_ALGSIM0(oldn, n, FS_OPT_CONV);
} else if (get_irn_op(a) == op_Conv) { /* Conv(Conv(b)) */
if (n_mode == mode_b) {
n = b; /* Convb(Conv*(xxxb(...))) == xxxb(...) */
DBG_OPT_ALGSIM1(oldn, a, b, n, FS_OPT_CONV);
- } else if (mode_is_int(n_mode) || mode_is_character(n_mode)) {
+ } else if (mode_is_int(n_mode)) {
if (smaller_mode(b_mode, a_mode)){
n = b; /* ConvS(ConvL(xxxS(...))) == xxxS(...) */
DBG_OPT_ALGSIM1(oldn, a, b, n, FS_OPT_CONV);
/*
* One could expect that we simply return the previous
* Bound here. However, this would be wrong, as we could
- * add an exception Proj to a new location than.
- * So, we must turn in into a tuple
+ * add an exception Proj to a new location then.
+ * So, we must turn in into a tuple.
*/
ret_tuple = 1;
}
DBG_OPT_ALGSIM0(oldn, n, FS_OPT_ADD_MUL_A_X_A);
}
}
+ /* Here we rely on constants be on the RIGHT side */
+ else if (is_Not(a) && classify_Const(b) == CNST_ONE) {
+ /* ~x + 1 = -x */
+ ir_node *op = get_Not_op(a);
+ ir_node *blk = get_irn_n(n, -1);
+ n = new_rd_Minus(get_irn_dbg_info(n), current_ir_graph, blk, op, mode);
+ DBG_OPT_ALGSIM0(oldn, n, FS_OPT_NOT_PLUS_1);
+ }
}
return n;
} /* transform_node_Add */
*/
if ((proj_nr == pn_Cmp_Eq || proj_nr == pn_Cmp_Lg) &&
(get_irn_op(left) == op_And)) {
- if (is_single_bit_tarval(tv)) {
+ if (tarval_is_single_bit(tv)) {
/* check for Constant's match. We have check hare the tarvals,
because our const might be changed */
ir_node *la = get_And_left(left);
ir_node *oldn = n, *sel = get_Mux_sel(n);
ir_mode *mode = get_irn_mode(n);
+ if (mode == mode_b) {
+ ir_node *t = get_Mux_true(n);
+ ir_node *f = get_Mux_false(n);
+ dbg_info *dbg = get_irn_dbg_info(n);
+ ir_node *block = get_irn_n(n, -1);
+ ir_graph *irg = current_ir_graph;
+
+ if (is_Const(t)) {
+ tarval *tv_t = get_Const_tarval(t);
+ if (tv_t == tarval_b_true) {
+ if (is_Const(f)) {
+ assert(get_Const_tarval(f) == tarval_b_false);
+ return sel;
+ } else {
+ return new_rd_Or(dbg, irg, block, sel, f, mode_b);
+ }
+ } else {
+ ir_node* not_sel = new_rd_Not(dbg, irg, block, sel, mode_b);
+ assert(tv_t == tarval_b_false);
+ if (is_Const(f)) {
+ assert(get_Const_tarval(f) == tarval_b_true);
+ return not_sel;
+ } else {
+ return new_rd_And(dbg, irg, block, not_sel, f, mode_b);
+ }
+ }
+ } else if (is_Const(f)) {
+ tarval *tv_f = get_Const_tarval(f);
+ if (tv_f == tarval_b_true) {
+ ir_node* not_sel = new_rd_Not(dbg, irg, block, sel, mode_b);
+ return new_rd_Or(dbg, irg, block, not_sel, t, mode_b);
+ } else {
+ assert(tv_f == tarval_b_false);
+ return new_rd_And(dbg, irg, block, sel, t, mode_b);
+ }
+ }
+ }
+
if (get_irn_op(sel) == op_Proj && !mode_honor_signed_zeros(mode)) {
ir_node *cmp = get_Proj_pred(sel);
long proj_nr = get_Proj_proj(sel);
* not be freed even if the equivalent node isn't the old one.
*/
static ir_node *transform_node(ir_node *n) {
- if (n->op->ops.transform_node)
- n = n->op->ops.transform_node(n);
+ ir_node *oldn;
+
+ /*
+ * Transform_node is the only "optimizing transformation" that might
+ * return a node with a different opcode. We iterate HERE until fixpoint
+ * to get the final result.
+ */
+ do {
+ oldn = n;
+ if (n->op->ops.transform_node)
+ n = n->op->ops.transform_node(n);
+ } while (oldn != n);
+
return n;
} /* transform_node */