[v2,1/2] tree-optimization: Add bitop reduction simplifications against zero

Message ID 20260603085303.7353-2-souradiptodas6@gmail.com
State Superseded
Headers
Series tree-optimization: Add bitop reduction simplifications against zero [PR125442] |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gcc_build--master-arm success Build passed
linaro-tcwg-bot/tcwg_gcc_check--master-arm success Test passed

Commit Message

Souradipto Das June 3, 2026, 8:51 a.m. UTC
  This patch introduces a simplification rule in match.pd to reduce bitwise
expressions against zero. Specifically, it simplifies patterns where a
variable checked against zero is combined via bitwise AND/OR with a compounded
bitwise OR check against zero.

        PR tree-optimization/125442

gcc/ChangeLog:

        * match.pd: Add simplification rules for
        (a == 0) | ((a | b) == 0) -> (a == 0) and
        (a != 0) & ((a | b) != 0) -> (a != 0).
---
 gcc/match.pd | 9 +++++++++
 1 file changed, 9 insertions(+)
  

Comments

Jeffrey Law June 7, 2026, 6:57 p.m. UTC | #1
On 6/3/2026 2:51 AM, Souradipto Das wrote:
> This patch introduces a simplification rule in match.pd to reduce bitwise
> expressions against zero. Specifically, it simplifies patterns where a
> variable checked against zero is combined via bitwise AND/OR with a compounded
> bitwise OR check against zero.
>
>          PR tree-optimization/125442
>
> gcc/ChangeLog:
>
>          * match.pd: Add simplification rules for
>          (a == 0) | ((a | b) == 0) -> (a == 0) and
>          (a != 0) & ((a | b) != 0) -> (a != 0).
> ---
>   gcc/match.pd | 9 +++++++++
>   1 file changed, 9 insertions(+)
>
> diff --git a/gcc/match.pd b/gcc/match.pd
> index 8a2de136e..4a2f9a784 100644
> --- a/gcc/match.pd
> +++ b/gcc/match.pd
> @@ -6660,6 +6660,15 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
>    (simplify
>     (bitop (neeql @0 @1) (neeqr (bit_ior @0 @1) integer_zerop))
>     { constant_boolean_node (bitop == BIT_IOR_EXPR, type); }))
> +
> +/* (a == 0) | ((a | b) == 0) -> (a == 0) -- PR125442
> +   (a != 0) & ((a | b) != 0) -> (a != 0) -- PR125442 */
> +
> +(for bitop (bit_and bit_ior)
> +     neeq  (ne      eq)
> +(simplify
> +  (bitop:c (neeq@2 @0 integer_zerop) (neeq (bit_ior:c @0 @1) integer_zerop))
> +  @2))
>   #endif
This may have been asked and answered already, but is simplifying to @2 
or (eq/ne @2 integer_zero) better?

Do we need to be careful with types?  I'm not 100% sure that @2's type 
is going to match the ultimate type for the pattern.  Do we need to do 
any conversion on the output?

We're dropping references to @1, if this applies before gimple (say in 
generic) do we run the risk of dropping an embedded side effect?

Overall I think it's going in the right direction, we just need to make 
sure the details are correct for the various corner cases.

Andrea, you have any thoughts on these issues?  You know this framework 
far better than I.

Jeff
  
Andrew Pinski June 7, 2026, 7:12 p.m. UTC | #2
On Sun, Jun 7, 2026 at 11:57 AM Jeffrey Law
<jeffrey.law@oss.qualcomm.com> wrote:
>
>
>
> On 6/3/2026 2:51 AM, Souradipto Das wrote:
> > This patch introduces a simplification rule in match.pd to reduce bitwise
> > expressions against zero. Specifically, it simplifies patterns where a
> > variable checked against zero is combined via bitwise AND/OR with a compounded
> > bitwise OR check against zero.
> >
> >          PR tree-optimization/125442
> >
> > gcc/ChangeLog:
> >
> >          * match.pd: Add simplification rules for
> >          (a == 0) | ((a | b) == 0) -> (a == 0) and
> >          (a != 0) & ((a | b) != 0) -> (a != 0).
> > ---
> >   gcc/match.pd | 9 +++++++++
> >   1 file changed, 9 insertions(+)
> >
> > diff --git a/gcc/match.pd b/gcc/match.pd
> > index 8a2de136e..4a2f9a784 100644
> > --- a/gcc/match.pd
> > +++ b/gcc/match.pd
> > @@ -6660,6 +6660,15 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
> >    (simplify
> >     (bitop (neeql @0 @1) (neeqr (bit_ior @0 @1) integer_zerop))
> >     { constant_boolean_node (bitop == BIT_IOR_EXPR, type); }))
> > +
> > +/* (a == 0) | ((a | b) == 0) -> (a == 0) -- PR125442
> > +   (a != 0) & ((a | b) != 0) -> (a != 0) -- PR125442 */
> > +
> > +(for bitop (bit_and bit_ior)
> > +     neeq  (ne      eq)
> > +(simplify
> > +  (bitop:c (neeq@2 @0 integer_zerop) (neeq (bit_ior:c @0 @1) integer_zerop))
> > +  @2))
> >   #endif
> This may have been asked and answered already, but is simplifying to @2
> or (eq/ne @2 integer_zero) better?

It is simplifying to @2 here. That is the `(a == 0)`/`(a != 0)` expression.

>
> Do we need to be careful with types?  I'm not 100% sure that @2's type
> is going to match the ultimate type for the pattern.  Do we need to do
> any conversion on the output?

No because @2 is the type of the neeq expression so it should be fine.

>
> We're dropping references to @1, if this applies before gimple (say in
> generic) do we run the risk of dropping an embedded side effect?

