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.
2016-05-02 Marc Glisse <marc.gli...@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"} } */