On Tue, Dec 16, 2014 at 03:08:23PM +0100, Richard Biener wrote: > You can use > > (for cmp (ne eq) > icmp (eq ne) > (simplify > (cmp (bit_and (lshift integer_onep @0) integer_onep) integer_zerop) > (icmp @0 { build_zero_cst (TREE_TYPE (@0)); }))) > > to combine both patterns. Btw, shoudln't it be (bit_and (...)
Ah, we can have multiple operators to iterate (and yes, it's documented, my bad). > integer_each_onep)? I'm always unsure about the complex integer case > (maybe try a runtime testcase and see what happens - eventually we > just don't support bit operations on them...) Correct - we don't allow complex operands for neither shift, nor bit and. So I left the integer_onep in there. Thanks. 2014-12-16 Marek Polacek <pola...@redhat.com> PR middle-end/64309 * match.pd: Add ((1 << A) & 1) != 0 -> A == 0 and ((1 << A) & 1) == 0 -> A != 0. * gcc.dg/pr64309.c: New test. diff --git gcc/match.pd gcc/match.pd index 083d65f..dbca99e 100644 --- gcc/match.pd +++ gcc/match.pd @@ -599,6 +599,13 @@ along with GCC; see the file COPYING3. If not see build_int_cst (TREE_TYPE (@1), element_precision (type)), @1); })) +/* ((1 << A) & 1) != 0 -> A == 0 + ((1 << A) & 1) == 0 -> A != 0 */ +(for cmp (ne eq) + icmp (eq ne) + (simplify + (cmp (bit_and (lshift integer_onep @0) integer_onep) integer_zerop) + (icmp @0 { build_zero_cst (TREE_TYPE (@0)); }))) /* Simplifications of conversions. */ diff --git gcc/testsuite/gcc.dg/pr64309.c gcc/testsuite/gcc.dg/pr64309.c index e69de29..710a762 100644 --- gcc/testsuite/gcc.dg/pr64309.c +++ gcc/testsuite/gcc.dg/pr64309.c @@ -0,0 +1,66 @@ +/* PR middle-end/64309 */ +/* { dg-do run } */ +/* { dg-options "-fdump-tree-original" } */ + +int +fn1 (int n) +{ + return ((1 << n) & 1) != 0; +} + +int +fn2 (int n) +{ + return (1 & (1 << n)) != 0; +} + +int +fn3 (int n) +{ + return ((1 << n) & 1) == 0; +} + +int +fn4 (int n) +{ + return (1 & (1 << n)) == 0; +} + +int +main (void) +{ + if (fn1 (0) != 1 + || fn1 (1) != 0 + || fn1 (2) != 0 + || fn1 (3) != 0 + || fn1 (4) != 0 + || fn1 (5) != 0) + __builtin_abort (); + + if (fn2 (0) != 1 + || fn2 (1) != 0 + || fn2 (2) != 0 + || fn2 (3) != 0 + || fn2 (4) != 0 + || fn2 (5) != 0) + __builtin_abort (); + + if (fn3 (0) != 0 + || fn3 (1) != 1 + || fn3 (2) != 1 + || fn3 (3) != 1 + || fn3 (4) != 1 + || fn3 (5) != 1) + __builtin_abort (); + + if (fn4 (0) != 0 + || fn4 (1) != 1 + || fn4 (2) != 1 + || fn4 (3) != 1 + || fn4 (4) != 1 + || fn4 (5) != 1) + __builtin_abort (); +} + +/* { dg-final { scan-tree-dump-not "(<<|>>)" "original" } } */ +/* { dg-final { cleanup-tree-dump "original" } } */ Marek