diff mbox

Fix PR 33512 Folding of x & ((~x) | y) into x & y on the tree level

Message ID CA+=Sn1kFkikJcCvjCk7W2e=ne06vM9yoBwfmr5u2oFesUBT7-A@mail.gmail.com
State New
Headers show

Commit Message

Andrew Pinski Jan. 17, 2012, 7:06 a.m. UTC
Hi,
  This adds the folding of x & ((~x) | y)) into x & y on the tree
level via fold-const.c
There is already partly done on the RTL level but it would be a good
thing for the tree level also.


OK for 4.8 (yes I know we have not branched yet but I thought I would
send it out so I don't forget about it)?
Bootstrapped and tested on x86_64-linux-gnu with no regressions.

Thanks,
Andrew Pinski

ChangeLog:
* fold-const.c (fold_binary_loc <case BIT_AND_EXPR>): Add folding of x
& (~x | y) into x & y.

testsuite/ChangeLog:
* gcc.dg/tree-ssa/andor-3.c: New testcase.

Comments

Richard Biener Jan. 17, 2012, 9:38 a.m. UTC | #1
On Tue, Jan 17, 2012 at 8:06 AM, Andrew Pinski
<andrew.pinski@caviumnetworks.com> wrote:
> Hi,
>  This adds the folding of x & ((~x) | y)) into x & y on the tree
> level via fold-const.c
> There is already partly done on the RTL level but it would be a good
> thing for the tree level also.
>
>
> OK for 4.8 (yes I know we have not branched yet but I thought I would
> send it out so I don't forget about it)?
> Bootstrapped and tested on x86_64-linux-gnu with no regressions.

Can you instead patch tree-ssa-forwprop.c:simplify_bitwise_binary?

Thanks,
Richard.

> Thanks,
> Andrew Pinski
>
> ChangeLog:
> * fold-const.c (fold_binary_loc <case BIT_AND_EXPR>): Add folding of x
> & (~x | y) into x & y.
>
> testsuite/ChangeLog:
> * gcc.dg/tree-ssa/andor-3.c: New testcase.
diff mbox

Patch

Index: fold-const.c
===================================================================
--- fold-const.c	(revision 183228)
+++ fold-const.c	(working copy)
@@ -11378,6 +11378,43 @@  fold_binary_loc (location_t loc,
 			      fold_build1_loc (loc, BIT_NOT_EXPR, type, tem),
 			      fold_convert_loc (loc, type, arg0));
 	}
+      /* Fold X & (~X | Y) as X & Y. */
+      if (TREE_CODE (arg1) == BIT_IOR_EXPR
+	  && TREE_CODE (TREE_OPERAND (arg1, 0)) == BIT_NOT_EXPR
+	  && operand_equal_p (arg0, TREE_OPERAND (TREE_OPERAND (arg1, 0), 0), 0))
+	{
+	  tem = fold_convert_loc (loc, type, TREE_OPERAND (arg1, 1));
+	  return fold_build2_loc (loc, BIT_AND_EXPR, type,
+				  fold_convert_loc (loc, type, arg0), tem);
+	}
+      /* Fold X & (Y | ~X) as X & Y. */
+      if (TREE_CODE (arg1) == BIT_IOR_EXPR
+	  && TREE_CODE (TREE_OPERAND (arg1, 1)) == BIT_NOT_EXPR
+	  && operand_equal_p (arg0, TREE_OPERAND (TREE_OPERAND (arg1, 1), 0), 0))
+	{
+	  tem = fold_convert_loc (loc, type, TREE_OPERAND (arg1, 0));
+	  return fold_build2_loc (loc, BIT_AND_EXPR, type,
+				  fold_convert_loc (loc, type, arg0), tem);
+	}
+      /* Fold (~X | Y) & X as X & Y. */
+      if (TREE_CODE (arg0) == BIT_IOR_EXPR
+	  && TREE_CODE (TREE_OPERAND (arg0, 0)) == BIT_NOT_EXPR
+	  && operand_equal_p (arg1, TREE_OPERAND (TREE_OPERAND (arg0, 0), 0), 0))
+	{
+	  tem = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 1));
+	  return fold_build2_loc (loc, BIT_AND_EXPR, type,
+				  fold_convert_loc (loc, type, arg1), tem);
+	}
+      /* Fold (Y | ~X) & X as  Y & X. */
+      if (TREE_CODE (arg0) == BIT_IOR_EXPR
+	  && TREE_CODE (TREE_OPERAND (arg0, 1)) == BIT_NOT_EXPR
+	  && operand_equal_p (arg1, TREE_OPERAND (TREE_OPERAND (arg0, 1), 0), 0))
+	{
+	  tem = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0));
+	  return fold_build2_loc (loc, BIT_AND_EXPR, type,
+				  tem, fold_convert_loc (loc, type, arg1));
+	}
+
 
       /* For constants M and N, if M == (1LL << cst) - 1 && (N & M) == M,
 	 ((A & N) + B) & M -> (A + B) & M
Index: testsuite/gcc.dg/tree-ssa/andor-3.c
===================================================================
--- testsuite/gcc.dg/tree-ssa/andor-3.c	(revision 0)
+++ testsuite/gcc.dg/tree-ssa/andor-3.c	(revision 0)
@@ -0,0 +1,24 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-original" } */
+
+int f(int y, int x)
+{
+  return x & ((~x) | y);
+}
+int f1(int y, int x)
+{
+  return x & (y | (~x));
+}
+int f2(int y, int x)
+{
+  return ((~x) | y) & x;
+}
+int f3(int y, int x)
+{
+  return (y | (~x)) & x;
+}
+
+
+/* { dg-final { scan-tree-dump-times "~x" 0 "original" } } */
+/* { dg-final { scan-tree-dump-times "x \& y" 4 "original" } } */
+/* { dg-final { cleanup-tree-dump "original" } } */