* fold-const.c (fold_binary) <EQ_EXPR>: Fold "(X^C1) eq/ne C2" into
authorsayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 2 Jan 2007 04:32:07 +0000 (04:32 +0000)
committersayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 2 Jan 2007 04:32:07 +0000 (04:32 +0000)
"X eq/ne (C1^C2)".  Fold "(X^Z) eq/ne (Y^Z)" as "X eq/ne Y" when Z
has no side-effects.  Fold "(X^C1) eq/ne (Y^C2)" as "(X^(C1^C2))
eq/ne Y".

* gcc.dg/fold-eqxor-4.c: New test case.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@120333 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/fold-const.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/fold-eqxor-4.c [new file with mode: 0644]

index 810f6e0..dca58fe 100644 (file)
@@ -1,3 +1,10 @@
+2007-01-01  Roger Sayle  <roger@eyesopen.com>
+
+       * fold-const.c (fold_binary) <EQ_EXPR>: Fold "(X^C1) eq/ne C2" into
+       "X eq/ne (C1^C2)".  Fold "(X^Z) eq/ne (Y^Z)" as "X eq/ne Y" when Z
+       has no side-effects.  Fold "(X^C1) eq/ne (Y^C2)" as "(X^(C1^C2))
+       eq/ne Y".
+
 2007-01-01  Mike Stump  <mrs@apple.com>
 
        * configure.ac: Remove support for building with Apple's gcc-3.1.
index 071ddcd..8826908 100644 (file)
@@ -10753,6 +10753,15 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
          && ! TREE_CONSTANT_OVERFLOW (tem))
        return fold_build2 (code, type, TREE_OPERAND (arg0, 0), tem);
 
+      /* Similarly for a BIT_XOR_EXPR;  X ^ C1 == C2 is X == (C1 ^ C2).  */
+      if (TREE_CODE (arg0) == BIT_XOR_EXPR
+         && TREE_CODE (arg1) == INTEGER_CST
+         && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
+       return fold_build2 (code, type, TREE_OPERAND (arg0, 0),
+                           fold_build2 (BIT_XOR_EXPR, TREE_TYPE (arg0),
+                                        fold_convert (TREE_TYPE (arg0), arg1),
+                                        TREE_OPERAND (arg0, 1)));
+
       /* If we have X - Y == 0, we can convert that to X == Y and similarly
         for !=.  Don't do this for ordered comparisons due to overflow.  */
       if (TREE_CODE (arg0) == MINUS_EXPR
@@ -11106,6 +11115,36 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
                                build_int_cst (itype, 0));
        }
 
+      if (TREE_CODE (arg0) == BIT_XOR_EXPR
+         && TREE_CODE (arg1) == BIT_XOR_EXPR)
+       {
+         tree arg00 = TREE_OPERAND (arg0, 0);
+         tree arg01 = TREE_OPERAND (arg0, 1);
+         tree arg10 = TREE_OPERAND (arg1, 0);
+         tree arg11 = TREE_OPERAND (arg1, 1);
+         tree itype = TREE_TYPE (arg0);
+
+         /* Optimize (X ^ Z) op (Y ^ Z) as X op Y, and symmetries.
+            operand_equal_p guarantees no side-effects so we don't need
+            to use omit_one_operand on Z.  */
+         if (operand_equal_p (arg01, arg11, 0))
+           return fold_build2 (code, type, arg00, arg10);
+         if (operand_equal_p (arg01, arg10, 0))
+           return fold_build2 (code, type, arg00, arg11);
+         if (operand_equal_p (arg00, arg11, 0))
+           return fold_build2 (code, type, arg01, arg10);
+         if (operand_equal_p (arg00, arg10, 0))
+           return fold_build2 (code, type, arg01, arg11);
+
+         /* Optimize (X ^ C1) op (Y ^ C2) as (X ^ (C1 ^ C2)) op Y.  */
+         if (TREE_CODE (arg01) == INTEGER_CST
+             && TREE_CODE (arg11) == INTEGER_CST)
+           return fold_build2 (code, type,
+                               fold_build2 (BIT_XOR_EXPR, itype, arg00,
+                                            fold_build2 (BIT_XOR_EXPR, itype,
+                                                         arg01, arg11)),
+                               arg10);
+       }
       return NULL_TREE;
 
     case LT_EXPR:
index b636d48..429382b 100644 (file)
@@ -1,3 +1,7 @@
+2007-01-01  Roger Sayle  <roger@eyesopen.com>
+
+       * gcc.dg/fold-eqxor-4.c: New test case.
+
 2007-01-02  Joseph Myers  <joseph@codesourcery.com>
 
        PR middle-end/30311
diff --git a/gcc/testsuite/gcc.dg/fold-eqxor-4.c b/gcc/testsuite/gcc.dg/fold-eqxor-4.c
new file mode 100644 (file)
index 0000000..bdf31bc
--- /dev/null
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-original" } */
+
+int test1(int a)
+{
+  return (a ^ 6) == 2;
+}
+
+int test2(int b, int c, int d)
+{
+  return (b ^ d) == (c ^ d);
+}
+
+int test3(int e, int f)
+{
+  return (e ^ 6) == (f ^ 4);
+}
+
+/* { dg-final { scan-tree-dump-times "a == 4" 1 "original" } } */
+/* { dg-final { scan-tree-dump-times "b == c" 1 "original" } } */
+/* { dg-final { scan-tree-dump-times "e \\^ 2" 1 "original" } } */
+/* { dg-final { cleanup-tree-dump "original" } } */