This adds a transformation of (x & ~m) | (y & m), which (on GIMPLE) has 4 ops to x ^ ((x ^ y) & m) that has 3 ops on GIMPLE. In fact, the latter is then transformed to (a ^ b) & m ^ a, which also has 3 ops. As discussed in the PR, the original form might also be 3-op on targets that support something like andn instruction (e.g. BMI1 on Intel), but that is something for expand/combine.
Not sure if some single-use restriction applies here or not. Bootstrapped/regtested on x86_64-linux and ppc64-linux, ok for trunk? 2014-12-17 Marek Polacek <pola...@redhat.com> PR middle-end/63568 * match.pd: Add (x & ~m) | (y & m) -> x ^ ((x ^ y) & m). * gcc.dg/pr63568.c: New test. diff --git gcc/match.pd gcc/match.pd index dbca99e..161b639 100644 --- gcc/match.pd +++ gcc/match.pd @@ -382,6 +382,11 @@ along with GCC; see the file COPYING3. If not see (bit_not (bit_not @0)) @0) +/* (x & ~m) | (y & m) -> x ^ ((x ^ y) & m) */ +(simplify + (bit_ior:c (bit_and:c @0 (bit_not @2)) (bit_and:c @1 @2)) + (bit_xor @0 (bit_and (bit_xor @0 @1) @2))) + /* Associate (p +p off1) +p off2 as (p +p (off1 + off2)). */ (simplify diff --git gcc/testsuite/gcc.dg/pr63568.c gcc/testsuite/gcc.dg/pr63568.c index e69de29..fb42bea 100644 --- gcc/testsuite/gcc.dg/pr63568.c +++ gcc/testsuite/gcc.dg/pr63568.c @@ -0,0 +1,54 @@ +/* PR middle-end/63568 */ +/* { dg-do compile } */ +/* { dg-options "-fdump-tree-original" } */ + +int +fn1 (int a, int b, int m) +{ + return (a & ~m) | (b & m); +} + +int +fn2 (int a, int b, int m) +{ + return (a & ~m) | (m & b); +} + +int +fn3 (int a, int b, int m) +{ + return (~m & a) | (m & b); +} + +int +fn4 (int a, int b, int m) +{ + return (~m & a) | (b & m); +} + +int +fn5 (int a, int b, int m) +{ + return (b & m) | (a & ~m); +} + +int +fn6 (int a, int b, int m) +{ + return (m & b) | (a & ~m); +} + +int +fn7 (int a, int b, int m) +{ + return (m & b) | (~m & a); +} + +int +fn8 (int a, int b, int m) +{ + return (b & m) | (~m & a); +} + +/* { dg-final { scan-tree-dump-not " \\| " "original" } } */ +/* { dg-final { cleanup-tree-dump "original" } } */ Marek