Fix fehler83: The mode of the outer Sub in the transformation Sub(Sub(x, y), b) ...
[libfirm] / ir / ir / iropt.c
index 8b5719a..947d676 100644 (file)
@@ -540,7 +540,7 @@ static tarval *computed_value_Proj_Cmp(ir_node *n) {
                                && (   (/* ab is NULL */
                                           is_Const(ab)
                                        && mode_is_reference(get_irn_mode(ab))
-                                       && (get_Const_tarval(ab) == get_mode_null(get_irn_mode(ab))))
+                                       && is_Const_null(ab))
                                    || (/* ab is other Alloc */
                                           is_Proj(ab)
                                        && mode_is_reference(get_irn_mode(ab))
@@ -549,7 +549,7 @@ static tarval *computed_value_Proj_Cmp(ir_node *n) {
                            || (/* aa is NULL and aba is Alloc */
                                   is_Const(aa)
                                && mode_is_reference(get_irn_mode(aa))
-                               && (get_Const_tarval(aa) == get_mode_null(get_irn_mode(aa)))
+                               && is_Const_null(aa)
                                && is_Proj(ab)
                                && mode_is_reference(get_irn_mode(ab))
                                && is_Alloc(aba)))
@@ -1908,7 +1908,7 @@ static ir_node *transform_node_Add(ir_node *n) {
 
        if (mode_is_num(mode)) {
                /* the following code leads to endless recursion when Mul are replaced by a simple instruction chain */
-               if (!get_opt_arch_dep_running() && a == b && mode_is_int(mode)) {
+               if (!is_arch_dep_running() && a == b && mode_is_int(mode)) {
                        ir_node *block = get_irn_n(n, -1);
 
                        n = new_rd_Mul(
@@ -1943,7 +1943,7 @@ static ir_node *transform_node_Add(ir_node *n) {
                        DBG_OPT_ALGSIM0(oldn, n, FS_OPT_ADD_A_MINUS_B);
                        return n;
                }
-               if (! get_opt_reassociation()) {
+               if (! is_reassoc_running()) {
                        /* do NOT execute this code if reassociation is enabled, it does the inverse! */
                        if (is_Mul(a)) {
                                ir_node *ma = get_Mul_left(a);
@@ -2035,7 +2035,7 @@ static ir_node *transform_node_Add(ir_node *n) {
                                ir_node *op = get_Not_op(b);
 
                                if (op == a) {
-                                       /* ~x + x = -1 */
+                                       /* x + ~x = -1 */
                                        ir_node *blk = get_irn_n(n, -1);
                                        n = new_r_Const(current_ir_graph, blk, mode, get_mode_minus_one(mode));
                                        DBG_OPT_ALGSIM0(oldn, n, FS_OPT_ADD_X_NOT_X);
@@ -2247,7 +2247,7 @@ restart:
                }
        }
        /* do NOT execute this code if reassociation is enabled, it does the inverse! */
-       if (get_opt_reassociation() && is_Mul(a)) {
+       if (!is_reassoc_running() && is_Mul(a)) {
                ir_node *ma = get_Mul_left(a);
                ir_node *mb = get_Mul_right(a);
 
@@ -2283,21 +2283,22 @@ restart:
                        return n;
                }
        }
-       if (is_Sub(a)) {
-               ir_node *x   = get_Sub_left(a);
-               ir_node *y   = get_Sub_right(a);
-               ir_node *blk = get_irn_n(n, -1);
-               ir_mode *m_b = get_irn_mode(b);
-               ir_mode *m_y = get_irn_mode(y);
+       if (is_Sub(a)) { /* (x - y) - b -> x - (y + b) */
+               ir_node *x   =      get_Sub_left(a);
+               ir_node *y        = get_Sub_right(a);
+               ir_node *blk      = get_irn_n(n, -1);
+               ir_mode *m_b      = get_irn_mode(b);
+               ir_mode *m_y      = get_irn_mode(y);
+               ir_mode *add_mode;
                ir_node *add;
 
                /* Determine the right mode for the Add. */
                if (m_b == m_y)
-                       mode = m_b;
+                       add_mode = m_b;
                else if (mode_is_reference(m_b))
-                       mode = m_b;
+                       add_mode = m_b;
                else if (mode_is_reference(m_y))
-                       mode = m_y;
+                       add_mode = m_y;
                else {
                        /*
                         * Both modes are different but none is reference,
@@ -2308,7 +2309,7 @@ restart:
                        return n;
                }
 
-               add = new_r_Add(current_ir_graph, blk, y, b, mode);
+               add = new_r_Add(current_ir_graph, blk, y, b, add_mode);
 
                n = new_rd_Sub(get_irn_dbg_info(n), current_ir_graph, blk, x, add, mode);
                DBG_OPT_ALGSIM0(oldn, n, FS_OPT_SUB_SUB_X_Y_Z);
@@ -3023,7 +3024,7 @@ static ir_node *transform_node_Eor(ir_node *n) {
        HANDLE_BINOP_PHI(tarval_eor, a,b,c);
 
        /* we can evaluate 2 Projs of the same Cmp */
-       if(get_irn_mode(n) == mode_b && is_Proj(a) && is_Proj(b)) {
+       if (mode == mode_b && is_Proj(a) && is_Proj(b)) {
                ir_node *pred_a = get_Proj_pred(a);
                ir_node *pred_b = get_Proj_pred(b);
                if(pred_a == pred_b) {
@@ -3053,12 +3054,20 @@ static ir_node *transform_node_Eor(ir_node *n) {
                                mode_b, get_negated_pnc(get_Proj_proj(a), mode));
 
                DBG_OPT_ALGSIM0(oldn, n, FS_OPT_EOR_TO_NOT_BOOL);
-       } else if (mode == mode_b && is_Const(b) && is_Const_one(b)) {
-               /* The Eor is a Not. Replace it by a Not. */
-               /*   ????!!!Extend to bitfield 1111111. */
-               n = new_r_Not(current_ir_graph, get_irn_n(n, -1), a, mode_b);
-
-               DBG_OPT_ALGSIM0(oldn, n, FS_OPT_EOR_TO_NOT);
+       } else if (is_Const(b)) {
+               if (is_Not(a)) { /* ~x ^ const -> x ^ ~const */
+                       ir_node  *cnst   = new_Const(mode, tarval_not(get_Const_tarval(b)));
+                       ir_node  *not_op = get_Not_op(a);
+                       dbg_info *dbg    = get_irn_dbg_info(n);
+                       ir_graph *irg    = current_ir_graph;
+                       ir_node  *block  = get_nodes_block(n);
+                       ir_mode  *mode   = get_irn_mode(n);
+                       n = new_rd_Eor(dbg, irg, block, not_op, cnst, mode);
+                       return n;
+               } else if (is_Const_all_one(b)) { /* x ^ 1...1 -> ~1 */
+                       n = new_r_Not(current_ir_graph, get_nodes_block(n), a, mode);
+                       DBG_OPT_ALGSIM0(oldn, n, FS_OPT_EOR_TO_NOT);
+               }
        } else {
                n = transform_bitwise_distributive(n, transform_node_Eor);
        }
@@ -3071,28 +3080,51 @@ static ir_node *transform_node_Eor(ir_node *n) {
  */
 static ir_node *transform_node_Not(ir_node *n) {
        ir_node *c, *oldn = n;
-       ir_node *a = get_Not_op(n);
+       ir_node *a    = get_Not_op(n);
+       ir_mode *mode = get_irn_mode(n);
 
        HANDLE_UNOP_PHI(tarval_not,a,c);
 
        /* check for a boolean Not */
-       if (get_irn_mode(n) == mode_b &&
+       if (mode == mode_b &&
                        is_Proj(a) &&
                        is_Cmp(get_Proj_pred(a))) {
                /* We negate a Cmp. The Cmp has the negated result anyways! */
                n = new_r_Proj(current_ir_graph, get_irn_n(n, -1), get_Proj_pred(a),
                                mode_b, get_negated_pnc(get_Proj_proj(a), mode_b));
                DBG_OPT_ALGSIM0(oldn, n, FS_OPT_NOT_CMP);
-                return n;
+               return n;
        }
-       if (is_Sub(a)) {
-               ir_node *sub_r = get_Sub_right(a);
-               if (is_Const(sub_r) && is_Const_one(sub_r)) {
-                       /* ~(x-1) = -x */
-                       ir_node *op = get_Sub_left(a);
-                       ir_node *blk = get_irn_n(n, -1);
-                       n = new_rd_Minus(get_irn_dbg_info(n), current_ir_graph, blk, op, get_irn_mode(n));
-                       DBG_OPT_ALGSIM0(oldn, n, FS_OPT_NOT_MINUS_1);
+       if  (is_Eor(a)) {
+               ir_node *eor_b = get_Eor_right(a);
+               if (is_Const(eor_b)) { /* ~(x ^ const) -> x ^ ~const */
+                       ir_node  *cnst  = new_Const(mode, tarval_not(get_Const_tarval(eor_b)));
+                       ir_node  *eor_a = get_Eor_left(a);
+                       dbg_info *dbg   = get_irn_dbg_info(n);
+                       ir_graph *irg   = current_ir_graph;
+                       ir_node  *block = get_nodes_block(n);
+                       ir_mode  *mode  = get_irn_mode(n);
+                       n = new_rd_Eor(dbg, irg, block, eor_a, cnst, mode);
+                       return n;
+               }
+       }
+       if (get_mode_arithmetic(mode) == irma_twos_complement) {
+               if (is_Minus(a)) { /* ~-x -> x + -1 */
+                       dbg_info *dbg   = get_irn_dbg_info(n);
+                       ir_graph *irg   = current_ir_graph;
+                       ir_node  *block = get_nodes_block(n);
+                       ir_node  *add_l = get_Minus_op(a);
+                       ir_node  *add_r = new_rd_Const(dbg, irg, block, mode, get_mode_minus_one(mode));
+                       n = new_rd_Add(dbg, irg, block, add_l, add_r, mode);
+               } else if (is_Add(a)) {
+                       ir_node *add_r = get_Add_right(a);
+                       if (is_Const(add_r) && is_Const_all_one(add_r)) {
+                               /* ~(x + -1) = -x */
+                               ir_node *op = get_Add_left(a);
+                               ir_node *blk = get_irn_n(n, -1);
+                               n = new_rd_Minus(get_irn_dbg_info(n), current_ir_graph, blk, op, get_irn_mode(n));
+                               DBG_OPT_ALGSIM0(oldn, n, FS_OPT_NOT_MINUS_1);
+                       }
                }
        }
        return n;
@@ -3168,6 +3200,20 @@ static ir_node *transform_node_Minus(ir_node *n) {
                return n;
        }
 
+       if (is_Mul(a)) { /* -(a * const) -> a * -const */
+               ir_node *mul_l = get_Mul_left(a);
+               ir_node *mul_r = get_Mul_right(a);
+               if (is_Const(mul_r)) {
+                       tarval   *tv    = tarval_neg(get_Const_tarval(mul_r));
+                       ir_node  *cnst  = new_Const(mode, tv);
+                       dbg_info *dbg   = get_irn_dbg_info(a);
+                       ir_graph *irg   = current_ir_graph;
+                       ir_node  *block = get_nodes_block(a);
+                       n = new_rd_Mul(dbg, irg, block, mul_l, cnst, mode);
+                       return n;
+               }
+       }
+
        return n;
 }  /* transform_node_Minus */