match.pd: Implement patterns from associate_plusminus and factor in differences from...
authorRichard Biener <rguenther@suse.de>
Tue, 11 Nov 2014 13:23:26 +0000 (13:23 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Tue, 11 Nov 2014 13:23:26 +0000 (13:23 +0000)
2014-11-11  Richard Biener  <rguenther@suse.de>

* match.pd: Implement patterns from associate_plusminus
and factor in differences from the fold-const.c implementation.
* fold-const.c (fold_binary_loc): Remove patterns here.
* tree-ssa-forwprop.c (associate_plusminus): Remove.
(pass_forwprop::execute): Don't call it.
* tree.c (tree_nop_conversion_p): New function, factored
from tree_nop_conversion.
* tree.h (tree_nop_conversion_p): Declare.

From-SVN: r217349

gcc/ChangeLog
gcc/fold-const.c
gcc/match.pd
gcc/tree-ssa-forwprop.c
gcc/tree.c
gcc/tree.h

index 2f6582d..2d57bd3 100644 (file)
@@ -1,3 +1,14 @@
+2014-11-11  Richard Biener  <rguenther@suse.de>
+
+       * match.pd: Implement patterns from associate_plusminus
+       and factor in differences from the fold-const.c implementation.
+       * fold-const.c (fold_binary_loc): Remove patterns here.
+       * tree-ssa-forwprop.c (associate_plusminus): Remove.
+       (pass_forwprop::execute): Don't call it.
+       * tree.c (tree_nop_conversion_p): New function, factored
+       from tree_nop_conversion.
+       * tree.h (tree_nop_conversion_p): Declare.
+
 2014-11-11  Uros Bizjak  <ubizjak@gmail.com>
 
        * system.h: Include algorithm and utility.
index 13faf0c..f3562ff 100644 (file)
@@ -9939,59 +9939,8 @@ fold_binary_loc (location_t loc,
       return NULL_TREE;
 
     case PLUS_EXPR:
-      /* A + (-B) -> A - B */
-      if (TREE_CODE (arg1) == NEGATE_EXPR
-         && (flag_sanitize & SANITIZE_SI_OVERFLOW) == 0)
-       return fold_build2_loc (loc, MINUS_EXPR, type,
-                           fold_convert_loc (loc, type, arg0),
-                           fold_convert_loc (loc, type,
-                                             TREE_OPERAND (arg1, 0)));
-      /* (-A) + B -> B - A */
-      if (TREE_CODE (arg0) == NEGATE_EXPR
-         && reorder_operands_p (TREE_OPERAND (arg0, 0), arg1)
-         && (flag_sanitize & SANITIZE_SI_OVERFLOW) == 0)
-       return fold_build2_loc (loc, MINUS_EXPR, type,
-                           fold_convert_loc (loc, type, arg1),
-                           fold_convert_loc (loc, type,
-                                             TREE_OPERAND (arg0, 0)));
-
       if (INTEGRAL_TYPE_P (type) || VECTOR_INTEGER_TYPE_P (type))
        {
-         /* Convert ~A + 1 to -A.  */
-         if (TREE_CODE (arg0) == BIT_NOT_EXPR
-             && integer_each_onep (arg1))
-           return fold_build1_loc (loc, NEGATE_EXPR, type,
-                               fold_convert_loc (loc, type,
-                                                 TREE_OPERAND (arg0, 0)));
-
-         /* ~X + X is -1.  */
-         if (TREE_CODE (arg0) == BIT_NOT_EXPR
-             && !TYPE_OVERFLOW_TRAPS (type))
-           {
-             tree tem = TREE_OPERAND (arg0, 0);
-
-             STRIP_NOPS (tem);
-             if (operand_equal_p (tem, arg1, 0))
-               {
-                 t1 = build_all_ones_cst (type);
-                 return omit_one_operand_loc (loc, type, t1, arg1);
-               }
-           }
-
-         /* X + ~X is -1.  */
-         if (TREE_CODE (arg1) == BIT_NOT_EXPR
-             && !TYPE_OVERFLOW_TRAPS (type))
-           {
-             tree tem = TREE_OPERAND (arg1, 0);
-
-             STRIP_NOPS (tem);
-             if (operand_equal_p (arg0, tem, 0))
-               {
-                 t1 = build_all_ones_cst (type);
-                 return omit_one_operand_loc (loc, type, t1, arg0);
-               }
-           }
-
          /* X + (X / CST) * -CST is X % CST.  */
          if (TREE_CODE (arg1) == MULT_EXPR
              && TREE_CODE (TREE_OPERAND (arg1, 0)) == TRUNC_DIV_EXPR
@@ -10469,11 +10418,6 @@ fold_binary_loc (location_t loc,
                return fold_build2_loc (loc, MINUS_EXPR, type, tmp, arg11);
            }
        }
-      /* A - (-B) -> A + B */
-      if (TREE_CODE (arg1) == NEGATE_EXPR)
-       return fold_build2_loc (loc, PLUS_EXPR, type, op0,
-                           fold_convert_loc (loc, type,
-                                             TREE_OPERAND (arg1, 0)));
       /* (-A) - B -> (-B) - A  where B is easily negated and we can swap.  */
       if (TREE_CODE (arg0) == NEGATE_EXPR
          && negate_expr_p (arg1)
index f4f9b8d..29b5ab2 100644 (file)
@@ -25,8 +25,9 @@ along with GCC; see the file COPYING3.  If not see
 
 /* Generic tree predicates we inherit.  */
 (define_predicates
-   integer_onep integer_zerop integer_all_onesp
-   real_zerop real_onep
+   integer_onep integer_zerop integer_all_onesp integer_minus_onep
+   integer_each_onep
+   real_zerop real_onep real_minus_onep
    CONSTANT_CLASS_P
    tree_expr_nonnegative_p)
 
@@ -239,10 +240,6 @@ along with GCC; see the file COPYING3.  If not see
   (bit_not (bit_not @0))
   @0)
 
-(simplify
- (negate (negate @0))
- @0)
-
 
 /* Associate (p +p off1) +p off2 as (p +p (off1 + off2)).  */
 (simplify
@@ -278,6 +275,116 @@ along with GCC; see the file COPYING3.  If not see
    (bit_and @0 { algn; })))
 
 
+/* We can't reassociate at all for saturating types.  */
+(if (!TYPE_SATURATING (type))
+
+ /* Contract negates.  */
+ /* A + (-B) -> A - B */
+ (simplify
+  (plus:c (convert1? @0) (convert2? (negate @1)))
+  /* Apply STRIP_NOPS on @0 and the negate.  */
+  (if (tree_nop_conversion_p (type, TREE_TYPE (@0))
+       && tree_nop_conversion_p (type, TREE_TYPE (@1))
+       && (flag_sanitize & SANITIZE_SI_OVERFLOW) == 0)
+   (minus (convert @0) (convert @1))))
+ /* A - (-B) -> A + B */
+ (simplify
+  (minus (convert1? @0) (convert2? (negate @1)))
+  (if (tree_nop_conversion_p (type, TREE_TYPE (@0))
+       && tree_nop_conversion_p (type, TREE_TYPE (@1)))
+   (plus (convert @0) (convert @1))))
+ /* -(-A) -> A */
+ (simplify
+  (negate (convert? (negate @1)))
+  (if (tree_nop_conversion_p (type, TREE_TYPE (@1))
+       && (TYPE_OVERFLOW_WRAPS (type)
+          || (flag_sanitize & SANITIZE_SI_OVERFLOW) == 0))
+   @1))
+
+ /* We can't reassociate floating-point or fixed-point plus or minus
+    because of saturation to +-Inf.  */
+ (if (!FLOAT_TYPE_P (type) && !FIXED_POINT_TYPE_P (type))
+
+  /* Match patterns that allow contracting a plus-minus pair
+     irrespective of overflow issues.  */
+  /* (A +- B) - A       ->  +- B */
+  /* (A +- B) -+ B      ->  A */
+  /* A - (A +- B)       -> -+ B */
+  /* A +- (B -+ A)      ->  +- B */
+  (simplify
+    (minus (plus:c @0 @1) @0)
+    @1)
+  (simplify
+    (minus (minus @0 @1) @0)
+    (negate @1))
+  (simplify
+    (plus:c (minus @0 @1) @1)
+    @0)
+  (simplify
+   (minus @0 (plus:c @0 @1))
+   (negate @1))
+  (simplify
+   (minus @0 (minus @0 @1))
+   @1)
+
+  /* (A +- CST) +- CST -> A + CST  */
+  (for outer_op (plus minus)
+   (for inner_op (plus minus)
+    (simplify
+     (outer_op (inner_op @0 CONSTANT_CLASS_P@1) CONSTANT_CLASS_P@2)
+     /* If the constant operation overflows we cannot do the transform
+       as we would introduce undefined overflow, for example
+       with (a - 1) + INT_MIN.  */
+     (with { tree cst = fold_binary (outer_op == inner_op
+                                    ? PLUS_EXPR : MINUS_EXPR, type, @1, @2); }
+      (if (cst && !TREE_OVERFLOW (cst))
+       (inner_op @0 { cst; } ))))))
+
+  /* (CST - A) +- CST -> CST - A  */
+  (for outer_op (plus minus)
+   (simplify
+    (outer_op (minus CONSTANT_CLASS_P@1 @0) CONSTANT_CLASS_P@2)
+    (with { tree cst = fold_binary (outer_op, type, @1, @2); }
+     (if (cst && !TREE_OVERFLOW (cst))
+      (minus { cst; } @0)))))
+
+  /* ~A + A -> -1 */
+  (simplify
+   (plus:c (bit_not @0) @0)
+   (if (!TYPE_OVERFLOW_TRAPS (type))
+    { build_all_ones_cst (type); }))
+
+  /* ~A + 1 -> -A */
+  (simplify
+   (plus (bit_not @0) integer_each_onep)
+   (negate @0))
+
+  /* (T)(P + A) - (T)P -> (T) A */
+  (for add (plus pointer_plus)
+   (simplify
+    (minus (convert (add @0 @1))
+     (convert @0))
+    (if (TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (@1))
+        /* For integer types, if A has a smaller type
+           than T the result depends on the possible
+           overflow in P + A.
+           E.g. T=size_t, A=(unsigned)429497295, P>0.
+           However, if an overflow in P + A would cause
+           undefined behavior, we can assume that there
+           is no overflow.  */
+        || (INTEGRAL_TYPE_P (TREE_TYPE (@0))
+            && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0)))
+        /* For pointer types, if the conversion of A to the
+           final type requires a sign- or zero-extension,
+           then we have to punt - it is not defined which
+           one is correct.  */
+        || (POINTER_TYPE_P (TREE_TYPE (@0))
+            && TREE_CODE (@1) == INTEGER_CST
+            && tree_int_cst_sign_bit (@1) == 0))
+     (convert @1))))))
+
+
+
 /* Simplifications of conversions.  */
 
 /* Basic strip-useless-type-conversions / strip_nops.  */
index 2d6a9fb..b47f7e2 100644 (file)
@@ -1920,359 +1920,6 @@ simplify_rotate (gimple_stmt_iterator *gsi)
   return true;
 }
 
-/* Perform re-associations of the plus or minus statement STMT that are
-   always permitted.  Returns true if the CFG was changed.  */
-
-static bool
-associate_plusminus (gimple_stmt_iterator *gsi)
-{
-  gimple stmt = gsi_stmt (*gsi);
-  tree rhs1 = gimple_assign_rhs1 (stmt);
-  tree rhs2 = gimple_assign_rhs2 (stmt);
-  enum tree_code code = gimple_assign_rhs_code (stmt);
-  bool changed;
-
-  /* We can't reassociate at all for saturating types.  */
-  if (TYPE_SATURATING (TREE_TYPE (rhs1)))
-    return false;
-
-  /* First contract negates.  */
-  do
-    {
-      changed = false;
-
-      /* A +- (-B) -> A -+ B.  */
-      if (TREE_CODE (rhs2) == SSA_NAME)
-       {
-         gimple def_stmt = SSA_NAME_DEF_STMT (rhs2);
-         if (is_gimple_assign (def_stmt)
-             && gimple_assign_rhs_code (def_stmt) == NEGATE_EXPR
-             && can_propagate_from (def_stmt))
-           {
-             code = (code == MINUS_EXPR) ? PLUS_EXPR : MINUS_EXPR;
-             gimple_assign_set_rhs_code (stmt, code);
-             rhs2 = gimple_assign_rhs1 (def_stmt);
-             gimple_assign_set_rhs2 (stmt, rhs2);
-             gimple_set_modified (stmt, true);
-             changed = true;
-           }
-       }
-
-      /* (-A) + B -> B - A.  */
-      if (TREE_CODE (rhs1) == SSA_NAME
-         && code == PLUS_EXPR)
-       {
-         gimple def_stmt = SSA_NAME_DEF_STMT (rhs1);
-         if (is_gimple_assign (def_stmt)
-             && gimple_assign_rhs_code (def_stmt) == NEGATE_EXPR
-             && can_propagate_from (def_stmt))
-           {
-             code = MINUS_EXPR;
-             gimple_assign_set_rhs_code (stmt, code);
-             rhs1 = rhs2;
-             gimple_assign_set_rhs1 (stmt, rhs1);
-             rhs2 = gimple_assign_rhs1 (def_stmt);
-             gimple_assign_set_rhs2 (stmt, rhs2);
-             gimple_set_modified (stmt, true);
-             changed = true;
-           }
-       }
-    }
-  while (changed);
-
-  /* We can't reassociate floating-point or fixed-point plus or minus
-     because of saturation to +-Inf.  */
-  if (FLOAT_TYPE_P (TREE_TYPE (rhs1))
-      || FIXED_POINT_TYPE_P (TREE_TYPE (rhs1)))
-    goto out;
-
-  /* Second match patterns that allow contracting a plus-minus pair
-     irrespective of overflow issues.
-
-       (A +- B) - A       ->  +- B
-       (A +- B) -+ B      ->  A
-       (CST +- A) +- CST  ->  CST +- A
-       (A +- CST) +- CST  ->  A +- CST
-       ~A + A             ->  -1
-       ~A + 1             ->  -A 
-       A - (A +- B)       ->  -+ B
-       A +- (B +- A)      ->  +- B
-       CST +- (CST +- A)  ->  CST +- A
-       CST +- (A +- CST)  ->  CST +- A
-       A + ~A             ->  -1
-       (T)(P + A) - (T)P  -> (T)A
-
-     via commutating the addition and contracting operations to zero
-     by reassociation.  */
-
-  if (TREE_CODE (rhs1) == SSA_NAME)
-    {
-      gimple def_stmt = SSA_NAME_DEF_STMT (rhs1);
-      if (is_gimple_assign (def_stmt) && can_propagate_from (def_stmt))
-       {
-         enum tree_code def_code = gimple_assign_rhs_code (def_stmt);
-         if (def_code == PLUS_EXPR
-             || def_code == MINUS_EXPR)
-           {
-             tree def_rhs1 = gimple_assign_rhs1 (def_stmt);
-             tree def_rhs2 = gimple_assign_rhs2 (def_stmt);
-             if (operand_equal_p (def_rhs1, rhs2, 0)
-                 && code == MINUS_EXPR)
-               {
-                 /* (A +- B) - A -> +- B.  */
-                 code = ((def_code == PLUS_EXPR)
-                         ? TREE_CODE (def_rhs2) : NEGATE_EXPR);
-                 rhs1 = def_rhs2;
-                 rhs2 = NULL_TREE;
-                 gimple_assign_set_rhs_with_ops (gsi, code, rhs1, NULL_TREE);
-                 gcc_assert (gsi_stmt (*gsi) == stmt);
-                 gimple_set_modified (stmt, true);
-               }
-             else if (operand_equal_p (def_rhs2, rhs2, 0)
-                      && code != def_code)
-               {
-                 /* (A +- B) -+ B -> A.  */
-                 code = TREE_CODE (def_rhs1);
-                 rhs1 = def_rhs1;
-                 rhs2 = NULL_TREE;
-                 gimple_assign_set_rhs_with_ops (gsi, code, rhs1, NULL_TREE);
-                 gcc_assert (gsi_stmt (*gsi) == stmt);
-                 gimple_set_modified (stmt, true);
-               }
-             else if (CONSTANT_CLASS_P (rhs2)
-                      && CONSTANT_CLASS_P (def_rhs1))
-               {
-                 /* (CST +- A) +- CST -> CST +- A.  */
-                 tree cst = fold_binary (code, TREE_TYPE (rhs1),
-                                         def_rhs1, rhs2);
-                 if (cst && !TREE_OVERFLOW (cst))
-                   {
-                     code = def_code;
-                     gimple_assign_set_rhs_code (stmt, code);
-                     rhs1 = cst;
-                     gimple_assign_set_rhs1 (stmt, rhs1);
-                     rhs2 = def_rhs2;
-                     gimple_assign_set_rhs2 (stmt, rhs2);
-                     gimple_set_modified (stmt, true);
-                   }
-               }
-             else if (CONSTANT_CLASS_P (rhs2)
-                      && CONSTANT_CLASS_P (def_rhs2))
-               {
-                 /* (A +- CST) +- CST -> A +- CST.  */
-                 enum tree_code mix = (code == def_code)
-                                      ? PLUS_EXPR : MINUS_EXPR;
-                 tree cst = fold_binary (mix, TREE_TYPE (rhs1),
-                                         def_rhs2, rhs2);
-                 if (cst && !TREE_OVERFLOW (cst))
-                   {
-                     code = def_code;
-                     gimple_assign_set_rhs_code (stmt, code);
-                     rhs1 = def_rhs1;
-                     gimple_assign_set_rhs1 (stmt, rhs1);
-                     rhs2 = cst;
-                     gimple_assign_set_rhs2 (stmt, rhs2);
-                     gimple_set_modified (stmt, true);
-                   }
-               }
-           }
-         else if (def_code == BIT_NOT_EXPR && code == PLUS_EXPR)
-           {
-             tree def_rhs1 = gimple_assign_rhs1 (def_stmt);
-             if (operand_equal_p (def_rhs1, rhs2, 0))
-               {
-                 /* ~A + A -> -1.  */
-                 rhs1 = build_all_ones_cst (TREE_TYPE (rhs2));
-                 rhs2 = NULL_TREE;
-                 code = TREE_CODE (rhs1);
-                 gimple_assign_set_rhs_with_ops (gsi, code, rhs1, NULL_TREE);
-                 gcc_assert (gsi_stmt (*gsi) == stmt);
-                 gimple_set_modified (stmt, true);
-               }
-             else if ((TREE_CODE (TREE_TYPE (rhs2)) != COMPLEX_TYPE
-                       && integer_onep (rhs2))
-                      || (TREE_CODE (rhs2) == COMPLEX_CST
-                          && integer_onep (TREE_REALPART (rhs2))
-                          && integer_onep (TREE_IMAGPART (rhs2))))
-               {
-                 /* ~A + 1 -> -A.  */
-                 code = NEGATE_EXPR;
-                 rhs1 = def_rhs1;
-                 rhs2 = NULL_TREE;
-                 gimple_assign_set_rhs_with_ops (gsi, code, rhs1, NULL_TREE);
-                 gcc_assert (gsi_stmt (*gsi) == stmt);
-                 gimple_set_modified (stmt, true);
-               }
-           }
-         else if (code == MINUS_EXPR
-                  && CONVERT_EXPR_CODE_P (def_code)
-                  && TREE_CODE (gimple_assign_rhs1 (def_stmt)) == SSA_NAME
-                  && TREE_CODE (rhs2) == SSA_NAME)
-           {
-             /* (T)(P + A) - (T)P -> (T)A.  */
-             gimple def_stmt2 = SSA_NAME_DEF_STMT (rhs2);
-             if (is_gimple_assign (def_stmt2)
-                 && can_propagate_from (def_stmt2)
-                 && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def_stmt2))
-                 && TREE_CODE (gimple_assign_rhs1 (def_stmt2)) == SSA_NAME)
-               {
-                 /* Now we have (T)X - (T)P.  */
-                 tree p = gimple_assign_rhs1 (def_stmt2);
-                 def_stmt2 = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (def_stmt));
-                 if (is_gimple_assign (def_stmt2)
-                     && can_propagate_from (def_stmt2)
-                     && (gimple_assign_rhs_code (def_stmt2) == POINTER_PLUS_EXPR
-                         || gimple_assign_rhs_code (def_stmt2) == PLUS_EXPR)
-                     && gimple_assign_rhs1 (def_stmt2) == p)
-                   {
-                     /* And finally (T)(P + A) - (T)P.  */
-                     tree a = gimple_assign_rhs2 (def_stmt2);
-                     if (TYPE_PRECISION (TREE_TYPE (rhs1))
-                         <= TYPE_PRECISION (TREE_TYPE (a))
-                         /* For integer types, if A has a smaller type
-                            than T the result depends on the possible
-                            overflow in P + A.
-                            E.g. T=size_t, A=(unsigned)429497295, P>0.
-                            However, if an overflow in P + A would cause
-                            undefined behavior, we can assume that there
-                            is no overflow.  */
-                         || (INTEGRAL_TYPE_P (TREE_TYPE (p))
-                             && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (p)))
-                         /* For pointer types, if the conversion of A to the
-                            final type requires a sign- or zero-extension,
-                            then we have to punt - it is not defined which
-                            one is correct.  */
-                         || (POINTER_TYPE_P (TREE_TYPE (p))
-                             && TREE_CODE (a) == INTEGER_CST
-                             && tree_int_cst_sign_bit (a) == 0))
-                       {
-                         if (issue_strict_overflow_warning
-                             (WARN_STRICT_OVERFLOW_MISC)
-                             && TYPE_PRECISION (TREE_TYPE (rhs1))
-                                > TYPE_PRECISION (TREE_TYPE (a))
-                             && INTEGRAL_TYPE_P (TREE_TYPE (p)))
-                           warning_at (gimple_location (stmt),
-                                       OPT_Wstrict_overflow,
-                                       "assuming signed overflow does not "
-                                       "occur when assuming that "
-                                       "(T)(P + A) - (T)P is always (T)A");
-                         if (useless_type_conversion_p (TREE_TYPE (rhs1),
-                                                        TREE_TYPE (a)))
-                           code = TREE_CODE (a);
-                         else
-                           code = NOP_EXPR;
-                         rhs1 = a;
-                         rhs2 = NULL_TREE;
-                         gimple_assign_set_rhs_with_ops (gsi, code, rhs1,
-                                                         rhs2);
-                         gcc_assert (gsi_stmt (*gsi) == stmt);
-                         gimple_set_modified (stmt, true);
-                       }
-                   }
-               }
-           }
-       }
-    }
-
-  if (rhs2 && TREE_CODE (rhs2) == SSA_NAME)
-    {
-      gimple def_stmt = SSA_NAME_DEF_STMT (rhs2);
-      if (is_gimple_assign (def_stmt) && can_propagate_from (def_stmt))
-       {
-         enum tree_code def_code = gimple_assign_rhs_code (def_stmt);
-         if (def_code == PLUS_EXPR
-             || def_code == MINUS_EXPR)
-           {
-             tree def_rhs1 = gimple_assign_rhs1 (def_stmt);
-             tree def_rhs2 = gimple_assign_rhs2 (def_stmt);
-             if (operand_equal_p (def_rhs1, rhs1, 0)
-                 && code == MINUS_EXPR)
-               {
-                 /* A - (A +- B) -> -+ B.  */
-                 code = ((def_code == PLUS_EXPR)
-                         ? NEGATE_EXPR : TREE_CODE (def_rhs2));
-                 rhs1 = def_rhs2;
-                 rhs2 = NULL_TREE;
-                 gimple_assign_set_rhs_with_ops (gsi, code, rhs1, NULL_TREE);
-                 gcc_assert (gsi_stmt (*gsi) == stmt);
-                 gimple_set_modified (stmt, true);
-               }
-             else if (operand_equal_p (def_rhs2, rhs1, 0)
-                      && code != def_code)
-               {
-                 /* A +- (B +- A) -> +- B.  */
-                 code = ((code == PLUS_EXPR)
-                         ? TREE_CODE (def_rhs1) : NEGATE_EXPR);
-                 rhs1 = def_rhs1;
-                 rhs2 = NULL_TREE;
-                 gimple_assign_set_rhs_with_ops (gsi, code, rhs1, NULL_TREE);
-                 gcc_assert (gsi_stmt (*gsi) == stmt);
-                 gimple_set_modified (stmt, true);
-               }
-             else if (CONSTANT_CLASS_P (rhs1)
-                      && CONSTANT_CLASS_P (def_rhs1))
-               {
-                 /* CST +- (CST +- A) -> CST +- A.  */
-                 tree cst = fold_binary (code, TREE_TYPE (rhs2),
-                                         rhs1, def_rhs1);
-                 if (cst && !TREE_OVERFLOW (cst))
-                   {
-                     code = (code == def_code ? PLUS_EXPR : MINUS_EXPR);
-                     gimple_assign_set_rhs_code (stmt, code);
-                     rhs1 = cst;
-                     gimple_assign_set_rhs1 (stmt, rhs1);
-                     rhs2 = def_rhs2;
-                     gimple_assign_set_rhs2 (stmt, rhs2);
-                     gimple_set_modified (stmt, true);
-                   }
-               }
-             else if (CONSTANT_CLASS_P (rhs1)
-                      && CONSTANT_CLASS_P (def_rhs2))
-               {
-                 /* CST +- (A +- CST) -> CST +- A.  */
-                 tree cst = fold_binary (def_code == code
-                                         ? PLUS_EXPR : MINUS_EXPR,
-                                         TREE_TYPE (rhs2),
-                                         rhs1, def_rhs2);
-                 if (cst && !TREE_OVERFLOW (cst))
-                   {
-                     rhs1 = cst;
-                     gimple_assign_set_rhs1 (stmt, rhs1);
-                     rhs2 = def_rhs1;
-                     gimple_assign_set_rhs2 (stmt, rhs2);
-                     gimple_set_modified (stmt, true);
-                   }
-               }
-           }
-         else if (def_code == BIT_NOT_EXPR)
-           {
-             tree def_rhs1 = gimple_assign_rhs1 (def_stmt);
-             if (code == PLUS_EXPR
-                 && operand_equal_p (def_rhs1, rhs1, 0))
-               {
-                 /* A + ~A -> -1.  */
-                 rhs1 = build_all_ones_cst (TREE_TYPE (rhs1));
-                 rhs2 = NULL_TREE;
-                 code = TREE_CODE (rhs1);
-                 gimple_assign_set_rhs_with_ops (gsi, code, rhs1, NULL_TREE);
-                 gcc_assert (gsi_stmt (*gsi) == stmt);
-                 gimple_set_modified (stmt, true);
-               }
-           }
-       }
-    }
-
-out:
-  if (gimple_modified_p (stmt))
-    {
-      fold_stmt_inplace (gsi);
-      update_stmt (stmt);
-      return true;
-    }
-
-  return false;
-}
-
 /* Combine an element access with a shuffle.  Returns true if there were
    any changes made, else it returns false.  */
  
@@ -2805,14 +2452,6 @@ pass_forwprop::execute (function *fun)
                          || code == BIT_XOR_EXPR)
                         && simplify_rotate (&gsi))
                  changed = true;
-               else if (code == PLUS_EXPR
-                        || code == MINUS_EXPR)
-                 {
-                   changed = associate_plusminus (&gsi);
-                   if (changed
-                       && maybe_clean_or_replace_eh_stmt (stmt, stmt))
-                     bitmap_set_bit (to_purge, bb->index);
-                 }
                else if (code == VEC_PERM_EXPR)
                  {
                    int did_something = simplify_permutation (&gsi);
index c7c4c41..221f0dd 100644 (file)
@@ -11659,6 +11659,27 @@ block_ultimate_origin (const_tree block)
     }
 }
 
+/* Return true iff conversion from INNER_TYPE to OUTER_TYPE generates
+   no instruction.  */
+
+bool
+tree_nop_conversion_p (const_tree outer_type, const_tree inner_type)
+{
+  /* Use precision rather then machine mode when we can, which gives
+     the correct answer even for submode (bit-field) types.  */
+  if ((INTEGRAL_TYPE_P (outer_type)
+       || POINTER_TYPE_P (outer_type)
+       || TREE_CODE (outer_type) == OFFSET_TYPE)
+      && (INTEGRAL_TYPE_P (inner_type)
+         || POINTER_TYPE_P (inner_type)
+         || TREE_CODE (inner_type) == OFFSET_TYPE))
+    return TYPE_PRECISION (outer_type) == TYPE_PRECISION (inner_type);
+
+  /* Otherwise fall back on comparing machine modes (e.g. for
+     aggregate types, floats).  */
+  return TYPE_MODE (outer_type) == TYPE_MODE (inner_type);
+}
+
 /* Return true iff conversion in EXP generates no instruction.  Mark
    it inline so that we fully inline into the stripping functions even
    though we have two uses of this function.  */
