diff options
author | Jakub Jelinek <jakub@redhat.com> | 2024-02-26 10:08:45 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@redhat.com> | 2024-02-26 10:09:21 +0100 |
commit | 24aa051af7c59f37ec45aea754b48b97d210ea6d (patch) | |
tree | 0fb4c9002b4ab93d7a90f068d7ffcbcccd113cd6 /gcc | |
parent | f9d2a95be5680e04f53141c2675798b06d23f409 (diff) | |
download | gcc-24aa051af7c59f37ec45aea754b48b97d210ea6d.zip gcc-24aa051af7c59f37ec45aea754b48b97d210ea6d.tar.gz gcc-24aa051af7c59f37ec45aea754b48b97d210ea6d.tar.bz2 |
match.pd: Guard 2 simplifications on integral TYPE_OVERFLOW_UNDEFINED [PR114090]
These 2 patterns are incorrect on floating point, or for -fwrapv, or
for -ftrapv, or the first one for unsigned types (the second one is
mathematically correct, but we ought to just fold that to 0 instead).
So, the following patch properly guards this.
I think we don't need && !TYPE_OVERFLOW_SANITIZED (type) because
in both simplifications there would be UB before and after on
signed integer minimum.
2024-02-26 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/114090
* match.pd ((x >= 0 ? x : 0) + (x <= 0 ? -x : 0) -> abs x):
Restrict pattern to ANY_INTEGRAL_TYPE_P and TYPE_OVERFLOW_UNDEFINED
types.
((x <= 0 ? -x : 0) -> max(-x, 0)): Likewise.
* gcc.dg/pr114090.c: New test.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/match.pd | 10 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/pr114090.c | 38 |
2 files changed, 44 insertions, 4 deletions
diff --git a/gcc/match.pd b/gcc/match.pd index 67007fc..f3fffd8 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -453,8 +453,9 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) /* (x >= 0 ? x : 0) + (x <= 0 ? -x : 0) -> abs x. */ (simplify - (plus:c (max @0 integer_zerop) (max (negate @0) integer_zerop)) - (abs @0)) + (plus:c (max @0 integer_zerop) (max (negate @0) integer_zerop)) + (if (ANY_INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_UNDEFINED (type)) + (abs @0))) /* X * 1, X / 1 -> X. */ (for op (mult trunc_div ceil_div floor_div round_div exact_div) @@ -4218,8 +4219,9 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) /* (x <= 0 ? -x : 0) -> max(-x, 0). */ (simplify - (cond (le @0 integer_zerop@1) (negate@2 @0) integer_zerop@1) - (max @2 @1)) + (cond (le @0 integer_zerop@1) (negate@2 @0) integer_zerop@1) + (if (ANY_INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_UNDEFINED (type)) + (max @2 @1))) /* (zero_one == 0) ? y : z <op> y -> ((typeof(y))zero_one * z) <op> y */ (for op (bit_xor bit_ior plus) diff --git a/gcc/testsuite/gcc.dg/pr114090.c b/gcc/testsuite/gcc.dg/pr114090.c new file mode 100644 index 0000000..dcc2f8b --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr114090.c @@ -0,0 +1,38 @@ +/* PR tree-optimization/114090 */ +/* { dg-do run } */ +/* { dg-options "-O2 -fwrapv" } */ + +__attribute__((noipa)) int +foo (int x) +{ + int w = (x >= 0 ? x : 0); + int y = -x; + int z = (y >= 0 ? y : 0); + return w + z; +} + +__attribute__((noipa)) int +bar (int x) +{ + int w = (x >= 0 ? x : 0); + int z = (x <= 0 ? -x : 0); + return w + z; +} + +__attribute__((noipa)) int +baz (int x) +{ + return x <= 0 ? -x : 0; +} + +int +main () +{ + int v = -__INT_MAX__ - 1; + if (foo (v) != 0) + __builtin_abort (); + if (bar (v) != v) + __builtin_abort (); + if (baz (v) != v) + __builtin_abort (); +} |