]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
fold-const.c (fold_binary): Fold (X & Y) ^ Y as the equivalent ~X & Y, and the symmet...
authorRoger Sayle <roger@eyesopen.com>
Tue, 28 Mar 2006 17:55:26 +0000 (17:55 +0000)
committerRoger Sayle <sayle@gcc.gnu.org>
Tue, 28 Mar 2006 17:55:26 +0000 (17:55 +0000)
* fold-const.c (fold_binary) <BIT_XOR_EXPR>: Fold (X & Y) ^ Y as
the equivalent ~X & Y, and the symmetry related transformations.
(fold_binary) <BIT_AND_EXPR>: Similarly, fold (X ^ Y) & Y as
~X & Y, and symmetry related transforms.

* gcc.dg/fold-andxor-1.c: New test case.
* gcc.dg/fold-xorand-1.c: Likewise.

From-SVN: r112459

gcc/ChangeLog
gcc/fold-const.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/fold-andxor-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/fold-xorand-1.c [new file with mode: 0644]

index 12d43d44e02590d6e9b5eb13d2095fba6826af14..17f1e2e4fc2637619a0387edb42cdb95ca2013e6 100644 (file)
@@ -1,3 +1,10 @@
+2006-03-28  Roger Sayle  <roger@eyesopen.com>
+
+       * fold-const.c (fold_binary) <BIT_XOR_EXPR>: Fold (X & Y) ^ Y as
+       the equivalent ~X & Y, and the symmetry related transformations.
+       (fold_binary) <BIT_AND_EXPR>: Similarly, fold (X ^ Y) & Y as 
+       ~X & Y, and symmetry related transforms.
+
 2006-03-28  Maxim Kuvyrkov  <mkuvyrkov@ispras.ru>
 
        Revert my 2006-03-27 patches.
index 695dc5d35122ca504e07c62d9f3e4bc4d0235f51..aa710b126c8a3e9202f71b5ed6e6bdd84c87d7ab 100644 (file)
@@ -8803,6 +8803,45 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
        return fold_build2 (EQ_EXPR, type, arg0,
                            build_int_cst (TREE_TYPE (arg0), 0));
 
+      /* Fold (X & Y) ^ Y as ~X & Y.  */
+      if (TREE_CODE (arg0) == BIT_AND_EXPR
+         && operand_equal_p (TREE_OPERAND (arg0, 1), arg1, 0))
+       {
+         tem = fold_convert (type, TREE_OPERAND (arg0, 0));
+         return fold_build2 (BIT_AND_EXPR, type, 
+                             fold_build1 (BIT_NOT_EXPR, type, tem),
+                             fold_convert (type, arg1));
+       }
+      /* Fold (X & Y) ^ X as ~Y & X.  */
+      if (TREE_CODE (arg0) == BIT_AND_EXPR
+         && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0)
+         && reorder_operands_p (TREE_OPERAND (arg0, 1), arg1))
+       {
+         tem = fold_convert (type, TREE_OPERAND (arg0, 1));
+         return fold_build2 (BIT_AND_EXPR, type,
+                             fold_build1 (BIT_NOT_EXPR, type, tem),
+                             fold_convert (type, arg1));
+       }
+      /* Fold X ^ (X & Y) as X & ~Y.  */
+      if (TREE_CODE (arg1) == BIT_AND_EXPR
+         && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
+       {
+         tem = fold_convert (type, TREE_OPERAND (arg1, 1));
+         return fold_build2 (BIT_AND_EXPR, type,
+                             fold_convert (type, arg0),
+                             fold_build1 (BIT_NOT_EXPR, type, tem));
+       }
+      /* Fold X ^ (Y & X) as ~Y & X.  */
+      if (TREE_CODE (arg1) == BIT_AND_EXPR
+         && operand_equal_p (arg0, TREE_OPERAND (arg1, 1), 0)
+         && reorder_operands_p (arg0, TREE_OPERAND (arg1, 0)))
+       {
+         tem = fold_convert (type, TREE_OPERAND (arg1, 0));
+         return fold_build2 (BIT_AND_EXPR, type,
+                             fold_build1 (BIT_NOT_EXPR, type, tem),
+                             fold_convert (type, arg0));
+       }
+
       /* See if this can be simplified into a rotate first.  If that
         is unsuccessful continue in the association code.  */
       goto bit_rotate;
@@ -8877,6 +8916,45 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
                              build_int_cst (TREE_TYPE (tem), 0));
        }
 
+      /* Fold (X ^ Y) & Y as ~X & Y.  */
+      if (TREE_CODE (arg0) == BIT_XOR_EXPR
+         && operand_equal_p (TREE_OPERAND (arg0, 1), arg1, 0))
+       {
+         tem = fold_convert (type, TREE_OPERAND (arg0, 0));
+         return fold_build2 (BIT_AND_EXPR, type, 
+                             fold_build1 (BIT_NOT_EXPR, type, tem),
+                             fold_convert (type, arg1));
+       }
+      /* Fold (X ^ Y) & X as ~Y & X.  */
+      if (TREE_CODE (arg0) == BIT_XOR_EXPR
+         && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0)
+         && reorder_operands_p (TREE_OPERAND (arg0, 1), arg1))
+       {
+         tem = fold_convert (type, TREE_OPERAND (arg0, 1));
+         return fold_build2 (BIT_AND_EXPR, type,
+                             fold_build1 (BIT_NOT_EXPR, type, tem),
+                             fold_convert (type, arg1));
+       }
+      /* Fold X & (X ^ Y) as X & ~Y.  */
+      if (TREE_CODE (arg1) == BIT_XOR_EXPR
+         && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
+       {
+         tem = fold_convert (type, TREE_OPERAND (arg1, 1));
+         return fold_build2 (BIT_AND_EXPR, type,
+                             fold_convert (type, arg0),
+                             fold_build1 (BIT_NOT_EXPR, type, tem));
+       }
+      /* Fold X & (Y ^ X) as ~Y & X.  */
+      if (TREE_CODE (arg1) == BIT_XOR_EXPR
+         && operand_equal_p (arg0, TREE_OPERAND (arg1, 1), 0)
+         && reorder_operands_p (arg0, TREE_OPERAND (arg1, 0)))
+       {
+         tem = fold_convert (type, TREE_OPERAND (arg1, 0));
+         return fold_build2 (BIT_AND_EXPR, type,
+                             fold_build1 (BIT_NOT_EXPR, type, tem),
+                             fold_convert (type, arg0));
+       }
+
       t1 = distribute_bit_expr (code, type, arg0, arg1);
       if (t1 != NULL_TREE)
        return t1;
index 8443fdaded5c95555276e271be1dcfae19bee9b9..91e22200af4ad3868616dca263dc70f0b549fbeb 100644 (file)
@@ -1,3 +1,8 @@
+2006-03-28  Roger Sayle  <roger@eyesopen.com>
+
+       * gcc.dg/fold-andxor-1.c: New test case.
+       * gcc.dg/fold-xorand-1.c: Likewise.
+
 2006-03-28  Roger Sayle  <roger@eyesopen.com>
 
        * gcc.dg/fold-convnotconv-1.c: New test case.
diff --git a/gcc/testsuite/gcc.dg/fold-andxor-1.c b/gcc/testsuite/gcc.dg/fold-andxor-1.c
new file mode 100644 (file)
index 0000000..cc46577
--- /dev/null
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-original" } */
+
+int test1(int a, int b)
+{
+  return (a ^ b) & a;
+}
+
+int test2(int c, int d)
+{
+  return (c ^ d) & d;
+}
+
+int test3(int e, int f)
+{
+  return e & (e ^ f);
+}
+
+int test4(int g, int h)
+{
+  return g & (h ^ g);
+}
+
+/* { dg-final { scan-tree-dump-times "~b \& a" 1 "original" } } */
+/* { dg-final { scan-tree-dump-times "~c \& d" 1 "original" } } */
+/* { dg-final { scan-tree-dump-times "~f \& e" 1 "original" } } */
+/* { dg-final { scan-tree-dump-times "~h \& g" 1 "original" } } */
+/* { dg-final { cleanup-tree-dump "original" } } */
+
diff --git a/gcc/testsuite/gcc.dg/fold-xorand-1.c b/gcc/testsuite/gcc.dg/fold-xorand-1.c
new file mode 100644 (file)
index 0000000..8d42654
--- /dev/null
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-original" } */
+
+int test1(int a, int b)
+{
+  return (a & b) ^ a;
+}
+
+int test2(int c, int d)
+{
+  return (c & d) ^ d;
+}
+
+int test3(int e, int f)
+{
+  return e ^ (e & f);
+}
+
+int test4(int g, int h)
+{
+  return g ^ (h & g);
+}
+
+/* { dg-final { scan-tree-dump-times "~b \& a" 1 "original" } } */
+/* { dg-final { scan-tree-dump-times "~c \& d" 1 "original" } } */
+/* { dg-final { scan-tree-dump-times "~f \& e" 1 "original" } } */
+/* { dg-final { scan-tree-dump-times "~h \& g" 1 "original" } } */
+/* { dg-final { cleanup-tree-dump "original" } } */
+