fold-const.c (distribute_bit_expr): Remove.
authorRichard Biener <rguenther@suse.de>
Fri, 10 Jul 2015 12:31:05 +0000 (12:31 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Fri, 10 Jul 2015 12:31:05 +0000 (12:31 +0000)
2015-07-10  Richard Biener  <rguenther@suse.de>

* fold-const.c (distribute_bit_expr): Remove.
(fold_binary_loc): Move simplifying (A & C1) + (B & C2)
to (A & C1) | (B & C2), distributing (A & B) | (A & C)
to A & (B | C) and simplifying A << C1 << C2 to ...
* match.pd: ... patterns here.

From-SVN: r225670

gcc/ChangeLog
gcc/fold-const.c
gcc/match.pd

index 643b4f5bff5a7467cce0ebb7dce523293e03c24a..5cfac4e9278fcd73c2b59b508fc43636c1026c03 100644 (file)
@@ -1,3 +1,11 @@
+2015-07-10  Richard Biener  <rguenther@suse.de>
+
+       * fold-const.c (distribute_bit_expr): Remove.
+       (fold_binary_loc): Move simplifying (A & C1) + (B & C2)
+       to (A & C1) | (B & C2), distributing (A & B) | (A & C)
+       to A & (B | C) and simplifying A << C1 << C2 to ...
+       * match.pd: ... patterns here.
+
 2015-07-10  Jiong Wang  <jiong.wang@arm.com>
 
        * config/aarch64/aarch64.c (aarch64_load_symref_appropriately): Mark mem
index f78ec4e68dfa08954bacc01df0ca1c0d04e8f267..7078edb16346a7abd8c02f2fd832d52a13a2a90f 100644 (file)
@@ -118,7 +118,6 @@ static enum tree_code compcode_to_comparison (enum comparison_code);
 static int operand_equal_for_comparison_p (tree, tree, tree);
 static int twoval_comparison_p (tree, tree *, tree *, int *);
 static tree eval_subst (location_t, tree, tree, tree, tree, tree);
-static tree distribute_bit_expr (location_t, enum tree_code, tree, tree, tree);
 static tree make_bit_field_ref (location_t, tree, tree,
                                HOST_WIDE_INT, HOST_WIDE_INT, int);
 static tree optimize_bit_field_compare (location_t, enum tree_code,
@@ -3550,62 +3549,6 @@ invert_truthvalue_loc (location_t loc, tree arg)
                          type, arg);
 }
 
-/* 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,
-   distribute the bit operations to save an operation and possibly two if
-   constants are involved.  For example, convert
-       (A | B) & (A | C) into A | (B & C)
-   Further simplification will occur if B and C are constants.
-
-   If this optimization cannot be done, 0 will be returned.  */
-
-static tree
-distribute_bit_expr (location_t loc, enum tree_code code, tree type,
-                    tree arg0, tree arg1)
-{
-  tree common;
-  tree left, right;
-
-  if (TREE_CODE (arg0) != TREE_CODE (arg1)
-      || TREE_CODE (arg0) == code
-      || (TREE_CODE (arg0) != BIT_AND_EXPR
-         && TREE_CODE (arg0) != BIT_IOR_EXPR))
-    return 0;
-
-  if (operand_equal_p (TREE_OPERAND (arg0, 0), TREE_OPERAND (arg1, 0), 0))
-    {
-      common = TREE_OPERAND (arg0, 0);
-      left = TREE_OPERAND (arg0, 1);
-      right = TREE_OPERAND (arg1, 1);
-    }
-  else if (operand_equal_p (TREE_OPERAND (arg0, 0), TREE_OPERAND (arg1, 1), 0))
-    {
-      common = TREE_OPERAND (arg0, 0);
-      left = TREE_OPERAND (arg0, 1);
-      right = TREE_OPERAND (arg1, 0);
-    }
-  else if (operand_equal_p (TREE_OPERAND (arg0, 1), TREE_OPERAND (arg1, 0), 0))
-    {
-      common = TREE_OPERAND (arg0, 1);
-      left = TREE_OPERAND (arg0, 0);
-      right = TREE_OPERAND (arg1, 1);
-    }
-  else if (operand_equal_p (TREE_OPERAND (arg0, 1), TREE_OPERAND (arg1, 1), 0))
-    {
-      common = TREE_OPERAND (arg0, 1);
-      left = TREE_OPERAND (arg0, 0);
-      right = TREE_OPERAND (arg1, 0);
-    }
-  else
-    return 0;
-
-  common = fold_convert_loc (loc, type, common);
-  left = fold_convert_loc (loc, type, left);
-  right = fold_convert_loc (loc, type, right);
-  return fold_build2_loc (loc, TREE_CODE (arg0), type, common,
-                     fold_build2_loc (loc, code, type, left, right));
-}
-
 /* Knowing that ARG0 and ARG1 are both RDIV_EXPRs, simplify a binary operation
    with code CODE.  This optimization is unsafe.  */
 static tree
