This moves simplifying of comparisons against the highest or lowest possible integer.
Bootstrapped on x86_64-unknown-linux-gnu, testing in progress. This needs the GENERIC code-gen fix, otherwise we miscompile GCC. Richard. 2015-07-24 Richard Biener <rguent...@suse.de> * fold-const.c (fold_binary_loc): Move simplifying of comparisons against the highest or lowest possible integer ... * match.pd: ... as patterns here. Index: gcc/fold-const.c =================================================================== --- gcc/fold-const.c (revision 226140) +++ gcc/fold-const.c (working copy) @@ -11651,123 +11463,6 @@ fold_binary_loc (location_t loc, } } - /* Comparisons with the highest or lowest possible integer of - the specified precision will have known values. */ - { - tree arg1_type = TREE_TYPE (arg1); - unsigned int prec = TYPE_PRECISION (arg1_type); - - if (TREE_CODE (arg1) == INTEGER_CST - && (INTEGRAL_TYPE_P (arg1_type) || POINTER_TYPE_P (arg1_type))) - { - wide_int max = wi::max_value (arg1_type); - wide_int signed_max = wi::max_value (prec, SIGNED); - wide_int min = wi::min_value (arg1_type); - - if (wi::eq_p (arg1, max)) - switch (code) - { - case GT_EXPR: - return omit_one_operand_loc (loc, type, integer_zero_node, arg0); - - case GE_EXPR: - return fold_build2_loc (loc, EQ_EXPR, type, op0, op1); - - case LE_EXPR: - return omit_one_operand_loc (loc, type, integer_one_node, arg0); - - case LT_EXPR: - return fold_build2_loc (loc, NE_EXPR, type, op0, op1); - - /* The GE_EXPR and LT_EXPR cases above are not normally - reached because of previous transformations. */ - - default: - break; - } - else if (wi::eq_p (arg1, max - 1)) - switch (code) - { - case GT_EXPR: - arg1 = const_binop (PLUS_EXPR, arg1, - build_int_cst (TREE_TYPE (arg1), 1)); - return fold_build2_loc (loc, EQ_EXPR, type, - fold_convert_loc (loc, - TREE_TYPE (arg1), arg0), - arg1); - case LE_EXPR: - arg1 = const_binop (PLUS_EXPR, arg1, - build_int_cst (TREE_TYPE (arg1), 1)); - return fold_build2_loc (loc, NE_EXPR, type, - fold_convert_loc (loc, TREE_TYPE (arg1), - arg0), - arg1); - default: - break; - } - else if (wi::eq_p (arg1, min)) - switch (code) - { - case LT_EXPR: - return omit_one_operand_loc (loc, type, integer_zero_node, arg0); - - case LE_EXPR: - return fold_build2_loc (loc, EQ_EXPR, type, op0, op1); - - case GE_EXPR: - return omit_one_operand_loc (loc, type, integer_one_node, arg0); - - case GT_EXPR: - return fold_build2_loc (loc, NE_EXPR, type, op0, op1); - - default: - break; - } - else if (wi::eq_p (arg1, min + 1)) - switch (code) - { - case GE_EXPR: - arg1 = const_binop (MINUS_EXPR, arg1, - build_int_cst (TREE_TYPE (arg1), 1)); - return fold_build2_loc (loc, NE_EXPR, type, - fold_convert_loc (loc, - TREE_TYPE (arg1), arg0), - arg1); - case LT_EXPR: - arg1 = const_binop (MINUS_EXPR, arg1, - build_int_cst (TREE_TYPE (arg1), 1)); - return fold_build2_loc (loc, EQ_EXPR, type, - fold_convert_loc (loc, TREE_TYPE (arg1), - arg0), - arg1); - default: - break; - } - - else if (wi::eq_p (arg1, signed_max) - && TYPE_UNSIGNED (arg1_type) - /* We will flip the signedness of the comparison operator - associated with the mode of arg1, so the sign bit is - specified by this mode. Check that arg1 is the signed - max associated with this sign bit. */ - && prec == GET_MODE_PRECISION (TYPE_MODE (arg1_type)) - /* signed_type does not work on pointer types. */ - && INTEGRAL_TYPE_P (arg1_type)) - { - /* The following case also applies to X < signed_max+1 - and X >= signed_max+1 because previous transformations. */ - if (code == LE_EXPR || code == GT_EXPR) - { - tree st = signed_type_for (arg1_type); - return fold_build2_loc (loc, - code == LE_EXPR ? GE_EXPR : LT_EXPR, - type, fold_convert_loc (loc, st, arg0), - build_int_cst (st, 0)); - } - } - } - } - /* If we are comparing an ABS_EXPR with a constant, we can convert all the cases into explicit comparisons, but they may well not be faster than doing the ABS and one comparison. Index: gcc/match.pd =================================================================== --- gcc/match.pd (revision 226140) +++ gcc/match.pd (working copy) @@ -1807,6 +1864,73 @@ (define_operator_list CBRT BUILT_IN_CBRT { constant_boolean_node (cmp == NE_EXPR, type); }))) +/* Non-equality compare simplifications from fold_binary */ +(for cmp (lt gt le ge) + /* Comparisons with the highest or lowest possible integer of + the specified precision will have known values. */ + (simplify + (cmp (convert?@2 @0) INTEGER_CST@1) + (if ((INTEGRAL_TYPE_P (TREE_TYPE (@1)) || POINTER_TYPE_P (TREE_TYPE (@1))) + && tree_nop_conversion_p (TREE_TYPE (@2), TREE_TYPE (@0))) + (with + { + tree arg1_type = TREE_TYPE (@1); + unsigned int prec = TYPE_PRECISION (arg1_type); + wide_int max = wi::max_value (arg1_type); + wide_int signed_max = wi::max_value (prec, SIGNED); + wide_int min = wi::min_value (arg1_type); + } + (switch + (if (wi::eq_p (@1, max)) + (switch + (if (cmp == GT_EXPR) + { constant_boolean_node (false, type); }) + (if (cmp == GE_EXPR) + (eq @2 @1)) + (if (cmp == LE_EXPR) + { constant_boolean_node (true, type); }) + (if (cmp == LT_EXPR) + (ne @2 @1)))) + (if (wi::eq_p (@1, max - 1)) + (switch + (if (cmp == GT_EXPR) + (eq @2 { wide_int_to_tree (TREE_TYPE (@1), wi::add (@1, 1)); })) + (if (cmp == LE_EXPR) + (ne @2 { wide_int_to_tree (TREE_TYPE (@1), wi::add (@1, 1)); })))) + (if (wi::eq_p (@1, min)) + (switch + (if (cmp == LT_EXPR) + { constant_boolean_node (false, type); }) + (if (cmp == LE_EXPR) + (eq @2 @1)) + (if (cmp == GE_EXPR) + { constant_boolean_node (true, type); }) + (if (cmp == GT_EXPR) + (ne @2 @1)))) + (if (wi::eq_p (@1, min + 1)) + (switch + (if (cmp == GE_EXPR) + (ne @2 { wide_int_to_tree (TREE_TYPE (@1), wi::sub (@1, 1)); })) + (if (cmp == LT_EXPR) + (eq @2 { wide_int_to_tree (TREE_TYPE (@1), wi::sub (@1, 1)); })))) + (if (wi::eq_p (@1, signed_max) + && TYPE_UNSIGNED (arg1_type) + /* We will flip the signedness of the comparison operator + associated with the mode of @1, so the sign bit is + specified by this mode. Check that @1 is the signed + max associated with this sign bit. */ + && prec == GET_MODE_PRECISION (TYPE_MODE (arg1_type)) + /* signed_type does not work on pointer types. */ + && INTEGRAL_TYPE_P (arg1_type)) + /* The following case also applies to X < signed_max+1 + and X >= signed_max+1 because previous transformations. */ + (if (cmp == LE_EXPR || cmp == GT_EXPR) + (with { tree st = signed_type_for (arg1_type); } + (if (cmp == LE_EXPR) + (ge (convert:st @0) { build_zero_cst (st); }) + (lt (convert:st @0) { build_zero_cst (st); })))))))))) + + /* bool_var != 0 becomes bool_var. */ (simplify (ne @0 integer_zerop@1)