diff options
author | Richard Biener <rguenther@suse.de> | 2017-04-04 09:06:04 +0000 |
---|---|---|
committer | Richard Biener <rguenth@gcc.gnu.org> | 2017-04-04 09:06:04 +0000 |
commit | 248179b5fc812b294e2488b23fedaaabe099ad9d (patch) | |
tree | 46598b536dd7896cb9ef0ba26970bcac31af8696 | |
parent | a577fcf2d5ec9695efb5c086fd328cf378289a55 (diff) | |
download | gcc-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/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/fold-const.c | 15 | ||||
-rw-r--r-- | gcc/match.pd | 30 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/torture/pr80281.c | 14 |
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; +} |