#include "gimple-walk.h"
#include "tree-cfg.h"
#include "wide-int.h"
+#include "value-relation.h"
#include "range-op.h"
// Return the upper limit for a type.
bool
range_operator::fold_range (irange &r, tree type,
const irange &lh,
- const irange &rh) const
+ const irange &rh,
+ relation_kind rel) const
{
gcc_checking_assert (irange::supports_type_p (type));
if (empty_range_varying (r, type, lh, rh))
{
wi_fold (r, type, lh.lower_bound (0), lh.upper_bound (0),
rh.lower_bound (0), rh.upper_bound (0));
+ op1_op2_relation_effect (r, type, lh, rh, rel);
return true;
}
wi_fold (tmp, type, lh_lb, lh_ub, rh_lb, rh_ub);
r.union_ (tmp);
if (r.varying_p ())
- return true;
+ {
+ op1_op2_relation_effect (r, type, lh, rh, rel);
+ return true;
+ }
}
+ op1_op2_relation_effect (r, type, lh, rh, rel);
return true;
}
range_operator::op1_range (irange &r ATTRIBUTE_UNUSED,
tree type ATTRIBUTE_UNUSED,
const irange &lhs ATTRIBUTE_UNUSED,
- const irange &op2 ATTRIBUTE_UNUSED) const
+ const irange &op2 ATTRIBUTE_UNUSED,
+ relation_kind rel ATTRIBUTE_UNUSED) const
{
return false;
}
range_operator::op2_range (irange &r ATTRIBUTE_UNUSED,
tree type ATTRIBUTE_UNUSED,
const irange &lhs ATTRIBUTE_UNUSED,
- const irange &op1 ATTRIBUTE_UNUSED) const
+ const irange &op1 ATTRIBUTE_UNUSED,
+ relation_kind rel ATTRIBUTE_UNUSED) const
{
return false;
}
+// The default relation routines return VREL_NONE.
+
+enum tree_code
+range_operator::lhs_op1_relation (const irange &lhs ATTRIBUTE_UNUSED,
+ const irange &op1 ATTRIBUTE_UNUSED,
+ const irange &op2 ATTRIBUTE_UNUSED) const
+{
+ return VREL_NONE;
+}
+
+enum tree_code
+range_operator::lhs_op2_relation (const irange &lhs ATTRIBUTE_UNUSED,
+ const irange &op1 ATTRIBUTE_UNUSED,
+ const irange &op2 ATTRIBUTE_UNUSED) const
+{
+ return VREL_NONE;
+}
+
+enum tree_code
+range_operator::op1_op2_relation (const irange &lhs ATTRIBUTE_UNUSED) const
+{
+ return VREL_NONE;
+}
+
+// Default is no relation affects the LHS.
+
+bool
+range_operator::op1_op2_relation_effect (irange &lhs_range ATTRIBUTE_UNUSED,
+ tree type ATTRIBUTE_UNUSED,
+ const irange &op1_range ATTRIBUTE_UNUSED,
+ const irange &op2_range ATTRIBUTE_UNUSED,
+ relation_kind rel ATTRIBUTE_UNUSED) const
+{
+ return false;
+}
// Create and return a range from a pair of wide-ints that are known
// to have overflowed (or underflowed).
return BRS_TRUE;
}
+// For relation opcodes, first try to see if the supplied relation
+// forces a true or false result, and return that.
+// Then check for undefined operands. If none of this applies,
+// return false.
+
+static inline bool
+relop_early_resolve (irange &r, tree type, const irange &op1,
+ const irange &op2, relation_kind rel,
+ relation_kind my_rel)
+{
+ // If known relation is a complete subset of this relation, always true.
+ if (relation_union (rel, my_rel) == my_rel)
+ {
+ r = range_true (type);
+ return true;
+ }
+
+ // If known relation has no subset of this relation, always false.
+ if (relation_intersect (rel, my_rel) == VREL_EMPTY)
+ {
+ r = range_false (type);
+ return true;
+ }
+
+ // If either operand is undefined, return VARYING.
+ if (empty_range_varying (r, type, op1, op2))
+ return true;
+
+ return false;
+}
+
class operator_equal : public range_operator
{
public:
virtual bool fold_range (irange &r, tree type,
const irange &op1,
- const irange &op2) const;
+ const irange &op2,
+ relation_kind rel = VREL_NONE) const;
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
- const irange &val) const;
+ const irange &val,
+ relation_kind rel = VREL_NONE) const;
virtual bool op2_range (irange &r, tree type,
const irange &lhs,
- const irange &val) const;
+ const irange &val,
+ relation_kind rel = VREL_NONE) const;
+ virtual enum tree_code op1_op2_relation (const irange &lhs) const;
} op_equal;
+// Check if the LHS range indicates a relation between OP1 and OP2.
+
+enum tree_code
+operator_equal::op1_op2_relation (const irange &lhs) const
+{
+ if (lhs.undefined_p ())
+ return VREL_EMPTY;
+
+ // FALSE = op1 == op2 indicates NE_EXPR.
+ if (lhs.zero_p ())
+ return NE_EXPR;
+
+ // TRUE = op1 == op2 indicates EQ_EXPR.
+ if (!lhs.contains_p (build_zero_cst (lhs.type ())))
+ return EQ_EXPR;
+ return VREL_NONE;
+}
+
+
bool
operator_equal::fold_range (irange &r, tree type,
const irange &op1,
- const irange &op2) const
+ const irange &op2,
+ relation_kind rel) const
{
- if (empty_range_varying (r, type, op1, op2))
+ if (relop_early_resolve (r, type, op1, op2, rel, EQ_EXPR))
return true;
// We can be sure the values are always equal or not if both ranges
bool
operator_equal::op1_range (irange &r, tree type,
const irange &lhs,
- const irange &op2) const
+ const irange &op2,
+ relation_kind rel ATTRIBUTE_UNUSED) const
{
switch (get_bool_state (r, lhs, type))
{
bool
operator_equal::op2_range (irange &r, tree type,
const irange &lhs,
- const irange &op1) const
+ const irange &op1,
+ relation_kind rel) const
{
- return operator_equal::op1_range (r, type, lhs, op1);
+ return operator_equal::op1_range (r, type, lhs, op1, rel);
}
-
class operator_not_equal : public range_operator
{
public:
virtual bool fold_range (irange &r, tree type,
const irange &op1,
- const irange &op2) const;
+ const irange &op2,
+ relation_kind rel = VREL_NONE) const;
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
- const irange &op2) const;
+ const irange &op2,
+ relation_kind rel = VREL_NONE) const;
virtual bool op2_range (irange &r, tree type,
const irange &lhs,
- const irange &op1) const;
+ const irange &op1,
+ relation_kind rel = VREL_NONE) const;
+ virtual enum tree_code op1_op2_relation (const irange &lhs) const;
} op_not_equal;
+// Check if the LHS range indicates a relation between OP1 and OP2.
+
+enum tree_code
+operator_not_equal::op1_op2_relation (const irange &lhs) const
+{
+ if (lhs.undefined_p ())
+ return VREL_EMPTY;
+
+ // FALSE = op1 != op2 indicates EQ_EXPR.
+ if (lhs.zero_p ())
+ return EQ_EXPR;
+
+ // TRUE = op1 != op2 indicates NE_EXPR.
+ if (!lhs.contains_p (build_zero_cst (lhs.type ())))
+ return NE_EXPR;
+ return VREL_NONE;
+}
+
bool
operator_not_equal::fold_range (irange &r, tree type,
const irange &op1,
- const irange &op2) const
+ const irange &op2,
+ relation_kind rel) const
{
- if (empty_range_varying (r, type, op1, op2))
+ if (relop_early_resolve (r, type, op1, op2, rel, NE_EXPR))
return true;
// We can be sure the values are always equal or not if both ranges
bool
operator_not_equal::op1_range (irange &r, tree type,
const irange &lhs,
- const irange &op2) const
+ const irange &op2,
+ relation_kind rel ATTRIBUTE_UNUSED) const
{
switch (get_bool_state (r, lhs, type))
{
bool
operator_not_equal::op2_range (irange &r, tree type,
const irange &lhs,
- const irange &op1) const
+ const irange &op1,
+ relation_kind rel) const
{
- return operator_not_equal::op1_range (r, type, lhs, op1);
+ return operator_not_equal::op1_range (r, type, lhs, op1, rel);
}
// (X < VAL) produces the range of [MIN, VAL - 1].
public:
virtual bool fold_range (irange &r, tree type,
const irange &op1,
- const irange &op2) const;
+ const irange &op2,
+ relation_kind rel = VREL_NONE) const;
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
- const irange &op2) const;
+ const irange &op2,
+ relation_kind rel = VREL_NONE) const;
virtual bool op2_range (irange &r, tree type,
const irange &lhs,
- const irange &op1) const;
+ const irange &op1,
+ relation_kind rel = VREL_NONE) const;
+ virtual enum tree_code op1_op2_relation (const irange &lhs) const;
} op_lt;
+// Check if the LHS range indicates a relation between OP1 and OP2.
+
+enum tree_code
+operator_lt::op1_op2_relation (const irange &lhs) const
+{
+ if (lhs.undefined_p ())
+ return VREL_EMPTY;
+
+ // FALSE = op1 < op2 indicates GE_EXPR.
+ if (lhs.zero_p ())
+ return GE_EXPR;
+
+ // TRUE = op1 < op2 indicates LT_EXPR.
+ if (!lhs.contains_p (build_zero_cst (lhs.type ())))
+ return LT_EXPR;
+ return VREL_NONE;
+}
+
bool
operator_lt::fold_range (irange &r, tree type,
const irange &op1,
- const irange &op2) const
+ const irange &op2,
+ relation_kind rel) const
{
- if (empty_range_varying (r, type, op1, op2))
+ if (relop_early_resolve (r, type, op1, op2, rel, LT_EXPR))
return true;
signop sign = TYPE_SIGN (op1.type ());
bool
operator_lt::op1_range (irange &r, tree type,
const irange &lhs,
- const irange &op2) const
+ const irange &op2,
+ relation_kind rel ATTRIBUTE_UNUSED) const
{
switch (get_bool_state (r, lhs, type))
{
bool
operator_lt::op2_range (irange &r, tree type,
const irange &lhs,
- const irange &op1) const
+ const irange &op1,
+ relation_kind rel ATTRIBUTE_UNUSED) const
{
switch (get_bool_state (r, lhs, type))
{
public:
virtual bool fold_range (irange &r, tree type,
const irange &op1,
- const irange &op2) const;
+ const irange &op2,
+ relation_kind rel = VREL_NONE) const;
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
- const irange &op2) const;
+ const irange &op2,
+ relation_kind rel = VREL_NONE) const;
virtual bool op2_range (irange &r, tree type,
const irange &lhs,
- const irange &op1) const;
+ const irange &op1,
+ relation_kind rel = VREL_NONE) const;
+ virtual enum tree_code op1_op2_relation (const irange &lhs) const;
} op_le;
+// Check if the LHS range indicates a relation between OP1 and OP2.
+
+enum tree_code
+operator_le::op1_op2_relation (const irange &lhs) const
+{
+ if (lhs.undefined_p ())
+ return VREL_EMPTY;
+
+ // FALSE = op1 <= op2 indicates GT_EXPR.
+ if (lhs.zero_p ())
+ return GT_EXPR;
+
+ // TRUE = op1 <= op2 indicates LE_EXPR.
+ if (!lhs.contains_p (build_zero_cst (lhs.type ())))
+ return LE_EXPR;
+ return VREL_NONE;
+}
+
bool
operator_le::fold_range (irange &r, tree type,
const irange &op1,
- const irange &op2) const
+ const irange &op2,
+ relation_kind rel) const
{
- if (empty_range_varying (r, type, op1, op2))
+ if (relop_early_resolve (r, type, op1, op2, rel, LE_EXPR))
return true;
signop sign = TYPE_SIGN (op1.type ());
bool
operator_le::op1_range (irange &r, tree type,
const irange &lhs,
- const irange &op2) const
+ const irange &op2,
+ relation_kind rel ATTRIBUTE_UNUSED) const
{
switch (get_bool_state (r, lhs, type))
{
bool
operator_le::op2_range (irange &r, tree type,
const irange &lhs,
- const irange &op1) const
+ const irange &op1,
+ relation_kind rel ATTRIBUTE_UNUSED) const
{
switch (get_bool_state (r, lhs, type))
{
public:
virtual bool fold_range (irange &r, tree type,
const irange &op1,
- const irange &op2) const;
+ const irange &op2,
+ relation_kind rel = VREL_NONE) const;
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
- const irange &op2) const;
+ const irange &op2,
+ relation_kind rel = VREL_NONE) const;
virtual bool op2_range (irange &r, tree type,
const irange &lhs,
- const irange &op1) const;
+ const irange &op1,
+ relation_kind rel = VREL_NONE) const;
+ virtual enum tree_code op1_op2_relation (const irange &lhs) const;
} op_gt;
+// Check if the LHS range indicates a relation between OP1 and OP2.
+
+enum tree_code
+operator_gt::op1_op2_relation (const irange &lhs) const
+{
+ if (lhs.undefined_p ())
+ return VREL_EMPTY;
+
+ // FALSE = op1 > op2 indicates LE_EXPR.
+ if (lhs.zero_p ())
+ return LE_EXPR;
+
+ // TRUE = op1 > op2 indicates GT_EXPR.
+ if (!lhs.contains_p (build_zero_cst (lhs.type ())))
+ return GT_EXPR;
+ return VREL_NONE;
+}
+
+
bool
operator_gt::fold_range (irange &r, tree type,
- const irange &op1, const irange &op2) const
+ const irange &op1, const irange &op2,
+ relation_kind rel) const
{
- if (empty_range_varying (r, type, op1, op2))
+ if (relop_early_resolve (r, type, op1, op2, rel, GT_EXPR))
return true;
signop sign = TYPE_SIGN (op1.type ());
bool
operator_gt::op1_range (irange &r, tree type,
- const irange &lhs, const irange &op2) const
+ const irange &lhs, const irange &op2,
+ relation_kind rel ATTRIBUTE_UNUSED) const
{
switch (get_bool_state (r, lhs, type))
{
bool
operator_gt::op2_range (irange &r, tree type,
const irange &lhs,
- const irange &op1) const
+ const irange &op1,
+ relation_kind rel ATTRIBUTE_UNUSED) const
{
switch (get_bool_state (r, lhs, type))
{
public:
virtual bool fold_range (irange &r, tree type,
const irange &op1,
- const irange &op2) const;
+ const irange &op2,
+ relation_kind rel = VREL_NONE) const;
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
- const irange &op2) const;
+ const irange &op2,
+ relation_kind rel = VREL_NONE) const;
virtual bool op2_range (irange &r, tree type,
const irange &lhs,
- const irange &op1) const;
+ const irange &op1,
+ relation_kind rel = VREL_NONE) const;
+ virtual enum tree_code op1_op2_relation (const irange &lhs) const;
} op_ge;
+// Check if the LHS range indicates a relation between OP1 and OP2.
+
+enum tree_code
+operator_ge::op1_op2_relation (const irange &lhs) const
+{
+ if (lhs.undefined_p ())
+ return VREL_EMPTY;
+
+ // FALSE = op1 >= op2 indicates LT_EXPR.
+ if (lhs.zero_p ())
+ return LT_EXPR;
+
+ // TRUE = op1 >= op2 indicates GE_EXPR.
+ if (!lhs.contains_p (build_zero_cst (lhs.type ())))
+ return GE_EXPR;
+ return VREL_NONE;
+}
+
bool
operator_ge::fold_range (irange &r, tree type,
const irange &op1,
- const irange &op2) const
+ const irange &op2,
+ relation_kind rel) const
{
- if (empty_range_varying (r, type, op1, op2))
+ if (relop_early_resolve (r, type, op1, op2, rel, GE_EXPR))
return true;
signop sign = TYPE_SIGN (op1.type ());
bool
operator_ge::op1_range (irange &r, tree type,
const irange &lhs,
- const irange &op2) const
+ const irange &op2,
+ relation_kind rel ATTRIBUTE_UNUSED) const
{
switch (get_bool_state (r, lhs, type))
{
bool
operator_ge::op2_range (irange &r, tree type,
const irange &lhs,
- const irange &op1) const
+ const irange &op1,
+ relation_kind rel ATTRIBUTE_UNUSED) const
{
switch (get_bool_state (r, lhs, type))
{
public:
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
- const irange &op2) const;
+ const irange &op2,
+ relation_kind rel ATTRIBUTE_UNUSED) const;
virtual bool op2_range (irange &r, tree type,
const irange &lhs,
- const irange &op1) const;
+ const irange &op1,
+ relation_kind rel ATTRIBUTE_UNUSED) const;
virtual void wi_fold (irange &r, tree type,
const wide_int &lh_lb,
const wide_int &lh_ub,
bool
operator_plus::op1_range (irange &r, tree type,
const irange &lhs,
- const irange &op2) const
+ const irange &op2,
+ relation_kind rel ATTRIBUTE_UNUSED) const
{
return range_op_handler (MINUS_EXPR, type)->fold_range (r, type, lhs, op2);
}
bool
operator_plus::op2_range (irange &r, tree type,
const irange &lhs,
- const irange &op1) const
+ const irange &op1,
+ relation_kind rel ATTRIBUTE_UNUSED) const
{
return range_op_handler (MINUS_EXPR, type)->fold_range (r, type, lhs, op1);
}
public:
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
- const irange &op2) const;
+ const irange &op2,
+ relation_kind rel ATTRIBUTE_UNUSED) const;
virtual bool op2_range (irange &r, tree type,
const irange &lhs,
- const irange &op1) const;
+ const irange &op1,
+ relation_kind rel ATTRIBUTE_UNUSED) const;
virtual void wi_fold (irange &r, tree type,
const wide_int &lh_lb,
const wide_int &lh_ub,
bool
operator_minus::op1_range (irange &r, tree type,
const irange &lhs,
- const irange &op2) const
+ const irange &op2,
+ relation_kind rel ATTRIBUTE_UNUSED) const
{
return range_op_handler (PLUS_EXPR, type)->fold_range (r, type, lhs, op2);
}
bool
operator_minus::op2_range (irange &r, tree type,
const irange &lhs,
- const irange &op1) const
+ const irange &op1,
+ relation_kind rel ATTRIBUTE_UNUSED) const
{
return fold_range (r, type, op1, lhs);
}
const wide_int &w0, const wide_int &w1) const;
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
- const irange &op2) const;
+ const irange &op2,
+ relation_kind rel ATTRIBUTE_UNUSED) const;
virtual bool op2_range (irange &r, tree type,
const irange &lhs,
- const irange &op1) const;
+ const irange &op1,
+ relation_kind rel ATTRIBUTE_UNUSED) const;
} op_mult;
bool
operator_mult::op1_range (irange &r, tree type,
- const irange &lhs, const irange &op2) const
+ const irange &lhs, const irange &op2,
+ relation_kind rel ATTRIBUTE_UNUSED) const
{
tree offset;
bool
operator_mult::op2_range (irange &r, tree type,
- const irange &lhs, const irange &op1) const
+ const irange &lhs, const irange &op1,
+ relation_kind rel) const
{
- return operator_mult::op1_range (r, type, lhs, op1);
+ return operator_mult::op1_range (r, type, lhs, op1, rel);
}
bool
operator_exact_divide () : operator_div (TRUNC_DIV_EXPR) { }
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
- const irange &op2) const;
+ const irange &op2,
+ relation_kind rel ATTRIBUTE_UNUSED) const;
} op_exact_div;
bool
operator_exact_divide::op1_range (irange &r, tree type,
const irange &lhs,
- const irange &op2) const
+ const irange &op2,
+ relation_kind rel ATTRIBUTE_UNUSED) const
{
tree offset;
// [2, 4] = op1 / [3,3] since its exact divide, no need to worry about
public:
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
- const irange &op2) const;
+ const irange &op2,
+ relation_kind rel = VREL_NONE) const;
virtual bool fold_range (irange &r, tree type,
const irange &op1,
- const irange &op2) const;
+ const irange &op2,
+ relation_kind rel = VREL_NONE) const;
virtual void wi_fold (irange &r, tree type,
const wide_int &lh_lb, const wide_int &lh_ub,
public:
virtual bool fold_range (irange &r, tree type,
const irange &op1,
- const irange &op2) const;
+ const irange &op2,
+ relation_kind rel = VREL_NONE) const;
virtual void wi_fold (irange &r, tree type,
const wide_int &lh_lb,
const wide_int &lh_ub,
const wide_int &w1) const;
virtual bool op1_range (irange &, tree type,
const irange &lhs,
- const irange &op2) const;
+ const irange &op2,
+ relation_kind rel = VREL_NONE) const;
} op_rshift;
bool
operator_lshift::fold_range (irange &r, tree type,
const irange &op1,
- const irange &op2) const
+ const irange &op2,
+ relation_kind rel ATTRIBUTE_UNUSED) const
{
int_range_max shift_range;
if (!get_shift_range (shift_range, type, op2))
operator_lshift::op1_range (irange &r,
tree type,
const irange &lhs,
- const irange &op2) const
+ const irange &op2,
+ relation_kind rel ATTRIBUTE_UNUSED) const
{
tree shift_amount;
if (op2.singleton_p (&shift_amount))
operator_rshift::op1_range (irange &r,
tree type,
const irange &lhs,
- const irange &op2) const
+ const irange &op2,
+ relation_kind rel ATTRIBUTE_UNUSED) const
{
tree shift;
if (op2.singleton_p (&shift))
bool
operator_rshift::fold_range (irange &r, tree type,
const irange &op1,
- const irange &op2) const
+ const irange &op2,
+ relation_kind rel ATTRIBUTE_UNUSED) const
{
int_range_max shift;
if (!get_shift_range (shift, type, op2))
public:
virtual bool fold_range (irange &r, tree type,
const irange &op1,
- const irange &op2) const;
+ const irange &op2,
+ relation_kind rel = VREL_NONE) const;
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
- const irange &op2) const;
+ const irange &op2,
+ relation_kind rel = VREL_NONE) const;
private:
bool truncating_cast_p (const irange &inner, const irange &outer) const;
bool inside_domain_p (const wide_int &min, const wide_int &max,
bool
operator_cast::fold_range (irange &r, tree type ATTRIBUTE_UNUSED,
const irange &inner,
- const irange &outer) const
+ const irange &outer,
+ relation_kind rel ATTRIBUTE_UNUSED) const
{
if (empty_range_varying (r, type, inner, outer))
return true;
bool
operator_cast::op1_range (irange &r, tree type,
const irange &lhs,
- const irange &op2) const
+ const irange &op2,
+ relation_kind rel ATTRIBUTE_UNUSED) const
{
tree lhs_type = lhs.type ();
gcc_checking_assert (types_compatible_p (op2.type(), type));
public:
virtual bool fold_range (irange &r, tree type,
const irange &lh,
- const irange &rh) const;
+ const irange &rh,
+ relation_kind rel = VREL_NONE) const;
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
- const irange &op2) const;
+ const irange &op2,
+ relation_kind rel = VREL_NONE) const;
virtual bool op2_range (irange &r, tree type,
const irange &lhs,
- const irange &op1) const;
+ const irange &op1,
+ relation_kind rel = VREL_NONE) const;
} op_logical_and;
bool
operator_logical_and::fold_range (irange &r, tree type,
const irange &lh,
- const irange &rh) const
+ const irange &rh,
+ relation_kind rel ATTRIBUTE_UNUSED) const
{
if (empty_range_varying (r, type, lh, rh))
return true;
bool
operator_logical_and::op1_range (irange &r, tree type,
const irange &lhs,
- const irange &op2 ATTRIBUTE_UNUSED) const
+ const irange &op2 ATTRIBUTE_UNUSED,
+ relation_kind rel ATTRIBUTE_UNUSED) const
{
switch (get_bool_state (r, lhs, type))
{
bool
operator_logical_and::op2_range (irange &r, tree type,
const irange &lhs,
- const irange &op1) const
+ const irange &op1,
+ relation_kind rel ATTRIBUTE_UNUSED) const
{
return operator_logical_and::op1_range (r, type, lhs, op1);
}
public:
virtual bool fold_range (irange &r, tree type,
const irange &lh,
- const irange &rh) const;
+ const irange &rh,
+ relation_kind rel = VREL_NONE) const;
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
- const irange &op2) const;
+ const irange &op2,
+ relation_kind rel = VREL_NONE) const;
virtual bool op2_range (irange &r, tree type,
const irange &lhs,
- const irange &op1) const;
+ const irange &op1,
+ relation_kind rel = VREL_NONE) const;
virtual void wi_fold (irange &r, tree type,
const wide_int &lh_lb,
const wide_int &lh_ub,
bool
operator_bitwise_and::fold_range (irange &r, tree type,
const irange &lh,
- const irange &rh) const
+ const irange &rh,
+ relation_kind rel ATTRIBUTE_UNUSED) const
{
if (range_operator::fold_range (r, type, lh, rh))
{
bool
operator_bitwise_and::op1_range (irange &r, tree type,
const irange &lhs,
- const irange &op2) const
+ const irange &op2,
+ relation_kind rel ATTRIBUTE_UNUSED) const
{
if (types_compatible_p (type, boolean_type_node))
return op_logical_and.op1_range (r, type, lhs, op2);
bool
operator_bitwise_and::op2_range (irange &r, tree type,
const irange &lhs,
- const irange &op1) const
+ const irange &op1,
+ relation_kind rel ATTRIBUTE_UNUSED) const
{
return operator_bitwise_and::op1_range (r, type, lhs, op1);
}
public:
virtual bool fold_range (irange &r, tree type,
const irange &lh,
- const irange &rh) const;
+ const irange &rh,
+ relation_kind rel = VREL_NONE) const;
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
- const irange &op2) const;
+ const irange &op2,
+ relation_kind rel = VREL_NONE) const;
virtual bool op2_range (irange &r, tree type,
const irange &lhs,
- const irange &op1) const;
+ const irange &op1,
+ relation_kind rel = VREL_NONE) const;
} op_logical_or;
bool
operator_logical_or::fold_range (irange &r, tree type ATTRIBUTE_UNUSED,
const irange &lh,
- const irange &rh) const
+ const irange &rh,
+ relation_kind rel ATTRIBUTE_UNUSED) const
{
if (empty_range_varying (r, type, lh, rh))
return true;
bool
operator_logical_or::op1_range (irange &r, tree type,
const irange &lhs,
- const irange &op2 ATTRIBUTE_UNUSED) const
+ const irange &op2 ATTRIBUTE_UNUSED,
+ relation_kind rel ATTRIBUTE_UNUSED) const
{
switch (get_bool_state (r, lhs, type))
{
bool
operator_logical_or::op2_range (irange &r, tree type,
const irange &lhs,
- const irange &op1) const
+ const irange &op1,
+ relation_kind rel ATTRIBUTE_UNUSED) const
{
return operator_logical_or::op1_range (r, type, lhs, op1);
}
public:
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
- const irange &op2) const;
+ const irange &op2,
+ relation_kind rel = VREL_NONE) const;
virtual bool op2_range (irange &r, tree type,
const irange &lhs,
- const irange &op1) const;
+ const irange &op1,
+ relation_kind rel= VREL_NONE) const;
virtual void wi_fold (irange &r, tree type,
const wide_int &lh_lb,
const wide_int &lh_ub,
bool
operator_bitwise_or::op1_range (irange &r, tree type,
const irange &lhs,
- const irange &op2) const
+ const irange &op2,
+ relation_kind rel ATTRIBUTE_UNUSED) const
{
// If this is really a logical wi_fold, call that.
if (types_compatible_p (type, boolean_type_node))
bool
operator_bitwise_or::op2_range (irange &r, tree type,
const irange &lhs,
- const irange &op1) const
+ const irange &op1,
+ relation_kind rel ATTRIBUTE_UNUSED) const
{
return operator_bitwise_or::op1_range (r, type, lhs, op1);
}
const wide_int &rh_ub) const;
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
- const irange &op2) const;
+ const irange &op2,
+ relation_kind rel = VREL_NONE) const;
virtual bool op2_range (irange &r, tree type,
const irange &lhs,
- const irange &op1) const;
+ const irange &op1,
+ relation_kind rel = VREL_NONE) const;
} op_bitwise_xor;
void
bool
operator_bitwise_xor::op1_range (irange &r, tree type,
const irange &lhs,
- const irange &op2) const
+ const irange &op2,
+ relation_kind rel ATTRIBUTE_UNUSED) const
{
if (lhs.undefined_p () || lhs.varying_p ())
{
bool
operator_bitwise_xor::op2_range (irange &r, tree type,
const irange &lhs,
- const irange &op1) const
+ const irange &op1,
+ relation_kind rel ATTRIBUTE_UNUSED) const
{
return operator_bitwise_xor::op1_range (r, type, lhs, op1);
}
const wide_int &rh_ub) const;
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
- const irange &op2) const;
+ const irange &op2,
+ relation_kind rel ATTRIBUTE_UNUSED) const;
virtual bool op2_range (irange &r, tree type,
const irange &lhs,
- const irange &op1) const;
+ const irange &op1,
+ relation_kind rel ATTRIBUTE_UNUSED) const;
} op_trunc_mod;
void
bool
operator_trunc_mod::op1_range (irange &r, tree type,
const irange &lhs,
- const irange &) const
+ const irange &,
+ relation_kind rel ATTRIBUTE_UNUSED) const
{
// PR 91029.
signop sign = TYPE_SIGN (type);
bool
operator_trunc_mod::op2_range (irange &r, tree type,
const irange &lhs,
- const irange &) const
+ const irange &,
+ relation_kind rel ATTRIBUTE_UNUSED) const
{
// PR 91029.
signop sign = TYPE_SIGN (type);
public:
virtual bool fold_range (irange &r, tree type,
const irange &lh,
- const irange &rh) const;
+ const irange &rh,
+ relation_kind rel = VREL_NONE) const;
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
- const irange &op2) const;
+ const irange &op2,
+ relation_kind rel = VREL_NONE) const;
} op_logical_not;
// Folding a logical NOT, oddly enough, involves doing nothing on the
bool
operator_logical_not::fold_range (irange &r, tree type,
const irange &lh,
- const irange &rh ATTRIBUTE_UNUSED) const
+ const irange &rh ATTRIBUTE_UNUSED,
+ relation_kind rel ATTRIBUTE_UNUSED) const
{
if (empty_range_varying (r, type, lh, rh))
return true;
operator_logical_not::op1_range (irange &r,
tree type,
const irange &lhs,
- const irange &op2) const
+ const irange &op2,
+ relation_kind rel ATTRIBUTE_UNUSED) const
{
// Logical NOT is involutary...do it again.
return fold_range (r, type, lhs, op2);
public:
virtual bool fold_range (irange &r, tree type,
const irange &lh,
- const irange &rh) const;
+ const irange &rh,
+ relation_kind rel = VREL_NONE) const;
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
- const irange &op2) const;
+ const irange &op2,
+ relation_kind rel = VREL_NONE) const;
} op_bitwise_not;
bool
operator_bitwise_not::fold_range (irange &r, tree type,
const irange &lh,
- const irange &rh) const
+ const irange &rh,
+ relation_kind rel ATTRIBUTE_UNUSED) const
{
if (empty_range_varying (r, type, lh, rh))
return true;
bool
operator_bitwise_not::op1_range (irange &r, tree type,
const irange &lhs,
- const irange &op2) const
+ const irange &op2,
+ relation_kind rel ATTRIBUTE_UNUSED) const
{
if (types_compatible_p (type, boolean_type_node))
return op_logical_not.op1_range (r, type, lhs, op2);
public:
virtual bool fold_range (irange &r, tree type,
const irange &op1,
- const irange &op2) const;
+ const irange &op2,
+ relation_kind rel = VREL_NONE) const;
} op_integer_cst;
bool
operator_cst::fold_range (irange &r, tree type ATTRIBUTE_UNUSED,
const irange &lh,
- const irange &rh ATTRIBUTE_UNUSED) const
+ const irange &rh ATTRIBUTE_UNUSED,
+ relation_kind rel ATTRIBUTE_UNUSED) const
{
r = lh;
return true;
public:
virtual bool fold_range (irange &r, tree type,
const irange &op1,
- const irange &op2) const;
+ const irange &op2,
+ relation_kind rel = VREL_NONE) const;
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
- const irange &op2) const;
+ const irange &op2,
+ relation_kind rel = VREL_NONE) const;
} op_identity;
bool
operator_identity::fold_range (irange &r, tree type ATTRIBUTE_UNUSED,
const irange &lh,
- const irange &rh ATTRIBUTE_UNUSED) const
+ const irange &rh ATTRIBUTE_UNUSED,
+ relation_kind rel ATTRIBUTE_UNUSED) const
{
r = lh;
return true;
bool
operator_identity::op1_range (irange &r, tree type ATTRIBUTE_UNUSED,
const irange &lhs,
- const irange &op2 ATTRIBUTE_UNUSED) const
+ const irange &op2 ATTRIBUTE_UNUSED,
+ relation_kind rel ATTRIBUTE_UNUSED) const
{
r = lhs;
return true;
public:
virtual bool fold_range (irange &r, tree type,
const irange &op1,
- const irange &op2) const;
+ const irange &op2,
+ relation_kind rel = VREL_NONE) const;
} op_unknown;
bool
operator_unknown::fold_range (irange &r, tree type,
const irange &lh ATTRIBUTE_UNUSED,
- const irange &rh ATTRIBUTE_UNUSED) const
+ const irange &rh ATTRIBUTE_UNUSED,
+ relation_kind rel ATTRIBUTE_UNUSED) const
{
r.set_varying (type);
return true;
const wide_int &rh_ub) const;
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
- const irange &op2) const;
+ const irange &op2,
+ relation_kind rel ATTRIBUTE_UNUSED) const;
} op_abs;
void
bool
operator_abs::op1_range (irange &r, tree type,
const irange &lhs,
- const irange &op2) const
+ const irange &op2,
+ relation_kind rel ATTRIBUTE_UNUSED) const
{
if (empty_range_varying (r, type, lhs, op2))
return true;
public:
virtual bool fold_range (irange &r, tree type,
const irange &op1,
- const irange &op2) const;
+ const irange &op2,
+ relation_kind rel = VREL_NONE) const;
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
- const irange &op2) const;
+ const irange &op2,
+ relation_kind rel = VREL_NONE) const;
} op_negate;
bool
operator_negate::fold_range (irange &r, tree type,
const irange &lh,
- const irange &rh) const
+ const irange &rh,
+ relation_kind rel ATTRIBUTE_UNUSED) const
{
if (empty_range_varying (r, type, lh, rh))
return true;
bool
operator_negate::op1_range (irange &r, tree type,
const irange &lhs,
- const irange &op2) const
+ const irange &op2,
+ relation_kind rel ATTRIBUTE_UNUSED) const
{
// NEGATE is involutory.
return fold_range (r, type, lhs, op2);
public:
virtual bool fold_range (irange &r, tree type,
const irange &op1,
- const irange &op2) const;
+ const irange &op2,
+ relation_kind rel = VREL_NONE) const;
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
- const irange &op2) const;
+ const irange &op2,
+ relation_kind rel = VREL_NONE) const;
} op_addr;
bool
operator_addr_expr::fold_range (irange &r, tree type,
const irange &lh,
- const irange &rh) const
+ const irange &rh,
+ relation_kind rel ATTRIBUTE_UNUSED) const
{
if (empty_range_varying (r, type, lh, rh))
return true;
bool
operator_addr_expr::op1_range (irange &r, tree type,
const irange &lhs,
- const irange &op2) const
+ const irange &op2,
+ relation_kind rel ATTRIBUTE_UNUSED) const
{
return operator_addr_expr::fold_range (r, type, lhs, op2);
}
public:
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
- const irange &op2) const;
+ const irange &op2,
+ relation_kind rel = VREL_NONE) const;
virtual bool op2_range (irange &r, tree type,
const irange &lhs,
- const irange &op1) const;
+ const irange &op1,
+ relation_kind rel = VREL_NONE) const;
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;
bool
pointer_or_operator::op1_range (irange &r, tree type,
const irange &lhs,
- const irange &op2 ATTRIBUTE_UNUSED) const
+ const irange &op2 ATTRIBUTE_UNUSED,
+ relation_kind rel ATTRIBUTE_UNUSED) const
{
if (lhs.zero_p ())
{
bool
pointer_or_operator::op2_range (irange &r, tree type,
const irange &lhs,
- const irange &op1) const
+ const irange &op1,
+ relation_kind rel ATTRIBUTE_UNUSED) const
{
return pointer_or_operator::op1_range (r, type, lhs, op1);
}