Transform a - (b - c) into (a - b) + c instead of a + (c - b) iff (b - c) is a pointer.
[libfirm] / ir / ir / iropt.c
index 9455a8e..85c5270 100644 (file)
@@ -522,31 +522,29 @@ static tarval *computed_value_Proj_Cmp(const ir_node *n) {
                 * the Cmp result.
                 */
                else {
-                       ir_node *aaa = skip_Id(skip_Proj(aa));
-                       ir_node *aba = skip_Id(skip_Proj(ab));
+                       ir_node *aaa = skip_Proj(aa);
+                       ir_node *aba = skip_Proj(ab);
 
                        if (   (   (/* aa is ProjP and aaa is Alloc */
                                       is_Proj(aa)
                                    && mode_is_reference(get_irn_mode(aa))
                                    && is_Alloc(aaa))
                                && (   (/* ab is NULL */
-                                          is_Const(ab)
-                                       && mode_is_reference(get_irn_mode(ab))
-                                       && is_Const_null(ab))
+                                       mode_is_reference(get_irn_mode(ab))
+                                       && tarval_is_null(tab))
                                    || (/* ab is other Alloc */
                                           is_Proj(ab)
                                        && mode_is_reference(get_irn_mode(ab))
                                        && is_Alloc(aba)
                                        && (aaa != aba))))
                            || (/* aa is NULL and aba is Alloc */
-                                  is_Const(aa)
-                               && mode_is_reference(get_irn_mode(aa))
-                               && is_Const_null(aa)
+                               mode_is_reference(get_irn_mode(aa))
+                               && tarval_is_null(taa)
                                && is_Proj(ab)
                                && mode_is_reference(get_irn_mode(ab))
                                && is_Alloc(aba)))
                                /* 3.: */
-                       return new_tarval_from_long(proj_nr & pn_Cmp_Ne, mode_b);
+                       return new_tarval_from_long(proj_nr & pn_Cmp_Lg, mode_b);
                }
        }
        return computed_value_Cmp_Confirm(a, aa, ab, proj_nr);
@@ -2365,18 +2363,30 @@ restart:
                n = new_rd_Add(dbg, irg, block, a, right, mode);
                DBG_OPT_ALGSIM0(oldn, n, FS_OPT_SUB_MINUS);
                return n;
-       } else if (is_Sub(b)) { /* a - (b - c) -> a + (c - b) */
+       } else if (is_Sub(b)) {
+               /* a - (b - c) -> a + (c - b)
+                *             -> (a - b) + c iff (b - c) is a pointer */
                ir_graph *irg     = current_ir_graph;
                dbg_info *s_dbg   = get_irn_dbg_info(b);
                ir_node  *s_block = get_nodes_block(b);
-               ir_node  *s_left  = get_Sub_right(b);
-               ir_node  *s_right = get_Sub_left(b);
+               ir_node  *s_left  = get_Sub_left(b);
+               ir_node  *s_right = get_Sub_right(b);
                ir_mode  *s_mode  = get_irn_mode(b);
-               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);
+               if (s_mode == mode_P) {
+                       ir_node  *sub     = new_rd_Sub(s_dbg, irg, s_block, a, s_left, mode);
+                       dbg_info *a_dbg   = get_irn_dbg_info(n);
+                       ir_node  *a_block = get_nodes_block(n);
+
+                       if (s_mode != mode)
+                               s_right = new_r_Conv(irg, a_block, s_right, mode);
+                       n = new_rd_Add(a_dbg, irg, a_block, sub, s_right, mode);
+               } else {
+                       ir_node  *sub     = new_rd_Sub(s_dbg, irg, s_block, s_right, s_left, s_mode);
+                       dbg_info *a_dbg   = get_irn_dbg_info(n);
+                       ir_node  *a_block = get_nodes_block(n);
 
-               n = new_rd_Add(a_dbg, irg, a_block, a, sub, 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) */