fold-const.c (tree_unary_nonnegative_warnv_p): Make it public.
2008-03-28 Rafael Espindola <espindola@google.com> * fold-const.c (tree_unary_nonnegative_warnv_p): Make it public. (tree_binary_nonnegative_warnv_p): Make it public. (tree_single_nonnegative_warnv_p): Make it public. (tree_invalid_nonnegative_warnv_p): Make it public. (tree_unary_nonzero_warnv_p): Make it public. (tree_binary_nonzero_warnv_p): Make it public (tree_single_nonzero_warnv_p): Make it public. * tree-vrp.c (vrp_evaluate_conditional_warnv_with_ops): New function. (extract_range_from_binary_expr): Split the expr argument. (extract_range_from_unary_expr): Split the expr argument. (extract_range_from_comparison): Split the expr argument. (extract_range_from_expr): Use the new aux functions. (vrp_evaluate_conditional_warnv): Use vrp_evaluate_conditional_warnv_with_ops. * tree.h (tree_unary_nonzero_warnv_p): Declare. (tree_binary_nonzero_warnv_p): Declare. (tree_single_nonzero_warnv_p): Declare. (tree_expr_nonzero_warnv_p): Declare. (tree_unary_nonnegative_warnv_p): Declare. (tree_binary_nonnegative_warnv_p): Declare. (tree_single_nonnegative_warnv_p): Declare. (tree_invalid_nonnegative_warnv_p): Declare. From-SVN: r133681
This commit is contained in:
parent
2ab8dbf48e
commit
2d3cd5d5ab
@ -1,3 +1,28 @@
|
||||
2008-03-28 Rafael Espindola <espindola@google.com>
|
||||
|
||||
* fold-const.c (tree_unary_nonnegative_warnv_p): Make it public.
|
||||
(tree_binary_nonnegative_warnv_p): Make it public.
|
||||
(tree_single_nonnegative_warnv_p): Make it public.
|
||||
(tree_invalid_nonnegative_warnv_p): Make it public.
|
||||
(tree_unary_nonzero_warnv_p): Make it public.
|
||||
(tree_binary_nonzero_warnv_p): Make it public
|
||||
(tree_single_nonzero_warnv_p): Make it public.
|
||||
* tree-vrp.c (vrp_evaluate_conditional_warnv_with_ops): New function.
|
||||
(extract_range_from_binary_expr): Split the expr argument.
|
||||
(extract_range_from_unary_expr): Split the expr argument.
|
||||
(extract_range_from_comparison): Split the expr argument.
|
||||
(extract_range_from_expr): Use the new aux functions.
|
||||
(vrp_evaluate_conditional_warnv): Use
|
||||
vrp_evaluate_conditional_warnv_with_ops.
|
||||
* tree.h (tree_unary_nonzero_warnv_p): Declare.
|
||||
(tree_binary_nonzero_warnv_p): Declare.
|
||||
(tree_single_nonzero_warnv_p): Declare.
|
||||
(tree_expr_nonzero_warnv_p): Declare.
|
||||
(tree_unary_nonnegative_warnv_p): Declare.
|
||||
(tree_binary_nonnegative_warnv_p): Declare.
|
||||
(tree_single_nonnegative_warnv_p): Declare.
|
||||
(tree_invalid_nonnegative_warnv_p): Declare.
|
||||
|
||||
2008-03-28 Richard Guenther <rguenther@suse.de>
|
||||
|
||||
PR tree-optimization/30317
|
||||
|
@ -13743,7 +13743,7 @@ tree_simple_nonnegative_warnv_p (enum tree_code code, tree type)
|
||||
set *STRICT_OVERFLOW_P to true; otherwise, don't change
|
||||
*STRICT_OVERFLOW_P. */
|
||||
|
||||
static bool
|
||||
bool
|
||||
tree_unary_nonnegative_warnv_p (enum tree_code code, tree type, tree op0,
|
||||
bool *strict_overflow_p)
|
||||
{
|
||||
@ -13813,7 +13813,7 @@ tree_unary_nonnegative_warnv_p (enum tree_code code, tree type, tree op0,
|
||||
set *STRICT_OVERFLOW_P to true; otherwise, don't change
|
||||
*STRICT_OVERFLOW_P. */
|
||||
|
||||
static bool
|
||||
bool
|
||||
tree_binary_nonnegative_warnv_p (enum tree_code code, tree type, tree op0,
|
||||
tree op1, bool *strict_overflow_p)
|
||||
{
|
||||
@ -13914,7 +13914,7 @@ tree_binary_nonnegative_warnv_p (enum tree_code code, tree type, tree op0,
|
||||
set *STRICT_OVERFLOW_P to true; otherwise, don't change
|
||||
*STRICT_OVERFLOW_P. */
|
||||
|
||||
static bool
|
||||
bool
|
||||
tree_single_nonnegative_warnv_p (tree t, bool *strict_overflow_p)
|
||||
{
|
||||
if (TYPE_UNSIGNED (TREE_TYPE (t)))
|
||||
@ -13954,7 +13954,7 @@ tree_single_nonnegative_warnv_p (tree t, bool *strict_overflow_p)
|
||||
set *STRICT_OVERFLOW_P to true; otherwise, don't change
|
||||
*STRICT_OVERFLOW_P. */
|
||||
|
||||
static bool
|
||||
bool
|
||||
tree_invalid_nonnegative_warnv_p (tree t, bool *strict_overflow_p)
|
||||
{
|
||||
enum tree_code code = TREE_CODE (t);
|
||||
@ -14243,7 +14243,7 @@ tree_expr_nonnegative_p (tree t)
|
||||
is undefined, set *STRICT_OVERFLOW_P to true; otherwise, don't
|
||||
change *STRICT_OVERFLOW_P. */
|
||||
|
||||
static bool
|
||||
bool
|
||||
tree_unary_nonzero_warnv_p (enum tree_code code, tree type, tree op0,
|
||||
bool *strict_overflow_p)
|
||||
{
|
||||
@ -14283,7 +14283,7 @@ tree_unary_nonzero_warnv_p (enum tree_code code, tree type, tree op0,
|
||||
is undefined, set *STRICT_OVERFLOW_P to true; otherwise, don't
|
||||
change *STRICT_OVERFLOW_P. */
|
||||
|
||||
static bool
|
||||
bool
|
||||
tree_binary_nonzero_warnv_p (enum tree_code code,
|
||||
tree type,
|
||||
tree op0,
|
||||
@ -14391,7 +14391,7 @@ tree_binary_nonzero_warnv_p (enum tree_code code,
|
||||
is undefined, set *STRICT_OVERFLOW_P to true; otherwise, don't
|
||||
change *STRICT_OVERFLOW_P. */
|
||||
|
||||
static bool
|
||||
bool
|
||||
tree_single_nonzero_warnv_p (tree t, bool *strict_overflow_p)
|
||||
{
|
||||
bool sub_strict_overflow_p;
|
||||
|
264
gcc/tree-vrp.c
264
gcc/tree-vrp.c
@ -47,6 +47,8 @@ static int compare_values (tree val1, tree val2);
|
||||
static int compare_values_warnv (tree val1, tree val2, bool *);
|
||||
static void vrp_meet (value_range_t *, value_range_t *);
|
||||
static tree vrp_evaluate_conditional_warnv (tree, bool, bool *);
|
||||
static tree vrp_evaluate_conditional_warnv_with_ops (enum tree_code,
|
||||
tree, tree, bool, bool *);
|
||||
|
||||
/* Location information for ASSERT_EXPRs. Each instance of this
|
||||
structure describes an ASSERT_EXPR for an SSA name. Since a single
|
||||
@ -1792,11 +1794,12 @@ vrp_int_const_binop (enum tree_code code, tree val1, tree val2)
|
||||
the ranges of each of its operands and the expression code. */
|
||||
|
||||
static void
|
||||
extract_range_from_binary_expr (value_range_t *vr, tree expr)
|
||||
extract_range_from_binary_expr (value_range_t *vr,
|
||||
enum tree_code code,
|
||||
tree expr_type, tree op0, tree op1)
|
||||
{
|
||||
enum tree_code code = TREE_CODE (expr);
|
||||
enum value_range_type type;
|
||||
tree op0, op1, min, max;
|
||||
tree min, max;
|
||||
int cmp;
|
||||
value_range_t vr0 = { VR_UNDEFINED, NULL_TREE, NULL_TREE, NULL };
|
||||
value_range_t vr1 = { VR_UNDEFINED, NULL_TREE, NULL_TREE, NULL };
|
||||
@ -1827,7 +1830,6 @@ extract_range_from_binary_expr (value_range_t *vr, tree expr)
|
||||
|
||||
/* Get value ranges for each operand. For constant operands, create
|
||||
a new value range with the operand to simplify processing. */
|
||||
op0 = TREE_OPERAND (expr, 0);
|
||||
if (TREE_CODE (op0) == SSA_NAME)
|
||||
vr0 = *(get_value_range (op0));
|
||||
else if (is_gimple_min_invariant (op0))
|
||||
@ -1835,7 +1837,6 @@ extract_range_from_binary_expr (value_range_t *vr, tree expr)
|
||||
else
|
||||
set_value_range_to_varying (&vr0);
|
||||
|
||||
op1 = TREE_OPERAND (expr, 1);
|
||||
if (TREE_CODE (op1) == SSA_NAME)
|
||||
vr1 = *(get_value_range (op1));
|
||||
else if (is_gimple_min_invariant (op1))
|
||||
@ -1872,7 +1873,7 @@ extract_range_from_binary_expr (value_range_t *vr, tree expr)
|
||||
}
|
||||
|
||||
/* Now evaluate the expression to determine the new range. */
|
||||
if (POINTER_TYPE_P (TREE_TYPE (expr))
|
||||
if (POINTER_TYPE_P (expr_type)
|
||||
|| POINTER_TYPE_P (TREE_TYPE (op0))
|
||||
|| POINTER_TYPE_P (TREE_TYPE (op1)))
|
||||
{
|
||||
@ -1883,9 +1884,9 @@ extract_range_from_binary_expr (value_range_t *vr, tree expr)
|
||||
If both are null, then the result is null. Otherwise they
|
||||
are varying. */
|
||||
if (range_is_nonnull (&vr0) && range_is_nonnull (&vr1))
|
||||
set_value_range_to_nonnull (vr, TREE_TYPE (expr));
|
||||
set_value_range_to_nonnull (vr, expr_type);
|
||||
else if (range_is_null (&vr0) && range_is_null (&vr1))
|
||||
set_value_range_to_null (vr, TREE_TYPE (expr));
|
||||
set_value_range_to_null (vr, expr_type);
|
||||
else
|
||||
set_value_range_to_varying (vr);
|
||||
|
||||
@ -1895,9 +1896,9 @@ extract_range_from_binary_expr (value_range_t *vr, tree expr)
|
||||
/* For pointer types, we are really only interested in asserting
|
||||
whether the expression evaluates to non-NULL. */
|
||||
if (range_is_nonnull (&vr0) || range_is_nonnull (&vr1))
|
||||
set_value_range_to_nonnull (vr, TREE_TYPE (expr));
|
||||
set_value_range_to_nonnull (vr, expr_type);
|
||||
else if (range_is_null (&vr0) && range_is_null (&vr1))
|
||||
set_value_range_to_null (vr, TREE_TYPE (expr));
|
||||
set_value_range_to_null (vr, expr_type);
|
||||
else
|
||||
set_value_range_to_varying (vr);
|
||||
|
||||
@ -1922,7 +1923,7 @@ extract_range_from_binary_expr (value_range_t *vr, tree expr)
|
||||
&& integer_zerop (vr1.max))))
|
||||
{
|
||||
type = VR_RANGE;
|
||||
min = max = build_int_cst (TREE_TYPE (expr), 0);
|
||||
min = max = build_int_cst (expr_type, 0);
|
||||
}
|
||||
/* If one of the operands is one, we know that the whole
|
||||
expression evaluates one. */
|
||||
@ -1935,7 +1936,7 @@ extract_range_from_binary_expr (value_range_t *vr, tree expr)
|
||||
&& integer_onep (vr1.max))))
|
||||
{
|
||||
type = VR_RANGE;
|
||||
min = max = build_int_cst (TREE_TYPE (expr), 1);
|
||||
min = max = build_int_cst (expr_type, 1);
|
||||
}
|
||||
else if (vr0.type != VR_VARYING
|
||||
&& vr1.type != VR_VARYING
|
||||
@ -1946,13 +1947,13 @@ extract_range_from_binary_expr (value_range_t *vr, tree expr)
|
||||
&& !overflow_infinity_range_p (&vr1))
|
||||
{
|
||||
/* Boolean expressions cannot be folded with int_const_binop. */
|
||||
min = fold_binary (code, TREE_TYPE (expr), vr0.min, vr1.min);
|
||||
max = fold_binary (code, TREE_TYPE (expr), vr0.max, vr1.max);
|
||||
min = fold_binary (code, expr_type, vr0.min, vr1.min);
|
||||
max = fold_binary (code, expr_type, vr0.max, vr1.max);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The result of a TRUTH_*_EXPR is always true or false. */
|
||||
set_value_range_to_truthvalue (vr, TREE_TYPE (expr));
|
||||
set_value_range_to_truthvalue (vr, expr_type);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -2018,7 +2019,7 @@ extract_range_from_binary_expr (value_range_t *vr, tree expr)
|
||||
|| !vrp_expr_computes_nonnegative (op1, &sop)
|
||||
|| (operand_less_p
|
||||
(build_int_cst (TREE_TYPE (vr1.max),
|
||||
TYPE_PRECISION (TREE_TYPE (expr)) - 1),
|
||||
TYPE_PRECISION (expr_type) - 1),
|
||||
vr1.max) != 0))
|
||||
{
|
||||
set_value_range_to_varying (vr);
|
||||
@ -2147,7 +2148,7 @@ extract_range_from_binary_expr (value_range_t *vr, tree expr)
|
||||
&& !TREE_OVERFLOW (vr0.max)
|
||||
&& tree_int_cst_sgn (vr0.max) >= 0)
|
||||
{
|
||||
min = build_int_cst (TREE_TYPE (expr), 0);
|
||||
min = build_int_cst (expr_type, 0);
|
||||
max = vr0.max;
|
||||
}
|
||||
else if (vr1.type == VR_RANGE
|
||||
@ -2157,7 +2158,7 @@ extract_range_from_binary_expr (value_range_t *vr, tree expr)
|
||||
&& tree_int_cst_sgn (vr1.max) >= 0)
|
||||
{
|
||||
type = VR_RANGE;
|
||||
min = build_int_cst (TREE_TYPE (expr), 0);
|
||||
min = build_int_cst (expr_type, 0);
|
||||
max = vr1.max;
|
||||
}
|
||||
else
|
||||
@ -2215,10 +2216,10 @@ extract_range_from_binary_expr (value_range_t *vr, tree expr)
|
||||
the range of its operand and the expression code. */
|
||||
|
||||
static void
|
||||
extract_range_from_unary_expr (value_range_t *vr, tree expr)
|
||||
extract_range_from_unary_expr (value_range_t *vr, enum tree_code code,
|
||||
tree type, tree op0)
|
||||
{
|
||||
enum tree_code code = TREE_CODE (expr);
|
||||
tree min, max, op0;
|
||||
tree min, max;
|
||||
int cmp;
|
||||
value_range_t vr0 = { VR_UNDEFINED, NULL_TREE, NULL_TREE, NULL };
|
||||
|
||||
@ -2236,7 +2237,6 @@ extract_range_from_unary_expr (value_range_t *vr, tree expr)
|
||||
|
||||
/* Get value ranges for the operand. For constant operands, create
|
||||
a new value range with the operand to simplify processing. */
|
||||
op0 = TREE_OPERAND (expr, 0);
|
||||
if (TREE_CODE (op0) == SSA_NAME)
|
||||
vr0 = *(get_value_range (op0));
|
||||
else if (is_gimple_min_invariant (op0))
|
||||
@ -2264,17 +2264,17 @@ extract_range_from_unary_expr (value_range_t *vr, tree expr)
|
||||
|
||||
/* If the expression involves pointers, we are only interested in
|
||||
determining if it evaluates to NULL [0, 0] or non-NULL (~[0, 0]). */
|
||||
if (POINTER_TYPE_P (TREE_TYPE (expr)) || POINTER_TYPE_P (TREE_TYPE (op0)))
|
||||
if (POINTER_TYPE_P (type) || POINTER_TYPE_P (TREE_TYPE (op0)))
|
||||
{
|
||||
bool sop;
|
||||
|
||||
sop = false;
|
||||
if (range_is_nonnull (&vr0)
|
||||
|| (tree_expr_nonzero_warnv_p (expr, &sop)
|
||||
|| (tree_unary_nonzero_warnv_p (code, type, op0, &sop)
|
||||
&& !sop))
|
||||
set_value_range_to_nonnull (vr, TREE_TYPE (expr));
|
||||
set_value_range_to_nonnull (vr, type);
|
||||
else if (range_is_null (&vr0))
|
||||
set_value_range_to_null (vr, TREE_TYPE (expr));
|
||||
set_value_range_to_null (vr, type);
|
||||
else
|
||||
set_value_range_to_varying (vr);
|
||||
|
||||
@ -2285,7 +2285,7 @@ extract_range_from_unary_expr (value_range_t *vr, tree expr)
|
||||
if (code == NOP_EXPR || code == CONVERT_EXPR)
|
||||
{
|
||||
tree inner_type = TREE_TYPE (op0);
|
||||
tree outer_type = TREE_TYPE (expr);
|
||||
tree outer_type = type;
|
||||
|
||||
/* If VR0 represents a simple range, then try to convert
|
||||
the min and max values for the range to the same type
|
||||
@ -2362,22 +2362,22 @@ extract_range_from_unary_expr (value_range_t *vr, tree expr)
|
||||
/* Apply the operation to each end of the range and see what we end
|
||||
up with. */
|
||||
if (code == NEGATE_EXPR
|
||||
&& !TYPE_UNSIGNED (TREE_TYPE (expr)))
|
||||
&& !TYPE_UNSIGNED (type))
|
||||
{
|
||||
/* NEGATE_EXPR flips the range around. We need to treat
|
||||
TYPE_MIN_VALUE specially. */
|
||||
if (is_positive_overflow_infinity (vr0.max))
|
||||
min = negative_overflow_infinity (TREE_TYPE (expr));
|
||||
min = negative_overflow_infinity (type);
|
||||
else if (is_negative_overflow_infinity (vr0.max))
|
||||
min = positive_overflow_infinity (TREE_TYPE (expr));
|
||||
min = positive_overflow_infinity (type);
|
||||
else if (!vrp_val_is_min (vr0.max))
|
||||
min = fold_unary_to_constant (code, TREE_TYPE (expr), vr0.max);
|
||||
else if (needs_overflow_infinity (TREE_TYPE (expr)))
|
||||
min = fold_unary_to_constant (code, type, vr0.max);
|
||||
else if (needs_overflow_infinity (type))
|
||||
{
|
||||
if (supports_overflow_infinity (TREE_TYPE (expr))
|
||||
if (supports_overflow_infinity (type)
|
||||
&& !is_overflow_infinity (vr0.min)
|
||||
&& !vrp_val_is_min (vr0.min))
|
||||
min = positive_overflow_infinity (TREE_TYPE (expr));
|
||||
min = positive_overflow_infinity (type);
|
||||
else
|
||||
{
|
||||
set_value_range_to_varying (vr);
|
||||
@ -2385,18 +2385,18 @@ extract_range_from_unary_expr (value_range_t *vr, tree expr)
|
||||
}
|
||||
}
|
||||
else
|
||||
min = TYPE_MIN_VALUE (TREE_TYPE (expr));
|
||||
min = TYPE_MIN_VALUE (type);
|
||||
|
||||
if (is_positive_overflow_infinity (vr0.min))
|
||||
max = negative_overflow_infinity (TREE_TYPE (expr));
|
||||
max = negative_overflow_infinity (type);
|
||||
else if (is_negative_overflow_infinity (vr0.min))
|
||||
max = positive_overflow_infinity (TREE_TYPE (expr));
|
||||
max = positive_overflow_infinity (type);
|
||||
else if (!vrp_val_is_min (vr0.min))
|
||||
max = fold_unary_to_constant (code, TREE_TYPE (expr), vr0.min);
|
||||
else if (needs_overflow_infinity (TREE_TYPE (expr)))
|
||||
max = fold_unary_to_constant (code, type, vr0.min);
|
||||
else if (needs_overflow_infinity (type))
|
||||
{
|
||||
if (supports_overflow_infinity (TREE_TYPE (expr)))
|
||||
max = positive_overflow_infinity (TREE_TYPE (expr));
|
||||
if (supports_overflow_infinity (type))
|
||||
max = positive_overflow_infinity (type);
|
||||
else
|
||||
{
|
||||
set_value_range_to_varying (vr);
|
||||
@ -2404,31 +2404,31 @@ extract_range_from_unary_expr (value_range_t *vr, tree expr)
|
||||
}
|
||||
}
|
||||
else
|
||||
max = TYPE_MIN_VALUE (TREE_TYPE (expr));
|
||||
max = TYPE_MIN_VALUE (type);
|
||||
}
|
||||
else if (code == NEGATE_EXPR
|
||||
&& TYPE_UNSIGNED (TREE_TYPE (expr)))
|
||||
&& TYPE_UNSIGNED (type))
|
||||
{
|
||||
if (!range_includes_zero_p (&vr0))
|
||||
{
|
||||
max = fold_unary_to_constant (code, TREE_TYPE (expr), vr0.min);
|
||||
min = fold_unary_to_constant (code, TREE_TYPE (expr), vr0.max);
|
||||
max = fold_unary_to_constant (code, type, vr0.min);
|
||||
min = fold_unary_to_constant (code, type, vr0.max);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (range_is_null (&vr0))
|
||||
set_value_range_to_null (vr, TREE_TYPE (expr));
|
||||
set_value_range_to_null (vr, type);
|
||||
else
|
||||
set_value_range_to_varying (vr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (code == ABS_EXPR
|
||||
&& !TYPE_UNSIGNED (TREE_TYPE (expr)))
|
||||
&& !TYPE_UNSIGNED (type))
|
||||
{
|
||||
/* -TYPE_MIN_VALUE = TYPE_MIN_VALUE with flag_wrapv so we can't get a
|
||||
useful range. */
|
||||
if (!TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (expr))
|
||||
if (!TYPE_OVERFLOW_UNDEFINED (type)
|
||||
&& ((vr0.type == VR_RANGE
|
||||
&& vrp_val_is_min (vr0.min))
|
||||
|| (vr0.type == VR_ANTI_RANGE
|
||||
@ -2442,13 +2442,13 @@ extract_range_from_unary_expr (value_range_t *vr, tree expr)
|
||||
/* ABS_EXPR may flip the range around, if the original range
|
||||
included negative values. */
|
||||
if (is_overflow_infinity (vr0.min))
|
||||
min = positive_overflow_infinity (TREE_TYPE (expr));
|
||||
min = positive_overflow_infinity (type);
|
||||
else if (!vrp_val_is_min (vr0.min))
|
||||
min = fold_unary_to_constant (code, TREE_TYPE (expr), vr0.min);
|
||||
else if (!needs_overflow_infinity (TREE_TYPE (expr)))
|
||||
min = TYPE_MAX_VALUE (TREE_TYPE (expr));
|
||||
else if (supports_overflow_infinity (TREE_TYPE (expr)))
|
||||
min = positive_overflow_infinity (TREE_TYPE (expr));
|
||||
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
|
||||
{
|
||||
set_value_range_to_varying (vr);
|
||||
@ -2456,13 +2456,13 @@ extract_range_from_unary_expr (value_range_t *vr, tree expr)
|
||||
}
|
||||
|
||||
if (is_overflow_infinity (vr0.max))
|
||||
max = positive_overflow_infinity (TREE_TYPE (expr));
|
||||
max = positive_overflow_infinity (type);
|
||||
else if (!vrp_val_is_min (vr0.max))
|
||||
max = fold_unary_to_constant (code, TREE_TYPE (expr), vr0.max);
|
||||
else if (!needs_overflow_infinity (TREE_TYPE (expr)))
|
||||
max = TYPE_MAX_VALUE (TREE_TYPE (expr));
|
||||
else if (supports_overflow_infinity (TREE_TYPE (expr)))
|
||||
max = positive_overflow_infinity (TREE_TYPE (expr));
|
||||
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))
|
||||
max = positive_overflow_infinity (type);
|
||||
else
|
||||
{
|
||||
set_value_range_to_varying (vr);
|
||||
@ -2485,9 +2485,9 @@ extract_range_from_unary_expr (value_range_t *vr, tree expr)
|
||||
or ~[-INF + 1, min (abs(MIN), abs(MAX))] when
|
||||
flag_wrapv is set and the original anti-range doesn't include
|
||||
TYPE_MIN_VALUE, remember -TYPE_MIN_VALUE = TYPE_MIN_VALUE. */
|
||||
if (TYPE_OVERFLOW_WRAPS (TREE_TYPE (expr)))
|
||||
if (TYPE_OVERFLOW_WRAPS (type))
|
||||
{
|
||||
tree type_min_value = TYPE_MIN_VALUE (TREE_TYPE (expr));
|
||||
tree type_min_value = TYPE_MIN_VALUE (type);
|
||||
|
||||
min = (vr0.min != type_min_value
|
||||
? int_const_binop (PLUS_EXPR, type_min_value,
|
||||
@ -2497,9 +2497,9 @@ extract_range_from_unary_expr (value_range_t *vr, tree expr)
|
||||
else
|
||||
{
|
||||
if (overflow_infinity_range_p (&vr0))
|
||||
min = negative_overflow_infinity (TREE_TYPE (expr));
|
||||
min = negative_overflow_infinity (type);
|
||||
else
|
||||
min = TYPE_MIN_VALUE (TREE_TYPE (expr));
|
||||
min = TYPE_MIN_VALUE (type);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -2508,11 +2508,11 @@ extract_range_from_unary_expr (value_range_t *vr, tree expr)
|
||||
flag_wrapv since TYPE_MIN_VALUE is in the original
|
||||
anti-range. */
|
||||
vr0.type = VR_RANGE;
|
||||
min = build_int_cst (TREE_TYPE (expr), 0);
|
||||
if (needs_overflow_infinity (TREE_TYPE (expr)))
|
||||
min = build_int_cst (type, 0);
|
||||
if (needs_overflow_infinity (type))
|
||||
{
|
||||
if (supports_overflow_infinity (TREE_TYPE (expr)))
|
||||
max = positive_overflow_infinity (TREE_TYPE (expr));
|
||||
if (supports_overflow_infinity (type))
|
||||
max = positive_overflow_infinity (type);
|
||||
else
|
||||
{
|
||||
set_value_range_to_varying (vr);
|
||||
@ -2520,7 +2520,7 @@ extract_range_from_unary_expr (value_range_t *vr, tree expr)
|
||||
}
|
||||
}
|
||||
else
|
||||
max = TYPE_MAX_VALUE (TREE_TYPE (expr));
|
||||
max = TYPE_MAX_VALUE (type);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2530,7 +2530,7 @@ extract_range_from_unary_expr (value_range_t *vr, tree expr)
|
||||
{
|
||||
if (cmp == 1)
|
||||
max = min;
|
||||
min = build_int_cst (TREE_TYPE (expr), 0);
|
||||
min = build_int_cst (type, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -2546,10 +2546,10 @@ extract_range_from_unary_expr (value_range_t *vr, tree expr)
|
||||
else
|
||||
{
|
||||
/* Otherwise, operate on each end of the range. */
|
||||
min = fold_unary_to_constant (code, TREE_TYPE (expr), vr0.min);
|
||||
max = fold_unary_to_constant (code, TREE_TYPE (expr), vr0.max);
|
||||
min = fold_unary_to_constant (code, type, vr0.min);
|
||||
max = fold_unary_to_constant (code, type, vr0.max);
|
||||
|
||||
if (needs_overflow_infinity (TREE_TYPE (expr)))
|
||||
if (needs_overflow_infinity (type))
|
||||
{
|
||||
gcc_assert (code != NEGATE_EXPR && code != ABS_EXPR);
|
||||
|
||||
@ -2568,7 +2568,7 @@ extract_range_from_unary_expr (value_range_t *vr, tree expr)
|
||||
min = vr0.min;
|
||||
else if (TREE_OVERFLOW (min))
|
||||
{
|
||||
if (supports_overflow_infinity (TREE_TYPE (expr)))
|
||||
if (supports_overflow_infinity (type))
|
||||
min = (tree_int_cst_sgn (min) >= 0
|
||||
? positive_overflow_infinity (TREE_TYPE (min))
|
||||
: negative_overflow_infinity (TREE_TYPE (min)));
|
||||
@ -2583,7 +2583,7 @@ extract_range_from_unary_expr (value_range_t *vr, tree expr)
|
||||
max = vr0.max;
|
||||
else if (TREE_OVERFLOW (max))
|
||||
{
|
||||
if (supports_overflow_infinity (TREE_TYPE (expr)))
|
||||
if (supports_overflow_infinity (type))
|
||||
max = (tree_int_cst_sgn (max) >= 0
|
||||
? positive_overflow_infinity (TREE_TYPE (max))
|
||||
: negative_overflow_infinity (TREE_TYPE (max)));
|
||||
@ -2647,10 +2647,14 @@ extract_range_from_cond_expr (value_range_t *vr, tree expr)
|
||||
on the range of its operand and the expression code. */
|
||||
|
||||
static void
|
||||
extract_range_from_comparison (value_range_t *vr, tree expr)
|
||||
extract_range_from_comparison (value_range_t *vr, enum tree_code code,
|
||||
tree type, tree op0, tree op1)
|
||||
{
|
||||
bool sop = false;
|
||||
tree val = vrp_evaluate_conditional_warnv (expr, false, &sop);
|
||||
tree val = vrp_evaluate_conditional_warnv_with_ops (code,
|
||||
op0,
|
||||
op1,
|
||||
false, &sop);
|
||||
|
||||
/* A disadvantage of using a special infinity as an overflow
|
||||
representation is that we lose the ability to record overflow
|
||||
@ -2662,7 +2666,7 @@ extract_range_from_comparison (value_range_t *vr, tree expr)
|
||||
/* Since this expression was found on the RHS of an assignment,
|
||||
its type may be different from _Bool. Convert VAL to EXPR's
|
||||
type. */
|
||||
val = fold_convert (TREE_TYPE (expr), val);
|
||||
val = fold_convert (type, val);
|
||||
if (is_gimple_min_invariant (val))
|
||||
set_value_range_to_value (vr, val, vr->equiv);
|
||||
else
|
||||
@ -2670,7 +2674,7 @@ extract_range_from_comparison (value_range_t *vr, tree expr)
|
||||
}
|
||||
else
|
||||
/* The result of a comparison is always true or false. */
|
||||
set_value_range_to_truthvalue (vr, TREE_TYPE (expr));
|
||||
set_value_range_to_truthvalue (vr, type);
|
||||
}
|
||||
|
||||
|
||||
@ -2692,13 +2696,18 @@ extract_range_from_expr (value_range_t *vr, tree expr)
|
||||
|| code == TRUTH_AND_EXPR
|
||||
|| code == TRUTH_OR_EXPR
|
||||
|| code == TRUTH_XOR_EXPR)
|
||||
extract_range_from_binary_expr (vr, expr);
|
||||
extract_range_from_binary_expr (vr, TREE_CODE (expr), TREE_TYPE (expr),
|
||||
TREE_OPERAND (expr, 0),
|
||||
TREE_OPERAND (expr, 1));
|
||||
else if (TREE_CODE_CLASS (code) == tcc_unary)
|
||||
extract_range_from_unary_expr (vr, expr);
|
||||
extract_range_from_unary_expr (vr, TREE_CODE (expr), TREE_TYPE (expr),
|
||||
TREE_OPERAND (expr, 0));
|
||||
else if (code == COND_EXPR)
|
||||
extract_range_from_cond_expr (vr, expr);
|
||||
else if (TREE_CODE_CLASS (code) == tcc_comparison)
|
||||
extract_range_from_comparison (vr, expr);
|
||||
extract_range_from_comparison (vr, TREE_CODE (expr), TREE_TYPE (expr),
|
||||
TREE_OPERAND (expr, 0),
|
||||
TREE_OPERAND (expr, 1));
|
||||
else if (is_gimple_min_invariant (expr))
|
||||
set_value_range_to_value (vr, expr, NULL);
|
||||
else
|
||||
@ -5111,6 +5120,51 @@ compare_names (enum tree_code comp, tree n1, tree n2,
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* Helper function for vrp_evaluate_conditional_warnv. */
|
||||
|
||||
static tree
|
||||
vrp_evaluate_conditional_warnv_with_ops (enum tree_code code, tree op0,
|
||||
tree op1, bool use_equiv_p,
|
||||
bool *strict_overflow_p)
|
||||
{
|
||||
/* We only deal with integral and pointer types. */
|
||||
if (!INTEGRAL_TYPE_P (TREE_TYPE (op0))
|
||||
&& !POINTER_TYPE_P (TREE_TYPE (op0)))
|
||||
return NULL_TREE;
|
||||
|
||||
if (use_equiv_p)
|
||||
{
|
||||
if (TREE_CODE (op0) == SSA_NAME && TREE_CODE (op1) == SSA_NAME)
|
||||
return compare_names (code, op0, op1,
|
||||
strict_overflow_p);
|
||||
else if (TREE_CODE (op0) == SSA_NAME)
|
||||
return compare_name_with_value (code, op0, op1,
|
||||
strict_overflow_p);
|
||||
else if (TREE_CODE (op1) == SSA_NAME)
|
||||
return (compare_name_with_value
|
||||
(swap_tree_comparison (code), op1, op0,
|
||||
strict_overflow_p));
|
||||
}
|
||||
else
|
||||
{
|
||||
value_range_t *vr0, *vr1;
|
||||
|
||||
vr0 = (TREE_CODE (op0) == SSA_NAME) ? get_value_range (op0) : NULL;
|
||||
vr1 = (TREE_CODE (op1) == SSA_NAME) ? get_value_range (op1) : NULL;
|
||||
|
||||
if (vr0 && vr1)
|
||||
return compare_ranges (code, vr0, vr1,
|
||||
strict_overflow_p);
|
||||
else if (vr0 && vr1 == NULL)
|
||||
return compare_range_with_value (code, vr0, op1,
|
||||
strict_overflow_p);
|
||||
else if (vr0 == NULL && vr1)
|
||||
return (compare_range_with_value
|
||||
(swap_tree_comparison (code), vr1, op0,
|
||||
strict_overflow_p));
|
||||
}
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* Given a conditional predicate COND, try to determine if COND yields
|
||||
true or false based on the value ranges of its operands. Return
|
||||
@ -5159,47 +5213,11 @@ vrp_evaluate_conditional_warnv (tree cond, bool use_equiv_p,
|
||||
return vr->min;
|
||||
}
|
||||
else
|
||||
{
|
||||
tree op0 = TREE_OPERAND (cond, 0);
|
||||
tree op1 = TREE_OPERAND (cond, 1);
|
||||
|
||||
/* We only deal with integral and pointer types. */
|
||||
if (!INTEGRAL_TYPE_P (TREE_TYPE (op0))
|
||||
&& !POINTER_TYPE_P (TREE_TYPE (op0)))
|
||||
return NULL_TREE;
|
||||
|
||||
if (use_equiv_p)
|
||||
{
|
||||
if (TREE_CODE (op0) == SSA_NAME && TREE_CODE (op1) == SSA_NAME)
|
||||
return compare_names (TREE_CODE (cond), op0, op1,
|
||||
strict_overflow_p);
|
||||
else if (TREE_CODE (op0) == SSA_NAME)
|
||||
return compare_name_with_value (TREE_CODE (cond), op0, op1,
|
||||
strict_overflow_p);
|
||||
else if (TREE_CODE (op1) == SSA_NAME)
|
||||
return (compare_name_with_value
|
||||
(swap_tree_comparison (TREE_CODE (cond)), op1, op0,
|
||||
strict_overflow_p));
|
||||
}
|
||||
else
|
||||
{
|
||||
value_range_t *vr0, *vr1;
|
||||
|
||||
vr0 = (TREE_CODE (op0) == SSA_NAME) ? get_value_range (op0) : NULL;
|
||||
vr1 = (TREE_CODE (op1) == SSA_NAME) ? get_value_range (op1) : NULL;
|
||||
|
||||
if (vr0 && vr1)
|
||||
return compare_ranges (TREE_CODE (cond), vr0, vr1,
|
||||
strict_overflow_p);
|
||||
else if (vr0 && vr1 == NULL)
|
||||
return compare_range_with_value (TREE_CODE (cond), vr0, op1,
|
||||
strict_overflow_p);
|
||||
else if (vr0 == NULL && vr1)
|
||||
return (compare_range_with_value
|
||||
(swap_tree_comparison (TREE_CODE (cond)), vr1, op0,
|
||||
strict_overflow_p));
|
||||
}
|
||||
}
|
||||
return vrp_evaluate_conditional_warnv_with_ops (TREE_CODE (cond),
|
||||
TREE_OPERAND (cond, 0),
|
||||
TREE_OPERAND (cond, 1),
|
||||
use_equiv_p,
|
||||
strict_overflow_p);
|
||||
|
||||
/* Anything else cannot be computed statically. */
|
||||
return NULL_TREE;
|
||||
|
10
gcc/tree.h
10
gcc/tree.h
@ -4841,6 +4841,16 @@ extern bool ptr_difference_const (tree, tree, HOST_WIDE_INT *);
|
||||
extern enum tree_code invert_tree_comparison (enum tree_code, bool);
|
||||
|
||||
extern bool tree_expr_nonzero_p (tree);
|
||||
extern bool tree_unary_nonzero_warnv_p (enum tree_code, tree, tree, bool *);
|
||||
extern bool tree_binary_nonzero_warnv_p (enum tree_code, tree, tree, tree op1,
|
||||
bool *);
|
||||
extern bool tree_single_nonzero_warnv_p (tree, bool *);
|
||||
extern bool tree_expr_nonzero_warnv_p (tree, bool *);
|
||||
extern bool tree_unary_nonnegative_warnv_p (enum tree_code, tree, tree, bool *);
|
||||
extern bool tree_binary_nonnegative_warnv_p (enum tree_code, tree, tree, tree,
|
||||
bool *);
|
||||
extern bool tree_single_nonnegative_warnv_p (tree t, bool *strict_overflow_p);
|
||||
extern bool tree_invalid_nonnegative_warnv_p (tree t, bool *strict_overflow_p);
|
||||
extern bool tree_expr_nonzero_warnv_p (tree, bool *);
|
||||
|
||||
extern bool fold_real_zero_addition_p (const_tree, const_tree, int);
|
||||
|
Loading…
Reference in New Issue
Block a user