@@ -11680,19 +11701,7 @@ tree_nop_conversion (const_tree exp)
   if (!inner_type)
     return false;
 
-  /* Use precision rather then machine mode when we can, which gives
-     the correct answer even for submode (bit-field) types.  */
-  if ((INTEGRAL_TYPE_P (outer_type)
-       || POINTER_TYPE_P (outer_type)
-       || TREE_CODE (outer_type) == OFFSET_TYPE)
-      && (INTEGRAL_TYPE_P (inner_type)
-         || POINTER_TYPE_P (inner_type)
-         || TREE_CODE (inner_type) == OFFSET_TYPE))
-    return TYPE_PRECISION (outer_type) == TYPE_PRECISION (inner_type);
-
-  /* Otherwise fall back on comparing machine modes (e.g. for
-     aggregate types, floats).  */
-  return TYPE_MODE (outer_type) == TYPE_MODE (inner_type);
+  return tree_nop_conversion_p (outer_type, inner_type);
 }
 
 /* Return true iff conversion in EXP generates no instruction.  Don't
index d9fe0c2..0577d51 100644 (file)
@@ -4226,6 +4226,7 @@ extern bool is_typedef_decl (tree x);
 extern bool typedef_variant_p (tree);
 extern bool auto_var_in_fn_p (const_tree, const_tree);
 extern tree build_low_bits_mask (tree, unsigned);
+extern bool tree_nop_conversion_p (const_tree, const_tree);
 extern tree tree_strip_nop_conversions (tree);
 extern tree tree_strip_sign_nop_conversions (tree);
 extern const_tree strip_invariant_refs (const_tree);