if (lhs ())
r2.set_varying (TREE_TYPE (lhs ()));
else
- r2.set_undefined (r1.type ());
+ r2.set_undefined ();
return fold (res, r1, r2);
}
tree type = TREE_TYPE (operand1 ());
if (lhs_range.undefined_p ())
{
- r.set_undefined (type);
+ r.set_undefined ();
return true;
}
// Unary operations require the type of the first operand in the second range
// An empty range is viral, so return an empty range.
if (op2_range.undefined_p () || lhs_range.undefined_p ())
{
- r.set_undefined (type);
+ r.set_undefined ();
return true;
}
return handler ()->op1_range (r, type, lhs_range, op2_range);
// An empty range is viral, so return an empty range.
if (op1_range.undefined_p () || lhs_range.undefined_p ())
{
- r.set_undefined (type);
+ r.set_undefined ();
return true;
}
return handler ()->op2_range (r, type, lhs_range, op1_range);
bool res = false;
// Clear and set result type.
- r.set_undefined (type);
+ r.set_undefined ();
if (lh.undefined_p () || rh.undefined_p ())
return true;
// undefined and return true.
inline bool
-empty_range_check (irange &r, const irange &op1, const irange & op2, tree type)
+empty_range_check (irange &r, const irange &op1, const irange & op2)
{
if (op1.undefined_p () || op2.undefined_p ())
{
- r.set_undefined (type);
+ r.set_undefined ();
return true;
}
else
/* If there is no result, then this is unexectuable, so no range. */
if (lhs.undefined_p ())
{
- r.set_undefined (val_type);
+ r.set_undefined ();
return BRS_EMPTY;
}
operator_equal::fold_range (irange &r, tree type, const irange &op1,
const irange &op2) const
{
- if (empty_range_check (r, op1, op2, type))
+ if (empty_range_check (r, op1, op2))
return true;
/* We can be sure the values are always equal or not if both ranges
operator_not_equal::fold_range (irange &r, tree type, const irange &op1,
const irange &op2) const
{
- if (empty_range_check (r, op1, op2, type))
+ if (empty_range_check (r, op1, op2))
return true;
/* We can be sure the values are always equal or not if both ranges
/* If val - 1 underflows, check is X < MIN, which is an empty range. */
if (ov)
- r.set_undefined (type);
+ r.set_undefined ();
else
r = irange (type, min_limit (type), lim);
}
wide_int lim = wi::add (val, 1, TYPE_SIGN (type), &ov);
/* If val + 1 overflows, check is for X > MAX , which is an empty range. */
if (ov)
- r.set_undefined (type);
+ r.set_undefined ();
else
r = irange (type, lim, max_limit (type));
}
bool
operator_lt::fold_range (irange &r, tree type, const irange &op1, const irange &op2) const
{
- if (empty_range_check (r, op1, op2, type))
+ if (empty_range_check (r, op1, op2))
return true;
signop sign = TYPE_SIGN (op1.type ());
bool
operator_le::fold_range (irange &r, tree type, const irange &op1, const irange &op2) const
{
- if (empty_range_check (r, op1, op2, type))
+ if (empty_range_check (r, op1, op2))
return true;
signop sign = TYPE_SIGN (op1.type ());
bool
operator_gt::fold_range (irange &r, tree type, const irange &op1, const irange &op2) const
{
- if (empty_range_check (r, op1, op2, type))
+ if (empty_range_check (r, op1, op2))
return true;
signop sign = TYPE_SIGN (op1.type ());
bool
operator_ge::fold_range (irange &r, tree type, const irange &op1, const irange &op2) const
{
- if (empty_range_check (r, op1, op2, type))
+ if (empty_range_check (r, op1, op2))
return true;
signop sign = TYPE_SIGN (op1.type ());
r = (type_of(rh)) lh. */
bool
-operator_cast::fold_range (irange &r, tree type, const irange &lh, const irange &rh) const
+operator_cast::fold_range (irange &r, tree type ATTRIBUTE_UNUSED,
+ const irange &lh, const irange &rh) const
{
- if (empty_range_check (r, lh, rh, type))
+ if (empty_range_check (r, lh, rh))
return true;
if (lh.type () != rh.type ())
operator_logical_and::fold_range (irange &r, tree type, const irange &lh,
const irange &rh) const
{
- if (empty_range_check (r, lh, rh, type))
+ if (empty_range_check (r, lh, rh))
return true;
// 0 && anything is 0
// For AND, calculate each subrange separately, and then union
// the results.
irange tmp;
- tmp.set_undefined (type);
+ tmp.set_undefined ();
accumulate_range (tmp, type, new_lb, new_ub);
r.union_ (tmp);
return true;
bool
-operator_logical_or::fold_range (irange &r, tree type, const irange &lh,
- const irange &rh) const
+operator_logical_or::fold_range (irange &r, tree type ATTRIBUTE_UNUSED,
+ const irange &lh, const irange &rh) const
{
- if (empty_range_check (r, lh, rh, type))
+ if (empty_range_check (r, lh, rh))
return true;
r = range_union (lh, rh);
operator_logical_not::fold_range (irange &r, tree type, const irange &lh,
const irange &rh ATTRIBUTE_UNUSED) const
{
- if (empty_range_check (r, lh, rh, type))
+ if (empty_range_check (r, lh, rh))
return true;
if (lh.varying_p () || lh.undefined_p ())
operator_bitwise_not::fold_range (irange &r, tree type, const irange &lh,
const irange &rh) const
{
- if (empty_range_check (r, lh, rh, type))
+ if (empty_range_check (r, lh, rh))
return true;
// ~X is simply -1 - X.
operator_abs::op1_range (irange &r, tree type,
const irange &lhs, const irange &op2) const
{
- if (empty_range_check (r, lhs, op2, type))
+ if (empty_range_check (r, lhs, op2))
return true;
if (TYPE_UNSIGNED (type))
{
operator_negate::fold_range (irange &r, tree type,
const irange &lh, const irange &rh) const
{
- if (empty_range_check (r, lh, rh, type))
+ if (empty_range_check (r, lh, rh))
return true;
// -X is simply 0 - X.
return range_op_handler (MINUS_EXPR, type)->fold_range (r, type, range_zero (type),
operator_addr_expr::fold_range (irange &r, tree type, const irange &lh,
const irange &rh) const
{
- if (empty_range_check (r, lh, rh, type))
+ if (empty_range_check (r, lh, rh))
return true;
// Return a non-null pointer of the LHS type (passed in op2)
signop sign = TYPE_SIGN (type);
irange r;
if (sign == UNSIGNED)
- r.set_undefined (type);
+ r.set_undefined ();
else
r = irange (type, wi::min_value (prec, sign), wi::minus_one (prec));
return r;
r0 = range_zero (boolean_type_node);
ASSERT_TRUE (r0 == irange (build_zero_cst (boolean_type_node),
build_zero_cst (boolean_type_node)));
- r0.invert();
+ r0.invert ();
ASSERT_TRUE (r0 == irange (build_one_cst (boolean_type_node),
build_one_cst (boolean_type_node)));
// Test irange_storage.
r0 = irange (INT (5), INT (10));
- irange_storage *stow = irange_storage::alloc (r0);
+ irange_storage *stow = irange_storage::alloc (r0, integer_type_node);
r1 = irange (integer_type_node, stow);
ASSERT_TRUE (r0 == r1);
// Test irange_storage with signed 1-bit fields.
tree s1bit_type = make_signed_type (1);
r0 = irange (build_int_cst (s1bit_type, -1), build_int_cst (s1bit_type, 0));
- stow = irange_storage::alloc (r0);
+ stow = irange_storage::alloc (r0, s1bit_type);
r1 = irange (s1bit_type, stow);
ASSERT_TRUE (r0 == r1);
{
if (rt == VR_UNDEFINED)
{
- set_undefined (type);
+ set_undefined ();
return;
}
if (rt == VR_VARYING)
void
irange::union_ (const irange &r)
{
- gcc_checking_assert (range_compatible_p (m_type, r.m_type));
-
if (undefined_p ())
{
*this = r;
else if (r.undefined_p ())
return;
+ gcc_checking_assert (range_compatible_p (m_type, r.m_type));
+
// Do not worry about merging and such by reserving twice as many
// pairs as needed, and then simply sort the 2 ranges into this
// intermediate form.
void
irange::intersect (const wide_int &x, const wide_int &y)
{
- unsigned pos = 0;
+ if (undefined_p ())
+ return;
+ unsigned pos = 0;
for (unsigned i = 0; i < m_nitems; i += 2)
{
signop sign = TYPE_SIGN (m_type);
void
irange::intersect (const irange &r)
{
- gcc_checking_assert (range_compatible_p (m_type, r.m_type));
irange orig_range (*this);
// Intersection with an empty range is an empty range.
- set_undefined ();
if (orig_range.undefined_p () || r.undefined_p ())
- return;
+ {
+ set_undefined ();
+ return;
+ }
+
+ gcc_checking_assert (range_compatible_p (m_type, r.m_type));
// The general algorithm is as follows.
//
// Step 2: [10,20][30,40][50,60] ^ [38,51] => [38,40]
// Step 3: [10,20][30,40][50,60] ^ [55,70] => [55,60]
// Final: [15,20] U [38,40] U [55,60] => [15,20][38,40][55,60]
+ set_undefined ();
for (unsigned i = 0; i < r.m_nitems; i += 2)
{
irange tmp (orig_range);
void
irange::invert ()
{
+ if (undefined_p ())
+ return;
+
// We always need one more set of bounds to represent an inverse, so
// if we're at the limit, we can't properly represent things.
//
return;
}
- // The inverse of the empty set is the entire domain.
- if (undefined_p ())
- {
- set_varying (m_type);
- return;
- }
-
// The algorithm is as follows. To calculate INVERT ([a,b][c,d]), we
// generate [-MIN, a-1][b+1, c-1][d+1, MAX].
//
void
irange::dump (pretty_printer *buffer) const
{
+ if (undefined_p ())
+ {
+ pp_string (buffer, "[]");
+ pp_flush (buffer);
+ return;
+ }
+
wide_int min = wi::min_value (TYPE_PRECISION (m_type), TYPE_SIGN (m_type));
wide_int max = wi::max_value (TYPE_PRECISION (m_type), TYPE_SIGN (m_type));
if (POINTER_TYPE_P (m_type) && nonzero_p ())
else
pp_character (buffer, ']');
}
- if (undefined_p ())
- pp_string (buffer, "[]");
pp_character (buffer, ' ');
dump_generic_node (buffer, m_type, 0, TDF_NONE, false);
// Initialize the current irange_storage to the irange in IR.
void
-irange_storage::set (const irange &ir)
+irange_storage::set (const irange &ir, tree type)
{
- unsigned precision = TYPE_PRECISION (ir.type ());
+ if (type)
+ gcc_checking_assert (ir.undefined_p ()
+ || types_compatible_p (type, ir.type ()));
+ else
+ type = ir.type ();
+ unsigned precision = TYPE_PRECISION (type);
trailing_bounds.set_precision (precision);
unsigned i;
for (i = 0; i < ir.num_pairs () * 2; ++i)
// Clear the remaining empty ranges.
for (; i < irange::m_max_pairs * 2; i += 2)
- set_empty_pair (i, i + 1, ir.type ());
+ set_empty_pair (i, i + 1, type);
}
// Update a previously initialized irange_storage to NEW_RANGE, iff the
// the new range. Return TRUE if update was successful.
bool
-irange_storage::update (const irange &new_range)
+irange_storage::update (const irange &new_range, tree type)
{
- if (trailing_bounds.get_precision () == TYPE_PRECISION (new_range.type ()))
+ if (trailing_bounds.get_precision () == TYPE_PRECISION (type))
{
- set (new_range);
+ set (new_range, type);
return true;
}
return false;
}
if (r.undefined_p ())
{
- vr.set_undefined (r.type ());
+ vr.set_undefined ();
return vr;
}
tree type = r.type ();
static irange
value_range_to_irange (const value_range_base &vr)
{
- tree type = vr.type ();
if (vr.varying_p ())
- return irange (type);
+ return irange (vr.type ());
if (vr.undefined_p ())
{
irange r;
- r.set_undefined (type);
+ r.set_undefined ();
return r;
}
return irange (vr.kind (), vr.min (), vr.max ());
static bool supports_p (tree expr);
void set_varying (tree);
- void set_undefined (tree = NULL);
+ void set_undefined ();
unsigned num_pairs () const;
wide_int lower_bound (unsigned pair = 0) const;
wide_int upper_bound () const;
wide_int upper_bound (unsigned pair) const;
- tree type () const { return m_type; }
+ tree type () const;
void cast (tree type);
return m_nitems / 2;
}
+inline tree
+irange::type () const
+{
+ gcc_checking_assert (!undefined_p ());
+ return m_type;
+}
+
inline void
-irange::set_undefined (tree type)
+irange::set_undefined ()
{
- if (type)
- m_type = type;
+ m_type = NULL;
m_nitems = 0;
}
inline bool
irange::zero_p () const
{
+ if (m_nitems != 2)
+ return false;
wide_int z = wi::zero (TYPE_PRECISION (m_type));
return (m_nitems == 2 && m_bounds[0] == z && m_bounds[1] == z);
}
inline bool
irange::nonzero_p () const
{
+ if (undefined_p ())
+ return false;
unsigned prec = TYPE_PRECISION (m_type);
return *this == irange (VR_ANTI_RANGE, m_type,
wi::zero (prec), wi::zero (prec));
// To store an irange class X into an irange_storage use:
//
// irange X = ...;
-// irange_storage *stow = irange_storage::alloc (X);
+// irange_storage *stow = irange_storage::alloc (X, range_type);
//
// To convert it back into an irange use:
//
friend class irange;
public:
- static irange_storage *alloc (const irange &);
- bool update (const irange &);
+ static irange_storage *alloc (const irange &, tree type);
+ bool update (const irange &, tree type);
private:
static size_t size (unsigned precision);
- void set (const irange &);
+ void set (const irange &, tree type);
bool empty_pair_p (unsigned, unsigned, tree) const;
void set_empty_pair (unsigned, unsigned, tree);
void set_nonzero_bits (const wide_int &);
// initialize it to IR.
inline irange_storage *
-irange_storage::alloc (const irange &ir)
+irange_storage::alloc (const irange &ir, tree type)
{
- unsigned precision = TYPE_PRECISION (ir.m_type);
+ if (type)
+ gcc_checking_assert (ir.undefined_p ()
+ || types_compatible_p (type, ir.type ()));
+ else
+ type = ir.type ();
+ unsigned precision = TYPE_PRECISION (type);
irange_storage *stow = static_cast<irange_storage *> (ggc_internal_alloc
(size (precision)));
- stow->set (ir);
+ stow->set (ir, type);
stow->set_nonzero_bits (wi::shwi (-1, precision));
return stow;
}
// Create the cached type range.
tr.set_varying (t);
- m_type_range = irange_storage::alloc (tr);
+ m_type_range = irange_storage::alloc (tr, t);
m_tab[ENTRY_BLOCK_PTR_FOR_FN (cfun)->index] = m_type_range;
}
irange_storage *m = m_tab[bb->index];
// If there is already range memory for this block, reuse it.
- if (m && m != m_type_range && m->update (r))
+ if (m && m != m_type_range && m->update (r, m_type))
;
else
- m = irange_storage::alloc (r);
+ m = irange_storage::alloc (r, m_type);
m_tab[bb->index] = m;
}
m_tab.safe_grow_cleared (num_ssa_names + 1);
irange_storage *m = m_tab[v];
- if (m && m->update (r))
+ if (m && m->update (r, TREE_TYPE (name)))
;
else
{
- m = irange_storage::alloc (r);
+ m = irange_storage::alloc (r, TREE_TYPE (name));
m_tab[SSA_NAME_VERSION (name)] = m;
}
}
gcc_assert (m_on_entry.get_bb_range (current_range, name, bb));
// Calculate the "new" range on entry by unioning the pred edges..
- new_range.set_undefined (TREE_TYPE (name));
+ new_range.set_undefined ();
FOR_EACH_EDGE (e, ei, bb->preds)
{
gcc_assert (edge_range (e_range, e, name));
// the range_on_entry cache for.
m_workback.truncate (0);
m_workback.quick_push (bb);
- undefined.set_undefined (TREE_TYPE (name));
+ undefined.set_undefined ();
m_on_entry.set_bb_range (name, bb, undefined);
gcc_checking_assert (m_update_list.length () == 0);
// Empty ranges are viral as they are on a path which isn't executable.
if (lhs.undefined_p ())
{
- r.set_undefined (TREE_TYPE (name));
+ r.set_undefined ();
return true;
}
bool res;
tree import = terminal_name (name);
- gcc_checking_assert (import &&
- useless_type_conversion_p (TREE_TYPE (import),
- import_range.type ()));
+ gcc_checking_assert
+ (import
+ && (import_range.undefined_p ()
+ || useless_type_conversion_p (TREE_TYPE (import),
+ import_range.type ())));
// Only handling range_ops until we find a cond-expr that matters.
// We process this specially so we can handle self-referencing chains. ie:
if (e != gimple_switch_default_edge (cfun, sw))
{
- r.set_undefined (type);
+ r.set_undefined ();
// Loop through all the switches edges, ignoring the default edge.
// unioning the ranges together.
for (x = 1; x < lim; x++)
gcc_checking_assert (valid_ssa_p (name));
range_on_exit (r, e->src, name);
- gcc_checking_assert (r.type() == TREE_TYPE (name));
+ gcc_checking_assert (r.undefined_p () || r.type() == TREE_TYPE (name));
// Check to see if NAME is defined on edge e.
if (outgoing_edge_range_p (edge_range, e, name, &r))
}
if (res)
{
+ if (r.undefined_p ())
+ return true;
if (name && TREE_TYPE (name) != r.type ())
r.cast (TREE_TYPE (name));
return true;
gcc_checking_assert (irange::supports_type_p (type));
// Start with an empty range.
- r.set_undefined (type);
+ r.set_undefined ();
gcc_checking_assert (bb != ENTRY_BLOCK_PTR_FOR_FN (cfun));
range_on_entry (r, bb, name);
else
gcc_assert (range_of_expr (r, name, s));
- gcc_checking_assert (r.type() == TREE_TYPE (name));
+ gcc_checking_assert (r.undefined_p () || r.type() == TREE_TYPE (name));
}
// Calculate a range for range_op statement S given RANGE1 and RANGE2 and
return false;
// And start with an empty range, unioning in each argument's range.
- r.set_undefined (type);
+ r.set_undefined ();
for (x = 0; x < gimple_phi_num_args (phi); x++)
{
irange arg_range;
if (kind == VR_VARYING)
vr.set_varying (TREE_TYPE (name));
else if (kind == VR_UNDEFINED)
- vr.set_undefined (TREE_TYPE (name));
+ vr.set_undefined ();
else
{
min = wide_int_to_tree (TREE_TYPE (name), wmin);
}
void
-value_range_base::set_undefined (tree type)
+value_range_base::set_undefined ()
{
m_kind = VR_UNDEFINED;
- if (type)
- {
- if (supports_type_p (type))
- {
- m_min = vrp_val_min (type, true);
- m_max = vrp_val_max (type, true);
- }
- else
- {
- /* This is a temporary kludge for ipa-cp which is building
- undefined/varying of floats. ?? */
- m_min = m_max = build1 (NOP_EXPR, type, type);
- }
- }
- else
- m_min = m_max = NULL;
+ m_min = m_max = NULL;
}
void
-value_range::set_undefined (tree type)
+value_range::set_undefined ()
{
- value_range_base::set_undefined (type);
- equiv_clear ();
+ set (VR_UNDEFINED, NULL, NULL, NULL);
}
void
tree
value_range_base::type () const
{
- gcc_assert (m_min || undefined_p ());
+ gcc_assert (m_min);
return TREE_TYPE (min ());
}
void
value_range_base::dump (FILE *file) const
{
- tree ttype;
- if (undefined_p () && !m_min)
- ttype = void_type_node;
- else ttype = TREE_TYPE (m_min);
-
if (undefined_p ())
- {
- print_generic_expr (file, ttype);
- fprintf (file, " UNDEFINED");
- }
+ fprintf (file, "UNDEFINED");
else if (m_kind == VR_RANGE || m_kind == VR_ANTI_RANGE)
{
+ tree ttype = type ();
+
print_generic_expr (file, ttype);
fprintf (file, " ");
{
if (kind == VR_UNDEFINED)
{
- if (min)
- set_undefined (TREE_TYPE (min));
- else
- set_undefined ();
+ set_undefined ();
return;
}
else if (kind == VR_VARYING)
if (kind == VR_RANGE)
set_varying (type);
else if (kind == VR_ANTI_RANGE)
- set_undefined (type);
+ set_undefined ();
else
gcc_unreachable ();
return;
tree type = ar->type ();
- vr0->set_undefined (type);
- vr1->set_undefined (type);
+ vr0->set_undefined ();
+ vr1->set_undefined ();
/* As a future improvement, we could handle ~[0, A] as: [-INF, -1] U
[A+1, +INF]. Not sure if this helps in practice, though. */
if (vr0->undefined_p ())
{
*vr0 = *vr1;
- vr1->set_undefined (type);
+ vr1->set_undefined ();
}
return !vr0->undefined_p ();
/* If both ranges are UNDEFINED, so is the result. */
if (vr0.undefined_p () && vr1.undefined_p ())
{
- vr->set_undefined (expr_type);
+ vr->set_undefined ();
return;
}
/* If one of the ranges is UNDEFINED drop it to VARYING for the following
/* Special case explicit division by zero as undefined. */
if (vr1.zero_p ())
{
- vr->set_undefined (expr_type);
+ vr->set_undefined ();
return;
}
{
if (vr1.zero_p ())
{
- vr->set_undefined (expr_type);
+ vr->set_undefined ();
return;
}
wide_int wmin, wmax, tmp;
/* If VR0 is UNDEFINED, so is the result. */
if (vr0.undefined_p ())
{
- vr->set_undefined (type);
+ vr->set_undefined ();
return;
}
value_range_base vr0 = *vr0_, vr1 = *vr1_;
if (vr0.undefined_p () && vr1.undefined_p ())
{
- vr->set_undefined (expr_type);
+ vr->set_undefined ();
return;
}
if (vr0.undefined_p ())
}
if (vr0->undefined_p ())
{
- vr->set_undefined (expr_type);
+ vr->set_undefined ();
return;
}
const value_range_base *vr1)
{
if (!value_range_base::supports_type_p (expr_type)
- || !value_range_base::supports_type_p (vr0->type ())
- || !value_range_base::supports_type_p (vr1->type ()))
+ || (!vr0->undefined_p ()
+ && !value_range_base::supports_type_p (vr0->type ()))
+ || (!vr1->undefined_p ()
+ && !value_range_base::supports_type_p (vr1->type ())))
{
*vr = value_range (expr_type);
return;
range_fold_unary_expr (value_range_base *vr,
enum tree_code code,
tree expr_type,
- const value_range_base *vr0)
+ const value_range_base *vr0,
+ tree vr0_type)
{
if (!value_range_base::supports_type_p (expr_type)
- || !value_range_base::supports_type_p (vr0->type ()))
+ || !value_range_base::supports_type_p (vr0_type))
{
*vr = value_range (expr_type);
return;
if (flag_ranges_mode & RANGES_VRP)
{
value_range_base old;
- extract_range_from_unary_expr (&old, code, expr_type, vr0, vr0->type ());
+ extract_range_from_unary_expr (&old, code, expr_type, vr0, vr0_type);
if (flag_ranges_mode & RANGES_CHECKING)
{
value_range_base vr1 (expr_type);
fall back to vr0 when this turns things to varying. */
value_range_base tem;
if (vr0type == VR_UNDEFINED)
- tem.set_undefined (TREE_TYPE (vr0->min ()));
+ tem.set_undefined ();
else if (vr0type == VR_VARYING)
tem.set_varying (TREE_TYPE (vr0->min ()));
else
/* Work on a temporary so we can still use vr0 when union returns varying. */
value_range_base tem;
if (vr0type == VR_UNDEFINED)
- tem.set_undefined (TREE_TYPE (vr0->min ()));
+ tem.set_undefined ();
else if (vr0type == VR_VARYING)
tem.set_varying (vr0->type ());
else
value_range_base::invert ()
{
if (undefined_p ())
- set_varying (type ());
- else if (varying_p ())
- set_undefined (type ());
+ return;
+ if (varying_p ())
+ set_undefined ();
else if (m_kind == VR_RANGE)
m_kind = VR_ANTI_RANGE;
else if (m_kind == VR_ANTI_RANGE)
gcc_unreachable ();
}
+value_range_storage *
+value_range_storage::alloc (const value_range_base &r, tree type)
+{
+ if (type)
+ gcc_checking_assert (r.undefined_p ()
+ || types_compatible_p (type, r.type ()));
+ else
+ type = r.type ();
+ value_range_storage *p = ggc_alloc<value_range_storage> ();
+ p->set (r, type);
+ return p;
+}
+
void
value_range_base::union_ (const value_range_base &r)
{
bool undefined_p () const;
bool varying_p () const;
void set_varying (tree type);
- void set_undefined (tree = NULL);
+ void set_undefined ();
void union_ (const value_range_base *);
void intersect (const value_range_base *);
bool equal_p (const value_range &, bool ignore_equivs) const;
/* Types of value ranges. */
- void set_undefined (tree = NULL);
+ void set_undefined ();
void set_varying (tree);
/* Equivalence bitmap methods. */
{
friend class value_range_base;
public:
- static value_range_storage *alloc (const value_range_base &r)
+ static value_range_storage *alloc (const value_range_base &r, tree type);
+ bool update (const value_range_base &r, tree type)
{
- value_range_storage *p = ggc_alloc<value_range_storage> ();
- p->set (r);
- return p;
- }
- bool update (const value_range_base &r)
- {
- set (r);
+ set (r, type);
return true;
}
private:
- void set (const value_range_base &r)
+ void set (const value_range_base &r, tree type ATTRIBUTE_UNUSED)
{
m_vr = r;
}
const value_range_base *,
const value_range_base *);
void range_fold_unary_expr (value_range_base *, enum tree_code, tree,
- const value_range_base *);
+ const value_range_base *, tree);
/* Return TRUE if *VR includes the value zero. */
inline bool
range_includes_zero_p (const value_range_base *vr)
{
- /* UNDEFINED may not have a type in uninitialized ranges. */
if (vr->undefined_p ())
return false;
+ if (vr->varying_p ())
+ return true;
+
return vr->may_contain_p (build_zero_cst (vr->type ()));
}
return vr;
}
- vr->set_undefined (TREE_TYPE (var));
+ vr->set_undefined ();
/* If VAR is a default definition of a parameter, the variable can
take any value in VAR's type. */
else
vr0.set_varying (type);
- range_fold_unary_expr (vr, code, type, &vr0);
+ range_fold_unary_expr (vr, code, type, &vr0, TREE_TYPE (op0));
}