]> gcc.gnu.org Git - gcc.git/commitdiff
re PR middle-end/24427 (missing optimization opportunity with binary operators)
authorRoger Sayle <roger@eyesopen.com>
Mon, 13 Feb 2006 18:33:32 +0000 (18:33 +0000)
committerRoger Sayle <sayle@gcc.gnu.org>
Mon, 13 Feb 2006 18:33:32 +0000 (18:33 +0000)
PR middle-end/24427
* fold-const.c (fold_binary) <BIT_IOR_EXPR>: Transform (X&C1)|C2
into (X,C2) if C1 is a subset of the bits of C2.  Transform
(X&C1)|C2 into X|C2 if C1|C2 == ~0.  Canonicalize (X&C1)|C2 as
(X&(C1&~C2))|C2.
<BIT_AND_EXPR>: Canonicalize (X|C1)&C2 as (X&C2)|(C1&C2).

* gcc.dg/tree-ssa/andor-1.c: New test case.

From-SVN: r110918

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

index 2c8fe9527c91c5e69a92b98c5a5db6e02cad6cf8..a5c9761dc4681096cebb01b9ed5ce1415cbd18b9 100644 (file)
@@ -1,3 +1,12 @@
+2006-02-13  Roger Sayle  <roger@eyesopen.com>
+
+       PR middle-end/24427
+       * fold-const.c (fold_binary) <BIT_IOR_EXPR>: Transform (X&C1)|C2
+       into (X,C2) if C1 is a subset of the bits of C2.  Transform
+       (X&C1)|C2 into X|C2 if C1|C2 == ~0.  Canonicalize (X&C1)|C2 as
+       (X&(C1&~C2))|C2.
+       <BIT_AND_EXPR>: Canonicalize (X|C1)&C2 as (X&C2)|(C1&C2).
+
 2006-02-13  Josh Conner  <jconner@apple.com>
 
        PR target/25376
index 67991076577de6d85fa523598d10988490a4e177..03c9d1c17e575946f0cc2725697b9cd6243e0a9d 100644 (file)
@@ -8114,6 +8114,53 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
          return omit_one_operand (type, t1, arg0);
        }
 
