Hello,we already have the more complicated: x & ~(x & y) -> x & ~y (which I am reindenting by the way) and the simpler: (~x | y) & x -> x & y, so I am proposing this one for completeness. Regtested on ppc64le-redhat-linux.
2015-05-15 Marc Glisse <marc.gli...@inria.fr> gcc/ * match.pd ((x | y) & ~x -> y & ~x, (x & y) | ~x -> y | ~x): New simplifications. gcc/testsuite/ * gcc.dg/nand.c: New testcase. -- Marc Glisse
Index: match.pd =================================================================== --- match.pd (revision 223217) +++ match.pd (working copy) @@ -257,24 +257,32 @@ along with GCC; see the file COPYING3. /* x + (x & 1) -> (x + 1) & ~1 */ (simplify (plus:c @0 (bit_and@2 @0 integer_onep@1)) (if (TREE_CODE (@2) != SSA_NAME || has_single_use (@2)) (bit_and (plus @0 @1) (bit_not @1)))) /* x & ~(x & y) -> x & ~y */ /* x | ~(x | y) -> x | ~y */ (for bitop (bit_and bit_ior) - (simplify - (bitop:c @0 (bit_not (bitop:c@2 @0 @1))) - (if (TREE_CODE (@2) != SSA_NAME || has_single_use (@2)) - (bitop @0 (bit_not @1))))) + (simplify + (bitop:c @0 (bit_not (bitop:c@2 @0 @1))) + (if (TREE_CODE (@2) != SSA_NAME || has_single_use (@2)) + (bitop @0 (bit_not @1))))) + +/* (x | y) & ~x -> y & ~x */ +/* (x & y) | ~x -> y | ~x */ +(for bitop (bit_and bit_ior) + rbitop (bit_ior bit_and) + (simplify + (bitop:c (rbitop:c @0 @1) (bit_not@2 @0)) + (bitop @1 @2))) (simplify (abs (negate @0)) (abs @0)) (simplify (abs tree_expr_nonnegative_p@0) @0) /* Try to fold (type) X op CST -> (type) (X op ((type-x) CST)) Index: testsuite/gcc.dg/nand.c =================================================================== --- testsuite/gcc.dg/nand.c (revision 0) +++ testsuite/gcc.dg/nand.c (working copy) @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-original" } */ + +unsigned f(unsigned x, unsigned y){ + return (x | y) & ~x; +} +unsigned g(unsigned x, unsigned y){ + return ~x & (y | x); +} + +/* { dg-final { scan-tree-dump-times "return ~x & y;" 2 "original" } } */ +/* { dg-final { cleanup-tree-dump "original" } } */