aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2017-04-04 09:06:04 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2017-04-04 09:06:04 +0000
commit248179b5fc812b294e2488b23fedaaabe099ad9d (patch)
tree46598b536dd7896cb9ef0ba26970bcac31af8696
parenta577fcf2d5ec9695efb5c086fd328cf378289a55 (diff)
downloadgcc-248179b5fc812b294e2488b23fedaaabe099ad9d.zip
gcc-248179b5fc812b294e2488b23fedaaabe099ad9d.tar.gz
gcc-248179b5fc812b294e2488b23fedaaabe099ad9d.tar.bz2
re PR tree-optimization/80281 (Wrong constant folding)
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
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/fold-const.c15
-rw-r--r--gcc/match.pd30
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr80281.c14
5 files changed, 60 insertions, 12 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 4d113af9..eceada1 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index d0f1c06..b4c117c 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -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. */
diff --git a/gcc/match.pd b/gcc/match.pd
index 4e6f719..3577978 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -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)))
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 8a88678..8d7418c 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,10 @@
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
* g++.dg/opt/pr80275.C: Make g static.
diff --git a/gcc/testsuite/gcc.dg/torture/pr80281.c b/gcc/testsuite/gcc.dg/torture/pr80281.c
new file mode 100644
index 0000000..bff4f6e6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr80281.c
@@ -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;
+}