This merges patterns from associate_plusminus and adjusts them with
details from their fold-const.c pendants.  It also fixes missing
flag_sanitize checks on negate contraction on the way.

This shows places where folds STRIP_NOPs was important (but also
shows where it may create wrong code - sth the patch doesn't fix
yet).  Without the conditonal convert handling on the negate
contraction we regress quite a few GENERIC folding testcases.

Note that the other explicit reassocation patterns are handled
by folds associate: piece which I am sure we don't implement
fully by the few patterns (OTOH on GIMPLE we have a reassoc
pass for that anyway).  So not too many patterns were removed
from fold.

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk.

Richard.

2014-11-11  Richard Biener  <rguent...@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.

Index: trunk/gcc/fold-const.c
===================================================================
*** trunk.orig/gcc/fold-const.c 2014-11-11 09:54:58.840824189 +0100
--- trunk/gcc/fold-const.c      2014-11-11 10:06:29.274793976 +0100
*************** fold_binary_loc (location_t loc,
*** 9939,9997 ****
        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
--- 9939,9946 ----
*************** fold_binary_loc (location_t loc,
*** 10469,10479 ****
                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)
--- 10418,10423 ----
Index: trunk/gcc/match.pd
===================================================================
*** trunk.orig/gcc/match.pd     2014-11-11 09:54:58.840824189 +0100
--- trunk/gcc/match.pd  2014-11-11 11:55:27.283507870 +0100
*************** along with GCC; see the file COPYING3.
*** 25,32 ****
  
  /* Generic tree predicates we inherit.  */
  (define_predicates
!    integer_onep integer_zerop integer_all_onesp
!    real_zerop real_onep
     CONSTANT_CLASS_P
     tree_expr_nonnegative_p)
  
--- 25,33 ----
  
  /* Generic tree predicates we inherit.  */
  (define_predicates
!    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)
  
*************** along with GCC; see the file COPYING3.
*** 239,248 ****
    (bit_not (bit_not @0))
    @0)
  
- (simplify
-  (negate (negate @0))
-  @0)
- 
  
  /* Associate (p +p off1) +p off2 as (p +p (off1 + off2)).  */
  (simplify
--- 240,245 ----
*************** along with GCC; see the file COPYING3.
*** 278,283 ****
--- 275,390 ----
     (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: trunk/gcc/tree-ssa-forwprop.c
===================================================================
*** trunk.orig/gcc/tree-ssa-forwprop.c  2014-11-11 09:54:58.840824189 +0100
--- trunk/gcc/tree-ssa-forwprop.c       2014-11-11 10:06:29.277793975 +0100
*************** simplify_rotate (gimple_stmt_iterator *g
*** 1920,2278 ****
    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.  */
   
--- 1920,1925 ----
*************** pass_forwprop::execute (function *fun)
*** 2805,2818 ****
                          || 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);
--- 2452,2457 ----
Index: trunk/gcc/tree.c
===================================================================
*** trunk.orig/gcc/tree.c       2014-11-07 11:34:50.437685555 +0100
--- trunk/gcc/tree.c    2014-11-11 11:12:05.077621744 +0100
*************** block_ultimate_origin (const_tree block)
*** 11659,11664 ****
--- 11659,11685 ----
      }
  }
  
+ /* 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.  */
*************** tree_nop_conversion (const_tree exp)
*** 11680,11698 ****
    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 true iff conversion in EXP generates no instruction.  Don't
--- 11701,11707 ----
    if (!inner_type)
      return false;
  
!   return tree_nop_conversion_p (outer_type, inner_type);
  }
  
  /* Return true iff conversion in EXP generates no instruction.  Don't
Index: trunk/gcc/tree.h
===================================================================
*** trunk.orig/gcc/tree.h       2014-11-06 10:46:21.676593734 +0100
--- trunk/gcc/tree.h    2014-11-11 11:12:37.388620330 +0100
*************** extern bool is_typedef_decl (tree x);
*** 4226,4231 ****
--- 4226,4232 ----
  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);

Reply via email to