OSDN Git Service

PR tree-optimization/13827
authorsayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 12 Nov 2006 18:41:31 +0000 (18:41 +0000)
committersayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 12 Nov 2006 18:41:31 +0000 (18:41 +0000)
* fold-const.c (fold_binary) <EQ_EXPR, NE_EXPR>: Fold (X&C) op (Y&C)
as ((X^Y)&C) op 0.

* gcc.dg/fold-eqand-1.c: New test case.

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

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

index 081c6cf..e1a2a65 100644 (file)
@@ -1,3 +1,9 @@
+2006-11-12  Roger Sayle  <roger@eyesopen.com>
+
+       PR tree-optimization/13827
+       * fold-const.c (fold_binary) <EQ_EXPR, NE_EXPR>: Fold (X&C) op (Y&C)
+       as ((X^Y)&C) op 0.
+
 2006-11-12  Zdenek Dvorak <dvorakz@suse.cz>
 
        * cfgloopmanip.c (update_single_exit_for_duplicated_loop,
index 08e74a2..cf1df69 100644 (file)
@@ -10818,6 +10818,49 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
                            TREE_OPERAND (arg0, 0),
                            TREE_OPERAND (arg1, 0));
 
+      /* Fold (X & C) op (Y & C) as (X ^ Y) & C op 0", and symmetries.  */
+      if (TREE_CODE (arg0) == BIT_AND_EXPR
+         && TREE_CODE (arg1) == BIT_AND_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);
+
+         if (operand_equal_p (arg01, arg11, 0))
+           return fold_build2 (code, type,
+                               fold_build2 (BIT_AND_EXPR, itype,
+                                            fold_build2 (BIT_XOR_EXPR, itype,
+                                                         arg00, arg10),
+                                            arg01),
+                               build_int_cst (itype, 0));
+
+         if (operand_equal_p (arg01, arg10, 0))
+           return fold_build2 (code, type,
+                               fold_build2 (BIT_AND_EXPR, itype,
+                                            fold_build2 (BIT_XOR_EXPR, itype,
+                                                         arg00, arg11),
+                                            arg01),
+                               build_int_cst (itype, 0));
+
+         if (operand_equal_p (arg00, arg11, 0))
+           return fold_build2 (code, type,
+                               fold_build2 (BIT_AND_EXPR, itype,
+                                            fold_build2 (BIT_XOR_EXPR, itype,
+                                                         arg01, arg10),
+                                            arg00),
+                               build_int_cst (itype, 0));
+
+         if (operand_equal_p (arg00, arg10, 0))
+           return fold_build2 (code, type,
+                               fold_build2 (BIT_AND_EXPR, itype,
+                                            fold_build2 (BIT_XOR_EXPR, itype,
+                                                         arg01, arg11),
+                                            arg00),
+                               build_int_cst (itype, 0));
+       }
+
       return NULL_TREE;
 
     case LT_EXPR:
index c8bd6d4..5a2b502 100644 (file)
@@ -1,3 +1,8 @@
+2006-11-12  Roger Sayle  <roger@eyesopen.com>
+
+       PR tree-optimization/13827
+       * gcc.dg/fold-eqand-1.c: New test case.
+
 2006-11-11  Andrew Pinski  <andrew_pinski@playstation.sony.com>
 
        PR rtl-opt/28812
diff --git a/gcc/testsuite/gcc.dg/fold-eqand-1.c b/gcc/testsuite/gcc.dg/fold-eqand-1.c
new file mode 100644 (file)
index 0000000..6ed5b6d
--- /dev/null
@@ -0,0 +1,17 @@
+/* PR tree-optimization/13827 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-original" } */
+
+unsigned foo (unsigned a, unsigned b)
+{
+  return (a & 0xff00) != (b & 0xff00);
+}
+
+unsigned bar (unsigned c, unsigned d)
+{
+  return (c & 0xff00) == (d & 0xff00);
+}
+
+/* { dg-final { scan-tree-dump-times "a \\^ b" 1 "original" } } */
+/* { dg-final { scan-tree-dump-times "c \\^ d" 1 "original" } } */
+/* { dg-final { cleanup-tree-dump "original" } } */