And some more.

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied.

Richard.

2014-09-12  Richard Biener  <rguent...@suse.de>

        * match-bitwise.pd: Complete tree-ssa-forwprop.c patterns
        from simplify_bitwise_binary.  Implement some from fold_binary.
        * match-constant-folding.pd: Add some comments.
        * match-plusminus.pd (~A + 1 -> -A): Fix COMPLEX_TYPE handling.

Index: gcc/match-bitwise.pd
===================================================================
--- gcc/match-bitwise.pd        (revision 215009)
+++ gcc/match-bitwise.pd        (working copy)
@@ -17,86 +17,211 @@ You should have received a copy of the G
 along with GCC; see the file COPYING3.  If not see
 <http://www.gnu.org/licenses/>.  */
 
-/* TODO bitwise patterns:
-1] x & x -> x
-2] x & 0 -> 0
-3] x & -1 -> x
-4] x & ~x -> 0
-5] ~x & ~y -> ~(x | y)
-6] ~x | ~y -> ~(x & y)
-7] x & (~x | y) -> y & x
-8] (x | CST1) & CST2  ->  (x & CST2) | (CST1 & CST2)
-9] x ^ x -> 0
-10] x ^ ~0 -> ~x
-11] (x | y) & x -> x
-12] (x & y) | x -> x
-13] (~x | y) & x -> x & y
-14] (~x & y) | x -> x | y
-15] ((a & b) & ~a) & ~b -> 0
-16] ~~x -> x
-*/
-
-/* x & x -> x */
-(simplify
-  (bit_and integral_op_p@0 @0)
-  @0)
-
-/* x & ~x -> 0 */
-(simplify
-  (bit_and:c integral_op_p@0 (bit_not @0))
-  { build_int_cst (type, 0); })
-
-/* ~x & ~y -> ~(x | y) */
-(simplify
-  (bit_and (bit_not integral_op_p@0) (bit_not @1))
-  (bit_not (bit_ior @0 @1)))
-
-/* ~x | ~y -> ~(x & y) */
-(simplify
-  (bit_ior (bit_not integral_op_p@0) (bit_not @1))
-  (bit_not (bit_and @0 @1)))
-
-/* x & (~x | y) -> y & x */
-(simplify
-  (bit_and:c integral_op_p@0 (bit_ior:c (bit_not @0) @1))
-  (bit_and @1 @0))
+/* Try to fold (type) X op CST -> (type) (X op ((type-x) CST))
+   when profitable.  */
+/* For bitwise binary operations apply operand conversions to the
+   binary operation result instead of to the operands.  This allows
+   to combine successive conversions and bitwise binary operations.  */
+/* We combine the above two cases by using a conditional convert.  */
+(for bitop (bit_and bit_ior bit_xor)
+ (simplify
+  (bitop (convert @0) (convert? @1))
+  (if (((TREE_CODE (@1) == INTEGER_CST
+        && INTEGRAL_TYPE_P (TREE_TYPE (@0))
+        && int_fits_type_p (@1, TREE_TYPE (@0)))
+       || types_compatible_p (TREE_TYPE (@0), TREE_TYPE (@1)))
+       && (/* That's a good idea if the conversion widens the operand, thus
+             after hoisting the conversion the operation will be narrower.  */
+          TYPE_PRECISION (TREE_TYPE (@0)) < TYPE_PRECISION (type)
+          /* It's also a good idea if the conversion is to a non-integer
+             mode.  */
+          || GET_MODE_CLASS (TYPE_MODE (type)) != MODE_INT
+          /* Or if the precision of TO is not the same as the precision
+             of its mode.  */
+          || TYPE_PRECISION (type) != GET_MODE_PRECISION (TYPE_MODE (type))))
+   (convert (bitop @0 (convert @1))))))
+
+/* Simplify (A & B) OP0 (C & B) to (A OP0 C) & B. */
+(for bitop (bit_and bit_ior bit_xor)
+ (simplify
+  (bitop (bit_and:c @0 @1) (bit_and @2 @1))
+  (bit_and (bitop @0 @2) @1)))
 
 /* (x | CST1) & CST2 -> (x & CST2) | (CST1 & CST2) */
 (simplify
-  (bit_and (bit_ior integral_op_p@0 INTEGER_CST@1) INTEGER_CST@2)
+  (bit_and (bit_ior @0 CONSTANT_CLASS_P@1) CONSTANT_CLASS_P@2)
   (bit_ior (bit_and @0 @2) (bit_and @1 @2)))
 
-/* x ^ ~0 -> ~x */
+/* Combine successive equal operations with constants.  */
+(for bitop (bit_and bit_ior bit_xor)
+ (simplify
+  (bitop (bitop @0 CONSTANT_CLASS_P@1) CONSTANT_CLASS_P@2)
+  (bitop @0 (bitop @1 @2))))
+
+/* Canonicalize X ^ ~0 to ~X.  */
 (simplify
   (bit_xor @0 integer_all_onesp@1)
   (bit_not @0))
 
