RE: [PATCH v2] match.pd: Fold umin(a, 1) | umin(b, 1) into umin(a | b, 1) [PR126646]

"Kumar, Venkataramanan" <[email protected]>
Newsgroups gmane.comp.gcc.patches
Message-ID <CYXPR12MB9387829833C3B820E673477A8FDA2@CYXPR12MB9387.namprd12.prod.outlook.com>
AMD General

Hi

> -----Original Message-----
> From: Andrea Pinski <[email protected]>
> Sent: Friday, August 14, 2026 11:43 AM
> To: Roy, Reshma <[email protected]>
> Cc: [email protected]; Kumar, Venkataramanan
> <[email protected]>
> Subject: Re: [PATCH v2] match.pd: Fold umin(a, 1) | umin(b, 1) into umin(a | b, 1)
> [PR126646]
>
> Caution: This message originated from an External Source. Use proper caution
> when opening attachments, clicking links, or responding.
>
>
> On Thu, Aug 13, 2026 at 10:28 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.
> >         * gcc.dg/tree-ssa/pr126646-2.c: New test.
>
> Ok, see below about being ok about the testcase.

Committed to gcc trunk at
 https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=b190388bad47b1d3507abd52dc2a07f39a899984

regards,
Venkat.

>
> >
> > ---
> > Hi,
> >   The patch is updated as per the comments and added a new test case for
> >   the same. My comments are added inline to the email.
> >
> >   Bootstrapped and tested on x86_64-linux
> >
> > > -----Original Message-----
> > > From: Andrea Pinski <[email protected]>
> > > Sent: Wednesday, August 12, 2026 9:59 AM
> > > To: Roy, Reshma <[email protected]>
> > > Cc: [email protected]; Kumar, Venkataramanan
> > > <[email protected]>
> > > Subject: Re: [PATCH] match.pd: Fold umin(a, 1) | umin(b, 1) into
> > > umin(a | b, 1) [PR126646]
> > >
> > > [You don't often get email from [email protected].
> > > Learn why this is important at
> > > https://aka.ms/LearnAboutSenderIdentification ]
> > >
> > > Caution: This message originated from an External Source. Use proper
> > > caution when opening attachments, clicking links, or responding.
> > >
> > >
> > > 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.
> > Agreed, updated to use tree_expr_nonnegative_p (@0) &&
> > tree_expr_nonnegative_p (@1). This is strictly more general as it
> > covers unsigned types (where tree_expr_nonnegative_p returns true by
> > definition) and also signed types when the operands are non-negative.
> > >
> > > 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;
> > > }
> > > ```
> > Understood the test case scenario. But the above test case doesn't
> > apply the new guard in practice because by the time match.pd sees the
> > MIN_EXPRs, the condition a >= 0 && b >= 0 has already been folded into
> > (a | b) >= 0. The dominating condition is now on the combined OR, so
> > tree_expr_nonnegative_p on a and b individually can't prove
> > non-negativity. Hence I have added a different test case
> > (pr126646-2.c) that uses __builtin_abs, where non-negativity is
> > implied in the expression itself. Hope that is fine. Let me know your thoughts.
>
> Yes, the different testcase using abs is fine. I forgot the ranger is NOT always
> enabled for forwprop so it is not always used for tree_expr_nonnegative_p;
> instead tree_expr_nonnegative_p will use the global range. That is something
> which I have been thinking about changing but I always get side tracked.
>
>
> >
> > > 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
> > > >
> >
> > Thanks,
> >  Reshma
> >
> >
> >  gcc/match.pd                               |  5 +++++
> >  gcc/testsuite/gcc.dg/tree-ssa/pr126646-1.c | 15 +++++++++++++++
> > gcc/testsuite/gcc.dg/tree-ssa/pr126646-2.c | 13 +++++++++++++
> >  3 files changed, 33 insertions(+)
> >  create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr126646-1.c
> >  create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr126646-2.c
> >
> > diff --git a/gcc/match.pd b/gcc/match.pd index
> > 5fc89426880..be2bc0dd8df 100644
> > --- a/gcc/match.pd
> > +++ b/gcc/match.pd
> > @@ -4887,6 +4887,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 (tree_expr_nonnegative_p (@0) && tree_expr_nonnegative_p (@1))
> > +     (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" } } */
> > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr126646-2.c
> > b/gcc/testsuite/gcc.dg/tree-ssa/pr126646-2.c
> > new file mode 100644
> > index 00000000000..3b47eee9656
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr126646-2.c
> > @@ -0,0 +1,13 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O2 -fdump-tree-optimized" } */
> > +
> > +int f (int a, int b)
> > +{
> > +  int x = __builtin_abs (a);
> > +  int y = __builtin_abs (b);
> > +  int p = x < 1 ? x : 1;
> > +  int q = y < 1 ? y : 1;
> > +  return p | q;
> > +}
> > +
> > +/* { dg-final { scan-tree-dump-times "MIN_EXPR" 1 "optimized" } } */
> > --
> > 2.34.1
> >
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.