This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Add (x & ~m) | (y & m) folding (PR middle-end/63568)
- From: Marek Polacek <polacek at redhat dot com>
- To: GCC Patches <gcc-patches at gcc dot gnu dot org>, Richard Biener <rguenther at suse dot de>
- Date: Wed, 17 Dec 2014 09:46:44 +0100
- Subject: [PATCH] Add (x & ~m) | (y & m) folding (PR middle-end/63568)
- Authentication-results: sourceware.org; auth=none
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 <polacek@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