Cleanups to frange.
These are some assorted cleanups to the frange class to make it easier to drop in an implementation with FP endpoints: * frange::set() had some asserts limiting the type of arguments passed. There's no reason why we can't handle all the variants. Worse comes to worse, we can always return a VARYING which is conservative and correct. * frange::normalize_kind() now returns a boolean that can be used in union and intersection to indicate that the range changed. * Implement vrp_val_max and vrp_val_min for floats. Also, move them earlier in the header file so frange can use them. Tested on x86-64 Linux. gcc/ChangeLog: * value-range.cc (tree_compare): New. (frange::set): Make more general. (frange::normalize_kind): Cleanup and return bool. (frange::union_): Use normalize_kind return value. (frange::intersect): Same. (frange::verify_range): Remove unnecessary else. * value-range.h (vrp_val_max): Move before frange class. (vrp_val_min): Same. (frange::frange): Remove set to m_type.
This commit is contained in:
parent
7e029e067d
commit
3f05605364
@ -260,66 +260,93 @@ frange::accept (const vrange_visitor &v) const
|
||||
v.visit (*this);
|
||||
}
|
||||
|
||||
// Setter for franges. Currently only singletons are supported.
|
||||
// Helper function to compare floats. Returns TRUE if op1 .CODE. op2
|
||||
// is nonzero.
|
||||
|
||||
static inline bool
|
||||
tree_compare (tree_code code, tree op1, tree op2)
|
||||
{
|
||||
return !integer_zerop (fold_build2 (code, integer_type_node, op1, op2));
|
||||
}
|
||||
|
||||
// Setter for franges.
|
||||
|
||||
void
|
||||
frange::set (tree min, tree max, value_range_kind kind)
|
||||
{
|
||||
gcc_checking_assert (kind == VR_RANGE);
|
||||
gcc_checking_assert (operand_equal_p (min, max));
|
||||
gcc_checking_assert (TREE_CODE (min) == REAL_CST);
|
||||
gcc_checking_assert (TREE_CODE (max) == REAL_CST);
|
||||
|
||||
if (kind == VR_UNDEFINED)
|
||||
{
|
||||
set_undefined ();
|
||||
return;
|
||||
}
|
||||
|
||||
// Treat VR_ANTI_RANGE and VR_VARYING as varying.
|
||||
if (kind != VR_RANGE)
|
||||
{
|
||||
set_varying (TREE_TYPE (min));
|
||||
return;
|
||||
}
|
||||
|
||||
m_kind = kind;
|
||||
m_type = TREE_TYPE (min);
|
||||
|
||||
REAL_VALUE_TYPE *const cst = TREE_REAL_CST_PTR (min);
|
||||
if (real_isnan (cst))
|
||||
m_props.nan_set_yes ();
|
||||
// Mark NANness.
|
||||
if (real_isnan (TREE_REAL_CST_PTR (min))
|
||||
|| real_isnan (TREE_REAL_CST_PTR (max)))
|
||||
{
|
||||
gcc_checking_assert (operand_equal_p (min, max));
|
||||
m_props.nan_set_yes ();
|
||||
}
|
||||
else
|
||||
m_props.nan_set_no ();
|
||||
|
||||
if (real_isinf (cst))
|
||||
bool is_min = vrp_val_is_min (min);
|
||||
bool is_max = vrp_val_is_max (max);
|
||||
|
||||
// Mark when the endpoints can't be INF.
|
||||
if (!is_min)
|
||||
m_props.ninf_set_no ();
|
||||
if (!is_max)
|
||||
m_props.inf_set_no ();
|
||||
|
||||
// Mark when the endpoints are definitely INF.
|
||||
if (operand_equal_p (min, max))
|
||||
{
|
||||
if (real_isneg (cst))
|
||||
{
|
||||
m_props.inf_set_no ();
|
||||
m_props.ninf_set_yes ();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_props.inf_set_yes ();
|
||||
m_props.ninf_set_no ();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_props.inf_set_no ();
|
||||
m_props.ninf_set_no ();
|
||||
if (is_min)
|
||||
m_props.ninf_set_yes ();
|
||||
else if (is_max)
|
||||
m_props.inf_set_yes ();
|
||||
}
|
||||
|
||||
// Check for swapped ranges.
|
||||
gcc_checking_assert (m_props.nan_yes_p ()
|
||||
|| tree_compare (LE_EXPR, min, max));
|
||||
|
||||
if (flag_checking)
|
||||
verify_range ();
|
||||
}
|
||||
|
||||
// Normalize range to VARYING or UNDEFINED, or vice versa.
|
||||
// Normalize range to VARYING or UNDEFINED, or vice versa. Return
|
||||
// TRUE if anything changed.
|
||||
//
|
||||
// A range with no known properties can be dropped to VARYING.
|
||||
// Similarly, a VARYING with any properties should be dropped to a
|
||||
// VR_RANGE. Normalizing ranges upon changing them ensures there is
|
||||
// only one representation for a given range.
|
||||
|
||||
void
|
||||
bool
|
||||
frange::normalize_kind ()
|
||||
{
|
||||
if (m_kind == VR_RANGE)
|
||||
{
|
||||
// No FP properties set means varying.
|
||||
if (m_props.nan_varying_p ()
|
||||
&& m_props.inf_varying_p ()
|
||||
&& m_props.ninf_varying_p ())
|
||||
if (m_props.varying_p ())
|
||||
{
|
||||
set_varying (m_type);
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
// Undefined is viral.
|
||||
if (m_props.nan_undefined_p ()
|
||||
@ -327,17 +354,19 @@ frange::normalize_kind ()
|
||||
|| m_props.ninf_undefined_p ())
|
||||
{
|
||||
set_undefined ();
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (m_kind == VR_VARYING)
|
||||
{
|
||||
// If a VARYING has any FP properties, it's no longer VARYING.
|
||||
if (!m_props.nan_varying_p ()
|
||||
|| !m_props.inf_varying_p ()
|
||||
|| !m_props.ninf_varying_p ())
|
||||
m_kind = VR_RANGE;
|
||||
if (!m_props.varying_p ())
|
||||
{
|
||||
m_kind = VR_RANGE;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
@ -354,7 +383,7 @@ frange::union_ (const vrange &v)
|
||||
}
|
||||
|
||||
bool ret = m_props.union_ (r.m_props);
|
||||
normalize_kind ();
|
||||
ret |= normalize_kind ();
|
||||
|
||||
if (flag_checking)
|
||||
verify_range ();
|
||||
@ -380,7 +409,7 @@ frange::intersect (const vrange &v)
|
||||
}
|
||||
|
||||
bool ret = m_props.intersect (r.m_props);
|
||||
normalize_kind ();
|
||||
ret |= normalize_kind ();
|
||||
|
||||
if (flag_checking)
|
||||
verify_range ();
|
||||
@ -429,12 +458,11 @@ frange::verify_range ()
|
||||
gcc_checking_assert (m_props.undefined_p ());
|
||||
return;
|
||||
}
|
||||
else if (varying_p ())
|
||||
if (varying_p ())
|
||||
{
|
||||
gcc_checking_assert (m_props.varying_p ());
|
||||
return;
|
||||
}
|
||||
|
||||
gcc_checking_assert (m_kind == VR_RANGE);
|
||||
gcc_checking_assert (!m_props.varying_p () && !m_props.undefined_p ());
|
||||
}
|
||||
|
@ -359,7 +359,7 @@ public:
|
||||
FRANGE_PROP_ACCESSOR(ninf)
|
||||
private:
|
||||
void verify_range ();
|
||||
void normalize_kind ();
|
||||
bool normalize_kind ();
|
||||
|
||||
frange_props m_props;
|
||||
tree m_type;
|
||||
@ -1010,6 +1010,45 @@ irange::normalize_kind ()
|
||||
}
|
||||
}
|
||||
|
||||
// Return the maximum value for TYPE.
|
||||
|
||||
inline tree
|
||||
vrp_val_max (const_tree type)
|
||||
{
|
||||
if (INTEGRAL_TYPE_P (type))
|
||||
return TYPE_MAX_VALUE (type);
|
||||
if (POINTER_TYPE_P (type))
|
||||
{
|
||||
wide_int max = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
|
||||
return wide_int_to_tree (const_cast<tree> (type), max);
|
||||
}
|
||||
if (frange::supports_p (type))
|
||||
{
|
||||
REAL_VALUE_TYPE real;
|
||||
real_inf (&real);
|
||||
return build_real (const_cast <tree> (type), real);
|
||||
}
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
// Return the minimum value for TYPE.
|
||||
|
||||
inline tree
|
||||
vrp_val_min (const_tree type)
|
||||
{
|
||||
if (INTEGRAL_TYPE_P (type))
|
||||
return TYPE_MIN_VALUE (type);
|
||||
if (POINTER_TYPE_P (type))
|
||||
return build_zero_cst (const_cast<tree> (type));
|
||||
if (frange::supports_p (type))
|
||||
{
|
||||
REAL_VALUE_TYPE real, real_ninf;
|
||||
real_inf (&real);
|
||||
real_ninf = real_value_negate (&real);
|
||||
return build_real (const_cast <tree> (type), real_ninf);
|
||||
}
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
// Supporting methods for frange.
|
||||
|
||||
@ -1039,7 +1078,6 @@ inline
|
||||
frange::frange ()
|
||||
{
|
||||
m_discriminator = VR_FRANGE;
|
||||
m_type = nullptr;
|
||||
set_undefined ();
|
||||
}
|
||||
|
||||
@ -1072,32 +1110,4 @@ frange::set_undefined ()
|
||||
m_props.set_undefined ();
|
||||
}
|
||||
|
||||
|
||||
// Return the maximum value for TYPE.
|
||||
|
||||
inline tree
|
||||
vrp_val_max (const_tree type)
|
||||
{
|
||||
if (INTEGRAL_TYPE_P (type))
|
||||
return TYPE_MAX_VALUE (type);
|
||||
if (POINTER_TYPE_P (type))
|
||||
{
|
||||
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.
|
||||
|
||||
inline tree
|
||||
vrp_val_min (const_tree type)
|
||||
{
|
||||
if (INTEGRAL_TYPE_P (type))
|
||||
return TYPE_MIN_VALUE (type);
|
||||
if (POINTER_TYPE_P (type))
|
||||
return build_zero_cst (const_cast<tree> (type));
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
#endif // GCC_VALUE_RANGE_H
|
||||
|
Loading…
Reference in New Issue
Block a user