@@ -9575,21 +9518,6 @@ fold_binary_loc (location_t loc,
 
       if (! FLOAT_TYPE_P (type))
        {
-         /* If we are adding two BIT_AND_EXPR's, both of which are and'ing
-            with a constant, and the two constants have no bits in common,
-            we should treat this as a BIT_IOR_EXPR since this may produce more
-            simplifications.  */
-         if (TREE_CODE (arg0) == BIT_AND_EXPR
-             && TREE_CODE (arg1) == BIT_AND_EXPR
-             && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
-             && TREE_CODE (TREE_OPERAND (arg1, 1)) == INTEGER_CST
-             && wi::bit_and (TREE_OPERAND (arg0, 1),
-                             TREE_OPERAND (arg1, 1)) == 0)
-           {
-             code = BIT_IOR_EXPR;
-             goto bit_ior;
-           }
-
          /* Reassociate (plus (plus (mult) (foo)) (mult)) as
             (plus (plus (mult) (mult)) (foo)) so that we can
             take advantage of the factoring cases below.  */
@@ -10423,7 +10351,6 @@ fold_binary_loc (location_t loc,
       goto associate;
 
     case BIT_IOR_EXPR:
-    bit_ior:
       /* Canonicalize (X & C1) | C2.  */
       if (TREE_CODE (arg0) == BIT_AND_EXPR
          && TREE_CODE (arg1) == INTEGER_CST
@@ -10494,10 +10421,6 @@ fold_binary_loc (location_t loc,
            return fold_build2_loc (loc, BIT_XOR_EXPR, type, l0, n1);
        }
 
-      t1 = distribute_bit_expr (loc, code, type, arg0, arg1);
-      if (t1 != NULL_TREE)
-       return t1;
-
       /* See if this can be simplified into a rotate first.  If that
         is unsuccessful continue in the association code.  */
       goto bit_rotate;
@@ -10760,9 +10683,6 @@ fold_binary_loc (location_t loc,
            }
        }
 
-      t1 = distribute_bit_expr (loc, code, type, arg0, arg1);
-      if (t1 != NULL_TREE)
-       return t1;
       /* Simplify ((int)c & 0377) into (int)c, if c is unsigned char.  */
       if (TREE_CODE (arg1) == INTEGER_CST && TREE_CODE (arg0) == NOP_EXPR
          && TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (arg0, 0))))
@@ -11111,32 +11031,6 @@ fold_binary_loc (location_t loc,
 
       prec = element_precision (type);
 
-      /* Turn (a OP c1) OP c2 into a OP (c1+c2).  */
-      if (TREE_CODE (op0) == code && tree_fits_uhwi_p (arg1)
-         && tree_to_uhwi (arg1) < prec
-         && tree_fits_uhwi_p (TREE_OPERAND (arg0, 1))
-         && tree_to_uhwi (TREE_OPERAND (arg0, 1)) < prec)
-       {
-         unsigned int low = (tree_to_uhwi (TREE_OPERAND (arg0, 1))
-                             + tree_to_uhwi (arg1));
-
-         /* Deal with a OP (c1 + c2) being undefined but (a OP c1) OP c2
-            being well defined.  */
-         if (low >= prec)
-           {
-             if (code == LROTATE_EXPR || code == RROTATE_EXPR)
-               low = low % prec;
-             else if (TYPE_UNSIGNED (type) || code == LSHIFT_EXPR)
-               return omit_one_operand_loc (loc, type, build_zero_cst (type),
-                                        TREE_OPERAND (arg0, 0));
-             else
-               low = prec - 1;
-           }
-
-         return fold_build2_loc (loc, code, type, TREE_OPERAND (arg0, 0),
-                                 build_int_cst (TREE_TYPE (arg1), low));
-       }
-
       /* Transform (x >> c) << c into x & (-1<<c), or transform (x << c) >> c
          into x & ((unsigned)-1 >> c) for unsigned types.  */
       if (((code == LSHIFT_EXPR && TREE_CODE (arg0) == RSHIFT_EXPR)
index b28f107be90bb764298e2964dc6db3227eb3ff1d..b991008b47f8ea77f4c1be40cd65b18343ae4fb1 100644 (file)
@@ -419,17 +419,18 @@ along with GCC; see the file COPYING3.  If not see
        && tree_nop_conversion_p (type, TREE_TYPE (@1)))
    (bit_not (rop (convert @0) (convert @1))))))
 