There is code in genmatch that handles the case of dropping the reference.
That is genmatch.cc (dt_simplify::gen_1):
```
          /* Search for captures not used in the result expression and dependent
             on TREE_SIDE_EFFECTS emit omit_one_operand.  */
```
The time a match pattern needs to deal with generic in a special way
is when we are making something that was conditional to unconditional
and vice versa. There is expr_no_side_effects_p for that.

>
> Overall I think it's going in the right direction, we just need to make
> sure the details are correct for the various corner cases.
>
> Andrea, you have any thoughts on these issues?  You know this framework
> far better than I.

I think the only thing is the testcases as part of one full patch. I
think Souradipto misunderstood my first review where I said to split
the new testcases out. I meant to create a new testcase file rather
than splitting the patch into two.

Thanks,
Andrea

>
> Jeff
  
Souradipto Das June 8, 2026, 2:20 a.m. UTC | #3
Hi Andrew, Jeff,

Thank you both for the detailed review !

I am sorry, I completely misunderstood the note about splitting the
testcases out in v2.
I will squash the testcases and the match.pd changes back into a single,
unified
patch and submit it shortly as v3.

Thanks,
Souradipto

On Mon, 8 Jun, 2026, 12:42 am Andrew Pinski, <andrew.pinski@oss.qualcomm.com>
wrote:

> On Sun, Jun 7, 2026 at 11:57 AM Jeffrey Law
> <jeffrey.law@oss.qualcomm.com> wrote:
> >
> >
> >
> > On 6/3/2026 2:51 AM, Souradipto Das wrote:
> > > This patch introduces a simplification rule in match.pd to reduce
> bitwise
> > > expressions against zero. Specifically, it simplifies patterns where a
> > > variable checked against zero is combined via bitwise AND/OR with a
> compounded
> > > bitwise OR check against zero.
> > >
> > >          PR tree-optimization/125442
> > >
> > > gcc/ChangeLog:
> > >
> > >          * match.pd: Add simplification rules for
> > >          (a == 0) | ((a | b) == 0) -> (a == 0) and
> > >          (a != 0) & ((a | b) != 0) -> (a != 0).
> > > ---
> > >   gcc/match.pd | 9 +++++++++
> > >   1 file changed, 9 insertions(+)
> > >
> > > diff --git a/gcc/match.pd b/gcc/match.pd
> > > index 8a2de136e..4a2f9a784 100644
> > > --- a/gcc/match.pd
> > > +++ b/gcc/match.pd
> > > @@ -6660,6 +6660,15 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
> > >    (simplify
> > >     (bitop (neeql @0 @1) (neeqr (bit_ior @0 @1) integer_zerop))
> > >     { constant_boolean_node (bitop == BIT_IOR_EXPR, type); }))
> > > +
> > > +/* (a == 0) | ((a | b) == 0) -> (a == 0) -- PR125442
> > > +   (a != 0) & ((a | b) != 0) -> (a != 0) -- PR125442 */
> > > +
> > > +(for bitop (bit_and bit_ior)
> > > +     neeq  (ne      eq)
> > > +(simplify
> > > +  (bitop:c (neeq@2 @0 integer_zerop) (neeq (bit_ior:c @0 @1)
> integer_zerop))
> > > +  @2))
> > >   #endif
> > This may have been asked and answered already, but is simplifying to @2
> > or (eq/ne @2 integer_zero) better?
>
> It is simplifying to @2 here. That is the `(a == 0)`/`(a != 0)` expression.
>
> >
> > Do we need to be careful with types?  I'm not 100% sure that @2's type
> > is going to match the ultimate type for the pattern.  Do we need to do
> > any conversion on the output?
>
> No because @2 is the type of the neeq expression so it should be fine.
>
> >
> > We're dropping references to @1, if this applies before gimple (say in
> > generic) do we run the risk of dropping an embedded side effect?
>
> There is code in genmatch that handles the case of dropping the reference.
> That is genmatch.cc (dt_simplify::gen_1):
> ```
>           /* Search for captures not used in the result expression and
> dependent
>              on TREE_SIDE_EFFECTS emit omit_one_operand.  */
> ```
> The time a match pattern needs to deal with generic in a special way
> is when we are making something that was conditional to unconditional
> and vice versa. There is expr_no_side_effects_p for that.
>
> >
> > Overall I think it's going in the right direction, we just need to make
> > sure the details are correct for the various corner cases.
> >
> > Andrea, you have any thoughts on these issues?  You know this framework
> > far better than I.
>
> I think the only thing is the testcases as part of one full patch. I
> think Souradipto misunderstood my first review where I said to split
> the new testcases out. I meant to create a new testcase file rather
> than splitting the patch into two.
>
> Thanks,
> Andrea
>
> >
> > Jeff
>
  

Patch

diff --git a/gcc/match.pd b/gcc/match.pd
index 8a2de136e..4a2f9a784 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -6660,6 +6660,15 @@  DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
  (simplify
   (bitop (neeql @0 @1) (neeqr (bit_ior @0 @1) integer_zerop))
   { constant_boolean_node (bitop == BIT_IOR_EXPR, type); }))
+
+/* (a == 0) | ((a | b) == 0) -> (a == 0) -- PR125442
+   (a != 0) & ((a | b) != 0) -> (a != 0) -- PR125442 */
+
+(for bitop (bit_and bit_ior)
+     neeq  (ne      eq)
+(simplify
+  (bitop:c (neeq@2 @0 integer_zerop) (neeq (bit_ior:c @0 @1) integer_zerop))
+  @2))
 #endif
 
 /* These was part of minmax phiopt.  */