> Am 16.11.2024 um 18:50 schrieb Andrew Pinski <quic_apin...@quicinc.com>:
> 
> For unsigned types, you can optimize `max<a,b> == 0` into
> `(a|b) == 0` (that is both have to be zero). A similar thing happens for `!= 
> 0`.
> This optimization fixes the missed optimization (g++.dg/tree-ssa/pr115275.C)
> that was reported exposed by adding phiprop early.
> 
> Bootstrapped and tested on x86_64-linux-gnu.

Ok

Richard 

>    PR tree-optimization/115275
> 
> gcc/ChangeLog:
> 
>    * match.pd (umax(a,b) ==/!= 0): New pattern.
> 
> gcc/testsuite/ChangeLog:
> 
>    * g++.dg/tree-ssa/pr115275.C: New test.
>    * gcc.dg/tree-ssa/max_eqne-1.c: New test.
>    * gcc.dg/tree-ssa/max_eqne-2.c: New test.
> 
> Signed-off-by: Andrew Pinski <quic_apin...@quicinc.com>
> ---
> gcc/match.pd                               |  8 +++++
> gcc/testsuite/g++.dg/tree-ssa/pr115275.C   | 36 ++++++++++++++++++++++
> gcc/testsuite/gcc.dg/tree-ssa/max_eqne-1.c | 20 ++++++++++++
> gcc/testsuite/gcc.dg/tree-ssa/max_eqne-2.c | 19 ++++++++++++
> 4 files changed, 83 insertions(+)
> create mode 100644 gcc/testsuite/g++.dg/tree-ssa/pr115275.C
> create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/max_eqne-1.c
> create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/max_eqne-2.c
> 
> diff --git a/gcc/match.pd b/gcc/match.pd
> index 753bf811f67..076e1241092 100644
> --- a/gcc/match.pd
> +++ b/gcc/match.pd
> @@ -4788,6 +4788,14 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
>   (cmp (minmax @0 INTEGER_CST@1) INTEGER_CST@2)
>   (comb (cmp @0 @2) (cmp @1 @2))))
> 
> +/* MAX (A, B) == 0 -> (A|B) == 0 iff unsigned.
> +   MAX (A, B) != 0 -> (A|B) != 0 iff unsigned.  */
> +(for cmp (eq ne)
> + (simplify
> +  (cmp (max @0 @1) integer_zerop@2)
> +  (if (TYPE_UNSIGNED (TREE_TYPE (@0)))
> +   (cmp (bit_ior @0 @1) @2))))
> +
> /* Undo fancy ways of writing max/min or other ?: expressions, like
>    a - ((a - b) & -(a < b))  and  a - (a - b) * (a < b) into (a < b) ? b : a.
>    People normally use ?: and that is what we actually try to optimize.  */
> diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr115275.C 
> b/gcc/testsuite/g++.dg/tree-ssa/pr115275.C
> new file mode 100644
> index 00000000000..1b84766186a
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/tree-ssa/pr115275.C
> @@ -0,0 +1,36 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -fdump-tree-optimized" } */
> +
> +/* PR tree-optimization/115275 */
> +
> +template<class T>
> +inline const T &
> +min(const T &a, const T &b)
> +{
> +  return a < b ? a : b;
> +}
> +
> +template<class T>
> +inline const T &
> +max(const T &a, const T &b)
> +{
> +  return a < b ? b : a;
> +}
> +
> +
> +unsigned short m, a, b;
> +void removeme ();
> +void fn(unsigned short f) {
> +    if(
> +    (min(max(f, a) ? f : 0U, 84991U))
> +    -
> +    (min(max(f, b) ? f : 0U, 84991U))
> +    )
> +    {
> +      removeme();
> +    }
> +}
> +
> +/* removeme call should be optimized out.  */
> +
> +/* { dg-final { scan-tree-dump-not "removeme " "optimized" } } */
> diff --git a/gcc/testsuite/gcc.dg/tree-ssa/max_eqne-1.c 
> b/gcc/testsuite/gcc.dg/tree-ssa/max_eqne-1.c
> new file mode 100644
> index 00000000000..a7f5e0ec7dc
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/tree-ssa/max_eqne-1.c
> @@ -0,0 +1,20 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O1 -fdump-tree-optimized-raw" } */
> +
> +/* PR tree-optimization/115275 */
> +
> +unsigned maxne(unsigned a, unsigned b)
> +{
> +  unsigned t = a > b ? a : b;
> +  return t != 0;
> +}
> +unsigned maxeq(unsigned a, unsigned b)
> +{
> +  unsigned t = a > b ? a : b;
> +  return t == 0;
> +}
> +/* `max(a,b) == 0` should be optimized to `(a|b) == 0` for unsigned types. */
> +/* { dg-final { scan-tree-dump-not "max_expr, " "optimized" } } */
> +/* { dg-final { scan-tree-dump-times "bit_ior_expr, " 2 "optimized" } } */
> +/* { dg-final { scan-tree-dump-times "eq_expr, " 1 "optimized" } } */
> +/* { dg-final { scan-tree-dump-times "ne_expr, " 1 "optimized" } } */
> diff --git a/gcc/testsuite/gcc.dg/tree-ssa/max_eqne-2.c 
> b/gcc/testsuite/gcc.dg/tree-ssa/max_eqne-2.c
> new file mode 100644
> index 00000000000..50808cc7e02
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/tree-ssa/max_eqne-2.c
> @@ -0,0 +1,19 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O1 -fdump-tree-optimized-raw" } */
> +
> +/* PR tree-optimization/115275 */
> +signed maxne(signed a, signed b)
> +{
> +  unsigned t = a > b ? a : b;
> +  return t != 0;
> +}
> +signed maxeq(signed a, signed b)
> +{
> +  unsigned t = a > b ? a : b;
> +  return t == 0;
> +}
> +/* For signed types, `max(a,b) == 0` should not optimized to `(a|b) == 0`. */
> +/* { dg-final { scan-tree-dump-times "max_expr, " 2 "optimized" } } */
> +/* { dg-final { scan-tree-dump-not "bit_ior_expr, " "optimized" } } */
> +/* { dg-final { scan-tree-dump-times "eq_expr, " 1 "optimized" } } */
> +/* { dg-final { scan-tree-dump-times "ne_expr, " 1 "optimized" } } */
> --
> 2.43.0
> 

Reply via email to