On Thu, Nov 27, 2025 at 12:26 PM 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. > > PR 122615 > PR 122616 > > gcc/ChangeLog: > > * match.pd: New pattern.
The changelog might be better this way: * match.pd (`x & c ? (x - c) | (x | c)`): New pattern. (`x & c ? (x & ~c) | (x | c)`): Likewise. So it might be easier to see what the change did. > > gcc/testsuite/ChangeLog: > > * gcc.dg/torture/pr122615.c: New test. > * gcc.dg/torture/pr122616.c: New test. First, LGTM with some minor changes listed below (but I can't approve it). > > Co-authored-by: Jeff Law <[email protected]> > Signed-off-by: Daniel Barboza <[email protected]> > --- > gcc/match.pd | 15 +++++++++++++++ > gcc/testsuite/gcc.dg/torture/pr122615.c | 22 ++++++++++++++++++++++ > gcc/testsuite/gcc.dg/torture/pr122616.c | 22 ++++++++++++++++++++++ > 3 files changed, 59 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..fbef7fd6e0f 100644 > --- a/gcc/match.pd > +++ b/gcc/match.pd > @@ -6627,6 +6627,21 @@ 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 INTEGER_CST@1)) The second `INTEGER_CST@1` should/needs to just be `@1`. I am actually surprised that `INTEGER_CST@1` twice worked. But maybe genmatch does not check. > + (with { > + auto c1 = wi::to_wide (@1); > + auto c2 = wi::to_wide (@2); } I think the style in the file is: (with { auto c1 = wi::to_wide (@1); auto c2 = wi::to_wide (@2); } Or (with { auto c1 = wi::to_wide (@1); auto c2 = wi::to_wide (@2); } Both of these are used in the file but I didn't see one or the other as the dominating one for 2 lines. There is one which is like the format you did but the first line is a comment. I am ok with both of the later formats as those are what is already in use. Thanks, Andrew Pinski > + (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 >
