match.pd: Guard 2 simplifications on integral TYPE_OVERFLOW_UNDEFINED [PR114090]

Message ID Zdw2G2swbBpJJn+w@tucnak
State Unresolved
Headers
Series match.pd: Guard 2 simplifications on integral TYPE_OVERFLOW_UNDEFINED [PR114090] |

Checks

Context Check Description
snail/gcc-patch-check warning Git am fail log

Commit Message

Jakub Jelinek Feb. 26, 2024, 6:56 a.m. UTC
  Hi!

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.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

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.


	Jakub
  

Comments

Richard Biener Feb. 26, 2024, 8:13 a.m. UTC | #1
On Mon, 26 Feb 2024, Jakub Jelinek wrote:

> Hi!
> 
> 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.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

OK.

Thanks,
Richard.

> 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.
> 
> --- gcc/match.pd.jj	2024-02-22 10:09:48.678446435 +0100
> +++ gcc/match.pd	2024-02-24 19:23:32.201014245 +0100
> @@ -453,8 +453,9 @@ (define_operator_list SYNC_FETCH_AND_AND
>  
>  /* (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_operator_list SYNC_FETCH_AND_AND
>  
>  /* (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)
> --- gcc/testsuite/gcc.dg/pr114090.c.jj	2024-02-24 19:38:56.301096850 +0100
> +++ gcc/testsuite/gcc.dg/pr114090.c	2024-02-24 19:42:26.917153801 +0100
> @@ -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 ();
> +}
> 
> 	Jakub
> 
>
  

Patch

--- gcc/match.pd.jj	2024-02-22 10:09:48.678446435 +0100
+++ gcc/match.pd	2024-02-24 19:23:32.201014245 +0100
@@ -453,8 +453,9 @@  (define_operator_list SYNC_FETCH_AND_AND
 
 /* (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_operator_list SYNC_FETCH_AND_AND
 
 /* (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)
--- gcc/testsuite/gcc.dg/pr114090.c.jj	2024-02-24 19:38:56.301096850 +0100
+++ gcc/testsuite/gcc.dg/pr114090.c	2024-02-24 19:42:26.917153801 +0100
@@ -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 ();
+}