On Thu, Aug 24, 2023 at 4:39 AM Andrew Pinski via Gcc-patches <gcc-patches@gcc.gnu.org> wrote: > > For 1bit types, negate is either undefined or don't change the value. > In either cases we want to remove them. > This patch adds a match pattern to do that. > Also converting to a 1bit type we can remove the negate just like we already > do > for `&1` so this patch adds that too. > > OK? Bootstrapped and tested on x86_64-linux-gnu with no regressions.
OK. Thanks, Richard. > Notes on the testcases: > This patch is the last part to fix PR 95929; cond-bool-2.c testcase. > bit1neg-1.c is a 1bit-field testcase where we could remove the assignment > all the way in one case (which happened on the RTL level for some targets but > not all). > cond-bool-2.c is the reduced testcase of PR 95929. > > PR tree-optimization/95929 > > gcc/ChangeLog: > > * match.pd (convert?(-a)): New pattern > for 1bit integer types. > > gcc/testsuite/ChangeLog: > > * gcc.dg/tree-ssa/bit1neg-1.c: New test. > * gcc.dg/tree-ssa/cond-bool-1.c: New test. > * gcc.dg/tree-ssa/cond-bool-2.c: New test. > --- > gcc/match.pd | 12 ++++++++++ > gcc/testsuite/gcc.dg/tree-ssa/bit1neg-1.c | 23 ++++++++++++++++++ > gcc/testsuite/gcc.dg/tree-ssa/cond-bool-1.c | 21 +++++++++++++++++ > gcc/testsuite/gcc.dg/tree-ssa/cond-bool-2.c | 26 +++++++++++++++++++++ > 4 files changed, 82 insertions(+) > create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/bit1neg-1.c > create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/cond-bool-1.c > create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/cond-bool-2.c > > diff --git a/gcc/match.pd b/gcc/match.pd > index a2e56d5a4e8..3bbeceb37b4 100644 > --- a/gcc/match.pd > +++ b/gcc/match.pd > @@ -9090,6 +9090,18 @@ and, > (if (!TYPE_OVERFLOW_SANITIZED (type)) > (bit_and @0 @1))) > > +/* `-a` is just `a` if the type is 1bit wide or when converting > + to a 1bit type; similar to the above transformation of `(-x)&1`. > + This is used mostly with the transformation of > + `a ? ~b : b` into `(-a)^b`. > + It also can show up with bitfields. */ > +(simplify > + (convert? (negate @0)) > + (if (INTEGRAL_TYPE_P (type) > + && TYPE_PRECISION (type) == 1 > + && !TYPE_OVERFLOW_SANITIZED (TREE_TYPE (@0))) > + (convert @0))) > + > /* Optimize > c1 = VEC_PERM_EXPR (a, a, mask) > c2 = VEC_PERM_EXPR (b, b, mask) > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/bit1neg-1.c > b/gcc/testsuite/gcc.dg/tree-ssa/bit1neg-1.c > new file mode 100644 > index 00000000000..2f123fbb9b5 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/tree-ssa/bit1neg-1.c > @@ -0,0 +1,23 @@ > +/* { dg-do compile } */ > +/* { dg-options "-O2 -fdump-tree-optimized" } */ > + > +struct f > +{ > + int a:1; > +}; > + > +void g(struct f *a) > +{ > + int t = a->a; > + t = -t; > + a->a = t; > +} > +void g1(struct f *a, int b) > +{ > + int t = b; > + t = -t; > + a->a = t; > +} > +/* the 2 negates should have been removed as this is basically the same > + as (-a) & 1. */ > +/* { dg-final { scan-tree-dump-not " = -" "optimized" } } */ > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/cond-bool-1.c > b/gcc/testsuite/gcc.dg/tree-ssa/cond-bool-1.c > new file mode 100644 > index 00000000000..752a3030ad1 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/tree-ssa/cond-bool-1.c > @@ -0,0 +1,21 @@ > +/* { dg-do compile } */ > +/* { dg-options "-O2 -fdump-tree-optimized-raw" } */ > +_Bool f1(int a, int b) > +{ > + _Bool _1 = b != 0; > + _Bool _2 = a != 0; > + _Bool _8 = a == 0; > + _Bool _13; > + if (_1) _13 = _8; else _13 = _2; > + return _13; > +} > + > +/* We should be able to optimize this to (a != 0) ^ (b != 0) */ > +/* There should be no negate_expr nor gimple_cond here. */ > + > +/* { dg-final { scan-tree-dump-not "negate_expr, " "optimized" } } */ > +/* { dg-final { scan-tree-dump-times "ne_expr, " 2 "optimized" } } */ > +/* { dg-final { scan-tree-dump-not "gimple_cond " "optimized" } } */ > +/* { dg-final { scan-tree-dump-not "gimple_phi " "optimized" } } */ > +/* { dg-final { scan-tree-dump-times "bit_xor_expr, " 1 "optimized" } } */ > +/* { dg-final { scan-tree-dump-times "gimple_assign " 3 "optimized" } } */ > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/cond-bool-2.c > b/gcc/testsuite/gcc.dg/tree-ssa/cond-bool-2.c > new file mode 100644 > index 00000000000..b3e7e25dec6 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/tree-ssa/cond-bool-2.c > @@ -0,0 +1,26 @@ > +/* { dg-do compile } */ > +/* { dg-options "-O2 -fdump-tree-optimized-raw" } */ > + > +/* PR tree-optimization/95929 */ > + > + > +static inline _Bool nand(_Bool a, _Bool b) > +{ > + return !(a && b); > +} > + > +_Bool f(int a, int b) > +{ > + return nand(nand(b, nand(a, a)), nand(a, nand(b, b))); > +} > + > +/* We should be able to optimize this to (a != 0) ^ (b != 0) */ > +/* There should be no negate_expr nor gimple_cond here. */ > + > +/* { dg-final { scan-tree-dump-not "negate_expr, " "optimized" } } */ > +/* { dg-final { scan-tree-dump-times "ne_expr, " 2 "optimized" } } */ > +/* { dg-final { scan-tree-dump-not "gimple_cond " "optimized" } } */ > +/* { dg-final { scan-tree-dump-not "cond_expr, " "optimized" } } */ > +/* { dg-final { scan-tree-dump-not "gimple_phi " "optimized" } } */ > +/* { dg-final { scan-tree-dump-times "bit_xor_expr, " 1 "optimized" } } */ > +/* { dg-final { scan-tree-dump-times "gimple_assign " 3 "optimized" } } */ > -- > 2.31.1 >