diff mbox

match.pd: Three new patterns

Message ID 20150612121332.GH2756@redhat.com
State New
Headers show

Commit Message

Marek Polacek June 12, 2015, 12:13 p.m. UTC
This patch brings three new patterns for match.pd.  I think these are
rare, but it shouldn't hurt to have them.
(I suppose you'd be happier if I was moving patterns from fold-const to
match.pd.  I'll work on that as well.)

Given previous discussion, I don't think there's much to say otherwise,
but I'd appreciate if someone could glance over this.

Bootstrapped/regtested on x86_64-linux, ok for trunk?

2015-06-12  Marek Polacek  <polacek@redhat.com>

	* match.pd ((x & y) + (x ^ y) -> x | y,
	(x & y) + (x | y) -> x + y,
	(x | y) - (x ^ y) -> x & y): New patterns.

	* gcc.dg/fold-plus-1.c: New test.
	* gcc.dg/fold-plus-2.c: New test.
	* gcc.dg/fold-minus-2.c: New test.


	Marek

Comments

Marc Glisse June 13, 2015, 10:05 a.m. UTC | #1
They look fine to me.

> +/* (x & y) + (x ^ y) -> x | y */

This also works if you replace + with | or ^.

> +/* (x | y) - (x ^ y) -> x & y */

For symmetry, you probably also want:
(x | y) - (x & y) -> x ^ y

(they both also work with ^ instead of -)

> +/* (x & y) + (x | y) -> x + y */

Again for symmetry, it seems like this comes with
x + y - (x | y) -> x & y
x + y - (x & y) -> x | y
which seem fine when overflow is undefined or wraps, but not if for 
instance it saturates.
Richard Biener June 16, 2015, 1:35 p.m. UTC | #2
On Sat, 13 Jun 2015, Marc Glisse wrote:

> They look fine to me.
> 
> > +/* (x & y) + (x ^ y) -> x | y */
> 
> This also works if you replace + with | or ^.
>
> > +/* (x | y) - (x ^ y) -> x & y */
> 
> For symmetry, you probably also want:
> (x | y) - (x & y) -> x ^ y
> 
> (they both also work with ^ instead of -)

We already have

/* (x & y) ^ (x | y) -> x ^ y */
(simplify
 (bit_xor:c (bit_and @0 @1) (bit_ior @0 @1))
 (bit_xor @0 @1))

but of course with minus it doesn't commutate so it's hard to
merge.

> > +/* (x & y) + (x | y) -> x + y */
> 
> Again for symmetry, it seems like this comes with
> x + y - (x | y) -> x & y
> x + y - (x & y) -> x | y
> which seem fine when overflow is undefined or wraps, but not if for instance
> it saturates.

Can you adjust according to Marcs comment and re-submit?  If you like
you can do it as followup as well and thus the original patch is ok
as well.

Thanks,
Richard.
Marek Polacek June 18, 2015, 3:41 p.m. UTC | #3
On Sat, Jun 13, 2015 at 12:05:42PM +0200, Marc Glisse wrote:
> They look fine to me.

Thanks!
 
> >+/* (x & y) + (x ^ y) -> x | y */
> 
> This also works if you replace + with | or ^.

Done.
 
> >+/* (x | y) - (x ^ y) -> x & y */
> 
> For symmetry, you probably also want:
> (x | y) - (x & y) -> x ^ y
 
Done.

> (they both also work with ^ instead of -)

Done (except (x & y) ^ (x | y) -> x ^ y which we already have).

> >+/* (x & y) + (x | y) -> x + y */
> 
> Again for symmetry, it seems like this comes with
> x + y - (x | y) -> x & y
> x + y - (x & y) -> x | y
> which seem fine when overflow is undefined or wraps, but not if for instance
> it saturates.

I'll leave this as a follow-up.

Testing a new patch.  Thanks again.

	Marek
diff mbox

Patch

--- gcc/match.pd
+++ gcc/match.pd
@@ -325,6 +325,21 @@  along with GCC; see the file COPYING3.  If not see
  (bit_xor:c (bit_and @0 @1) (bit_ior @0 @1))
  (bit_xor @0 @1))
 
+/* (x & y) + (x ^ y) -> x | y */
+(simplify
+ (plus:c (bit_and @0 @1) (bit_xor @0 @1))
+ (bit_ior @0 @1))
+
+/* (x & y) + (x | y) -> x + y */
+(simplify
+ (plus:c (bit_and @0 @1) (bit_ior @0 @1))
+ (plus @0 @1))
+
+/* (x | y) - (x ^ y) -> x & y */
+(simplify
+ (minus (bit_ior @0 @1) (bit_xor @0 @1))
+ (bit_and @0 @1))
+
 (simplify
  (abs (negate @0))
  (abs @0))
--- gcc/testsuite/gcc.dg/fold-plus-1.c
+++ gcc/testsuite/gcc.dg/fold-plus-1.c
@@ -0,0 +1,70 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-cddce1" } */
+
+int
+fn1 (int a, int b)
+{
+  int tem1 = a & b;
+  int tem2 = a ^ b;
+  return tem1 + tem2;
+}
+
+int
+fn2 (int a, int b)
+{
+  int tem1 = b & a;
+  int tem2 = a ^ b;
+  return tem1 + tem2;
+}
+
+int
+fn3 (int a, int b)
+{
+  int tem1 = a & b;
+  int tem2 = b ^ a;
+  return tem1 + tem2;
+}
+
+int
+fn4 (int a, int b)
+{
+  int tem1 = b & a;
+  int tem2 = b ^ a;
+  return tem1 + tem2;
+}
+
+int
+fn5 (int a, int b)
+{
+  int tem1 = a ^ b;
+  int tem2 = a & b;
+  return tem1 + tem2;
+}
+
+int
+fn6 (int a, int b)
+{
+  int tem1 = b ^ a;
+  int tem2 = a & b;
+  return tem1 + tem2;
+}
+
+int
+fn7 (int a, int b)
+{
+  int tem1 = a ^ b;
+  int tem2 = b & a;
+  return tem1 + tem2;
+}
+
+int
+fn8 (int a, int b)
+{
+  int tem1 = b ^ a;
+  int tem2 = b & a;
+  return tem1 + tem2;
+}
+
+/* { dg-final { scan-tree-dump-not " & " "cddce1" } } */
+/* { dg-final { scan-tree-dump-not " \\^ " "cddce1" } } */
+/* { dg-final { scan-tree-dump-not " \\+ " "cddce1" } } */
--- gcc/testsuite/gcc.dg/fold-plus-2.c
+++ gcc/testsuite/gcc.dg/fold-plus-2.c
@@ -0,0 +1,69 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-cddce1" } */
+
+int
+fn1 (int a, int b)
+{
+  int tem1 = a & b;
+  int tem2 = a | b;
+  return tem1 + tem2;
+}
+
+int
+fn2 (int a, int b)
+{
+  int tem1 = b & a;
+  int tem2 = a | b;
+  return tem1 + tem2;
+}
+
+int
+fn3 (int a, int b)
+{
+  int tem1 = a & b;
+  int tem2 = b | a;
+  return tem1 + tem2;
+}
+
+int
+fn4 (int a, int b)
+{
+  int tem1 = b & a;
+  int tem2 = b | a;
+  return tem1 + tem2;
+}
+
+int
+fn5 (int a, int b)
+{
+  int tem1 = a | b;
+  int tem2 = a & b;
+  return tem1 + tem2;
+}
+
+int
+fn6 (int a, int b)
+{
+  int tem1 = b | a;
+  int tem2 = a & b;
+  return tem1 + tem2;
+}
+
+int
+fn7 (int a, int b)
+{
+  int tem1 = a | b;
+  int tem2 = b & a;
+  return tem1 + tem2;
+}
+
+int
+fn8 (int a, int b)
+{
+  int tem1 = b | a;
+  int tem2 = b & a;
+  return tem1 + tem2;
+}
+
+/* { dg-final { scan-tree-dump-not " & " "cddce1" } } */
+/* { dg-final { scan-tree-dump-not " \\| " "cddce1" } } */
--- gcc/testsuite/gcc.dg/fold-minus-2.c
+++ gcc/testsuite/gcc.dg/fold-minus-2.c
@@ -0,0 +1,37 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-cddce1" } */
+
+int
+fn1 (int a, int b)
+{
+  int tem1 = a | b;
+  int tem2 = a ^ b;
+  return tem1 - tem2;
+}
+
+int
+fn2 (int a, int b)
+{
+  int tem1 = b | a;
+  int tem2 = a ^ b;
+  return tem1 - tem2;
+}
+
+int
+fn3 (int a, int b)
+{
+  int tem1 = a | b;
+  int tem2 = b ^ a;
+  return tem1 - tem2;
+}
+
+int
+fn4 (int a, int b)
+{
+  int tem1 = b | a;
+  int tem2 = b ^ a;
+  return tem1 - tem2;
+}
+
+/* { dg-final { scan-tree-dump-not " \\^ " "cddce1" } } */
+/* { dg-final { scan-tree-dump-not " \\| " "cddce1" } } */