The call to range_operator::fold_range() and wi_fold() originally
returned the resulting range in a reference parameter. When prepping
for trunk, we got excited about something else and I changed it to
return the result by value.
As we move towards multiple sub-ranges in value_range, I recalled the
rationale for the reference parameter was to allow us to better support
a variable number of sub-ranges. range-ops will work with as many
subranges as are available, and this allows the caller to provide a
range object with the desired number. It also makes fold_range a
bit more consistent with the way op1_range and op2_range work.
The fundamental change is moving from:
virtual value_range fold_range (tree type, const value_range &lh,
const value_range &rh) const;
to
virtual void fold_range (value_range &r, tree type, const
value_range &lh, const value_range &rh) const;
and likewise for wi_fold.
The change is quite mechanical. Bootstraps all languages and causes no
regressions.
Checked in as SVN revision 277979
Andrew
Change range_operator methods 'fold_range' and 'wi_fold' to return the result
range by a reference parameter instead of by value.
2019-11-08 Andrew MacLeod <amacl...@redhat.com>
* range-op.h (range_operator::fold_range): Return result in a
reference parameter instead of by value.
(range_operator::wi_fold): Same.
* range-op.cc (range_operator::wi_fold): Return result in a reference
parameter instead of by value.
(range_operator::fold_range): Same.
(value_range_from_overflowed_bounds): Same.
(value_range_with_overflow): Same
(create_possibly_reversed_range): Same.
(operator_equal::fold_range): Same.
(operator_not_equal::fold_range): Same.
(operator_lt::fold_range): Same.
(operator_le::fold_range): Same.
(operator_gt::fold_range): Same.
(operator_ge::fold_range): Same.
(operator_plus::wi_fold): Same.
(operator_plus::op1_range): Change call to fold_range.
(operator_plus::op2_range): Change call to fold_range.
(operator_minus::wi_fold): Return result via reference parameter.
(operator_minus::op1_range): Change call to fold_range.
(operator_minus::op2_range): Change call to fold_range.
(operator_min::wi_fold): Return result via reference parameter.
(operator_max::wi_fold): Same.
(cross_product_operator::wi_cross_product): Same.
(operator_mult::wi_fold): Same.
(operator_div::wi_fold): Same.
(operator_div op_floor_div): Fix whitespace.
(operator_exact_divide::op1_range): Change call to fold_range.
(operator_lshift::fold_range): Return result via reference parameter.
(operator_lshift::wi_fold): Same.
(operator_rshift::fold_range): Same.
(operator_rshift::wi_fold): Same.
(operator_cast::fold_range): Same.
(operator_cast::op1_range): Change calls to fold_range.
(operator_logical_and::fold_range): Return result via reference.
(wi_optimize_and_or): Adjust call to value_range_with_overflow.
(operator_bitwise_and::wi_fold): Return result via reference.
(operator_logical_or::fold_range): Same.
(operator_bitwise_or::wi_fold): Same.
(operator_bitwise_xor::wi_fold): Same.
(operator_trunc_mod::wi_fold): Same.
(operator_logical_not::fold_range): Same.
(operator_bitwise_not::fold_range): Same.
(operator_bitwise_not::op1_range): Change call to fold_range.
(operator_cst::fold_range): Return result via reference.
(operator_identity::fold_range): Same.
(operator_abs::wi_fold): Same.
(operator_absu::wi_fold): Same.
(operator_negate::fold_range): Same.
(operator_negate::op1_range): Change call to fold_range.
(operator_addr_expr::fold_range): Return result via reference.
(operator_addr_expr::op1_range): Change call to fold_range.
(operator_pointer_plus::wi_fold): Return result via reference.
(operator_pointer_min_max::wi_fold): Same.
(operator_pointer_and::wi_fold): Same.
(operator_pointer_or::wi_fold): Same.
(range_op_handler): Change call to fold_range.
(range_cast): Same.
* tree-vrp.c (range_fold_binary_symbolics_p): Change call to
fold_range.
(range_fold_unary_symbolics_p): Same.
(range_fold_binary_expr): Same.
(range_fold_unary_expr): Same.
Index: range-op.h
===================================================================
*** range-op.h (revision 277853)
--- range-op.h (working copy)
*************** class range_operator
*** 50,58 ****
{
public:
// Perform an operation between 2 ranges and return it.
! virtual value_range fold_range (tree type,
! const value_range &lh,
! const value_range &rh) const;
// Return the range for op[12] in the general case. LHS is the range for
// the LHS of the expression, OP[12]is the range for the other
--- 50,58 ----
{
public:
// Perform an operation between 2 ranges and return it.
! virtual void fold_range (value_range &r, tree type,
! const value_range &lh,
! const value_range &rh) const;
// Return the range for op[12] in the general case. LHS is the range for
// the LHS of the expression, OP[12]is the range for the other
*************** public:
*** 74,84 ****
protected:
// Perform an operation between 2 sub-ranges and return it.
! virtual value_range wi_fold (tree type,
! const wide_int &lh_lb,
! const wide_int &lh_ub,
! const wide_int &rh_lb,
! const wide_int &rh_ub) const;
};
extern range_operator *range_op_handler (enum tree_code code, tree type);
--- 74,84 ----
protected:
// Perform an operation between 2 sub-ranges and return it.
! virtual void wi_fold (value_range &r, tree type,
! const wide_int &lh_lb,
! const wide_int &lh_ub,
! const wide_int &rh_lb,
! const wide_int &rh_ub) const;
};
extern range_operator *range_op_handler (enum tree_code code, tree type);
Index: range-op.cc
===================================================================
*** range-op.cc (revision 277853)
--- range-op.cc (working copy)
*************** wi_zero_p (tree type, const wide_int &wm
*** 124,151 ****
// Default wide_int fold operation returns [MIN, MAX].
! value_range
! range_operator::wi_fold (tree type,
const wide_int &lh_lb ATTRIBUTE_UNUSED,
const wide_int &lh_ub ATTRIBUTE_UNUSED,
const wide_int &rh_lb ATTRIBUTE_UNUSED,
const wide_int &rh_ub ATTRIBUTE_UNUSED) const
{
! return value_range (type);
}
// The default for fold is to break all ranges into sub-ranges and
// invoke the wi_fold method on each sub-range pair.
! value_range
! range_operator::fold_range (tree type,
const value_range &lh,
const value_range &rh) const
{
- value_range r;
if (empty_range_check (r, lh, rh))
! return r;
for (unsigned x = 0; x < lh.num_pairs (); ++x)
for (unsigned y = 0; y < rh.num_pairs (); ++y)
{
--- 124,151 ----
// Default wide_int fold operation returns [MIN, MAX].
! void
! range_operator::wi_fold (value_range &r, tree type,
const wide_int &lh_lb ATTRIBUTE_UNUSED,
const wide_int &lh_ub ATTRIBUTE_UNUSED,
const wide_int &rh_lb ATTRIBUTE_UNUSED,
const wide_int &rh_ub ATTRIBUTE_UNUSED) const
{
! r = value_range (type);
}
// The default for fold is to break all ranges into sub-ranges and
// invoke the wi_fold method on each sub-range pair.
! void
! range_operator::fold_range (value_range &r, tree type,
const value_range &lh,
const value_range &rh) const
{
if (empty_range_check (r, lh, rh))
! return;
+ value_range tmp;
for (unsigned x = 0; x < lh.num_pairs (); ++x)
for (unsigned y = 0; y < rh.num_pairs (); ++y)
{
*************** range_operator::fold_range (tree type,
*** 153,163 ****
wide_int lh_ub = lh.upper_bound (x);
wide_int rh_lb = rh.lower_bound (y);
wide_int rh_ub = rh.upper_bound (y);
! r.union_ (wi_fold (type, lh_lb, lh_ub, rh_lb, rh_ub));
if (r.varying_p ())
! return r;
}
- return r;
}
// The default for op1_range is to return false.
--- 153,163 ----
wide_int lh_ub = lh.upper_bound (x);
wide_int rh_lb = rh.lower_bound (y);
wide_int rh_ub = rh.upper_bound (y);
! wi_fold (tmp, type, lh_lb, lh_ub, rh_lb, rh_ub);
! r.union_ (tmp);
if (r.varying_p ())
! return;
}
}
// The default for op1_range is to return false.
*************** range_operator::op2_range (value_range &
*** 186,193 ****
// Create and return a range from a pair of wide-ints that are known
// to have overflowed (or underflowed).
! static value_range
! value_range_from_overflowed_bounds (tree type,
const wide_int &wmin,
const wide_int &wmax)
{
--- 186,193 ----
// Create and return a range from a pair of wide-ints that are known
// to have overflowed (or underflowed).
! static void
! value_range_from_overflowed_bounds (value_range &r, tree type,
const wide_int &wmin,
const wide_int &wmax)
{
*************** value_range_from_overflowed_bounds (tree
*** 210,226 ****
// Likewise if the anti-range bounds are outside of the types
// values.
if (covers || wi::cmp (tmin, tmax, sgn) > 0)
! return value_range (type);
!
! return value_range (VR_ANTI_RANGE, type, tmin, tmax);
}
// Create and return a range from a pair of wide-ints. MIN_OVF and
// MAX_OVF describe any overflow that might have occurred while
// calculating WMIN and WMAX respectively.
! static value_range
! value_range_with_overflow (tree type,
const wide_int &wmin, const wide_int &wmax,
wi::overflow_type min_ovf = wi::OVF_NONE,
wi::overflow_type max_ovf = wi::OVF_NONE)
--- 210,226 ----
// Likewise if the anti-range bounds are outside of the types
// values.
if (covers || wi::cmp (tmin, tmax, sgn) > 0)
! r = value_range (type);
! else
! r = value_range (VR_ANTI_RANGE, type, tmin, tmax);
}
// Create and return a range from a pair of wide-ints. MIN_OVF and
// MAX_OVF describe any overflow that might have occurred while
// calculating WMIN and WMAX respectively.
! static void
! value_range_with_overflow (value_range &r, tree type,
const wide_int &wmin, const wide_int &wmax,
wi::overflow_type min_ovf = wi::OVF_NONE,
wi::overflow_type max_ovf = wi::OVF_NONE)
*************** value_range_with_overflow (tree type,
*** 232,238 ****
// For one bit precision if max != min, then the range covers all
// values.
if (prec == 1 && wi::ne_p (wmax, wmin))
! return value_range (type);
if (overflow_wraps)
{
--- 232,241 ----
// For one bit precision if max != min, then the range covers all
// values.
if (prec == 1 && wi::ne_p (wmax, wmin))
! {
! r = value_range (type);
! return;
! }
if (overflow_wraps)
{
*************** value_range_with_overflow (tree type,
*** 245,263 ****
// If the limits are swapped, we wrapped around and cover
// the entire range.
if (wi::gt_p (tmin, tmax, sgn))
! return value_range (type);
!
! // No overflow or both overflow or underflow. The range
! // kind stays normal.
! return value_range (type, tmin, tmax);
}
if ((min_ovf == wi::OVF_UNDERFLOW && max_ovf == wi::OVF_NONE)
|| (max_ovf == wi::OVF_OVERFLOW && min_ovf == wi::OVF_NONE))
! return value_range_from_overflowed_bounds (type, wmin, wmax);
!
! // Other underflow and/or overflow, drop to VR_VARYING.
! return value_range (type);
}
else
{
--- 248,267 ----
// If the limits are swapped, we wrapped around and cover
// the entire range.
if (wi::gt_p (tmin, tmax, sgn))
! r = value_range (type);
! else
! // No overflow or both overflow or underflow. The range
! // kind stays normal.
! r = value_range (type, tmin, tmax);
! return;
}
if ((min_ovf == wi::OVF_UNDERFLOW && max_ovf == wi::OVF_NONE)
|| (max_ovf == wi::OVF_OVERFLOW && min_ovf == wi::OVF_NONE))
! value_range_from_overflowed_bounds (r, type, wmin, wmax);
! else
! // Other underflow and/or overflow, drop to VR_VARYING.
! r = value_range (type);
}
else
{
*************** value_range_with_overflow (tree type,
*** 277,283 ****
else
new_ub = wmax;
! return value_range (type, new_lb, new_ub);
}
}
--- 281,287 ----
else
new_ub = wmax;
! r = value_range (type, new_lb, new_ub);
}
}
*************** value_range_with_overflow (tree type,
*** 285,301 ****
// the case where the bounds are swapped. In which case, we transform
// [10,5] into [MIN,5][10,MAX].
! static inline value_range
! create_possibly_reversed_range (tree type,
const wide_int &new_lb, const wide_int &new_ub)
{
signop s = TYPE_SIGN (type);
// If the bounds are swapped, treat the result as if an overflow occured.
if (wi::gt_p (new_lb, new_ub, s))
! return value_range_from_overflowed_bounds (type, new_lb, new_ub);
!
! // Otherwise its just a normal range.
! return value_range (type, new_lb, new_ub);
}
// Return a value_range instance that is a boolean TRUE.
--- 289,305 ----
// the case where the bounds are swapped. In which case, we transform
// [10,5] into [MIN,5][10,MAX].
! static inline void
! create_possibly_reversed_range (value_range &r, tree type,
const wide_int &new_lb, const wide_int &new_ub)
{
signop s = TYPE_SIGN (type);
// If the bounds are swapped, treat the result as if an overflow occured.
if (wi::gt_p (new_lb, new_ub, s))
! value_range_from_overflowed_bounds (r, type, new_lb, new_ub);
! else
! // Otherwise its just a normal range.
! r = value_range (type, new_lb, new_ub);
}
// Return a value_range instance that is a boolean TRUE.
*************** get_bool_state (value_range &r, const va
*** 359,367 ****
class operator_equal : public range_operator
{
public:
! virtual value_range fold_range (tree type,
! const value_range &op1,
! const value_range &op2) const;
virtual bool op1_range (value_range &r, tree type,
const value_range &lhs,
const value_range &val) const;
--- 363,371 ----
class operator_equal : public range_operator
{
public:
! virtual void fold_range (value_range &r, tree type,
! const value_range &op1,
! const value_range &op2) const;
virtual bool op1_range (value_range &r, tree type,
const value_range &lhs,
const value_range &val) const;
*************** public:
*** 370,383 ****
const value_range &val) const;
} op_equal;
! value_range
! operator_equal::fold_range (tree type,
const value_range &op1,
const value_range &op2) const
{
- value_range r;
if (empty_range_check (r, op1, op2))
! return r;
// We can be sure the values are always equal or not if both ranges
// consist of a single value, and then compare them.
--- 374,386 ----
const value_range &val) const;
} op_equal;
! void
! operator_equal::fold_range (value_range &r, tree type,
const value_range &op1,
const value_range &op2) const
{
if (empty_range_check (r, op1, op2))
! return;
// We can be sure the values are always equal or not if both ranges
// consist of a single value, and then compare them.
*************** operator_equal::fold_range (tree type,
*** 399,406 ****
else
r = range_true_and_false (type);
}
-
- return r;
}
bool
--- 402,407 ----
*************** operator_equal::op2_range (value_range &
*** 442,450 ****
class operator_not_equal : public range_operator
{
public:
! virtual value_range fold_range (tree type,
! const value_range &op1,
! const value_range &op2) const;
virtual bool op1_range (value_range &r, tree type,
const value_range &lhs,
const value_range &op2) const;
--- 443,451 ----
class operator_not_equal : public range_operator
{
public:
! virtual void fold_range (value_range &r, tree type,
! const value_range &op1,
! const value_range &op2) const;
virtual bool op1_range (value_range &r, tree type,
const value_range &lhs,
const value_range &op2) const;
*************** public:
*** 453,466 ****
const value_range &op1) const;
} op_not_equal;
! value_range
! operator_not_equal::fold_range (tree type,
const value_range &op1,
const value_range &op2) const
{
- value_range r;
if (empty_range_check (r, op1, op2))
! return r;
// We can be sure the values are always equal or not if both ranges
// consist of a single value, and then compare them.
--- 454,466 ----
const value_range &op1) const;
} op_not_equal;
! void
! operator_not_equal::fold_range (value_range &r, tree type,
const value_range &op1,
const value_range &op2) const
{
if (empty_range_check (r, op1, op2))
! return;
// We can be sure the values are always equal or not if both ranges
// consist of a single value, and then compare them.
*************** operator_not_equal::fold_range (tree typ
*** 482,489 ****
else
r = range_true_and_false (type);
}
-
- return r;
}
bool
--- 482,487 ----
*************** build_ge (value_range &r, tree type, con
*** 571,579 ****
class operator_lt : public range_operator
{
public:
! virtual value_range fold_range (tree type,
! const value_range &op1,
! const value_range &op2) const;
virtual bool op1_range (value_range &r, tree type,
const value_range &lhs,
const value_range &op2) const;
--- 569,577 ----
class operator_lt : public range_operator
{
public:
! virtual void fold_range (value_range &r, tree type,
! const value_range &op1,
! const value_range &op2) const;
virtual bool op1_range (value_range &r, tree type,
const value_range &lhs,
const value_range &op2) const;
*************** public:
*** 582,595 ****
const value_range &op1) const;
} op_lt;
! value_range
! operator_lt::fold_range (tree type,
const value_range &op1,
const value_range &op2) const
{
- value_range r;
if (empty_range_check (r, op1, op2))
! return r;
signop sign = TYPE_SIGN (op1.type ());
gcc_checking_assert (sign == TYPE_SIGN (op2.type ()));
--- 580,592 ----
const value_range &op1) const;
} op_lt;
! void
! operator_lt::fold_range (value_range &r, tree type,
const value_range &op1,
const value_range &op2) const
{
if (empty_range_check (r, op1, op2))
! return;
signop sign = TYPE_SIGN (op1.type ());
gcc_checking_assert (sign == TYPE_SIGN (op2.type ()));
*************** operator_lt::fold_range (tree type,
*** 600,606 ****
r = range_false (type);
else
r = range_true_and_false (type);
- return r;
}
bool
--- 597,602 ----
*************** operator_lt::op2_range (value_range &r,
*** 649,657 ****
class operator_le : public range_operator
{
public:
! virtual value_range fold_range (tree type,
! const value_range &op1,
! const value_range &op2) const;
virtual bool op1_range (value_range &r, tree type,
const value_range &lhs,
const value_range &op2) const;
--- 645,653 ----
class operator_le : public range_operator
{
public:
! virtual void fold_range (value_range &r, tree type,
! const value_range &op1,
! const value_range &op2) const;
virtual bool op1_range (value_range &r, tree type,
const value_range &lhs,
const value_range &op2) const;
*************** public:
*** 660,673 ****
const value_range &op1) const;
} op_le;
! value_range
! operator_le::fold_range (tree type,
const value_range &op1,
const value_range &op2) const
{
- value_range r;
if (empty_range_check (r, op1, op2))
! return r;
signop sign = TYPE_SIGN (op1.type ());
gcc_checking_assert (sign == TYPE_SIGN (op2.type ()));
--- 656,668 ----
const value_range &op1) const;
} op_le;
! void
! operator_le::fold_range (value_range &r, tree type,
const value_range &op1,
const value_range &op2) const
{
if (empty_range_check (r, op1, op2))
! return;
signop sign = TYPE_SIGN (op1.type ());
gcc_checking_assert (sign == TYPE_SIGN (op2.type ()));
*************** operator_le::fold_range (tree type,
*** 678,684 ****
r = range_false (type);
else
r = range_true_and_false (type);
- return r;
}
bool
--- 673,678 ----
*************** operator_le::op2_range (value_range &r,
*** 727,735 ****
class operator_gt : public range_operator
{
public:
! virtual value_range fold_range (tree type,
! const value_range &op1,
! const value_range &op2) const;
virtual bool op1_range (value_range &r, tree type,
const value_range &lhs,
const value_range &op2) const;
--- 721,729 ----
class operator_gt : public range_operator
{
public:
! virtual void fold_range (value_range &r, tree type,
! const value_range &op1,
! const value_range &op2) const;
virtual bool op1_range (value_range &r, tree type,
const value_range &lhs,
const value_range &op2) const;
*************** public:
*** 738,750 ****
const value_range &op1) const;
} op_gt;
! value_range
! operator_gt::fold_range (tree type,
const value_range &op1, const value_range &op2) const
{
- value_range r;
if (empty_range_check (r, op1, op2))
! return r;
signop sign = TYPE_SIGN (op1.type ());
gcc_checking_assert (sign == TYPE_SIGN (op2.type ()));
--- 732,743 ----
const value_range &op1) const;
} op_gt;
! void
! operator_gt::fold_range (value_range &r, tree type,
const value_range &op1, const value_range &op2) const
{
if (empty_range_check (r, op1, op2))
! return;
signop sign = TYPE_SIGN (op1.type ());
gcc_checking_assert (sign == TYPE_SIGN (op2.type ()));
*************** operator_gt::fold_range (tree type,
*** 755,761 ****
r = range_false (type);
else
r = range_true_and_false (type);
- return r;
}
bool
--- 748,753 ----
*************** operator_gt::op2_range (value_range &r,
*** 803,811 ****
class operator_ge : public range_operator
{
public:
! virtual value_range fold_range (tree type,
! const value_range &op1,
! const value_range &op2) const;
virtual bool op1_range (value_range &r, tree type,
const value_range &lhs,
const value_range &op2) const;
--- 795,803 ----
class operator_ge : public range_operator
{
public:
! virtual void fold_range (value_range &r, tree type,
! const value_range &op1,
! const value_range &op2) const;
virtual bool op1_range (value_range &r, tree type,
const value_range &lhs,
const value_range &op2) const;
*************** public:
*** 814,827 ****
const value_range &op1) const;
} op_ge;
! value_range
! operator_ge::fold_range (tree type,
const value_range &op1,
const value_range &op2) const
{
- value_range r;
if (empty_range_check (r, op1, op2))
! return r;
signop sign = TYPE_SIGN (op1.type ());
gcc_checking_assert (sign == TYPE_SIGN (op2.type ()));
--- 806,818 ----
const value_range &op1) const;
} op_ge;
! void
! operator_ge::fold_range (value_range &r, tree type,
const value_range &op1,
const value_range &op2) const
{
if (empty_range_check (r, op1, op2))
! return;
signop sign = TYPE_SIGN (op1.type ());
gcc_checking_assert (sign == TYPE_SIGN (op2.type ()));
*************** operator_ge::fold_range (tree type,
*** 832,838 ****
r = range_false (type);
else
r = range_true_and_false (type);
- return r;
}
bool
--- 823,828 ----
*************** public:
*** 887,901 ****
virtual bool op2_range (value_range &r, tree type,
const value_range &lhs,
const value_range &op1) const;
! virtual value_range wi_fold (tree type,
! const wide_int &lh_lb,
! const wide_int &lh_ub,
! const wide_int &rh_lb,
! const wide_int &rh_ub) const;
} op_plus;
! value_range
! operator_plus::wi_fold (tree type,
const wide_int &lh_lb, const wide_int &lh_ub,
const wide_int &rh_lb, const wide_int &rh_ub) const
{
--- 877,891 ----
virtual bool op2_range (value_range &r, tree type,
const value_range &lhs,
const value_range &op1) const;
! virtual void wi_fold (value_range &r, tree type,
! const wide_int &lh_lb,
! const wide_int &lh_ub,
! const wide_int &rh_lb,
! const wide_int &rh_ub) const;
} op_plus;
! void
! operator_plus::wi_fold (value_range &r, tree type,
const wide_int &lh_lb, const wide_int &lh_ub,
const wide_int &rh_lb, const wide_int &rh_ub) const
{
*************** operator_plus::wi_fold (tree type,
*** 903,909 ****
signop s = TYPE_SIGN (type);
wide_int new_lb = wi::add (lh_lb, rh_lb, s, &ov_lb);
wide_int new_ub = wi::add (lh_ub, rh_ub, s, &ov_ub);
! return value_range_with_overflow (type, new_lb, new_ub, ov_lb, ov_ub);
}
bool
--- 893,899 ----
signop s = TYPE_SIGN (type);
wide_int new_lb = wi::add (lh_lb, rh_lb, s, &ov_lb);
wide_int new_ub = wi::add (lh_ub, rh_ub, s, &ov_ub);
! value_range_with_overflow (r, type, new_lb, new_ub, ov_lb, ov_ub);
}
bool
*************** operator_plus::op1_range (value_range &r
*** 911,917 ****
const value_range &lhs,
const value_range &op2) const
{
! r = range_op_handler (MINUS_EXPR, type)->fold_range (type, lhs, op2);
return true;
}
--- 901,907 ----
const value_range &lhs,
const value_range &op2) const
{
! range_op_handler (MINUS_EXPR, type)->fold_range (r, type, lhs, op2);
return true;
}
*************** operator_plus::op2_range (value_range &r
*** 920,926 ****
const value_range &lhs,
const value_range &op1) const
{
! r = range_op_handler (MINUS_EXPR, type)->fold_range (type, lhs, op1);
return true;
}
--- 910,916 ----
const value_range &lhs,
const value_range &op1) const
{
! range_op_handler (MINUS_EXPR, type)->fold_range (r, type, lhs, op1);
return true;
}
*************** public:
*** 934,948 ****
virtual bool op2_range (value_range &r, tree type,
const value_range &lhs,
const value_range &op1) const;
! virtual value_range wi_fold (tree type,
! const wide_int &lh_lb,
! const wide_int &lh_ub,
! const wide_int &rh_lb,
! const wide_int &rh_ub) const;
} op_minus;
! value_range
! operator_minus::wi_fold (tree type,
const wide_int &lh_lb, const wide_int &lh_ub,
const wide_int &rh_lb, const wide_int &rh_ub) const
{
--- 924,938 ----
virtual bool op2_range (value_range &r, tree type,
const value_range &lhs,
const value_range &op1) const;
! virtual void wi_fold (value_range &r, tree type,
! const wide_int &lh_lb,
! const wide_int &lh_ub,
! const wide_int &rh_lb,
! const wide_int &rh_ub) const;
} op_minus;
! void
! operator_minus::wi_fold (value_range &r, tree type,
const wide_int &lh_lb, const wide_int &lh_ub,
const wide_int &rh_lb, const wide_int &rh_ub) const
{
*************** operator_minus::wi_fold (tree type,
*** 950,956 ****
signop s = TYPE_SIGN (type);
wide_int new_lb = wi::sub (lh_lb, rh_ub, s, &ov_lb);
wide_int new_ub = wi::sub (lh_ub, rh_lb, s, &ov_ub);
! return value_range_with_overflow (type, new_lb, new_ub, ov_lb, ov_ub);
}
bool
--- 940,946 ----
signop s = TYPE_SIGN (type);
wide_int new_lb = wi::sub (lh_lb, rh_ub, s, &ov_lb);
wide_int new_ub = wi::sub (lh_ub, rh_lb, s, &ov_ub);
! value_range_with_overflow (r, type, new_lb, new_ub, ov_lb, ov_ub);
}
bool
*************** operator_minus::op1_range (value_range &
*** 958,964 ****
const value_range &lhs,
const value_range &op2) const
{
! r = range_op_handler (PLUS_EXPR, type)->fold_range (type, lhs, op2);
return true;
}
--- 948,954 ----
const value_range &lhs,
const value_range &op2) const
{
! range_op_handler (PLUS_EXPR, type)->fold_range (r, type, lhs, op2);
return true;
}
*************** operator_minus::op2_range (value_range &
*** 967,973 ****
const value_range &lhs,
const value_range &op1) const
{
! r = fold_range (type, op1, lhs);
return true;
}
--- 957,963 ----
const value_range &lhs,
const value_range &op1) const
{
! fold_range (r, type, op1, lhs);
return true;
}
*************** operator_minus::op2_range (value_range &
*** 975,1018 ****
class operator_min : public range_operator
{
public:
! virtual value_range wi_fold (tree type,
! const wide_int &lh_lb,
! const wide_int &lh_ub,
! const wide_int &rh_lb,
! const wide_int &rh_ub) const;
} op_min;
! value_range
! operator_min::wi_fold (tree type,
const wide_int &lh_lb, const wide_int &lh_ub,
const wide_int &rh_lb, const wide_int &rh_ub) const
{
signop s = TYPE_SIGN (type);
wide_int new_lb = wi::min (lh_lb, rh_lb, s);
wide_int new_ub = wi::min (lh_ub, rh_ub, s);
! return value_range_with_overflow (type, new_lb, new_ub);
}
class operator_max : public range_operator
{
public:
! virtual value_range wi_fold (tree type,
! const wide_int &lh_lb,
! const wide_int &lh_ub,
! const wide_int &rh_lb,
! const wide_int &rh_ub) const;
} op_max;
! value_range
! operator_max::wi_fold (tree type,
const wide_int &lh_lb, const wide_int &lh_ub,
const wide_int &rh_lb, const wide_int &rh_ub) const
{
signop s = TYPE_SIGN (type);
wide_int new_lb = wi::max (lh_lb, rh_lb, s);
wide_int new_ub = wi::max (lh_ub, rh_ub, s);
! return value_range_with_overflow (type, new_lb, new_ub);
}
--- 965,1008 ----
class operator_min : public range_operator
{
public:
! virtual void wi_fold (value_range &r, tree type,
! const wide_int &lh_lb,
! const wide_int &lh_ub,
! const wide_int &rh_lb,
! const wide_int &rh_ub) const;
} op_min;
! void
! operator_min::wi_fold (value_range &r, tree type,
const wide_int &lh_lb, const wide_int &lh_ub,
const wide_int &rh_lb, const wide_int &rh_ub) const
{
signop s = TYPE_SIGN (type);
wide_int new_lb = wi::min (lh_lb, rh_lb, s);
wide_int new_ub = wi::min (lh_ub, rh_ub, s);
! value_range_with_overflow (r, type, new_lb, new_ub);
}
class operator_max : public range_operator
{
public:
! virtual void wi_fold (value_range &r, tree type,
! const wide_int &lh_lb,
! const wide_int &lh_ub,
! const wide_int &rh_lb,
! const wide_int &rh_ub) const;
} op_max;
! void
! operator_max::wi_fold (value_range &r, tree type,
const wide_int &lh_lb, const wide_int &lh_ub,
const wide_int &rh_lb, const wide_int &rh_ub) const
{
signop s = TYPE_SIGN (type);
wide_int new_lb = wi::max (lh_lb, rh_lb, s);
wide_int new_ub = wi::max (lh_ub, rh_ub, s);
! value_range_with_overflow (r, type, new_lb, new_ub);
}
*************** public:
*** 1027,1037 ****
const wide_int &) const = 0;
// Calculate the cross product of two sets of sub-ranges and return it.
! value_range wi_cross_product (tree type,
! const wide_int &lh_lb,
! const wide_int &lh_ub,
! const wide_int &rh_lb,
! const wide_int &rh_ub) const;
};
// Calculate the cross product of two sets of ranges and return it.
--- 1017,1027 ----
const wide_int &) const = 0;
// Calculate the cross product of two sets of sub-ranges and return it.
! void wi_cross_product (value_range &r, tree type,
! const wide_int &lh_lb,
! const wide_int &lh_ub,
! const wide_int &rh_lb,
! const wide_int &rh_ub) const;
};
// Calculate the cross product of two sets of ranges and return it.
*************** public:
*** 1047,1077 ****
// MIN1, MIN0 OP MAX1, MAX0 OP MIN1 and MAX0 OP MAX0 OP MAX1) and then
// figure the smallest and largest values to form the new range.
! value_range
! cross_product_operator::wi_cross_product (tree type,
const wide_int &lh_lb,
const wide_int &lh_ub,
const wide_int &rh_lb,
const wide_int &rh_ub) const
{
wide_int cp1, cp2, cp3, cp4;
// Compute the 4 cross operations, bailing if we get an overflow we
// can't handle.
if (wi_op_overflows (cp1, type, lh_lb, rh_lb))
! return value_range (type);
if (wi::eq_p (lh_lb, lh_ub))
cp3 = cp1;
else if (wi_op_overflows (cp3, type, lh_ub, rh_lb))
! return value_range (type);
if (wi::eq_p (rh_lb, rh_ub))
cp2 = cp1;
else if (wi_op_overflows (cp2, type, lh_lb, rh_ub))
! return value_range (type);
if (wi::eq_p (lh_lb, lh_ub))
cp4 = cp2;
else if (wi_op_overflows (cp4, type, lh_ub, rh_ub))
! return value_range (type);
// Order pairs.
signop sign = TYPE_SIGN (type);
--- 1037,1069 ----
// MIN1, MIN0 OP MAX1, MAX0 OP MIN1 and MAX0 OP MAX0 OP MAX1) and then
// figure the smallest and largest values to form the new range.
! void
! cross_product_operator::wi_cross_product (value_range &r, tree type,
const wide_int &lh_lb,
const wide_int &lh_ub,
const wide_int &rh_lb,
const wide_int &rh_ub) const
{
wide_int cp1, cp2, cp3, cp4;
+ // Default to varying.
+ r = value_range (type);
// Compute the 4 cross operations, bailing if we get an overflow we
// can't handle.
if (wi_op_overflows (cp1, type, lh_lb, rh_lb))
! return;
if (wi::eq_p (lh_lb, lh_ub))
cp3 = cp1;
else if (wi_op_overflows (cp3, type, lh_ub, rh_lb))
! return;
if (wi::eq_p (rh_lb, rh_ub))
cp2 = cp1;
else if (wi_op_overflows (cp2, type, lh_lb, rh_ub))
! return;
if (wi::eq_p (lh_lb, lh_ub))
cp4 = cp2;
else if (wi_op_overflows (cp4, type, lh_ub, rh_ub))
! return;
// Order pairs.
signop sign = TYPE_SIGN (type);
*************** cross_product_operator::wi_cross_product
*** 1083,1100 ****
// Choose min and max from the ordered pairs.
wide_int res_lb = wi::min (cp1, cp3, sign);
wide_int res_ub = wi::max (cp2, cp4, sign);
! return value_range_with_overflow (type, res_lb, res_ub);
}
class operator_mult : public cross_product_operator
{
public:
! virtual value_range wi_fold (tree type,
! const wide_int &lh_lb,
! const wide_int &lh_ub,
! const wide_int &rh_lb,
! const wide_int &rh_ub) const;
virtual bool wi_op_overflows (wide_int &res, tree type,
const wide_int &w0, const wide_int &w1) const;
} op_mult;
--- 1075,1092 ----
// Choose min and max from the ordered pairs.
wide_int res_lb = wi::min (cp1, cp3, sign);
wide_int res_ub = wi::max (cp2, cp4, sign);
! value_range_with_overflow (r, type, res_lb, res_ub);
}
class operator_mult : public cross_product_operator
{
public:
! virtual void wi_fold (value_range &r, tree type,
! const wide_int &lh_lb,
! const wide_int &lh_ub,
! const wide_int &rh_lb,
! const wide_int &rh_ub) const;
virtual bool wi_op_overflows (wide_int &res, tree type,
const wide_int &w0, const wide_int &w1) const;
} op_mult;
*************** operator_mult::wi_op_overflows (wide_int
*** 1119,1131 ****
return overflow;
}
! value_range
! operator_mult::wi_fold (tree type,
const wide_int &lh_lb, const wide_int &lh_ub,
const wide_int &rh_lb, const wide_int &rh_ub) const
{
if (TYPE_OVERFLOW_UNDEFINED (type))
! return wi_cross_product (type, lh_lb, lh_ub, rh_lb, rh_ub);
// Multiply the ranges when overflow wraps. This is basically fancy
// code so we don't drop to varying with an unsigned
--- 1111,1126 ----
return overflow;
}
! void
! operator_mult::wi_fold (value_range &r, tree type,
const wide_int &lh_lb, const wide_int &lh_ub,
const wide_int &rh_lb, const wide_int &rh_ub) const
{
if (TYPE_OVERFLOW_UNDEFINED (type))
! {
! wi_cross_product (r, type, lh_lb, lh_ub, rh_lb, rh_ub);
! return;
! }
// Multiply the ranges when overflow wraps. This is basically fancy
// code so we don't drop to varying with an unsigned
*************** operator_mult::wi_fold (tree type,
*** 1186,1196 ****
prod2 = prod3 - prod0;
if (wi::geu_p (prod2, sizem1))
// The range covers all values.
! return value_range (type);
!
! wide_int new_lb = wide_int::from (prod0, prec, sign);
! wide_int new_ub = wide_int::from (prod3, prec, sign);
! return create_possibly_reversed_range (type, new_lb, new_ub);
}
--- 1181,1193 ----
prod2 = prod3 - prod0;
if (wi::geu_p (prod2, sizem1))
// The range covers all values.
! r = value_range (type);
! else
! {
! wide_int new_lb = wide_int::from (prod0, prec, sign);
! wide_int new_ub = wide_int::from (prod3, prec, sign);
! create_possibly_reversed_range (r, type, new_lb, new_ub);
! }
}
*************** class operator_div : public cross_produc
*** 1198,1208 ****
{
public:
operator_div (enum tree_code c) { code = c; }
! virtual value_range wi_fold (tree type,
! const wide_int &lh_lb,
! const wide_int &lh_ub,
! const wide_int &rh_lb,
! const wide_int &rh_ub) const;
virtual bool wi_op_overflows (wide_int &res, tree type,
const wide_int &, const wide_int &) const;
private:
--- 1195,1205 ----
{
public:
operator_div (enum tree_code c) { code = c; }
! virtual void wi_fold (value_range &r, tree type,
! const wide_int &lh_lb,
! const wide_int &lh_ub,
! const wide_int &rh_lb,
! const wide_int &rh_ub) const;
virtual bool wi_op_overflows (wide_int &res, tree type,
const wide_int &, const wide_int &) const;
private:
*************** operator_div::wi_op_overflows (wide_int
*** 1251,1264 ****
return overflow;
}
! value_range
! operator_div::wi_fold (tree type,
const wide_int &lh_lb, const wide_int &lh_ub,
const wide_int &rh_lb, const wide_int &rh_ub) const
{
// If we know we will divide by zero, return undefined.
if (rh_lb == 0 && rh_ub == 0)
! return value_range ();
const wide_int dividend_min = lh_lb;
const wide_int dividend_max = lh_ub;
--- 1248,1264 ----
return overflow;
}
! void
! operator_div::wi_fold (value_range &r, tree type,
const wide_int &lh_lb, const wide_int &lh_ub,
const wide_int &rh_lb, const wide_int &rh_ub) const
{
// If we know we will divide by zero, return undefined.
if (rh_lb == 0 && rh_ub == 0)
! {
! r = value_range ();
! return;
! }
const wide_int dividend_min = lh_lb;
const wide_int dividend_max = lh_ub;
*************** operator_div::wi_fold (tree type,
*** 1270,1307 ****
// If we know we won't divide by zero, just do the division.
if (!wi_includes_zero_p (type, divisor_min, divisor_max))
! return wi_cross_product (type, dividend_min, dividend_max,
! divisor_min, divisor_max);
// If flag_non_call_exceptions, we must not eliminate a division by zero.
if (cfun->can_throw_non_call_exceptions)
! return value_range (type);
// If we're definitely dividing by zero, there's nothing to do.
if (wi_zero_p (type, divisor_min, divisor_max))
! return value_range ();
// Perform the division in 2 parts, [LB, -1] and [1, UB], which will
// skip any division by zero.
// First divide by the negative numbers, if any.
- value_range r;
if (wi::neg_p (divisor_min, sign))
! r = wi_cross_product (type, dividend_min, dividend_max,
! divisor_min, wi::minus_one (prec));
// Then divide by the non-zero positive numbers, if any.
if (wi::gt_p (divisor_max, wi::zero (prec), sign))
{
value_range tmp;
! tmp = wi_cross_product (type, dividend_min, dividend_max,
! wi::one (prec), divisor_max);
r.union_ (tmp);
}
! return r;
}
operator_div op_trunc_div (TRUNC_DIV_EXPR);
! operator_div op_floor_div(FLOOR_DIV_EXPR);
operator_div op_round_div (ROUND_DIV_EXPR);
operator_div op_ceil_div (CEIL_DIV_EXPR);
--- 1270,1319 ----
// If we know we won't divide by zero, just do the division.
if (!wi_includes_zero_p (type, divisor_min, divisor_max))
! {
! wi_cross_product (r, type, dividend_min, dividend_max,
! divisor_min, divisor_max);
! return;
! }
// If flag_non_call_exceptions, we must not eliminate a division by zero.
if (cfun->can_throw_non_call_exceptions)
! {
! r = value_range (type);
! return;
! }
// If we're definitely dividing by zero, there's nothing to do.
if (wi_zero_p (type, divisor_min, divisor_max))
! {
! r = value_range ();
! return;
! }
// Perform the division in 2 parts, [LB, -1] and [1, UB], which will
// skip any division by zero.
// First divide by the negative numbers, if any.
if (wi::neg_p (divisor_min, sign))
! wi_cross_product (r, type, dividend_min, dividend_max,
! divisor_min, wi::minus_one (prec));
! else
! r = value_range ();
!
// Then divide by the non-zero positive numbers, if any.
if (wi::gt_p (divisor_max, wi::zero (prec), sign))
{
value_range tmp;
! wi_cross_product (tmp, type, dividend_min, dividend_max,
! wi::one (prec), divisor_max);
r.union_ (tmp);
}
! // We shouldn't still have undefined here.
! gcc_checking_assert (!r.undefined_p ());
}
operator_div op_trunc_div (TRUNC_DIV_EXPR);
! operator_div op_floor_div (FLOOR_DIV_EXPR);
operator_div op_round_div (ROUND_DIV_EXPR);
operator_div op_ceil_div (CEIL_DIV_EXPR);
*************** operator_exact_divide::op1_range (value_
*** 1331,1337 ****
if (op2.singleton_p (&offset)
&& !integer_zerop (offset))
{
! r = range_op_handler (MULT_EXPR, type)->fold_range (type, lhs, op2);
return true;
}
return false;
--- 1343,1349 ----
if (op2.singleton_p (&offset)
&& !integer_zerop (offset))
{
! range_op_handler (MULT_EXPR, type)->fold_range (r, type, lhs, op2);
return true;
}
return false;
*************** operator_exact_divide::op1_range (value_
*** 1341,1367 ****
class operator_lshift : public cross_product_operator
{
public:
! virtual value_range fold_range (tree type,
! const value_range &op1,
! const value_range &op2) const;
! virtual value_range wi_fold (tree type,
! const wide_int &lh_lb, const wide_int &lh_ub,
! const wide_int &rh_lb, const wide_int &rh_ub) const;
virtual bool wi_op_overflows (wide_int &res,
tree type,
const wide_int &,
const wide_int &) const;
} op_lshift;
! value_range
! operator_lshift::fold_range (tree type,
const value_range &op1,
const value_range &op2) const
{
- value_range r;
if (undefined_shift_range_check (r, type, op2))
! return r;
// Transform left shifts by constants into multiplies.
if (op2.singleton_p ())
--- 1353,1378 ----
class operator_lshift : public cross_product_operator
{
public:
! virtual void fold_range (value_range &r, tree type,
! const value_range &op1,
! const value_range &op2) const;
! virtual void wi_fold (value_range &r, tree type,
! const wide_int &lh_lb, const wide_int &lh_ub,
! const wide_int &rh_lb, const wide_int &rh_ub) const;
virtual bool wi_op_overflows (wide_int &res,
tree type,
const wide_int &,
const wide_int &) const;
} op_lshift;
! void
! operator_lshift::fold_range (value_range &r, tree type,
const value_range &op1,
const value_range &op2) const
{
if (undefined_shift_range_check (r, type, op2))
! return;
// Transform left shifts by constants into multiplies.
if (op2.singleton_p ())
*************** operator_lshift::fold_range (tree type,
*** 1375,1392 ****
bool saved_flag_wrapv_pointer = flag_wrapv_pointer;
flag_wrapv = 1;
flag_wrapv_pointer = 1;
! r = range_op_handler (MULT_EXPR, type)->fold_range (type, op1, mult);
flag_wrapv = saved_flag_wrapv;
flag_wrapv_pointer = saved_flag_wrapv_pointer;
! return r;
}
// Otherwise, invoke the generic fold routine.
! return range_operator::fold_range (type, op1, op2);
}
! value_range
! operator_lshift::wi_fold (tree type,
const wide_int &lh_lb, const wide_int &lh_ub,
const wide_int &rh_lb, const wide_int &rh_ub) const
{
--- 1386,1403 ----
bool saved_flag_wrapv_pointer = flag_wrapv_pointer;
flag_wrapv = 1;
flag_wrapv_pointer = 1;
! range_op_handler (MULT_EXPR, type)->fold_range (r, type, op1, mult);
flag_wrapv = saved_flag_wrapv;
flag_wrapv_pointer = saved_flag_wrapv_pointer;
! return;
}
// Otherwise, invoke the generic fold routine.
! range_operator::fold_range (r, type, op1, op2);
}
! void
! operator_lshift::wi_fold (value_range &r, tree type,
const wide_int &lh_lb, const wide_int &lh_ub,
const wide_int &rh_lb, const wide_int &rh_ub) const
{
*************** operator_lshift::wi_fold (tree type,
*** 1440,1448 ****
}
if (in_bounds)
! return wi_cross_product (type, lh_lb, lh_ub, rh_lb, rh_ub);
!
! return value_range (type);
}
bool
--- 1451,1459 ----
}
if (in_bounds)
! wi_cross_product (r, type, lh_lb, lh_ub, rh_lb, rh_ub);
! else
! r = value_range (type);
}
bool
*************** operator_lshift::wi_op_overflows (wide_i
*** 1466,1479 ****
class operator_rshift : public cross_product_operator
{
public:
! virtual value_range fold_range (tree type,
! const value_range &op1,
! const value_range &op2) const;
! virtual value_range wi_fold (tree type,
! const wide_int &lh_lb,
! const wide_int &lh_ub,
! const wide_int &rh_lb,
! const wide_int &rh_ub) const;
virtual bool wi_op_overflows (wide_int &res,
tree type,
const wide_int &w0,
--- 1477,1490 ----
class operator_rshift : public cross_product_operator
{
public:
! virtual void fold_range (value_range &r, tree type,
! const value_range &op1,
! const value_range &op2) const;
! virtual void wi_fold (value_range &r, tree type,
! const wide_int &lh_lb,
! const wide_int &lh_ub,
! const wide_int &rh_lb,
! const wide_int &rh_ub) const;
virtual bool wi_op_overflows (wide_int &res,
tree type,
const wide_int &w0,
*************** operator_rshift::wi_op_overflows (wide_i
*** 1499,1547 ****
return false;
}
! value_range
! operator_rshift::fold_range (tree type,
const value_range &op1,
const value_range &op2) const
{
- value_range r;
if (undefined_shift_range_check (r, type, op2))
! return r;
// Otherwise, invoke the generic fold routine.
! return range_operator::fold_range (type, op1, op2);
}
! value_range
! operator_rshift::wi_fold (tree type,
const wide_int &lh_lb, const wide_int &lh_ub,
const wide_int &rh_lb, const wide_int &rh_ub) const
{
! return wi_cross_product (type, lh_lb, lh_ub, rh_lb, rh_ub);
}
class operator_cast: public range_operator
{
public:
! virtual value_range fold_range (tree type,
! const value_range &op1,
! const value_range &op2) const;
virtual bool op1_range (value_range &r, tree type,
const value_range &lhs,
const value_range &op2) const;
} op_convert;
! value_range
! operator_cast::fold_range (tree type ATTRIBUTE_UNUSED,
const value_range &lh,
const value_range &rh) const
{
- value_range r;
if (empty_range_check (r, lh, rh))
! return r;
!
tree inner = lh.type ();
tree outer = rh.type ();
gcc_checking_assert (rh.varying_p ());
--- 1510,1556 ----
return false;
}
! void
! operator_rshift::fold_range (value_range &r, tree type,
const value_range &op1,
const value_range &op2) const
{
if (undefined_shift_range_check (r, type, op2))
! return;
// Otherwise, invoke the generic fold routine.
! range_operator::fold_range (r, type, op1, op2);
}
! void
! operator_rshift::wi_fold (value_range &r, tree type,
const wide_int &lh_lb, const wide_int &lh_ub,
const wide_int &rh_lb, const wide_int &rh_ub) const
{
! wi_cross_product (r, type, lh_lb, lh_ub, rh_lb, rh_ub);
}
class operator_cast: public range_operator
{
public:
! virtual void fold_range (value_range &r, tree type,
! const value_range &op1,
! const value_range &op2) const;
virtual bool op1_range (value_range &r, tree type,
const value_range &lhs,
const value_range &op2) const;
} op_convert;
! void
! operator_cast::fold_range (value_range &r, tree type ATTRIBUTE_UNUSED,
const value_range &lh,
const value_range &rh) const
{
if (empty_range_check (r, lh, rh))
! return;
!
tree inner = lh.type ();
tree outer = rh.type ();
gcc_checking_assert (rh.varying_p ());
*************** operator_cast::fold_range (tree type ATT
*** 1551,1556 ****
--- 1560,1567 ----
unsigned inner_prec = TYPE_PRECISION (inner);
unsigned outer_prec = TYPE_PRECISION (outer);
+ // Start with an empty range and add subranges.
+ r = value_range ();
for (unsigned x = 0; x < lh.num_pairs (); ++x)
{
wide_int lh_lb = lh.lower_bound (x);
*************** operator_cast::fold_range (tree type ATT
*** 1572,1585 ****
|| !wi::eq_p (max, wi::max_value (outer_prec, outer_sign)))
{
value_range tmp;
! tmp = create_possibly_reversed_range (type, min, max);
r.union_ (tmp);
continue;
}
}
! return value_range (type);
}
- return r;
}
bool
--- 1583,1596 ----
|| !wi::eq_p (max, wi::max_value (outer_prec, outer_sign)))
{
value_range tmp;
! create_possibly_reversed_range (tmp, type, min, max);
r.union_ (tmp);
continue;
}
}
! r = value_range (type);
! return;
}
}
bool
*************** operator_cast::op1_range (value_range &r
*** 1588,1593 ****
--- 1599,1605 ----
const value_range &op2) const
{
tree lhs_type = lhs.type ();
+ value_range tmp;
gcc_checking_assert (types_compatible_p (op2.type(), type));
// If the precision of the LHS is smaller than the precision of the
*************** operator_cast::op1_range (value_range &r
*** 1598,1612 ****
// If we've been passed an actual value for the RHS rather than
// the type, see if it fits the LHS, and if so, then we can allow
// it.
! r = op2;
! r = fold_range (lhs_type, r, value_range (lhs_type));
! r = fold_range (type, r, value_range (type));
! if (r == op2)
{
// We know the value of the RHS fits in the LHS type, so
// convert the LHS and remove any values that arent in OP2.
! r = lhs;
! r = fold_range (type, r, value_range (type));
r.intersect (op2);
return true;
}
--- 1610,1622 ----
// If we've been passed an actual value for the RHS rather than
// the type, see if it fits the LHS, and if so, then we can allow
// it.
! fold_range (r, lhs_type, op2, value_range (lhs_type));
! fold_range (tmp, type, r, value_range (type));
! if (tmp == op2)
{
// We know the value of the RHS fits in the LHS type, so
// convert the LHS and remove any values that arent in OP2.
! fold_range (r, type, lhs, value_range (type));
r.intersect (op2);
return true;
}
*************** operator_cast::op1_range (value_range &r
*** 1646,1662 ****
if (TYPE_PRECISION (lhs_type) > TYPE_PRECISION (type))
{
// Cast the range of the RHS to the type of the LHS.
! value_range op_type (type);
! op_type = fold_range (lhs_type, op_type, value_range (lhs_type));
!
! // Intersect this with the LHS range will produce the RHS range.
! r = range_intersect (lhs, op_type);
}
else
! r = lhs;
// Cast the calculated range to the type of the RHS.
! r = fold_range (type, r, value_range (type));
return true;
}
--- 1656,1671 ----
if (TYPE_PRECISION (lhs_type) > TYPE_PRECISION (type))
{
// Cast the range of the RHS to the type of the LHS.
! fold_range (tmp, lhs_type, value_range (type), value_range (lhs_type));
! // Intersect this with the LHS range will produce the range, which
! // will be cast to the RHS type before returning.
! tmp.intersect (lhs);
}
else
! tmp = lhs;
// Cast the calculated range to the type of the RHS.
! fold_range (r, type, tmp, value_range (type));
return true;
}
*************** operator_cast::op1_range (value_range &r
*** 1664,1672 ****
class operator_logical_and : public range_operator
{
public:
! virtual value_range fold_range (tree type,
! const value_range &lh,
! const value_range &rh) const;
virtual bool op1_range (value_range &r, tree type,
const value_range &lhs,
const value_range &op2) const;
--- 1673,1681 ----
class operator_logical_and : public range_operator
{
public:
! virtual void fold_range (value_range &r, tree type,
! const value_range &lh,
! const value_range &rh) const;
virtual bool op1_range (value_range &r, tree type,
const value_range &lhs,
const value_range &op2) const;
*************** public:
*** 1676,1702 ****
} op_logical_and;
! value_range
! operator_logical_and::fold_range (tree type,
const value_range &lh,
const value_range &rh) const
{
- value_range r;
if (empty_range_check (r, lh, rh))
! return r;
// 0 && anything is 0.
if ((wi::eq_p (lh.lower_bound (), 0) && wi::eq_p (lh.upper_bound (), 0))
|| (wi::eq_p (lh.lower_bound (), 0) && wi::eq_p (rh.upper_bound (), 0)))
! return range_false (type);
!
! // To reach this point, there must be a logical 1 on each side, and
! // the only remaining question is whether there is a zero or not.
! if (lh.contains_p (build_zero_cst (lh.type ()))
! || rh.contains_p (build_zero_cst (rh.type ())))
! return range_true_and_false (type);
!
! return range_true (type);
}
bool
--- 1685,1709 ----
} op_logical_and;
! void
! operator_logical_and::fold_range (value_range &r, tree type,
const value_range &lh,
const value_range &rh) const
{
if (empty_range_check (r, lh, rh))
! return;
// 0 && anything is 0.
if ((wi::eq_p (lh.lower_bound (), 0) && wi::eq_p (lh.upper_bound (), 0))
|| (wi::eq_p (lh.lower_bound (), 0) && wi::eq_p (rh.upper_bound (), 0)))
! r = range_false (type);
! else if (lh.contains_p (build_zero_cst (lh.type ()))
! || rh.contains_p (build_zero_cst (rh.type ())))
! // To reach this point, there must be a logical 1 on each side, and
! // the only remaining question is whether there is a zero or not.
! r = range_true_and_false (type);
! else
! r = range_true (type);
}
bool
*************** public:
*** 1738,1748 ****
virtual bool op2_range (value_range &r, tree type,
const value_range &lhs,
const value_range &op1) const;
! virtual value_range wi_fold (tree type,
! const wide_int &lh_lb,
! const wide_int &lh_ub,
! const wide_int &rh_lb,
! const wide_int &rh_ub) const;
} op_bitwise_and;
// Optimize BIT_AND_EXPR and BIT_IOR_EXPR in terms of a mask if
--- 1745,1755 ----
virtual bool op2_range (value_range &r, tree type,
const value_range &lhs,
const value_range &op1) const;
! virtual void wi_fold (value_range &r, tree type,
! const wide_int &lh_lb,
! const wide_int &lh_ub,
! const wide_int &rh_lb,
! const wide_int &rh_ub) const;
} op_bitwise_and;
// Optimize BIT_AND_EXPR and BIT_IOR_EXPR in terms of a mask if
*************** wi_optimize_and_or (value_range &r,
*** 1820,1826 ****
}
else
gcc_unreachable ();
! r = value_range_with_overflow (type, res_lb, res_ub);
return true;
}
--- 1827,1833 ----
}
else
gcc_unreachable ();
! value_range_with_overflow (r, type, res_lb, res_ub);
return true;
}
*************** wi_set_zero_nonzero_bits (tree type,
*** 1864,1879 ****
}
}
! value_range
! operator_bitwise_and::wi_fold (tree type,
const wide_int &lh_lb,
const wide_int &lh_ub,
const wide_int &rh_lb,
const wide_int &rh_ub) const
{
- value_range r;
if (wi_optimize_and_or (r, BIT_AND_EXPR, type, lh_lb, lh_ub, rh_lb, rh_ub))
! return r;
wide_int maybe_nonzero_lh, mustbe_nonzero_lh;
wide_int maybe_nonzero_rh, mustbe_nonzero_rh;
--- 1871,1885 ----
}
}
! void
! operator_bitwise_and::wi_fold (value_range &r, tree type,
const wide_int &lh_lb,
const wide_int &lh_ub,
const wide_int &rh_lb,
const wide_int &rh_ub) const
{
if (wi_optimize_and_or (r, BIT_AND_EXPR, type, lh_lb, lh_ub, rh_lb, rh_ub))
! return;
wide_int maybe_nonzero_lh, mustbe_nonzero_lh;
wide_int maybe_nonzero_rh, mustbe_nonzero_rh;
*************** operator_bitwise_and::wi_fold (tree type
*** 1918,1926 ****
}
// If the limits got swapped around, return varying.
if (wi::gt_p (new_lb, new_ub,sign))
! return value_range (type);
!
! return value_range_with_overflow (type, new_lb, new_ub);
}
bool
--- 1924,1932 ----
}
// If the limits got swapped around, return varying.
if (wi::gt_p (new_lb, new_ub,sign))
! r = value_range (type);
! else
! value_range_with_overflow (r, type, new_lb, new_ub);
}
bool
*************** operator_bitwise_and::op2_range (value_r
*** 1949,1957 ****
class operator_logical_or : public range_operator
{
public:
! virtual value_range fold_range (tree type,
! const value_range &lh,
! const value_range &rh) const;
virtual bool op1_range (value_range &r, tree type,
const value_range &lhs,
const value_range &op2) const;
--- 1955,1963 ----
class operator_logical_or : public range_operator
{
public:
! virtual void fold_range (value_range &r, tree type,
! const value_range &lh,
! const value_range &rh) const;
virtual bool op1_range (value_range &r, tree type,
const value_range &lhs,
const value_range &op2) const;
*************** public:
*** 1960,1975 ****
const value_range &op1) const;
} op_logical_or;
! value_range
! operator_logical_or::fold_range (tree type ATTRIBUTE_UNUSED,
const value_range &lh,
const value_range &rh) const
{
- value_range r;
if (empty_range_check (r, lh, rh))
! return r;
! return range_union (lh, rh);
}
bool
--- 1966,1980 ----
const value_range &op1) const;
} op_logical_or;
! void
! operator_logical_or::fold_range (value_range &r, tree type ATTRIBUTE_UNUSED,
const value_range &lh,
const value_range &rh) const
{
if (empty_range_check (r, lh, rh))
! return;
! r = range_union (lh, rh);
}
bool
*************** public:
*** 2011,2033 ****
virtual bool op2_range (value_range &r, tree type,
const value_range &lhs,
const value_range &op1) const;
! virtual value_range wi_fold (tree type,
! const wide_int &lh_lb,
! const wide_int &lh_ub,
! const wide_int &rh_lb,
! const wide_int &rh_ub) const;
} op_bitwise_or;
! value_range
! operator_bitwise_or::wi_fold (tree type,
const wide_int &lh_lb,
const wide_int &lh_ub,
const wide_int &rh_lb,
const wide_int &rh_ub) const
{
- value_range r;
if (wi_optimize_and_or (r, BIT_IOR_EXPR, type, lh_lb, lh_ub, rh_lb, rh_ub))
! return r;
wide_int maybe_nonzero_lh, mustbe_nonzero_lh;
wide_int maybe_nonzero_rh, mustbe_nonzero_rh;
--- 2016,2037 ----
virtual bool op2_range (value_range &r, tree type,
const value_range &lhs,
const value_range &op1) const;
! virtual void wi_fold (value_range &r, tree type,
! const wide_int &lh_lb,
! const wide_int &lh_ub,
! const wide_int &rh_lb,
! const wide_int &rh_ub) const;
} op_bitwise_or;
! void
! operator_bitwise_or::wi_fold (value_range &r, tree type,
const wide_int &lh_lb,
const wide_int &lh_ub,
const wide_int &rh_lb,
const wide_int &rh_ub) const
{
if (wi_optimize_and_or (r, BIT_IOR_EXPR, type, lh_lb, lh_ub, rh_lb, rh_ub))
! return;
wide_int maybe_nonzero_lh, mustbe_nonzero_lh;
wide_int maybe_nonzero_rh, mustbe_nonzero_rh;
*************** operator_bitwise_or::wi_fold (tree type,
*** 2056,2064 ****
new_lb = wi::max (new_lb, rh_lb, sign);
// If the limits got swapped around, return varying.
if (wi::gt_p (new_lb, new_ub,sign))
! return value_range (type);
!
! return value_range_with_overflow (type, new_lb, new_ub);
}
bool
--- 2060,2068 ----
new_lb = wi::max (new_lb, rh_lb, sign);
// If the limits got swapped around, return varying.
if (wi::gt_p (new_lb, new_ub,sign))
! r = value_range (type);
! else
! value_range_with_overflow (r, type, new_lb, new_ub);
}
bool
*************** operator_bitwise_or::op2_range (value_ra
*** 2087,2101 ****
class operator_bitwise_xor : public range_operator
{
public:
! virtual value_range wi_fold (tree type,
! const wide_int &lh_lb,
! const wide_int &lh_ub,
! const wide_int &rh_lb,
! const wide_int &rh_ub) const;
} op_bitwise_xor;
! value_range
! operator_bitwise_xor::wi_fold (tree type,
const wide_int &lh_lb,
const wide_int &lh_ub,
const wide_int &rh_lb,
--- 2091,2105 ----
class operator_bitwise_xor : public range_operator
{
public:
! virtual void wi_fold (value_range &r, tree type,
! const wide_int &lh_lb,
! const wide_int &lh_ub,
! const wide_int &rh_lb,
! const wide_int &rh_ub) const;
} op_bitwise_xor;
! void
! operator_bitwise_xor::wi_fold (value_range &r, tree type,
const wide_int &lh_lb,
const wide_int &lh_ub,
const wide_int &rh_lb,
*************** operator_bitwise_xor::wi_fold (tree type
*** 2120,2143 ****
// If the range has all positive or all negative values, the result
// is better than VARYING.
if (wi::lt_p (new_lb, 0, sign) || wi::ge_p (new_ub, 0, sign))
! return value_range_with_overflow (type, new_lb, new_ub);
!
! return value_range (type);
}
class operator_trunc_mod : public range_operator
{
public:
! virtual value_range wi_fold (tree type,
! const wide_int &lh_lb,
! const wide_int &lh_ub,
! const wide_int &rh_lb,
! const wide_int &rh_ub) const;
} op_trunc_mod;
! value_range
! operator_trunc_mod::wi_fold (tree type,
const wide_int &lh_lb,
const wide_int &lh_ub,
const wide_int &rh_lb,
--- 2124,2147 ----
// If the range has all positive or all negative values, the result
// is better than VARYING.
if (wi::lt_p (new_lb, 0, sign) || wi::ge_p (new_ub, 0, sign))
! value_range_with_overflow (r, type, new_lb, new_ub);
! else
! r = value_range (type);
}
class operator_trunc_mod : public range_operator
{
public:
! virtual void wi_fold (value_range &r, tree type,
! const wide_int &lh_lb,
! const wide_int &lh_ub,
! const wide_int &rh_lb,
! const wide_int &rh_ub) const;
} op_trunc_mod;
! void
! operator_trunc_mod::wi_fold (value_range &r, tree type,
const wide_int &lh_lb,
const wide_int &lh_ub,
const wide_int &rh_lb,
*************** operator_trunc_mod::wi_fold (tree type,
*** 2149,2155 ****
// Mod 0 is undefined. Return undefined.
if (wi_zero_p (type, rh_lb, rh_ub))
! return value_range ();
// ABS (A % B) < ABS (B) and either 0 <= A % B <= A or A <= A % B <= 0.
new_ub = rh_ub - 1;
--- 2153,2162 ----
// Mod 0 is undefined. Return undefined.
if (wi_zero_p (type, rh_lb, rh_ub))
! {
! r = value_range ();
! return;
! }
// ABS (A % B) < ABS (B) and either 0 <= A % B <= A or A <= A % B <= 0.
new_ub = rh_ub - 1;
*************** operator_trunc_mod::wi_fold (tree type,
*** 2174,2189 ****
tmp = wi::zero (prec);
new_ub = wi::min (new_ub, tmp, sign);
! return value_range_with_overflow (type, new_lb, new_ub);
}
class operator_logical_not : public range_operator
{
public:
! virtual value_range fold_range (tree type,
! const value_range &lh,
! const value_range &rh) const;
virtual bool op1_range (value_range &r, tree type,
const value_range &lhs,
const value_range &op2) const;
--- 2181,2196 ----
tmp = wi::zero (prec);
new_ub = wi::min (new_ub, tmp, sign);
! value_range_with_overflow (r, type, new_lb, new_ub);
}
class operator_logical_not : public range_operator
{
public:
! virtual void fold_range (value_range &r, tree type,
! const value_range &lh,
! const value_range &rh) const;
virtual bool op1_range (value_range &r, tree type,
const value_range &lhs,
const value_range &op2) const;
*************** public:
*** 2203,2223 ****
// b_2 = x_1 < 20 [0,0] = x_1 < 20, false, so x_1 == [20, 255]
// which is the result we are looking for.. so.. pass it through.
! value_range
! operator_logical_not::fold_range (tree type,
const value_range &lh,
const value_range &rh ATTRIBUTE_UNUSED) const
{
- value_range r;
if (empty_range_check (r, lh, rh))
! return r;
if (lh.varying_p () || lh.undefined_p ())
r = lh;
else
r = range_invert (lh);
gcc_checking_assert (lh.type() == type);
! return r;
}
bool
--- 2210,2229 ----
// b_2 = x_1 < 20 [0,0] = x_1 < 20, false, so x_1 == [20, 255]
// which is the result we are looking for.. so.. pass it through.
! void
! operator_logical_not::fold_range (value_range &r, tree type,
const value_range &lh,
const value_range &rh ATTRIBUTE_UNUSED) const
{
if (empty_range_check (r, lh, rh))
! return;
if (lh.varying_p () || lh.undefined_p ())
r = lh;
else
r = range_invert (lh);
gcc_checking_assert (lh.type() == type);
! return;
}
bool
*************** operator_logical_not::op1_range (value_r
*** 2237,2264 ****
class operator_bitwise_not : public range_operator
{
public:
! virtual value_range fold_range (tree type,
! const value_range &lh,
! const value_range &rh) const;
virtual bool op1_range (value_range &r, tree type,
const value_range &lhs,
const value_range &op2) const;
} op_bitwise_not;
! value_range
! operator_bitwise_not::fold_range (tree type,
const value_range &lh,
const value_range &rh) const
{
- value_range r;
if (empty_range_check (r, lh, rh))
! return r;
// ~X is simply -1 - X.
value_range minusone (type, wi::minus_one (TYPE_PRECISION (type)),
wi::minus_one (TYPE_PRECISION (type)));
! r = range_op_handler (MINUS_EXPR, type)->fold_range (type, minusone, lh);
! return r;
}
bool
--- 2243,2269 ----
class operator_bitwise_not : public range_operator
{
public:
! virtual void fold_range (value_range &r, tree type,
! const value_range &lh,
! const value_range &rh) const;
virtual bool op1_range (value_range &r, tree type,
const value_range &lhs,
const value_range &op2) const;
} op_bitwise_not;
! void
! operator_bitwise_not::fold_range (value_range &r, tree type,
const value_range &lh,
const value_range &rh) const
{
if (empty_range_check (r, lh, rh))
! return;
// ~X is simply -1 - X.
value_range minusone (type, wi::minus_one (TYPE_PRECISION (type)),
wi::minus_one (TYPE_PRECISION (type)));
! range_op_handler (MINUS_EXPR, type)->fold_range (r, type, minusone, lh);
! return;
}
bool
*************** operator_bitwise_not::op1_range (value_r
*** 2267,2273 ****
const value_range &op2) const
{
// ~X is -1 - X and since bitwise NOT is involutary...do it again.
! r = fold_range (type, lhs, op2);
return true;
}
--- 2272,2278 ----
const value_range &op2) const
{
// ~X is -1 - X and since bitwise NOT is involutary...do it again.
! fold_range (r, type, lhs, op2);
return true;
}
*************** operator_bitwise_not::op1_range (value_r
*** 2275,2311 ****
class operator_cst : public range_operator
{
public:
! virtual value_range fold_range (tree type,
! const value_range &op1,
! const value_range &op2) const;
} op_integer_cst;
! value_range
! operator_cst::fold_range (tree type ATTRIBUTE_UNUSED,
const value_range &lh,
const value_range &rh ATTRIBUTE_UNUSED) const
{
! return lh;
}
class operator_identity : public range_operator
{
public:
! virtual value_range fold_range (tree type,
! const value_range &op1,
! const value_range &op2) const;
virtual bool op1_range (value_range &r, tree type,
const value_range &lhs,
const value_range &op2) const;
} op_identity;
! value_range
! operator_identity::fold_range (tree type ATTRIBUTE_UNUSED,
const value_range &lh,
const value_range &rh ATTRIBUTE_UNUSED) const
{
! return lh;
}
bool
--- 2280,2316 ----
class operator_cst : public range_operator
{
public:
! virtual void fold_range (value_range &r, tree type,
! const value_range &op1,
! const value_range &op2) const;
} op_integer_cst;
! void
! operator_cst::fold_range (value_range &r, tree type ATTRIBUTE_UNUSED,
const value_range &lh,
const value_range &rh ATTRIBUTE_UNUSED) const
{
! r = lh;
}
class operator_identity : public range_operator
{
public:
! virtual void fold_range (value_range &r, tree type,
! const value_range &op1,
! const value_range &op2) const;
virtual bool op1_range (value_range &r, tree type,
const value_range &lhs,
const value_range &op2) const;
} op_identity;
! void
! operator_identity::fold_range (value_range &r, tree type ATTRIBUTE_UNUSED,
const value_range &lh,
const value_range &rh ATTRIBUTE_UNUSED) const
{
! r = lh;
}
bool
*************** operator_identity::op1_range (value_rang
*** 2321,2338 ****
class operator_abs : public range_operator
{
public:
! virtual value_range wi_fold (tree type,
! const wide_int &lh_lb,
! const wide_int &lh_ub,
! const wide_int &rh_lb,
! const wide_int &rh_ub) const;
virtual bool op1_range (value_range &r, tree type,
const value_range &lhs,
const value_range &op2) const;
} op_abs;
! value_range
! operator_abs::wi_fold (tree type,
const wide_int &lh_lb, const wide_int &lh_ub,
const wide_int &rh_lb ATTRIBUTE_UNUSED,
const wide_int &rh_ub ATTRIBUTE_UNUSED) const
--- 2326,2343 ----
class operator_abs : public range_operator
{
public:
! virtual void wi_fold (value_range &r, tree type,
! const wide_int &lh_lb,
! const wide_int &lh_ub,
! const wide_int &rh_lb,
! const wide_int &rh_ub) const;
virtual bool op1_range (value_range &r, tree type,
const value_range &lhs,
const value_range &op2) const;
} op_abs;
! void
! operator_abs::wi_fold (value_range &r, tree type,
const wide_int &lh_lb, const wide_int &lh_ub,
const wide_int &rh_lb ATTRIBUTE_UNUSED,
const wide_int &rh_ub ATTRIBUTE_UNUSED) const
*************** operator_abs::wi_fold (tree type,
*** 2343,2356 ****
// Pass through LH for the easy cases.
if (sign == UNSIGNED || wi::ge_p (lh_lb, 0, sign))
! return value_range (type, lh_lb, lh_ub);
// -TYPE_MIN_VALUE = TYPE_MIN_VALUE with flag_wrapv so we can't get
// a useful range.
wide_int min_value = wi::min_value (prec, sign);
wide_int max_value = wi::max_value (prec, sign);
if (!TYPE_OVERFLOW_UNDEFINED (type) && wi::eq_p (lh_lb, min_value))
! return value_range (type);
// ABS_EXPR may flip the range around, if the original range
// included negative values.
--- 2348,2367 ----
// Pass through LH for the easy cases.
if (sign == UNSIGNED || wi::ge_p (lh_lb, 0, sign))
! {
! r = value_range (type, lh_lb, lh_ub);
! return;
! }
// -TYPE_MIN_VALUE = TYPE_MIN_VALUE with flag_wrapv so we can't get
// a useful range.
wide_int min_value = wi::min_value (prec, sign);
wide_int max_value = wi::max_value (prec, sign);
if (!TYPE_OVERFLOW_UNDEFINED (type) && wi::eq_p (lh_lb, min_value))
! {
! r = value_range (type, lh_lb, lh_ub);
! return;
! }
// ABS_EXPR may flip the range around, if the original range
// included negative values.
*************** operator_abs::wi_fold (tree type,
*** 2386,2392 ****
min = wi::zero (prec);
max = max_value;
}
! return value_range (type, min, max);
}
bool
--- 2397,2403 ----
min = wi::zero (prec);
max = max_value;
}
! r = value_range (type, min, max);
}
bool
*************** operator_abs::op1_range (value_range &r,
*** 2418,2430 ****
class operator_absu : public range_operator
{
public:
! virtual value_range wi_fold (tree type,
! const wide_int &lh_lb, const wide_int &lh_ub,
! const wide_int &rh_lb, const wide_int &rh_ub) const;
} op_absu;
! value_range
! operator_absu::wi_fold (tree type,
const wide_int &lh_lb, const wide_int &lh_ub,
const wide_int &rh_lb ATTRIBUTE_UNUSED,
const wide_int &rh_ub ATTRIBUTE_UNUSED) const
--- 2429,2441 ----
class operator_absu : public range_operator
{
public:
! virtual void wi_fold (value_range &r, tree type,
! const wide_int &lh_lb, const wide_int &lh_ub,
! const wide_int &rh_lb, const wide_int &rh_ub) const;
} op_absu;
! void
! operator_absu::wi_fold (value_range &r, tree type,
const wide_int &lh_lb, const wide_int &lh_ub,
const wide_int &rh_lb ATTRIBUTE_UNUSED,
const wide_int &rh_ub ATTRIBUTE_UNUSED) const
*************** operator_absu::wi_fold (tree type,
*** 2455,2487 ****
}
gcc_checking_assert (TYPE_UNSIGNED (type));
! return value_range (type, new_lb, new_ub);
}
class operator_negate : public range_operator
{
public:
! virtual value_range fold_range (tree type,
! const value_range &op1,
! const value_range &op2) const;
virtual bool op1_range (value_range &r, tree type,
const value_range &lhs,
const value_range &op2) const;
} op_negate;
! value_range
! operator_negate::fold_range (tree type,
const value_range &lh,
const value_range &rh) const
{
- value_range r;
if (empty_range_check (r, lh, rh))
! return r;
// -X is simply 0 - X.
! return
! range_op_handler (MINUS_EXPR, type)->fold_range (type,
! range_zero (type), lh);
}
bool
--- 2466,2496 ----
}
gcc_checking_assert (TYPE_UNSIGNED (type));
! r = value_range (type, new_lb, new_ub);
}
class operator_negate : public range_operator
{
public:
! virtual void fold_range (value_range &r, tree type,
! const value_range &op1,
! const value_range &op2) const;
virtual bool op1_range (value_range &r, tree type,
const value_range &lhs,
const value_range &op2) const;
} op_negate;
! void
! operator_negate::fold_range (value_range &r, tree type,
const value_range &lh,
const value_range &rh) const
{
if (empty_range_check (r, lh, rh))
! return;
// -X is simply 0 - X.
! range_op_handler (MINUS_EXPR, type)->fold_range (r, type,
! range_zero (type), lh);
}
bool
*************** operator_negate::op1_range (value_range
*** 2490,2496 ****
const value_range &op2) const
{
// NEGATE is involutory.
! r = fold_range (type, lhs, op2);
return true;
}
--- 2499,2505 ----
const value_range &op2) const
{
// NEGATE is involutory.
! fold_range (r, type, lhs, op2);
return true;
}
*************** operator_negate::op1_range (value_range
*** 2498,2526 ****
class operator_addr_expr : public range_operator
{
public:
! virtual value_range fold_range (tree type,
! const value_range &op1,
! const value_range &op2) const;
virtual bool op1_range (value_range &r, tree type,
const value_range &lhs,
const value_range &op2) const;
} op_addr;
! value_range
! operator_addr_expr::fold_range (tree type,
const value_range &lh,
const value_range &rh) const
{
- value_range r;
if (empty_range_check (r, lh, rh))
! return r;
// Return a non-null pointer of the LHS type (passed in op2).
if (lh.zero_p ())
! return range_zero (type);
! if (!lh.contains_p (build_zero_cst (lh.type ())))
! return range_nonzero (type);
! return value_range (type);
}
bool
--- 2507,2535 ----
class operator_addr_expr : public range_operator
{
public:
! virtual void fold_range (value_range &r, tree type,
! const value_range &op1,
! const value_range &op2) const;
virtual bool op1_range (value_range &r, tree type,
const value_range &lhs,
const value_range &op2) const;
} op_addr;
! void
! operator_addr_expr::fold_range (value_range &r, tree type,
const value_range &lh,
const value_range &rh) const
{
if (empty_range_check (r, lh, rh))
! return;
// Return a non-null pointer of the LHS type (passed in op2).
if (lh.zero_p ())
! r = range_zero (type);
! else if (!lh.contains_p (build_zero_cst (lh.type ())))
! r = range_nonzero (type);
! else
! r = value_range (type);
}
bool
*************** operator_addr_expr::op1_range (value_ran
*** 2528,2534 ****
const value_range &lhs,
const value_range &op2) const
{
! r = operator_addr_expr::fold_range (type, lhs, op2);
return true;
}
--- 2537,2543 ----
const value_range &lhs,
const value_range &op2) const
{
! operator_addr_expr::fold_range (r, type, lhs, op2);
return true;
}
*************** operator_addr_expr::op1_range (value_ran
*** 2536,2550 ****
class pointer_plus_operator : public range_operator
{
public:
! virtual value_range wi_fold (tree type,
! const wide_int &lh_lb,
! const wide_int &lh_ub,
! const wide_int &rh_lb,
! const wide_int &rh_ub) const;
} op_pointer_plus;
! value_range
! pointer_plus_operator::wi_fold (tree type,
const wide_int &lh_lb,
const wide_int &lh_ub,
const wide_int &rh_lb,
--- 2545,2559 ----
class pointer_plus_operator : public range_operator
{
public:
! virtual void wi_fold (value_range &r, tree type,
! const wide_int &lh_lb,
! const wide_int &lh_ub,
! const wide_int &rh_lb,
! const wide_int &rh_ub) const;
} op_pointer_plus;
! void
! pointer_plus_operator::wi_fold (value_range &r, tree type,
const wide_int &lh_lb,
const wide_int &lh_ub,
const wide_int &rh_lb,
*************** pointer_plus_operator::wi_fold (tree typ
*** 2571,2594 ****
&& !TYPE_OVERFLOW_WRAPS (type)
&& (flag_delete_null_pointer_checks
|| !wi::sign_mask (rh_ub)))
! return range_nonzero (type);
! if (lh_lb == lh_ub && lh_lb == 0
! && rh_lb == rh_ub && rh_lb == 0)
! return range_zero (type);
! return value_range (type);
}
class pointer_min_max_operator : public range_operator
{
public:
! virtual value_range wi_fold (tree type,
! const wide_int &lh_lb, const wide_int &lh_ub,
! const wide_int &rh_lb, const wide_int &rh_ub) const;
} op_ptr_min_max;
! value_range
! pointer_min_max_operator::wi_fold (tree type,
const wide_int &lh_lb,
const wide_int &lh_ub,
const wide_int &rh_lb,
--- 2580,2604 ----
&& !TYPE_OVERFLOW_WRAPS (type)
&& (flag_delete_null_pointer_checks
|| !wi::sign_mask (rh_ub)))
! r = range_nonzero (type);
! else if (lh_lb == lh_ub && lh_lb == 0
! && rh_lb == rh_ub && rh_lb == 0)
! r = range_zero (type);
! else
! r = value_range (type);
}
class pointer_min_max_operator : public range_operator
{
public:
! virtual void wi_fold (value_range & r, tree type,
! const wide_int &lh_lb, const wide_int &lh_ub,
! const wide_int &rh_lb, const wide_int &rh_ub) const;
} op_ptr_min_max;
! void
! pointer_min_max_operator::wi_fold (value_range &r, tree type,
const wide_int &lh_lb,
const wide_int &lh_ub,
const wide_int &rh_lb,
*************** pointer_min_max_operator::wi_fold (tree
*** 2600,2622 ****
// are varying.
if (!wi_includes_zero_p (type, lh_lb, lh_ub)
&& !wi_includes_zero_p (type, rh_lb, rh_ub))
! return range_nonzero (type);
! if (wi_zero_p (type, lh_lb, lh_ub) && wi_zero_p (type, rh_lb, rh_ub))
! return range_zero (type);
! return value_range (type);
}
class pointer_and_operator : public range_operator
{
public:
! virtual value_range wi_fold (tree type,
! const wide_int &lh_lb, const wide_int &lh_ub,
! const wide_int &rh_lb, const wide_int &rh_ub) const;
} op_pointer_and;
! value_range
! pointer_and_operator::wi_fold (tree type,
const wide_int &lh_lb,
const wide_int &lh_ub,
const wide_int &rh_lb ATTRIBUTE_UNUSED,
--- 2610,2633 ----
// are varying.
if (!wi_includes_zero_p (type, lh_lb, lh_ub)
&& !wi_includes_zero_p (type, rh_lb, rh_ub))
! r = range_nonzero (type);
! else if (wi_zero_p (type, lh_lb, lh_ub) && wi_zero_p (type, rh_lb, rh_ub))
! r = range_zero (type);
! else
! r = value_range (type);
}
class pointer_and_operator : public range_operator
{
public:
! virtual void wi_fold (value_range &r, tree type,
! const wide_int &lh_lb, const wide_int &lh_ub,
! const wide_int &rh_lb, const wide_int &rh_ub) const;
} op_pointer_and;
! void
! pointer_and_operator::wi_fold (value_range &r, tree type,
const wide_int &lh_lb,
const wide_int &lh_ub,
const wide_int &rh_lb ATTRIBUTE_UNUSED,
*************** pointer_and_operator::wi_fold (tree type
*** 2625,2646 ****
// For pointer types, we are really only interested in asserting
// whether the expression evaluates to non-NULL.
if (wi_zero_p (type, lh_lb, lh_ub) || wi_zero_p (type, lh_lb, lh_ub))
! return range_zero (type);
!
! return value_range (type);
}
class pointer_or_operator : public range_operator
{
public:
! virtual value_range wi_fold (tree type,
! const wide_int &lh_lb, const wide_int &lh_ub,
! const wide_int &rh_lb, const wide_int &rh_ub) const;
} op_pointer_or;
! value_range
! pointer_or_operator::wi_fold (tree type,
const wide_int &lh_lb,
const wide_int &lh_ub,
const wide_int &rh_lb,
--- 2636,2657 ----
// For pointer types, we are really only interested in asserting
// whether the expression evaluates to non-NULL.
if (wi_zero_p (type, lh_lb, lh_ub) || wi_zero_p (type, lh_lb, lh_ub))
! r = range_zero (type);
! else
! r = value_range (type);
}
class pointer_or_operator : public range_operator
{
public:
! virtual void wi_fold (value_range &r, tree type,
! const wide_int &lh_lb, const wide_int &lh_ub,
! const wide_int &rh_lb, const wide_int &rh_ub) const;
} op_pointer_or;
! void
! pointer_or_operator::wi_fold (value_range &r, tree type,
const wide_int &lh_lb,
const wide_int &lh_ub,
const wide_int &rh_lb,
*************** pointer_or_operator::wi_fold (tree type,
*** 2650,2659 ****
// whether the expression evaluates to non-NULL.
if (!wi_includes_zero_p (type, lh_lb, lh_ub)
&& !wi_includes_zero_p (type, rh_lb, rh_ub))
! return range_nonzero (type);
! if (wi_zero_p (type, lh_lb, lh_ub) && wi_zero_p (type, rh_lb, rh_ub))
! return range_zero (type);
! return value_range (type);
}
// This implements the range operator tables as local objects in this file.
--- 2661,2671 ----
// whether the expression evaluates to non-NULL.
if (!wi_includes_zero_p (type, lh_lb, lh_ub)
&& !wi_includes_zero_p (type, rh_lb, rh_ub))
! r = range_nonzero (type);
! else if (wi_zero_p (type, lh_lb, lh_ub) && wi_zero_p (type, rh_lb, rh_ub))
! r = range_zero (type);
! else
! r = value_range (type);
}
// This implements the range operator tables as local objects in this file.
*************** range_op_handler (enum tree_code code, t
*** 2782,2789 ****
void
range_cast (value_range &r, tree type)
{
range_operator *op = range_op_handler (CONVERT_EXPR, type);
! r = op->fold_range (type, r, value_range (type));
}
#if CHECKING_P
--- 2794,2802 ----
void
range_cast (value_range &r, tree type)
{
+ value_range tmp = r;
range_operator *op = range_op_handler (CONVERT_EXPR, type);
! op->fold_range (r, type, tmp, value_range (type));
}
#if CHECKING_P
Index: tree-vrp.c
===================================================================
*** tree-vrp.c (revision 277853)
--- tree-vrp.c (working copy)
*************** range_fold_binary_symbolics_p (value_ran
*** 1781,1789 ****
return true;
}
const range_operator *op = get_range_op_handler (vr, code, expr_type);
! *vr = op->fold_range (expr_type,
! vr0->normalize_symbolics (),
! vr1->normalize_symbolics ());
return true;
}
return false;
--- 1781,1788 ----
return true;
}
const range_operator *op = get_range_op_handler (vr, code, expr_type);
! op->fold_range (*vr, expr_type, vr0->normalize_symbolics (),
! vr1->normalize_symbolics ());
return true;
}
return false;
*************** range_fold_unary_symbolics_p (value_rang
*** 1817,1825 ****
return true;
}
const range_operator *op = get_range_op_handler (vr, code, expr_type);
! *vr = op->fold_range (expr_type,
! vr0->normalize_symbolics (),
! value_range (expr_type));
return true;
}
return false;
--- 1816,1823 ----
return true;
}
const range_operator *op = get_range_op_handler (vr, code, expr_type);
! op->fold_range (*vr, expr_type, vr0->normalize_symbolics (),
! value_range (expr_type));
return true;
}
return false;
*************** range_fold_binary_expr (value_range *vr,
*** 1846,1854 ****
if (range_fold_binary_symbolics_p (vr, code, expr_type, &vr0, &vr1))
return;
! *vr = op->fold_range (expr_type,
! vr0.normalize_addresses (),
! vr1.normalize_addresses ());
}
/* Perform a unary operation on a range. */
--- 1844,1851 ----
if (range_fold_binary_symbolics_p (vr, code, expr_type, &vr0, &vr1))
return;
! op->fold_range (*vr, expr_type, vr0.normalize_addresses (),
! vr1.normalize_addresses ());
}
/* Perform a unary operation on a range. */
*************** range_fold_unary_expr (value_range *vr,
*** 1869,1877 ****
if (range_fold_unary_symbolics_p (vr, code, expr_type, vr0))
return;
! *vr = op->fold_range (expr_type,
! vr0->normalize_addresses (),
! value_range (expr_type));
}
/* Given a COND_EXPR COND of the form 'V OP W', and an SSA name V,
--- 1866,1873 ----
if (range_fold_unary_symbolics_p (vr, code, expr_type, vr0))
return;
! op->fold_range (*vr, expr_type, vr0->normalize_addresses (),
! value_range (expr_type));
}
/* Given a COND_EXPR COND of the form 'V OP W', and an SSA name V,