Unify MULT_EXPR range operator
Move the declaration of the class to the range-op-mixed header, add the floating point prototypes as well, and use it in the new unified table. * range-op-float.cc (foperator_mult_div_base): Delete. (foperator_mult_div_base::find_range): Make static local function. (foperator_mult): Remove. Move prototypes to range-op-mixed.h (operator_mult::op1_range): Rename from foperator_mult. (operator_mult::op2_range): Ditto. (operator_mult::rv_fold): Ditto. (float_table::float_table): Remove MULT_EXPR. (class foperator_div): Inherit from range_operator. (float_table::float_table): Delete. * range-op-mixed.h (class operator_mult): Combined from integer and float files. * range-op.cc (float_tree_table): Delete. (op_mult): New object. (unified_table::unified_table): Add MULT_EXPR. (get_op_handler): Do not check float table any longer. (class cross_product_operator): Move to range-op-mixed.h. (class operator_mult): Move to range-op-mixed.h. (integral_table::integral_table): Remove MULT_EXPR. (pointer_table::pointer_table): Remove MULT_EXPR. * range-op.h (float_table): Remove.
This commit is contained in:
parent
56518befc2
commit
a13c444094
4 changed files with 221 additions and 230 deletions
|
@ -2331,188 +2331,182 @@ operator_minus::rv_fold (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub,
|
|||
}
|
||||
|
||||
|
||||
class foperator_mult_div_base : public range_operator
|
||||
// Given CP[0] to CP[3] floating point values rounded to -INF,
|
||||
// set LB to the smallest of them (treating -0 as smaller to +0).
|
||||
// Given CP[4] to CP[7] floating point values rounded to +INF,
|
||||
// set UB to the largest of them (treating -0 as smaller to +0).
|
||||
|
||||
static void
|
||||
find_range (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub,
|
||||
const REAL_VALUE_TYPE (&cp)[8])
|
||||
{
|
||||
protected:
|
||||
// Given CP[0] to CP[3] floating point values rounded to -INF,
|
||||
// set LB to the smallest of them (treating -0 as smaller to +0).
|
||||
// Given CP[4] to CP[7] floating point values rounded to +INF,
|
||||
// set UB to the largest of them (treating -0 as smaller to +0).
|
||||
static void find_range (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub,
|
||||
const REAL_VALUE_TYPE (&cp)[8])
|
||||
{
|
||||
lb = cp[0];
|
||||
ub = cp[4];
|
||||
for (int i = 1; i < 4; ++i)
|
||||
{
|
||||
if (real_less (&cp[i], &lb)
|
||||
|| (real_iszero (&lb) && real_isnegzero (&cp[i])))
|
||||
lb = cp[i];
|
||||
if (real_less (&ub, &cp[i + 4])
|
||||
|| (real_isnegzero (&ub) && real_iszero (&cp[i + 4])))
|
||||
ub = cp[i + 4];
|
||||
}
|
||||
}
|
||||
};
|
||||
lb = cp[0];
|
||||
ub = cp[4];
|
||||
for (int i = 1; i < 4; ++i)
|
||||
{
|
||||
if (real_less (&cp[i], &lb)
|
||||
|| (real_iszero (&lb) && real_isnegzero (&cp[i])))
|
||||
lb = cp[i];
|
||||
if (real_less (&ub, &cp[i + 4])
|
||||
|| (real_isnegzero (&ub) && real_iszero (&cp[i + 4])))
|
||||
ub = cp[i + 4];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class foperator_mult : public foperator_mult_div_base
|
||||
bool
|
||||
operator_mult::op1_range (frange &r, tree type,
|
||||
const frange &lhs, const frange &op2,
|
||||
relation_trio) const
|
||||
{
|
||||
using range_operator::op1_range;
|
||||
using range_operator::op2_range;
|
||||
public:
|
||||
virtual bool op1_range (frange &r, tree type,
|
||||
const frange &lhs,
|
||||
const frange &op2,
|
||||
relation_trio = TRIO_VARYING) const final override
|
||||
{
|
||||
if (lhs.undefined_p ())
|
||||
return false;
|
||||
range_op_handler rdiv (RDIV_EXPR, type);
|
||||
if (!rdiv)
|
||||
return false;
|
||||
frange wlhs = float_widen_lhs_range (type, lhs);
|
||||
bool ret = rdiv.fold_range (r, type, wlhs, op2);
|
||||
if (ret == false)
|
||||
return false;
|
||||
if (wlhs.known_isnan () || op2.known_isnan () || op2.undefined_p ())
|
||||
return float_binary_op_range_finish (ret, r, type, wlhs);
|
||||
const REAL_VALUE_TYPE &lhs_lb = wlhs.lower_bound ();
|
||||
const REAL_VALUE_TYPE &lhs_ub = wlhs.upper_bound ();
|
||||
const REAL_VALUE_TYPE &op2_lb = op2.lower_bound ();
|
||||
const REAL_VALUE_TYPE &op2_ub = op2.upper_bound ();
|
||||
if ((contains_zero_p (lhs_lb, lhs_ub) && contains_zero_p (op2_lb, op2_ub))
|
||||
|| ((real_isinf (&lhs_lb) || real_isinf (&lhs_ub))
|
||||
&& (real_isinf (&op2_lb) || real_isinf (&op2_ub))))
|
||||
{
|
||||
// If both lhs and op2 could be zeros or both could be infinities,
|
||||
// we don't know anything about op1 except maybe for the sign
|
||||
// and perhaps if it can be NAN or not.
|
||||
REAL_VALUE_TYPE lb, ub;
|
||||
int signbit_known = signbit_known_p (lhs_lb, lhs_ub, op2_lb, op2_ub);
|
||||
zero_to_inf_range (lb, ub, signbit_known);
|
||||
r.set (type, lb, ub);
|
||||
}
|
||||
// Otherwise, if op2 is a singleton INF and lhs doesn't include INF,
|
||||
// or if lhs must be zero and op2 doesn't include zero, it would be
|
||||
// UNDEFINED, while rdiv.fold_range computes a zero or singleton INF
|
||||
// range. Those are supersets of UNDEFINED, so let's keep that way.
|
||||
if (lhs.undefined_p ())
|
||||
return false;
|
||||
range_op_handler rdiv (RDIV_EXPR, type);
|
||||
if (!rdiv)
|
||||
return false;
|
||||
frange wlhs = float_widen_lhs_range (type, lhs);
|
||||
bool ret = rdiv.fold_range (r, type, wlhs, op2);
|
||||
if (ret == false)
|
||||
return false;
|
||||
if (wlhs.known_isnan () || op2.known_isnan () || op2.undefined_p ())
|
||||
return float_binary_op_range_finish (ret, r, type, wlhs);
|
||||
}
|
||||
virtual bool op2_range (frange &r, tree type,
|
||||
const frange &lhs,
|
||||
const frange &op1,
|
||||
relation_trio = TRIO_VARYING) const final override
|
||||
{
|
||||
return op1_range (r, type, lhs, op1);
|
||||
}
|
||||
private:
|
||||
void rv_fold (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub, bool &maybe_nan,
|
||||
tree type,
|
||||
const REAL_VALUE_TYPE &lh_lb,
|
||||
const REAL_VALUE_TYPE &lh_ub,
|
||||
const REAL_VALUE_TYPE &rh_lb,
|
||||
const REAL_VALUE_TYPE &rh_ub,
|
||||
relation_kind kind) const final override
|
||||
{
|
||||
bool is_square
|
||||
= (kind == VREL_EQ
|
||||
&& real_equal (&lh_lb, &rh_lb)
|
||||
&& real_equal (&lh_ub, &rh_ub)
|
||||
&& real_isneg (&lh_lb) == real_isneg (&rh_lb)
|
||||
&& real_isneg (&lh_ub) == real_isneg (&rh_ub));
|
||||
const REAL_VALUE_TYPE &lhs_lb = wlhs.lower_bound ();
|
||||
const REAL_VALUE_TYPE &lhs_ub = wlhs.upper_bound ();
|
||||
const REAL_VALUE_TYPE &op2_lb = op2.lower_bound ();
|
||||
const REAL_VALUE_TYPE &op2_ub = op2.upper_bound ();
|
||||
if ((contains_zero_p (lhs_lb, lhs_ub) && contains_zero_p (op2_lb, op2_ub))
|
||||
|| ((real_isinf (&lhs_lb) || real_isinf (&lhs_ub))
|
||||
&& (real_isinf (&op2_lb) || real_isinf (&op2_ub))))
|
||||
{
|
||||
// If both lhs and op2 could be zeros or both could be infinities,
|
||||
// we don't know anything about op1 except maybe for the sign
|
||||
// and perhaps if it can be NAN or not.
|
||||
REAL_VALUE_TYPE lb, ub;
|
||||
int signbit_known = signbit_known_p (lhs_lb, lhs_ub, op2_lb, op2_ub);
|
||||
zero_to_inf_range (lb, ub, signbit_known);
|
||||
r.set (type, lb, ub);
|
||||
}
|
||||
// Otherwise, if op2 is a singleton INF and lhs doesn't include INF,
|
||||
// or if lhs must be zero and op2 doesn't include zero, it would be
|
||||
// UNDEFINED, while rdiv.fold_range computes a zero or singleton INF
|
||||
// range. Those are supersets of UNDEFINED, so let's keep that way.
|
||||
return float_binary_op_range_finish (ret, r, type, wlhs);
|
||||
}
|
||||
|
||||
maybe_nan = false;
|
||||
// x * x never produces a new NAN and we only multiply the same
|
||||
// values, so the 0 * INF problematic cases never appear there.
|
||||
if (!is_square)
|
||||
{
|
||||
// [+-0, +-0] * [+INF,+INF] (or [-INF,-INF] or swapped is a known NAN.
|
||||
if ((zero_p (lh_lb, lh_ub) && singleton_inf_p (rh_lb, rh_ub))
|
||||
|| (zero_p (rh_lb, rh_ub) && singleton_inf_p (lh_lb, lh_ub)))
|
||||
{
|
||||
real_nan (&lb, "", 0, TYPE_MODE (type));
|
||||
ub = lb;
|
||||
maybe_nan = true;
|
||||
return;
|
||||
}
|
||||
bool
|
||||
operator_mult::op2_range (frange &r, tree type,
|
||||
const frange &lhs, const frange &op1,
|
||||
relation_trio) const
|
||||
{
|
||||
return op1_range (r, type, lhs, op1);
|
||||
}
|
||||
|
||||
// Otherwise, if one range includes zero and the other ends with +-INF,
|
||||
// it is a maybe NAN.
|
||||
if ((contains_zero_p (lh_lb, lh_ub)
|
||||
&& (real_isinf (&rh_lb) || real_isinf (&rh_ub)))
|
||||
|| (contains_zero_p (rh_lb, rh_ub)
|
||||
&& (real_isinf (&lh_lb) || real_isinf (&lh_ub))))
|
||||
{
|
||||
maybe_nan = true;
|
||||
void
|
||||
operator_mult::rv_fold (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub,
|
||||
bool &maybe_nan, tree type,
|
||||
const REAL_VALUE_TYPE &lh_lb,
|
||||
const REAL_VALUE_TYPE &lh_ub,
|
||||
const REAL_VALUE_TYPE &rh_lb,
|
||||
const REAL_VALUE_TYPE &rh_ub,
|
||||
relation_kind kind) const
|
||||
{
|
||||
bool is_square
|
||||
= (kind == VREL_EQ
|
||||
&& real_equal (&lh_lb, &rh_lb)
|
||||
&& real_equal (&lh_ub, &rh_ub)
|
||||
&& real_isneg (&lh_lb) == real_isneg (&rh_lb)
|
||||
&& real_isneg (&lh_ub) == real_isneg (&rh_ub));
|
||||
|
||||
int signbit_known = signbit_known_p (lh_lb, lh_ub, rh_lb, rh_ub);
|
||||
maybe_nan = false;
|
||||
// x * x never produces a new NAN and we only multiply the same
|
||||
// values, so the 0 * INF problematic cases never appear there.
|
||||
if (!is_square)
|
||||
{
|
||||
// [+-0, +-0] * [+INF,+INF] (or [-INF,-INF] or swapped is a known NAN.
|
||||
if ((zero_p (lh_lb, lh_ub) && singleton_inf_p (rh_lb, rh_ub))
|
||||
|| (zero_p (rh_lb, rh_ub) && singleton_inf_p (lh_lb, lh_ub)))
|
||||
{
|
||||
real_nan (&lb, "", 0, TYPE_MODE (type));
|
||||
ub = lb;
|
||||
maybe_nan = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// If one of the ranges that includes INF is singleton
|
||||
// and the other range includes zero, the resulting
|
||||
// range is INF and NAN, because the 0 * INF boundary
|
||||
// case will be NAN, but already nextafter (0, 1) * INF
|
||||
// is INF.
|
||||
if (singleton_inf_p (lh_lb, lh_ub)
|
||||
|| singleton_inf_p (rh_lb, rh_ub))
|
||||
return inf_range (lb, ub, signbit_known);
|
||||
// Otherwise, if one range includes zero and the other ends with +-INF,
|
||||
// it is a maybe NAN.
|
||||
if ((contains_zero_p (lh_lb, lh_ub)
|
||||
&& (real_isinf (&rh_lb) || real_isinf (&rh_ub)))
|
||||
|| (contains_zero_p (rh_lb, rh_ub)
|
||||
&& (real_isinf (&lh_lb) || real_isinf (&lh_ub))))
|
||||
{
|
||||
maybe_nan = true;
|
||||
|
||||
// If one of the multiplicands must be zero, the resulting
|
||||
// range is +-0 and NAN.
|
||||
if (zero_p (lh_lb, lh_ub) || zero_p (rh_lb, rh_ub))
|
||||
return zero_range (lb, ub, signbit_known);
|
||||
int signbit_known = signbit_known_p (lh_lb, lh_ub, rh_lb, rh_ub);
|
||||
|
||||
// Otherwise one of the multiplicands could be
|
||||
// [0.0, nextafter (0.0, 1.0)] and the [DBL_MAX, INF]
|
||||
// or similarly with different signs. 0.0 * DBL_MAX
|
||||
// is still 0.0, nextafter (0.0, 1.0) * INF is still INF,
|
||||
// so if the signs are always the same or always different,
|
||||
// result is [+0.0, +INF] or [-INF, -0.0], otherwise VARYING.
|
||||
return zero_to_inf_range (lb, ub, signbit_known);
|
||||
}
|
||||
}
|
||||
// If one of the ranges that includes INF is singleton
|
||||
// and the other range includes zero, the resulting
|
||||
// range is INF and NAN, because the 0 * INF boundary
|
||||
// case will be NAN, but already nextafter (0, 1) * INF
|
||||
// is INF.
|
||||
if (singleton_inf_p (lh_lb, lh_ub)
|
||||
|| singleton_inf_p (rh_lb, rh_ub))
|
||||
return inf_range (lb, ub, signbit_known);
|
||||
|
||||
REAL_VALUE_TYPE cp[8];
|
||||
// Do a cross-product. At this point none of the multiplications
|
||||
// should produce a NAN.
|
||||
frange_arithmetic (MULT_EXPR, type, cp[0], lh_lb, rh_lb, dconstninf);
|
||||
frange_arithmetic (MULT_EXPR, type, cp[4], lh_lb, rh_lb, dconstinf);
|
||||
if (is_square)
|
||||
{
|
||||
// For x * x we can just do max (lh_lb * lh_lb, lh_ub * lh_ub)
|
||||
// as maximum and -0.0 as minimum if 0.0 is in the range,
|
||||
// otherwise min (lh_lb * lh_lb, lh_ub * lh_ub).
|
||||
// -0.0 rather than 0.0 because VREL_EQ doesn't prove that
|
||||
// x and y are bitwise equal, just that they compare equal.
|
||||
if (contains_zero_p (lh_lb, lh_ub))
|
||||
{
|
||||
if (real_isneg (&lh_lb) == real_isneg (&lh_ub))
|
||||
cp[1] = dconst0;
|
||||
else
|
||||
cp[1] = dconstm0;
|
||||
}
|
||||
else
|
||||
cp[1] = cp[0];
|
||||
cp[2] = cp[0];
|
||||
cp[5] = cp[4];
|
||||
cp[6] = cp[4];
|
||||
}
|
||||
else
|
||||
{
|
||||
frange_arithmetic (MULT_EXPR, type, cp[1], lh_lb, rh_ub, dconstninf);
|
||||
frange_arithmetic (MULT_EXPR, type, cp[5], lh_lb, rh_ub, dconstinf);
|
||||
frange_arithmetic (MULT_EXPR, type, cp[2], lh_ub, rh_lb, dconstninf);
|
||||
frange_arithmetic (MULT_EXPR, type, cp[6], lh_ub, rh_lb, dconstinf);
|
||||
}
|
||||
frange_arithmetic (MULT_EXPR, type, cp[3], lh_ub, rh_ub, dconstninf);
|
||||
frange_arithmetic (MULT_EXPR, type, cp[7], lh_ub, rh_ub, dconstinf);
|
||||
// If one of the multiplicands must be zero, the resulting
|
||||
// range is +-0 and NAN.
|
||||
if (zero_p (lh_lb, lh_ub) || zero_p (rh_lb, rh_ub))
|
||||
return zero_range (lb, ub, signbit_known);
|
||||
|
||||
find_range (lb, ub, cp);
|
||||
}
|
||||
} fop_mult;
|
||||
// Otherwise one of the multiplicands could be
|
||||
// [0.0, nextafter (0.0, 1.0)] and the [DBL_MAX, INF]
|
||||
// or similarly with different signs. 0.0 * DBL_MAX
|
||||
// is still 0.0, nextafter (0.0, 1.0) * INF is still INF,
|
||||
// so if the signs are always the same or always different,
|
||||
// result is [+0.0, +INF] or [-INF, -0.0], otherwise VARYING.
|
||||
return zero_to_inf_range (lb, ub, signbit_known);
|
||||
}
|
||||
}
|
||||
|
||||
REAL_VALUE_TYPE cp[8];
|
||||
// Do a cross-product. At this point none of the multiplications
|
||||
// should produce a NAN.
|
||||
frange_arithmetic (MULT_EXPR, type, cp[0], lh_lb, rh_lb, dconstninf);
|
||||
frange_arithmetic (MULT_EXPR, type, cp[4], lh_lb, rh_lb, dconstinf);
|
||||
if (is_square)
|
||||
{
|
||||
// For x * x we can just do max (lh_lb * lh_lb, lh_ub * lh_ub)
|
||||
// as maximum and -0.0 as minimum if 0.0 is in the range,
|
||||
// otherwise min (lh_lb * lh_lb, lh_ub * lh_ub).
|
||||
// -0.0 rather than 0.0 because VREL_EQ doesn't prove that
|
||||
// x and y are bitwise equal, just that they compare equal.
|
||||
if (contains_zero_p (lh_lb, lh_ub))
|
||||
{
|
||||
if (real_isneg (&lh_lb) == real_isneg (&lh_ub))
|
||||
cp[1] = dconst0;
|
||||
else
|
||||
cp[1] = dconstm0;
|
||||
}
|
||||
else
|
||||
cp[1] = cp[0];
|
||||
cp[2] = cp[0];
|
||||
cp[5] = cp[4];
|
||||
cp[6] = cp[4];
|
||||
}
|
||||
else
|
||||
{
|
||||
frange_arithmetic (MULT_EXPR, type, cp[1], lh_lb, rh_ub, dconstninf);
|
||||
frange_arithmetic (MULT_EXPR, type, cp[5], lh_lb, rh_ub, dconstinf);
|
||||
frange_arithmetic (MULT_EXPR, type, cp[2], lh_ub, rh_lb, dconstninf);
|
||||
frange_arithmetic (MULT_EXPR, type, cp[6], lh_ub, rh_lb, dconstinf);
|
||||
}
|
||||
frange_arithmetic (MULT_EXPR, type, cp[3], lh_ub, rh_ub, dconstninf);
|
||||
frange_arithmetic (MULT_EXPR, type, cp[7], lh_ub, rh_ub, dconstinf);
|
||||
|
||||
find_range (lb, ub, cp);
|
||||
}
|
||||
|
||||
|
||||
class foperator_div : public foperator_mult_div_base
|
||||
class foperator_div : public range_operator
|
||||
{
|
||||
using range_operator::op1_range;
|
||||
using range_operator::op2_range;
|
||||
|
@ -2525,7 +2519,7 @@ public:
|
|||
if (lhs.undefined_p ())
|
||||
return false;
|
||||
frange wlhs = float_widen_lhs_range (type, lhs);
|
||||
bool ret = fop_mult.fold_range (r, type, wlhs, op2);
|
||||
bool ret = range_op_handler (MULT_EXPR).fold_range (r, type, wlhs, op2);
|
||||
if (!ret)
|
||||
return ret;
|
||||
if (wlhs.known_isnan () || op2.known_isnan () || op2.undefined_p ())
|
||||
|
@ -2669,12 +2663,7 @@ private:
|
|||
} fop_div;
|
||||
|
||||
|
||||
float_table::float_table ()
|
||||
{
|
||||
set (MULT_EXPR, fop_mult);
|
||||
}
|
||||
|
||||
// Initialize any pointer operators to the primary table
|
||||
// Initialize any float operators to the primary table
|
||||
|
||||
void
|
||||
range_op_table::initialize_float_ops ()
|
||||
|
|
|
@ -450,4 +450,55 @@ class operator_negate : public range_operator
|
|||
const frange &lhs, const frange &op2,
|
||||
relation_trio rel = TRIO_VARYING) const final override;
|
||||
};
|
||||
|
||||
|
||||
class cross_product_operator : public range_operator
|
||||
{
|
||||
public:
|
||||
virtual bool wi_op_overflows (wide_int &r,
|
||||
tree type,
|
||||
const wide_int &,
|
||||
const wide_int &) const = 0;
|
||||
void wi_cross_product (irange &r, tree type,
|
||||
const wide_int &lh_lb,
|
||||
const wide_int &lh_ub,
|
||||
const wide_int &rh_lb,
|
||||
const wide_int &rh_ub) const;
|
||||
};
|
||||
|
||||
class operator_mult : public cross_product_operator
|
||||
{
|
||||
public:
|
||||
using range_operator::op1_range;
|
||||
using range_operator::op2_range;
|
||||
bool op1_range (irange &r, tree type,
|
||||
const irange &lhs, const irange &op2,
|
||||
relation_trio) const final override;
|
||||
bool op1_range (frange &r, tree type,
|
||||
const frange &lhs, const frange &op2,
|
||||
relation_trio = TRIO_VARYING) const final override;
|
||||
|
||||
bool op2_range (irange &r, tree type,
|
||||
const irange &lhs, const irange &op1,
|
||||
relation_trio) const final override;
|
||||
bool op2_range (frange &r, tree type,
|
||||
const frange &lhs, const frange &op1,
|
||||
relation_trio = TRIO_VARYING) const final override;
|
||||
|
||||
void update_bitmask (irange &r, const irange &lh,
|
||||
const irange &rh) const final override;
|
||||
|
||||
void wi_fold (irange &r, tree type, const wide_int &lh_lb,
|
||||
const wide_int &lh_ub, const wide_int &rh_lb,
|
||||
const wide_int &rh_ub) const final override;
|
||||
bool wi_op_overflows (wide_int &res, tree type, const wide_int &w0,
|
||||
const wide_int &w1) const final override;
|
||||
|
||||
void rv_fold (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub,
|
||||
bool &maybe_nan, tree type,
|
||||
const REAL_VALUE_TYPE &lh_lb, const REAL_VALUE_TYPE &lh_ub,
|
||||
const REAL_VALUE_TYPE &rh_lb, const REAL_VALUE_TYPE &rh_ub,
|
||||
relation_kind kind) const final override;
|
||||
};
|
||||
|
||||
#endif // GCC_RANGE_OP_MIXED_H
|
||||
|
|
|
@ -51,7 +51,6 @@ along with GCC; see the file COPYING3. If not see
|
|||
|
||||
integral_table integral_tree_table;
|
||||
pointer_table pointer_tree_table;
|
||||
float_table float_tree_table;
|
||||
|
||||
// Instantiate a range_op_table for unified operations.
|
||||
class unified_table : public range_op_table
|
||||
|
@ -75,6 +74,7 @@ operator_plus op_plus;
|
|||
operator_abs op_abs;
|
||||
operator_minus op_minus;
|
||||
operator_negate op_negate;
|
||||
operator_mult op_mult;
|
||||
|
||||
// Invoke the initialization routines for each class of range.
|
||||
|
||||
|
@ -101,6 +101,7 @@ unified_table::unified_table ()
|
|||
set (ABS_EXPR, op_abs);
|
||||
set (MINUS_EXPR, op_minus);
|
||||
set (NEGATE_EXPR, op_negate);
|
||||
set (MULT_EXPR, op_mult);
|
||||
}
|
||||
|
||||
// The tables are hidden and accessed via a simple extern function.
|
||||
|
@ -113,7 +114,6 @@ get_op_handler (enum tree_code code, tree type)
|
|||
// Should not be in any other table if it is in the unified table.
|
||||
gcc_checking_assert (!pointer_tree_table[code]);
|
||||
gcc_checking_assert (!integral_tree_table[code]);
|
||||
gcc_checking_assert (!float_tree_table[code]);
|
||||
return unified_tree_table[code];
|
||||
}
|
||||
|
||||
|
@ -121,8 +121,6 @@ get_op_handler (enum tree_code code, tree type)
|
|||
return pointer_tree_table[code];
|
||||
if (INTEGRAL_TYPE_P (type))
|
||||
return integral_tree_table[code];
|
||||
if (frange::supports_p (type))
|
||||
return float_tree_table[code];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -2012,24 +2010,6 @@ operator_max::wi_fold (irange &r, tree type,
|
|||
}
|
||||
|
||||
|
||||
class cross_product_operator : public range_operator
|
||||
{
|
||||
public:
|
||||
// Perform an operation between two wide-ints and place the result
|
||||
// in R. Return true if the operation overflowed.
|
||||
virtual bool wi_op_overflows (wide_int &r,
|
||||
tree type,
|
||||
const wide_int &,
|
||||
const wide_int &) const = 0;
|
||||
|
||||
// Calculate the cross product of two sets of sub-ranges and return it.
|
||||
void wi_cross_product (irange &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.
|
||||
//
|
||||
// Multiplications, divisions and shifts are a bit tricky to handle,
|
||||
|
@ -2085,30 +2065,12 @@ cross_product_operator::wi_cross_product (irange &r, tree type,
|
|||
}
|
||||
|
||||
|
||||
class operator_mult : public cross_product_operator
|
||||
void
|
||||
operator_mult::update_bitmask (irange &r, const irange &lh,
|
||||
const irange &rh) const
|
||||
{
|
||||
using range_operator::op1_range;
|
||||
using range_operator::op2_range;
|
||||
public:
|
||||
virtual void wi_fold (irange &r, tree type,
|
||||
const wide_int &lh_lb,
|
||||
const wide_int &lh_ub,
|
||||
const wide_int &rh_lb,
|
||||
const wide_int &rh_ub) const final override;
|
||||
virtual bool wi_op_overflows (wide_int &res, tree type,
|
||||
const wide_int &w0, const wide_int &w1)
|
||||
const final override;
|
||||
virtual bool op1_range (irange &r, tree type,
|
||||
const irange &lhs,
|
||||
const irange &op2,
|
||||
relation_trio) const final override;
|
||||
virtual bool op2_range (irange &r, tree type,
|
||||
const irange &lhs,
|
||||
const irange &op1,
|
||||
relation_trio) const final override;
|
||||
void update_bitmask (irange &r, const irange &lh, const irange &rh) const
|
||||
{ update_known_bitmask (r, MULT_EXPR, lh, rh); }
|
||||
} op_mult;
|
||||
update_known_bitmask (r, MULT_EXPR, lh, rh);
|
||||
}
|
||||
|
||||
bool
|
||||
operator_mult::op1_range (irange &r, tree type,
|
||||
|
@ -4647,7 +4609,6 @@ integral_table::integral_table ()
|
|||
{
|
||||
set (MIN_EXPR, op_min);
|
||||
set (MAX_EXPR, op_max);
|
||||
set (MULT_EXPR, op_mult);
|
||||
set (BIT_AND_EXPR, op_bitwise_and);
|
||||
set (BIT_IOR_EXPR, op_bitwise_or);
|
||||
set (BIT_XOR_EXPR, op_bitwise_xor);
|
||||
|
|
|
@ -317,16 +317,6 @@ public:
|
|||
};
|
||||
extern pointer_table pointer_tree_table;
|
||||
|
||||
// Instantiate a range_op_table for floating point operations.
|
||||
class float_table : public range_op_table
|
||||
{
|
||||
public:
|
||||
float_table ();
|
||||
};
|
||||
extern float_table float_tree_table;
|
||||
|
||||
|
||||
|
||||
extern range_operator *ptr_op_widen_mult_signed;
|
||||
extern range_operator *ptr_op_widen_mult_unsigned;
|
||||
extern range_operator *ptr_op_widen_plus_signed;
|
||||
|
|
Loading…
Add table
Reference in a new issue