fur_source::query_relation (tree op1 ATTRIBUTE_UNUSED,
tree op2 ATTRIBUTE_UNUSED)
{
- return VREL_NONE;
+ return VREL_VARYING;
}
// Default registers nothing.
src.gori ()->register_dependency (lhs, op1);
relation_kind rel;
rel = handler->lhs_op1_relation (r, range1, range1);
- if (rel != VREL_NONE)
+ if (rel != VREL_VARYING)
src.register_relation (s, rel, lhs, op1);
}
}
else if (src.get_operand (range2, op2))
{
relation_kind rel = src.query_relation (op1, op2);
- if (dump_file && (dump_flags & TDF_DETAILS) && rel != VREL_NONE)
+ if (dump_file && (dump_flags & TDF_DETAILS) && rel != VREL_VARYING)
{
fprintf (dump_file, " folding with relation ");
print_generic_expr (dump_file, op1, TDF_SLIM);
if (gimple_range_ssa_p (op1))
{
rel = handler->lhs_op1_relation (r, range1, range2, rel);
- if (rel != VREL_NONE)
+ if (rel != VREL_VARYING)
src.register_relation (s, rel, lhs, op1);
}
if (gimple_range_ssa_p (op2))
{
rel= handler->lhs_op2_relation (r, range1, range2, rel);
- if (rel != VREL_NONE)
+ if (rel != VREL_VARYING)
src.register_relation (s, rel, lhs, op2);
}
}
// Likewise, if the incoming PHI argument is equivalent to this
// PHI definition, it provides no new info. Accumulate these ranges
// in case all arguments are equivalences.
- if (src.query ()->query_relation (e, arg, phi_def, false) == EQ_EXPR)
+ if (src.query ()->query_relation (e, arg, phi_def, false) == VREL_EQ)
equiv_range.union_(arg_range);
else
r.union_ (arg_range);
{
// Symbolic arguments are equivalences.
if (gimple_range_ssa_p (single_arg))
- src.register_relation (phi, EQ_EXPR, phi_def, single_arg);
+ src.register_relation (phi, VREL_EQ, phi_def, single_arg);
else if (src.get_operand (arg_range, single_arg)
&& arg_range.singleton_p ())
{
relation_kind relation1 = handler1->op1_op2_relation (bool_one);
relation_kind relation2 = handler2->op1_op2_relation (bool_one);
- if (relation1 == VREL_NONE || relation2 == VREL_NONE)
+ if (relation1 == VREL_VARYING || relation2 == VREL_VARYING)
return;
if (reverse_op2)
relation2 = relation_negate (relation2);
// x && y is false if the relation intersection of the true cases is NULL.
- if (is_and && relation_intersect (relation1, relation2) == VREL_EMPTY)
+ if (is_and && relation_intersect (relation1, relation2) == VREL_UNDEFINED)
lhs_range = int_range<2> (boolean_false_node, boolean_false_node);
// x || y is true if the union of the true cases is NO-RELATION..
// ie, one or the other being true covers the full range of possibilties.
- else if (!is_and && relation_union (relation1, relation2) == VREL_NONE)
+ else if (!is_and && relation_union (relation1, relation2) == VREL_VARYING)
lhs_range = bool_one;
else
return;
if (e0)
{
relation_kind relation = handler->op1_op2_relation (e0_range);
- if (relation != VREL_NONE)
+ if (relation != VREL_VARYING)
register_relation (e0, relation, ssa1, ssa2);
}
if (e1)
{
relation_kind relation = handler->op1_op2_relation (e1_range);
- if (relation != VREL_NONE)
+ if (relation != VREL_VARYING)
register_relation (e1, relation, ssa1, ssa2);
}
}
&& r.singleton_p ())
{
relation_kind relation = handler->op1_op2_relation (r);
- if (relation != VREL_NONE)
+ if (relation != VREL_VARYING)
register_relation (e0, relation, ssa1, ssa2);
}
if (e1 && gori ()->outgoing_edge_range_p (r, e1, name, *m_query)
&& r.singleton_p ())
{
relation_kind relation = handler->op1_op2_relation (r);
- if (relation != VREL_NONE)
+ if (relation != VREL_VARYING)
register_relation (e1, relation, ssa1, ssa2);
}
}
jt_fur_source::query_relation (tree op1, tree op2)
{
if (!m_oracle)
- return VREL_NONE;
+ return VREL_VARYING;
if (TREE_CODE (op1) != SSA_NAME || TREE_CODE (op2) != SSA_NAME)
- return VREL_NONE;
+ return VREL_VARYING;
return m_oracle->query_relation (m_entry, op1, op2);
}
fprintf (dump_file, "maybe_register_phi_relation in bb%d:", bb->index);
get_path_oracle ()->killing_def (result);
- m_oracle->register_relation (entry_bb (), EQ_EXPR, arg, result);
+ m_oracle->register_relation (entry_bb (), VREL_EQ, arg, result);
}
// Compute relations for each PHI in BB. For example:
return false;
}
-// The default relation routines return VREL_NONE.
+// The default relation routines return VREL_VARYING.
-enum tree_code
+relation_kind
range_operator::lhs_op1_relation (const irange &lhs ATTRIBUTE_UNUSED,
const irange &op1 ATTRIBUTE_UNUSED,
const irange &op2 ATTRIBUTE_UNUSED,
relation_kind rel ATTRIBUTE_UNUSED) const
{
- return VREL_NONE;
+ return VREL_VARYING;
}
-enum tree_code
+relation_kind
range_operator::lhs_op2_relation (const irange &lhs ATTRIBUTE_UNUSED,
const irange &op1 ATTRIBUTE_UNUSED,
const irange &op2 ATTRIBUTE_UNUSED,
relation_kind rel ATTRIBUTE_UNUSED) const
{
- return VREL_NONE;
+ return VREL_VARYING;
}
-enum tree_code
+relation_kind
range_operator::op1_op2_relation (const irange &lhs ATTRIBUTE_UNUSED) const
{
- return VREL_NONE;
+ return VREL_VARYING;
}
// Default is no relation affects the LHS.
virtual bool fold_range (irange &r, tree type,
const irange &op1,
const irange &op2,
- relation_kind rel = VREL_NONE) const;
+ relation_kind rel = VREL_VARYING) const;
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
const irange &val,
- relation_kind rel = VREL_NONE) const;
+ relation_kind rel = VREL_VARYING) const;
virtual bool op2_range (irange &r, tree type,
const irange &lhs,
const irange &val,
- relation_kind rel = VREL_NONE) const;
- virtual enum tree_code op1_op2_relation (const irange &lhs) const;
+ relation_kind rel = VREL_VARYING) const;
+ virtual relation_kind op1_op2_relation (const irange &lhs) const;
} op_equal;
// Check if the LHS range indicates a relation between OP1 and OP2.
-enum tree_code
+relation_kind
equal_op1_op2_relation (const irange &lhs)
{
if (lhs.undefined_p ())
- return VREL_EMPTY;
+ return VREL_UNDEFINED;
// FALSE = op1 == op2 indicates NE_EXPR.
if (lhs.zero_p ())
- return NE_EXPR;
+ return VREL_NE;
// TRUE = op1 == op2 indicates EQ_EXPR.
if (!lhs.contains_p (build_zero_cst (lhs.type ())))
- return EQ_EXPR;
- return VREL_NONE;
+ return VREL_EQ;
+ return VREL_VARYING;
}
-enum tree_code
+relation_kind
operator_equal::op1_op2_relation (const irange &lhs) const
{
return equal_op1_op2_relation (lhs);
const irange &op2,
relation_kind rel) const
{
- if (relop_early_resolve (r, type, op1, op2, rel, EQ_EXPR))
+ if (relop_early_resolve (r, type, op1, op2, rel, VREL_EQ))
return true;
// We can be sure the values are always equal or not if both ranges
virtual bool fold_range (irange &r, tree type,
const irange &op1,
const irange &op2,
- relation_kind rel = VREL_NONE) const;
+ relation_kind rel = VREL_VARYING) const;
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
const irange &op2,
- relation_kind rel = VREL_NONE) const;
+ relation_kind rel = VREL_VARYING) const;
virtual bool op2_range (irange &r, tree type,
const irange &lhs,
const irange &op1,
- relation_kind rel = VREL_NONE) const;
- virtual enum tree_code op1_op2_relation (const irange &lhs) const;
+ relation_kind rel = VREL_VARYING) const;
+ virtual relation_kind 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
+relation_kind
not_equal_op1_op2_relation (const irange &lhs)
{
if (lhs.undefined_p ())
- return VREL_EMPTY;
+ return VREL_UNDEFINED;
// FALSE = op1 != op2 indicates EQ_EXPR.
if (lhs.zero_p ())
- return EQ_EXPR;
+ return VREL_EQ;
// TRUE = op1 != op2 indicates NE_EXPR.
if (!lhs.contains_p (build_zero_cst (lhs.type ())))
- return NE_EXPR;
- return VREL_NONE;
+ return VREL_NE;
+ return VREL_VARYING;
}
-enum tree_code
+relation_kind
operator_not_equal::op1_op2_relation (const irange &lhs) const
{
return not_equal_op1_op2_relation (lhs);
const irange &op2,
relation_kind rel) const
{
- if (relop_early_resolve (r, type, op1, op2, rel, NE_EXPR))
+ if (relop_early_resolve (r, type, op1, op2, rel, VREL_NE))
return true;
// We can be sure the values are always equal or not if both ranges
virtual bool fold_range (irange &r, tree type,
const irange &op1,
const irange &op2,
- relation_kind rel = VREL_NONE) const;
+ relation_kind rel = VREL_VARYING) const;
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
const irange &op2,
- relation_kind rel = VREL_NONE) const;
+ relation_kind rel = VREL_VARYING) const;
virtual bool op2_range (irange &r, tree type,
const irange &lhs,
const irange &op1,
- relation_kind rel = VREL_NONE) const;
- virtual enum tree_code op1_op2_relation (const irange &lhs) const;
+ relation_kind rel = VREL_VARYING) const;
+ virtual relation_kind op1_op2_relation (const irange &lhs) const;
} op_lt;
// Check if the LHS range indicates a relation between OP1 and OP2.
-enum tree_code
+relation_kind
lt_op1_op2_relation (const irange &lhs)
{
if (lhs.undefined_p ())
- return VREL_EMPTY;
+ return VREL_UNDEFINED;
// FALSE = op1 < op2 indicates GE_EXPR.
if (lhs.zero_p ())
- return GE_EXPR;
+ return VREL_GE;
// TRUE = op1 < op2 indicates LT_EXPR.
if (!lhs.contains_p (build_zero_cst (lhs.type ())))
- return LT_EXPR;
- return VREL_NONE;
+ return VREL_LT;
+ return VREL_VARYING;
}
-enum tree_code
+relation_kind
operator_lt::op1_op2_relation (const irange &lhs) const
{
return lt_op1_op2_relation (lhs);
const irange &op2,
relation_kind rel) const
{
- if (relop_early_resolve (r, type, op1, op2, rel, LT_EXPR))
+ if (relop_early_resolve (r, type, op1, op2, rel, VREL_LT))
return true;
signop sign = TYPE_SIGN (op1.type ());
virtual bool fold_range (irange &r, tree type,
const irange &op1,
const irange &op2,
- relation_kind rel = VREL_NONE) const;
+ relation_kind rel = VREL_VARYING) const;
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
const irange &op2,
- relation_kind rel = VREL_NONE) const;
+ relation_kind rel = VREL_VARYING) const;
virtual bool op2_range (irange &r, tree type,
const irange &lhs,
const irange &op1,
- relation_kind rel = VREL_NONE) const;
- virtual enum tree_code op1_op2_relation (const irange &lhs) const;
+ relation_kind rel = VREL_VARYING) const;
+ virtual relation_kind op1_op2_relation (const irange &lhs) const;
} op_le;
// Check if the LHS range indicates a relation between OP1 and OP2.
-enum tree_code
+relation_kind
le_op1_op2_relation (const irange &lhs)
{
if (lhs.undefined_p ())
- return VREL_EMPTY;
+ return VREL_UNDEFINED;
// FALSE = op1 <= op2 indicates GT_EXPR.
if (lhs.zero_p ())
- return GT_EXPR;
+ return VREL_GT;
// TRUE = op1 <= op2 indicates LE_EXPR.
if (!lhs.contains_p (build_zero_cst (lhs.type ())))
- return LE_EXPR;
- return VREL_NONE;
+ return VREL_LE;
+ return VREL_VARYING;
}
-enum tree_code
+relation_kind
operator_le::op1_op2_relation (const irange &lhs) const
{
return le_op1_op2_relation (lhs);
const irange &op2,
relation_kind rel) const
{
- if (relop_early_resolve (r, type, op1, op2, rel, LE_EXPR))
+ if (relop_early_resolve (r, type, op1, op2, rel, VREL_LE))
return true;
signop sign = TYPE_SIGN (op1.type ());
virtual bool fold_range (irange &r, tree type,
const irange &op1,
const irange &op2,
- relation_kind rel = VREL_NONE) const;
+ relation_kind rel = VREL_VARYING) const;
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
const irange &op2,
- relation_kind rel = VREL_NONE) const;
+ relation_kind rel = VREL_VARYING) const;
virtual bool op2_range (irange &r, tree type,
const irange &lhs,
const irange &op1,
- relation_kind rel = VREL_NONE) const;
- virtual enum tree_code op1_op2_relation (const irange &lhs) const;
+ relation_kind rel = VREL_VARYING) const;
+ virtual relation_kind op1_op2_relation (const irange &lhs) const;
} op_gt;
// Check if the LHS range indicates a relation between OP1 and OP2.
-enum tree_code
+relation_kind
gt_op1_op2_relation (const irange &lhs)
{
if (lhs.undefined_p ())
- return VREL_EMPTY;
+ return VREL_UNDEFINED;
// FALSE = op1 > op2 indicates LE_EXPR.
if (lhs.zero_p ())
- return LE_EXPR;
+ return VREL_LE;
// TRUE = op1 > op2 indicates GT_EXPR.
if (!lhs.contains_p (build_zero_cst (lhs.type ())))
- return GT_EXPR;
- return VREL_NONE;
+ return VREL_GT;
+ return VREL_VARYING;
}
-enum tree_code
+relation_kind
operator_gt::op1_op2_relation (const irange &lhs) const
{
return gt_op1_op2_relation (lhs);
const irange &op1, const irange &op2,
relation_kind rel) const
{
- if (relop_early_resolve (r, type, op1, op2, rel, GT_EXPR))
+ if (relop_early_resolve (r, type, op1, op2, rel, VREL_GT))
return true;
signop sign = TYPE_SIGN (op1.type ());
virtual bool fold_range (irange &r, tree type,
const irange &op1,
const irange &op2,
- relation_kind rel = VREL_NONE) const;
+ relation_kind rel = VREL_VARYING) const;
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
const irange &op2,
- relation_kind rel = VREL_NONE) const;
+ relation_kind rel = VREL_VARYING) const;
virtual bool op2_range (irange &r, tree type,
const irange &lhs,
const irange &op1,
- relation_kind rel = VREL_NONE) const;
- virtual enum tree_code op1_op2_relation (const irange &lhs) const;
+ relation_kind rel = VREL_VARYING) const;
+ virtual relation_kind op1_op2_relation (const irange &lhs) const;
} op_ge;
// Check if the LHS range indicates a relation between OP1 and OP2.
-enum tree_code
+relation_kind
ge_op1_op2_relation (const irange &lhs)
{
if (lhs.undefined_p ())
- return VREL_EMPTY;
+ return VREL_UNDEFINED;
// FALSE = op1 >= op2 indicates LT_EXPR.
if (lhs.zero_p ())
- return LT_EXPR;
+ return VREL_LT;
// TRUE = op1 >= op2 indicates GE_EXPR.
if (!lhs.contains_p (build_zero_cst (lhs.type ())))
- return GE_EXPR;
- return VREL_NONE;
+ return VREL_GE;
+ return VREL_VARYING;
}
-enum tree_code
+relation_kind
operator_ge::op1_op2_relation (const irange &lhs) const
{
return ge_op1_op2_relation (lhs);
const irange &op2,
relation_kind rel) const
{
- if (relop_early_resolve (r, type, op1, op2, rel, GE_EXPR))
+ if (relop_early_resolve (r, type, op1, op2, rel, VREL_GE))
return true;
signop sign = TYPE_SIGN (op1.type ());
const wide_int &lh_ub,
const wide_int &rh_lb,
const wide_int &rh_ub) const;
- virtual enum tree_code lhs_op1_relation (const irange &lhs, const irange &op1,
- const irange &op2,
- relation_kind rel) const;
- virtual enum tree_code lhs_op2_relation (const irange &lhs, const irange &op1,
- const irange &op2,
- relation_kind rel) const;
+ virtual relation_kind lhs_op1_relation (const irange &lhs, const irange &op1,
+ const irange &op2,
+ relation_kind rel) const;
+ virtual relation_kind lhs_op2_relation (const irange &lhs, const irange &op1,
+ const irange &op2,
+ relation_kind rel) const;
} op_plus;
// Check to see if the range of OP2 indicates anything about the relation
// between LHS and OP1.
-enum tree_code
+relation_kind
operator_plus::lhs_op1_relation (const irange &lhs,
const irange &op1,
const irange &op2,
relation_kind) const
{
if (lhs.undefined_p () || op1.undefined_p () || op2.undefined_p ())
- return VREL_NONE;
+ return VREL_VARYING;
tree type = lhs.type ();
unsigned prec = TYPE_PRECISION (type);
// LHS = OP1 + 0 indicates LHS == OP1.
if (op2.zero_p ())
- return EQ_EXPR;
+ return VREL_EQ;
if (TYPE_OVERFLOW_WRAPS (type))
{
{
// Positive op2 means lhs > op1.
if (wi::gt_p (op2.lower_bound (), wi::zero (prec), sign))
- return GT_EXPR;
+ return VREL_GT;
if (wi::ge_p (op2.lower_bound (), wi::zero (prec), sign))
- return GE_EXPR;
+ return VREL_GE;
// Negative op2 means lhs < op1.
if (wi::lt_p (op2.upper_bound (), wi::zero (prec), sign))
- return LT_EXPR;
+ return VREL_LT;
if (wi::le_p (op2.upper_bound (), wi::zero (prec), sign))
- return LE_EXPR;
+ return VREL_LE;
}
// Always wrapping additions.
else if (ovf1 && ovf1 == ovf2)
{
// Positive op2 means lhs < op1.
if (wi::gt_p (op2.lower_bound (), wi::zero (prec), sign))
- return LT_EXPR;
+ return VREL_LT;
if (wi::ge_p (op2.lower_bound (), wi::zero (prec), sign))
- return LE_EXPR;
+ return VREL_LE;
// Negative op2 means lhs > op1.
if (wi::lt_p (op2.upper_bound (), wi::zero (prec), sign))
- return GT_EXPR;
+ return VREL_GT;
if (wi::le_p (op2.upper_bound (), wi::zero (prec), sign))
- return GE_EXPR;
+ return VREL_GE;
}
// If op2 does not contain 0, then LHS and OP1 can never be equal.
if (!range_includes_zero_p (&op2))
- return NE_EXPR;
+ return VREL_NE;
- return VREL_NONE;
+ return VREL_VARYING;
}
// PLUS is symmetrical, so we can simply call lhs_op1_relation with reversed
// operands.
-enum tree_code
+relation_kind
operator_plus::lhs_op2_relation (const irange &lhs, const irange &op1,
const irange &op2, relation_kind rel) const
{
const wide_int &lh_ub,
const wide_int &rh_lb,
const wide_int &rh_ub) const;
- virtual enum tree_code lhs_op1_relation (const irange &lhs,
+ virtual relation_kind lhs_op1_relation (const irange &lhs,
const irange &op1,
const irange &op2,
relation_kind rel) const;
// Return the relation between LHS and OP1 based on the relation between
// OP1 and OP2.
-enum tree_code
+relation_kind
operator_minus::lhs_op1_relation (const irange &lhs, const irange &,
const irange &, relation_kind rel) const
{
if (TYPE_SIGN (lhs.type ()) == UNSIGNED)
switch (rel)
{
- case GT_EXPR:
- return LT_EXPR;
- case GE_EXPR:
- return LE_EXPR;
+ case VREL_GT:
+ return VREL_LT;
+ case VREL_GE:
+ return VREL_LE;
default:
break;
}
- return VREL_NONE;
+ return VREL_VARYING;
}
// Check to see if the relation REL between OP1 and OP2 has any effect on the
const irange &op2_range ATTRIBUTE_UNUSED,
relation_kind rel)
{
- if (rel == VREL_NONE)
+ if (rel == VREL_VARYING)
return false;
int_range<2> rel_range;
signop sgn = TYPE_SIGN (type);
// == and != produce [0,0] and ~[0,0] regardless of wrapping.
- if (rel == EQ_EXPR)
+ if (rel == VREL_EQ)
rel_range = int_range<2> (type, wi::zero (prec), wi::zero (prec));
- else if (rel == NE_EXPR)
+ else if (rel == VREL_NE)
rel_range = int_range<2> (type, wi::zero (prec), wi::zero (prec),
VR_ANTI_RANGE);
else if (TYPE_OVERFLOW_WRAPS (type))
{
// For wrapping signed values and unsigned, if op1 > op2 or
// op1 < op2, then op1 - op2 can be restricted to ~[0, 0].
- case GT_EXPR:
- case LT_EXPR:
+ case VREL_GT:
+ case VREL_LT:
rel_range = int_range<2> (type, wi::zero (prec), wi::zero (prec),
VR_ANTI_RANGE);
break;
switch (rel)
{
// op1 > op2, op1 - op2 can be restricted to [1, +INF]
- case GT_EXPR:
+ case VREL_GT:
rel_range = int_range<2> (type, wi::one (prec),
wi::max_value (prec, sgn));
break;
// op1 >= op2, op1 - op2 can be restricted to [0, +INF]
- case GE_EXPR:
+ case VREL_GE:
rel_range = int_range<2> (type, wi::zero (prec),
wi::max_value (prec, sgn));
break;
// op1 < op2, op1 - op2 can be restricted to [-INF, -1]
- case LT_EXPR:
+ case VREL_LT:
rel_range = int_range<2> (type, wi::min_value (prec, sgn),
wi::minus_one (prec));
break;
// op1 <= op2, op1 - op2 can be restricted to [-INF, 0]
- case LE_EXPR:
+ case VREL_LE:
rel_range = int_range<2> (type, wi::min_value (prec, sgn),
wi::zero (prec));
break;
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
const irange &op2,
- relation_kind rel = VREL_NONE) const;
+ relation_kind rel = VREL_VARYING) const;
virtual bool fold_range (irange &r, tree type,
const irange &op1,
const irange &op2,
- relation_kind rel = VREL_NONE) const;
+ relation_kind rel = VREL_VARYING) const;
virtual void wi_fold (irange &r, tree type,
const wide_int &lh_lb, const wide_int &lh_ub,
virtual bool fold_range (irange &r, tree type,
const irange &op1,
const irange &op2,
- relation_kind rel = VREL_NONE) const;
+ relation_kind rel = VREL_VARYING) const;
virtual void wi_fold (irange &r, tree type,
const wide_int &lh_lb,
const wide_int &lh_ub,
virtual bool op1_range (irange &, tree type,
const irange &lhs,
const irange &op2,
- relation_kind rel = VREL_NONE) const;
- virtual enum tree_code lhs_op1_relation (const irange &lhs,
+ relation_kind rel = VREL_VARYING) const;
+ virtual relation_kind lhs_op1_relation (const irange &lhs,
const irange &op1,
const irange &op2,
relation_kind rel) const;
} op_rshift;
-enum tree_code
+relation_kind
operator_rshift::lhs_op1_relation (const irange &lhs ATTRIBUTE_UNUSED,
const irange &op1,
const irange &op2,
if (!op1.undefined_p () && !op2.undefined_p ()
&& wi::ge_p (op1.lower_bound (), 0, TYPE_SIGN (op1.type ()))
&& wi::ge_p (op2.lower_bound (), 0, TYPE_SIGN (op2.type ())))
- return LE_EXPR;
- return VREL_NONE;
+ return VREL_LE;
+ return VREL_VARYING;
}
bool
virtual bool fold_range (irange &r, tree type,
const irange &op1,
const irange &op2,
- relation_kind rel = VREL_NONE) const;
+ relation_kind rel = VREL_VARYING) const;
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
const irange &op2,
- relation_kind rel = VREL_NONE) const;
+ relation_kind rel = VREL_VARYING) 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,
virtual bool fold_range (irange &r, tree type,
const irange &lh,
const irange &rh,
- relation_kind rel = VREL_NONE) const;
+ relation_kind rel = VREL_VARYING) const;
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
const irange &op2,
- relation_kind rel = VREL_NONE) const;
+ relation_kind rel = VREL_VARYING) const;
virtual bool op2_range (irange &r, tree type,
const irange &lhs,
const irange &op1,
- relation_kind rel = VREL_NONE) const;
+ relation_kind rel = VREL_VARYING) const;
} op_logical_and;
virtual bool fold_range (irange &r, tree type,
const irange &lh,
const irange &rh,
- relation_kind rel = VREL_NONE) const;
+ relation_kind rel = VREL_VARYING) const;
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
const irange &op2,
- relation_kind rel = VREL_NONE) const;
+ relation_kind rel = VREL_VARYING) const;
virtual bool op2_range (irange &r, tree type,
const irange &lhs,
const irange &op1,
- relation_kind rel = VREL_NONE) const;
+ relation_kind rel = VREL_VARYING) const;
virtual void wi_fold (irange &r, tree type,
const wide_int &lh_lb,
const wide_int &lh_ub,
virtual bool fold_range (irange &r, tree type,
const irange &lh,
const irange &rh,
- relation_kind rel = VREL_NONE) const;
+ relation_kind rel = VREL_VARYING) const;
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
const irange &op2,
- relation_kind rel = VREL_NONE) const;
+ relation_kind rel = VREL_VARYING) const;
virtual bool op2_range (irange &r, tree type,
const irange &lhs,
const irange &op1,
- relation_kind rel = VREL_NONE) const;
+ relation_kind rel = VREL_VARYING) const;
} op_logical_or;
bool
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
const irange &op2,
- relation_kind rel = VREL_NONE) const;
+ relation_kind rel = VREL_VARYING) const;
virtual bool op2_range (irange &r, tree type,
const irange &lhs,
const irange &op1,
- relation_kind rel= VREL_NONE) const;
+ relation_kind rel= VREL_VARYING) const;
virtual void wi_fold (irange &r, tree type,
const wide_int &lh_lb,
const wide_int &lh_ub,
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
const irange &op2,
- relation_kind rel = VREL_NONE) const;
+ relation_kind rel = VREL_VARYING) const;
virtual bool op2_range (irange &r, tree type,
const irange &lhs,
const irange &op1,
- relation_kind rel = VREL_NONE) const;
+ relation_kind rel = VREL_VARYING) const;
virtual bool op1_op2_relation_effect (irange &lhs_range,
tree type,
const irange &op1_range,
const irange &,
relation_kind rel) const
{
- if (rel == VREL_NONE)
+ if (rel == VREL_VARYING)
return false;
int_range<2> rel_range;
switch (rel)
{
- case EQ_EXPR:
+ case VREL_EQ:
rel_range.set_zero (type);
break;
- case NE_EXPR:
+ case VREL_NE:
rel_range.set_nonzero (type);
break;
default:
virtual bool fold_range (irange &r, tree type,
const irange &lh,
const irange &rh,
- relation_kind rel = VREL_NONE) const;
+ relation_kind rel = VREL_VARYING) const;
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
const irange &op2,
- relation_kind rel = VREL_NONE) const;
+ relation_kind rel = VREL_VARYING) const;
} op_logical_not;
// Folding a logical NOT, oddly enough, involves doing nothing on the
virtual bool fold_range (irange &r, tree type,
const irange &lh,
const irange &rh,
- relation_kind rel = VREL_NONE) const;
+ relation_kind rel = VREL_VARYING) const;
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
const irange &op2,
- relation_kind rel = VREL_NONE) const;
+ relation_kind rel = VREL_VARYING) const;
} op_bitwise_not;
bool
virtual bool fold_range (irange &r, tree type,
const irange &op1,
const irange &op2,
- relation_kind rel = VREL_NONE) const;
+ relation_kind rel = VREL_VARYING) const;
} op_integer_cst;
bool
virtual bool fold_range (irange &r, tree type,
const irange &op1,
const irange &op2,
- relation_kind rel = VREL_NONE) const;
+ relation_kind rel = VREL_VARYING) const;
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
const irange &op2,
- relation_kind rel = VREL_NONE) const;
- virtual enum tree_code lhs_op1_relation (const irange &lhs,
+ relation_kind rel = VREL_VARYING) const;
+ virtual relation_kind lhs_op1_relation (const irange &lhs,
const irange &op1,
const irange &op2,
relation_kind rel) const;
// Determine if there is a relationship between LHS and OP1.
-enum tree_code
+relation_kind
operator_identity::lhs_op1_relation (const irange &lhs,
const irange &op1 ATTRIBUTE_UNUSED,
const irange &op2 ATTRIBUTE_UNUSED,
relation_kind) const
{
if (lhs.undefined_p ())
- return VREL_NONE;
+ return VREL_VARYING;
// Simply a copy, so they are equivalent.
- return EQ_EXPR;
+ return VREL_EQ;
}
bool
virtual bool fold_range (irange &r, tree type,
const irange &op1,
const irange &op2,
- relation_kind rel = VREL_NONE) const;
+ relation_kind rel = VREL_VARYING) const;
} op_unknown;
bool
virtual bool fold_range (irange &r, tree type,
const irange &op1,
const irange &op2,
- relation_kind rel = VREL_NONE) const;
+ relation_kind rel = VREL_VARYING) const;
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
const irange &op2,
- relation_kind rel = VREL_NONE) const;
+ relation_kind rel = VREL_VARYING) const;
} op_negate;
bool
virtual bool fold_range (irange &r, tree type,
const irange &op1,
const irange &op2,
- relation_kind rel = VREL_NONE) const;
+ relation_kind rel = VREL_VARYING) const;
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
const irange &op2,
- relation_kind rel = VREL_NONE) const;
+ relation_kind rel = VREL_VARYING) const;
} op_addr;
bool
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
const irange &op2,
- relation_kind rel = VREL_NONE) const;
+ relation_kind rel = VREL_VARYING) const;
virtual bool op2_range (irange &r, tree type,
const irange &lhs,
const irange &op1,
- relation_kind rel = VREL_NONE) const;
+ relation_kind rel = VREL_VARYING) 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;
int_range<2> op2 (UCHAR (20), UCHAR (20));
// Never wrapping additions mean LHS > OP1.
- tree_code code = op_plus.lhs_op1_relation (lhs, op1, op2, VREL_NONE);
- ASSERT_TRUE (code == GT_EXPR);
+ relation_kind code = op_plus.lhs_op1_relation (lhs, op1, op2, VREL_VARYING);
+ ASSERT_TRUE (code == VREL_GT);
// Most wrapping additions mean nothing...
op1 = int_range<2> (UCHAR (8), UCHAR (10));
op2 = int_range<2> (UCHAR (0), UCHAR (255));
- code = op_plus.lhs_op1_relation (lhs, op1, op2, VREL_NONE);
- ASSERT_TRUE (code == VREL_NONE);
+ code = op_plus.lhs_op1_relation (lhs, op1, op2, VREL_VARYING);
+ ASSERT_TRUE (code == VREL_VARYING);
// However, always wrapping additions mean LHS < OP1.
op1 = int_range<2> (UCHAR (1), UCHAR (255));
op2 = int_range<2> (UCHAR (255), UCHAR (255));
- code = op_plus.lhs_op1_relation (lhs, op1, op2, VREL_NONE);
- ASSERT_TRUE (code == LT_EXPR);
+ code = op_plus.lhs_op1_relation (lhs, op1, op2, VREL_VARYING);
+ ASSERT_TRUE (code == VREL_LT);
}
void
virtual bool fold_range (irange &r, tree type,
const irange &lh,
const irange &rh,
- relation_kind rel = VREL_NONE) const;
+ relation_kind rel = VREL_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
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
const irange &op2,
- relation_kind rel = VREL_NONE) const;
+ relation_kind rel = VREL_VARYING) const;
virtual bool op2_range (irange &r, tree type,
const irange &lhs,
const irange &op1,
- relation_kind rel = VREL_NONE) const;
+ relation_kind rel = VREL_VARYING) const;
// The following routines are used to represent relations between the
// various operations. If the caller knows where the symbolics are,
// it can query for relationships between them given known ranges.
// the optional relation passed in is the relation between op1 and op2.
- virtual enum tree_code lhs_op1_relation (const irange &lhs,
- const irange &op1,
- const irange &op2,
- relation_kind rel = VREL_NONE) const;
- virtual enum tree_code lhs_op2_relation (const irange &lhs,
- const irange &op1,
- const irange &op2,
- relation_kind rel = VREL_NONE) const;
- virtual enum tree_code op1_op2_relation (const irange &lhs) const;
+ virtual relation_kind lhs_op1_relation (const irange &lhs,
+ const irange &op1,
+ const irange &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 op1_op2_relation (const irange &lhs) const;
protected:
// Perform an integral operation between 2 sub-ranges and return it.
virtual void wi_fold (irange &r, tree type,
wide_int &mustbe_nonzero);
// op1_op2_relation methods that are the same across irange and frange.
-enum tree_code equal_op1_op2_relation (const irange &lhs);
-enum tree_code not_equal_op1_op2_relation (const irange &lhs);
-enum tree_code lt_op1_op2_relation (const irange &lhs);
-enum tree_code le_op1_op2_relation (const irange &lhs);
-enum tree_code gt_op1_op2_relation (const irange &lhs);
-enum tree_code ge_op1_op2_relation (const irange &lhs);
+relation_kind equal_op1_op2_relation (const irange &lhs);
+relation_kind not_equal_op1_op2_relation (const irange &lhs);
+relation_kind lt_op1_op2_relation (const irange &lhs);
+relation_kind le_op1_op2_relation (const irange &lhs);
+relation_kind gt_op1_op2_relation (const irange &lhs);
+relation_kind ge_op1_op2_relation (const irange &lhs);
enum bool_range_state { BRS_FALSE, BRS_TRUE, BRS_EMPTY, BRS_FULL };
bool_range_state get_bool_state (irange &r, const irange &lhs, tree val_type);
}
// If known relation has no subset of this relation, always false.
- if (relation_intersect (rel, my_rel) == VREL_EMPTY)
+ if (relation_intersect (rel, my_rel) == VREL_UNDEFINED)
{
r = range_false (type);
return true;
{
int_range_max tmp;
if (!m_oracle || TREE_CODE (ssa1) != SSA_NAME || TREE_CODE (ssa2) != SSA_NAME)
- return VREL_NONE;
+ return VREL_VARYING;
// Ensure ssa1 and ssa2 have both been evaluated.
if (get_range)
basic_block bb;
int_range_max tmp;
if (!m_oracle || TREE_CODE (ssa1) != SSA_NAME || TREE_CODE (ssa2) != SSA_NAME)
- return VREL_NONE;
+ return VREL_VARYING;
// Use destination block if it has a single predecessor, and this picks
// up any relation on the edge.
#include "alloc-pool.h"
#include "dominance.h"
-// These VREL codes are arranged such that VREL_NONE is the first
-// code, and all the rest are contiguous up to and including VREL_LAST.
-
-#define VREL_FIRST VREL_NONE
-#define VREL_LAST NE_EXPR
-#define VREL_COUNT (VREL_LAST - VREL_FIRST + 1)
-
-// vrel_range_assert will either assert that the tree code passed is valid,
-// or mark invalid codes as unreachable to help with table optimation.
-#if CHECKING_P
- #define vrel_range_assert(c) \
- gcc_checking_assert ((c) >= VREL_FIRST && (c) <= VREL_LAST)
-#else
- #define vrel_range_assert(c) \
- if ((c) < VREL_FIRST || (c) > VREL_LAST) \
- gcc_unreachable ();
-#endif
-
-static const char *kind_string[VREL_COUNT] =
-{ "none", "<", "<=", ">", ">=", "empty", "==", "!=" };
+#define VREL_LAST VREL_NE
+
+static const char *kind_string[VREL_LAST + 1] =
+{ "varying", "undefined", "<", "<=", ">", ">=", "==", "!=" };
// Print a relation_kind REL to file F.
void
print_relation (FILE *f, relation_kind rel)
{
- vrel_range_assert (rel);
- fprintf (f, " %s ", kind_string[rel - VREL_FIRST]);
+ fprintf (f, " %s ", kind_string[rel]);
}
// This table is used to negate the operands. op1 REL op2 -> !(op1 REL op2).
-relation_kind rr_negate_table[VREL_COUNT] = {
-// NONE, LT_EXPR, LE_EXPR, GT_EXPR, GE_EXPR, EMPTY, EQ_EXPR, NE_EXPR
- VREL_NONE, GE_EXPR, GT_EXPR, LE_EXPR, LT_EXPR, VREL_EMPTY, NE_EXPR, EQ_EXPR };
+relation_kind rr_negate_table[VREL_LAST + 1] = {
+ VREL_VARYING, VREL_UNDEFINED, VREL_GE, VREL_GT, VREL_LE, VREL_LT, VREL_NE,
+ VREL_EQ };
// Negate the relation, as in logical negation.
relation_kind
relation_negate (relation_kind r)
{
- vrel_range_assert (r);
- return rr_negate_table [r - VREL_FIRST];
+ return rr_negate_table [r];
}
// This table is used to swap the operands. op1 REL op2 -> op2 REL op1.
-relation_kind rr_swap_table[VREL_COUNT] = {
-// NONE, LT_EXPR, LE_EXPR, GT_EXPR, GE_EXPR, EMPTY, EQ_EXPR, NE_EXPR
- VREL_NONE, GT_EXPR, GE_EXPR, LT_EXPR, LE_EXPR, VREL_EMPTY, EQ_EXPR, NE_EXPR };
+relation_kind rr_swap_table[VREL_LAST + 1] = {
+ VREL_VARYING, VREL_UNDEFINED, VREL_GT, VREL_GE, VREL_LT, VREL_LE, VREL_EQ,
+ VREL_NE };
// Return the relation as if the operands were swapped.
relation_kind
relation_swap (relation_kind r)
{
- vrel_range_assert (r);
- return rr_swap_table [r - VREL_FIRST];
+ return rr_swap_table [r];
}
// This table is used to perform an intersection between 2 relations.
-relation_kind rr_intersect_table[VREL_COUNT][VREL_COUNT] = {
-// NONE, LT_EXPR, LE_EXPR, GT_EXPR, GE_EXPR, EMPTY, EQ_EXPR, NE_EXPR
-// VREL_NONE
- { VREL_NONE, LT_EXPR, LE_EXPR, GT_EXPR, GE_EXPR, VREL_EMPTY, EQ_EXPR, NE_EXPR },
-// LT_EXPR
- { LT_EXPR, LT_EXPR, LT_EXPR, VREL_EMPTY, VREL_EMPTY, VREL_EMPTY, VREL_EMPTY, LT_EXPR },
-// LE_EXPR
- { LE_EXPR, LT_EXPR, LE_EXPR, VREL_EMPTY, EQ_EXPR, VREL_EMPTY, EQ_EXPR, LT_EXPR },
-// GT_EXPR
- { GT_EXPR, VREL_EMPTY, VREL_EMPTY, GT_EXPR, GT_EXPR, VREL_EMPTY, VREL_EMPTY, GT_EXPR },
-// GE_EXPR
- { GE_EXPR, VREL_EMPTY, EQ_EXPR, GT_EXPR, GE_EXPR, VREL_EMPTY, EQ_EXPR, GT_EXPR },
-// VREL_EMPTY
- { VREL_EMPTY, VREL_EMPTY, VREL_EMPTY, VREL_EMPTY, VREL_EMPTY, VREL_EMPTY, VREL_EMPTY, VREL_EMPTY },
-// EQ_EXPR
- { EQ_EXPR, VREL_EMPTY, EQ_EXPR, VREL_EMPTY, EQ_EXPR, VREL_EMPTY, EQ_EXPR, VREL_EMPTY },
-// NE_EXPR
- { NE_EXPR, LT_EXPR, LT_EXPR, GT_EXPR, GT_EXPR, VREL_EMPTY, VREL_EMPTY, NE_EXPR } };
+relation_kind rr_intersect_table[VREL_LAST + 1][VREL_LAST + 1] = {
+// VREL_VARYING
+ { VREL_VARYING, VREL_UNDEFINED, VREL_LT, VREL_LE, VREL_GT, VREL_GE, VREL_EQ,
+ VREL_NE },
+// VREL_UNDEFINED
+ { VREL_UNDEFINED, VREL_UNDEFINED, VREL_UNDEFINED, VREL_UNDEFINED,
+ VREL_UNDEFINED, VREL_UNDEFINED, VREL_UNDEFINED, VREL_UNDEFINED },
+// VREL_LT
+ { VREL_LT, VREL_UNDEFINED, VREL_LT, VREL_LT, VREL_UNDEFINED, VREL_UNDEFINED,
+ VREL_UNDEFINED, VREL_LT },
+// VREL_LE
+ { VREL_LE, VREL_UNDEFINED, VREL_LT, VREL_LE, VREL_UNDEFINED, VREL_EQ,
+ VREL_EQ, VREL_LT },
+// VREL_GT
+ { VREL_GT, VREL_UNDEFINED, VREL_UNDEFINED, VREL_UNDEFINED, VREL_GT, VREL_GT,
+ VREL_UNDEFINED, VREL_GT },
+// VREL_GE
+ { VREL_GE, VREL_UNDEFINED, VREL_UNDEFINED, VREL_EQ, VREL_GT, VREL_GE,
+ VREL_EQ, VREL_GT },
+// VREL_EQ
+ { VREL_EQ, VREL_UNDEFINED, VREL_UNDEFINED, VREL_EQ, VREL_UNDEFINED, VREL_EQ,
+ VREL_EQ, VREL_UNDEFINED },
+// VREL_NE
+ { VREL_NE, VREL_UNDEFINED, VREL_LT, VREL_LT, VREL_GT, VREL_GT,
+ VREL_UNDEFINED, VREL_NE } };
// Intersect relation R1 with relation R2 and return the resulting relation.
relation_kind
relation_intersect (relation_kind r1, relation_kind r2)
{
- vrel_range_assert (r1);
- vrel_range_assert (r2);
- return rr_intersect_table[r1 - VREL_FIRST][r2 - VREL_FIRST];
+ return rr_intersect_table[r1][r2];
}
// This table is used to perform a union between 2 relations.
-relation_kind rr_union_table[VREL_COUNT][VREL_COUNT] = {
-// NONE, LT_EXPR, LE_EXPR, GT_EXPR, GE_EXPR, EMPTY, EQ_EXPR, NE_EXPR
-// VREL_NONE
- { VREL_NONE, VREL_NONE, VREL_NONE, VREL_NONE, VREL_NONE, VREL_NONE, VREL_NONE, VREL_NONE },
-// LT_EXPR
- { VREL_NONE, LT_EXPR, LE_EXPR, NE_EXPR, VREL_NONE, LT_EXPR, LE_EXPR, NE_EXPR },
-// LE_EXPR
- { VREL_NONE, LE_EXPR, LE_EXPR, VREL_NONE, VREL_NONE, LE_EXPR, LE_EXPR, VREL_NONE },
-// GT_EXPR
- { VREL_NONE, NE_EXPR, VREL_NONE, GT_EXPR, GE_EXPR, GT_EXPR, GE_EXPR, NE_EXPR },
-// GE_EXPR
- { VREL_NONE, VREL_NONE, VREL_NONE, GE_EXPR, GE_EXPR, GE_EXPR, GE_EXPR, VREL_NONE },
-// VREL_EMPTY
- { VREL_NONE, LT_EXPR, LE_EXPR, GT_EXPR, GE_EXPR, VREL_EMPTY, EQ_EXPR, NE_EXPR },
-// EQ_EXPR
- { VREL_NONE, LE_EXPR, LE_EXPR, GE_EXPR, GE_EXPR, EQ_EXPR, EQ_EXPR, VREL_NONE },
-// NE_EXPR
- { VREL_NONE, NE_EXPR, VREL_NONE, NE_EXPR, VREL_NONE, NE_EXPR, VREL_NONE, NE_EXPR } };
+relation_kind rr_union_table[VREL_LAST + 1][VREL_LAST + 1] = {
+// VREL_VARYING
+ { VREL_VARYING, VREL_VARYING, VREL_VARYING, VREL_VARYING, VREL_VARYING,
+ VREL_VARYING, VREL_VARYING, VREL_VARYING },
+// VREL_UNDEFINED
+ { VREL_VARYING, VREL_LT, VREL_LE, VREL_GT, VREL_GE, VREL_UNDEFINED,
+ VREL_EQ, VREL_NE },
+// VREL_LT
+ { VREL_VARYING, VREL_LT, VREL_LT, VREL_LE, VREL_NE, VREL_VARYING, VREL_LE,
+ VREL_NE },
+// VREL_LE
+ { VREL_VARYING, VREL_LE, VREL_LE, VREL_LE, VREL_VARYING, VREL_VARYING,
+ VREL_LE, VREL_VARYING },
+// VREL_GT
+ { VREL_VARYING, VREL_GT, VREL_NE, VREL_VARYING, VREL_GT, VREL_GE, VREL_GE,
+ VREL_NE },
+// VREL_GE
+ { VREL_VARYING, VREL_GE, VREL_VARYING, VREL_VARYING, VREL_GE, VREL_GE,
+ VREL_GE, VREL_VARYING },
+// VREL_EQ
+ { VREL_VARYING, VREL_EQ, VREL_LE, VREL_LE, VREL_GE, VREL_GE, VREL_EQ,
+ VREL_VARYING },
+// VREL_NE
+ { VREL_VARYING, VREL_NE, VREL_NE, VREL_VARYING, VREL_NE, VREL_VARYING,
+ VREL_VARYING, VREL_NE } };
// Union relation R1 with relation R2 and return the result.
relation_kind
relation_union (relation_kind r1, relation_kind r2)
{
- vrel_range_assert (r1);
- vrel_range_assert (r2);
- return rr_union_table[r1 - VREL_FIRST][r2 - VREL_FIRST];
+ return rr_union_table[r1][r2];
}
// This table is used to determine transitivity between 2 relations.
// (A relation0 B) and (B relation1 C) implies (A result C)
-relation_kind rr_transitive_table[VREL_COUNT][VREL_COUNT] = {
-// NONE, LT_EXPR, LE_EXPR, GT_EXPR, GE_EXPR, EMPTY, EQ_EXPR, NE_EXPR
-// VREL_NONE
- { VREL_NONE, VREL_NONE, VREL_NONE, VREL_NONE, VREL_NONE, VREL_NONE, VREL_NONE, VREL_NONE },
-// LT_EXPR
- { VREL_NONE, LT_EXPR, LT_EXPR, VREL_NONE, VREL_NONE, VREL_NONE, LT_EXPR, VREL_NONE },
-// LE_EXPR
- { VREL_NONE, LT_EXPR, LE_EXPR, VREL_NONE, VREL_NONE, VREL_NONE, LE_EXPR, VREL_NONE },
-// GT_EXPR
- { VREL_NONE, VREL_NONE, VREL_NONE, GT_EXPR, GT_EXPR, VREL_NONE, GT_EXPR, VREL_NONE },
-// GE_EXPR
- { VREL_NONE, VREL_NONE, VREL_NONE, GT_EXPR, GE_EXPR, VREL_NONE, GE_EXPR, VREL_NONE },
-// VREL_EMPTY
- { VREL_NONE, VREL_NONE, VREL_NONE, VREL_NONE, VREL_NONE, VREL_NONE, VREL_NONE, VREL_NONE },
-// EQ_EXPR
- { VREL_NONE, LT_EXPR, LE_EXPR, GT_EXPR, GE_EXPR, VREL_NONE, EQ_EXPR, VREL_NONE },
-// NE_EXPR
- { VREL_NONE, VREL_NONE, VREL_NONE, VREL_NONE, VREL_NONE, VREL_NONE, VREL_NONE, VREL_NONE } };
+relation_kind rr_transitive_table[VREL_LAST + 1][VREL_LAST + 1] = {
+// VREL_VARYING
+ { VREL_VARYING, VREL_VARYING, VREL_VARYING, VREL_VARYING, VREL_VARYING,
+ VREL_VARYING, VREL_VARYING, VREL_VARYING },
+// VREL_UNDEFINED
+ { VREL_VARYING, VREL_VARYING, VREL_VARYING, VREL_VARYING, VREL_VARYING,
+ VREL_VARYING, VREL_VARYING, VREL_VARYING },
+// VREL_LT
+ { VREL_VARYING, VREL_VARYING, VREL_LT, VREL_LT, VREL_VARYING, VREL_VARYING,
+ VREL_LT, VREL_VARYING },
+// VREL_LE
+ { VREL_VARYING, VREL_VARYING, VREL_LT, VREL_LE, VREL_VARYING, VREL_VARYING,
+ VREL_LE, VREL_VARYING },
+// VREL_GT
+ { VREL_VARYING, VREL_VARYING, VREL_VARYING, VREL_VARYING, VREL_GT, VREL_GT,
+ VREL_GT, VREL_VARYING },
+// VREL_GE
+ { VREL_VARYING, VREL_VARYING, VREL_VARYING, VREL_VARYING, VREL_GT, VREL_GE,
+ VREL_GE, VREL_VARYING },
+// VREL_EQ
+ { VREL_VARYING, VREL_VARYING, VREL_LT, VREL_LE, VREL_GT, VREL_GE, VREL_EQ,
+ VREL_VARYING },
+// VREL_NE
+ { VREL_VARYING, VREL_VARYING, VREL_VARYING, VREL_VARYING, VREL_VARYING,
+ VREL_VARYING, VREL_VARYING, VREL_VARYING } };
// Apply transitive operation between relation R1 and relation R2, and
// return the resulting relation, if any.
relation_kind
relation_transitive (relation_kind r1, relation_kind r2)
{
- vrel_range_assert (r1);
- vrel_range_assert (r2);
- return rr_transitive_table[r1 - VREL_FIRST][r2 - VREL_FIRST];
+ return rr_transitive_table[r1][r2];
}
// Given an equivalence set EQUIV, set all the bits in B that are still valid
{
// If the 2 ssa names share the same equiv set, they are equal.
if (equiv_set (ssa1, bb) == equiv_set (ssa2, bb))
- return EQ_EXPR;
- return VREL_NONE;
+ return VREL_EQ;
+ return VREL_VARYING;
}
// Query if thre is a relation (equivalence) between 2 SSA_NAMEs.
{
// If the 2 ssa names share the same equiv set, they are equal.
if (bitmap_equal_p (e1, e2))
- return EQ_EXPR;
- return VREL_NONE;
+ return VREL_EQ;
+ return VREL_VARYING;
}
// If SSA has an equivalence in block BB, find and return it.
tree ssa2)
{
// Only handle equality relations.
- if (k != EQ_EXPR)
+ if (k != VREL_EQ)
return;
unsigned v1 = SSA_NAME_VERSION (ssa1);
inline
value_relation::value_relation ()
{
- related = VREL_NONE;
+ related = VREL_VARYING;
name1 = NULL_TREE;
name2 = NULL_TREE;
}
bool
value_relation::apply_transitive (const value_relation &rel)
{
- relation_kind k = VREL_NONE;
+ relation_kind k = VREL_VARYING;
// Idenity any common operand, and notrmalize the relations to
// the form : A < B B < C produces A < C
if (rel.op2 () == name1)
return false;
k = relation_transitive (kind (), rel.kind ());
- if (k != VREL_NONE)
+ if (k != VREL_VARYING)
{
related = k;
name2 = rel.op2 ();
if (rel.op2 () == name2)
return false;
k = relation_transitive (relation_swap (kind ()), rel.kind ());
- if (k != VREL_NONE)
+ if (k != VREL_VARYING)
{
related = k;
name1 = name2;
if (rel.op1 () == name1)
return false;
k = relation_transitive (kind (), relation_swap (rel.kind ()));
- if (k != VREL_NONE)
+ if (k != VREL_VARYING)
{
related = k;
name2 = rel.op1 ();
return false;
k = relation_transitive (relation_swap (kind ()),
relation_swap (rel.kind ()));
- if (k != VREL_NONE)
+ if (k != VREL_VARYING)
{
related = k;
name1 = name2;
relation_chain_head::find_relation (const_bitmap b1, const_bitmap b2) const
{
if (!m_names)
- return VREL_NONE;
+ return VREL_VARYING;
// If both b1 and b2 aren't referenced in thie block, cant be a relation
if (!bitmap_intersect_p (m_names, b1) || !bitmap_intersect_p (m_names, b2))
- return VREL_NONE;
+ return VREL_VARYING;
// Search for the fiorst relation that contains BOTH an element from B1
// and B2, and return that relation.
return relation_swap (ptr->kind ());
}
- return VREL_NONE;
+ return VREL_VARYING;
}
// Instantiate a relation oracle.
gcc_checking_assert (stmt && gimple_bb (stmt));
// Don't register lack of a relation.
- if (k == VREL_NONE)
+ if (k == VREL_VARYING)
return;
if (dump_file && (dump_flags & TDF_DETAILS))
// make sure that that argument is not defined in the same block.
// This can happen along back edges and the equivalence will not be
// applicable as it would require a use before def.
- if (k == EQ_EXPR && is_a<gphi *> (stmt))
+ if (k == VREL_EQ && is_a<gphi *> (stmt))
{
tree phi_def = gimple_phi_result (stmt);
gcc_checking_assert (phi_def == op1 || phi_def == op2);
// Do not register lack of relation, or blocks which have more than
// edge E for a predecessor.
- if (k == VREL_NONE || !single_pred_p (e->dest))
+ if (k == VREL_VARYING || !single_pred_p (e->dest))
return;
if (dump_file && (dump_flags & TDF_DETAILS))
return;
// Equivalencies are handled by the equivalence oracle.
- if (k == EQ_EXPR)
+ if (k == VREL_EQ)
equiv_oracle::register_relation (bb, k, op1, op2);
else
{
dom_oracle::set_one_relation (basic_block bb, relation_kind k, tree op1,
tree op2)
{
- gcc_checking_assert (k != VREL_NONE && k != EQ_EXPR);
+ gcc_checking_assert (k != VREL_VARYING && k != VREL_EQ);
value_relation vr(k, op1, op2);
int bbi = bb->index;
relation_chain *ptr;
curr = find_relation_block (bbi, v1, v2, &ptr);
// There is an existing relation in this block, just intersect with it.
- if (curr != VREL_NONE)
+ if (curr != VREL_VARYING)
{
if (dump_file && (dump_flags & TDF_DETAILS))
{
// By including dominating relations, The first one found in any search
// will be the aggregate of all the previous ones.
curr = find_relation_dom (bb, v1, v2);
- if (curr != VREL_NONE)
+ if (curr != VREL_VARYING)
k = relation_intersect (curr, k);
bitmap_set_bit (bm, v1);
// Only apply transitives to certain kinds of operations.
switch (relation.kind ())
{
- case LE_EXPR:
- case LT_EXPR:
- case GT_EXPR:
- case GE_EXPR:
+ case VREL_LE:
+ case VREL_LT:
+ case VREL_GT:
+ case VREL_GE:
break;
default:
return;
const_bitmap b2) const
{
if (bb >= m_relations.length())
- return VREL_NONE;
+ return VREL_VARYING;
return m_relations[bb].find_relation (b1, b2);
}
{
relation_kind r;
if (bitmap_equal_p (b1, b2))
- return EQ_EXPR;
+ return VREL_EQ;
// If either name does not occur in a relation anywhere, there isnt one.
if (!bitmap_intersect_p (m_relation_set, b1)
|| !bitmap_intersect_p (m_relation_set, b2))
- return VREL_NONE;
+ return VREL_VARYING;
// Search each block in the DOM tree checking.
for ( ; bb; bb = get_immediate_dominator (CDI_DOMINATORS, bb))
{
r = find_relation_block (bb->index, b1, b2);
- if (r != VREL_NONE)
+ if (r != VREL_VARYING)
return r;
}
- return VREL_NONE;
+ return VREL_VARYING;
}
relation_chain **obj) const
{
if (bb >= (int)m_relations.length())
- return VREL_NONE;
+ return VREL_VARYING;
const_bitmap bm = m_relations[bb].m_names;
if (!bm)
- return VREL_NONE;
+ return VREL_VARYING;
// If both b1 and b2 aren't referenced in thie block, cant be a relation
if (!bitmap_bit_p (bm, v1) || !bitmap_bit_p (bm, v2))
- return VREL_NONE;
+ return VREL_VARYING;
relation_chain *ptr;
for (ptr = m_relations[bb].m_head; ptr ; ptr = ptr->m_next)
}
}
- return VREL_NONE;
+ return VREL_VARYING;
}
// Find a relation between SSA version V1 and V2 in the dominator tree
relation_kind r;
// IF either name does not occur in a relation anywhere, there isnt one.
if (!bitmap_bit_p (m_relation_set, v1) || !bitmap_bit_p (m_relation_set, v2))
- return VREL_NONE;
+ return VREL_VARYING;
for ( ; bb; bb = get_immediate_dominator (CDI_DOMINATORS, bb))
{
r = find_relation_block (bb->index, v1, v2);
- if (r != VREL_NONE)
+ if (r != VREL_VARYING)
return r;
}
- return VREL_NONE;
+ return VREL_VARYING;
}
unsigned v1 = SSA_NAME_VERSION (ssa1);
unsigned v2 = SSA_NAME_VERSION (ssa2);
if (v1 == v2)
- return EQ_EXPR;
+ return VREL_EQ;
// Check for equivalence first. They must be in each equivalency set.
const_bitmap equiv1 = equiv_set (ssa1, bb);
const_bitmap equiv2 = equiv_set (ssa2, bb);
if (bitmap_bit_p (equiv1, v2) && bitmap_bit_p (equiv2, v1))
- return EQ_EXPR;
+ return VREL_EQ;
// Initially look for a direct relationship and just return that.
kind = find_relation_dom (bb, v1, v2);
- if (kind != VREL_NONE)
+ if (kind != VREL_VARYING)
return kind;
// Query using the equiovalence sets.
fprintf (dump_file, " (root: bb%d)\n", bb->index);
}
- if (k == EQ_EXPR)
+ if (k == VREL_EQ)
{
register_equiv (bb, ssa1, ssa2);
return;
}
relation_kind curr = query_relation (bb, ssa1, ssa2);
- if (curr != VREL_NONE)
+ if (curr != VREL_VARYING)
k = relation_intersect (curr, k);
bitmap_set_bit (m_relations.m_names, SSA_NAME_VERSION (ssa1));
path_oracle::query_relation (basic_block bb, const_bitmap b1, const_bitmap b2)
{
if (bitmap_equal_p (b1, b2))
- return EQ_EXPR;
+ return VREL_EQ;
relation_kind k = m_relations.find_relation (b1, b2);
|| bitmap_intersect_p (m_killed_defs, b2))
return k;
- if (k == VREL_NONE && m_root)
+ if (k == VREL_VARYING && m_root)
k = m_root->query_relation (bb, b1, b2);
return k;
unsigned v2 = SSA_NAME_VERSION (ssa2);
if (v1 == v2)
- return EQ_EXPR;
+ return VREL_EQ;
const_bitmap equiv_1 = equiv_set (ssa1, bb);
const_bitmap equiv_2 = equiv_set (ssa2, bb);
if (bitmap_bit_p (equiv_1, v2) && bitmap_bit_p (equiv_2, v1))
- return EQ_EXPR;
+ return VREL_EQ;
return query_relation (bb, equiv_1, equiv_2);
}
// The general range_query object provided in value-query.h provides
// access to an oracle, if one is available, via the oracle() method.
// Thre are also a couple of access routines provided, which even if there is
-// no oracle, will return the default VREL_NONE no relation.
+// no oracle, will return the default VREL_VARYING no relation.
//
// Typically, when a ranger object is active, there will be an oracle, and
// any information available can be directly queried. Ranger also sets and
// block, or on an edge, the possible return values are:
//
// EQ_EXPR, NE_EXPR, LT_EXPR, LE_EXPR, GT_EXPR, and GE_EXPR mean the same.
-// VREL_NONE : No relation between the 2 names.
-// VREL_EMPTY : Impossible relation (ie, A < B && A > B produces VREL_EMPTY.
+// VREL_VARYING : No relation between the 2 names.
+// VREL_UNDEFINED : Impossible relation (ie, A < B && A > B)
//
// The oracle maintains EQ_EXPR relations with equivalency sets, so if a
// relation comes back EQ_EXPR, it is also possible to query the set of
// Rather than introduce a new enumerated type for relations, we can use the
// existing tree_codes for relations, plus add a couple of #defines for
-// the other cases. These codes are arranged such that VREL_NONE is the first
-// code, and all the rest are contiguous.
+// the other cases. These codes are arranged such that VREL_VARYING is the
+// first code, and all the rest are contiguous.
-typedef enum tree_code relation_kind;
-
-#define VREL_NONE TRUTH_NOT_EXPR
-#define VREL_EMPTY LTGT_EXPR
+typedef enum relation_kind_t
+{
+ VREL_VARYING = 0, // No known relation, AKA varying.
+ VREL_UNDEFINED, // Impossible relation, ie (r1 < r2) && (r2 > r1)
+ VREL_LT, // r1 < r2
+ VREL_LE, // r1 <= r2
+ VREL_GT, // r1 > r2
+ VREL_GE, // r1 >= r2
+ VREL_EQ, // r1 == r2
+ VREL_NE // r1 != r2
+} relation_kind;
// General relation kind transformations.
relation_kind relation_union (relation_kind r1, relation_kind r2);
relation_kind relation_swap (relation_kind r);
void print_relation (FILE *f, relation_kind rel);
-
class relation_oracle
{
public: