On Wed, Jun 12, 2024 at 6:39 AM Andrew Pinski <quic_apin...@quicinc.com> wrote:
>
> As mentioned by Jeff in r15-831-g05daf617ea22e1d818295ed2d037456937e23530, we 
> don't handle
> `(X | Y) & ~Y` -> `X & ~Y` on the gimple level when there are some different 
> signed
> (but same precision) types dealing with matching `~Y` with the `Y` part. This
> improves both gimple_bitwise_equal_p and gimple_bitwise_inverted_equal_p to
> be able to say `(truncate)a` and `(truncate)a` are bitwise_equal and
> that `~(truncate)a` and `(truncate)a` are bitwise_invert_equal.
>
> Bootstrapped and tested on x86_64-linux-gnu with no regressions.

OK.

Richard.

>         PR tree-optimization/115449
>
> gcc/ChangeLog:
>
>         * gimple-match-head.cc (gimple_maybe_truncate): New declaration.
>         (gimple_bitwise_equal_p): Match truncations that differ only
>         in types with the same precision.
>         (gimple_bitwise_inverted_equal_p): For matching after bit_not_with_nop
>         call gimple_bitwise_equal_p.
>         * match.pd (maybe_truncate): New match pattern.
>
> gcc/testsuite/ChangeLog:
>
>         * gcc.dg/tree-ssa/bitops-10.c: New test.
>
> Signed-off-by: Andrew Pinski <quic_apin...@quicinc.com>
> ---
>  gcc/gimple-match-head.cc                  | 17 +++++-------
>  gcc/match.pd                              |  7 +++++
>  gcc/testsuite/gcc.dg/tree-ssa/bitops-10.c | 34 +++++++++++++++++++++++
>  3 files changed, 48 insertions(+), 10 deletions(-)
>  create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/bitops-10.c
>
> diff --git a/gcc/gimple-match-head.cc b/gcc/gimple-match-head.cc
> index e26fa0860ee..924d3f1e710 100644
> --- a/gcc/gimple-match-head.cc
> +++ b/gcc/gimple-match-head.cc
> @@ -243,6 +243,7 @@ optimize_successive_divisions_p (tree divisor, tree 
> inner_div)
>    gimple_bitwise_equal_p (expr1, expr2, valueize)
>
>  bool gimple_nop_convert (tree, tree *, tree (*) (tree));
> +bool gimple_maybe_truncate (tree, tree *, tree (*) (tree));
>
>  /* Helper function for bitwise_equal_p macro.  */
>
> @@ -271,6 +272,10 @@ gimple_bitwise_equal_p (tree expr1, tree expr2, tree 
> (*valueize) (tree))
>      }
>    if (expr2 != expr4 && operand_equal_p (expr1, expr4, 0))
>      return true;
> +  if (gimple_maybe_truncate (expr3, &expr3, valueize)
> +      && gimple_maybe_truncate (expr4, &expr4, valueize)
> +      && operand_equal_p (expr3, expr4, 0))
> +    return true;
>    return false;
>  }
>
> @@ -318,21 +323,13 @@ gimple_bitwise_inverted_equal_p (tree expr1, tree 
> expr2, bool &wascmp, tree (*va
>    /* Try if EXPR1 was defined as ~EXPR2. */
>    if (gimple_bit_not_with_nop (expr1, &other, valueize))
>      {
> -      if (operand_equal_p (other, expr2, 0))
> -       return true;
> -      tree expr4;
> -      if (gimple_nop_convert (expr2, &expr4, valueize)
> -         && operand_equal_p (other, expr4, 0))
> +      if (gimple_bitwise_equal_p (other, expr2, valueize))
>         return true;
>      }
>    /* Try if EXPR2 was defined as ~EXPR1. */
>    if (gimple_bit_not_with_nop (expr2, &other, valueize))
>      {
> -      if (operand_equal_p (other, expr1, 0))
> -       return true;
> -      tree expr3;
> -      if (gimple_nop_convert (expr1, &expr3, valueize)
> -         && operand_equal_p (other, expr3, 0))
> +      if (gimple_bitwise_equal_p (other, expr1, valueize))
>         return true;
>      }
>
> diff --git a/gcc/match.pd b/gcc/match.pd
> index 5cfe81e80b3..3204cf41538 100644
> --- a/gcc/match.pd
> +++ b/gcc/match.pd
> @@ -200,6 +200,13 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
>  (match (maybe_bit_not @0)
>   (bit_xor_cst@0 @1 @2))
>
> +#if GIMPLE
> +(match (maybe_truncate @0)
> + (convert @0)
> + (if (INTEGRAL_TYPE_P (type)
> +      && TYPE_PRECISION (type) < TYPE_PRECISION (TREE_TYPE (@0)))))
> +#endif
> +
>  /* Transform likes of (char) ABS_EXPR <(int) x> into (char) ABSU_EXPR <x>
>     ABSU_EXPR returns unsigned absolute value of the operand and the operand
>     of the ABSU_EXPR will have the corresponding signed type.  */
> diff --git a/gcc/testsuite/gcc.dg/tree-ssa/bitops-10.c 
> b/gcc/testsuite/gcc.dg/tree-ssa/bitops-10.c
> new file mode 100644
> index 00000000000..000c5aef237
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/tree-ssa/bitops-10.c
> @@ -0,0 +1,34 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O1 -fdump-tree-optimized-raw" } */
> +/* PR tree-optimization/115449 */
> +
> +void setBit_un(unsigned char *a, int b) {
> +   unsigned char c = 0x1UL << b;
> +   *a &= ~c;
> +   *a |= c;
> +}
> +
> +void setBit_sign(signed char *a, int b) {
> +   signed char c = 0x1UL << b;
> +   *a &= ~c;
> +   *a |= c;
> +}
> +
> +void setBit(char *a, int b) {
> +   char c = 0x1UL << b;
> +   *a &= ~c;
> +   *a |= c;
> +}
> +/*
> +   All three should produce:
> +    _1 = 1 << b_4(D);
> +    c_5 = (cast) _1;
> +    _2 = *a_7(D);
> +    _3 = _2 | c_5;
> +    *a_7(D) = _3;
> +   Removing the `&~c` as we are matching `(~x & y) | x` -> `x | y`
> +   match pattern even with extra casts are being involved. */
> +
> +/* { dg-final { scan-tree-dump-not "bit_not_expr, " "optimized" } } */
> +/* { dg-final { scan-tree-dump-not "bit_and_expr, " "optimized" } } */
> +/* { dg-final { scan-tree-dump-times "bit_ior_expr, " 3 "optimized" } } */
> --
> 2.43.0
>

Reply via email to