{
tree tcmp;
+ fold_defer_overflow_warnings ();
+
tcmp = fold_binary_to_constant (LT_EXPR, boolean_type_node, val, val2);
+
+ fold_undefer_and_ignore_overflow_warnings ();
+
if (!tcmp)
return -2;
&& !supports_overflow_infinity (TREE_TYPE (res)))
return NULL_TREE;
- /* We have to punt on subtracting infinities of the same sign,
- since we can't tell what the sign of the result should
- be. */
- if (code == MINUS_EXPR
- && sgn1 == sgn2
+ /* 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
operations handled by extract_range_from_binary_expr.
Among them, only multiplication, addition and subtraction
if ((code == MULT_EXPR && sgn1 == sgn2)
/* For addition, the operands must be of the same sign
to yield an overflow. Its sign is therefore that
- of one of the operands, for example the first. */
- || (code == PLUS_EXPR && sgn1 > 0)
+ of one of the operands, for example the first. For
+ infinite operands X + -INF is negative, not positive. */
+ || (code == PLUS_EXPR
+ && (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
therefore that of the first operand or the opposite of
&& (sgn1 >= 0
? !is_positive_overflow_infinity (val2)
: is_negative_overflow_infinity (val2)))
+ /* We only get in here with positive shift count, so the
+ overflow direction is the same as the sign of val1.
+ Actually rshift does not overflow at all, but we only
+ handle the case of shifting overflowed -INF and +INF. */
+ || (code == RSHIFT_EXPR
+ && sgn1 >= 0)
/* For division, the only case is -INF / -1 = +INF. */
|| code == TRUNC_DIV_EXPR
|| code == FLOOR_DIV_EXPR
&& code != CEIL_DIV_EXPR
&& code != EXACT_DIV_EXPR
&& code != ROUND_DIV_EXPR
+ && code != RSHIFT_EXPR
&& code != MIN_EXPR
&& code != MAX_EXPR
&& code != BIT_AND_EXPR
|| code == FLOOR_DIV_EXPR
|| code == CEIL_DIV_EXPR
|| code == EXACT_DIV_EXPR
- || code == ROUND_DIV_EXPR)
+ || code == ROUND_DIV_EXPR
+ || code == RSHIFT_EXPR)
{
tree val[4];
size_t i;
return;
}
+ /* If we have a RSHIFT_EXPR with any shift values outside [0..prec-1],
+ then drop to VR_VARYING. Outside of this range we get undefined
+ behaviour from the shift operation. We cannot even trust
+ SHIFT_COUNT_TRUNCATED at this stage, because that applies to rtl
+ shifts, and the operation at the tree level may be widened. */
+ if (code == RSHIFT_EXPR)
+ {
+ if (vr1.type == VR_ANTI_RANGE
+ || !vrp_expr_computes_nonnegative (op1, &sop)
+ || (operand_less_p
+ (build_int_cst (TREE_TYPE (vr1.max),
+ TYPE_PRECISION (TREE_TYPE (expr)) - 1),
+ vr1.max) != 0))
+ {
+ set_value_range_to_varying (vr);
+ return;
+ }
+ }
+
/* Multiplications and divisions are a bit tricky to handle,
depending on the mix of signs we have in the two ranges, we
need to operate on different values to get the minimum and
the new range. */
/* Divisions by zero result in a VARYING value. */
- if (code != MULT_EXPR
- && (vr0.type == VR_ANTI_RANGE || range_includes_zero_p (&vr1)))
+ else if (code != MULT_EXPR
+ && (vr0.type == VR_ANTI_RANGE || range_includes_zero_p (&vr1)))
{
set_value_range_to_varying (vr);
return;
return;
}
+ /* We punt if:
+ 1) [-INF, +INF]
+ 2) [-INF, +-INF(OVF)]
+ 3) [+-INF(OVF), +INF]
+ 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 ((min == TYPE_MIN_VALUE (TREE_TYPE (min))
- || is_negative_overflow_infinity (min))
+ || is_overflow_infinity (min))
&& (max == TYPE_MAX_VALUE (TREE_TYPE (max))
- || is_positive_overflow_infinity (max)))
+ || is_overflow_infinity (max)))
{
set_value_range_to_varying (vr);
return;
if (COMPARISON_CLASS_P (cond))
{
tree a = build2 (ASSERT_EXPR, TREE_TYPE (v), v, cond);
- assertion = build2 (GIMPLE_MODIFY_STMT, TREE_TYPE (v), n, a);
+ assertion = build_gimple_modify_stmt (n, a);
}
else if (TREE_CODE (cond) == TRUTH_NOT_EXPR)
{
/* Given !V, build the assignment N = false. */
tree op0 = TREE_OPERAND (cond, 0);
gcc_assert (op0 == v);
- assertion = build2 (GIMPLE_MODIFY_STMT, TREE_TYPE (v), n,
- boolean_false_node);
+ assertion = build_gimple_modify_stmt (n, boolean_false_node);
}
else if (TREE_CODE (cond) == SSA_NAME)
{
/* Given V, build the assignment N = true. */
gcc_assert (v == cond);
- assertion = build2 (GIMPLE_MODIFY_STMT,
- TREE_TYPE (v), n, boolean_true_node);
+ assertion = build_gimple_modify_stmt (n, boolean_true_node);
}
else
gcc_unreachable ();
}
else if (TREE_CODE (rhs) == NOP_EXPR
|| TREE_CODE (rhs) == CONVERT_EXPR
- || TREE_CODE (rhs) == VIEW_CONVERT_EXPR
|| TREE_CODE (rhs) == NON_LVALUE_EXPR)
{
/* Recurse through the type conversion. */
| TODO_ggc_collect
| TODO_verify_ssa
| TODO_dump_func
- | TODO_update_ssa
- | TODO_update_smt_usage, /* todo_flags_finish */
+ | TODO_update_ssa, /* todo_flags_finish */
0 /* letter */
};