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))))