> 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
>