Enforce canonicalization in value_range.
From-SVN: r274525
This commit is contained in:
parent
eb2211e357
commit
c7cf3a9bb0
|
@ -1,3 +1,37 @@
|
|||
2019-08-15 Aldy Hernandez <aldyh@redhat.com>
|
||||
|
||||
* tree-vrp.c (value_range_base::set): Merge in code from
|
||||
value_range_base::set_and_canonicalize.
|
||||
Enforce canonicalization at set time.
|
||||
Normalize [MIN, MAX] into VARYING and ~[MIN, MAX] into UNDEFINED.
|
||||
(value_range_base::set_undefined): Inline call to set().
|
||||
(value_range_base::set_varying): Same.
|
||||
(value_range_base::singleton_p): Handle VR_ANTI_RANGEs.
|
||||
(vrp_val_max): New argument handle_pointers.
|
||||
(vrp_val_min): Same.
|
||||
(ranges_from_anti_range): Same.
|
||||
(extract_range_into_wide_ints): Use tree argument instead of sign
|
||||
and precision.
|
||||
(extract_range_from_multiplicative_op): Take in tree type instead
|
||||
of precision and sign. Adapt function for canonicalized ranges.
|
||||
(extract_range_from_binary_expr): Pass type to
|
||||
extract_range_from_multiplicative_op.
|
||||
Adapt for canonicalized ranges.
|
||||
(extract_range_from_unary_expr): Same.
|
||||
(value_range_base::intersect_helper): Adjust for canonicalized
|
||||
ranges.
|
||||
(value_range_base::union_helper): Same.
|
||||
(value_range_base::normalize_symbolics): New.
|
||||
* tree-vrp.h (class value_range_base): Remove
|
||||
set_and_canonicalize.
|
||||
New prototype for normalize_symbolics.
|
||||
(class value_range): Remove set_and_canonicalize.
|
||||
(vrp_val_min): Adjust prototype.
|
||||
(vrp_val_max): Same.
|
||||
* vr-values.c
|
||||
(vr_values::extract_range_for_var_from_comparison_expr): Call set
|
||||
instead of set_and_canonicalize.
|
||||
|
||||
2019-08-15 Richard Sandiford <richard.sandiford@arm.com>
|
||||
|
||||
PR middle-end/91444
|
||||
|
|
298
gcc/tree-vrp.c
298
gcc/tree-vrp.c
|
@ -69,23 +69,20 @@ along with GCC; see the file COPYING3. If not see
|
|||
#include "builtins.h"
|
||||
#include "wide-int-range.h"
|
||||
|
||||
static bool
|
||||
ranges_from_anti_range (const value_range_base *ar,
|
||||
value_range_base *vr0, value_range_base *vr1,
|
||||
bool handle_pointers = false);
|
||||
|
||||
/* Set of SSA names found live during the RPO traversal of the function
|
||||
for still active basic-blocks. */
|
||||
static sbitmap *live;
|
||||
|
||||
void
|
||||
value_range_base::set (enum value_range_kind kind, tree min, tree max)
|
||||
{
|
||||
m_kind = kind;
|
||||
m_min = min;
|
||||
m_max = max;
|
||||
if (flag_checking)
|
||||
check ();
|
||||
}
|
||||
|
||||
void
|
||||
value_range::set_equiv (bitmap equiv)
|
||||
{
|
||||
if (undefined_p () || varying_p ())
|
||||
equiv = NULL;
|
||||
/* Since updating the equivalence set involves deep copying the
|
||||
bitmaps, only do it if absolutely necessary.
|
||||
|
||||
|
@ -261,7 +258,8 @@ value_range_base::constant_p () const
|
|||
void
|
||||
value_range_base::set_undefined ()
|
||||
{
|
||||
set (VR_UNDEFINED, NULL, NULL);
|
||||
m_kind = VR_UNDEFINED;
|
||||
m_min = m_max = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -273,7 +271,8 @@ value_range::set_undefined ()
|
|||
void
|
||||
value_range_base::set_varying ()
|
||||
{
|
||||
set (VR_VARYING, NULL, NULL);
|
||||
m_kind = VR_VARYING;
|
||||
m_min = m_max = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -324,6 +323,24 @@ value_range::equiv_add (const_tree var,
|
|||
bool
|
||||
value_range_base::singleton_p (tree *result) const
|
||||
{
|
||||
if (m_kind == VR_ANTI_RANGE)
|
||||
{
|
||||
if (nonzero_p ())
|
||||
{
|
||||
if (TYPE_PRECISION (type ()) == 1)
|
||||
{
|
||||
if (result)
|
||||
*result = m_max;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
value_range_base vr0, vr1;
|
||||
return (ranges_from_anti_range (this, &vr0, &vr1, true)
|
||||
&& vr1.undefined_p ()
|
||||
&& vr0.singleton_p (result));
|
||||
}
|
||||
if (m_kind == VR_RANGE
|
||||
&& vrp_operand_equal_p (min (), max ())
|
||||
&& is_gimple_min_invariant (min ()))
|
||||
|
@ -499,23 +516,28 @@ static assert_locus **asserts_for;
|
|||
/* Return the maximum value for TYPE. */
|
||||
|
||||
tree
|
||||
vrp_val_max (const_tree type)
|
||||
vrp_val_max (const_tree type, bool handle_pointers)
|
||||
{
|
||||
if (!INTEGRAL_TYPE_P (type))
|
||||
return NULL_TREE;
|
||||
|
||||
return TYPE_MAX_VALUE (type);
|
||||
if (INTEGRAL_TYPE_P (type))
|
||||
return TYPE_MAX_VALUE (type);
|
||||
if (POINTER_TYPE_P (type) && handle_pointers)
|
||||
{
|
||||
wide_int max = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
|
||||
return wide_int_to_tree (const_cast<tree> (type), max);
|
||||
}
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* Return the minimum value for TYPE. */
|
||||
|
||||
tree
|
||||
vrp_val_min (const_tree type)
|
||||
vrp_val_min (const_tree type, bool handle_pointers)
|
||||
{
|
||||
if (!INTEGRAL_TYPE_P (type))
|
||||
return NULL_TREE;
|
||||
|
||||
return TYPE_MIN_VALUE (type);
|
||||
if (INTEGRAL_TYPE_P (type))
|
||||
return TYPE_MIN_VALUE (type);
|
||||
if (POINTER_TYPE_P (type) && handle_pointers)
|
||||
return build_zero_cst (const_cast<tree> (type));
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* Return whether VAL is equal to the maximum value of its type.
|
||||
|
@ -626,8 +648,7 @@ intersect_range_with_nonzero_bits (enum value_range_kind vr_type,
|
|||
extract ranges from var + CST op limit. */
|
||||
|
||||
void
|
||||
value_range_base::set_and_canonicalize (enum value_range_kind kind,
|
||||
tree min, tree max)
|
||||
value_range_base::set (enum value_range_kind kind, tree min, tree max)
|
||||
{
|
||||
/* Use the canonical setters for VR_UNDEFINED and VR_VARYING. */
|
||||
if (kind == VR_UNDEFINED)
|
||||
|
@ -645,7 +666,9 @@ value_range_base::set_and_canonicalize (enum value_range_kind kind,
|
|||
if (TREE_CODE (min) != INTEGER_CST
|
||||
|| TREE_CODE (max) != INTEGER_CST)
|
||||
{
|
||||
set (kind, min, max);
|
||||
m_kind = kind;
|
||||
m_min = min;
|
||||
m_max = max;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -681,12 +704,13 @@ value_range_base::set_and_canonicalize (enum value_range_kind kind,
|
|||
kind = kind == VR_RANGE ? VR_ANTI_RANGE : VR_RANGE;
|
||||
}
|
||||
|
||||
tree type = TREE_TYPE (min);
|
||||
|
||||
/* Anti-ranges that can be represented as ranges should be so. */
|
||||
if (kind == VR_ANTI_RANGE)
|
||||
{
|
||||
/* For -fstrict-enums we may receive out-of-range ranges so consider
|
||||
values < -INF and values > INF as -INF/INF as well. */
|
||||
tree type = TREE_TYPE (min);
|
||||
bool is_min = (INTEGRAL_TYPE_P (type)
|
||||
&& tree_int_cst_compare (min, TYPE_MIN_VALUE (type)) <= 0);
|
||||
bool is_max = (INTEGRAL_TYPE_P (type)
|
||||
|
@ -729,22 +753,37 @@ value_range_base::set_and_canonicalize (enum value_range_kind kind,
|
|||
}
|
||||
}
|
||||
|
||||
/* Normalize [MIN, MAX] into VARYING and ~[MIN, MAX] into UNDEFINED.
|
||||
|
||||
Avoid using TYPE_{MIN,MAX}_VALUE because -fstrict-enums can
|
||||
restrict those to a subset of what actually fits in the type.
|
||||
Instead use the extremes of the type precision which will allow
|
||||
compare_range_with_value() to check if a value is inside a range,
|
||||
whereas if we used TYPE_*_VAL, said function would just punt
|
||||
upon seeing a VARYING. */
|
||||
unsigned prec = TYPE_PRECISION (type);
|
||||
signop sign = TYPE_SIGN (type);
|
||||
if (wi::eq_p (wi::to_wide (min), wi::min_value (prec, sign))
|
||||
&& wi::eq_p (wi::to_wide (max), wi::max_value (prec, sign)))
|
||||
{
|
||||
if (kind == VR_RANGE)
|
||||
set_varying ();
|
||||
else if (kind == VR_ANTI_RANGE)
|
||||
set_undefined ();
|
||||
else
|
||||
gcc_unreachable ();
|
||||
return;
|
||||
}
|
||||
|
||||
/* Do not drop [-INF(OVF), +INF(OVF)] to varying. (OVF) has to be sticky
|
||||
to make sure VRP iteration terminates, otherwise we can get into
|
||||
oscillations. */
|
||||
|
||||
set (kind, min, max);
|
||||
}
|
||||
|
||||
void
|
||||
value_range::set_and_canonicalize (enum value_range_kind kind,
|
||||
tree min, tree max, bitmap equiv)
|
||||
{
|
||||
value_range_base::set_and_canonicalize (kind, min, max);
|
||||
if (this->kind () == VR_RANGE || this->kind () == VR_ANTI_RANGE)
|
||||
set_equiv (equiv);
|
||||
else
|
||||
equiv_clear ();
|
||||
m_kind = kind;
|
||||
m_min = min;
|
||||
m_max = max;
|
||||
if (flag_checking)
|
||||
check ();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1180,7 +1219,8 @@ vrp_set_zero_nonzero_bits (const tree expr_type,
|
|||
|
||||
static bool
|
||||
ranges_from_anti_range (const value_range_base *ar,
|
||||
value_range_base *vr0, value_range_base *vr1)
|
||||
value_range_base *vr0, value_range_base *vr1,
|
||||
bool handle_pointers)
|
||||
{
|
||||
tree type = ar->type ();
|
||||
|
||||
|
@ -1193,18 +1233,18 @@ ranges_from_anti_range (const value_range_base *ar,
|
|||
if (ar->kind () != VR_ANTI_RANGE
|
||||
|| TREE_CODE (ar->min ()) != INTEGER_CST
|
||||
|| TREE_CODE (ar->max ()) != INTEGER_CST
|
||||
|| !vrp_val_min (type)
|
||||
|| !vrp_val_max (type))
|
||||
|| !vrp_val_min (type, handle_pointers)
|
||||
|| !vrp_val_max (type, handle_pointers))
|
||||
return false;
|
||||
|
||||
if (tree_int_cst_lt (vrp_val_min (type), ar->min ()))
|
||||
if (tree_int_cst_lt (vrp_val_min (type, handle_pointers), ar->min ()))
|
||||
vr0->set (VR_RANGE,
|
||||
vrp_val_min (type),
|
||||
vrp_val_min (type, handle_pointers),
|
||||
wide_int_to_tree (type, wi::to_wide (ar->min ()) - 1));
|
||||
if (tree_int_cst_lt (ar->max (), vrp_val_max (type)))
|
||||
if (tree_int_cst_lt (ar->max (), vrp_val_max (type, handle_pointers)))
|
||||
vr1->set (VR_RANGE,
|
||||
wide_int_to_tree (type, wi::to_wide (ar->max ()) + 1),
|
||||
vrp_val_max (type));
|
||||
vrp_val_max (type, handle_pointers));
|
||||
if (vr0->undefined_p ())
|
||||
{
|
||||
*vr0 = *vr1;
|
||||
|
@ -1215,21 +1255,20 @@ ranges_from_anti_range (const value_range_base *ar,
|
|||
}
|
||||
|
||||
/* Extract the components of a value range into a pair of wide ints in
|
||||
[WMIN, WMAX].
|
||||
|
||||
If the value range is anything but a VR_*RANGE of constants, the
|
||||
resulting wide ints are set to [-MIN, +MAX] for the type. */
|
||||
[WMIN, WMAX], after having normalized any symbolics from the input. */
|
||||
|
||||
static void inline
|
||||
extract_range_into_wide_ints (const value_range_base *vr,
|
||||
signop sign, unsigned prec,
|
||||
wide_int &wmin, wide_int &wmax)
|
||||
extract_range_into_wide_ints (const value_range_base *vr_,
|
||||
tree type, wide_int &wmin, wide_int &wmax)
|
||||
{
|
||||
gcc_assert (vr->kind () != VR_ANTI_RANGE || vr->symbolic_p ());
|
||||
if (range_int_cst_p (vr))
|
||||
signop sign = TYPE_SIGN (type);
|
||||
unsigned int prec = TYPE_PRECISION (type);
|
||||
gcc_assert (vr_->kind () != VR_ANTI_RANGE || vr_->symbolic_p ());
|
||||
value_range vr = vr_->normalize_symbolics ();
|
||||
if (range_int_cst_p (&vr))
|
||||
{
|
||||
wmin = wi::to_wide (vr->min ());
|
||||
wmax = wi::to_wide (vr->max ());
|
||||
wmin = wi::to_wide (vr.min ());
|
||||
wmax = wi::to_wide (vr.max ());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1256,12 +1295,31 @@ extract_range_from_multiplicative_op (value_range_base *vr,
|
|||
|| code == ROUND_DIV_EXPR
|
||||
|| code == RSHIFT_EXPR
|
||||
|| code == LSHIFT_EXPR);
|
||||
gcc_assert (vr0->kind () == VR_RANGE
|
||||
&& vr0->kind () == vr1->kind ());
|
||||
if (!range_int_cst_p (vr1))
|
||||
{
|
||||
vr->set_varying ();
|
||||
return;
|
||||
}
|
||||
|
||||
/* Even if vr0 is VARYING or otherwise not usable, we can derive
|
||||
useful ranges just from the shift count. E.g.
|
||||
x >> 63 for signed 64-bit x is always [-1, 0]. */
|
||||
value_range_base tem = vr0->normalize_symbolics ();
|
||||
tree vr0_min, vr0_max;
|
||||
if (tem.kind () == VR_RANGE)
|
||||
{
|
||||
vr0_min = tem.min ();
|
||||
vr0_max = tem.max ();
|
||||
}
|
||||
else
|
||||
{
|
||||
vr0_min = vrp_val_min (type);
|
||||
vr0_max = vrp_val_max (type);
|
||||
}
|
||||
|
||||
wide_int res_lb, res_ub;
|
||||
wide_int vr0_lb = wi::to_wide (vr0->min ());
|
||||
wide_int vr0_ub = wi::to_wide (vr0->max ());
|
||||
wide_int vr0_lb = wi::to_wide (vr0_min);
|
||||
wide_int vr0_ub = wi::to_wide (vr0_max);
|
||||
wide_int vr1_lb = wi::to_wide (vr1->min ());
|
||||
wide_int vr1_ub = wi::to_wide (vr1->max ());
|
||||
bool overflow_undefined = TYPE_OVERFLOW_UNDEFINED (type);
|
||||
|
@ -1271,9 +1329,8 @@ extract_range_from_multiplicative_op (value_range_base *vr,
|
|||
code, TYPE_SIGN (type), prec,
|
||||
vr0_lb, vr0_ub, vr1_lb, vr1_ub,
|
||||
overflow_undefined))
|
||||
vr->set_and_canonicalize (VR_RANGE,
|
||||
wide_int_to_tree (type, res_lb),
|
||||
wide_int_to_tree (type, res_ub));
|
||||
vr->set (VR_RANGE, wide_int_to_tree (type, res_lb),
|
||||
wide_int_to_tree (type, res_ub));
|
||||
else
|
||||
vr->set_varying ();
|
||||
}
|
||||
|
@ -1667,19 +1724,30 @@ extract_range_from_binary_expr (value_range_base *vr,
|
|||
range and see what we end up with. */
|
||||
if (code == PLUS_EXPR || code == MINUS_EXPR)
|
||||
{
|
||||
value_range_kind vr0_kind = vr0.kind (), vr1_kind = vr1.kind ();
|
||||
tree vr0_min = vr0.min (), vr0_max = vr0.max ();
|
||||
tree vr1_min = vr1.min (), vr1_max = vr1.max ();
|
||||
/* This will normalize things such that calculating
|
||||
[0,0] - VR_VARYING is not dropped to varying, but is
|
||||
calculated as [MIN+1, MAX]. */
|
||||
if (vr0.varying_p ())
|
||||
vr0.set (VR_RANGE, vrp_val_min (expr_type), vrp_val_max (expr_type));
|
||||
{
|
||||
vr0_kind = VR_RANGE;
|
||||
vr0_min = vrp_val_min (expr_type);
|
||||
vr0_max = vrp_val_max (expr_type);
|
||||
}
|
||||
if (vr1.varying_p ())
|
||||
vr1.set (VR_RANGE, vrp_val_min (expr_type), vrp_val_max (expr_type));
|
||||
{
|
||||
vr1_kind = VR_RANGE;
|
||||
vr1_min = vrp_val_min (expr_type);
|
||||
vr1_max = vrp_val_max (expr_type);
|
||||
}
|
||||
|
||||
const bool minus_p = (code == MINUS_EXPR);
|
||||
tree min_op0 = vr0.min ();
|
||||
tree min_op1 = minus_p ? vr1.max () : vr1.min ();
|
||||
tree max_op0 = vr0.max ();
|
||||
tree max_op1 = minus_p ? vr1.min () : vr1.max ();
|
||||
tree min_op0 = vr0_min;
|
||||
tree min_op1 = minus_p ? vr1_max : vr1_min;
|
||||
tree max_op0 = vr0_max;
|
||||
tree max_op1 = minus_p ? vr1_min : vr1_max;
|
||||
tree sym_min_op0 = NULL_TREE;
|
||||
tree sym_min_op1 = NULL_TREE;
|
||||
tree sym_max_op0 = NULL_TREE;
|
||||
|
@ -1692,7 +1760,7 @@ extract_range_from_binary_expr (value_range_base *vr,
|
|||
single-symbolic ranges, try to compute the precise resulting range,
|
||||
but only if we know that this resulting range will also be constant
|
||||
or single-symbolic. */
|
||||
if (vr0.kind () == VR_RANGE && vr1.kind () == VR_RANGE
|
||||
if (vr0_kind == VR_RANGE && vr1_kind == VR_RANGE
|
||||
&& (TREE_CODE (min_op0) == INTEGER_CST
|
||||
|| (sym_min_op0
|
||||
= get_single_symbol (min_op0, &neg_min_op0, &min_op0)))
|
||||
|
@ -1772,8 +1840,8 @@ extract_range_from_binary_expr (value_range_base *vr,
|
|||
wide_int wmin, wmax;
|
||||
wide_int vr0_min, vr0_max;
|
||||
wide_int vr1_min, vr1_max;
|
||||
extract_range_into_wide_ints (&vr0, sign, prec, vr0_min, vr0_max);
|
||||
extract_range_into_wide_ints (&vr1, sign, prec, vr1_min, vr1_max);
|
||||
extract_range_into_wide_ints (&vr0, expr_type, vr0_min, vr0_max);
|
||||
extract_range_into_wide_ints (&vr1, expr_type, vr1_min, vr1_max);
|
||||
if (wide_int_range_min_max (wmin, wmax, code, sign, prec,
|
||||
vr0_min, vr0_max, vr1_min, vr1_max))
|
||||
vr->set (VR_RANGE, wide_int_to_tree (expr_type, wmin),
|
||||
|
@ -1805,12 +1873,6 @@ extract_range_from_binary_expr (value_range_base *vr,
|
|||
{
|
||||
if (code == RSHIFT_EXPR)
|
||||
{
|
||||
/* Even if vr0 is VARYING or otherwise not usable, we can derive
|
||||
useful ranges just from the shift count. E.g.
|
||||
x >> 63 for signed 64-bit x is always [-1, 0]. */
|
||||
if (vr0.kind () != VR_RANGE || vr0.symbolic_p ())
|
||||
vr0.set (VR_RANGE, vrp_val_min (expr_type),
|
||||
vrp_val_max (expr_type));
|
||||
extract_range_from_multiplicative_op (vr, code, expr_type,
|
||||
&vr0, &vr1);
|
||||
return;
|
||||
|
@ -1828,7 +1890,7 @@ extract_range_from_binary_expr (value_range_base *vr,
|
|||
{
|
||||
min = wide_int_to_tree (expr_type, res_lb);
|
||||
max = wide_int_to_tree (expr_type, res_ub);
|
||||
vr->set_and_canonicalize (VR_RANGE, min, max);
|
||||
vr->set (VR_RANGE, min, max);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -1860,9 +1922,9 @@ extract_range_from_binary_expr (value_range_base *vr,
|
|||
NOTE: As a future improvement, we may be able to do better
|
||||
with mixed symbolic (anti-)ranges like [0, A]. See note in
|
||||
ranges_from_anti_range. */
|
||||
extract_range_into_wide_ints (&vr0, sign, prec,
|
||||
extract_range_into_wide_ints (&vr0, expr_type,
|
||||
dividend_min, dividend_max);
|
||||
extract_range_into_wide_ints (&vr1, sign, prec,
|
||||
extract_range_into_wide_ints (&vr1, expr_type,
|
||||
divisor_min, divisor_max);
|
||||
if (!wide_int_range_div (wmin, wmax, code, sign, prec,
|
||||
dividend_min, dividend_max,
|
||||
|
@ -1893,8 +1955,8 @@ extract_range_from_binary_expr (value_range_base *vr,
|
|||
}
|
||||
wide_int wmin, wmax, tmp;
|
||||
wide_int vr0_min, vr0_max, vr1_min, vr1_max;
|
||||
extract_range_into_wide_ints (&vr0, sign, prec, vr0_min, vr0_max);
|
||||
extract_range_into_wide_ints (&vr1, sign, prec, vr1_min, vr1_max);
|
||||
extract_range_into_wide_ints (&vr0, expr_type, vr0_min, vr0_max);
|
||||
extract_range_into_wide_ints (&vr1, expr_type, vr1_min, vr1_max);
|
||||
wide_int_range_trunc_mod (wmin, wmax, sign, prec,
|
||||
vr0_min, vr0_max, vr1_min, vr1_max);
|
||||
min = wide_int_to_tree (expr_type, wmin);
|
||||
|
@ -1912,8 +1974,8 @@ extract_range_from_binary_expr (value_range_base *vr,
|
|||
&may_be_nonzero0, &must_be_nonzero0);
|
||||
vrp_set_zero_nonzero_bits (expr_type, &vr1,
|
||||
&may_be_nonzero1, &must_be_nonzero1);
|
||||
extract_range_into_wide_ints (&vr0, sign, prec, vr0_min, vr0_max);
|
||||
extract_range_into_wide_ints (&vr1, sign, prec, vr1_min, vr1_max);
|
||||
extract_range_into_wide_ints (&vr0, expr_type, vr0_min, vr0_max);
|
||||
extract_range_into_wide_ints (&vr1, expr_type, vr1_min, vr1_max);
|
||||
if (code == BIT_AND_EXPR)
|
||||
{
|
||||
if (wide_int_range_bit_and (wmin, wmax, sign, prec,
|
||||
|
@ -2117,8 +2179,7 @@ extract_range_from_unary_expr (value_range_base *vr,
|
|||
signop outer_sign = TYPE_SIGN (outer_type);
|
||||
unsigned inner_prec = TYPE_PRECISION (inner_type);
|
||||
unsigned outer_prec = TYPE_PRECISION (outer_type);
|
||||
extract_range_into_wide_ints (&vr0, inner_sign, inner_prec,
|
||||
vr0_min, vr0_max);
|
||||
extract_range_into_wide_ints (&vr0, inner_type, vr0_min, vr0_max);
|
||||
if (wide_int_range_convert (wmin, wmax,
|
||||
inner_sign, inner_prec,
|
||||
outer_sign, outer_prec,
|
||||
|
@ -2126,7 +2187,7 @@ extract_range_from_unary_expr (value_range_base *vr,
|
|||
{
|
||||
tree min = wide_int_to_tree (outer_type, wmin);
|
||||
tree max = wide_int_to_tree (outer_type, wmax);
|
||||
vr->set_and_canonicalize (VR_RANGE, min, max);
|
||||
vr->set (VR_RANGE, min, max);
|
||||
}
|
||||
else
|
||||
vr->set_varying ();
|
||||
|
@ -2136,7 +2197,7 @@ extract_range_from_unary_expr (value_range_base *vr,
|
|||
{
|
||||
wide_int wmin, wmax;
|
||||
wide_int vr0_min, vr0_max;
|
||||
extract_range_into_wide_ints (&vr0, sign, prec, vr0_min, vr0_max);
|
||||
extract_range_into_wide_ints (&vr0, type, vr0_min, vr0_max);
|
||||
if (wide_int_range_abs (wmin, wmax, sign, prec, vr0_min, vr0_max,
|
||||
TYPE_OVERFLOW_UNDEFINED (type)))
|
||||
vr->set (VR_RANGE, wide_int_to_tree (type, wmin),
|
||||
|
@ -2149,7 +2210,8 @@ extract_range_from_unary_expr (value_range_base *vr,
|
|||
{
|
||||
wide_int wmin, wmax;
|
||||
wide_int vr0_min, vr0_max;
|
||||
extract_range_into_wide_ints (&vr0, SIGNED, prec, vr0_min, vr0_max);
|
||||
tree signed_type = make_signed_type (TYPE_PRECISION (type));
|
||||
extract_range_into_wide_ints (&vr0, signed_type, vr0_min, vr0_max);
|
||||
wide_int_range_absu (wmin, wmax, prec, vr0_min, vr0_max);
|
||||
vr->set (VR_RANGE, wide_int_to_tree (type, wmin),
|
||||
wide_int_to_tree (type, wmax));
|
||||
|
@ -6038,7 +6100,7 @@ value_range_base::intersect_helper (const value_range_base *vr0,
|
|||
VR_RANGE can still be a VR_RANGE. Work on a temporary so we can
|
||||
fall back to vr0 when this turns things to varying. */
|
||||
value_range_base tem;
|
||||
tem.set_and_canonicalize (vr0type, vr0min, vr0max);
|
||||
tem.set (vr0type, vr0min, vr0max);
|
||||
/* If that failed, use the saved original VR0. */
|
||||
if (tem.varying_p ())
|
||||
return *vr0;
|
||||
|
@ -6143,7 +6205,7 @@ value_range_base::union_helper (const value_range_base *vr0,
|
|||
|
||||
/* Work on a temporary so we can still use vr0 when union returns varying. */
|
||||
value_range_base tem;
|
||||
tem.set_and_canonicalize (vr0type, vr0min, vr0max);
|
||||
tem.set (vr0type, vr0min, vr0max);
|
||||
|
||||
/* Failed to find an efficient meet. Before giving up and setting
|
||||
the result to VARYING, see if we can at least derive a useful
|
||||
|
@ -6223,6 +6285,58 @@ value_range::union_ (const value_range *other)
|
|||
}
|
||||
}
|
||||
|
||||
/* Normalize symbolics into constants. */
|
||||
|
||||
value_range_base
|
||||
value_range_base::normalize_symbolics () const
|
||||
{
|
||||
if (varying_p () || undefined_p ())
|
||||
return *this;
|
||||
tree ttype = type ();
|
||||
bool min_symbolic = !is_gimple_min_invariant (min ());
|
||||
bool max_symbolic = !is_gimple_min_invariant (max ());
|
||||
if (!min_symbolic && !max_symbolic)
|
||||
return *this;
|
||||
|
||||
// [SYM, SYM] -> VARYING
|
||||
if (min_symbolic && max_symbolic)
|
||||
{
|
||||
value_range_base var;
|
||||
var.set_varying ();
|
||||
return var;
|
||||
}
|
||||
if (kind () == VR_RANGE)
|
||||
{
|
||||
// [SYM, NUM] -> [-MIN, NUM]
|
||||
if (min_symbolic)
|
||||
return value_range_base (VR_RANGE, vrp_val_min (ttype), max ());
|
||||
// [NUM, SYM] -> [NUM, +MAX]
|
||||
return value_range_base (VR_RANGE, min (), vrp_val_max (ttype));
|
||||
}
|
||||
gcc_assert (kind () == VR_ANTI_RANGE);
|
||||
// ~[SYM, NUM] -> [NUM + 1, +MAX]
|
||||
if (min_symbolic)
|
||||
{
|
||||
if (!vrp_val_is_max (max ()))
|
||||
{
|
||||
tree n = wide_int_to_tree (ttype, wi::to_wide (max ()) + 1);
|
||||
return value_range_base (VR_RANGE, n, vrp_val_max (ttype));
|
||||
}
|
||||
value_range_base var;
|
||||
var.set_varying ();
|
||||
return var;
|
||||
}
|
||||
// ~[NUM, SYM] -> [-MIN, NUM - 1]
|
||||
if (!vrp_val_is_min (min ()))
|
||||
{
|
||||
tree n = wide_int_to_tree (ttype, wi::to_wide (min ()) - 1);
|
||||
return value_range_base (VR_RANGE, vrp_val_min (ttype), n);
|
||||
}
|
||||
value_range_base var;
|
||||
var.set_varying ();
|
||||
return var;
|
||||
}
|
||||
|
||||
/* Visit all arguments for PHI node PHI that flow through executable
|
||||
edges. If a valid value range can be derived from all the incoming
|
||||
value ranges, set a new range for the LHS of PHI. */
|
||||
|
|
|
@ -71,12 +71,13 @@ public:
|
|||
/* Misc methods. */
|
||||
tree type () const;
|
||||
bool may_contain_p (tree) const;
|
||||
void set_and_canonicalize (enum value_range_kind, tree, tree);
|
||||
bool zero_p () const;
|
||||
bool nonzero_p () const;
|
||||
bool singleton_p (tree *result = NULL) const;
|
||||
void dump (FILE *) const;
|
||||
|
||||
value_range_base normalize_symbolics () const;
|
||||
|
||||
protected:
|
||||
void check ();
|
||||
static value_range_base union_helper (const value_range_base *,
|
||||
|
@ -143,7 +144,6 @@ class GTY((user)) value_range : public value_range_base
|
|||
|
||||
/* Misc methods. */
|
||||
void deep_copy (const value_range *);
|
||||
void set_and_canonicalize (enum value_range_kind, tree, tree, bitmap = NULL);
|
||||
void dump (FILE *) const;
|
||||
|
||||
private:
|
||||
|
@ -270,8 +270,8 @@ extern int operand_less_p (tree, tree);
|
|||
extern bool vrp_val_is_min (const_tree);
|
||||
extern bool vrp_val_is_max (const_tree);
|
||||
|
||||
extern tree vrp_val_min (const_tree);
|
||||
extern tree vrp_val_max (const_tree);
|
||||
extern tree vrp_val_min (const_tree, bool handle_pointers = false);
|
||||
extern tree vrp_val_max (const_tree, bool handle_pointers = false);
|
||||
|
||||
extern void extract_range_from_unary_expr (value_range_base *vr,
|
||||
enum tree_code code,
|
||||
|
|
|
@ -522,9 +522,9 @@ vr_values::extract_range_for_var_from_comparison_expr (tree var,
|
|||
vice-versa. Use set_and_canonicalize which does this for
|
||||
us. */
|
||||
if (cond_code == LE_EXPR)
|
||||
vr_p->set_and_canonicalize (VR_RANGE, min, max, vr_p->equiv ());
|
||||
vr_p->set (VR_RANGE, min, max, vr_p->equiv ());
|
||||
else if (cond_code == GT_EXPR)
|
||||
vr_p->set_and_canonicalize (VR_ANTI_RANGE, min, max, vr_p->equiv ());
|
||||
vr_p->set (VR_ANTI_RANGE, min, max, vr_p->equiv ());
|
||||
else
|
||||
gcc_unreachable ();
|
||||
}
|
||||
|
@ -596,7 +596,7 @@ vr_values::extract_range_for_var_from_comparison_expr (tree var,
|
|||
&& vrp_val_is_max (max))
|
||||
min = max = limit;
|
||||
|
||||
vr_p->set_and_canonicalize (VR_ANTI_RANGE, min, max, vr_p->equiv ());
|
||||
vr_p->set (VR_ANTI_RANGE, min, max, vr_p->equiv ());
|
||||
}
|
||||
else if (cond_code == LE_EXPR || cond_code == LT_EXPR)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue