re PR tree-optimization/80281 (Wrong constant folding)
authorRichard Biener <rguenther@suse.de>
Tue, 4 Apr 2017 09:06:04 +0000 (09:06 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Tue, 4 Apr 2017 09:06:04 +0000 (09:06 +0000)
2017-04-04  Richard Biener  <rguenther@suse.de>

PR middle-end/80281
* match.pd (A + (-B) -> A - B): Make sure to preserve unsigned
arithmetic done for the negate or the plus.  Simplify.
(A - (-B) -> A + B): Likewise.
* fold-const.c (split_tree): Make sure to not negate pointers.

* gcc.dg/torture/pr80281.c: New testcase.

From-SVN: r246674

gcc/ChangeLog
gcc/fold-const.c
gcc/match.pd
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/torture/pr80281.c [new file with mode: 0644]

index 4d113af985d293e5282966defc40e166b328290e..eceada15c3663f7f77705ac73790a1ef456c6df1 100644 (file)
@@ -1,3 +1,11 @@
+2017-04-04  Richard Biener  <rguenther@suse.de>
+
+       PR middle-end/80281
+       * match.pd (A + (-B) -> A - B): Make sure to preserve unsigned
+       arithmetic done for the negate or the plus.  Simplify.
+       (A - (-B) -> A + B): Likewise.
+       * fold-const.c (split_tree): Make sure to not negate pointers.
+
 2017-04-04  Segher Boessenkool  <segher@kernel.crashing.org>
 
        PR rtl-optimization/60818
index d0f1c0685ca05aa514c63f6f3321da3743ae556e..b4c117c84948f6994c2ac0354b76ce8d393eb2b4 100644 (file)
@@ -831,8 +831,12 @@ split_tree (location_t loc, tree in, tree type, enum tree_code code,
       /* Now do any needed negations.  */
       if (neg_litp_p)
        *minus_litp = *litp, *litp = 0;
-      if (neg_conp_p)
-       *conp = negate_expr (*conp);
+      if (neg_conp_p && *conp)
+       {
+         /* Convert to TYPE before negating.  */
+         *conp = fold_convert_loc (loc, type, *conp);
+         *conp = negate_expr (*conp);
+       }
       if (neg_var_p && var)
        {
          /* Convert to TYPE before negating.  */
@@ -859,7 +863,12 @@ split_tree (location_t loc, tree in, tree type, enum tree_code code,
        *minus_litp = *litp, *litp = 0;
       else if (*minus_litp)
        *litp = *minus_litp, *minus_litp = 0;
-      *conp = negate_expr (*conp);
+      if (*conp)
+       {
+         /* Convert to TYPE before negating.  */
+         *conp = fold_convert_loc (loc, type, *conp);
+         *conp = negate_expr (*conp);
+       }
       if (var)
        {
          /* Convert to TYPE before negating.  */
index 4e6f7199947719afe443740979dff139372606f2..357797877c868bd3985ab5f2e283a3431a5337a7 100644 (file)
@@ -1148,19 +1148,31 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
  /* 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))
+  (plus:c @0 (convert? (negate @1)))
+  /* Apply STRIP_NOPS on the negate.  */
+  (if (tree_nop_conversion_p (type, TREE_TYPE (@1))
        && !TYPE_OVERFLOW_SANITIZED (type))
-   (minus (convert @0) (convert @1))))
+   (with
+    {
+     tree t1 = type;
+     if (INTEGRAL_TYPE_P (type)
+        && TYPE_OVERFLOW_WRAPS (type) != TYPE_OVERFLOW_WRAPS (TREE_TYPE (@1)))
+       t1 = TYPE_OVERFLOW_WRAPS (type) ? type : TREE_TYPE (@1);
+    }
+    (convert (minus (convert:t1 @0) (convert:t1 @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))
+  (minus @0 (convert? (negate @1)))
+  (if (tree_nop_conversion_p (type, TREE_TYPE (@1))
        && !TYPE_OVERFLOW_SANITIZED (type))
-   (plus (convert @0) (convert @1))))
+   (with
+    {
+     tree t1 = type;
+     if (INTEGRAL_TYPE_P (type)
+        && TYPE_OVERFLOW_WRAPS (type) != TYPE_OVERFLOW_WRAPS (TREE_TYPE (@1)))
+       t1 = TYPE_OVERFLOW_WRAPS (type) ? type : TREE_TYPE (@1);
+    }
+    (convert (plus (convert:t1 @0) (convert:t1 @1))))))
  /* -(-A) -> A */
  (simplify
   (negate (convert? (negate @1)))
index 8a88678a4a398f4883010283b603b37fcba4822f..8d7418cd36642702dfa2cdcf6a8b9513cd3ab208 100644 (file)
@@ -1,3 +1,8 @@
+2017-04-04  Richard Biener  <rguenther@suse.de>
+
+       PR middle-end/80281
+       * gcc.dg/torture/pr80281.c: New testcase.
+
 2017-04-04  Richard Biener  <rguenther@suse.de>
 
        PR tree-optimization/80275
diff --git a/gcc/testsuite/gcc.dg/torture/pr80281.c b/gcc/testsuite/gcc.dg/torture/pr80281.c
new file mode 100644 (file)
index 0000000..bff4f6e
--- /dev/null
@@ -0,0 +1,14 @@
+/* { dg-run } */
+/* { dg-require-effective-target int32plus } */
+
+int
+main ()
+{
+  volatile int a = 0;
+  long long b = 2147483648LL;
+  int c = a % 2;
+  int x = ((int) -b + c) % -2147483647;
+  if (x != -1)
+    __builtin_abort ();
+  return 0;
+}