Message ID | alpine.DEB.2.02.1604291925110.19034@laptop-mg.saclay.inria.fr |
---|---|
State | New |
Headers | show |
On Fri, Apr 29, 2016 at 7:36 PM, Marc Glisse <marc.glisse@inria.fr> wrote: > On Fri, 29 Apr 2016, Richard Biener wrote: > >> Another option is to move the enum declaration from flag-types.h to >> coretypes.h. I think I like that best. > > > This works. Ok. Thanks, Richard. > 2016-05-02 Marc Glisse <marc.glisse@inria.fr> > > 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. > > -- > Marc Glisse > > Index: gcc/coretypes.h > =================================================================== > --- gcc/coretypes.h (revision 235644) > +++ gcc/coretypes.h (working copy) > @@ -215,20 +215,44 @@ enum optimization_type { > /* Possible initialization status of a variable. When requested > by the user, this information is tracked and recorded in the DWARF > debug information, along with the variable's location. */ > enum var_init_status > { > VAR_INIT_STATUS_UNKNOWN, > VAR_INIT_STATUS_UNINITIALIZED, > 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 > unknown, sometimes indicating a memory barrier) and -2 (indicating > that the alias set should be set to a unique value but has not been > set yet). */ > typedef int alias_set_type; > > struct edge_def; > typedef struct edge_def *edge; > Index: gcc/flag-types.h > =================================================================== > --- gcc/flag-types.h (revision 235644) > +++ gcc/flag-types.h (working copy) > @@ -171,44 +171,20 @@ enum stack_check_type > /* Check the stack and rely on the target configuration files to > check the static frame of functions, i.e. use the generic > mechanism only for dynamic stack allocations. */ > STATIC_BUILTIN_STACK_CHECK, > > /* Check the stack and entirely rely on the target configuration > files, i.e. do not use the generic mechanism at all. */ > 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, > FP_CONTRACT_ON = 1, > FP_CONTRACT_FAST = 2 > }; > > /* Scalar storage order kind. */ > enum scalar_storage_order_kind { > SSO_NATIVE = 0, > Index: gcc/fold-const.c > =================================================================== > --- gcc/fold-const.c (revision 235644) > +++ gcc/fold-const.c (working copy) > @@ -290,21 +290,21 @@ fold_undefer_and_ignore_overflow_warning > > bool > fold_deferring_overflow_warnings_p (void) > { > return fold_deferring_overflow_warnings > 0; > } > > /* 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) > { > if (fold_deferred_overflow_warning == NULL > || wc < fold_deferred_overflow_code) > { > fold_deferred_overflow_warning = gmsgid; > fold_deferred_overflow_code = wc; > } > @@ -8388,89 +8388,20 @@ fold_comparison (location_t loc, enum tr > { > const bool equality_code = (code == EQ_EXPR || code == NE_EXPR); > tree arg0, arg1, tem; > > arg0 = op0; > arg1 = op1; > > 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 > POINTER_PLUS_EXPR to do more than the operand_equal_p test below. */ > if (POINTER_TYPE_P (TREE_TYPE (arg0)) > && (TREE_CODE (arg0) == ADDR_EXPR > || TREE_CODE (arg1) == ADDR_EXPR > || TREE_CODE (arg0) == POINTER_PLUS_EXPR > || TREE_CODE (arg1) == POINTER_PLUS_EXPR)) > { > Index: gcc/fold-const.h > =================================================================== > --- gcc/fold-const.h (revision 235644) > +++ gcc/fold-const.h (working copy) > @@ -79,20 +79,21 @@ extern bool fold_convertible_p (const_tr > fold_convert_loc (UNKNOWN_LOCATION, T1, T2) > extern tree fold_convert_loc (location_t, tree, tree); > extern tree fold_single_bit_test (location_t, enum tree_code, tree, tree, > tree); > extern tree fold_ignored_result (tree); > extern tree fold_abs_const (tree, tree); > extern tree fold_indirect_ref_1 (location_t, tree, tree); > 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)\ > omit_one_operand_loc (UNKNOWN_LOCATION, T1, T2, T3) > extern tree omit_one_operand_loc (location_t, tree, tree, tree); > #define omit_two_operands(T1,T2,T3,T4)\ > omit_two_operands_loc (UNKNOWN_LOCATION, T1, T2, T3, T4) > extern tree omit_two_operands_loc (location_t, tree, tree, tree, tree); > #define invert_truthvalue(T)\ > invert_truthvalue_loc (UNKNOWN_LOCATION, T) > Index: gcc/gimple-fold.c > =================================================================== > --- gcc/gimple-fold.c (revision 235644) > +++ gcc/gimple-fold.c (working copy) > @@ -3518,21 +3518,23 @@ maybe_canonicalize_mem_ref_addr (tree *t > } > > /* Worker for both fold_stmt and fold_stmt_inplace. The INPLACE argument > distinguishes both cases. */ > > static bool > 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. > ??? This shouldn't be done in generic folding but in the > propagation helpers which also know whether an address was > propagated. > Also canonicalize operand order. */ > switch (gimple_code (stmt)) > { > case GIMPLE_ASSIGN: > @@ -3811,20 +3813,21 @@ fold_stmt_1 (gimple_stmt_iterator *gsi, > { > tree new_lhs = maybe_fold_reference (lhs, true); > if (new_lhs) > { > gimple_set_lhs (stmt, new_lhs); > changed = true; > } > } > } > > + fold_undefer_overflow_warnings (changed && !nowarning, stmt, 0); > return changed; > } > > /* Valueziation callback that ends up not following SSA edges. */ > > tree > no_follow_ssa_edges (tree) > { > return NULL_TREE; > } > Index: gcc/match.pd > =================================================================== > --- gcc/match.pd (revision 235644) > +++ gcc/match.pd (working copy) > @@ -3179,10 +3179,54 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) > (simplify > /* signbit(x) -> 0 if x is nonnegative. */ > (SIGNBIT tree_expr_nonnegative_p@0) > { integer_zero_node; }) > > (simplify > /* signbit(x) -> x<0 if x doesn't have signed zeros. */ > (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; }))))))))) > Index: gcc/testsuite/gcc.dg/tree-ssa/20040305-1.c > =================================================================== > --- gcc/testsuite/gcc.dg/tree-ssa/20040305-1.c (revision 235644) > +++ gcc/testsuite/gcc.dg/tree-ssa/20040305-1.c (working copy) > @@ -16,15 +16,15 @@ void foo(int edx, int eax) > } > if (eax == 100) > { > if (-- edx == 0) > afred[0] = 2; > } > } > > > /* 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. */ > /* { dg-final { scan-tree-dump-times "if " 2 "cddce2"} } */ >
Index: gcc/coretypes.h =================================================================== --- gcc/coretypes.h (revision 235644) +++ gcc/coretypes.h (working copy) @@ -215,20 +215,44 @@ enum optimization_type { /* Possible initialization status of a variable. When requested by the user, this information is tracked and recorded in the DWARF debug information, along with the variable's location. */ enum var_init_status { VAR_INIT_STATUS_UNKNOWN, VAR_INIT_STATUS_UNINITIALIZED, 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 unknown, sometimes indicating a memory barrier) and -2 (indicating that the alias set should be set to a unique value but has not been set yet). */ typedef int alias_set_type; struct edge_def; typedef struct edge_def *edge; Index: gcc/flag-types.h =================================================================== --- gcc/flag-types.h (revision 235644) +++ gcc/flag-types.h (working copy) @@ -171,44 +171,20 @@ enum stack_check_type /* Check the stack and rely on the target configuration files to check the static frame of functions, i.e. use the generic mechanism only for dynamic stack allocations. */ STATIC_BUILTIN_STACK_CHECK, /* Check the stack and entirely rely on the target configuration files, i.e. do not use the generic mechanism at all. */ 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, FP_CONTRACT_ON = 1, FP_CONTRACT_FAST = 2 }; /* Scalar storage order kind. */ enum scalar_storage_order_kind { SSO_NATIVE = 0, Index: gcc/fold-const.c =================================================================== --- gcc/fold-const.c (revision 235644) +++ gcc/fold-const.c (working copy) @@ -290,21 +290,21 @@ fold_undefer_and_ignore_overflow_warning bool fold_deferring_overflow_warnings_p (void) { return fold_deferring_overflow_warnings > 0; } /* 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) { if (fold_deferred_overflow_warning == NULL || wc < fold_deferred_overflow_code) { fold_deferred_overflow_warning = gmsgid; fold_deferred_overflow_code = wc; } @@ -8388,89 +8388,20 @@ fold_comparison (location_t loc, enum tr { const bool equality_code = (code == EQ_EXPR || code == NE_EXPR); tree arg0, arg1, tem; arg0 = op0; arg1 = op1; 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 POINTER_PLUS_EXPR to do more than the operand_equal_p test below. */ if (POINTER_TYPE_P (TREE_TYPE (arg0)) && (TREE_CODE (arg0) == ADDR_EXPR || TREE_CODE (arg1) == ADDR_EXPR || TREE_CODE (arg0) == POINTER_PLUS_EXPR || TREE_CODE (arg1) == POINTER_PLUS_EXPR)) { Index: gcc/fold-const.h =================================================================== --- gcc/fold-const.h (revision 235644) +++ gcc/fold-const.h (working copy) @@ -79,20 +79,21 @@ extern bool fold_convertible_p (const_tr fold_convert_loc (UNKNOWN_LOCATION, T1, T2) extern tree fold_convert_loc (location_t, tree, tree); extern tree fold_single_bit_test (location_t, enum tree_code, tree, tree, tree); extern tree fold_ignored_result (tree); extern tree fold_abs_const (tree, tree); extern tree fold_indirect_ref_1 (location_t, tree, tree); 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)\ omit_one_operand_loc (UNKNOWN_LOCATION, T1, T2, T3) extern tree omit_one_operand_loc (location_t, tree, tree, tree); #define omit_two_operands(T1,T2,T3,T4)\ omit_two_operands_loc (UNKNOWN_LOCATION, T1, T2, T3, T4) extern tree omit_two_operands_loc (location_t, tree, tree, tree, tree); #define invert_truthvalue(T)\ invert_truthvalue_loc (UNKNOWN_LOCATION, T) Index: gcc/gimple-fold.c =================================================================== --- gcc/gimple-fold.c (revision 235644) +++ gcc/gimple-fold.c (working copy) @@ -3518,21 +3518,23 @@ maybe_canonicalize_mem_ref_addr (tree *t } /* Worker for both fold_stmt and fold_stmt_inplace. The INPLACE argument distinguishes both cases. */ static bool 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. ??? This shouldn't be done in generic folding but in the propagation helpers which also know whether an address was propagated. Also canonicalize operand order. */ switch (gimple_code (stmt)) { case GIMPLE_ASSIGN: @@ -3811,20 +3813,21 @@ fold_stmt_1 (gimple_stmt_iterator *gsi, { tree new_lhs = maybe_fold_reference (lhs, true); if (new_lhs) { gimple_set_lhs (stmt, new_lhs); changed = true; } } } + fold_undefer_overflow_warnings (changed && !nowarning, stmt, 0); return changed; } /* Valueziation callback that ends up not following SSA edges. */ tree no_follow_ssa_edges (tree) { return NULL_TREE; } Index: gcc/match.pd =================================================================== --- gcc/match.pd (revision 235644) +++ gcc/match.pd (working copy) @@ -3179,10 +3179,54 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (simplify /* signbit(x) -> 0 if x is nonnegative. */ (SIGNBIT tree_expr_nonnegative_p@0) { integer_zero_node; }) (simplify /* signbit(x) -> x<0 if x doesn't have signed zeros. */ (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; }))))))))) Index: gcc/testsuite/gcc.dg/tree-ssa/20040305-1.c =================================================================== --- gcc/testsuite/gcc.dg/tree-ssa/20040305-1.c (revision 235644) +++ gcc/testsuite/gcc.dg/tree-ssa/20040305-1.c (working copy) @@ -16,15 +16,15 @@ void foo(int edx, int eax) } if (eax == 100) { if (-- edx == 0) afred[0] = 2; } } /* 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. */ /* { dg-final { scan-tree-dump-times "if " 2 "cddce2"} } */