re PR tree-optimization/83269 (Wrong constant folding)
authorJakub Jelinek <jakub@redhat.com>
Fri, 15 Dec 2017 14:37:52 +0000 (15:37 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Fri, 15 Dec 2017 14:37:52 +0000 (15:37 +0100)
PR tree-optimization/83269
* fold-const.c (fold_binary_loc): Perform (-A) - B -> (-B) - A
subtraction in arg0's type if type is signed and arg0 is unsigned.
Formatting fix.

* gcc.c-torture/execute/pr83269.c: New test.

From-SVN: r255697

gcc/ChangeLog
gcc/fold-const.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/pr83269.c [new file with mode: 0644]

index 8d655acf2c8aee599d0e7514b9d27748e67b6aa2..60f621d8fd1b8f747778b179c634bd263f5910e2 100644 (file)
@@ -1,5 +1,10 @@
 2017-12-15  Jakub Jelinek  <jakub@redhat.com>
 
+       PR tree-optimization/83269
+       * fold-const.c (fold_binary_loc): Perform (-A) - B -> (-B) - A
+       subtraction in arg0's type if type is signed and arg0 is unsigned.
+       Formatting fix.
+
        PR sanitizer/81281
        * match.pd ((T)(P + A) - (T)P -> (T) A): Use @@0 instead of @0 and
        convert? on @0 instead of convert.  Check type of @1, not @0.
index 0f110765f44ba42754ddca3dbdcaf36f0809182d..9fc69e8058bb8d7c6458a96b0f2ebe6b121e04b1 100644 (file)
@@ -9098,8 +9098,8 @@ expr_not_equal_to (tree t, const wide_int &w)
    return NULL_TREE.  */
 
 tree
-fold_binary_loc (location_t loc,
-            enum tree_code code, tree type, tree op0, tree op1)
+fold_binary_loc (location_t loc, enum tree_code code, tree type,
+                tree op0, tree op1)
 {
   enum tree_code_class kind = TREE_CODE_CLASS (code);
   tree arg0, arg1, tem;
@@ -9769,10 +9769,17 @@ fold_binary_loc (location_t loc,
 
       /* (-A) - B -> (-B) - A  where B is easily negated and we can swap.  */
       if (TREE_CODE (arg0) == NEGATE_EXPR
-         && negate_expr_p (op1))
-       return fold_build2_loc (loc, MINUS_EXPR, type,
-                               negate_expr (op1),
-                               fold_convert_loc (loc, type,
+         && negate_expr_p (op1)
+         /* If arg0 is e.g. unsigned int and type is int, then this could
+            introduce UB, because if A is INT_MIN at runtime, the original
+            expression can be well defined while the latter is not.
+            See PR83269.  */
+         && !(ANY_INTEGRAL_TYPE_P (type)
+              && TYPE_OVERFLOW_UNDEFINED (type)
+              && ANY_INTEGRAL_TYPE_P (TREE_TYPE (arg0))
+              && !TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg0))))
+       return fold_build2_loc (loc, MINUS_EXPR, type, negate_expr (op1),
+                               fold_convert_loc (loc, type,
                                                  TREE_OPERAND (arg0, 0)));
 
       /* Fold __complex__ ( x, 0 ) - __complex__ ( 0, y ) to
index e1196919a3c4b94aed037d50b89a6c70de4be6ce..c87d2cd09800ef83aa7b3d4bd104062c51837fd8 100644 (file)
@@ -1,5 +1,8 @@
 2017-12-15  Jakub Jelinek  <jakub@redhat.com>
 
+       PR tree-optimization/83269
+       * gcc.c-torture/execute/pr83269.c: New test.
+
        PR sanitizer/81281
        * gcc.dg/pr81281-3.c: New test.
 
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr83269.c b/gcc/testsuite/gcc.c-torture/execute/pr83269.c
new file mode 100644 (file)
index 0000000..37fc5d1
--- /dev/null
@@ -0,0 +1,14 @@
+/* PR tree-optimization/83269 */
+
+int
+main ()
+{
+#if __SIZEOF_INT__ == 4 && __SIZEOF_LONG_LONG__ > 4 && __CHAR_BIT__ == 8
+  volatile unsigned char a = 1;
+  long long b = 0x80000000L;
+  int c = -((int)(-b) - (-0x7fffffff * a));
+  if (c != 1)
+    __builtin_abort ();
+#endif
+  return 0;
+}