On Mon, 13 Jul 2026, Neal Patalay wrote:
> When `b` is known to be non-negative, the sign of both `MIN (a, b)`
> and `a | b` depends only on the sign of `a`. Add patterns to match.pd
> to optimize `MIN (a, b) cmp 0` and `(a | b) cmp 0` into `a cmp 0`,
> where `cmp` is `<` or `>=`. Currently, `(a | b) cmp 0` is optimized
> at the RTL level for some targets, but simplifying earlier is
> preferable.
>
> PR tree-optimization/126087
>
> gcc/ChangeLog:
>
> * match.pd: Simplify MIN and BIT_IOR compared to 0 when
> one operand is non-negative.
>
> gcc/testsuite/ChangeLog:
>
> * gcc.dg/tree-ssa/pr126087.c: New test.
>
> Signed-off-by: Neal Patalay <[email protected]>
> ---
> Bootstrapped and regression tested on x86_64-pc-linux-gnu with no
> regressions.
>
> If this patch is approved, could someone please commit it and update
> PR126087 for me?
>
> gcc/match.pd | 16 +++++++++++
> gcc/testsuite/gcc.dg/tree-ssa/pr126087.c | 36 ++++++++++++++++++++++++
> 2 files changed, 52 insertions(+)
> create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr126087.c
>
> diff --git a/gcc/match.pd b/gcc/match.pd
> index 9d4ab622fe5..5c8d1cc1b52 100644
> --- a/gcc/match.pd
> +++ b/gcc/match.pd
> @@ -4831,6 +4831,14 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
> (cmp (bit_ior (convert:utype @0) (convert:utype @1))
> { build_zero_cst (utype); } ))))
>
> +/* Optimize MIN (a, b) >= 0 to a >= 0 if b is non-negative.
> + Optimize MIN (a, b) < 0 to a < 0 if b is non-negative. */
> +(for cmp (ge lt)
> + (simplify
> + (cmp (min:c @0 @1) integer_zerop@2)
> + (if (tree_expr_nonnegative_p (@1))
> + (cmp @0 @2))))
> +
Please merge both patterns with a (for op (min bit_ior), otherwise
this looks OK.
> /* 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. */
> @@ -6900,6 +6908,14 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
> @2))
> #endif
>
> +/* Optimize (a | b) >= 0 to a >= 0 if b is non-negative.
> + Optimize (a | b) < 0 to a < 0 if b is non-negative. */
> +(for cmp (ge lt)
> + (simplify
> + (cmp (bit_ior:c @0 @1) integer_zerop@2)
> + (if (tree_expr_nonnegative_p (@1))
> + (cmp @0 @2))))
> +
> /* These was part of minmax phiopt. */
> /* Optimize (a CMP b) ? minmax<a, c> : minmax<b, c>
> to minmax<min/max<a, b>, c> */
> diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr126087.c
> b/gcc/testsuite/gcc.dg/tree-ssa/pr126087.c
> new file mode 100644
> index 00000000000..308a5096c42
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr126087.c
> @@ -0,0 +1,36 @@
> +/* PR tree-optimization/126087 */
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -fdump-tree-optimized" } */
> +
> +void use();
> +
> +void f2(int a, unsigned short bb) {
> + int b = bb;
> + int m = a < b ? a : b;
> + if (m >= 0)
> + use();
> +}
> +
> +void f3(int a, unsigned short bb) {
> + int b = bb;
> + int m = a | b;
> + if (m >= 0)
> + use();
> +}
> +
> +void f4(int a, unsigned short bb) {
> + int b = bb;
> + int m = a < b ? a : b;
> + if (m < 0)
> + use();
> +}
> +
> +void f5(int a, unsigned short bb) {
> + int b = bb;
> + int m = a | b;
> + if (m < 0)
> + use();
> +}
> +
> +/* { dg-final { scan-tree-dump-not "MIN_EXPR" "optimized" } } */
> +/* { dg-final { scan-tree-dump-not " \\| " "optimized" } } */
>
--
Richard Biener <[email protected]>
SUSE Software Solutions Germany GmbH,
Frankenstrasse 146, 90461 Nuernberg, Germany;
GF: Jochen Jaser, Andrew McDonald, Abhinav Puri; (HRB 36809, AG Nuernberg)