On Tue, Aug 11, 2026 at 8:50 PM <[email protected]> wrote:
>
> From: Reshma Roy <[email protected]>
>
> gcc/ChangeLog:
>
>         PR tree-optimization/126646
>         * match.pd: Fold umin(a, 1) | umin(b, 1) into umin(a | b, 1).
>
> gcc/testsuite/ChangeLog:
>
>         * gcc.dg/tree-ssa/pr126646-1.c: New test.
> ---
>
> Hi,
>   This patch fixes the missed optimization opportunity reported in
>   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=126646.
>   For the following snippet of code, gcc generates 2 MIN_EXPR.
>   unsigned f(unsigned a, unsigned b)
>   {
>     unsigned t = 1;
>     a = a < t ? a : t;
>     b = b < t ? b : t;
>     return a | b;
>   }
>  But this can be optimized with just one MIN_EXPR since
>  umin(a,1) | umin(b,1) can be simplified to umin(a|b, 1).
>
>  Bootstrapped and tested on x86_64-linux.
>
> Thanks,
>   Reshma
>
>  gcc/match.pd                               |  5 +++++
>  gcc/testsuite/gcc.dg/tree-ssa/pr126646-1.c | 15 +++++++++++++++
>  2 files changed, 20 insertions(+)
>  create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr126646-1.c
>
> diff --git a/gcc/match.pd b/gcc/match.pd
> index 50e73177022..7347b83ec4f 100644
> --- a/gcc/match.pd
> +++ b/gcc/match.pd
> @@ -4860,6 +4860,11 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
>    (bit_not (minmax:cs (bit_not @0) @1))
>    (maxmin @0 (bit_not @1))))
>
> +/* umin (a, 1) | umin (b, 1) -> umin (a | b, 1).  */
> + (simplify
> +  (bit_ior (min @0 integer_onep@2) (min @1 @2))
> +    (if (TYPE_UNSIGNED (type))

Instead of TYPE_UNSIGNED here; I think it might be a good idea to use
tree_expr_nonnegative_p on both @0 and @1..
tree_expr_nonnegative_p does return true for TYPE_UNSIGNED already but
it also returns true when the argument is known to be zero or
positive.

This allows for say:
```
int f(int a, int b)
{
  int c = 0;
  if (a >= 0 && b >= 0)
    c = (a > 1 ? 1 : a) | (b > 1 ? 1 : b);
  return c;
}
```
Which then should optimize to just:
  _10 = a_6(D) | b_7(D);
  c_8 = MIN_EXPR <_10, 1>;
  _11 = MAX_EXPR <c_8, 0>;


Thanks,
Andrea

> +     (min (bit_ior @0 @1) @2)))
>  /* MIN (X, Y) == X -> X <= Y  */
>  /* MIN (X, Y) < X -> X > Y  */
>  /* MIN (X, Y) >= X -> X <= Y  */
> diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr126646-1.c 
> b/gcc/testsuite/gcc.dg/tree-ssa/pr126646-1.c
> new file mode 100644
> index 00000000000..447a1739b5f
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr126646-1.c
> @@ -0,0 +1,15 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -fdump-tree-optimized" } */
> +
> +/* The test case should produce only one min expr.  */
> +/* umin(a,1) | umin(b,1) -> umin(a|b, 1).  */
> +
> +unsigned min_or (unsigned a, unsigned b)
> +{
> +  unsigned t = 1;
> +  a = a < t ? a : t;
> +  b = b < t ? b : t;
> +  return a | b;
> +}
> +
> +/* { dg-final { scan-tree-dump-times "MIN_EXPR" 1 "optimized" } } */
> --
> 2.34.1
>

Reply via email to