From a8b85ce9e2bffc9fcacaf0cfbbb803b01f7598e8 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Mon, 2 May 2016 16:09:07 +0200 Subject: [PATCH] Move "X +- C1 CMP C2 to X CMP C2 -+ C1" to match.pd 2016-05-02 Marc Glisse gcc/ * flag-types.h (enum warn_strict_overflow_code): Move ... * coretypes.h: ... here. * fold-const.h (fold_overflow_warning): Declare. * fold-const.c (fold_overflow_warning): Make non-static. (fold_comparison): Move the transformation of X +- C1 CMP C2 into X CMP C2 -+ C1 ... * match.pd: ... here. * gimple-fold.c (fold_stmt_1): Protect with fold_defer_overflow_warnings. gcc/testsuite/ * gcc.dg/tree-ssa/20040305-1.c: Adjust. From-SVN: r235760 --- gcc/ChangeLog | 12 ++++ gcc/coretypes.h | 24 ++++++++ gcc/flag-types.h | 24 -------- gcc/fold-const.c | 71 +--------------------- gcc/fold-const.h | 1 + gcc/gimple-fold.c | 3 + gcc/match.pd | 44 ++++++++++++++ gcc/testsuite/ChangeLog | 4 ++ gcc/testsuite/gcc.dg/tree-ssa/20040305-1.c | 2 +- 9 files changed, 90 insertions(+), 95 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ff0b573b0c9..10bf855f351 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2016-05-02 Marc Glisse + + * flag-types.h (enum warn_strict_overflow_code): Move ... + * coretypes.h: ... here. + * fold-const.h (fold_overflow_warning): Declare. + * fold-const.c (fold_overflow_warning): Make non-static. + (fold_comparison): Move the transformation of X +- C1 CMP C2 + into X CMP C2 -+ C1 ... + * match.pd: ... here. + * gimple-fold.c (fold_stmt_1): Protect with + fold_defer_overflow_warnings. + 2016-05-02 Nathan Sidwell * omp-low.c (struct oacc_loop): Add 'inner' field. diff --git a/gcc/coretypes.h b/gcc/coretypes.h index 12067fdf534..2932d73e261 100644 --- a/gcc/coretypes.h +++ b/gcc/coretypes.h @@ -222,6 +222,30 @@ enum var_init_status VAR_INIT_STATUS_INITIALIZED }; +/* Names for the different levels of -Wstrict-overflow=N. The numeric + values here correspond to N. */ +enum warn_strict_overflow_code +{ + /* Overflow warning that should be issued with -Wall: a questionable + construct that is easy to avoid even when using macros. Example: + folding (x + CONSTANT > x) to 1. */ + WARN_STRICT_OVERFLOW_ALL = 1, + /* Overflow warning about folding a comparison to a constant because + of undefined signed overflow, other than cases covered by + WARN_STRICT_OVERFLOW_ALL. Example: folding (abs (x) >= 0) to 1 + (this is false when x == INT_MIN). */ + WARN_STRICT_OVERFLOW_CONDITIONAL = 2, + /* Overflow warning about changes to comparisons other than folding + them to a constant. Example: folding (x + 1 > 1) to (x > 0). */ + WARN_STRICT_OVERFLOW_COMPARISON = 3, + /* Overflow warnings not covered by the above cases. Example: + folding ((x * 10) / 5) to (x * 2). */ + WARN_STRICT_OVERFLOW_MISC = 4, + /* Overflow warnings about reducing magnitude of constants in + comparison. Example: folding (x + 2 > y) to (x + 1 >= y). */ + WARN_STRICT_OVERFLOW_MAGNITUDE = 5 +}; + /* The type of an alias set. Code currently assumes that variables of this type can take the values 0 (the alias set which aliases everything) and -1 (sometimes indicating that the alias set is diff --git a/gcc/flag-types.h b/gcc/flag-types.h index 82016763621..dd57e167098 100644 --- a/gcc/flag-types.h +++ b/gcc/flag-types.h @@ -178,30 +178,6 @@ enum stack_check_type FULL_BUILTIN_STACK_CHECK }; -/* Names for the different levels of -Wstrict-overflow=N. The numeric - values here correspond to N. */ -enum warn_strict_overflow_code -{ - /* Overflow warning that should be issued with -Wall: a questionable - construct that is easy to avoid even when using macros. Example: - folding (x + CONSTANT > x) to 1. */ - WARN_STRICT_OVERFLOW_ALL = 1, - /* Overflow warning about folding a comparison to a constant because - of undefined signed overflow, other than cases covered by - WARN_STRICT_OVERFLOW_ALL. Example: folding (abs (x) >= 0) to 1 - (this is false when x == INT_MIN). */ - WARN_STRICT_OVERFLOW_CONDITIONAL = 2, - /* Overflow warning about changes to comparisons other than folding - them to a constant. Example: folding (x + 1 > 1) to (x > 0). */ - WARN_STRICT_OVERFLOW_COMPARISON = 3, - /* Overflow warnings not covered by the above cases. Example: - folding ((x * 10) / 5) to (x * 2). */ - WARN_STRICT_OVERFLOW_MISC = 4, - /* Overflow warnings about reducing magnitude of constants in - comparison. Example: folding (x + 2 > y) to (x + 1 >= y). */ - WARN_STRICT_OVERFLOW_MAGNITUDE = 5 -}; - /* Floating-point contraction mode. */ enum fp_contract_mode { FP_CONTRACT_OFF = 0, diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 3c389ee446e..0004f789d53 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -297,7 +297,7 @@ fold_deferring_overflow_warnings_p (void) /* This is called when we fold something based on the fact that signed overflow is undefined. */ -static void +void fold_overflow_warning (const char* gmsgid, enum warn_strict_overflow_code wc) { if (fold_deferring_overflow_warnings > 0) @@ -8392,75 +8392,6 @@ fold_comparison (location_t loc, enum tree_code code, tree type, STRIP_SIGN_NOPS (arg0); STRIP_SIGN_NOPS (arg1); - /* Transform comparisons of the form X +- C1 CMP C2 to X CMP C2 -+ C1. */ - if ((TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MINUS_EXPR) - && (equality_code - || (ANY_INTEGRAL_TYPE_P (TREE_TYPE (arg0)) - && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg0)))) - && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST - && !TREE_OVERFLOW (TREE_OPERAND (arg0, 1)) - && TREE_CODE (arg1) == INTEGER_CST - && !TREE_OVERFLOW (arg1)) - { - const enum tree_code - reverse_op = TREE_CODE (arg0) == PLUS_EXPR ? MINUS_EXPR : PLUS_EXPR; - tree const1 = TREE_OPERAND (arg0, 1); - tree const2 = fold_convert_loc (loc, TREE_TYPE (const1), arg1); - tree variable = TREE_OPERAND (arg0, 0); - tree new_const = int_const_binop (reverse_op, const2, const1); - - /* If the constant operation overflowed this can be - simplified as a comparison against INT_MAX/INT_MIN. */ - if (TREE_OVERFLOW (new_const) - && !TYPE_OVERFLOW_WRAPS (TREE_TYPE (arg0))) - { - int const1_sgn = tree_int_cst_sgn (const1); - enum tree_code code2 = code; - - /* Get the sign of the constant on the lhs if the - operation were VARIABLE + CONST1. */ - if (TREE_CODE (arg0) == MINUS_EXPR) - const1_sgn = -const1_sgn; - - /* The sign of the constant determines if we overflowed - INT_MAX (const1_sgn == -1) or INT_MIN (const1_sgn == 1). - Canonicalize to the INT_MIN overflow by swapping the comparison - if necessary. */ - if (const1_sgn == -1) - code2 = swap_tree_comparison (code); - - /* We now can look at the canonicalized case - VARIABLE + 1 CODE2 INT_MIN - and decide on the result. */ - switch (code2) - { - case EQ_EXPR: - case LT_EXPR: - case LE_EXPR: - return - omit_one_operand_loc (loc, type, boolean_false_node, variable); - - case NE_EXPR: - case GE_EXPR: - case GT_EXPR: - return - omit_one_operand_loc (loc, type, boolean_true_node, variable); - - default: - gcc_unreachable (); - } - } - else - { - if (!equality_code) - fold_overflow_warning ("assuming signed overflow does not occur " - "when changing X +- C1 cmp C2 to " - "X cmp C2 -+ C1", - WARN_STRICT_OVERFLOW_COMPARISON); - return fold_build2_loc (loc, code, type, variable, new_const); - } - } - /* 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 diff --git a/gcc/fold-const.h b/gcc/fold-const.h index 02f42709c4e..637e46b0d48 100644 --- a/gcc/fold-const.h +++ b/gcc/fold-const.h @@ -86,6 +86,7 @@ extern void fold_defer_overflow_warnings (void); extern void fold_undefer_overflow_warnings (bool, const gimple *, int); extern void fold_undefer_and_ignore_overflow_warnings (void); extern bool fold_deferring_overflow_warnings_p (void); +extern void fold_overflow_warning (const char*, enum warn_strict_overflow_code); extern int operand_equal_p (const_tree, const_tree, unsigned int); extern int multiple_of_p (tree, const_tree, const_tree); #define omit_one_operand(T1,T2,T3)\ diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c index 5607598210b..d5e859c9573 100644 --- a/gcc/gimple-fold.c +++ b/gcc/gimple-fold.c @@ -3525,7 +3525,9 @@ fold_stmt_1 (gimple_stmt_iterator *gsi, bool inplace, tree (*valueize) (tree)) { bool changed = false; gimple *stmt = gsi_stmt (*gsi); + bool nowarning = gimple_no_warning_p (stmt); unsigned i; + fold_defer_overflow_warnings (); /* First do required canonicalization of [TARGET_]MEM_REF addresses after propagation. @@ -3818,6 +3820,7 @@ fold_stmt_1 (gimple_stmt_iterator *gsi, bool inplace, tree (*valueize) (tree)) } } + fold_undefer_overflow_warnings (changed && !nowarning, stmt, 0); return changed; } diff --git a/gcc/match.pd b/gcc/match.pd index 608afa3e25e..f1b1f154125 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -3186,3 +3186,47 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (SIGNBIT @0) (if (!HONOR_SIGNED_ZEROS (@0)) (convert (lt @0 { build_real (TREE_TYPE (@0), dconst0); })))) + +/* Transform comparisons of the form X +- C1 CMP C2 to X CMP C2 -+ C1. */ +(for cmp (eq ne) + (for op (plus minus) + rop (minus plus) + (simplify + (cmp (op@3 @0 INTEGER_CST@1) INTEGER_CST@2) + (if (!TREE_OVERFLOW (@1) && !TREE_OVERFLOW (@2) + && !TYPE_OVERFLOW_SANITIZED (TREE_TYPE (@0)) + && !TYPE_OVERFLOW_TRAPS (TREE_TYPE (@0)) + && !TYPE_SATURATING (TREE_TYPE (@0))) + (with { tree res = int_const_binop (rop, @2, @1); } + (if (TREE_OVERFLOW (res)) + { constant_boolean_node (cmp == NE_EXPR, type); } + (if (single_use (@3)) + (cmp @0 { res; })))))))) +(for cmp (lt le gt ge) + (for op (plus minus) + rop (minus plus) + (simplify + (cmp (op@3 @0 INTEGER_CST@1) INTEGER_CST@2) + (if (!TREE_OVERFLOW (@1) && !TREE_OVERFLOW (@2) + && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0))) + (with { tree res = int_const_binop (rop, @2, @1); } + (if (TREE_OVERFLOW (res)) + { + fold_overflow_warning (("assuming signed overflow does not occur " + "when simplifying conditional to constant"), + WARN_STRICT_OVERFLOW_CONDITIONAL); + bool less = cmp == LE_EXPR || cmp == LT_EXPR; + /* wi::ges_p (@2, 0) should be sufficient for a signed type. */ + bool ovf_high = wi::lt_p (@1, 0, TYPE_SIGN (TREE_TYPE (@1))) + != (op == MINUS_EXPR); + constant_boolean_node (less == ovf_high, type); + } + (if (single_use (@3)) + (with + { + fold_overflow_warning (("assuming signed overflow does not occur " + "when changing X +- C1 cmp C2 to " + "X cmp C2 -+ C1"), + WARN_STRICT_OVERFLOW_COMPARISON); + } + (cmp @0 { res; }))))))))) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 27a5972024e..f4075843284 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2016-05-02 Marc Glisse + + * gcc.dg/tree-ssa/20040305-1.c: Adjust. + 2016-05-02 Nathan Sidwell * c-c++-common/goacc/loop-auto-1.c: Adjust expected warnings. diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20040305-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20040305-1.c index d00acba07e4..501e28cff54 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/20040305-1.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/20040305-1.c @@ -23,7 +23,7 @@ void foo(int edx, int eax) /* Verify that we did a forward propagation. */ -/* { dg-final { scan-tree-dump-times "Replaced" 1 "forwprop1"} } */ +/* { dg-final { scan-tree-dump-times "gimple_simplified" 1 "forwprop1"} } */ /* After cddce we should have two IF statements remaining as the other two tests can be threaded. */ -- 2.30.2