Simple bitop reassoc in match.pd
authorMarc Glisse <marc.glisse@inria.fr>
Tue, 10 May 2016 19:52:20 +0000 (21:52 +0200)
committerMarc Glisse <glisse@gcc.gnu.org>
Tue, 10 May 2016 19:52:20 +0000 (19:52 +0000)
2016-05-10  Marc Glisse  <marc.glisse@inria.fr>

gcc/
* fold-const.c (fold_binary_loc) [(X ^ Y) & Y]: Remove and merge with...
* match.pd ((X & Y) ^ Y): ... this.
((X & Y) & Y, (X | Y) | Y, (X ^ Y) ^ Y, (X & Y) & (X & Z), (X | Y)
| (X | Z), (X ^ Y) ^ (X ^ Z)): New transformations.

gcc/testsuite/
* gcc.dg/tree-ssa/bit-assoc.c: New testcase.
* gcc.dg/tree-ssa/pr69270.c: Adjust.
* gcc.dg/tree-ssa/vrp59.c: Disable forwprop.

From-SVN: r236103

gcc/ChangeLog
gcc/fold-const.c
gcc/match.pd
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/bit-assoc.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/pr69270.c
gcc/testsuite/gcc.dg/tree-ssa/vrp59.c

index 2e58aebb21d7c3df692a23109030835920114337..0f20a323c6bef894fa67992cc1b9dc7b2e849d42 100644 (file)
@@ -1,3 +1,10 @@
+2016-05-10  Marc Glisse  <marc.glisse@inria.fr>
+
+       * fold-const.c (fold_binary_loc) [(X ^ Y) & Y]: Remove and merge with...
+       * match.pd ((X & Y) ^ Y): ... this.
+       ((X & Y) & Y, (X | Y) | Y, (X ^ Y) ^ Y, (X & Y) & (X & Z), (X | Y)
+       | (X | Z), (X ^ Y) ^ (X ^ Z)): New transformations.
+
 2016-05-10  David Malcolm  <dmalcolm@redhat.com>
 
        * read-md.c (require_char_ws): New function.
index 8aabe2155fa6962e6b256d8805bc50dda6cb0942..0ef48ddd54e446e4f8d65e9dc111f2eaed43d9d5 100644 (file)
@@ -10071,45 +10071,6 @@ fold_binary_loc (location_t loc,
                                  build_zero_cst (TREE_TYPE (tem)));
        }
 
-      /* 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_loc (loc, type, TREE_OPERAND (arg0, 0));
-         return fold_build2_loc (loc, BIT_AND_EXPR, type,
-                             fold_build1_loc (loc, BIT_NOT_EXPR, type, tem),
-                             fold_convert_loc (loc, 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_loc (loc, type, TREE_OPERAND (arg0, 1));
-         return fold_build2_loc (loc, BIT_AND_EXPR, type,
-                             fold_build1_loc (loc, BIT_NOT_EXPR, type, tem),
-                             fold_convert_loc (loc, 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_loc (loc, type, TREE_OPERAND (arg1, 1));
-         return fold_build2_loc (loc, BIT_AND_EXPR, type,
-                             fold_convert_loc (loc, type, arg0),
-                             fold_build1_loc (loc, 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_loc (loc, type, TREE_OPERAND (arg1, 0));
-         return fold_build2_loc (loc, BIT_AND_EXPR, type,
-                             fold_build1_loc (loc, BIT_NOT_EXPR, type, tem),
-                             fold_convert_loc (loc, type, arg0));
-       }
-
       /* Fold (X * Y) & -(1 << CST) to X * Y if Y is a constant
          multiple of 1 << CST.  */
       if (TREE_CODE (arg1) == INTEGER_CST)
index e511e9a6b9b71d7a42b3bc20b109095fdd465a50..5b3cb3bfd5e86dce2708c909b76d37da09855ca9 100644 (file)
@@ -674,10 +674,12 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
  (if (tree_nop_conversion_p (type, TREE_TYPE (@0)))
   (bit_xor (convert @0) (bit_not @1))))
 
