5. (vrange) Temporaries (1)
class Value_Range
{
public:
bool varying_p () const;
bool undefined_p () const;
bool union_ (const vrange &r);
bool intersect (const vrange &r);
<etc>
<etc>
operator vrange &();
private:
vrange *m_vrange; // Pointer to active temporary.
int_range_max m_irange; // Integer temporary.
frange m_frange; // Floating point temporary.
unsupported_range m_unsupported; // Unsupported temporary.
};
value_range temp; // old world
Value_Range temp (some_type); // new world
6. (vrange) Global range storage (1)
• Can store full resolution ranges.
• Never loses information (*).
• As efficient as we want to make it
• Uses same set_range_info() API.
7. Floating point ranges (frange) (2)
“I told you it would be complicated, and hard and take
forever, but no… you insisted we needed float support.”
Andrew MacLeod
8. Floating point ranges (frange) (2)
// Symbolic relational operators.
if (x > y) {
if (x == y)
link_error ();
}
9. Floating point ranges (frange) (2)
// Propagation of NANs and INFs.
if (x > y) {
// x is not a NAN
// y is not a NAN
// x is not -INF
// y is not +INF
}
10. Floating point ranges (frange) (2)
// Intervals for ranges.
if (x >= 5.0) {
// x is not a NAN
// x is [5.0, +INF]
} else {
// x is [-INF, 5.0] U [NAN]
}
11. Floating point ranges (frange) (2)
// Signed zeros.
if (x == 0.0) {
if (__builtin_sign (x))
y = x; // y = -0.0
else
z = x; // z = +0.0
}
14. (enhancing) Template for new operators (3)
class foperator_plus : public range_operator_float
{
public:
// r = op1 .op. op2
bool fold_range (frange &r, tree type,
const frange &op1,
const frange &op2,
relation_kind rel) const final override
{
r.set_varying (type);
return true;
}
} fop_plus;
floating_op_table::floating_op_table ()
{
set (EQ_EXPR, fop_equal);
set (NE_EXPR, fop_not_equal);
// etc
// etc
set (PLUS_EXPR, fop_plus);
}
15. (enhancing) PLUS_EXPR implementation (3)
bool
foperator_plus::fold_range (frange &r, tree type, const frange &op1,
const frange &op2, relation_kind) const
{
// Propagate known NANs.
if (op1.known_isnan () || op2.known_isnan ()) {
r.set_nan (type);
return true;
}
// [a, b] + [c, d] = [a+c, b+d]
REAL_VALUE_TYPE min, max;
frange_arithmetic (PLUS_EXPR, type, min, op1.lower_bound (), op2.lower_bound (), ninf);
frange_arithmetic (PLUS_EXPR, type, max, op1.upper_bound (), op2.upper_bound (), inf);
// Adjust for possible NANs.
bool maybe_nan = drop_nan (min, ninf);
maybe_nan |= drop_nan (max, inf);
r.set (type, min, max);
// Clear NAN bit if neither the result nor the operands are NAN.
if (!HONOR_NANS (type)
|| (!maybe_nan && !op1.maybe_nan () && !op2.maybe_nan ()))
r.clear_nan ();
return true;
}
16. Future ranger work (4)
• Frange improvements (GCC 13/14 ops, subranges, builtins, libs).
• Final VRP replacement with ranger (GCC13/14).
• irange conversion to wide-ints (GCC13/14).
• prange: pointer ranges (GCC13/14).
• Fast -O0 ranger (GCC14).
• One threader to rule them all (GCC14).
• DOM replacement with FRE (GCC14).