gcc.dg/20150120-2.c: New test Clearing a certain subset of bits, for example to round down x to a multiple of a power of 2, is sometimes written x & ~(x & y), where y may or may not be a constant. It is shorter to use x & ~y, particularly when y is a constant. gcc already does this when it is spelled x - (x & y) or x ^ (x & y).
Signed-off-by: Rasmus Villemoes <r...@rasmusvillemoes.dk> --- gcc/match.pd | 6 ++++++ gcc/testsuite/gcc.dg/20150120-2.c | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 gcc/testsuite/gcc.dg/20150120-2.c diff --git gcc/match.pd gcc/match.pd index ecefcfb..d25fc3a 100644 --- gcc/match.pd +++ gcc/match.pd @@ -261,6 +261,12 @@ along with GCC; see the file COPYING3. If not see (if (TREE_CODE (@2) != SSA_NAME || has_single_use (@2)) (bit_and (plus @0 @1) (bit_not @1)))) +/* x & ~(x & y) -> x & ~y */ +(simplify + (bit_and:c @0 (bit_not (bit_and:c@2 @0 @1))) + (if (TREE_CODE (@2) != SSA_NAME || has_single_use (@2)) + (bit_and @0 (bit_not @1)))) + (simplify (abs (negate @0)) (abs @0)) diff --git gcc/testsuite/gcc.dg/20150120-2.c gcc/testsuite/gcc.dg/20150120-2.c new file mode 100644 index 0000000..976b654 --- /dev/null +++ gcc/testsuite/gcc.dg/20150120-2.c @@ -0,0 +1,32 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-original" } */ + +/* x & ~(x & y) -> x & ~y */ +int fn1 (int x, int y) +{ + return x & ~(x & y); +} +int fn2 (int x, int y) +{ + return ~(x & y) & x; +} +int fn3 (int x, int y) +{ + return x & ~(y & x); +} +int fn4 (int x, int y) +{ + return ~(y & x) & x; +} +int fn5 (int z) +{ + return z & ~(z & 3); +} +int fn6 (int z) +{ + return ~(z & 3) & z; +} + + +/* { dg-final { scan-tree-dump-times "~y & x" 4 "original" } } */ +/* { dg-final { scan-tree-dump-times "z & -4" 2 "original" } } */ -- 2.1.3