Re: [PATCH] MATCH: Add simplifications of `(a == CST) & a`
On Sat, Sep 16, 2023 at 6:00 PM Andrew Pinski via Gcc-patches wrote: > > `(a == CST) & a` can be either simplified to simplying `a == CST` > or 0 depending on the first bit of the CST. > This is an extension of the already pattern of `X & !X` and allows > us to remove the 2 xfails on gcc.dg/binop-notand1a.c and > gcc.dg/binop-notand4a.c. > > OK? Bootstrapped and tested on x86_64-linux-gnu with no regressions. OK. > PR tree-optimization/111431 > > gcc/ChangeLog: > > * match.pd (`(a == CST) & a`): New pattern. > > gcc/testsuite/ChangeLog: > > * gcc.dg/binop-notand1a.c: Remove xfail. > * gcc.dg/binop-notand4a.c: Likewise. > * gcc.c-torture/execute/pr111431-1.c: New test. > * gcc.dg/binop-andeq1.c: New test. > * gcc.dg/binop-andeq2.c: New test. > * gcc.dg/binop-notand7.c: New test. > * gcc.dg/binop-notand7a.c: New test. > --- > gcc/match.pd | 8 > .../gcc.c-torture/execute/pr111431-1.c| 39 +++ > gcc/testsuite/gcc.dg/binop-andeq1.c | 12 ++ > gcc/testsuite/gcc.dg/binop-andeq2.c | 14 +++ > gcc/testsuite/gcc.dg/binop-notand1a.c | 4 +- > gcc/testsuite/gcc.dg/binop-notand4a.c | 4 +- > gcc/testsuite/gcc.dg/binop-notand7.c | 12 ++ > gcc/testsuite/gcc.dg/binop-notand7a.c | 12 ++ > 8 files changed, 99 insertions(+), 6 deletions(-) > create mode 100644 gcc/testsuite/gcc.c-torture/execute/pr111431-1.c > create mode 100644 gcc/testsuite/gcc.dg/binop-andeq1.c > create mode 100644 gcc/testsuite/gcc.dg/binop-andeq2.c > create mode 100644 gcc/testsuite/gcc.dg/binop-notand7.c > create mode 100644 gcc/testsuite/gcc.dg/binop-notand7a.c > > diff --git a/gcc/match.pd b/gcc/match.pd > index ebb50ee0581..65960a1701e 100644 > --- a/gcc/match.pd > +++ b/gcc/match.pd > @@ -5172,6 +5172,14 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) > ) > ) > > +/* `(a == CST) & a` can be simplified to `0` or `(a == CST)` depending > + on the first bit of the CST. */ > +(simplify > + (bit_and:c (convert@2 (eq @0 INTEGER_CST@1)) (convert? @0)) > + (if ((wi::to_wide (@1) & 1) != 0) > + @2 > + { build_zero_cst (type); })) > + > /* Optimize > # x_5 in range [cst1, cst2] where cst2 = cst1 + 1 > x_5 ? cstN ? cst4 : cst3 > diff --git a/gcc/testsuite/gcc.c-torture/execute/pr111431-1.c > b/gcc/testsuite/gcc.c-torture/execute/pr111431-1.c > new file mode 100644 > index 000..a96dbadf2b5 > --- /dev/null > +++ b/gcc/testsuite/gcc.c-torture/execute/pr111431-1.c > @@ -0,0 +1,39 @@ > +int > +foo (int a) > +{ > + int b = a == 0; > + return (a & b); > +} > + > +#define function(vol,cst) \ > +__attribute__((noipa)) \ > +_Bool func_##cst##_##vol(vol int a) \ > +{ \ > + vol int b = a == cst; \ > + return (a & b); \ > +} > + > +#define funcdefs(cst) \ > +function(,cst) \ > +function(volatile,cst) > + > +#define funcs(f) \ > +f(0) \ > +f(1) \ > +f(5) > + > +funcs(funcdefs) > + > +#define test(cst) \ > +do { \ > + if(func_##cst##_(a) != func_##cst##_volatile(a))\ > + __builtin_abort(); \ > +} while(0); > +int main(void) > +{ > + for(int a = -10; a <= 10; a++) > + { > + funcs(test) > + } > +} > + > diff --git a/gcc/testsuite/gcc.dg/binop-andeq1.c > b/gcc/testsuite/gcc.dg/binop-andeq1.c > new file mode 100644 > index 000..2a92b8f95df > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/binop-andeq1.c > @@ -0,0 +1,12 @@ > +/* { dg-do compile } */ > +/* { dg-options "-O2 -fdump-tree-optimized" } */ > +/* PR tree-optimization/111431 */ > + > +int > +foo (int a) > +{ > + int b = a == 2; > + return (a & b); > +} > + > +/* { dg-final { scan-tree-dump-times "return 0" 1 "optimized" } } */ > diff --git a/gcc/testsuite/gcc.dg/binop-andeq2.c > b/gcc/testsuite/gcc.dg/binop-andeq2.c > new file mode 100644 > index 000..895262fc17e > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/binop-andeq2.c > @@ -0,0 +1,14 @@ > +/* { dg-do compile } */ > +/* { dg-options "-O2 -fdump-tree-optimized" } */ > +/* PR tree-optimization/111431 */ > + > +int > +foo (int a) > +{ > + int b = a == 1025; > + return (a & b); > +} > + > +/* { dg-final { scan-tree-dump-not "return 0" "optimized" } } */ > +/* { dg-final { scan-tree-dump-not " & " "optimized" } } */ > +/* { dg-final { scan-tree-dump-times " == 1025;" 1 "optimized" } } */ > diff --git a/gcc/testsuite/gcc.dg/binop-notand1a.c > b/gcc/testsuite/gcc.dg/binop-notand1a.c > index c7e932b2638..d94685eb4ce 100644 > --- a/gcc/testsuite/gcc.dg/binop-notand1a.c > +++ b/gcc/testsuite/gcc.dg/binop-notand1a.c > @@ -7,6 +7,4 @@ foo (char a, unsigned short b) >return (a & !a) | (b & !b); > } > > -/* As long as comparisons aren't boolified and casts from boolean-types > - aren't preserved, the folding of X & !X to zero fails. */ > -/* { dg-final { scan-tree-dump-times "return 0" 1 "optimized" { xfail *-*-* > } } } */ > +/* { dg-final { scan-tree-dump-times "return 0" 1 "optimized" } } */ > diff
[PATCH] MATCH: Add simplifications of `(a == CST) & a`
`(a == CST) & a` can be either simplified to simplying `a == CST` or 0 depending on the first bit of the CST. This is an extension of the already pattern of `X & !X` and allows us to remove the 2 xfails on gcc.dg/binop-notand1a.c and gcc.dg/binop-notand4a.c. OK? Bootstrapped and tested on x86_64-linux-gnu with no regressions. PR tree-optimization/111431 gcc/ChangeLog: * match.pd (`(a == CST) & a`): New pattern. gcc/testsuite/ChangeLog: * gcc.dg/binop-notand1a.c: Remove xfail. * gcc.dg/binop-notand4a.c: Likewise. * gcc.c-torture/execute/pr111431-1.c: New test. * gcc.dg/binop-andeq1.c: New test. * gcc.dg/binop-andeq2.c: New test. * gcc.dg/binop-notand7.c: New test. * gcc.dg/binop-notand7a.c: New test. --- gcc/match.pd | 8 .../gcc.c-torture/execute/pr111431-1.c| 39 +++ gcc/testsuite/gcc.dg/binop-andeq1.c | 12 ++ gcc/testsuite/gcc.dg/binop-andeq2.c | 14 +++ gcc/testsuite/gcc.dg/binop-notand1a.c | 4 +- gcc/testsuite/gcc.dg/binop-notand4a.c | 4 +- gcc/testsuite/gcc.dg/binop-notand7.c | 12 ++ gcc/testsuite/gcc.dg/binop-notand7a.c | 12 ++ 8 files changed, 99 insertions(+), 6 deletions(-) create mode 100644 gcc/testsuite/gcc.c-torture/execute/pr111431-1.c create mode 100644 gcc/testsuite/gcc.dg/binop-andeq1.c create mode 100644 gcc/testsuite/gcc.dg/binop-andeq2.c create mode 100644 gcc/testsuite/gcc.dg/binop-notand7.c create mode 100644 gcc/testsuite/gcc.dg/binop-notand7a.c diff --git a/gcc/match.pd b/gcc/match.pd index ebb50ee0581..65960a1701e 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -5172,6 +5172,14 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) ) ) +/* `(a == CST) & a` can be simplified to `0` or `(a == CST)` depending + on the first bit of the CST. */ +(simplify + (bit_and:c (convert@2 (eq @0 INTEGER_CST@1)) (convert? @0)) + (if ((wi::to_wide (@1) & 1) != 0) + @2 + { build_zero_cst (type); })) + /* Optimize # x_5 in range [cst1, cst2] where cst2 = cst1 + 1 x_5 ? cstN ? cst4 : cst3 diff --git a/gcc/testsuite/gcc.c-torture/execute/pr111431-1.c b/gcc/testsuite/gcc.c-torture/execute/pr111431-1.c new file mode 100644 index 000..a96dbadf2b5 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr111431-1.c @@ -0,0 +1,39 @@ +int +foo (int a) +{ + int b = a == 0; + return (a & b); +} + +#define function(vol,cst) \ +__attribute__((noipa)) \ +_Bool func_##cst##_##vol(vol int a) \ +{ \ + vol int b = a == cst; \ + return (a & b); \ +} + +#define funcdefs(cst) \ +function(,cst) \ +function(volatile,cst) + +#define funcs(f) \ +f(0) \ +f(1) \ +f(5) + +funcs(funcdefs) + +#define test(cst) \ +do { \ + if(func_##cst##_(a) != func_##cst##_volatile(a))\ + __builtin_abort(); \ +} while(0); +int main(void) +{ + for(int a = -10; a <= 10; a++) + { + funcs(test) + } +} + diff --git a/gcc/testsuite/gcc.dg/binop-andeq1.c b/gcc/testsuite/gcc.dg/binop-andeq1.c new file mode 100644 index 000..2a92b8f95df --- /dev/null +++ b/gcc/testsuite/gcc.dg/binop-andeq1.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +/* PR tree-optimization/111431 */ + +int +foo (int a) +{ + int b = a == 2; + return (a & b); +} + +/* { dg-final { scan-tree-dump-times "return 0" 1 "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/binop-andeq2.c b/gcc/testsuite/gcc.dg/binop-andeq2.c new file mode 100644 index 000..895262fc17e --- /dev/null +++ b/gcc/testsuite/gcc.dg/binop-andeq2.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +/* PR tree-optimization/111431 */ + +int +foo (int a) +{ + int b = a == 1025; + return (a & b); +} + +/* { dg-final { scan-tree-dump-not "return 0" "optimized" } } */ +/* { dg-final { scan-tree-dump-not " & " "optimized" } } */ +/* { dg-final { scan-tree-dump-times " == 1025;" 1 "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/binop-notand1a.c b/gcc/testsuite/gcc.dg/binop-notand1a.c index c7e932b2638..d94685eb4ce 100644 --- a/gcc/testsuite/gcc.dg/binop-notand1a.c +++ b/gcc/testsuite/gcc.dg/binop-notand1a.c @@ -7,6 +7,4 @@ foo (char a, unsigned short b) return (a & !a) | (b & !b); } -/* As long as comparisons aren't boolified and casts from boolean-types - aren't preserved, the folding of X & !X to zero fails. */ -/* { dg-final { scan-tree-dump-times "return 0" 1 "optimized" { xfail *-*-* } } } */ +/* { dg-final { scan-tree-dump-times "return 0" 1 "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/binop-notand4a.c b/gcc/testsuite/gcc.dg/binop-notand4a.c index dce6a5c7eb5..bd9c7cce638 100644 --- a/gcc/testsuite/gcc.dg/binop-notand4a.c +++ b/gcc/testsuite/gcc.dg/binop-notand4a.c @@ -7,6 +7,4 @@ foo (unsigned char a, _Bool b) return (!a & a) | (b & !b); } -/* As long as comparisons aren't boolified and casts from boolean-types - aren't