On Tue, Mar 31, 2026 at 3:12 AM Bohan Lei <[email protected]> wrote:
>
> This is v2 of
> https://gcc.gnu.org/pipermail/gcc-patches/2026-March/711809.html, fixed
> and enhanced as was suggested by Philipp.
>
> This patch adds missing simplifications for (op (and/ior x C1) C2) in
> special cases.  In the AND case, when (and C1 C2) is not equal to C1,
> some bits set in C2 are not set in C1, and thus (eq (and x C1) C2) can
> never be true.  The OR case is similar when (and C1 C2) is not equal to
> C2.  As we know that the result of (and x C1) cannot be greater than C1,
> and that that of (or x C1) cannot be less than C1 for unsigned integers,
> LTU, LEU, GTU, GEU cases can be optimized, too.
>
> The patch is meant to fix an ICE on RISC-V.  In a former patch, I tried
> to change the insn condition directly, but Jeff pointed out that it was
> more reasonable to optimize it out before the split.  As was suggested
> by Jeff, this patch tries to simplify the expression in
> simplify_relational_operation_1.
>
> The URL for the former patch:
> https://patchwork.sourceware.org/project/gcc/patch/[email protected]/
>
> gcc/ChangeLog:
>
>         * simplify-rtx.cc (simplify_context::simplify_relational_operation_1):
> Add simplifications for (op (and/ior x C1) C2) in special cases.
>
> gcc/testsuite/ChangeLog:
>
>         * gcc.target/riscv/zbs-if_then_else-02.c: New test.
> ---
>  gcc/simplify-rtx.cc                           | 30 +++++++++++++++++
>  .../gcc.target/riscv/zbs-if_then_else-02.c    | 32 +++++++++++++++++++
>  2 files changed, 62 insertions(+)
>  create mode 100644 gcc/testsuite/gcc.target/riscv/zbs-if_then_else-02.c
>
> diff --git a/gcc/simplify-rtx.cc b/gcc/simplify-rtx.cc
> index 50fc51152ca..abaee2423a7 100644
> --- a/gcc/simplify-rtx.cc
> +++ b/gcc/simplify-rtx.cc
> @@ -6731,6 +6731,36 @@ simplify_context::simplify_relational_operation_1 
> (rtx_code code,
>         }
>      }
>
> +  /* Several optimizable scenerios of (op (and/ior x C1) C2) */
> +  if ((op0code == AND || op0code == IOR)
> +      && CONST_SCALAR_INT_P (op1)
> +      && CONST_SCALAR_INT_P (XEXP (op0, 1)))
> +    {
> +      unsigned HOST_WIDE_INT c1 = UINTVAL (XEXP (op0, 1));
> +      unsigned HOST_WIDE_INT c2 = UINTVAL (op1);

If you are checking CONST_SCALAR_INT_P, you need to use
rtx_mode_t/wide_int instead.
Otherwise you change the check to CONST_INT_P and keep the UINTVAL.
As using CONST_WIDE_INT here can that will cause an ICE with RTL
checking and maybe even produce wrong code. E.g. using __int128.

> +
> +      if ((op0code == AND
> +          && ((code == EQ && (c1 & c2) != c2)
> +              || (code == GEU && c1 < c2)
> +              || (code == GTU && c1 <= c2)))
> +         || ((op0code == IOR
> +             && ((code == EQ && (c1 & c2) != c1)
> +                 || (code == LEU && c1 > c2)
> +                 || (code == LTU && c1 >= c2)))))
> +       return const0_rtx;

Can you add a comment before this mentioning each path down to 0 here?
Like say:
/*
  (x & c1) == c2 when c1 and c2 don't share any bits -> false
 */
....

I have not checked but are these also implemented in match.pd? If not
please file a bug report for them.

Thanks,
Andrew

> +
> +
> +      if ((op0code == AND
> +          && ((code == NE && (c1 & c2) != c2)
> +              || (code == LTU && c1 < c2)
> +              || (code == LEU && c1 <= c2)))
> +         || ((op0code == IOR
> +             && ((code == NE && (c1 & c2) != c1)
> +                 || (code == GTU && c1 > c2)
> +                 || (code == GEU && c1 >= c2)))))
> +       return const_true_rtx;
> +    }
> +
>    /* (eq/ne (bswap x) C1) simplifies to (eq/ne x C2) with C2 swapped.  */
>    if ((code == EQ || code == NE)
>        && GET_CODE (op0) == BSWAP
> diff --git a/gcc/testsuite/gcc.target/riscv/zbs-if_then_else-02.c 
> b/gcc/testsuite/gcc.target/riscv/zbs-if_then_else-02.c
> new file mode 100644
> index 00000000000..3393bea8898
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/riscv/zbs-if_then_else-02.c
> @@ -0,0 +1,32 @@
> +/* { dg-do link  { target { rv64 } } } */
> +/* { dg-options "-march=rv64gc_zbb_zbs -mabi=lp64d -flto" } */
> +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-O1" } } */
> +
> +struct S {
> +  int a;
> +  char b;
> +  int c;
> +} s;
> +
> +const signed char c = -37;
> +int d;
> +struct S v1[] = {{0, 8}, 0, 0, -108976}, v2[] = {{}, 0, 0, 2804};
> +int a;
> +struct S v3[3];
> +int *p = &a;
> +
> +void foo() {
> +  int a;
> +  if (a)
> +    ;
> +  else if (v1[0].b)
> +    s.a = 0;
> +  else
> +    d = 0;
> +  if (*p)
> +    if (v3[1].c)
> +      if (1 ^ (d & c & v2[1].c & ~v1[1].c | s.a))
> +        v3[2].c = 0;
> +}
> +
> +int main() { foo(); }
> --
> 2.46.0
>

Reply via email to