Commit 02c64149 by Richard Biener Committed by Richard Biener

re PR tree-optimization/31130 (VRP no longer derives range for division after negation)

2017-05-04  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/31130
	* tree-vrp.c (needs_overflow_infinity): Remove as always returning
	false.
	(supports_overflow_infinity): Likewise.
	(is_negative_overflow_infinity): Likewise.
	(is_positive_overflow_infinity): Likewise.
	(is_overflow_infinity): Likewise.
	(stmt_overflow_infinity): Likewise.
	(overflow_infinity_range_p): Likewise.
	(usable_range_p): Remove as always returning true.
	(make_overflow_infinity): Remove.
	(negative_overflow_infinity): Likewise.
	(positive_overflow_infinity): Likewise.
	(avoid_overflow_infinity): Likewise.
	(set_value_range): Adjust accordingly.
	(set_value_range_to_nonnegative): Likewise, remove now unused
	overflow_infinity arg.
	(vrp_operand_equal_p): Adjust.
	(update_value_range): Likewise.
	(range_int_cst_singleton_p): Likewise.
	(operand_less_p): Likewise.
	(compare_values_warnv): Likewise.
	(extract_range_for_var_from_comparison_expr): Likewise.
	(vrp_int_const_binop): Likewise.
	(zero_nonzero_bits_from_vr): Likewise.
	(extract_range_from_multiplicative_op_1): Likewise.
	(extract_range_from_binary_expr_1): Likewise.
	(extract_range_from_unary_expr): Likewise.
	(extract_range_from_comparison): Likewise.
	(extract_range_basic): Likewise.
	(adjust_range_with_scev): Likewise.
	(compare_ranges): Likewise.
	(compare_range_with_value): Likewise.
	(dump_value_range): Likewise.
	(test_for_singularity): Likewise, remove strict_overflow_p parameter
	never used.
	(simplify_cond_using_ranges): Adjust.

	* gcc.dg/Wstrict-overflow-12.c: XFAIL.
	* gcc.dg/Wstrict-overflow-13.c: Likewise.
	* gcc.dg/Wstrict-overflow-21.c: Likewise.
	* gcc.dg/pr52904.c: Remove XFAIL.
	* gcc.dg/tree-ssa/vrp114.c: New testcase.

From-SVN: r247578
parent 2b451410
2017-05-04 Richard Biener <rguenther@suse.de>
PR tree-optimization/31130
* tree-vrp.c (needs_overflow_infinity): Remove as always returning
false.
(supports_overflow_infinity): Likewise.
(is_negative_overflow_infinity): Likewise.
(is_positive_overflow_infinity): Likewise.
(is_overflow_infinity): Likewise.
(stmt_overflow_infinity): Likewise.
(overflow_infinity_range_p): Likewise.
(usable_range_p): Remove as always returning true.
(make_overflow_infinity): Remove.
(negative_overflow_infinity): Likewise.
(positive_overflow_infinity): Likewise.
(avoid_overflow_infinity): Likewise.
(set_value_range): Adjust accordingly.
(set_value_range_to_nonnegative): Likewise, remove now unused
overflow_infinity arg.
(vrp_operand_equal_p): Adjust.
(update_value_range): Likewise.
(range_int_cst_singleton_p): Likewise.
(operand_less_p): Likewise.
(compare_values_warnv): Likewise.
(extract_range_for_var_from_comparison_expr): Likewise.
(vrp_int_const_binop): Likewise.
(zero_nonzero_bits_from_vr): Likewise.
(extract_range_from_multiplicative_op_1): Likewise.
(extract_range_from_binary_expr_1): Likewise.
(extract_range_from_unary_expr): Likewise.
(extract_range_from_comparison): Likewise.
(extract_range_basic): Likewise.
(adjust_range_with_scev): Likewise.
(compare_ranges): Likewise.
(compare_range_with_value): Likewise.
(dump_value_range): Likewise.
(test_for_singularity): Likewise, remove strict_overflow_p parameter
never used.
(simplify_cond_using_ranges): Adjust.
2017-05-04 Pekka Jääskeläinen <pekka.jaaskelainen@parmance.com> 2017-05-04 Pekka Jääskeläinen <pekka.jaaskelainen@parmance.com>
* brig-builtins.def: Added a builtin for class_f64. * brig-builtins.def: Added a builtin for class_f64.
......
2017-05-04 Richard Biener <rguenther@suse.de>
PR tree-optimization/31130
* gcc.dg/Wstrict-overflow-12.c: XFAIL.
* gcc.dg/Wstrict-overflow-13.c: Likewise.
* gcc.dg/Wstrict-overflow-21.c: Likewise.
* gcc.dg/pr52904.c: Remove XFAIL.
* gcc.dg/tree-ssa/vrp114.c: New testcase.
2017-05-03 Jeff Law <law@redhat.com> 2017-05-03 Jeff Law <law@redhat.com>
PR tree-optimization/78496 PR tree-optimization/78496
......
...@@ -10,7 +10,7 @@ int ...@@ -10,7 +10,7 @@ int
foo () foo ()
{ {
int i, bits; int i, bits;
for (i = 1, bits = 1; i > 0; i += i) /* { dg-warning "assuming signed overflow does not occur" "correct warning" } */ for (i = 1, bits = 1; i > 0; i += i) /* { dg-warning "assuming signed overflow does not occur" "correct warning" { xfail *-*-* } } */
++bits; ++bits;
return bits; return bits;
} }
...@@ -11,7 +11,7 @@ int ...@@ -11,7 +11,7 @@ int
foo () foo ()
{ {
int j; int j;
for (j = 1; 0 < j; j *= 2) /* { dg-warning "assuming signed overflow does not occur" "correct warning" } */ for (j = 1; 0 < j; j *= 2) /* { dg-warning "assuming signed overflow does not occur" "correct warning" { xfail *-*-* } } */
if (! bigtime_test (j)) if (! bigtime_test (j))
return 1; return 1;
return 0; return 0;
......
...@@ -5,7 +5,7 @@ int ...@@ -5,7 +5,7 @@ int
foo () foo ()
{ {
int i, bits; int i, bits;
for (i = 1, bits = 1; i > 0; i += i) /* { dg-warning "assuming signed overflow does not occur" "correct warning" } */ for (i = 1, bits = 1; i > 0; i += i) /* { dg-warning "assuming signed overflow does not occur" "correct warning" { xfail *-*-* } } */
++bits; ++bits;
return bits; return bits;
} }
......
...@@ -14,7 +14,7 @@ wait_reading_process_output (void) ...@@ -14,7 +14,7 @@ wait_reading_process_output (void)
nfds++; nfds++;
} }
if (nfds < 0) /* { dg-bogus "assuming signed overflow does not occur" "" { xfail *-*-* } } */ if (nfds < 0) /* { dg-bogus "assuming signed overflow does not occur" "" } */
return 1; return 1;
return 0; return 0;
} }
/* { dg-do link } */
/* { dg-options "-O2 -fdump-tree-fre1 -fdump-tree-evrp" } */
extern void link_error ();
void foo (int a)
{
if (a < 0)
{
int y;
a = -a;
y = a / 7;
y = y * 2;
if (y > 1 << 30)
link_error ();
}
}
int main()
{
return 0;
}
/* { dg-final { scan-tree-dump-times "link_error" 1 "fre1" } } */
/* { dg-final { scan-tree-dump-times "link_error" 0 "evrp" } } */
...@@ -213,127 +213,6 @@ vrp_val_is_min (const_tree val) ...@@ -213,127 +213,6 @@ vrp_val_is_min (const_tree val)
} }
/* Return whether TYPE should use an overflow infinity distinct from
TYPE_{MIN,MAX}_VALUE. We use an overflow infinity value to
represent a signed overflow during VRP computations. An infinity
is distinct from a half-range, which will go from some number to
TYPE_{MIN,MAX}_VALUE. */
static inline bool
needs_overflow_infinity (const_tree type)
{
return INTEGRAL_TYPE_P (type) && !TYPE_OVERFLOW_WRAPS (type);
}
/* Return whether TYPE can support our overflow infinity
representation: we use the TREE_OVERFLOW flag, which only exists
for constants. If TYPE doesn't support this, we don't optimize
cases which would require signed overflow--we drop them to
VARYING. */
static inline bool
supports_overflow_infinity (const_tree type)
{
tree min = vrp_val_min (type), max = vrp_val_max (type);
gcc_checking_assert (needs_overflow_infinity (type));
return (min != NULL_TREE
&& CONSTANT_CLASS_P (min)
&& max != NULL_TREE
&& CONSTANT_CLASS_P (max));
}
/* VAL is the maximum or minimum value of a type. Return a
corresponding overflow infinity. */
static inline tree
make_overflow_infinity (tree val)
{
gcc_checking_assert (val != NULL_TREE && CONSTANT_CLASS_P (val));
val = copy_node (val);
TREE_OVERFLOW (val) = 1;
return val;
}
/* Return a negative overflow infinity for TYPE. */
static inline tree
negative_overflow_infinity (tree type)
{
gcc_checking_assert (supports_overflow_infinity (type));
return make_overflow_infinity (vrp_val_min (type));
}
/* Return a positive overflow infinity for TYPE. */
static inline tree
positive_overflow_infinity (tree type)
{
gcc_checking_assert (supports_overflow_infinity (type));
return make_overflow_infinity (vrp_val_max (type));
}
/* Return whether VAL is a negative overflow infinity. */
static inline bool
is_negative_overflow_infinity (const_tree val)
{
return (TREE_OVERFLOW_P (val)
&& needs_overflow_infinity (TREE_TYPE (val))
&& vrp_val_is_min (val));
}
/* Return whether VAL is a positive overflow infinity. */
static inline bool
is_positive_overflow_infinity (const_tree val)
{
return (TREE_OVERFLOW_P (val)
&& needs_overflow_infinity (TREE_TYPE (val))
&& vrp_val_is_max (val));
}
/* Return whether VAL is a positive or negative overflow infinity. */
static inline bool
is_overflow_infinity (const_tree val)
{
return (TREE_OVERFLOW_P (val)
&& needs_overflow_infinity (TREE_TYPE (val))
&& (vrp_val_is_min (val) || vrp_val_is_max (val)));
}
/* Return whether STMT has a constant rhs that is_overflow_infinity. */
static inline bool
stmt_overflow_infinity (gimple *stmt)
{
if (is_gimple_assign (stmt)
&& get_gimple_rhs_class (gimple_assign_rhs_code (stmt)) ==
GIMPLE_SINGLE_RHS)
return is_overflow_infinity (gimple_assign_rhs1 (stmt));
return false;
}
/* If VAL is now an overflow infinity, return VAL. Otherwise, return
the same value with TREE_OVERFLOW clear. This can be used to avoid
confusing a regular value with an overflow value. */
static inline tree
avoid_overflow_infinity (tree val)
{
if (!is_overflow_infinity (val))
return val;
if (vrp_val_is_max (val))
return vrp_val_max (TREE_TYPE (val));
else
{
gcc_checking_assert (vrp_val_is_min (val));
return vrp_val_min (TREE_TYPE (val));
}
}
/* Set value range VR to VR_UNDEFINED. */ /* Set value range VR to VR_UNDEFINED. */
static inline void static inline void
...@@ -372,8 +251,7 @@ set_value_range (value_range *vr, enum value_range_type t, tree min, ...@@ -372,8 +251,7 @@ set_value_range (value_range *vr, enum value_range_type t, tree min,
gcc_assert (min && max); gcc_assert (min && max);
gcc_assert ((!TREE_OVERFLOW_P (min) || is_overflow_infinity (min)) gcc_assert (!TREE_OVERFLOW_P (min) && !TREE_OVERFLOW_P (max));
&& (!TREE_OVERFLOW_P (max) || is_overflow_infinity (max)));
if (INTEGRAL_TYPE_P (TREE_TYPE (min)) && t == VR_ANTI_RANGE) if (INTEGRAL_TYPE_P (TREE_TYPE (min)) && t == VR_ANTI_RANGE)
gcc_assert (!vrp_val_is_min (min) || !vrp_val_is_max (max)); gcc_assert (!vrp_val_is_min (min) || !vrp_val_is_max (max));
...@@ -553,23 +431,10 @@ set_value_range_to_value (value_range *vr, tree val, bitmap equiv) ...@@ -553,23 +431,10 @@ set_value_range_to_value (value_range *vr, tree val, bitmap equiv)
overflow does not occur. */ overflow does not occur. */
static inline void static inline void
set_value_range_to_nonnegative (value_range *vr, tree type, set_value_range_to_nonnegative (value_range *vr, tree type)
bool overflow_infinity)
{ {
tree zero; tree zero = build_int_cst (type, 0);
set_value_range (vr, VR_RANGE, zero, vrp_val_max (type), vr->equiv);
if (overflow_infinity && !supports_overflow_infinity (type))
{
set_value_range_to_varying (vr);
return;
}
zero = build_int_cst (type, 0);
set_value_range (vr, VR_RANGE, zero,
(overflow_infinity
? positive_overflow_infinity (type)
: TYPE_MAX_VALUE (type)),
vr->equiv);
} }
/* Set value range VR to a non-NULL range of type TYPE. */ /* Set value range VR to a non-NULL range of type TYPE. */
...@@ -743,7 +608,7 @@ vrp_operand_equal_p (const_tree val1, const_tree val2) ...@@ -743,7 +608,7 @@ vrp_operand_equal_p (const_tree val1, const_tree val2)
return true; return true;
if (!val1 || !val2 || !operand_equal_p (val1, val2, 0)) if (!val1 || !val2 || !operand_equal_p (val1, val2, 0))
return false; return false;
return is_overflow_infinity (val1) == is_overflow_infinity (val2); return true;
} }
/* Return true, if the bitmaps B1 and B2 are equal. */ /* Return true, if the bitmaps B1 and B2 are equal. */
...@@ -783,25 +648,7 @@ update_value_range (const_tree var, value_range *new_vr) ...@@ -783,25 +648,7 @@ update_value_range (const_tree var, value_range *new_vr)
if (rtype == VR_RANGE || rtype == VR_ANTI_RANGE) if (rtype == VR_RANGE || rtype == VR_ANTI_RANGE)
{ {
tree nr_min, nr_max; tree nr_min, nr_max;
/* Range info on SSA names doesn't carry overflow information
so make sure to preserve the overflow bit on the lattice. */
if (rtype == VR_RANGE
&& needs_overflow_infinity (TREE_TYPE (var))
&& (new_vr->type == VR_VARYING
|| (new_vr->type == VR_RANGE
&& is_negative_overflow_infinity (new_vr->min)))
&& wi::eq_p (vrp_val_min (TREE_TYPE (var)), min))
nr_min = negative_overflow_infinity (TREE_TYPE (var));
else
nr_min = wide_int_to_tree (TREE_TYPE (var), min); nr_min = wide_int_to_tree (TREE_TYPE (var), min);
if (rtype == VR_RANGE
&& needs_overflow_infinity (TREE_TYPE (var))
&& (new_vr->type == VR_VARYING
|| (new_vr->type == VR_RANGE
&& is_positive_overflow_infinity (new_vr->max)))
&& wi::eq_p (vrp_val_max (TREE_TYPE (var)), max))
nr_max = positive_overflow_infinity (TREE_TYPE (var));
else
nr_max = wide_int_to_tree (TREE_TYPE (var), max); nr_max = wide_int_to_tree (TREE_TYPE (var), max);
value_range nr = VR_INITIALIZER; value_range nr = VR_INITIALIZER;
set_and_canonicalize_value_range (&nr, rtype, nr_min, nr_max, NULL); set_and_canonicalize_value_range (&nr, rtype, nr_min, nr_max, NULL);
...@@ -897,8 +744,6 @@ static inline bool ...@@ -897,8 +744,6 @@ static inline bool
range_int_cst_singleton_p (value_range *vr) range_int_cst_singleton_p (value_range *vr)
{ {
return (range_int_cst_p (vr) return (range_int_cst_p (vr)
&& !is_overflow_infinity (vr->min)
&& !is_overflow_infinity (vr->max)
&& tree_int_cst_equal (vr->min, vr->max)); && tree_int_cst_equal (vr->min, vr->max));
} }
...@@ -1006,41 +851,6 @@ symbolic_range_based_on_p (value_range *vr, const_tree sym) ...@@ -1006,41 +851,6 @@ symbolic_range_based_on_p (value_range *vr, const_tree sym)
return (min_has_symbol || max_has_symbol); return (min_has_symbol || max_has_symbol);
} }
/* Return true if value range VR uses an overflow infinity. */
static inline bool
overflow_infinity_range_p (value_range *vr)
{
return (vr->type == VR_RANGE
&& (is_overflow_infinity (vr->min)
|| is_overflow_infinity (vr->max)));
}
/* Return false if we can not make a valid comparison based on VR;
this will be the case if it uses an overflow infinity and overflow
is not undefined (i.e., -fno-strict-overflow is in effect).
Otherwise return true, and set *STRICT_OVERFLOW_P to true if VR
uses an overflow infinity. */
static bool
usable_range_p (value_range *vr, bool *strict_overflow_p)
{
gcc_assert (vr->type == VR_RANGE);
if (is_overflow_infinity (vr->min))
{
*strict_overflow_p = true;
if (!TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (vr->min)))
return false;
}
if (is_overflow_infinity (vr->max))
{
*strict_overflow_p = true;
if (!TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (vr->max)))
return false;
}
return true;
}
/* Return true if the result of assignment STMT is know to be non-zero. /* Return true if the result of assignment STMT is know to be non-zero.
If the return value is based on the assumption that signed overflow is If the return value is based on the assumption that signed overflow is
undefined, set *STRICT_OVERFLOW_P to true; otherwise, don't change undefined, set *STRICT_OVERFLOW_P to true; otherwise, don't change
...@@ -1180,10 +990,7 @@ operand_less_p (tree val, tree val2) ...@@ -1180,10 +990,7 @@ operand_less_p (tree val, tree val2)
{ {
/* LT is folded faster than GE and others. Inline the common case. */ /* LT is folded faster than GE and others. Inline the common case. */
if (TREE_CODE (val) == INTEGER_CST && TREE_CODE (val2) == INTEGER_CST) if (TREE_CODE (val) == INTEGER_CST && TREE_CODE (val2) == INTEGER_CST)
{
if (! is_positive_overflow_infinity (val2))
return tree_int_cst_lt (val, val2); return tree_int_cst_lt (val, val2);
}
else else
{ {
tree tcmp; tree tcmp;
...@@ -1202,12 +1009,6 @@ operand_less_p (tree val, tree val2) ...@@ -1202,12 +1009,6 @@ operand_less_p (tree val, tree val2)
return 1; return 1;
} }
/* val >= val2, not considering overflow infinity. */
if (is_negative_overflow_infinity (val))
return is_negative_overflow_infinity (val2) ? 0 : 1;
else if (is_positive_overflow_infinity (val2))
return is_positive_overflow_infinity (val) ? 0 : 1;
return 0; return 0;
} }
...@@ -1323,14 +1124,6 @@ compare_values_warnv (tree val1, tree val2, bool *strict_overflow_p) ...@@ -1323,14 +1124,6 @@ compare_values_warnv (tree val1, tree val2, bool *strict_overflow_p)
{ {
if (strict_overflow_p != NULL) if (strict_overflow_p != NULL)
*strict_overflow_p = true; *strict_overflow_p = true;
if (is_negative_overflow_infinity (val1))
return is_negative_overflow_infinity (val2) ? 0 : -1;
else if (is_negative_overflow_infinity (val2))
return 1;
else if (is_positive_overflow_infinity (val1))
return is_positive_overflow_infinity (val2) ? 0 : 1;
else if (is_positive_overflow_infinity (val2))
return -1;
return -2; return -2;
} }
...@@ -1523,7 +1316,6 @@ extract_range_for_var_from_comparison_expr (tree var, enum tree_code cond_code, ...@@ -1523,7 +1316,6 @@ extract_range_for_var_from_comparison_expr (tree var, enum tree_code cond_code,
{ {
tree min, max, type; tree min, max, type;
value_range *limit_vr; value_range *limit_vr;
limit = avoid_overflow_infinity (limit);
type = TREE_TYPE (var); type = TREE_TYPE (var);
gcc_assert (limit != var); gcc_assert (limit != var);
...@@ -1691,9 +1483,8 @@ extract_range_for_var_from_comparison_expr (tree var, enum tree_code cond_code, ...@@ -1691,9 +1483,8 @@ extract_range_for_var_from_comparison_expr (tree var, enum tree_code cond_code,
/* If the maximum value forces us to be out of bounds, simply punt. /* If the maximum value forces us to be out of bounds, simply punt.
It would be pointless to try and do anything more since this It would be pointless to try and do anything more since this
all should be optimized away above us. */ all should be optimized away above us. */
if ((cond_code == LT_EXPR if (cond_code == LT_EXPR
&& compare_values (max, min) == 0) && compare_values (max, min) == 0)
|| is_overflow_infinity (max))
set_value_range_to_varying (vr_p); set_value_range_to_varying (vr_p);
else else
{ {
...@@ -1731,9 +1522,8 @@ extract_range_for_var_from_comparison_expr (tree var, enum tree_code cond_code, ...@@ -1731,9 +1522,8 @@ extract_range_for_var_from_comparison_expr (tree var, enum tree_code cond_code,
/* If the minimum value forces us to be out of bounds, simply punt. /* If the minimum value forces us to be out of bounds, simply punt.
It would be pointless to try and do anything more since this It would be pointless to try and do anything more since this
all should be optimized away above us. */ all should be optimized away above us. */
if ((cond_code == GT_EXPR if (cond_code == GT_EXPR
&& compare_values (min, max) == 0) && compare_values (min, max) == 0)
|| is_overflow_infinity (min))
set_value_range_to_varying (vr_p); set_value_range_to_varying (vr_p);
else else
{ {
...@@ -1884,11 +1674,9 @@ vrp_int_const_binop (enum tree_code code, tree val1, tree val2) ...@@ -1884,11 +1674,9 @@ vrp_int_const_binop (enum tree_code code, tree val1, tree val2)
returns NULL_TREE. */ returns NULL_TREE. */
else if (!res) else if (!res)
return NULL_TREE; return NULL_TREE;
else if ((TREE_OVERFLOW (res) else if (TREE_OVERFLOW (res)
&& !TREE_OVERFLOW (val1) && ! TREE_OVERFLOW (val1)
&& !TREE_OVERFLOW (val2)) && ! TREE_OVERFLOW (val2))
|| is_overflow_infinity (val1)
|| is_overflow_infinity (val2))
{ {
/* If the operation overflowed but neither VAL1 nor VAL2 are /* If the operation overflowed but neither VAL1 nor VAL2 are
overflown, return -INF or +INF depending on the operation overflown, return -INF or +INF depending on the operation
...@@ -1896,30 +1684,6 @@ vrp_int_const_binop (enum tree_code code, tree val1, tree val2) ...@@ -1896,30 +1684,6 @@ vrp_int_const_binop (enum tree_code code, tree val1, tree val2)
int sgn1 = tree_int_cst_sgn (val1); int sgn1 = tree_int_cst_sgn (val1);
int sgn2 = tree_int_cst_sgn (val2); int sgn2 = tree_int_cst_sgn (val2);
if (needs_overflow_infinity (TREE_TYPE (res))
&& !supports_overflow_infinity (TREE_TYPE (res)))
return NULL_TREE;
/* We have to punt on adding infinities of different signs,
since we can't tell what the sign of the result should be.
Likewise for subtracting infinities of the same sign. */
if (((code == PLUS_EXPR && sgn1 != sgn2)
|| (code == MINUS_EXPR && sgn1 == sgn2))
&& is_overflow_infinity (val1)
&& is_overflow_infinity (val2))
return NULL_TREE;
/* Don't try to handle division or shifting of infinities. */
if ((code == TRUNC_DIV_EXPR
|| code == FLOOR_DIV_EXPR
|| code == CEIL_DIV_EXPR
|| code == EXACT_DIV_EXPR
|| code == ROUND_DIV_EXPR
|| code == RSHIFT_EXPR)
&& (is_overflow_infinity (val1)
|| is_overflow_infinity (val2)))
return NULL_TREE;
/* Notice that we only need to handle the restricted set of /* Notice that we only need to handle the restricted set of
operations handled by extract_range_from_binary_expr. operations handled by extract_range_from_binary_expr.
Among them, only multiplication, addition and subtraction Among them, only multiplication, addition and subtraction
...@@ -1933,23 +1697,15 @@ vrp_int_const_binop (enum tree_code code, tree val1, tree val2) ...@@ -1933,23 +1697,15 @@ vrp_int_const_binop (enum tree_code code, tree val1, tree val2)
if ((code == MULT_EXPR && sgn1 == sgn2) if ((code == MULT_EXPR && sgn1 == sgn2)
/* For addition, the operands must be of the same sign /* For addition, the operands must be of the same sign
to yield an overflow. Its sign is therefore that to yield an overflow. Its sign is therefore that
of one of the operands, for example the first. For of one of the operands, for example the first. */
infinite operands X + -INF is negative, not positive. */ || (code == PLUS_EXPR && sgn1 >= 0)
|| (code == PLUS_EXPR /* For subtraction, operands must be of
&& (sgn1 >= 0
? !is_negative_overflow_infinity (val2)
: is_positive_overflow_infinity (val2)))
/* For subtraction, non-infinite operands must be of
different signs to yield an overflow. Its sign is different signs to yield an overflow. Its sign is
therefore that of the first operand or the opposite of therefore that of the first operand or the opposite of
that of the second operand. A first operand of 0 counts that of the second operand. A first operand of 0 counts
as positive here, for the corner case 0 - (-INF), which as positive here, for the corner case 0 - (-INF), which
overflows, but must yield +INF. For infinite operands 0 overflows, but must yield +INF. */
- INF is negative, not positive. */ || (code == MINUS_EXPR && sgn1 >= 0)
|| (code == MINUS_EXPR
&& (sgn1 >= 0
? !is_positive_overflow_infinity (val2)
: is_negative_overflow_infinity (val2)))
/* We only get in here with positive shift count, so the /* We only get in here with positive shift count, so the
overflow direction is the same as the sign of val1. overflow direction is the same as the sign of val1.
Actually rshift does not overflow at all, but we only Actually rshift does not overflow at all, but we only
...@@ -1962,13 +1718,9 @@ vrp_int_const_binop (enum tree_code code, tree val1, tree val2) ...@@ -1962,13 +1718,9 @@ vrp_int_const_binop (enum tree_code code, tree val1, tree val2)
|| code == CEIL_DIV_EXPR || code == CEIL_DIV_EXPR
|| code == EXACT_DIV_EXPR || code == EXACT_DIV_EXPR
|| code == ROUND_DIV_EXPR) || code == ROUND_DIV_EXPR)
return (needs_overflow_infinity (TREE_TYPE (res)) return TYPE_MAX_VALUE (TREE_TYPE (res));
? positive_overflow_infinity (TREE_TYPE (res))
: TYPE_MAX_VALUE (TREE_TYPE (res)));
else else
return (needs_overflow_infinity (TREE_TYPE (res)) return TYPE_MIN_VALUE (TREE_TYPE (res));
? negative_overflow_infinity (TREE_TYPE (res))
: TYPE_MIN_VALUE (TREE_TYPE (res)));
} }
return res; return res;
...@@ -1989,9 +1741,7 @@ zero_nonzero_bits_from_vr (const tree expr_type, ...@@ -1989,9 +1741,7 @@ zero_nonzero_bits_from_vr (const tree expr_type,
{ {
*may_be_nonzero = wi::minus_one (TYPE_PRECISION (expr_type)); *may_be_nonzero = wi::minus_one (TYPE_PRECISION (expr_type));
*must_be_nonzero = wi::zero (TYPE_PRECISION (expr_type)); *must_be_nonzero = wi::zero (TYPE_PRECISION (expr_type));
if (!range_int_cst_p (vr) if (!range_int_cst_p (vr))
|| is_overflow_infinity (vr->min)
|| is_overflow_infinity (vr->max))
return false; return false;
if (range_int_cst_singleton_p (vr)) if (range_int_cst_singleton_p (vr))
...@@ -2146,16 +1896,15 @@ extract_range_from_multiplicative_op_1 (value_range *vr, ...@@ -2146,16 +1896,15 @@ extract_range_from_multiplicative_op_1 (value_range *vr,
for (i = 1; i < 4; i++) for (i = 1; i < 4; i++)
{ {
if (!is_gimple_min_invariant (min) if (!is_gimple_min_invariant (min)
|| (TREE_OVERFLOW (min) && !is_overflow_infinity (min)) || TREE_OVERFLOW (min)
|| !is_gimple_min_invariant (max) || !is_gimple_min_invariant (max)
|| (TREE_OVERFLOW (max) && !is_overflow_infinity (max))) || TREE_OVERFLOW (max))
break; break;
if (val[i]) if (val[i])
{ {
if (!is_gimple_min_invariant (val[i]) if (!is_gimple_min_invariant (val[i])
|| (TREE_OVERFLOW (val[i]) || TREE_OVERFLOW (val[i]))
&& !is_overflow_infinity (val[i])))
{ {
/* If we found an overflowed value, set MIN and MAX /* If we found an overflowed value, set MIN and MAX
to it so that we set the resulting range to to it so that we set the resulting range to
...@@ -2177,25 +1926,20 @@ extract_range_from_multiplicative_op_1 (value_range *vr, ...@@ -2177,25 +1926,20 @@ extract_range_from_multiplicative_op_1 (value_range *vr,
representation. */ representation. */
if (min == NULL_TREE if (min == NULL_TREE
|| !is_gimple_min_invariant (min) || !is_gimple_min_invariant (min)
|| (TREE_OVERFLOW (min) && !is_overflow_infinity (min)) || TREE_OVERFLOW (min)
|| max == NULL_TREE || max == NULL_TREE
|| !is_gimple_min_invariant (max) || !is_gimple_min_invariant (max)
|| (TREE_OVERFLOW (max) && !is_overflow_infinity (max))) || TREE_OVERFLOW (max))
{ {
set_value_range_to_varying (vr); set_value_range_to_varying (vr);
return; return;
} }
/* We punt if: /* We punt for [-INF, +INF].
1) [-INF, +INF] We learn nothing when we have INF on both sides.
2) [-INF, +-INF(OVF)] Note that we do accept [-INF, -INF] and [+INF, +INF]. */
3) [+-INF(OVF), +INF] if (vrp_val_is_min (min)
4) [+-INF(OVF), +-INF(OVF)] && vrp_val_is_max (max))
We learn nothing when we have INF and INF(OVF) on both sides.
Note that we do accept [-INF, -INF] and [+INF, +INF] without
overflow. */
if ((vrp_val_is_min (min) || is_overflow_infinity (min))
&& (vrp_val_is_max (max) || is_overflow_infinity (max)))
{ {
set_value_range_to_varying (vr); set_value_range_to_varying (vr);
return; return;
...@@ -2609,61 +2353,20 @@ extract_range_from_binary_expr_1 (value_range *vr, ...@@ -2609,61 +2353,20 @@ extract_range_from_binary_expr_1 (value_range *vr,
/* If overflow does not wrap, saturate to the types min/max /* If overflow does not wrap, saturate to the types min/max
value. */ value. */
if (min_ovf == -1) if (min_ovf == -1)
{
if (needs_overflow_infinity (expr_type)
&& supports_overflow_infinity (expr_type))
min = negative_overflow_infinity (expr_type);
else
min = wide_int_to_tree (expr_type, type_min); min = wide_int_to_tree (expr_type, type_min);
}
else if (min_ovf == 1) else if (min_ovf == 1)
{
if (needs_overflow_infinity (expr_type)
&& supports_overflow_infinity (expr_type))
min = positive_overflow_infinity (expr_type);
else
min = wide_int_to_tree (expr_type, type_max); min = wide_int_to_tree (expr_type, type_max);
}
else else
min = wide_int_to_tree (expr_type, wmin); min = wide_int_to_tree (expr_type, wmin);
if (max_ovf == -1) if (max_ovf == -1)
{
if (needs_overflow_infinity (expr_type)
&& supports_overflow_infinity (expr_type))
max = negative_overflow_infinity (expr_type);
else
max = wide_int_to_tree (expr_type, type_min); max = wide_int_to_tree (expr_type, type_min);
}
else if (max_ovf == 1) else if (max_ovf == 1)
{
if (needs_overflow_infinity (expr_type)
&& supports_overflow_infinity (expr_type))
max = positive_overflow_infinity (expr_type);
else
max = wide_int_to_tree (expr_type, type_max); max = wide_int_to_tree (expr_type, type_max);
}
else else
max = wide_int_to_tree (expr_type, wmax); max = wide_int_to_tree (expr_type, wmax);
} }
if (needs_overflow_infinity (expr_type)
&& supports_overflow_infinity (expr_type))
{
if ((min_op0 && is_negative_overflow_infinity (min_op0))
|| (min_op1
&& (minus_p
? is_positive_overflow_infinity (min_op1)
: is_negative_overflow_infinity (min_op1))))
min = negative_overflow_infinity (expr_type);
if ((max_op0 && is_positive_overflow_infinity (max_op0))
|| (max_op1
&& (minus_p
? is_negative_overflow_infinity (max_op1)
: is_positive_overflow_infinity (max_op1))))
max = positive_overflow_infinity (expr_type);
}
/* If the result lower bound is constant, we're done; /* If the result lower bound is constant, we're done;
otherwise, build the symbolic lower bound. */ otherwise, build the symbolic lower bound. */
if (sym_min_op0 == sym_min_op1) if (sym_min_op0 == sym_min_op1)
...@@ -3251,26 +2954,20 @@ extract_range_from_binary_expr_1 (value_range *vr, ...@@ -3251,26 +2954,20 @@ extract_range_from_binary_expr_1 (value_range *vr,
gcc_unreachable (); gcc_unreachable ();
/* If either MIN or MAX overflowed, then set the resulting range to /* If either MIN or MAX overflowed, then set the resulting range to
VARYING. But we do accept an overflow infinity representation. */ VARYING. */
if (min == NULL_TREE if (min == NULL_TREE
|| (TREE_OVERFLOW_P (min) && !is_overflow_infinity (min)) || TREE_OVERFLOW_P (min)
|| max == NULL_TREE || max == NULL_TREE
|| (TREE_OVERFLOW_P (max) && !is_overflow_infinity (max))) || TREE_OVERFLOW_P (max))
{ {
set_value_range_to_varying (vr); set_value_range_to_varying (vr);
return; return;
} }
/* We punt if: /* We punt for [-INF, +INF].
1) [-INF, +INF] We learn nothing when we have INF on both sides.
2) [-INF, +-INF(OVF)] Note that we do accept [-INF, -INF] and [+INF, +INF]. */
3) [+-INF(OVF), +INF] if (vrp_val_is_min (min) && vrp_val_is_max (max))
4) [+-INF(OVF), +-INF(OVF)]
We learn nothing when we have INF and INF(OVF) on both sides.
Note that we do accept [-INF, -INF] and [+INF, +INF] without
overflow. */
if ((vrp_val_is_min (min) || is_overflow_infinity (min))
&& (vrp_val_is_max (max) || is_overflow_infinity (max)))
{ {
set_value_range_to_varying (vr); set_value_range_to_varying (vr);
return; return;
...@@ -3497,16 +3194,6 @@ extract_range_from_unary_expr (value_range *vr, ...@@ -3497,16 +3194,6 @@ extract_range_from_unary_expr (value_range *vr,
|| vr0.type == VR_ANTI_RANGE) || vr0.type == VR_ANTI_RANGE)
&& TREE_CODE (vr0.min) == INTEGER_CST && TREE_CODE (vr0.min) == INTEGER_CST
&& TREE_CODE (vr0.max) == INTEGER_CST && TREE_CODE (vr0.max) == INTEGER_CST
&& (!is_overflow_infinity (vr0.min)
|| (vr0.type == VR_RANGE
&& TYPE_PRECISION (outer_type) > TYPE_PRECISION (inner_type)
&& needs_overflow_infinity (outer_type)
&& supports_overflow_infinity (outer_type)))
&& (!is_overflow_infinity (vr0.max)
|| (vr0.type == VR_RANGE
&& TYPE_PRECISION (outer_type) > TYPE_PRECISION (inner_type)
&& needs_overflow_infinity (outer_type)
&& supports_overflow_infinity (outer_type)))
&& (TYPE_PRECISION (outer_type) >= TYPE_PRECISION (inner_type) && (TYPE_PRECISION (outer_type) >= TYPE_PRECISION (inner_type)
|| (vr0.type == VR_RANGE || (vr0.type == VR_RANGE
&& integer_zerop (int_const_binop (RSHIFT_EXPR, && integer_zerop (int_const_binop (RSHIFT_EXPR,
...@@ -3514,14 +3201,8 @@ extract_range_from_unary_expr (value_range *vr, ...@@ -3514,14 +3201,8 @@ extract_range_from_unary_expr (value_range *vr,
size_int (TYPE_PRECISION (outer_type))))))) size_int (TYPE_PRECISION (outer_type)))))))
{ {
tree new_min, new_max; tree new_min, new_max;
if (is_overflow_infinity (vr0.min))
new_min = negative_overflow_infinity (outer_type);
else
new_min = force_fit_type (outer_type, wi::to_widest (vr0.min), new_min = force_fit_type (outer_type, wi::to_widest (vr0.min),
0, false); 0, false);
if (is_overflow_infinity (vr0.max))
new_max = positive_overflow_infinity (outer_type);
else
new_max = force_fit_type (outer_type, wi::to_widest (vr0.max), new_max = force_fit_type (outer_type, wi::to_widest (vr0.max),
0, false); 0, false);
set_and_canonicalize_value_range (vr, vr0.type, set_and_canonicalize_value_range (vr, vr0.type,
...@@ -3568,36 +3249,15 @@ extract_range_from_unary_expr (value_range *vr, ...@@ -3568,36 +3249,15 @@ extract_range_from_unary_expr (value_range *vr,
/* ABS_EXPR may flip the range around, if the original range /* ABS_EXPR may flip the range around, if the original range
included negative values. */ included negative values. */
if (is_overflow_infinity (vr0.min)) if (!vrp_val_is_min (vr0.min))
min = positive_overflow_infinity (type);
else if (!vrp_val_is_min (vr0.min))
min = fold_unary_to_constant (code, type, vr0.min); min = fold_unary_to_constant (code, type, vr0.min);
else if (!needs_overflow_infinity (type))
min = TYPE_MAX_VALUE (type);
else if (supports_overflow_infinity (type))
min = positive_overflow_infinity (type);
else else
{ min = TYPE_MAX_VALUE (type);
set_value_range_to_varying (vr);
return;
}
if (is_overflow_infinity (vr0.max)) if (!vrp_val_is_min (vr0.max))
max = positive_overflow_infinity (type);
else if (!vrp_val_is_min (vr0.max))
max = fold_unary_to_constant (code, type, vr0.max); max = fold_unary_to_constant (code, type, vr0.max);
else if (!needs_overflow_infinity (type))
max = TYPE_MAX_VALUE (type);
else if (supports_overflow_infinity (type)
/* We shouldn't generate [+INF, +INF] as set_value_range
doesn't like this and ICEs. */
&& !is_positive_overflow_infinity (min))
max = positive_overflow_infinity (type);
else else
{ max = TYPE_MAX_VALUE (type);
set_value_range_to_varying (vr);
return;
}
cmp = compare_values (min, max); cmp = compare_values (min, max);
...@@ -3625,13 +3285,8 @@ extract_range_from_unary_expr (value_range *vr, ...@@ -3625,13 +3285,8 @@ extract_range_from_unary_expr (value_range *vr,
: type_min_value); : type_min_value);
} }
else else
{
if (overflow_infinity_range_p (&vr0))
min = negative_overflow_infinity (type);
else
min = TYPE_MIN_VALUE (type); min = TYPE_MIN_VALUE (type);
} }
}
else else
{ {
/* All else has failed, so create the range [0, INF], even for /* All else has failed, so create the range [0, INF], even for
...@@ -3639,17 +3294,6 @@ extract_range_from_unary_expr (value_range *vr, ...@@ -3639,17 +3294,6 @@ extract_range_from_unary_expr (value_range *vr,
anti-range. */ anti-range. */
vr0.type = VR_RANGE; vr0.type = VR_RANGE;
min = build_int_cst (type, 0); min = build_int_cst (type, 0);
if (needs_overflow_infinity (type))
{
if (supports_overflow_infinity (type))
max = positive_overflow_infinity (type);
else
{
set_value_range_to_varying (vr);
return;
}
}
else
max = TYPE_MAX_VALUE (type); max = TYPE_MAX_VALUE (type);
} }
} }
...@@ -3763,7 +3407,7 @@ extract_range_from_comparison (value_range *vr, enum tree_code code, ...@@ -3763,7 +3407,7 @@ extract_range_from_comparison (value_range *vr, enum tree_code code,
when we don't have an infinity. So we have to ignore a result when we don't have an infinity. So we have to ignore a result
which relies on overflow. */ which relies on overflow. */
if (val && !is_overflow_infinity (val) && !sop) if (val && !sop)
{ {
/* Since this expression was found on the RHS of an assignment, /* Since this expression was found on the RHS of an assignment,
its type may be different from _Bool. Convert VAL to EXPR's its type may be different from _Bool. Convert VAL to EXPR's
...@@ -3933,20 +3577,17 @@ extract_range_basic (value_range *vr, gimple *stmt) ...@@ -3933,20 +3577,17 @@ extract_range_basic (value_range *vr, gimple *stmt)
value_range *vr0 = get_value_range (arg); value_range *vr0 = get_value_range (arg);
/* If arg is non-zero, then ffs or popcount /* If arg is non-zero, then ffs or popcount
are non-zero. */ are non-zero. */
if (((vr0->type == VR_RANGE if ((vr0->type == VR_RANGE
&& range_includes_zero_p (vr0->min, vr0->max) == 0) && range_includes_zero_p (vr0->min, vr0->max) == 0)
|| (vr0->type == VR_ANTI_RANGE || (vr0->type == VR_ANTI_RANGE
&& range_includes_zero_p (vr0->min, vr0->max) == 1)) && range_includes_zero_p (vr0->min, vr0->max) == 1))
&& !is_overflow_infinity (vr0->min)
&& !is_overflow_infinity (vr0->max))
mini = 1; mini = 1;
/* If some high bits are known to be zero, /* If some high bits are known to be zero,
we can decrease the maximum. */ we can decrease the maximum. */
if (vr0->type == VR_RANGE if (vr0->type == VR_RANGE
&& TREE_CODE (vr0->max) == INTEGER_CST && TREE_CODE (vr0->max) == INTEGER_CST
&& !operand_less_p (vr0->min, && !operand_less_p (vr0->min,
build_zero_cst (TREE_TYPE (vr0->min))) build_zero_cst (TREE_TYPE (vr0->min))))
&& !is_overflow_infinity (vr0->max))
maxi = tree_floor_log2 (vr0->max) + 1; maxi = tree_floor_log2 (vr0->max) + 1;
} }
goto bitop_builtin; goto bitop_builtin;
...@@ -3980,16 +3621,14 @@ extract_range_basic (value_range *vr, gimple *stmt) ...@@ -3980,16 +3621,14 @@ extract_range_basic (value_range *vr, gimple *stmt)
/* From clz of VR_RANGE minimum we can compute /* From clz of VR_RANGE minimum we can compute
result maximum. */ result maximum. */
if (vr0->type == VR_RANGE if (vr0->type == VR_RANGE
&& TREE_CODE (vr0->min) == INTEGER_CST && TREE_CODE (vr0->min) == INTEGER_CST)
&& !is_overflow_infinity (vr0->min))
{ {
maxi = prec - 1 - tree_floor_log2 (vr0->min); maxi = prec - 1 - tree_floor_log2 (vr0->min);
if (maxi != prec) if (maxi != prec)
mini = 0; mini = 0;
} }
else if (vr0->type == VR_ANTI_RANGE else if (vr0->type == VR_ANTI_RANGE
&& integer_zerop (vr0->min) && integer_zerop (vr0->min))
&& !is_overflow_infinity (vr0->min))
{ {
maxi = prec - 1; maxi = prec - 1;
mini = 0; mini = 0;
...@@ -3999,8 +3638,7 @@ extract_range_basic (value_range *vr, gimple *stmt) ...@@ -3999,8 +3638,7 @@ extract_range_basic (value_range *vr, gimple *stmt)
/* From clz of VR_RANGE maximum we can compute /* From clz of VR_RANGE maximum we can compute
result minimum. */ result minimum. */
if (vr0->type == VR_RANGE if (vr0->type == VR_RANGE
&& TREE_CODE (vr0->max) == INTEGER_CST && TREE_CODE (vr0->max) == INTEGER_CST)
&& !is_overflow_infinity (vr0->max))
{ {
mini = prec - 1 - tree_floor_log2 (vr0->max); mini = prec - 1 - tree_floor_log2 (vr0->max);
if (mini == prec) if (mini == prec)
...@@ -4039,11 +3677,10 @@ extract_range_basic (value_range *vr, gimple *stmt) ...@@ -4039,11 +3677,10 @@ extract_range_basic (value_range *vr, gimple *stmt)
{ {
value_range *vr0 = get_value_range (arg); value_range *vr0 = get_value_range (arg);
/* If arg is non-zero, then use [0, prec - 1]. */ /* If arg is non-zero, then use [0, prec - 1]. */
if (((vr0->type == VR_RANGE if ((vr0->type == VR_RANGE
&& integer_nonzerop (vr0->min)) && integer_nonzerop (vr0->min))
|| (vr0->type == VR_ANTI_RANGE || (vr0->type == VR_ANTI_RANGE
&& integer_zerop (vr0->min))) && integer_zerop (vr0->min)))
&& !is_overflow_infinity (vr0->min))
{ {
mini = 0; mini = 0;
maxi = prec - 1; maxi = prec - 1;
...@@ -4051,8 +3688,7 @@ extract_range_basic (value_range *vr, gimple *stmt) ...@@ -4051,8 +3688,7 @@ extract_range_basic (value_range *vr, gimple *stmt)
/* If some high bits are known to be zero, /* If some high bits are known to be zero,
we can decrease the result maximum. */ we can decrease the result maximum. */
if (vr0->type == VR_RANGE if (vr0->type == VR_RANGE
&& TREE_CODE (vr0->max) == INTEGER_CST && TREE_CODE (vr0->max) == INTEGER_CST)
&& !is_overflow_infinity (vr0->max))
{ {
maxi = tree_floor_log2 (vr0->max); maxi = tree_floor_log2 (vr0->max);
/* For vr0 [0, 0] give up. */ /* For vr0 [0, 0] give up. */
...@@ -4239,8 +3875,7 @@ extract_range_basic (value_range *vr, gimple *stmt) ...@@ -4239,8 +3875,7 @@ extract_range_basic (value_range *vr, gimple *stmt)
} }
if (INTEGRAL_TYPE_P (type) if (INTEGRAL_TYPE_P (type)
&& gimple_stmt_nonnegative_warnv_p (stmt, &sop)) && gimple_stmt_nonnegative_warnv_p (stmt, &sop))
set_value_range_to_nonnegative (vr, type, set_value_range_to_nonnegative (vr, type);
sop || stmt_overflow_infinity (stmt));
else if (vrp_stmt_computes_nonzero (stmt, &sop) else if (vrp_stmt_computes_nonzero (stmt, &sop)
&& !sop) && !sop)
set_value_range_to_nonnull (vr, type); set_value_range_to_nonnull (vr, type);
...@@ -4406,11 +4041,9 @@ adjust_range_with_scev (value_range *vr, struct loop *loop, ...@@ -4406,11 +4041,9 @@ adjust_range_with_scev (value_range *vr, struct loop *loop,
because the loop may exit immediately. Overflow could because the loop may exit immediately. Overflow could
happen in the plus expression in this case. */ happen in the plus expression in this case. */
if ((dir == EV_DIR_DECREASES if ((dir == EV_DIR_DECREASES
&& (is_negative_overflow_infinity (maxvr.min) && compare_values (maxvr.min, initvr.min) != -1)
|| compare_values (maxvr.min, initvr.min) != -1))
|| (dir == EV_DIR_GROWS || (dir == EV_DIR_GROWS
&& (is_positive_overflow_infinity (maxvr.max) && compare_values (maxvr.max, initvr.max) != 1))
|| compare_values (maxvr.max, initvr.max) != 1)))
return; return;
tmin = maxvr.min; tmin = maxvr.min;
...@@ -4446,11 +4079,8 @@ adjust_range_with_scev (value_range *vr, struct loop *loop, ...@@ -4446,11 +4079,8 @@ adjust_range_with_scev (value_range *vr, struct loop *loop,
max = init; max = init;
/* According to the loop information, the variable does not /* According to the loop information, the variable does not
overflow. If we think it does, probably because of an overflow. */
overflow due to arithmetic on a different INF value, if (compare_values (min, tmin) == -1)
reset now. */
if (is_negative_overflow_infinity (min)
|| compare_values (min, tmin) == -1)
min = tmin; min = tmin;
} }
...@@ -4460,8 +4090,7 @@ adjust_range_with_scev (value_range *vr, struct loop *loop, ...@@ -4460,8 +4090,7 @@ adjust_range_with_scev (value_range *vr, struct loop *loop,
if (compare_values (init, min) == 1) if (compare_values (init, min) == 1)
min = init; min = init;
if (is_positive_overflow_infinity (max) if (compare_values (tmax, max) == -1)
|| compare_values (tmax, max) == -1)
max = tmax; max = tmax;
} }
} }
...@@ -4472,20 +4101,15 @@ adjust_range_with_scev (value_range *vr, struct loop *loop, ...@@ -4472,20 +4101,15 @@ adjust_range_with_scev (value_range *vr, struct loop *loop,
greater than the maximum, we fail conservatively. greater than the maximum, we fail conservatively.
This should happen only in unreachable This should happen only in unreachable
parts of code, or for invalid programs. */ parts of code, or for invalid programs. */
if (compare_values (min, max) == 1 if (compare_values (min, max) == 1)
|| (is_negative_overflow_infinity (min)
&& is_positive_overflow_infinity (max)))
return; return;
/* Even for valid range info, sometimes overflow flag will leak in. /* Even for valid range info, sometimes overflow flag will leak in.
As GIMPLE IL should have no constants with TREE_OVERFLOW set, we As GIMPLE IL should have no constants with TREE_OVERFLOW set, we
drop them except for +-overflow_infinity which still need special drop them. */
handling in vrp pass. */ if (TREE_OVERFLOW_P (min))
if (TREE_OVERFLOW_P (min)
&& ! is_negative_overflow_infinity (min))
min = drop_tree_overflow (min); min = drop_tree_overflow (min);
if (TREE_OVERFLOW_P (max) if (TREE_OVERFLOW_P (max))
&& ! is_positive_overflow_infinity (max))
max = drop_tree_overflow (max); max = drop_tree_overflow (max);
set_value_range (vr, VR_RANGE, min, max, vr->equiv); set_value_range (vr, VR_RANGE, min, max, vr->equiv);
...@@ -4551,10 +4175,6 @@ compare_ranges (enum tree_code comp, value_range *vr0, value_range *vr1, ...@@ -4551,10 +4175,6 @@ compare_ranges (enum tree_code comp, value_range *vr0, value_range *vr1,
return NULL_TREE; return NULL_TREE;
} }
if (!usable_range_p (vr0, strict_overflow_p)
|| !usable_range_p (vr1, strict_overflow_p))
return NULL_TREE;
/* Simplify processing. If COMP is GT_EXPR or GE_EXPR, switch the /* Simplify processing. If COMP is GT_EXPR or GE_EXPR, switch the
operands around and change the comparison code. */ operands around and change the comparison code. */
if (comp == GT_EXPR || comp == GE_EXPR) if (comp == GT_EXPR || comp == GE_EXPR)
...@@ -4626,23 +4246,13 @@ compare_ranges (enum tree_code comp, value_range *vr0, value_range *vr1, ...@@ -4626,23 +4246,13 @@ compare_ranges (enum tree_code comp, value_range *vr0, value_range *vr1,
tst = compare_values_warnv (vr0->max, vr1->min, strict_overflow_p); tst = compare_values_warnv (vr0->max, vr1->min, strict_overflow_p);
if ((comp == LT_EXPR && tst == -1) if ((comp == LT_EXPR && tst == -1)
|| (comp == LE_EXPR && (tst == -1 || tst == 0))) || (comp == LE_EXPR && (tst == -1 || tst == 0)))
{
if (overflow_infinity_range_p (vr0)
|| overflow_infinity_range_p (vr1))
*strict_overflow_p = true;
return boolean_true_node; return boolean_true_node;
}
/* If VR0 is to the right of VR1, return false. */ /* If VR0 is to the right of VR1, return false. */
tst = compare_values_warnv (vr0->min, vr1->max, strict_overflow_p); tst = compare_values_warnv (vr0->min, vr1->max, strict_overflow_p);
if ((comp == LT_EXPR && (tst == 0 || tst == 1)) if ((comp == LT_EXPR && (tst == 0 || tst == 1))
|| (comp == LE_EXPR && tst == 1)) || (comp == LE_EXPR && tst == 1))
{
if (overflow_infinity_range_p (vr0)
|| overflow_infinity_range_p (vr1))
*strict_overflow_p = true;
return boolean_false_node; return boolean_false_node;
}
/* Otherwise, we don't know. */ /* Otherwise, we don't know. */
return NULL_TREE; return NULL_TREE;
...@@ -4685,9 +4295,6 @@ compare_range_with_value (enum tree_code comp, value_range *vr, tree val, ...@@ -4685,9 +4295,6 @@ compare_range_with_value (enum tree_code comp, value_range *vr, tree val,
return NULL_TREE; return NULL_TREE;
} }
if (!usable_range_p (vr, strict_overflow_p))
return NULL_TREE;
if (comp == EQ_EXPR) if (comp == EQ_EXPR)
{ {
/* EQ_EXPR may only be computed if VR represents exactly /* EQ_EXPR may only be computed if VR represents exactly
...@@ -4730,21 +4337,13 @@ compare_range_with_value (enum tree_code comp, value_range *vr, tree val, ...@@ -4730,21 +4337,13 @@ compare_range_with_value (enum tree_code comp, value_range *vr, tree val,
tst = compare_values_warnv (vr->max, val, strict_overflow_p); tst = compare_values_warnv (vr->max, val, strict_overflow_p);
if ((comp == LT_EXPR && tst == -1) if ((comp == LT_EXPR && tst == -1)
|| (comp == LE_EXPR && (tst == -1 || tst == 0))) || (comp == LE_EXPR && (tst == -1 || tst == 0)))
{
if (overflow_infinity_range_p (vr))
*strict_overflow_p = true;
return boolean_true_node; return boolean_true_node;
}
/* If VR is to the right of VAL, return false. */ /* If VR is to the right of VAL, return false. */
tst = compare_values_warnv (vr->min, val, strict_overflow_p); tst = compare_values_warnv (vr->min, val, strict_overflow_p);
if ((comp == LT_EXPR && (tst == 0 || tst == 1)) if ((comp == LT_EXPR && (tst == 0 || tst == 1))
|| (comp == LE_EXPR && tst == 1)) || (comp == LE_EXPR && tst == 1))
{
if (overflow_infinity_range_p (vr))
*strict_overflow_p = true;
return boolean_false_node; return boolean_false_node;
}
/* Otherwise, we don't know. */ /* Otherwise, we don't know. */
return NULL_TREE; return NULL_TREE;
...@@ -4757,21 +4356,13 @@ compare_range_with_value (enum tree_code comp, value_range *vr, tree val, ...@@ -4757,21 +4356,13 @@ compare_range_with_value (enum tree_code comp, value_range *vr, tree val,
tst = compare_values_warnv (vr->min, val, strict_overflow_p); tst = compare_values_warnv (vr->min, val, strict_overflow_p);
if ((comp == GT_EXPR && tst == 1) if ((comp == GT_EXPR && tst == 1)
|| (comp == GE_EXPR && (tst == 0 || tst == 1))) || (comp == GE_EXPR && (tst == 0 || tst == 1)))
{
if (overflow_infinity_range_p (vr))
*strict_overflow_p = true;
return boolean_true_node; return boolean_true_node;
}
/* If VR is to the left of VAL, return false. */ /* If VR is to the left of VAL, return false. */
tst = compare_values_warnv (vr->max, val, strict_overflow_p); tst = compare_values_warnv (vr->max, val, strict_overflow_p);
if ((comp == GT_EXPR && (tst == -1 || tst == 0)) if ((comp == GT_EXPR && (tst == -1 || tst == 0))
|| (comp == GE_EXPR && tst == -1)) || (comp == GE_EXPR && tst == -1))
{
if (overflow_infinity_range_p (vr))
*strict_overflow_p = true;
return boolean_false_node; return boolean_false_node;
}
/* Otherwise, we don't know. */ /* Otherwise, we don't know. */
return NULL_TREE; return NULL_TREE;
...@@ -4806,9 +4397,7 @@ dump_value_range (FILE *file, const value_range *vr) ...@@ -4806,9 +4397,7 @@ dump_value_range (FILE *file, const value_range *vr)
fprintf (file, "%s[", (vr->type == VR_ANTI_RANGE) ? "~" : ""); fprintf (file, "%s[", (vr->type == VR_ANTI_RANGE) ? "~" : "");
if (is_negative_overflow_infinity (vr->min)) if (INTEGRAL_TYPE_P (type)
fprintf (file, "-INF(OVF)");
else if (INTEGRAL_TYPE_P (type)
&& !TYPE_UNSIGNED (type) && !TYPE_UNSIGNED (type)
&& vrp_val_is_min (vr->min)) && vrp_val_is_min (vr->min))
fprintf (file, "-INF"); fprintf (file, "-INF");
...@@ -4817,9 +4406,7 @@ dump_value_range (FILE *file, const value_range *vr) ...@@ -4817,9 +4406,7 @@ dump_value_range (FILE *file, const value_range *vr)
fprintf (file, ", "); fprintf (file, ", ");
if (is_positive_overflow_infinity (vr->max)) if (INTEGRAL_TYPE_P (type)
fprintf (file, "+INF(OVF)");
else if (INTEGRAL_TYPE_P (type)
&& vrp_val_is_max (vr->max)) && vrp_val_is_max (vr->max))
fprintf (file, "+INF"); fprintf (file, "+INF");
else else
...@@ -9854,8 +9441,7 @@ simplify_bit_ops_using_ranges (gimple_stmt_iterator *gsi, gimple *stmt) ...@@ -9854,8 +9441,7 @@ simplify_bit_ops_using_ranges (gimple_stmt_iterator *gsi, gimple *stmt)
static tree static tree
test_for_singularity (enum tree_code cond_code, tree op0, test_for_singularity (enum tree_code cond_code, tree op0,
tree op1, value_range *vr, tree op1, value_range *vr)
bool *strict_overflow_p)
{ {
tree min = NULL; tree min = NULL;
tree max = NULL; tree max = NULL;
...@@ -9869,7 +9455,7 @@ test_for_singularity (enum tree_code cond_code, tree op0, ...@@ -9869,7 +9455,7 @@ test_for_singularity (enum tree_code cond_code, tree op0,
min = TYPE_MIN_VALUE (TREE_TYPE (op0)); min = TYPE_MIN_VALUE (TREE_TYPE (op0));
max = op1; max = op1;
if (cond_code == LT_EXPR && !is_overflow_infinity (max)) if (cond_code == LT_EXPR)
{ {
tree one = build_int_cst (TREE_TYPE (op0), 1); tree one = build_int_cst (TREE_TYPE (op0), 1);
max = fold_build2 (MINUS_EXPR, TREE_TYPE (op0), max, one); max = fold_build2 (MINUS_EXPR, TREE_TYPE (op0), max, one);
...@@ -9884,7 +9470,7 @@ test_for_singularity (enum tree_code cond_code, tree op0, ...@@ -9884,7 +9470,7 @@ test_for_singularity (enum tree_code cond_code, tree op0,
max = TYPE_MAX_VALUE (TREE_TYPE (op0)); max = TYPE_MAX_VALUE (TREE_TYPE (op0));
min = op1; min = op1;
if (cond_code == GT_EXPR && !is_overflow_infinity (min)) if (cond_code == GT_EXPR)
{ {
tree one = build_int_cst (TREE_TYPE (op0), 1); tree one = build_int_cst (TREE_TYPE (op0), 1);
min = fold_build2 (PLUS_EXPR, TREE_TYPE (op0), min, one); min = fold_build2 (PLUS_EXPR, TREE_TYPE (op0), min, one);
...@@ -9906,17 +9492,8 @@ test_for_singularity (enum tree_code cond_code, tree op0, ...@@ -9906,17 +9492,8 @@ test_for_singularity (enum tree_code cond_code, tree op0,
then there is only one value which can satisfy the condition, then there is only one value which can satisfy the condition,
return that value. */ return that value. */
if (operand_equal_p (min, max, 0) && is_gimple_min_invariant (min)) if (operand_equal_p (min, max, 0) && is_gimple_min_invariant (min))
{
if ((cond_code == LE_EXPR || cond_code == LT_EXPR)
&& is_overflow_infinity (vr->max))
*strict_overflow_p = true;
if ((cond_code == GE_EXPR || cond_code == GT_EXPR)
&& is_overflow_infinity (vr->min))
*strict_overflow_p = true;
return min; return min;
} }
}
return NULL; return NULL;
} }
...@@ -9995,12 +9572,8 @@ simplify_cond_using_ranges_1 (gcond *stmt) ...@@ -9995,12 +9572,8 @@ simplify_cond_using_ranges_1 (gcond *stmt)
able to simplify this conditional. */ able to simplify this conditional. */
if (vr->type == VR_RANGE) if (vr->type == VR_RANGE)
{ {
enum warn_strict_overflow_code wc = WARN_STRICT_OVERFLOW_COMPARISON; tree new_tree = test_for_singularity (cond_code, op0, op1, vr);
bool sop = false; if (new_tree)
tree new_tree = test_for_singularity (cond_code, op0, op1, vr, &sop);
if (new_tree
&& (!sop || TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (op0))))
{ {
if (dump_file) if (dump_file)
{ {
...@@ -10021,30 +9594,16 @@ simplify_cond_using_ranges_1 (gcond *stmt) ...@@ -10021,30 +9594,16 @@ simplify_cond_using_ranges_1 (gcond *stmt)
fprintf (dump_file, "\n"); fprintf (dump_file, "\n");
} }
if (sop && issue_strict_overflow_warning (wc))
{
location_t location = input_location;
if (gimple_has_location (stmt))
location = gimple_location (stmt);
warning_at (location, OPT_Wstrict_overflow,
"assuming signed overflow does not occur when "
"simplifying conditional");
}
return true; return true;
} }
/* Try again after inverting the condition. We only deal /* Try again after inverting the condition. We only deal
with integral types here, so no need to worry about with integral types here, so no need to worry about
issues with inverting FP comparisons. */ issues with inverting FP comparisons. */
sop = false;
new_tree = test_for_singularity new_tree = test_for_singularity
(invert_tree_comparison (cond_code, false), (invert_tree_comparison (cond_code, false),
op0, op1, vr, &sop); op0, op1, vr);
if (new_tree)
if (new_tree
&& (!sop || TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (op0))))
{ {
if (dump_file) if (dump_file)
{ {
...@@ -10065,17 +9624,6 @@ simplify_cond_using_ranges_1 (gcond *stmt) ...@@ -10065,17 +9624,6 @@ simplify_cond_using_ranges_1 (gcond *stmt)
fprintf (dump_file, "\n"); fprintf (dump_file, "\n");
} }
if (sop && issue_strict_overflow_warning (wc))
{
location_t location = input_location;
if (gimple_has_location (stmt))
location = gimple_location (stmt);
warning_at (location, OPT_Wstrict_overflow,
"assuming signed overflow does not occur when "
"simplifying conditional");
}
return true; return true;
} }
} }
...@@ -10128,33 +9676,8 @@ simplify_cond_using_ranges_2 (gcond *stmt) ...@@ -10128,33 +9676,8 @@ simplify_cond_using_ranges_2 (gcond *stmt)
&& range_fits_type_p (vr, && range_fits_type_p (vr,
TYPE_PRECISION (TREE_TYPE (op0)), TYPE_PRECISION (TREE_TYPE (op0)),
TYPE_SIGN (TREE_TYPE (op0))) TYPE_SIGN (TREE_TYPE (op0)))
&& int_fits_type_p (op1, TREE_TYPE (innerop)) && int_fits_type_p (op1, TREE_TYPE (innerop)))
/* The range must not have overflowed, or if it did overflow
we must not be wrapping/trapping overflow and optimizing
with strict overflow semantics. */
&& ((!is_negative_overflow_infinity (vr->min)
&& !is_positive_overflow_infinity (vr->max))
|| TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (innerop))))
{
/* If the range overflowed and the user has asked for warnings
when strict overflow semantics were used to optimize code,
issue an appropriate warning. */
if (cond_code != EQ_EXPR && cond_code != NE_EXPR
&& (is_negative_overflow_infinity (vr->min)
|| is_positive_overflow_infinity (vr->max))
&& issue_strict_overflow_warning (WARN_STRICT_OVERFLOW_CONDITIONAL))
{ {
location_t location;
if (!gimple_has_location (stmt))
location = input_location;
else
location = gimple_location (stmt);
warning_at (location, OPT_Wstrict_overflow,
"assuming signed overflow does not occur when "
"simplifying conditional");
}
tree newconst = fold_convert (TREE_TYPE (innerop), op1); tree newconst = fold_convert (TREE_TYPE (innerop), op1);
gimple_cond_set_lhs (stmt, innerop); gimple_cond_set_lhs (stmt, innerop);
gimple_cond_set_rhs (stmt, newconst); gimple_cond_set_rhs (stmt, newconst);
......
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