fold-const.c (fold_addr_of_array_ref_difference): Properly convert operands before...
authorRichard Biener <rguenther@suse.de>
Thu, 22 Oct 2015 08:38:15 +0000 (08:38 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Thu, 22 Oct 2015 08:38:15 +0000 (08:38 +0000)
2015-10-22  Richard Biener  <rguenther@suse.de>

* fold-const.c (fold_addr_of_array_ref_difference): Properly
convert operands before folding a MINUS_EXPR.
(fold_binary_loc): Move simplification of MINUS_EXPR on
converted POINTER_PLUS_EXPRs ...
* match.pd: ... here.

c/
* c-typeck.c (c_finish_omp_clauses): Properly convert operands
before folding a MINUS_EXPR.

cp/
* semantics.c (cp_finish_omp_clause_depend_sink): Properly convert
before folding a MINUS_EXPR.
(finish_omp_clauses): Likewise.

From-SVN: r229167

gcc/ChangeLog
gcc/c/ChangeLog
gcc/c/c-typeck.c
gcc/cp/ChangeLog
gcc/cp/semantics.c
gcc/fold-const.c
gcc/match.pd

index 2ec877a92566c8393fda139f815504cc96f092fb..63319ad6ed533805d4fb93a331e6a235cf2f0d78 100644 (file)
@@ -1,3 +1,11 @@
+2015-10-22  Richard Biener  <rguenther@suse.de>
+
+       * fold-const.c (fold_addr_of_array_ref_difference): Properly
+       convert operands before folding a MINUS_EXPR.
+       (fold_binary_loc): Move simplification of MINUS_EXPR on
+       converted POINTER_PLUS_EXPRs ...
+       * match.pd: ... here.
+
 2015-10-22  Richard Sandiford  <richard.sandiford@arm.com>
 
        * builtins.c (fold_builtin_tan): Delete.
index b5179a3a714731fb33c61aec8a6f999ab16a15e1..aed7a627932f14d41088eddf94698ea60c093ddf 100644 (file)
@@ -1,3 +1,8 @@
+2015-10-22  Richard Biener  <rguenther@suse.de>
+
+       * c-typeck.c (c_finish_omp_clauses): Properly convert operands
+       before folding a MINUS_EXPR.
+
 2015-10-21  Marek Polacek  <polacek@redhat.com>
 
        PR c/68024
index 6b32781c03bef9312823bb96d5e1f6aaae7511e7..61c5313c25bc0758eb1f11ab36a68cfff9b73330 100644 (file)
@@ -12547,7 +12547,9 @@ c_finish_omp_clauses (tree clauses, bool is_omp, bool declare_simd)
              s = pointer_int_sum (OMP_CLAUSE_LOCATION (c), PLUS_EXPR,
                                   OMP_CLAUSE_DECL (c), s);
              s = fold_build2_loc (OMP_CLAUSE_LOCATION (c), MINUS_EXPR,
-                                  sizetype, s, OMP_CLAUSE_DECL (c));
+                                  sizetype, fold_convert (sizetype, s),
+                                  fold_convert
+                                    (sizetype, OMP_CLAUSE_DECL (c)));
              if (s == error_mark_node)
                s = size_one_node;
              OMP_CLAUSE_LINEAR_STEP (c) = s;
@@ -12671,7 +12673,9 @@ c_finish_omp_clauses (tree clauses, bool is_omp, bool declare_simd)
                                                 neg ? MINUS_EXPR : PLUS_EXPR,
                                                 decl, offset);
                      t2 = fold_build2_loc (OMP_CLAUSE_LOCATION (c), MINUS_EXPR,
-                                           sizetype, t2, decl);
+                                           sizetype,
+                                           fold_convert (sizetype, t2),
+                                           fold_convert (sizetype, decl));
                      if (t2 == error_mark_node)
                        {
                          remove = true;
index 0ed4e29615da0d4e0c9cc18a17821cfcc5cbd611..8dbff11574c8cb1fda78f6af57e485e356e8edee 100644 (file)
@@ -1,3 +1,9 @@
+2015-10-22  Richard Biener  <rguenther@suse.de>
+
+       * semantics.c (cp_finish_omp_clause_depend_sink): Properly convert
+       before folding a MINUS_EXPR.
+       (finish_omp_clauses): Likewise.
+
 2015-10-21  Paolo Carlini  <paolo.carlini@oracle.com>
 
        PR c++/66781
index c0a8b32276782a902b4ee05e8709fde063ec12a8..11315d90668d4b822cbd2070c4e636cfe055fdce 100644 (file)
@@ -5632,8 +5632,9 @@ cp_finish_omp_clause_depend_sink (tree sink_clause)
                                     neg ? MINUS_EXPR : PLUS_EXPR,
                                     decl, offset);
          t2 = fold_build2_loc (OMP_CLAUSE_LOCATION (sink_clause),
-                               MINUS_EXPR, sizetype, t2,
-                               decl);
+                               MINUS_EXPR, sizetype,
+                               fold_convert (sizetype, t2),
+                               fold_convert (sizetype, decl));
          if (t2 == error_mark_node)
            return true;
          TREE_PURPOSE (t) = t2;
