===================================================================
@@ -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)))
+
===================================================================
@@ -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); })
===================================================================
@@ -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))))