From 6358a676c3eb4c6df013ce8319bcf429cd14232b Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Wed, 11 Oct 2017 15:18:06 +0200 Subject: [PATCH] X+Y < X iff Y<0 moved to match.pd 2017-10-11 Marc Glisse gcc/ * fold-const.c (fold_binary_loc) [X +- Y CMP X]: Move ... * match.pd: ... here. ((T) X == (T) Y): Relax condition. gcc/testsuite/ * gcc.dg/Wstrict-overflow-7.c: Xfail. * gcc.dg/pragma-diag-3.c: Likewise. From-SVN: r253642 --- gcc/ChangeLog | 6 ++ gcc/fold-const.c | 140 ++---------------------------- gcc/match.pd | 45 +++++++++- gcc/testsuite/ChangeLog | 5 ++ gcc/testsuite/gcc.dg/Wstrict-overflow-7.c | 2 +- gcc/testsuite/gcc.dg/pragma-diag-3.c | 2 +- 6 files changed, 62 insertions(+), 138 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 0028fc9a38a..d30aa3adf2d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2017-10-11 Marc Glisse + + * fold-const.c (fold_binary_loc) [X +- Y CMP X]: Move ... + * match.pd: ... here. + ((T) X == (T) Y): Relax condition. + 2017-10-11 Bin Cheng PR tree-optimization/82472 diff --git a/gcc/fold-const.c b/gcc/fold-const.c index f2e1cea2038..e22b02f1312 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -10502,40 +10502,6 @@ fold_binary_loc (location_t loc, && code == NE_EXPR) return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg0)); - /* Transform comparisons of the form X +- Y CMP X to Y CMP 0. */ - if ((TREE_CODE (arg0) == PLUS_EXPR - || TREE_CODE (arg0) == POINTER_PLUS_EXPR - || TREE_CODE (arg0) == MINUS_EXPR) - && operand_equal_p (tree_strip_nop_conversions (TREE_OPERAND (arg0, - 0)), - arg1, 0) - && (INTEGRAL_TYPE_P (TREE_TYPE (arg0)) - || POINTER_TYPE_P (TREE_TYPE (arg0)))) - { - tree val = TREE_OPERAND (arg0, 1); - val = fold_build2_loc (loc, code, type, val, - build_int_cst (TREE_TYPE (val), 0)); - return omit_two_operands_loc (loc, type, val, - TREE_OPERAND (arg0, 0), arg1); - } - - /* Transform comparisons of the form X CMP X +- Y to Y CMP 0. */ - if ((TREE_CODE (arg1) == PLUS_EXPR - || TREE_CODE (arg1) == POINTER_PLUS_EXPR - || TREE_CODE (arg1) == MINUS_EXPR) - && operand_equal_p (tree_strip_nop_conversions (TREE_OPERAND (arg1, - 0)), - arg0, 0) - && (INTEGRAL_TYPE_P (TREE_TYPE (arg1)) - || POINTER_TYPE_P (TREE_TYPE (arg1)))) - { - tree val = TREE_OPERAND (arg1, 1); - val = fold_build2_loc (loc, code, type, val, - build_int_cst (TREE_TYPE (val), 0)); - return omit_two_operands_loc (loc, type, val, - TREE_OPERAND (arg1, 0), arg0); - } - /* If this is an EQ or NE comparison with zero and ARG0 is (1 << foo) & bar, convert it to (bar >> foo) & 1. Both require two operations, but the latter can be done in one less insn @@ -10918,130 +10884,38 @@ fold_binary_loc (location_t loc, /* Transform comparisons of the form X +- C CMP X. */ if ((TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MINUS_EXPR) && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0) - && ((TREE_CODE (TREE_OPERAND (arg0, 1)) == REAL_CST - && !HONOR_SNANS (arg0)) - || (TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST - && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg1))))) + && TREE_CODE (TREE_OPERAND (arg0, 1)) == REAL_CST + && !HONOR_SNANS (arg0)) { tree arg01 = TREE_OPERAND (arg0, 1); enum tree_code code0 = TREE_CODE (arg0); - int is_positive; - - if (TREE_CODE (arg01) == REAL_CST) - is_positive = REAL_VALUE_NEGATIVE (TREE_REAL_CST (arg01)) ? -1 : 1; - else - is_positive = tree_int_cst_sgn (arg01); + int is_positive = REAL_VALUE_NEGATIVE (TREE_REAL_CST (arg01)) ? -1 : 1; /* (X - c) > X becomes false. */ if (code == GT_EXPR && ((code0 == MINUS_EXPR && is_positive >= 0) || (code0 == PLUS_EXPR && is_positive <= 0))) - { - if (TREE_CODE (arg01) == INTEGER_CST - && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg1))) - fold_overflow_warning (("assuming signed overflow does not " - "occur when assuming that (X - c) > X " - "is always false"), - WARN_STRICT_OVERFLOW_ALL); - return constant_boolean_node (0, type); - } + return constant_boolean_node (0, type); /* Likewise (X + c) < X becomes false. */ if (code == LT_EXPR && ((code0 == PLUS_EXPR && is_positive >= 0) || (code0 == MINUS_EXPR && is_positive <= 0))) - { - if (TREE_CODE (arg01) == INTEGER_CST - && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg1))) - fold_overflow_warning (("assuming signed overflow does not " - "occur when assuming that " - "(X + c) < X is always false"), - WARN_STRICT_OVERFLOW_ALL); - return constant_boolean_node (0, type); - } + return constant_boolean_node (0, type); /* Convert (X - c) <= X to true. */ if (!HONOR_NANS (arg1) && code == LE_EXPR && ((code0 == MINUS_EXPR && is_positive >= 0) || (code0 == PLUS_EXPR && is_positive <= 0))) - { - if (TREE_CODE (arg01) == INTEGER_CST - && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg1))) - fold_overflow_warning (("assuming signed overflow does not " - "occur when assuming that " - "(X - c) <= X is always true"), - WARN_STRICT_OVERFLOW_ALL); - return constant_boolean_node (1, type); - } + return constant_boolean_node (1, type); /* Convert (X + c) >= X to true. */ if (!HONOR_NANS (arg1) && code == GE_EXPR && ((code0 == PLUS_EXPR && is_positive >= 0) || (code0 == MINUS_EXPR && is_positive <= 0))) - { - if (TREE_CODE (arg01) == INTEGER_CST - && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg1))) - fold_overflow_warning (("assuming signed overflow does not " - "occur when assuming that " - "(X + c) >= X is always true"), - WARN_STRICT_OVERFLOW_ALL); - return constant_boolean_node (1, type); - } - - if (TREE_CODE (arg01) == INTEGER_CST) - { - /* Convert X + c > X and X - c < X to true for integers. */ - if (code == GT_EXPR - && ((code0 == PLUS_EXPR && is_positive > 0) - || (code0 == MINUS_EXPR && is_positive < 0))) - { - if (TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg1))) - fold_overflow_warning (("assuming signed overflow does " - "not occur when assuming that " - "(X + c) > X is always true"), - WARN_STRICT_OVERFLOW_ALL); - return constant_boolean_node (1, type); - } - - if (code == LT_EXPR - && ((code0 == MINUS_EXPR && is_positive > 0) - || (code0 == PLUS_EXPR && is_positive < 0))) - { - if (TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg1))) - fold_overflow_warning (("assuming signed overflow does " - "not occur when assuming that " - "(X - c) < X is always true"), - WARN_STRICT_OVERFLOW_ALL); - return constant_boolean_node (1, type); - } - - /* Convert X + c <= X and X - c >= X to false for integers. */ - if (code == LE_EXPR - && ((code0 == PLUS_EXPR && is_positive > 0) - || (code0 == MINUS_EXPR && is_positive < 0))) - { - if (TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg1))) - fold_overflow_warning (("assuming signed overflow does " - "not occur when assuming that " - "(X + c) <= X is always false"), - WARN_STRICT_OVERFLOW_ALL); - return constant_boolean_node (0, type); - } - - if (code == GE_EXPR - && ((code0 == MINUS_EXPR && is_positive > 0) - || (code0 == PLUS_EXPR && is_positive < 0))) - { - if (TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg1))) - fold_overflow_warning (("assuming signed overflow does " - "not occur when assuming that " - "(X - c) >= X is always false"), - WARN_STRICT_OVERFLOW_ALL); - return constant_boolean_node (0, type); - } - } + return constant_boolean_node (1, type); } /* If we are comparing an ABS_EXPR with a constant, we can diff --git a/gcc/match.pd b/gcc/match.pd index 2f8a7411d76..f2c43737b80 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -1280,6 +1280,44 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) || TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0)))) (op @1 @0)))) +/* X + Y < Y is the same as X < 0 when there is no overflow. */ +(for op (lt le gt ge) + (simplify + (op:c (plus:c@2 @0 @1) @1) + (if (ANY_INTEGRAL_TYPE_P (TREE_TYPE (@0)) + && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0)) + && (CONSTANT_CLASS_P (@0) || single_use (@2))) + (op @0 { build_zero_cst (TREE_TYPE (@0)); })))) +/* For equality, this is also true with wrapping overflow. */ +(for op (eq ne) + (simplify + (op:c (nop_convert@3 (plus:c@2 @0 (convert1? @1))) (convert2? @1)) + (if (ANY_INTEGRAL_TYPE_P (TREE_TYPE (@0)) + && (TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0)) + || TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0))) + && (CONSTANT_CLASS_P (@0) || (single_use (@2) && single_use (@3))) + && tree_nop_conversion_p (TREE_TYPE (@3), TREE_TYPE (@2)) + && tree_nop_conversion_p (TREE_TYPE (@3), TREE_TYPE (@1))) + (op @0 { build_zero_cst (TREE_TYPE (@0)); }))) + (simplify + (op:c (nop_convert@3 (pointer_plus@2 (convert1? @0) @1)) (convert2? @0)) + (if (tree_nop_conversion_p (TREE_TYPE (@2), TREE_TYPE (@0)) + && tree_nop_conversion_p (TREE_TYPE (@3), TREE_TYPE (@0)) + && (CONSTANT_CLASS_P (@1) || (single_use (@2) && single_use (@3)))) + (op @1 { build_zero_cst (TREE_TYPE (@1)); })))) + +/* X - Y < X is the same as Y > 0 when there is no overflow. + For equality, this is also true with wrapping overflow. */ +(for op (simple_comparison) + (simplify + (op:c @0 (minus@2 @0 @1)) + (if (ANY_INTEGRAL_TYPE_P (TREE_TYPE (@0)) + && (TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0)) + || ((op == EQ_EXPR || op == NE_EXPR) + && TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0)))) + && (CONSTANT_CLASS_P (@1) || single_use (@2))) + (op @1 { build_zero_cst (TREE_TYPE (@1)); })))) + /* Transform: * (X / Y) == 0 -> X < Y if X, Y are unsigned. * (X / Y) != 0 -> X >= Y, if X, Y are unsigned. @@ -3125,7 +3163,8 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (op (abs @0) zerop@1) (op @0 @1))) -/* From fold_sign_changed_comparison and fold_widened_comparison. */ +/* From fold_sign_changed_comparison and fold_widened_comparison. + FIXME: the lack of symmetry is disturbing. */ (for cmp (simple_comparison) (simplify (cmp (convert@0 @00) (convert?@1 @10)) @@ -3138,11 +3177,11 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) && single_use (@0)) (if (TYPE_PRECISION (TREE_TYPE (@00)) == TYPE_PRECISION (TREE_TYPE (@0)) && (TREE_CODE (@10) == INTEGER_CST - || (@1 != @10 && types_match (TREE_TYPE (@10), TREE_TYPE (@00)))) + || @1 != @10) && (TYPE_UNSIGNED (TREE_TYPE (@00)) == TYPE_UNSIGNED (TREE_TYPE (@0)) || cmp == NE_EXPR || cmp == EQ_EXPR) - && (POINTER_TYPE_P (TREE_TYPE (@00)) == POINTER_TYPE_P (TREE_TYPE (@0)))) + && !POINTER_TYPE_P (TREE_TYPE (@00))) /* ??? The special-casing of INTEGER_CST conversion was in the original code and here to avoid a spurious overflow flag on the resulting constant which fold_convert produces. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 23fccba5a67..20f7b0f132c 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2017-10-11 Marc Glisse + + * gcc.dg/Wstrict-overflow-7.c: Xfail. + * gcc.dg/pragma-diag-3.c: Likewise. + 2017-10-11 Bin Cheng PR tree-optimization/82472 diff --git a/gcc/testsuite/gcc.dg/Wstrict-overflow-7.c b/gcc/testsuite/gcc.dg/Wstrict-overflow-7.c index 5bf7b6005ca..401cbc3c987 100644 --- a/gcc/testsuite/gcc.dg/Wstrict-overflow-7.c +++ b/gcc/testsuite/gcc.dg/Wstrict-overflow-7.c @@ -6,5 +6,5 @@ int foo (int i) { - return i + 10 > i; /* { dg-warning "assuming signed overflow does not occur" "correct warning" } */ + return i + 10 > i; /* { dg-warning "assuming signed overflow does not occur" "correct warning" { xfail *-*-* } } */ } diff --git a/gcc/testsuite/gcc.dg/pragma-diag-3.c b/gcc/testsuite/gcc.dg/pragma-diag-3.c index 2ee439d7e33..b6ee60f1677 100644 --- a/gcc/testsuite/gcc.dg/pragma-diag-3.c +++ b/gcc/testsuite/gcc.dg/pragma-diag-3.c @@ -15,7 +15,7 @@ void testing2() { void testing3() { int k = 4; - k + 4 < k; /* { dg-error "overflow" } */ + k + 4 < k; /* { dg-error "overflow" "" { xfail *-*-* } } */ } int bar() -- 2.11.4.GIT