@@ -5783,7 +5784,9 @@ finish_omp_clauses (tree clauses, bool allow_fields, bool declare_simd)
                      t = pointer_int_sum (OMP_CLAUSE_LOCATION (c), PLUS_EXPR,
                                           d, t);
                      t = fold_build2_loc (OMP_CLAUSE_LOCATION (c),
-                                          MINUS_EXPR, sizetype, t, d);
+                                          MINUS_EXPR, sizetype,
+                                          fold_convert (sizetype, t),
+                                          fold_convert (sizetype, d));
                      if (t == error_mark_node)
                        {
                          remove = true;
@@ -5804,7 +5807,9 @@ finish_omp_clauses (tree clauses, bool allow_fields, bool declare_simd)
                      t = pointer_int_sum (OMP_CLAUSE_LOCATION (c), PLUS_EXPR,
                                           d, t);
                      t = fold_build2_loc (OMP_CLAUSE_LOCATION (c),
-                                          MINUS_EXPR, sizetype, t, d);
+                                          MINUS_EXPR, sizetype,
+                                          fold_convert (sizetype, t),
+                                          fold_convert (sizetype, d));
                      if (t == error_mark_node)
                        {
                          remove = true;
index 602ea240cb4b148442890fff3b0358556f87d4ff..c4be017c50c55864ce1b3ba212215fb8807969fb 100644 (file)
@@ -8841,9 +8841,11 @@ fold_addr_of_array_ref_difference (location_t loc, tree type,
           = fold_addr_of_array_ref_difference (loc, type, base0, base1)))
       || (INDIRECT_REF_P (base0)
          && INDIRECT_REF_P (base1)
-         && (base_offset = fold_binary_loc (loc, MINUS_EXPR, type,
-                                            TREE_OPERAND (base0, 0),
-                                            TREE_OPERAND (base1, 0))))
+         && (base_offset
+               = fold_binary_loc (loc, MINUS_EXPR, type,
+                                  fold_convert (type, TREE_OPERAND (base0, 0)),
+                                  fold_convert (type,
+                                                TREE_OPERAND (base1, 0)))))
       || operand_equal_p (base0, base1, OEP_ADDRESS_OF))
     {
       tree op0 = fold_convert_loc (loc, type, TREE_OPERAND (aref0, 1));
@@ -9637,48 +9639,6 @@ fold_binary_loc (location_t loc,
       return NULL_TREE;
 
     case MINUS_EXPR:
-      /* Pointer simplifications for subtraction, simple reassociations. */
-      if (POINTER_TYPE_P (TREE_TYPE (arg1)) && POINTER_TYPE_P (TREE_TYPE (arg0)))
-       {
-         /* (PTR0 p+ A) - (PTR1 p+ B) -> (PTR0 - PTR1) + (A - B) */
-         if (TREE_CODE (arg0) == POINTER_PLUS_EXPR
-             && TREE_CODE (arg1) == POINTER_PLUS_EXPR)
-           {
-             tree arg00 = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0));
-             tree arg01 = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 1));
-             tree arg10 = fold_convert_loc (loc, type, TREE_OPERAND (arg1, 0));
-             tree arg11 = fold_convert_loc (loc, type, TREE_OPERAND (arg1, 1));
-             return fold_build2_loc (loc, PLUS_EXPR, type,
-                                 fold_build2_loc (loc, MINUS_EXPR, type,
-                                              arg00, arg10),
-                                 fold_build2_loc (loc, MINUS_EXPR, type,
-                                              arg01, arg11));
-           }
-         /* (PTR0 p+ A) - PTR1 -> (PTR0 - PTR1) + A, assuming PTR0 - PTR1 simplifies. */
-         else if (TREE_CODE (arg0) == POINTER_PLUS_EXPR)
-           {
-             tree arg00 = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0));
-             tree arg01 = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 1));
-             tree tmp = fold_binary_loc (loc, MINUS_EXPR, type, arg00,
-                                     fold_convert_loc (loc, type, arg1));
-             if (tmp)
-               return fold_build2_loc (loc, PLUS_EXPR, type, tmp, arg01);
-           }
-         /* PTR0 - (PTR1 p+ A) -> (PTR0 - PTR1) - A, assuming PTR0 - PTR1
-            simplifies. */
-         else if (TREE_CODE (arg1) == POINTER_PLUS_EXPR)
-           {
-             tree arg10 = fold_convert_loc (loc, type,
-                                            TREE_OPERAND (arg1, 0));
-             tree arg11 = fold_convert_loc (loc, type,
-                                            TREE_OPERAND (arg1, 1));
-             tree tmp = fold_binary_loc (loc, MINUS_EXPR, type,
-                                         fold_convert_loc (loc, type, arg0),
-                                         arg10);
-             if (tmp)
-               return fold_build2_loc (loc, MINUS_EXPR, type, tmp, arg11);
-           }
-       }
       /* (-A) - B -> (-B) - A  where B is easily negated and we can swap.  */
       if (TREE_CODE (arg0) == NEGATE_EXPR
          && negate_expr_p (arg1)
index 1ba43c44c16851d5ad4cfc2a3d5c86995c763c60..b399786bac2e85b15a84b80b9131a85f8cc5193b 100644 (file)
@@ -1056,7 +1056,57 @@ along with GCC; see the file COPYING3.  If not see
         || (POINTER_TYPE_P (TREE_TYPE (@0))
             && TREE_CODE (@1) == INTEGER_CST
             && tree_int_cst_sign_bit (@1) == 0))
-     (convert @1))))))
+     (convert @1))))
+
+  /* (T)P - (T)(P + A) -> -(T) A */
+  (for add (plus pointer_plus)
+   (simplify
+    (minus (convert @0)
+     (convert (add @0 @1)))
+    (if (element_precision (type) <= element_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))
+     (negate (convert @1)))))
+
+  /* (T)(P + A) - (T)(P + B) -> (T)A - (T)B */
+  (for add (plus pointer_plus)
+   (simplify
+    (minus (convert (add @0 @1))
+     (convert (add @0 @2)))
+    (if (element_precision (type) <= element_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
+            && TREE_CODE (@2) == INTEGER_CST
+            && tree_int_cst_sign_bit (@2) == 0))
+     (minus (convert @1) (convert @2)))))))
 
 
 /* Simplifications of MIN_EXPR and MAX_EXPR.  */