-/* If we are XORing two BIT_AND_EXPR's, both of which are and'ing
+/* If we are XORing or adding two BIT_AND_EXPR's, both of which are and'ing
    with a constant, and the two constants have no bits in common,
    we should treat this as a BIT_IOR_EXPR since this may produce more
    simplifications.  */
-(simplify
- (bit_xor (convert1? (bit_and@4 @0 INTEGER_CST@1))
-          (convert2? (bit_and@5 @2 INTEGER_CST@3)))
- (if (tree_nop_conversion_p (type, TREE_TYPE (@0))
-      && tree_nop_conversion_p (type, TREE_TYPE (@2))
-      && wi::bit_and (@1, @3) == 0)
-  (bit_ior (convert @4) (convert @5))))
+(for op (bit_xor plus)
+ (simplify
+  (op (convert1? (bit_and@4 @0 INTEGER_CST@1))
+      (convert2? (bit_and@5 @2 INTEGER_CST@3)))
+  (if (tree_nop_conversion_p (type, TREE_TYPE (@0))
+       && tree_nop_conversion_p (type, TREE_TYPE (@2))
+       && wi::bit_and (@1, @3) == 0)
+   (bit_ior (convert @4) (convert @5)))))
 
 /* (X | Y) ^ X -> Y & ~ X*/
 (simplify
@@ -455,6 +456,19 @@ along with GCC; see the file COPYING3.  If not see
  (bit_xor:c (bit_and: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,
+   distribute the bit operations to save an operation and possibly two if
+   constants are involved.  For example, convert
+     (A | B) & (A | C) into A | (B & C)
+   Further simplification will occur if B and C are constants.  */
+(for op (bit_and bit_ior)
+     rop (bit_ior bit_and)
+ (simplify
+  (op (convert? (rop:c @0 @1)) (convert? (rop @0 @2)))
+  (if (tree_nop_conversion_p (type, TREE_TYPE (@0)))
+   (rop (convert @0) (op (convert @1) (convert @2))))))
+
 
 (simplify
  (abs (abs@1 @0))
@@ -880,6 +894,27 @@ along with GCC; see the file COPYING3.  If not see
                            build_int_cst (TREE_TYPE (@1),
                                           element_precision (type)), @1); }))
 
+/* Turn (a OP c1) OP c2 into a OP (c1+c2).  */
+(for op (lrotate rrotate rshift lshift)
+ (simplify
+  (op (op @0 INTEGER_CST@1) INTEGER_CST@2)
+  (with { unsigned int prec = element_precision (type); }
+   (if (wi::ge_p (@1, 0, TYPE_SIGN (TREE_TYPE (@1)))
+        && wi::lt_p (@1, prec, TYPE_SIGN (TREE_TYPE (@1)))
+        && wi::ge_p (@2, 0, TYPE_SIGN (TREE_TYPE (@2)))
+       && wi::lt_p (@2, prec, TYPE_SIGN (TREE_TYPE (@2))))
+    (with { unsigned int low = wi::add (@1, @2).to_uhwi (); }
+     /* Deal with a OP (c1 + c2) being undefined but (a OP c1) OP c2
+        being well defined.  */
+     (if (low >= prec)
+      (if (op == LROTATE_EXPR || op == RROTATE_EXPR)
+       (op @0 { build_int_cst (TREE_TYPE (@1), low % prec); }))
+      (if (TYPE_UNSIGNED (type) || code == LSHIFT_EXPR)
+       { build_zero_cst (type); })
+      (op @0 { build_int_cst (TREE_TYPE (@1), prec - 1); }))
+     (op @0 { build_int_cst (TREE_TYPE (@1), low); }))))))
+
+
 /* ((1 << A) & 1) != 0 -> A == 0
    ((1 << A) & 1) == 0 -> A != 0 */
 (for cmp (ne eq)