[2/3] MATCH: `a | C -> C` when we know that `a & ~C == 0`

Message ID 20230824191455.3547513-2-apinski@marvell.com
State Unresolved
Headers
Series [1/3] MATCH: Move `a ? one_zero : one_zero` matching after min/max matching |

Checks

Context Check Description
snail/gcc-patch-check warning Git am fail log

Commit Message

Andrew Pinski Aug. 24, 2023, 7:14 p.m. UTC
  Even though this is handled by other code inside both VRP and CCP,
sometimes we want to optimize this outside of VRP and CCP.
An example is given in PR 106677 where phiopt will happen
after VRP (which removes a cast for a comparison) and then
phiopt will optimize the phi to be `a | 1` which can then
be optimized to `1` due to this patch.

OK? Bootstrapped and tested on x86_64-linux-gnu with no regressions.

Note Similar code already exists in simplify_rtx for the RTL level;
it was moved from combine to simplify_rtx in r0-72539-gbd1ef757767f6d.
gcc/ChangeLog:

	* match.pd (`a | C -> C`): New pattern.
---
 gcc/match.pd | 6 ++++++
 1 file changed, 6 insertions(+)
  

Comments

Richard Biener Aug. 25, 2023, 6:36 a.m. UTC | #1
On Thu, Aug 24, 2023 at 9:16 PM Andrew Pinski via Gcc-patches
<gcc-patches@gcc.gnu.org> wrote:
>
> Even though this is handled by other code inside both VRP and CCP,
> sometimes we want to optimize this outside of VRP and CCP.
> An example is given in PR 106677 where phiopt will happen
> after VRP (which removes a cast for a comparison) and then
> phiopt will optimize the phi to be `a | 1` which can then
> be optimized to `1` due to this patch.

Also works for xor, no?

> OK? Bootstrapped and tested on x86_64-linux-gnu with no regressions.

OK with or without adding XOR.

Richard.

> Note Similar code already exists in simplify_rtx for the RTL level;
> it was moved from combine to simplify_rtx in r0-72539-gbd1ef757767f6d.
> gcc/ChangeLog:
>
>         * match.pd (`a | C -> C`): New pattern.
> ---
>  gcc/match.pd | 6 ++++++
>  1 file changed, 6 insertions(+)
>
> diff --git a/gcc/match.pd b/gcc/match.pd
> index c87a0795667..3bbeceb37b4 100644
> --- a/gcc/match.pd
> +++ b/gcc/match.pd
> @@ -1456,6 +1456,12 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
>   (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
>        && wi::bit_and_not (get_nonzero_bits (@0), wi::to_wide (@1)) == 0)
>    @0))
> +/* x | C -> C if we know that x & ~C == 0.  */
> +(simplify
> + (bit_ior SSA_NAME@0 INTEGER_CST@1)
> + (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
> +      && wi::bit_and_not (get_nonzero_bits (@0), wi::to_wide (@1)) == 0)
> +  @1))
>  #endif
>
>  /* ~(~X - Y) -> X + Y and ~(~X + Y) -> X - Y.  */
> --
> 2.31.1
>
  
Andrew Pinski Aug. 25, 2023, 7:40 a.m. UTC | #2
On Thu, Aug 24, 2023 at 11:37 PM Richard Biener via Gcc-patches
<gcc-patches@gcc.gnu.org> wrote:
>
> On Thu, Aug 24, 2023 at 9:16 PM Andrew Pinski via Gcc-patches
> <gcc-patches@gcc.gnu.org> wrote:
> >
> > Even though this is handled by other code inside both VRP and CCP,
> > sometimes we want to optimize this outside of VRP and CCP.
> > An example is given in PR 106677 where phiopt will happen
> > after VRP (which removes a cast for a comparison) and then
> > phiopt will optimize the phi to be `a | 1` which can then
> > be optimized to `1` due to this patch.
>
> Also works for xor, no?

No, because IOR is a saturation operation while XOR is not. So if you
know that x and C are full subsets (nonzero(x) & ~nonzero(C) == 0)
then A^C is not the constant C but rather just (~A)&C which we already
a pattern for that to turn it back in to A^C:
/* Simplify (~X & Y) to X ^ Y if we know that (X & ~Y) is 0.  */

The only thing you can do for XOR is that if you have `A ^ B` and A
and B are known not to share any bits in common (that is nonzero(A) &
nonzero(B) == 0), you can convert it to `A | B` (that is what
simplify-rtx.cc does). Which looks like we don't do on the gimple
level.

>
> > OK? Bootstrapped and tested on x86_64-linux-gnu with no regressions.
>
> OK with or without adding XOR.

Ok.

Thanks,
Andrew

>
> Richard.
>
> > Note Similar code already exists in simplify_rtx for the RTL level;
> > it was moved from combine to simplify_rtx in r0-72539-gbd1ef757767f6d.
> > gcc/ChangeLog:
> >
> >         * match.pd (`a | C -> C`): New pattern.
> > ---
> >  gcc/match.pd | 6 ++++++
> >  1 file changed, 6 insertions(+)
> >
> > diff --git a/gcc/match.pd b/gcc/match.pd
> > index c87a0795667..3bbeceb37b4 100644
> > --- a/gcc/match.pd
> > +++ b/gcc/match.pd
> > @@ -1456,6 +1456,12 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
> >   (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
> >        && wi::bit_and_not (get_nonzero_bits (@0), wi::to_wide (@1)) == 0)
> >    @0))
> > +/* x | C -> C if we know that x & ~C == 0.  */
> > +(simplify
> > + (bit_ior SSA_NAME@0 INTEGER_CST@1)
> > + (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
> > +      && wi::bit_and_not (get_nonzero_bits (@0), wi::to_wide (@1)) == 0)
> > +  @1))
> >  #endif
> >
> >  /* ~(~X - Y) -> X + Y and ~(~X + Y) -> X - Y.  */
> > --
> > 2.31.1
> >
  

Patch

diff --git a/gcc/match.pd b/gcc/match.pd
index c87a0795667..3bbeceb37b4 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -1456,6 +1456,12 @@  DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
  (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
       && wi::bit_and_not (get_nonzero_bits (@0), wi::to_wide (@1)) == 0)
   @0))
+/* x | C -> C if we know that x & ~C == 0.  */
+(simplify
+ (bit_ior SSA_NAME@0 INTEGER_CST@1)
+ (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
+      && wi::bit_and_not (get_nonzero_bits (@0), wi::to_wide (@1)) == 0)
+  @1))
 #endif
 
 /* ~(~X - Y) -> X + Y and ~(~X + Y) -> X - Y.  */