On Fri, Nov 28, 2025 at 2:04 AM Daniel Barboza <[email protected]> wrote: > > Add a single pattern to reduce these patterns to "x ^ c": > > x & c ? (x - c) | (x | c) > x & c ? (x & ~c) | (x | c) > > As long as "c" has a single bit set.
OK Thanks, Richard. > PR 122615 > PR 122616 > > gcc/ChangeLog: > > * match.pd (`x & c ? (x - c) | (x | c)`): New pattern. > (`x & c ? (x & ~c) | (x | c)`): Likewise. > > gcc/testsuite/ChangeLog: > > * gcc.dg/torture/pr122615.c: New test. > * gcc.dg/torture/pr122616.c: Likewise. > > Co-authored-by: Jeff Law <[email protected]> > Signed-off-by: Daniel Barboza <[email protected]> > --- > Changes since v1, all suggested by Andrwe Pinski: > - changed 'match.pd' ChangeLog commit msg > - replaced second INTEGER_CST@1 with @1 > - changed "with {...}" style > > gcc/match.pd | 16 ++++++++++++++++ > gcc/testsuite/gcc.dg/torture/pr122615.c | 22 ++++++++++++++++++++++ > gcc/testsuite/gcc.dg/torture/pr122616.c | 22 ++++++++++++++++++++++ > 3 files changed, 60 insertions(+) > create mode 100644 gcc/testsuite/gcc.dg/torture/pr122615.c > create mode 100644 gcc/testsuite/gcc.dg/torture/pr122616.c > > diff --git a/gcc/match.pd b/gcc/match.pd > index 05c8b59eb9e..d2b55aad5a7 100644 > --- a/gcc/match.pd > +++ b/gcc/match.pd > @@ -6627,6 +6627,22 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) > (convert (minus { arg; } (convert:type1 @0)))))))))) > #endif > > +/* X & C1 ? (X + -C1) : (X | C1) -> X ^ C1 > + X & C1 ? (X & ~C1) : (X | C1) -> X ^ C1 > + when C1 has a single bit set. */ > +(for op (plus bit_and) > + (simplify > + (cond (ne (bit_and @0 INTEGER_CST@1) integer_zerop) > + (op @0 INTEGER_CST@2) (bit_ior @0 @1)) > + (with { > + auto c1 = wi::to_wide (@1); > + auto c2 = wi::to_wide (@2); > + } > + (if (wi::popcount (c1) == 1 > + && ((op == PLUS_EXPR && wi::eq_p (wi::neg (c2), c1)) > + || (op == BIT_AND_EXPR && wi::eq_p (wi::bit_not (c2), c1)))) > + (bit_xor @0 @1))))) > + > (simplify > (convert (cond@0 @1 INTEGER_CST@2 INTEGER_CST@3)) > (if (INTEGRAL_TYPE_P (type) > diff --git a/gcc/testsuite/gcc.dg/torture/pr122615.c > b/gcc/testsuite/gcc.dg/torture/pr122615.c > new file mode 100644 > index 00000000000..9f4f3c49a01 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/torture/pr122615.c > @@ -0,0 +1,22 @@ > +/* { dg-do compile } */ > +/* { dg-options "-fdump-tree-original" } */ > +/* { dg-skip-if "" { *-*-* } { "-O0" } { "" } } */ > + > +int f1 (int x) > +{ > + return x & 1 ? (x & ~1) : (x | 1); > +} > + > +int f2 (int x) > +{ > + return x & 2 ? (x & ~2) : (x | 2); > +} > + > +int f3 (int x) > +{ > + return x & 3 ? (x & ~3) : (x | 3); > +} > + > +/* { dg-final { scan-tree-dump-times "x \\^ 1" 1 "original" } } */ > +/* { dg-final { scan-tree-dump-times "x \\^ 2" 1 "original" } } */ > +/* { dg-final { scan-tree-dump-times "x \\^ 3" 0 "original" } } */ > diff --git a/gcc/testsuite/gcc.dg/torture/pr122616.c > b/gcc/testsuite/gcc.dg/torture/pr122616.c > new file mode 100644 > index 00000000000..77d364ef2f4 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/torture/pr122616.c > @@ -0,0 +1,22 @@ > +/* { dg-do compile } */ > +/* { dg-options "-fdump-tree-original" } */ > +/* { dg-skip-if "" { *-*-* } { "-O0" } { "" } } */ > + > +int f1 (int x) > +{ > + return x & 1 ? (x - 1) : (x | 1); > +} > + > +int f2 (int x) > +{ > + return x & 2 ? (x - 2) : (x | 2); > +} > + > +int f3 (int x) > +{ > + return x & 3 ? (x - 3) : (x | 3); > +} > + > +/* { dg-final { scan-tree-dump-times "x \\^ 1" 1 "original" } } */ > +/* { dg-final { scan-tree-dump-times "x \\^ 2" 1 "original" } } */ > +/* { dg-final { scan-tree-dump-times "x \\^ 3" 0 "original" } } */ > -- > 2.43.0 >