-/* (x | y) & x -> x */
-(simplify
-  (bit_and:c (bit_ior integral_op_p@0 @1) @0)
+/* Try simple folding for X op !X, and X op X.
+   From tree-ssa-forwprop.c:simplify_bitwise_binary_1.  */
+/* x & x -> x,  x | x -> x  */
+(for bitop (bit_and bit_ior)
+ (simplify
+  (bitop @0 @0)
+  @0))
+/* X & ~X -> 0.  */
+(simplify
+  (bit_and:c @0 (bit_not @0))
+  { build_zero_cst (type); })
+/* X | ~X -> ~0,  X ^ ~X -> ~0.  */
+(for bitop (bit_ior bit_xor)
+ (simplify
+  (bitop:c @0 (bit_not @0))
+  { build_all_ones_cst (type); }))
+/* ???  The following ones are suspicious and want generalization.
+   Also X != 1 vs. X ^ 1 vs ~X wants canonicalization for truth
+   values.  */
+#if 0  /* FIXME.  truth_valued_ssa_name isn't exported either.  */
+(for bitop (bit_and bit_ior bit_xor)
+ /* X & (X == 0) -> 0.  */
+ /* X | (X == 0) -> 1.  */
+ (simplify
+  (bitop:c @0 (eq @0 integer_zerop))
+  (if (truth_valued_ssa_name (@0))
+   { bitop == BIT_AND ? build_zero_cst (type) : build_one_cst (type); }))
+ /* X & (X != 1) -> 0,  X & (X ^ 1) -> 0 for truth-valued X.  */
+ /* X | (X != 1) -> 1,  X | (X ^ 1) -> 1 for truth-valued X.  */
+ (for op (ne bit_xor)
+  (simplify
+   (bitop:c @0 (op @0 integer_onep))
+   (if (truth_valued_ssa_name (@0))
+    { bitop == BIT_AND ? build_zero_cst (type) : build_one_cst (type); }))))
+#endif
+
+(for bitop (bit_and bit_ior)
+     rbitop (bit_ior bit_and)
+  /* (x | y) & x -> x */
+  /* (x & y) | x -> x */
+ (simplify
+  (bitop:c (rbitop:c @0 @1) @0)
   @0)
+ /* (~x | y) & x -> x & y */
+ /* (~x & y) | x -> x | y */
+ (simplify
+  (bitop:c (rbitop:c (bit_not @0) @1) @0)
+  (bitop @0 @1)))
+
+/* If arg1 and arg2 are booleans (or any single bit type)
+   then try to simplify:
+
+   (~X & Y) -> X < Y
+   (X & ~Y) -> Y < X
+   (~X | Y) -> X <= Y
+   (X | ~Y) -> Y <= X
+
+   But only do this if our result feeds into a comparison as
+   this transformation is not always a win, particularly on
+   targets with and-not instructions.
+   -> simplify_bitwise_binary_boolean */
+(simplify
+  (ne (bit_and:c (bit_not @0) @1) integer_zerop)
+  (if (INTEGRAL_TYPE_P (TREE_TYPE (@1))
+       && TYPE_PRECISION (TREE_TYPE (@1)) == 1)
+   (lt @0 @1)))
+(simplify
+  (ne (bit_ior:c (bit_not @0) @1) integer_zerop)
+  (if (INTEGRAL_TYPE_P (TREE_TYPE (@1))
+       && TYPE_PRECISION (TREE_TYPE (@1)) == 1)
+   (le @0 @1)))
 
-/* (x & y) | x -> x */
-(simplify
-  (bit_ior:c (bit_and integral_op_p@0 @1) @0)
-  @0)
 
-/* (~x | y) & x -> x & y */
+/* End of known transform origin.  Note that some bitwise transforms
+   are handled in match-constant-folding.pd.  */
+
+/* ~x & ~y -> ~(x | y) */
 (simplify
-  (bit_and:c (bit_ior:c (bit_not integral_op_p@0) @1) @0)
-  (bit_and @0 @1))
+  (bit_and (bit_not @0) (bit_not @1))
+  (bit_not (bit_ior @0 @1)))
 
-/* (~x & y) | x -> x | y */
+/* ~x | ~y -> ~(x & y) */
 (simplify
-  (bit_ior:c (bit_and:c (bit_not integral_op_p@0) @1) @0)
-  (bit_ior @0 @1))
+  (bit_ior (bit_not @0) (bit_not @1))
+  (bit_not (bit_and @0 @1)))
 
 /* ~~x -> x */
 (simplify
-  (bit_not (bit_not integral_op_p@0))
+  (bit_not (bit_not @0))
   @0)
 
-/* ((a & b) & ~a) -> 0 */
-(simplify
-  (bit_and:c (bit_and integral_op_p@0 @1) (bit_not @0))
-  { build_int_cst (type, 0); })
+/* Simple association cases that cancel one operand.  */
+
+/* ((a OP b) & ~a) -> (b & ~a) OP 0  */
+(for bitop (bit_and bit_ior bit_xor)
+ (simplify
+  (bit_and:c (bitop:c @0 @1) (bit_not@2 @0))
+  (bitop (bit_and @1 @2) { build_zero_cst (type); })))
+
+/* From fold-const.c:fold_binary_loc, in order of appearance.  */
+
+/* If we are XORing 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 (bit_and @0 INTEGER_CST@1) (bit_and @2 INTEGER_CST@3))
+ (if (wi::bit_and (@1, @3) == 0)
+   (bit_ior (bit_and @0 @1) (bit_and @2 @3))))
+
+/* ((a | b) ^ a) -> b & ~a  */
+(simplify
+ (bit_xor:c (bit_ior:c @0 @1) @0)
+ (bit_and @1 (bit_not @0)))
+
+/* Convert ~X ^ ~Y to X ^ Y.  */
+(simplify
+ (bit_xor (bit_not @0) (bit_not @1))
+ (bit_xor @0 @1))
+
+/* Convert ~X ^ C to X ^ ~C.  */
+(simplify
+ (bit_xor (bit_not @0) INTEGER_CST@1)
+ (bit_xor @0 (bit_not @1)))
+
+/* Fold (X & 1) ^ 1 as (X & 1) == 0.  */
+/* Questionable on GIMPLE as the equality compare can't have a
+   type different from boolean_type_node.  */
+
+/* Fold (X & Y) ^ Y as ~X & Y.  */
+(simplify
+ (bit_xor:c (bit_and:c @0 @1) @1)
+ (bit_and (bit_not @0) @1))
+
+
+/* PR61559.  Transforms for gcc.dg/builtin-bswap-8.c  */
+(for bswap (BUILT_IN_BSWAP16 BUILT_IN_BSWAP32 BUILT_IN_BSWAP64)
+  (simplify
+    (bswap (bswap @0))
+    @0)
+  (simplify
+    (bswap (bit_not (bswap @0)))
+    (bit_not @0))
+  (for bitop (bit_xor bit_ior bit_and)
+    /* This might not be profitable if the inner bswaps are
+       free because @0 and @1 are memory operands and the
+       target has an instruction for load+bswap.  */
+    (simplify
+      (bitop (bswap @0) (bswap @1))
+      (bswap (bitop @0 @1)))
+    (simplify
+      (bswap (bitop:c (bswap @0) @1))
+      (bitop @0 (bswap @1)))))
+
+/* Similar transform for vector permute.
+   ???  Missing an easy way to check if a mask is a reverse
+   operation of another mask (most masks are not reversible).  */
+(for bitop (bit_xor bit_ior bit_and)
+  (simplify
+    (bitop (vec_perm @1 @2 @0) (vec_perm @3 @4 @0))
+    (vec_perm (bitop @1 @3) (bitop @2 @4) @0)))
+
Index: gcc/match-constant-folding.pd
===================================================================
--- gcc/match-constant-folding.pd       (revision 215010)
+++ gcc/match-constant-folding.pd       (working copy)
@@ -55,18 +55,22 @@ along with GCC; see the file COPYING3.
   (if (!integer_zerop (@1))
    @0))
 
+/* x | ~0 -> ~0  */
 (simplify
   (bit_ior @0 integer_all_onesp@1)
   @1)
 
+/* x ^ ~0 -> ~x  */
 (simplify
   (bit_and @0 integer_all_onesp)
   @0)
 
+/* x & 0 -> 0  */
 (simplify
   (bit_and @0 integer_zerop@1)
   @1)
 
+/* x ^ x -> 0 */
 (simplify
   (bit_xor @0 @0)
   { build_zero_cst (type); })
Index: gcc/match-plusminus.pd
===================================================================
--- gcc/match-plusminus.pd      (revision 215170)
+++ gcc/match-plusminus.pd      (working copy)
@@ -85,8 +85,9 @@ along with GCC; see the file COPYING3.
 
   /* ~A + 1 -> -A */
   (simplify
-   (plus (bit_not @0) integer_onep@1)
-   (if (TREE_CODE (TREE_TYPE (@1)) != COMPLEX_TYPE
+   (plus (bit_not @0) @1)
+   (if ((TREE_CODE (TREE_TYPE (@1)) != COMPLEX_TYPE
+        && integer_onep (@1))
        || (TREE_CODE (@1) == COMPLEX_CST
            && integer_onep (TREE_REALPART (@1))
            && integer_onep (TREE_IMAGPART (@1))))

Reply via email to