+      /* Canonicalize (X & C1) | C2.  */
+      if (TREE_CODE (arg0) == BIT_AND_EXPR
+         && TREE_CODE (arg1) == INTEGER_CST
+         && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
+       {
+         unsigned HOST_WIDE_INT hi1, lo1, hi2, lo2, mlo, mhi;
+         int width = TYPE_PRECISION (type);
+         hi1 = TREE_INT_CST_HIGH (TREE_OPERAND (arg0, 1));
+         lo1 = TREE_INT_CST_LOW (TREE_OPERAND (arg0, 1));
+         hi2 = TREE_INT_CST_HIGH (arg1);
+         lo2 = TREE_INT_CST_LOW (arg1);
+
+         /* If (C1&C2) == C1, then (X&C1)|C2 becomes (X,C2).  */
+         if ((hi1 & hi2) == hi1 && (lo1 & lo2) == lo1)
+           return omit_one_operand (type, arg1, TREE_OPERAND (arg0, 0));
+
+         if (width > HOST_BITS_PER_WIDE_INT)
+           {
+             mhi = (unsigned HOST_WIDE_INT) -1 
+                   >> (2 * HOST_BITS_PER_WIDE_INT - width);
+             mlo = -1;
+           }
+         else
+           {
+             mhi = 0;
+             mlo = (unsigned HOST_WIDE_INT) -1
+                   >> (HOST_BITS_PER_WIDE_INT - width);
+           }
+
+         /* If (C1|C2) == ~0 then (X&C1)|C2 becomes X|C2.  */
+         if ((~(hi1 | hi2) & mhi) == 0 && (~(lo1 | lo2) & mlo) == 0)
+           return fold_build2 (BIT_IOR_EXPR, type,
+                               TREE_OPERAND (arg0, 0), arg1);
+
+         /* Minimize the number of bits set in C1, i.e. C1 := C1 & ~C2.  */
+         hi1 &= mhi;
+         lo1 &= mlo;
+         if ((hi1 & ~hi2) != hi1 || (lo1 & ~lo2) != lo1)
+           return fold_build2 (BIT_IOR_EXPR, type,
+                               fold_build2 (BIT_AND_EXPR, type,
+                                            TREE_OPERAND (arg0, 0),
+                                            build_int_cst_wide (type,
+                                                                lo1 & ~lo2,
+                                                                hi1 & ~hi2)),
+                               arg1);
+       }
+
       t1 = distribute_bit_expr (code, type, arg0, arg1);
       if (t1 != NULL_TREE)
        return t1;
@@ -8256,6 +8303,16 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
          && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
        return omit_one_operand (type, integer_zero_node, arg0);
 
+      /* Canonicalize (X | C1) & C2 as (X & C2) | (C1 & C2).  */
+      if (TREE_CODE (arg0) == BIT_IOR_EXPR
+         && TREE_CODE (arg1) == INTEGER_CST
+         && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
+       return fold_build2 (BIT_IOR_EXPR, type,
+                           fold_build2 (BIT_AND_EXPR, type,
+                                        TREE_OPERAND (arg0, 0), arg1),
+                           fold_build2 (BIT_AND_EXPR, type,
+                                        TREE_OPERAND (arg0, 1), arg1));
+
       t1 = distribute_bit_expr (code, type, arg0, arg1);
       if (t1 != NULL_TREE)
        return t1;
index 3338042a72c87ecebf64c588c7ecba55683518ed..03caacb0f1a41a66c5a3bf1385fb936983251b26 100644 (file)
@@ -1,3 +1,8 @@
+2006-02-13  Roger Sayle  <roger@eyesopen.com>
+
+       PR middle-end/24427
+       * gcc.dg/tree-ssa/andor-1.c: New test case.
+
 2006-02-13  Josh Conner  <jconner@apple.com>
 
        PR target/25376
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/andor-1.c b/gcc/testsuite/gcc.dg/tree-ssa/andor-1.c
new file mode 100644 (file)
index 0000000..1a53857
--- /dev/null
@@ -0,0 +1,65 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-original" } */
+
+unsigned int test1(unsigned int a)
+{
+  return (a & 1) | 1;
+}
+
+int test2(int b)
+{
+  return (b & 1) | 1;
+}
+
+unsigned int test3(unsigned int c)
+{
+  return (c | 1) & 1;
+}
+
+int test4(int d)
+{
+  return (d | 1) & 1;
+}
+
+unsigned int test5(unsigned int e)
+{
+  return (e | 4) & 6;
+}
+
+int test6(int f)
+{
+  return (f | 4) & 6;
+}
+
+unsigned int test7(unsigned int g)
+{
+  return (g & -2) | 1;
+}
+
+int test8(int h)
+{
+  return (h & -2) | 1;
+}
+
+unsigned int test9(unsigned int i)
+{
+  return (i & 3) | 1;
+}
+
+int test10(int j)
+{
+  return (j & 3) | 1;
+}
+
+/* { dg-final { scan-tree-dump-times "a \& 1 \\| 1" 0 "original" } } */
+/* { dg-final { scan-tree-dump-times "b \& 1 \\| 1" 0 "original" } } */
+/* { dg-final { scan-tree-dump-times "\\(c \\| 1\\) \& 1" 0 "original" } } */
+/* { dg-final { scan-tree-dump-times "\\(d \\| 1\\) \& 1" 0 "original" } } */
+/* { dg-final { scan-tree-dump-times "e \& 2 \\| 4" 1 "original" } } */
+/* { dg-final { scan-tree-dump-times "f \& 2 \\| 4" 1 "original" } } */
+/* { dg-final { scan-tree-dump-times "g \\| 1" 1 "original" } } */
+/* { dg-final { scan-tree-dump-times "h \\| 1" 1 "original" } } */
+/* { dg-final { scan-tree-dump-times "i \& 2 \\| 1" 1 "original" } } */
+/* { dg-final { scan-tree-dump-times "j \& 2 \\| 1" 1 "original" } } */
+/* { dg-final { cleanup-tree-dump "original" } } */
+
This page took 0.106026 seconds and 5 git commands to generate.