-/* Fold (X & Y) ^ Y as ~X & Y.  */
-(simplify
- (bit_xor:c (bit_and:c @0 @1) @1)
- (bit_and (bit_not @0) @1))
+/* Fold (X & Y) ^ Y and (X ^ Y) & Y as ~X & Y.  */
+(for opo (bit_and bit_xor)
+     opi (bit_xor bit_and)
+ (simplify
+  (opo:c (opi:c @0 @1) @1) 
+  (bit_and (bit_not @0) @1)))
 
 /* Given a bit-wise operation CODE applied to ARG0 and ARG1, see if both
    operands are another bit-wise operation with a common input.  If so,
@@ -693,6 +695,35 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
        && tree_nop_conversion_p (type, TREE_TYPE (@2)))
    (rop (convert @0) (op (convert @1) (convert @2))))))
 
+/* Some simple reassociation for bit operations, also handled in reassoc.  */
+/* (X & Y) & Y -> X & Y
+   (X | Y) | Y -> X | Y  */
+(for op (bit_and bit_ior)
+ (simplify
+  (op:c (convert?@2 (op:c @0 @1)) (convert? @1))
+  @2))
+/* (X ^ Y) ^ Y -> X  */
+(simplify
+ (bit_xor:c (convert? (bit_xor:c @0 @1)) (convert? @1))
+ (if (tree_nop_conversion_p (type, TREE_TYPE (@0)))
+  (convert @0)))
+/* (X & Y) & (X & Z) -> (X & Y) & Z
+   (X | Y) | (X | Z) -> (X | Y) | Z  */
+(for op (bit_and bit_ior)
+ (simplify
+  (op:c (convert1?@3 (op:c@4 @0 @1)) (convert2?@5 (op:c@6 @0 @2)))
+  (if (tree_nop_conversion_p (type, TREE_TYPE (@1))
+       && tree_nop_conversion_p (type, TREE_TYPE (@2)))
+   (if (single_use (@5) && single_use (@6))
+    (op @3 (convert @2))
+    (if (single_use (@3) && single_use (@4))
+     (op (convert @1) @5))))))
+/* (X ^ Y) ^ (X ^ Z) -> Y ^ Z  */
+(simplify
+ (bit_xor (convert1? (bit_xor:c @0 @1)) (convert2? (bit_xor:c @0 @2)))
+ (if (tree_nop_conversion_p (type, TREE_TYPE (@1))
+      && tree_nop_conversion_p (type, TREE_TYPE (@2)))
+  (convert (bit_xor @1 @2))))
 
 (simplify
  (abs (abs@1 @0))
index 7ab92a51390ca6bb35b929458cb64e879d6917ca..ee47bd8bdf74908f86c03957f23dc31db9ebd257 100644 (file)
@@ -1,3 +1,9 @@
+2016-05-10  Marc Glisse  <marc.glisse@inria.fr>
+
+       * gcc.dg/tree-ssa/bit-assoc.c: New testcase.
+       * gcc.dg/tree-ssa/pr69270.c: Adjust.
+       * gcc.dg/tree-ssa/vrp59.c: Disable forwprop.
+
 2016-05-10  Ilya Enkovich  <ilya.enkovich@intel.com>
 
        PR target/70799
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/bit-assoc.c b/gcc/testsuite/gcc.dg/tree-ssa/bit-assoc.c
new file mode 100644 (file)
index 0000000..b563f5e
--- /dev/null
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-forwprop1-details -fdump-tree-ccp1-details" } */
+
+int f1(int a, int b){
+  int c = a & b;
+  return c & b;
+}
+int f2(int a, int b){
+  int c = a | b;
+  return b | c;
+}
+int g1(int a, int b, int c){
+  int d = a & b;
+  int e = b & c;
+  return d & e;
+}
+int g2(int a, int b, int c){
+  int d = a | b;
+  int e = c | b;
+  return d | e;
+}
+int g3(int a, int b, int c){
+  int d = a ^ b;
+  int e = b ^ c;
+  return e ^ d;
+}
+
+/* { dg-final { scan-tree-dump-times "Match-and-simplified" 2 "ccp1" } } */
+/* { dg-final { scan-tree-dump-times "gimple_simplified" 3 "forwprop1" } } */
index 529b5212a2751e127626ecba582093b2f4bf208b..28f6d0fac286574a77209b9735f43e7e933c3ae3 100644 (file)
@@ -7,8 +7,10 @@
 /* { dg-final { scan-tree-dump-times "Replaced .bufferstep_\[0-9\]+. with constant .1." 1 "dom3"} } */
 
 /* And some assignments ought to fold down to constants.  */
-/* { dg-final { scan-tree-dump-times "Folded to: _\[0-9\]+ = 1;" 2 "dom3"} } */
-/* { dg-final { scan-tree-dump-times "Folded to: _\[0-9\]+ = 0;" 2 "dom3"} } */
+/* { dg-final { scan-tree-dump-times "Folded to: _\[0-9\]+ = -1;" 1 "dom3"} } */
+/* { dg-final { scan-tree-dump-times "Folded to: _\[0-9\]+ = -2;" 1 "dom3"} } */
+/* { dg-final { scan-tree-dump-times "Folded to: _\[0-9\]+ = 1;" 1 "dom3"} } */
+/* { dg-final { scan-tree-dump-times "Folded to: _\[0-9\]+ = 0;" 1 "dom3"} } */
 
 /* The XOR operations should have been optimized to constants.  */
 /* { dg-final { scan-tree-dump-not "bit_xor" "dom3"} } */
index 0f5801dd78524562b5c14978790850ab1ead6a4a..5f6e9d956f096bb87f457c6947fdd23ed65cf1e8 100644 (file)
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-O2 -fno-tree-ccp -fdump-tree-vrp1" } */
+/* { dg-options "-O2 -fno-tree-ccp -fno-tree-forwprop -fdump-tree-vrp1" } */
 
 int f(int x)
 {