This moves a few more patterns from fold-const.c to match.pd, also covering two cases where fold basically recurses (calling fold_unary or using negate_expr_p/negate_expr). For these cases we have to implement a subset of all possible cases (all fold cases basically searching for some stuff arbitrarily deep in an expression tree would need to be converted to a propagator-like pass rather than too many patterns).
It also moves (x & y) | x -> x before (x | CST1) & CST2 -> (x & CST2) | (CST1 & CST2) so it has the chance to match (x | 1) & 1 which with the first pattern simplifies without needing intermediate stmts (which I don't allow for SCCVN for efficiency reasons). As for other generator inputs what comes earlier is matched earlier. Bootstrap and regtest running on x86_64-unknown-linux-gnu. I think next I'll merge trunk into match-and-simplify and see what patterns I have implemented there and will either kill them off if they are broken or move them. Richard. 2015-06-29 Richard Biener <rguent...@suse.de> * fold-const.c (fold_unary_loc): Move abs(abs(x)) -> abs(x), ~ (-A) to A - 1, ~ (A - 1) or ~ (A + -1) to -A and some cases of ~(X ^ Y) to ~X ^ Y or X ^ ~Y if ~X or ~Y simplify to ... * match.pd: ... here. Add a few cases of A - B -> A + (-B) when B "easily" negates. Move (x & y) | x -> x and friends before (x | CST1) & CST2 -> (x & CST2) | (CST1 & CST2). Index: gcc/fold-const.c =================================================================== *** gcc/fold-const.c (revision 225115) --- gcc/fold-const.c (working copy) *************** fold_unary_loc (location_t loc, enum tre *** 8131,8139 **** TREE_TYPE (targ0), targ0)); } - /* ABS_EXPR<ABS_EXPR<x>> = ABS_EXPR<x> even if flag_wrapv is on. */ - else if (TREE_CODE (arg0) == ABS_EXPR) - return arg0; /* Strip sign ops from argument. */ if (TREE_CODE (type) == REAL_TYPE) --- 8131,8136 ---- *************** fold_unary_loc (location_t loc, enum tre *** 8161,8193 **** return NULL_TREE; case BIT_NOT_EXPR: - /* Convert ~ (-A) to A - 1. */ - if (INTEGRAL_TYPE_P (type) && TREE_CODE (arg0) == NEGATE_EXPR) - return fold_build2_loc (loc, MINUS_EXPR, type, - fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0)), - build_int_cst (type, 1)); - /* Convert ~ (A - 1) or ~ (A + -1) to -A. */ - else if (INTEGRAL_TYPE_P (type) - && ((TREE_CODE (arg0) == MINUS_EXPR - && integer_onep (TREE_OPERAND (arg0, 1))) - || (TREE_CODE (arg0) == PLUS_EXPR - && integer_all_onesp (TREE_OPERAND (arg0, 1))))) - { - /* Perform the negation in ARG0's type and only then convert - to TYPE as to avoid introducing undefined behavior. */ - tree t = fold_build1_loc (loc, NEGATE_EXPR, - TREE_TYPE (TREE_OPERAND (arg0, 0)), - TREE_OPERAND (arg0, 0)); - return fold_convert_loc (loc, type, t); - } /* Convert ~(X ^ Y) to ~X ^ Y or X ^ ~Y if ~X or ~Y simplify. */ ! else if (TREE_CODE (arg0) == BIT_XOR_EXPR ! && (tem = fold_unary_loc (loc, BIT_NOT_EXPR, type, ! fold_convert_loc (loc, type, ! TREE_OPERAND (arg0, 0))))) return fold_build2_loc (loc, BIT_XOR_EXPR, type, tem, ! fold_convert_loc (loc, type, ! TREE_OPERAND (arg0, 1))); else if (TREE_CODE (arg0) == BIT_XOR_EXPR && (tem = fold_unary_loc (loc, BIT_NOT_EXPR, type, fold_convert_loc (loc, type, --- 8158,8171 ---- return NULL_TREE; case BIT_NOT_EXPR: /* Convert ~(X ^ Y) to ~X ^ Y or X ^ ~Y if ~X or ~Y simplify. */ ! if (TREE_CODE (arg0) == BIT_XOR_EXPR ! && (tem = fold_unary_loc (loc, BIT_NOT_EXPR, type, ! fold_convert_loc (loc, type, ! TREE_OPERAND (arg0, 0))))) return fold_build2_loc (loc, BIT_XOR_EXPR, type, tem, ! fold_convert_loc (loc, type, ! TREE_OPERAND (arg0, 1))); else if (TREE_CODE (arg0) == BIT_XOR_EXPR && (tem = fold_unary_loc (loc, BIT_NOT_EXPR, type, fold_convert_loc (loc, type, Index: gcc/match.pd =================================================================== *** gcc/match.pd (revision 225115) --- gcc/match.pd (working copy) *************** (define_operator_list swapped_tcc_compar *** 378,389 **** --- 378,409 ---- (bit_and @0 @1)) (simplify + (abs (abs@1 @0)) + @1) + (simplify (abs (negate @0)) (abs @0)) (simplify (abs tree_expr_nonnegative_p@0) @0) + /* A - B -> A + (-B) if B is easily negatable. This just covers + very few cases of "easily negatable", effectively inlining negate_expr_p. */ + (simplify + (minus @0 INTEGER_CST@1) + (if (!TYPE_OVERFLOW_SANITIZED (type) + && (TYPE_OVERFLOW_WRAPS (type) + || may_negate_without_overflow_p (@1))) + (plus @0 (negate @1)))) + (simplify + (minus @0 REAL_CST@1) + (if (REAL_VALUE_NEGATIVE (TREE_REAL_CST (@1))) + (plus @0 (negate @1)))) + (simplify + (minus @0 VECTOR_CST@1) + (if (FLOAT_TYPE_P (type) || TYPE_OVERFLOW_WRAPS (type)) + (plus @0 (negate @1)))) + /* Try to fold (type) X op CST -> (type) (X op ((type-x) CST)) when profitable. *************** (define_operator_list swapped_tcc_compar *** 415,420 **** --- 435,453 ---- || TYPE_PRECISION (type) != GET_MODE_PRECISION (TYPE_MODE (type)))) (convert (bitop @0 (convert @1)))))) + (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))) + /* Simplify (A & B) OP0 (C & B) to (A OP0 C) & B. */ (for bitop (bit_and bit_ior bit_xor) (simplify *************** (define_operator_list swapped_tcc_compar *** 462,480 **** (op:c truth_valued_p@0 (logical_inverted_value @0)) { constant_boolean_node (true, type); })) - (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: --- 495,500 ---- *************** (define_operator_list swapped_tcc_compar *** 503,508 **** --- 523,554 ---- (bit_not (bit_not @0)) @0) + /* Convert ~ (-A) to A - 1. */ + (simplify + (bit_not (convert? (negate @0))) + (if (tree_nop_conversion_p (type, TREE_TYPE (@0))) + (convert (minus @0 { build_one_cst (TREE_TYPE (@0)); })))) + + /* Convert ~ (A - 1) or ~ (A + -1) to -A. */ + (simplify + (bit_not (convert? (minus @0 integer_onep))) + (if (tree_nop_conversion_p (type, TREE_TYPE (@0))) + (convert (negate @0)))) + (simplify + (bit_not (convert? (plus @0 integer_all_onesp))) + (if (tree_nop_conversion_p (type, TREE_TYPE (@0))) + (convert (negate @0)))) + + /* Part of convert ~(X ^ Y) to ~X ^ Y or X ^ ~Y if ~X or ~Y simplify. */ + (simplify + (bit_not (convert? (bit_xor @0 INTEGER_CST@1))) + (if (tree_nop_conversion_p (type, TREE_TYPE (@0))) + (convert (bit_xor @0 (bit_not @1))))) + (simplify + (bit_not (convert? (bit_xor:c (bit_not @0) @1))) + (if (tree_nop_conversion_p (type, TREE_TYPE (@0))) + (convert (bit_xor @0 @1)))) + /* (x & ~m) | (y & m) -> ((x ^ y) & m) ^ x */ (simplify (bit_ior:c (bit_and:c@3 @0 (bit_not @2)) (bit_and:c@4 @1 @2))