The following patch adds more comparison patterns (with comments on what is missing still).
Bootstrapped on x86_64-unknown-linux-gnu, testing in progress. Richard. 2014-09-02 Richard Biener <rguent...@suse.de> * fold-const.h (negate_expr_p): Declare. * fold-const.c (negate_expr_p): Export. * match-comparison.pd: Implement more comparison patterns. Index: gcc/match-comparison.pd =================================================================== *** gcc/match-comparison.pd.orig 2014-09-02 11:10:06.855348847 +0200 --- gcc/match-comparison.pd 2014-09-02 13:30:52.392767381 +0200 *************** *** 1,3 **** --- 1,62 ---- + /* From fold_binary. */ + + (simplify + (ne @0 integer_zerop@1) + (if (TREE_CODE (TREE_TYPE (@0)) == BOOLEAN_TYPE) + /* ??? In GENERIC the type of the comparison may be 'int'. */ + (convert @0))) + + /* Distribute operations in equality compares. */ + (for op in eq ne + /* -exp op CST is exp op -CST. */ + (simplify + (op (negate @0) INTEGER_CST@1) + /* ??? fix fold-const to use negate_expr_p */ + (if (negate_expr_p (@1)) + (op @0 (negate @1)))) + /* X ^ C1 == C2 is X == (C1 ^ C2). */ + (simplify + (op (bit_xor @0 INTEGER_CST@1) INTEGER_CST@2) + (op @0 (bit_xor @1 @2)))) + + /* From fold_comparison, in the order of transforms in there. */ + + /* Transform comparisons of the form X +- C1 CMP C2 to X CMP C2 -+ C1. */ + (for cmp in lt le eq ge gt ne + (for op in plus minus + (simplify + (cmp (op @0 INTEGER_CST@1) INTEGER_CST@2) + (if ((cmp == NE_EXPR || cmp == EQ_EXPR + || TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0))) + && (@3 = int_const_binop (op == MINUS_EXPR ? PLUS_EXPR : MINUS_EXPR, @2, @1)) + /* ??? fold_comparison here does, when @1 and @2 didn't have + TREE_OVERFLOW set, simplify the comparison to true/false + by using a staturated add. */ + && !TREE_OVERFLOW (@3)) + (cmp @0 @3))))) + + /* Transform comparisons of the form X - Y CMP 0 to X CMP Y. */ + /* ??? The transformation is valid for the other operators if overflow + is undefined for the type, but performing it here badly interacts + with the transformation in fold_cond_expr_with_comparison which + attempts to synthetize ABS_EXPR. */ + (for cmp in eq ne + (simplify + (cmp (minus @0 @1) integer_zerop) + (cmp @0 @1))) + + /* For comparisons of pointers we can decompose it to a compile time + comparison of the base objects and the offsets into the object. + This requires at least one operand being an ADDR_EXPR or a + POINTER_PLUS_EXPR to do more than the operand_equal_p test below. */ + #if 0 + (for cmp in lt le eq ge gt ne + (for op in addr pointer_plus + (simplify + (cmp:c (op@0 @1 @2) @3) + (if (simplify_addr_comparison (@0, @3, @@)))))) + #endif + /* Simplify X * C1 CMP 0 to X CMP 0 if C1 is not zero. */ (for op in lt le eq ne ge gt (simplify *************** *** 13,15 **** --- 72,141 ---- (if (tree_int_cst_sgn (@1) < 0) (op @2 @0))))) + #if 0 + /* If this is comparing a constant with a MIN_EXPR or a MAX_EXPR of a + constant, we can simplify it. */ + (for op in min max + (for cmp in eq gt + (cmp (op @0 INTEGER_CST@1) INTEGER_CST@2) + (if (op == MAX_EXPR && tree_int_cst_compare (@1, @2) == 0) + (le @0 @2)) + (if ( + ) + /* ??? optimize_minmax_comparison handles ne, lt and le by + recursing with an inverted comparison and then inverting + the result. Or combining equality and gt with truth_or. */) + #endif + + /* Simplify comparison of something with itself. For IEEE + floating-point, we can only do some of these simplifications. */ + (for cmp in ge le + (simplify + (cmp @0 @0) + (eq @0 @0))) + (simplify + (eq @0 @0) + (if (! FLOAT_TYPE_P (TREE_TYPE (@0)) + || ! HONOR_NANS (TYPE_MODE (TREE_TYPE (@0)))) + { constant_boolean_node (true, type); })) + (for cmp in ne gt lt + (simplify + (cmp @0 @0) + (if (cmp != NE_EXPR + || ! FLOAT_TYPE_P (TREE_TYPE (@0)) + || ! HONOR_NANS (TYPE_MODE (TREE_TYPE (@0)))) + { constant_boolean_node (false, type); }))) + + /* Need to split up the cases in twoval_comparison_p. */ + + #if 0 + /* We can fold X/C1 op C2 where C1 and C2 are integer constants + into a single range test. */ + (for cmp in lt le eq ge gt ne + (for div in trunc_div exact_div + (simplify + (cmp (div @0 INTEGER_CST@1) INTEGER_CST) + (if (!integer_zerop (@1)) + /* ??? Need to think about what fold_div_compare does. IMHO + we can unconditionally build a + (unsigned)@0 +- CST <= CST' + range check. */ + )))) + #endif + + /* Fold ~X op ~Y as Y op X. */ + (for cmp in lt le eq ge gt ne + (simplify + (cmp (bit_not @0) (bit_not @1)) + (cmp @1 @0))) + + /* Fold ~X op C as X op' ~C, where op' is the swapped comparison. */ + (for cmp in lt le eq ge gt ne + (simplify + (cmp (bit_not @0) @1) + /* ??? (for cst in INTEGER_CST VECTOR_CST) is not supported yet. */ + (if ((TREE_CODE (@1) == INTEGER_CST || TREE_CODE (@1) == VECTOR_CST)) + /* fold_comparison uses swapped 'cmp' to canonicalize the result + (constants second operand), swapping 'cmp' isn't available so we + cheat here and leave canonicalization to re-simplifying. */ + (cmp (bit_not @1) @0)))) Index: gcc/fold-const.c =================================================================== *** gcc/fold-const.c.orig 2014-09-02 11:10:06.855348847 +0200 --- gcc/fold-const.c 2014-09-02 13:24:21.284794309 +0200 *************** enum comparison_code { *** 98,104 **** }; static bool negate_mathfn_p (enum built_in_function); - static bool negate_expr_p (tree); static tree negate_expr (tree); static tree split_tree (tree, enum tree_code, tree *, tree *, tree *, int); static tree associate_trees (location_t, tree, tree, enum tree_code, tree); --- 98,103 ---- *************** may_negate_without_overflow_p (const_tre *** 373,379 **** /* Determine whether an expression T can be cheaply negated using the function negate_expr without introducing undefined overflow. */ ! static bool negate_expr_p (tree t) { tree type; --- 372,378 ---- /* Determine whether an expression T can be cheaply negated using the function negate_expr without introducing undefined overflow. */ ! bool negate_expr_p (tree t) { tree type; Index: gcc/fold-const.h =================================================================== *** gcc/fold-const.h.orig 2014-09-02 11:10:06.855348847 +0200 --- gcc/fold-const.h 2014-09-02 13:24:21.285794309 +0200 *************** extern tree make_range_step (location_t, *** 167,171 **** --- 167,172 ---- extern tree build_range_check (location_t, tree, tree, int, tree, tree); extern bool merge_ranges (int *, tree *, tree *, int, tree, tree, int, tree, tree); + extern bool negate_expr_p (tree); #endif // GCC_FOLD_CONST_H