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
This commit is contained in:
parent
5b37e8664b
commit
a8b85ce9e2
9 changed files with 90 additions and 95 deletions
|
@ -1,3 +1,15 @@
|
|||
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>
|
||||
|
||||
* omp-low.c (struct oacc_loop): Add 'inner' field.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)\
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
44
gcc/match.pd
44
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; })))))))))
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
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>
|
||||
|
||||
* c-c++-common/goacc/loop-auto-1.c: Adjust expected warnings.
|
||||
|
|
|
@ -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. */
|
||||
|
|
Loading…
Add table
Reference in a new issue