// Default definitions for floating point operators.
bool
-range_operator_float::fold_range (frange &r, tree type,
+range_operator::fold_range (frange &r, tree type,
const frange &op1, const frange &op2,
relation_trio trio) const
{
// MAYBE_NAN is set to TRUE if, in addition to any result in LB or
// UB, the final range has the possibility of a NAN.
void
-range_operator_float::rv_fold (REAL_VALUE_TYPE &lb,
+range_operator::rv_fold (REAL_VALUE_TYPE &lb,
REAL_VALUE_TYPE &ub,
bool &maybe_nan,
tree type ATTRIBUTE_UNUSED,
}
bool
-range_operator_float::fold_range (irange &r ATTRIBUTE_UNUSED,
+range_operator::fold_range (irange &r ATTRIBUTE_UNUSED,
tree type ATTRIBUTE_UNUSED,
const frange &lh ATTRIBUTE_UNUSED,
const irange &rh ATTRIBUTE_UNUSED,
}
bool
-range_operator_float::fold_range (irange &r ATTRIBUTE_UNUSED,
+range_operator::fold_range (irange &r ATTRIBUTE_UNUSED,
tree type ATTRIBUTE_UNUSED,
const frange &lh ATTRIBUTE_UNUSED,
const frange &rh ATTRIBUTE_UNUSED,
}
bool
-range_operator_float::op1_range (frange &r ATTRIBUTE_UNUSED,
+range_operator::op1_range (frange &r ATTRIBUTE_UNUSED,
tree type ATTRIBUTE_UNUSED,
const frange &lhs ATTRIBUTE_UNUSED,
const frange &op2 ATTRIBUTE_UNUSED,
}
bool
-range_operator_float::op1_range (frange &r ATTRIBUTE_UNUSED,
+range_operator::op1_range (frange &r ATTRIBUTE_UNUSED,
tree type ATTRIBUTE_UNUSED,
const irange &lhs ATTRIBUTE_UNUSED,
const frange &op2 ATTRIBUTE_UNUSED,
}
bool
-range_operator_float::op2_range (frange &r ATTRIBUTE_UNUSED,
+range_operator::op2_range (frange &r ATTRIBUTE_UNUSED,
tree type ATTRIBUTE_UNUSED,
const frange &lhs ATTRIBUTE_UNUSED,
const frange &op1 ATTRIBUTE_UNUSED,
}
bool
-range_operator_float::op2_range (frange &r ATTRIBUTE_UNUSED,
+range_operator::op2_range (frange &r ATTRIBUTE_UNUSED,
tree type ATTRIBUTE_UNUSED,
const irange &lhs ATTRIBUTE_UNUSED,
const frange &op1 ATTRIBUTE_UNUSED,
}
relation_kind
-range_operator_float::lhs_op1_relation (const frange &lhs ATTRIBUTE_UNUSED,
+range_operator::lhs_op1_relation (const frange &lhs ATTRIBUTE_UNUSED,
const frange &op1 ATTRIBUTE_UNUSED,
const frange &op2 ATTRIBUTE_UNUSED,
relation_kind) const
}
relation_kind
-range_operator_float::lhs_op1_relation (const irange &lhs ATTRIBUTE_UNUSED,
+range_operator::lhs_op1_relation (const irange &lhs ATTRIBUTE_UNUSED,
const frange &op1 ATTRIBUTE_UNUSED,
const frange &op2 ATTRIBUTE_UNUSED,
relation_kind) const
}
relation_kind
-range_operator_float::lhs_op2_relation (const irange &lhs ATTRIBUTE_UNUSED,
+range_operator::lhs_op2_relation (const irange &lhs ATTRIBUTE_UNUSED,
const frange &op1 ATTRIBUTE_UNUSED,
const frange &op2 ATTRIBUTE_UNUSED,
relation_kind) const
}
relation_kind
-range_operator_float::lhs_op2_relation (const frange &lhs ATTRIBUTE_UNUSED,
+range_operator::lhs_op2_relation (const frange &lhs ATTRIBUTE_UNUSED,
const frange &op1 ATTRIBUTE_UNUSED,
const frange &op2 ATTRIBUTE_UNUSED,
relation_kind) const
}
relation_kind
-range_operator_float::op1_op2_relation (const irange &lhs ATTRIBUTE_UNUSED) const
-{
- return VREL_VARYING;
-}
-
-relation_kind
-range_operator_float::op1_op2_relation (const frange &lhs ATTRIBUTE_UNUSED) const
+range_operator::op1_op2_relation (const frange &lhs ATTRIBUTE_UNUSED) const
{
return VREL_VARYING;
}
}
-class foperator_identity : public range_operator_float
+class foperator_identity : public range_operator
{
- using range_operator_float::fold_range;
- using range_operator_float::op1_range;
+ using range_operator::fold_range;
+ using range_operator::op1_range;
public:
bool fold_range (frange &r, tree type ATTRIBUTE_UNUSED,
const frange &op1, const frange &op2 ATTRIBUTE_UNUSED,
public:
} fop_identity;
-class foperator_equal : public range_operator_float
+class foperator_equal : public range_operator
{
- using range_operator_float::fold_range;
- using range_operator_float::op1_range;
- using range_operator_float::op2_range;
- using range_operator_float::op1_op2_relation;
+ using range_operator::fold_range;
+ using range_operator::op1_range;
+ using range_operator::op2_range;
+ using range_operator::op1_op2_relation;
public:
bool fold_range (irange &r, tree type,
const frange &op1, const frange &op2,
return true;
}
-class foperator_not_equal : public range_operator_float
+class foperator_not_equal : public range_operator
{
- using range_operator_float::fold_range;
- using range_operator_float::op1_range;
- using range_operator_float::op1_op2_relation;
+ using range_operator::fold_range;
+ using range_operator::op1_range;
+ using range_operator::op1_op2_relation;
public:
bool fold_range (irange &r, tree type,
const frange &op1, const frange &op2,
return true;
}
-class foperator_lt : public range_operator_float
+class foperator_lt : public range_operator
{
- using range_operator_float::fold_range;
- using range_operator_float::op1_range;
- using range_operator_float::op2_range;
- using range_operator_float::op1_op2_relation;
+ using range_operator::fold_range;
+ using range_operator::op1_range;
+ using range_operator::op2_range;
+ using range_operator::op1_op2_relation;
public:
bool fold_range (irange &r, tree type,
const frange &op1, const frange &op2,
return true;
}
-class foperator_le : public range_operator_float
+class foperator_le : public range_operator
{
- using range_operator_float::fold_range;
- using range_operator_float::op1_range;
- using range_operator_float::op2_range;
- using range_operator_float::op1_op2_relation;
+ using range_operator::fold_range;
+ using range_operator::op1_range;
+ using range_operator::op2_range;
+ using range_operator::op1_op2_relation;
public:
bool fold_range (irange &r, tree type,
const frange &op1, const frange &op2,
return true;
}
-class foperator_gt : public range_operator_float
+class foperator_gt : public range_operator
{
- using range_operator_float::fold_range;
- using range_operator_float::op1_range;
- using range_operator_float::op2_range;
- using range_operator_float::op1_op2_relation;
+ using range_operator::fold_range;
+ using range_operator::op1_range;
+ using range_operator::op2_range;
+ using range_operator::op1_op2_relation;
public:
bool fold_range (irange &r, tree type,
const frange &op1, const frange &op2,
return true;
}
-class foperator_ge : public range_operator_float
+class foperator_ge : public range_operator
{
- using range_operator_float::fold_range;
- using range_operator_float::op1_range;
- using range_operator_float::op2_range;
- using range_operator_float::op1_op2_relation;
+ using range_operator::fold_range;
+ using range_operator::op1_range;
+ using range_operator::op2_range;
+ using range_operator::op1_op2_relation;
public:
bool fold_range (irange &r, tree type,
const frange &op1, const frange &op2,
// UNORDERED_EXPR comparison.
-class foperator_unordered : public range_operator_float
+class foperator_unordered : public range_operator
{
- using range_operator_float::fold_range;
- using range_operator_float::op1_range;
- using range_operator_float::op2_range;
+ using range_operator::fold_range;
+ using range_operator::op1_range;
+ using range_operator::op2_range;
public:
bool fold_range (irange &r, tree type,
const frange &op1, const frange &op2,
// ORDERED_EXPR comparison.
-class foperator_ordered : public range_operator_float
+class foperator_ordered : public range_operator
{
- using range_operator_float::fold_range;
- using range_operator_float::op1_range;
- using range_operator_float::op2_range;
+ using range_operator::fold_range;
+ using range_operator::op1_range;
+ using range_operator::op2_range;
public:
bool fold_range (irange &r, tree type,
const frange &op1, const frange &op2,
return true;
}
-class foperator_negate : public range_operator_float
+class foperator_negate : public range_operator
{
- using range_operator_float::fold_range;
- using range_operator_float::op1_range;
+ using range_operator::fold_range;
+ using range_operator::op1_range;
public:
bool fold_range (frange &r, tree type,
const frange &op1, const frange &op2,
}
} fop_negate;
-class foperator_abs : public range_operator_float
+class foperator_abs : public range_operator
{
- using range_operator_float::fold_range;
- using range_operator_float::op1_range;
+ using range_operator::fold_range;
+ using range_operator::op1_range;
public:
bool fold_range (frange &r, tree type,
const frange &op1, const frange &,
return true;
}
-class foperator_unordered_lt : public range_operator_float
+class foperator_unordered_lt : public range_operator
{
- using range_operator_float::fold_range;
- using range_operator_float::op1_range;
- using range_operator_float::op2_range;
+ using range_operator::fold_range;
+ using range_operator::op1_range;
+ using range_operator::op2_range;
public:
bool fold_range (irange &r, tree type,
const frange &op1, const frange &op2,
return true;
}
-class foperator_unordered_le : public range_operator_float
+class foperator_unordered_le : public range_operator
{
- using range_operator_float::fold_range;
- using range_operator_float::op1_range;
- using range_operator_float::op2_range;
+ using range_operator::fold_range;
+ using range_operator::op1_range;
+ using range_operator::op2_range;
public:
bool fold_range (irange &r, tree type,
const frange &op1, const frange &op2,
return true;
}
-class foperator_unordered_gt : public range_operator_float
+class foperator_unordered_gt : public range_operator
{
- using range_operator_float::fold_range;
- using range_operator_float::op1_range;
- using range_operator_float::op2_range;
+ using range_operator::fold_range;
+ using range_operator::op1_range;
+ using range_operator::op2_range;
public:
bool fold_range (irange &r, tree type,
const frange &op1, const frange &op2,
return true;
}
-class foperator_unordered_ge : public range_operator_float
+class foperator_unordered_ge : public range_operator
{
- using range_operator_float::fold_range;
- using range_operator_float::op1_range;
- using range_operator_float::op2_range;
+ using range_operator::fold_range;
+ using range_operator::op1_range;
+ using range_operator::op2_range;
public:
bool fold_range (irange &r, tree type,
const frange &op1, const frange &op2,
return true;
}
-class foperator_unordered_equal : public range_operator_float
+class foperator_unordered_equal : public range_operator
{
- using range_operator_float::fold_range;
- using range_operator_float::op1_range;
- using range_operator_float::op2_range;
+ using range_operator::fold_range;
+ using range_operator::op1_range;
+ using range_operator::op2_range;
public:
bool fold_range (irange &r, tree type,
const frange &op1, const frange &op2,
return true;
}
-class foperator_ltgt : public range_operator_float
+class foperator_ltgt : public range_operator
{
- using range_operator_float::fold_range;
- using range_operator_float::op1_range;
- using range_operator_float::op2_range;
+ using range_operator::fold_range;
+ using range_operator::op1_range;
+ using range_operator::op2_range;
public:
bool fold_range (irange &r, tree type,
const frange &op1, const frange &op2,
return ret;
}
-class foperator_plus : public range_operator_float
+class foperator_plus : public range_operator
{
- using range_operator_float::op1_range;
- using range_operator_float::op2_range;
+ using range_operator::op1_range;
+ using range_operator::op2_range;
public:
virtual bool op1_range (frange &r, tree type,
const frange &lhs,
} fop_plus;
-class foperator_minus : public range_operator_float
+class foperator_minus : public range_operator
{
- using range_operator_float::op1_range;
- using range_operator_float::op2_range;
+ using range_operator::op1_range;
+ using range_operator::op2_range;
public:
virtual bool op1_range (frange &r, tree type,
const frange &lhs,
} fop_minus;
-class foperator_mult_div_base : public range_operator_float
+class foperator_mult_div_base : public range_operator
{
protected:
// Given CP[0] to CP[3] floating point values rounded to -INF,
class foperator_mult : public foperator_mult_div_base
{
- using range_operator_float::op1_range;
- using range_operator_float::op2_range;
+ using range_operator::op1_range;
+ using range_operator::op2_range;
public:
virtual bool op1_range (frange &r, tree type,
const frange &lhs,
class foperator_div : public foperator_mult_div_base
{
- using range_operator_float::op1_range;
- using range_operator_float::op2_range;
+ using range_operator::op1_range;
+ using range_operator::op2_range;
public:
virtual bool op1_range (frange &r, tree type,
const frange &lhs,
} fop_div;
// Instantiate a range_op_table for floating point operations.
-static floating_op_table global_floating_table;
+class float_table : public range_op_table
+{
+ public:
+ float_table ();
+} global_floating_table;
// Pointer to the float table so the dispatch code can access it.
-floating_op_table *floating_tree_table = &global_floating_table;
+range_op_table *floating_tree_table = &global_floating_table;
-floating_op_table::floating_op_table ()
+float_table::float_table ()
{
set (SSA_NAME, fop_identity);
set (PAREN_EXPR, fop_identity);
set (RDIV_EXPR, fop_div);
}
-// Return a pointer to the range_operator_float instance, if there is
-// one associated with tree_code CODE.
-
-range_operator_float *
-floating_op_table::operator[] (enum tree_code code)
-{
- return m_range_tree[code];
-}
-
-// Add OP to the handler table for CODE.
-
-void
-floating_op_table::set (enum tree_code code, range_operator_float &op)
-{
- gcc_checking_assert (m_range_tree[code] == NULL);
- m_range_tree[code] = &op;
-}
-
#if CHECKING_P
#include "selftest.h"
// non-zero. This is mostly for logical true false, but can serve other
// purposes.
// ie 0 = op1 - op2 implies op2 has the same range as op1.
+//
+// 4 - All supported range combinations are explicitly specified.
+// Any desired combinations should be implemented for each operator.
+// When new range classes are added, new matching prototypes should be
+// added.
class range_operator
{
const irange &lh,
const irange &rh,
relation_trio = TRIO_VARYING) const;
+ virtual bool fold_range (frange &r, tree type,
+ const frange &lh,
+ const frange &rh,
+ relation_trio = TRIO_VARYING) const;
+ virtual bool fold_range (irange &r, tree type,
+ const frange &lh,
+ const irange &rh,
+ relation_trio = TRIO_VARYING) const;
+ virtual bool fold_range (irange &r, tree type,
+ const frange &lh,
+ const frange &rh,
+ relation_trio = TRIO_VARYING) 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
const irange &lhs,
const irange &op2,
relation_trio = TRIO_VARYING) const;
+ virtual bool op1_range (frange &r, tree type,
+ const frange &lhs,
+ const frange &op2,
+ relation_trio = TRIO_VARYING) const;
+ virtual bool op1_range (frange &r, tree type,
+ const irange &lhs,
+ const frange &op2,
+ relation_trio = TRIO_VARYING) const;
+
+
virtual bool op2_range (irange &r, tree type,
const irange &lhs,
const irange &op1,
relation_trio = TRIO_VARYING) const;
+ virtual bool op2_range (frange &r, tree type,
+ const frange &lhs,
+ const frange &op1,
+ relation_trio = TRIO_VARYING) const;
+ virtual bool op2_range (frange &r, tree type,
+ const irange &lhs,
+ const frange &op1,
+ relation_trio = TRIO_VARYING) const;
// The following routines are used to represent relations between the
// various operations. If the caller knows where the symbolics are,
const irange &op1,
const irange &op2,
relation_kind = VREL_VARYING) const;
+ virtual relation_kind lhs_op1_relation (const frange &lhs,
+ const frange &op1,
+ const frange &op2,
+ relation_kind = VREL_VARYING) const;
+ virtual relation_kind lhs_op1_relation (const irange &lhs,
+ const frange &op1,
+ const frange &op2,
+ relation_kind = VREL_VARYING) const;
+
virtual relation_kind lhs_op2_relation (const irange &lhs,
const irange &op1,
const irange &op2,
relation_kind = VREL_VARYING) const;
+ virtual relation_kind lhs_op2_relation (const frange &lhs,
+ const frange &op1,
+ const frange &op2,
+ relation_kind = VREL_VARYING) const;
+ virtual relation_kind lhs_op2_relation (const irange &lhs,
+ const frange &op1,
+ const frange &op2,
+ relation_kind = VREL_VARYING) const;
+
virtual relation_kind op1_op2_relation (const irange &lhs) const;
+ virtual relation_kind op1_op2_relation (const frange &lhs) const;
protected:
// Perform an integral operation between 2 sub-ranges and return it.
virtual void wi_fold (irange &r, tree type,
unsigned limit) const;
// Apply any bitmasks implied by these ranges.
virtual void update_bitmask (irange &, const irange &, const irange &) const;
-};
-
-// Like range_operator above, but for floating point operators.
-class range_operator_float
-{
-public:
- virtual bool fold_range (frange &r, tree type,
- const frange &lh,
- const frange &rh,
- relation_trio = TRIO_VARYING) const;
+ // Perform an float operation between 2 ranges and return it.
virtual void rv_fold (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub,
bool &maybe_nan,
tree type,
const REAL_VALUE_TYPE &rh_lb,
const REAL_VALUE_TYPE &rh_ub,
relation_kind) const;
- // Unary operations have the range of the LHS as op2.
- virtual bool fold_range (irange &r, tree type,
- const frange &lh,
- const irange &rh,
- relation_trio = TRIO_VARYING) const;
- virtual bool fold_range (irange &r, tree type,
- const frange &lh,
- const frange &rh,
- relation_trio = TRIO_VARYING) const;
- virtual bool op1_range (frange &r, tree type,
- const frange &lhs,
- const frange &op2,
- relation_trio = TRIO_VARYING) const;
- virtual bool op1_range (frange &r, tree type,
- const irange &lhs,
- const frange &op2,
- relation_trio = TRIO_VARYING) const;
- virtual bool op2_range (frange &r, tree type,
- const frange &lhs,
- const frange &op1,
- relation_trio = TRIO_VARYING) const;
- virtual bool op2_range (frange &r, tree type,
- const irange &lhs,
- const frange &op1,
- relation_trio = TRIO_VARYING) const;
-
- virtual relation_kind lhs_op1_relation (const frange &lhs,
- const frange &op1,
- const frange &op2,
- relation_kind = VREL_VARYING) const;
- virtual relation_kind lhs_op1_relation (const irange &lhs,
- const frange &op1,
- const frange &op2,
- relation_kind = VREL_VARYING) const;
- virtual relation_kind lhs_op2_relation (const frange &lhs,
- const frange &op1,
- const frange &op2,
- relation_kind = VREL_VARYING) const;
- virtual relation_kind lhs_op2_relation (const irange &lhs,
- const frange &op1,
- const frange &op2,
- relation_kind = VREL_VARYING) const;
- virtual relation_kind op1_op2_relation (const irange &lhs) const;
- virtual relation_kind op1_op2_relation (const frange &lhs) const;
};
class range_op_handler
void set_op_handler (enum tree_code code, tree type);
bool m_valid;
range_operator *m_int;
- range_operator_float *m_float;
+ range_operator *m_float;
};
extern bool range_cast (vrange &, tree type);
range_operator *m_range_tree[MAX_TREE_CODES];
};
-// Like above, but for floating point operators.
-
-class floating_op_table
-{
-public:
- floating_op_table ();
- range_operator_float *operator[] (enum tree_code code);
-private:
- void set (enum tree_code code, range_operator_float &op);
- range_operator_float *m_range_tree[MAX_TREE_CODES];
-};
// This holds the range op table for floating point operations.
-extern floating_op_table *floating_tree_table;
+extern range_op_table *floating_tree_table;
extern range_operator *ptr_op_widen_mult_signed;
extern range_operator *ptr_op_widen_mult_unsigned;