Commit a8b85ce9 by Marc Glisse Committed by Marc Glisse

Move "X +- C1 CMP C2 to X CMP C2 -+ C1" to match.pd

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.

From-SVN: r235760
parent 5b37e866
2016-05-02 Marc Glisse <marc.glisse@inria.fr>
* 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 <nathan@codesourcery.com> 2016-05-02 Nathan Sidwell <nathan@codesourcery.com>
* omp-low.c (struct oacc_loop): Add 'inner' field. * omp-low.c (struct oacc_loop): Add 'inner' field.
......
...@@ -222,6 +222,30 @@ enum var_init_status ...@@ -222,6 +222,30 @@ enum var_init_status
VAR_INIT_STATUS_INITIALIZED 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 /* The type of an alias set. Code currently assumes that variables of
this type can take the values 0 (the alias set which aliases this type can take the values 0 (the alias set which aliases
everything) and -1 (sometimes indicating that the alias set is everything) and -1 (sometimes indicating that the alias set is
......
...@@ -178,30 +178,6 @@ enum stack_check_type ...@@ -178,30 +178,6 @@ enum stack_check_type
FULL_BUILTIN_STACK_CHECK 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. */ /* Floating-point contraction mode. */
enum fp_contract_mode { enum fp_contract_mode {
FP_CONTRACT_OFF = 0, FP_CONTRACT_OFF = 0,
......
...@@ -297,7 +297,7 @@ fold_deferring_overflow_warnings_p (void) ...@@ -297,7 +297,7 @@ fold_deferring_overflow_warnings_p (void)
/* This is called when we fold something based on the fact that signed /* This is called when we fold something based on the fact that signed
overflow is undefined. */ overflow is undefined. */
static void void
fold_overflow_warning (const char* gmsgid, enum warn_strict_overflow_code wc) fold_overflow_warning (const char* gmsgid, enum warn_strict_overflow_code wc)
{ {
if (fold_deferring_overflow_warnings > 0) if (fold_deferring_overflow_warnings > 0)
...@@ -8392,75 +8392,6 @@ fold_comparison (location_t loc, enum tree_code code, tree type, ...@@ -8392,75 +8392,6 @@ fold_comparison (location_t loc, enum tree_code code, tree type,
STRIP_SIGN_NOPS (arg0); STRIP_SIGN_NOPS (arg0);
STRIP_SIGN_NOPS (arg1); 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 /* For comparisons of pointers we can decompose it to a compile time
comparison of the base objects and the offsets into the object. comparison of the base objects and the offsets into the object.
This requires at least one operand being an ADDR_EXPR or a This requires at least one operand being an ADDR_EXPR or a
......
...@@ -86,6 +86,7 @@ extern void fold_defer_overflow_warnings (void); ...@@ -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_overflow_warnings (bool, const gimple *, int);
extern void fold_undefer_and_ignore_overflow_warnings (void); extern void fold_undefer_and_ignore_overflow_warnings (void);
extern bool fold_deferring_overflow_warnings_p (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 operand_equal_p (const_tree, const_tree, unsigned int);
extern int multiple_of_p (tree, const_tree, const_tree); extern int multiple_of_p (tree, const_tree, const_tree);
#define omit_one_operand(T1,T2,T3)\ #define omit_one_operand(T1,T2,T3)\
......
...@@ -3525,7 +3525,9 @@ fold_stmt_1 (gimple_stmt_iterator *gsi, bool inplace, tree (*valueize) (tree)) ...@@ -3525,7 +3525,9 @@ fold_stmt_1 (gimple_stmt_iterator *gsi, bool inplace, tree (*valueize) (tree))
{ {
bool changed = false; bool changed = false;
gimple *stmt = gsi_stmt (*gsi); gimple *stmt = gsi_stmt (*gsi);
bool nowarning = gimple_no_warning_p (stmt);
unsigned i; unsigned i;
fold_defer_overflow_warnings ();
/* First do required canonicalization of [TARGET_]MEM_REF addresses /* First do required canonicalization of [TARGET_]MEM_REF addresses
after propagation. after propagation.
...@@ -3818,6 +3820,7 @@ fold_stmt_1 (gimple_stmt_iterator *gsi, bool inplace, tree (*valueize) (tree)) ...@@ -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; return changed;
} }
......
...@@ -3186,3 +3186,47 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) ...@@ -3186,3 +3186,47 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(SIGNBIT @0) (SIGNBIT @0)
(if (!HONOR_SIGNED_ZEROS (@0)) (if (!HONOR_SIGNED_ZEROS (@0))
(convert (lt @0 { build_real (TREE_TYPE (@0), dconst0); })))) (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; })))))))))
2016-05-02 Marc Glisse <marc.glisse@inria.fr>
* gcc.dg/tree-ssa/20040305-1.c: Adjust.
2016-05-02 Nathan Sidwell <nathan@codesourcery.com> 2016-05-02 Nathan Sidwell <nathan@codesourcery.com>
* c-c++-common/goacc/loop-auto-1.c: Adjust expected warnings. * c-c++-common/goacc/loop-auto-1.c: Adjust expected warnings.
......
...@@ -23,7 +23,7 @@ void foo(int edx, int eax) ...@@ -23,7 +23,7 @@ void foo(int edx, int eax)
/* Verify that we did a forward propagation. */ /* 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 /* After cddce we should have two IF statements remaining as the other
two tests can be threaded. */ two tests can be threaded. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment