diff options
-rw-r--r-- | gcc/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/fold-const.c | 117 | ||||
-rw-r--r-- | gcc/match.pd | 67 |
3 files changed, 73 insertions, 117 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6f8ae02..d7f6ca5 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,11 @@ 2015-07-24 Richard Biener <rguenther@suse.de> + * fold-const.c (fold_binary_loc): Move simplifying of comparisons + against the highest or lowest possible integer ... + * match.pd: ... as patterns here. + +2015-07-24 Richard Biener <rguenther@suse.de> + * genmatch.c (struct capture_info): Add same_as field. (capture_info::capture_info): Initialize same_as. (capture_info::walk_match): Compute same_as. diff --git a/gcc/fold-const.c b/gcc/fold-const.c index c404857..739a3a9 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -11617,123 +11617,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. diff --git a/gcc/match.pd b/gcc/match.pd index 398378d..3d53abf 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -1824,6 +1824,73 @@ along with GCC; see the file COPYING3. If not see { 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) |