fputc ('\n', dump_file);
}
// Fold range, and register any dependency if available.
- if (!handler.fold_range (r, type, range1, range2, rel))
+ if (!handler.fold_range (r, type, range1, range2,
+ relation_trio::op1_op2 (rel)))
r.set_varying (type);
if (irange::supports_p (type))
relation_fold_and_or (as_a <irange> (r), s, src);
}
if (gimple_range_ssa_p (op2))
{
- rel= handler.lhs_op2_relation (r, range1, range2, rel);
+ rel = handler.lhs_op2_relation (r, range1, range2, rel);
if (rel != VREL_VARYING)
src.register_relation (s, rel, lhs, op2);
}
Value_Range new_result (type);
if (!op_handler.op1_range (new_result, type,
op1_def_p ? op1_range : op2_range,
- other_op, k))
+ other_op, relation_trio::lhs_op2 (k)))
return false;
if (op1_def_p)
{
Value_Range new_result (type);
if (!op_handler.op2_range (new_result, type,
op1_def_p ? op1_range : op2_range,
- other_op, k))
+ other_op, relation_trio::lhs_op1 (k)))
return false;
if (op1_def_p)
{
{
src.get_operand (op2_range, op2);
relation_kind k = VREL_VARYING;
+ relation_kind op_op = (op1 == op2) ? VREL_EQ : VREL_VARYING;
if (rel)
{
if (lhs_name == rel->op1 () && op1 == rel->op2 ())
else if (lhs_name == rel->op2 () && op1 == rel->op1 ())
k = relation_swap (rel->kind ());
else if (op1 == rel->op1 () && op2 == rel->op2 ())
- refine_using_relation (op1, op1_range, op2, op2_range, src,
- rel->kind ());
+ {
+ op_op = rel->kind ();
+ refine_using_relation (op1, op1_range, op2, op2_range, src, op_op);
+ }
else if (op1 == rel->op2 () && op2 == rel->op1 ())
- refine_using_relation (op1, op1_range, op2, op2_range, src,
- relation_swap (rel->kind ()));
+ {
+ op_op = relation_swap (rel->kind ());
+ refine_using_relation (op1, op1_range, op2, op2_range, src, op_op);
+ }
}
- if (!handler.calc_op1 (tmp, lhs, op2_range, k))
+ if (!handler.calc_op1 (tmp, lhs, op2_range, relation_trio (VREL_VARYING,
+ k, op_op)))
return false;
}
else
// We pass op1_range to the unary operation. Nomally it's a
// hidden range_for_type parameter, but sometimes having the
// actual range can result in better information.
- if (!handler.calc_op1 (tmp, lhs, op1_range, VREL_VARYING))
+ if (!handler.calc_op1 (tmp, lhs, op1_range, TRIO_VARYING))
return false;
}
src.get_operand (op1_range, op1);
src.get_operand (op2_range, op2);
relation_kind k = VREL_VARYING;
+ relation_kind op_op = (op1 == op2) ? VREL_EQ : VREL_VARYING;
if (rel)
{
if (lhs_name == rel->op1 () && op2 == rel->op2 ())
- k = rel->kind ();
+ k = rel->kind ();
else if (lhs_name == rel->op2 () && op2 == rel->op1 ())
- k = relation_swap (rel->kind ());
+ k = relation_swap (rel->kind ());
else if (op1 == rel->op1 () && op2 == rel->op2 ())
- refine_using_relation (op1, op1_range, op2, op2_range, src,
- rel->kind ());
+ {
+ op_op = rel->kind ();
+ refine_using_relation (op1, op1_range, op2, op2_range, src, op_op);
+ }
else if (op1 == rel->op2 () && op2 == rel->op1 ())
- refine_using_relation (op1, op1_range, op2, op2_range, src,
- relation_swap (rel->kind ()));
+ {
+ op_op = relation_swap (rel->kind ());
+ refine_using_relation (op1, op1_range, op2, op2_range, src, op_op);
+ }
}
-
// Intersect with range for op2 based on lhs and op1.
- if (!handler.calc_op2 (tmp, lhs, op1_range, k))
+ if (!handler.calc_op2 (tmp, lhs, op1_range, relation_trio (k, VREL_VARYING,
+ op_op)))
return false;
unsigned idx;
bool
gimple_range_op_handler::calc_op1 (vrange &r, const vrange &lhs_range,
- const vrange &op2_range, relation_kind k)
+ const vrange &op2_range, relation_trio k)
{
// Give up on empty ranges.
if (lhs_range.undefined_p ())
bool
gimple_range_op_handler::calc_op2 (vrange &r, const vrange &lhs_range,
- const vrange &op1_range, relation_kind k)
+ const vrange &op1_range, relation_trio k)
{
// Give up on empty ranges.
if (lhs_range.undefined_p ())
public:
using range_operator_float::fold_range;
virtual bool fold_range (irange &r, tree type, const frange &lh,
- const irange &, relation_kind) const
+ const irange &, relation_trio) const
{
if (lh.singleton_p ())
{
public:
using range_operator::fold_range;
virtual bool fold_range (irange &r, tree type, const irange &lh,
- const irange &, relation_kind) const
+ const irange &, relation_trio) const
{
if (lh.singleton_p ())
{
using range_operator_float::fold_range;
using range_operator_float::op1_range;
virtual bool fold_range (irange &r, tree type, const frange &lh,
- const irange &, relation_kind) const override
+ const irange &, relation_trio) const override
{
bool signbit;
if (lh.signbit_p (signbit))
return false;
}
virtual bool op1_range (frange &r, tree type, const irange &lhs,
- const frange &, relation_kind) const override
+ const frange &, relation_trio) const override
{
if (lhs.zero_p ())
{
public:
using range_operator_float::fold_range;
virtual bool fold_range (frange &r, tree type, const frange &lh,
- const frange &rh, relation_kind) const override
+ const frange &rh, relation_trio) const override
{
frange neg;
range_op_handler abs_op (ABS_EXPR, type);
using range_operator::fold_range;
cfn_toupper_tolower (bool toupper) { m_toupper = toupper; }
virtual bool fold_range (irange &r, tree type, const irange &lh,
- const irange &, relation_kind) const;
+ const irange &, relation_trio) const;
private:
bool get_letter_range (tree type, irange &lowers, irange &uppers) const;
bool m_toupper;
bool
cfn_toupper_tolower::fold_range (irange &r, tree type, const irange &lh,
- const irange &, relation_kind) const
+ const irange &, relation_trio) const
{
int_range<3> lowers;
int_range<3> uppers;
public:
using range_operator::fold_range;
virtual bool fold_range (irange &r, tree type, const irange &lh,
- const irange &, relation_kind) const
+ const irange &, relation_trio) const
{
if (lh.undefined_p ())
return false;
public:
using range_operator::fold_range;
virtual bool fold_range (irange &r, tree type, const irange &lh,
- const irange &rh, relation_kind rel) const
+ const irange &rh, relation_trio rel) const
{
if (lh.undefined_p ())
return false;
cfn_clz (bool internal) { m_gimple_call_internal_p = internal; }
using range_operator::fold_range;
virtual bool fold_range (irange &r, tree type, const irange &lh,
- const irange &, relation_kind) const;
+ const irange &, relation_trio) const;
private:
bool m_gimple_call_internal_p;
} op_cfn_clz (false), op_cfn_clz_internal (true);
bool
cfn_clz::fold_range (irange &r, tree type, const irange &lh,
- const irange &, relation_kind) const
+ const irange &, relation_trio) const
{
// __builtin_c[lt]z* return [0, prec-1], except when the
// argument is 0, but that is undefined behavior.
cfn_ctz (bool internal) { m_gimple_call_internal_p = internal; }
using range_operator::fold_range;
virtual bool fold_range (irange &r, tree type, const irange &lh,
- const irange &, relation_kind) const;
+ const irange &, relation_trio) const;
private:
bool m_gimple_call_internal_p;
} op_cfn_ctz (false), op_cfn_ctz_internal (true);
bool
cfn_ctz::fold_range (irange &r, tree type, const irange &lh,
- const irange &, relation_kind) const
+ const irange &, relation_trio) const
{
if (lh.undefined_p ())
return false;
public:
using range_operator::fold_range;
virtual bool fold_range (irange &r, tree type, const irange &lh,
- const irange &, relation_kind) const
+ const irange &, relation_trio) const
{
if (lh.undefined_p ())
return false;
cfn_ubsan (enum tree_code code) { m_code = code; }
using range_operator::fold_range;
virtual bool fold_range (irange &r, tree type, const irange &lh,
- const irange &rh, relation_kind rel) const
+ const irange &rh, relation_trio rel) const
{
range_op_handler handler (m_code, type);
gcc_checking_assert (handler);
public:
using range_operator::fold_range;
virtual bool fold_range (irange &r, tree type, const irange &,
- const irange &, relation_kind) const
+ const irange &, relation_trio) const
{
tree max = vrp_val_max (ptrdiff_type_node);
wide_int wmax
cfn_goacc_dim (bool is_pos) { m_is_pos = is_pos; }
using range_operator::fold_range;
virtual bool fold_range (irange &r, tree type, const irange &lh,
- const irange &, relation_kind) const
+ const irange &, relation_trio) const
{
tree axis_tree;
if (!lh.singleton_p (&axis_tree))
public:
using range_operator::fold_range;
virtual bool fold_range (irange &r, tree type, const irange &,
- const irange &, relation_kind) const
+ const irange &, relation_trio) const
{
r.set (build_zero_cst (type), build_one_cst (type));
return true;
tree operand2 () const { gcc_checking_assert (m_valid); return m_op2; }
bool calc_op1 (vrange &r, const vrange &lhs_range);
bool calc_op1 (vrange &r, const vrange &lhs_range, const vrange &op2_range,
- relation_kind k = VREL_VARYING);
+ relation_trio = TRIO_VARYING);
bool calc_op2 (vrange &r, const vrange &lhs_range, const vrange &op1_range,
- relation_kind k = VREL_VARYING);
+ relation_trio = TRIO_VARYING);
private:
void maybe_builtin_call ();
gimple *m_stmt;
tree type ATTRIBUTE_UNUSED,
const frange &lh ATTRIBUTE_UNUSED,
const frange &rh ATTRIBUTE_UNUSED,
- relation_kind rel ATTRIBUTE_UNUSED) const
+ relation_trio) const
{
return false;
}
tree type ATTRIBUTE_UNUSED,
const frange &lh ATTRIBUTE_UNUSED,
const irange &rh ATTRIBUTE_UNUSED,
- relation_kind rel ATTRIBUTE_UNUSED) const
+ relation_trio) const
{
return false;
}
tree type ATTRIBUTE_UNUSED,
const frange &lh ATTRIBUTE_UNUSED,
const frange &rh ATTRIBUTE_UNUSED,
- relation_kind rel ATTRIBUTE_UNUSED) const
+ relation_trio) const
{
return false;
}
tree type ATTRIBUTE_UNUSED,
const frange &lhs ATTRIBUTE_UNUSED,
const frange &op2 ATTRIBUTE_UNUSED,
- relation_kind rel ATTRIBUTE_UNUSED) const
+ relation_trio) const
{
return false;
}
tree type ATTRIBUTE_UNUSED,
const irange &lhs ATTRIBUTE_UNUSED,
const frange &op2 ATTRIBUTE_UNUSED,
- relation_kind rel ATTRIBUTE_UNUSED) const
+ relation_trio) const
{
return false;
}
tree type ATTRIBUTE_UNUSED,
const frange &lhs ATTRIBUTE_UNUSED,
const frange &op1 ATTRIBUTE_UNUSED,
- relation_kind rel ATTRIBUTE_UNUSED) const
+ relation_trio) const
{
return false;
}
tree type ATTRIBUTE_UNUSED,
const irange &lhs ATTRIBUTE_UNUSED,
const frange &op1 ATTRIBUTE_UNUSED,
- relation_kind rel ATTRIBUTE_UNUSED) const
+ relation_trio) const
{
return false;
}
inline bool
frelop_early_resolve (irange &r, tree type,
const frange &op1, const frange &op2,
- relation_kind rel, relation_kind my_rel)
+ relation_trio rel, relation_kind my_rel)
{
// If either operand is undefined, return VARYING.
if (empty_range_varying (r, type, op1, op2))
public:
bool fold_range (frange &r, tree type ATTRIBUTE_UNUSED,
const frange &op1, const frange &op2 ATTRIBUTE_UNUSED,
- relation_kind = VREL_VARYING) const final override
+ relation_trio = TRIO_VARYING) const final override
{
r = op1;
return true;
}
bool op1_range (frange &r, tree type ATTRIBUTE_UNUSED,
const frange &lhs, const frange &op2 ATTRIBUTE_UNUSED,
- relation_kind = VREL_VARYING) const final override
+ relation_trio = TRIO_VARYING) const final override
{
r = lhs;
return true;
public:
bool fold_range (irange &r, tree type,
const frange &op1, const frange &op2,
- relation_kind = VREL_VARYING) const final override;
+ relation_trio = TRIO_VARYING) const final override;
relation_kind op1_op2_relation (const irange &lhs) const final override
{
return equal_op1_op2_relation (lhs);
}
bool op1_range (frange &r, tree type,
const irange &lhs, const frange &op2,
- relation_kind = VREL_VARYING) const final override;
+ relation_trio = TRIO_VARYING) const final override;
bool op2_range (frange &r, tree type,
const irange &lhs, const frange &op1,
- relation_kind rel = VREL_VARYING) const final override
+ relation_trio rel = TRIO_VARYING) const final override
{
- return op1_range (r, type, lhs, op1, rel);
+ return op1_range (r, type, lhs, op1, rel.swap_op1_op2 ());
}
} fop_equal;
bool
foperator_equal::fold_range (irange &r, tree type,
const frange &op1, const frange &op2,
- relation_kind rel) const
+ relation_trio rel) const
{
if (frelop_early_resolve (r, type, op1, op2, rel, VREL_EQ))
return true;
foperator_equal::op1_range (frange &r, tree type,
const irange &lhs,
const frange &op2,
- relation_kind rel) const
+ relation_trio trio) const
{
+ relation_kind rel = trio.op1_op2 ();
switch (get_bool_state (r, lhs, type))
{
case BRS_TRUE:
public:
bool fold_range (irange &r, tree type,
const frange &op1, const frange &op2,
- relation_kind rel = VREL_VARYING) const final override;
+ relation_trio rel = TRIO_VARYING) const final override;
relation_kind op1_op2_relation (const irange &lhs) const final override
{
return not_equal_op1_op2_relation (lhs);
}
bool op1_range (frange &r, tree type,
const irange &lhs, const frange &op2,
- relation_kind = VREL_VARYING) const final override;
+ relation_trio = TRIO_VARYING) const final override;
} fop_not_equal;
bool
foperator_not_equal::fold_range (irange &r, tree type,
const frange &op1, const frange &op2,
- relation_kind rel) const
+ relation_trio rel) const
{
if (frelop_early_resolve (r, type, op1, op2, rel, VREL_NE))
return true;
foperator_not_equal::op1_range (frange &r, tree type,
const irange &lhs,
const frange &op2,
- relation_kind rel) const
+ relation_trio trio) const
{
+ relation_kind rel = trio.op1_op2 ();
switch (get_bool_state (r, lhs, type))
{
case BRS_TRUE:
public:
bool fold_range (irange &r, tree type,
const frange &op1, const frange &op2,
- relation_kind = VREL_VARYING) const final override;
+ relation_trio = TRIO_VARYING) const final override;
relation_kind op1_op2_relation (const irange &lhs) const final override
{
return lt_op1_op2_relation (lhs);
}
bool op1_range (frange &r, tree type,
const irange &lhs, const frange &op2,
- relation_kind = VREL_VARYING) const final override;
+ relation_trio = TRIO_VARYING) const final override;
bool op2_range (frange &r, tree type,
const irange &lhs, const frange &op1,
- relation_kind = VREL_VARYING) const final override;
+ relation_trio = TRIO_VARYING) const final override;
} fop_lt;
bool
foperator_lt::fold_range (irange &r, tree type,
const frange &op1, const frange &op2,
- relation_kind rel) const
+ relation_trio rel) const
{
if (frelop_early_resolve (r, type, op1, op2, rel, VREL_LT))
return true;
tree type,
const irange &lhs,
const frange &op2,
- relation_kind) const
+ relation_trio) const
{
switch (get_bool_state (r, lhs, type))
{
tree type,
const irange &lhs,
const frange &op1,
- relation_kind) const
+ relation_trio) const
{
switch (get_bool_state (r, lhs, type))
{
public:
bool fold_range (irange &r, tree type,
const frange &op1, const frange &op2,
- relation_kind rel = VREL_VARYING) const final override;
+ relation_trio rel = TRIO_VARYING) const final override;
relation_kind op1_op2_relation (const irange &lhs) const final override
{
return le_op1_op2_relation (lhs);
}
bool op1_range (frange &r, tree type,
const irange &lhs, const frange &op2,
- relation_kind rel = VREL_VARYING) const final override;
+ relation_trio rel = TRIO_VARYING) const final override;
bool op2_range (frange &r, tree type,
const irange &lhs, const frange &op1,
- relation_kind rel = VREL_VARYING) const final override;
+ relation_trio rel = TRIO_VARYING) const final override;
} fop_le;
bool
foperator_le::fold_range (irange &r, tree type,
const frange &op1, const frange &op2,
- relation_kind rel) const
+ relation_trio rel) const
{
if (frelop_early_resolve (r, type, op1, op2, rel, VREL_LE))
return true;
tree type,
const irange &lhs,
const frange &op2,
- relation_kind) const
+ relation_trio) const
{
switch (get_bool_state (r, lhs, type))
{
tree type,
const irange &lhs,
const frange &op1,
- relation_kind) const
+ relation_trio) const
{
switch (get_bool_state (r, lhs, type))
{
public:
bool fold_range (irange &r, tree type,
const frange &op1, const frange &op2,
- relation_kind = VREL_VARYING) const final override;
+ relation_trio = TRIO_VARYING) const final override;
relation_kind op1_op2_relation (const irange &lhs) const final override
{
return gt_op1_op2_relation (lhs);
}
bool op1_range (frange &r, tree type,
const irange &lhs, const frange &op2,
- relation_kind = VREL_VARYING) const final override;
+ relation_trio = TRIO_VARYING) const final override;
bool op2_range (frange &r, tree type,
const irange &lhs, const frange &op1,
- relation_kind = VREL_VARYING) const final override;
+ relation_trio = TRIO_VARYING) const final override;
} fop_gt;
bool
foperator_gt::fold_range (irange &r, tree type,
const frange &op1, const frange &op2,
- relation_kind rel) const
+ relation_trio rel) const
{
if (frelop_early_resolve (r, type, op1, op2, rel, VREL_GT))
return true;
tree type,
const irange &lhs,
const frange &op2,
- relation_kind) const
+ relation_trio) const
{
switch (get_bool_state (r, lhs, type))
{
tree type,
const irange &lhs,
const frange &op1,
- relation_kind) const
+ relation_trio) const
{
switch (get_bool_state (r, lhs, type))
{
public:
bool fold_range (irange &r, tree type,
const frange &op1, const frange &op2,
- relation_kind = VREL_VARYING) const final override;
+ relation_trio = TRIO_VARYING) const final override;
relation_kind op1_op2_relation (const irange &lhs) const final override
{
return ge_op1_op2_relation (lhs);
}
bool op1_range (frange &r, tree type,
const irange &lhs, const frange &op2,
- relation_kind = VREL_VARYING) const final override;
+ relation_trio = TRIO_VARYING) const final override;
bool op2_range (frange &r, tree type,
const irange &lhs, const frange &op1,
- relation_kind = VREL_VARYING) const final override;
+ relation_trio = TRIO_VARYING) const final override;
} fop_ge;
bool
foperator_ge::fold_range (irange &r, tree type,
const frange &op1, const frange &op2,
- relation_kind rel) const
+ relation_trio rel) const
{
if (frelop_early_resolve (r, type, op1, op2, rel, VREL_GE))
return true;
tree type,
const irange &lhs,
const frange &op2,
- relation_kind) const
+ relation_trio) const
{
switch (get_bool_state (r, lhs, type))
{
foperator_ge::op2_range (frange &r, tree type,
const irange &lhs,
const frange &op1,
- relation_kind) const
+ relation_trio) const
{
switch (get_bool_state (r, lhs, type))
{
public:
bool fold_range (irange &r, tree type,
const frange &op1, const frange &op2,
- relation_kind = VREL_VARYING) const final override;
+ relation_trio = TRIO_VARYING) const final override;
bool op1_range (frange &r, tree type,
const irange &lhs, const frange &op2,
- relation_kind = VREL_VARYING) const final override;
+ relation_trio = TRIO_VARYING) const final override;
bool op2_range (frange &r, tree type,
const irange &lhs, const frange &op1,
- relation_kind rel = VREL_VARYING) const final override
+ relation_trio rel = TRIO_VARYING) const final override
{
- return op1_range (r, type, lhs, op1, rel);
+ return op1_range (r, type, lhs, op1, rel.swap_op1_op2 ());
}
} fop_unordered;
bool
foperator_unordered::fold_range (irange &r, tree type,
const frange &op1, const frange &op2,
- relation_kind) const
+ relation_trio) const
{
// UNORDERED is TRUE if either operand is a NAN.
if (op1.known_isnan () || op2.known_isnan ())
foperator_unordered::op1_range (frange &r, tree type,
const irange &lhs,
const frange &op2,
- relation_kind rel) const
+ relation_trio trio) const
{
+ relation_kind rel = trio.op1_op2 ();
switch (get_bool_state (r, lhs, type))
{
case BRS_TRUE:
public:
bool fold_range (irange &r, tree type,
const frange &op1, const frange &op2,
- relation_kind = VREL_VARYING) const final override;
+ relation_trio = TRIO_VARYING) const final override;
bool op1_range (frange &r, tree type,
const irange &lhs, const frange &op2,
- relation_kind = VREL_VARYING) const final override;
+ relation_trio = TRIO_VARYING) const final override;
bool op2_range (frange &r, tree type,
const irange &lhs, const frange &op1,
- relation_kind rel = VREL_VARYING) const final override
+ relation_trio rel = TRIO_VARYING) const final override
{
- return op1_range (r, type, lhs, op1, rel);
+ return op1_range (r, type, lhs, op1, rel.swap_op1_op2 ());
}
} fop_ordered;
bool
foperator_ordered::fold_range (irange &r, tree type,
const frange &op1, const frange &op2,
- relation_kind) const
+ relation_trio) const
{
if (op1.known_isnan () || op2.known_isnan ())
r = range_false (type);
foperator_ordered::op1_range (frange &r, tree type,
const irange &lhs,
const frange &op2,
- relation_kind rel) const
+ relation_trio trio) const
{
+ relation_kind rel = trio.op1_op2 ();
switch (get_bool_state (r, lhs, type))
{
case BRS_TRUE:
public:
bool fold_range (frange &r, tree type,
const frange &op1, const frange &op2,
- relation_kind = VREL_VARYING) const final override
+ relation_trio = TRIO_VARYING) const final override
{
if (empty_range_varying (r, type, op1, op2))
return true;
}
bool op1_range (frange &r, tree type,
const frange &lhs, const frange &op2,
- relation_kind rel = VREL_VARYING) const final override
+ relation_trio rel = TRIO_VARYING) const final override
{
return fold_range (r, type, lhs, op2, rel);
}
public:
bool fold_range (frange &r, tree type,
const frange &op1, const frange &,
- relation_kind = VREL_VARYING) const final override;
+ relation_trio = TRIO_VARYING) const final override;
bool op1_range (frange &r, tree type,
const frange &lhs, const frange &op2,
- relation_kind rel = VREL_VARYING) const final override;
+ relation_trio rel = TRIO_VARYING) const final override;
} fop_abs;
bool
foperator_abs::fold_range (frange &r, tree type,
const frange &op1, const frange &op2,
- relation_kind) const
+ relation_trio) const
{
if (empty_range_varying (r, type, op1, op2))
return true;
bool
foperator_abs::op1_range (frange &r, tree type,
const frange &lhs, const frange &op2,
- relation_kind) const
+ relation_trio) const
{
if (empty_range_varying (r, type, lhs, op2))
return true;
public:
bool fold_range (irange &r, tree type,
const frange &op1, const frange &op2,
- relation_kind rel = VREL_VARYING) const final override
+ relation_trio rel = TRIO_VARYING) const final override
{
if (op1.known_isnan () || op2.known_isnan ())
{
public:
bool fold_range (irange &r, tree type,
const frange &op1, const frange &op2,
- relation_kind rel = VREL_VARYING) const final override
+ relation_trio rel = TRIO_VARYING) const final override
{
if (op1.known_isnan () || op2.known_isnan ())
{
}
bool op1_range (frange &r, tree type,
const irange &lhs, const frange &op2,
- relation_kind = VREL_VARYING) const final override;
+ relation_trio = TRIO_VARYING) const final override;
bool op2_range (frange &r, tree type,
const irange &lhs, const frange &op1,
- relation_kind = VREL_VARYING) const final override;
+ relation_trio = TRIO_VARYING) const final override;
} fop_unordered_le;
bool
foperator_unordered_le::op1_range (frange &r, tree type,
const irange &lhs, const frange &op2,
- relation_kind) const
+ relation_trio) const
{
switch (get_bool_state (r, lhs, type))
{
tree type,
const irange &lhs,
const frange &op1,
- relation_kind) const
+ relation_trio) const
{
switch (get_bool_state (r, lhs, type))
{
public:
bool fold_range (irange &r, tree type,
const frange &op1, const frange &op2,
- relation_kind rel = VREL_VARYING) const final override
+ relation_trio rel = TRIO_VARYING) const final override
{
if (op1.known_isnan () || op2.known_isnan ())
{
}
bool op1_range (frange &r, tree type,
const irange &lhs, const frange &op2,
- relation_kind = VREL_VARYING) const final override;
+ relation_trio = TRIO_VARYING) const final override;
bool op2_range (frange &r, tree type,
const irange &lhs, const frange &op1,
- relation_kind = VREL_VARYING) const final override;
+ relation_trio = TRIO_VARYING) const final override;
} fop_unordered_gt;
bool
tree type,
const irange &lhs,
const frange &op2,
- relation_kind) const
+ relation_trio) const
{
switch (get_bool_state (r, lhs, type))
{
tree type,
const irange &lhs,
const frange &op1,
- relation_kind) const
+ relation_trio) const
{
switch (get_bool_state (r, lhs, type))
{
public:
bool fold_range (irange &r, tree type,
const frange &op1, const frange &op2,
- relation_kind rel = VREL_VARYING) const final override
+ relation_trio rel = TRIO_VARYING) const final override
{
if (op1.known_isnan () || op2.known_isnan ())
{
}
bool op1_range (frange &r, tree type,
const irange &lhs, const frange &op2,
- relation_kind = VREL_VARYING) const final override;
+ relation_trio = TRIO_VARYING) const final override;
bool op2_range (frange &r, tree type,
const irange &lhs, const frange &op1,
- relation_kind = VREL_VARYING) const final override;
+ relation_trio = TRIO_VARYING) const final override;
} fop_unordered_ge;
bool
tree type,
const irange &lhs,
const frange &op2,
- relation_kind) const
+ relation_trio) const
{
switch (get_bool_state (r, lhs, type))
{
foperator_unordered_ge::op2_range (frange &r, tree type,
const irange &lhs,
const frange &op1,
- relation_kind) const
+ relation_trio) const
{
switch (get_bool_state (r, lhs, type))
{
public:
bool fold_range (irange &r, tree type,
const frange &op1, const frange &op2,
- relation_kind rel = VREL_VARYING) const final override
+ relation_trio rel = TRIO_VARYING) const final override
{
if (op1.known_isnan () || op2.known_isnan ())
{
}
bool op1_range (frange &r, tree type,
const irange &lhs, const frange &op2,
- relation_kind = VREL_VARYING) const final override;
+ relation_trio = TRIO_VARYING) const final override;
bool op2_range (frange &r, tree type,
const irange &lhs, const frange &op1,
- relation_kind rel = VREL_VARYING) const final override
+ relation_trio rel = TRIO_VARYING) const final override
{
- return op1_range (r, type, lhs, op1, rel);
+ return op1_range (r, type, lhs, op1, rel.swap_op1_op2 ());
}
} fop_unordered_equal;
foperator_unordered_equal::op1_range (frange &r, tree type,
const irange &lhs,
const frange &op2,
- relation_kind) const
+ relation_trio) const
{
switch (get_bool_state (r, lhs, type))
{
range_operator::fold_range (irange &r, tree type,
const irange &lh,
const irange &rh,
- relation_kind rel) const
+ relation_trio trio) const
{
gcc_checking_assert (r.supports_type_p (type));
if (empty_range_varying (r, type, lh, rh))
return true;
+ relation_kind rel = trio.op1_op2 ();
unsigned num_lh = lh.num_pairs ();
unsigned num_rh = rh.num_pairs ();
tree type ATTRIBUTE_UNUSED,
const irange &lhs ATTRIBUTE_UNUSED,
const irange &op2 ATTRIBUTE_UNUSED,
- relation_kind rel ATTRIBUTE_UNUSED) const
+ relation_trio) const
{
return false;
}
tree type ATTRIBUTE_UNUSED,
const irange &lhs ATTRIBUTE_UNUSED,
const irange &op1 ATTRIBUTE_UNUSED,
- relation_kind rel ATTRIBUTE_UNUSED) const
+ relation_trio) const
{
return false;
}
virtual bool fold_range (irange &r, tree type,
const irange &op1,
const irange &op2,
- relation_kind rel = VREL_VARYING) const;
+ relation_trio = TRIO_VARYING) const;
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
const irange &val,
- relation_kind rel = VREL_VARYING) const;
+ relation_trio = TRIO_VARYING) const;
virtual bool op2_range (irange &r, tree type,
const irange &lhs,
const irange &val,
- relation_kind rel = VREL_VARYING) const;
+ relation_trio = TRIO_VARYING) const;
virtual relation_kind op1_op2_relation (const irange &lhs) const;
} op_equal;
operator_equal::fold_range (irange &r, tree type,
const irange &op1,
const irange &op2,
- relation_kind rel) const
+ relation_trio rel) const
{
if (relop_early_resolve (r, type, op1, op2, rel, VREL_EQ))
return true;
operator_equal::op1_range (irange &r, tree type,
const irange &lhs,
const irange &op2,
- relation_kind rel ATTRIBUTE_UNUSED) const
+ relation_trio) const
{
switch (get_bool_state (r, lhs, type))
{
operator_equal::op2_range (irange &r, tree type,
const irange &lhs,
const irange &op1,
- relation_kind rel) const
+ relation_trio rel) const
{
- return operator_equal::op1_range (r, type, lhs, op1, rel);
+ return operator_equal::op1_range (r, type, lhs, op1, rel.swap_op1_op2 ());
}
class operator_not_equal : public range_operator
virtual bool fold_range (irange &r, tree type,
const irange &op1,
const irange &op2,
- relation_kind rel = VREL_VARYING) const;
+ relation_trio = TRIO_VARYING) const;
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
const irange &op2,
- relation_kind rel = VREL_VARYING) const;
+ relation_trio = TRIO_VARYING) const;
virtual bool op2_range (irange &r, tree type,
const irange &lhs,
const irange &op1,
- relation_kind rel = VREL_VARYING) const;
+ relation_trio = TRIO_VARYING) const;
virtual relation_kind op1_op2_relation (const irange &lhs) const;
} op_not_equal;
operator_not_equal::fold_range (irange &r, tree type,
const irange &op1,
const irange &op2,
- relation_kind rel) const
+ relation_trio rel) const
{
if (relop_early_resolve (r, type, op1, op2, rel, VREL_NE))
return true;
operator_not_equal::op1_range (irange &r, tree type,
const irange &lhs,
const irange &op2,
- relation_kind rel ATTRIBUTE_UNUSED) const
+ relation_trio) const
{
switch (get_bool_state (r, lhs, type))
{
operator_not_equal::op2_range (irange &r, tree type,
const irange &lhs,
const irange &op1,
- relation_kind rel) const
+ relation_trio rel) const
{
- return operator_not_equal::op1_range (r, type, lhs, op1, rel);
+ return operator_not_equal::op1_range (r, type, lhs, op1, rel.swap_op1_op2 ());
}
// (X < VAL) produces the range of [MIN, VAL - 1].
virtual bool fold_range (irange &r, tree type,
const irange &op1,
const irange &op2,
- relation_kind rel = VREL_VARYING) const;
+ relation_trio = TRIO_VARYING) const;
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
const irange &op2,
- relation_kind rel = VREL_VARYING) const;
+ relation_trio = TRIO_VARYING) const;
virtual bool op2_range (irange &r, tree type,
const irange &lhs,
const irange &op1,
- relation_kind rel = VREL_VARYING) const;
+ relation_trio = TRIO_VARYING) const;
virtual relation_kind op1_op2_relation (const irange &lhs) const;
} op_lt;
operator_lt::fold_range (irange &r, tree type,
const irange &op1,
const irange &op2,
- relation_kind rel) const
+ relation_trio rel) const
{
if (relop_early_resolve (r, type, op1, op2, rel, VREL_LT))
return true;
operator_lt::op1_range (irange &r, tree type,
const irange &lhs,
const irange &op2,
- relation_kind rel ATTRIBUTE_UNUSED) const
+ relation_trio) const
{
switch (get_bool_state (r, lhs, type))
{
operator_lt::op2_range (irange &r, tree type,
const irange &lhs,
const irange &op1,
- relation_kind rel ATTRIBUTE_UNUSED) const
+ relation_trio) const
{
switch (get_bool_state (r, lhs, type))
{
virtual bool fold_range (irange &r, tree type,
const irange &op1,
const irange &op2,
- relation_kind rel = VREL_VARYING) const;
+ relation_trio = TRIO_VARYING) const;
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
const irange &op2,
- relation_kind rel = VREL_VARYING) const;
+ relation_trio = TRIO_VARYING) const;
virtual bool op2_range (irange &r, tree type,
const irange &lhs,
const irange &op1,
- relation_kind rel = VREL_VARYING) const;
+ relation_trio = TRIO_VARYING) const;
virtual relation_kind op1_op2_relation (const irange &lhs) const;
} op_le;
operator_le::fold_range (irange &r, tree type,
const irange &op1,
const irange &op2,
- relation_kind rel) const
+ relation_trio rel) const
{
if (relop_early_resolve (r, type, op1, op2, rel, VREL_LE))
return true;
operator_le::op1_range (irange &r, tree type,
const irange &lhs,
const irange &op2,
- relation_kind rel ATTRIBUTE_UNUSED) const
+ relation_trio) const
{
switch (get_bool_state (r, lhs, type))
{
operator_le::op2_range (irange &r, tree type,
const irange &lhs,
const irange &op1,
- relation_kind rel ATTRIBUTE_UNUSED) const
+ relation_trio) const
{
switch (get_bool_state (r, lhs, type))
{
virtual bool fold_range (irange &r, tree type,
const irange &op1,
const irange &op2,
- relation_kind rel = VREL_VARYING) const;
+ relation_trio = TRIO_VARYING) const;
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
const irange &op2,
- relation_kind rel = VREL_VARYING) const;
+ relation_trio = TRIO_VARYING) const;
virtual bool op2_range (irange &r, tree type,
const irange &lhs,
const irange &op1,
- relation_kind rel = VREL_VARYING) const;
+ relation_trio = TRIO_VARYING) const;
virtual relation_kind op1_op2_relation (const irange &lhs) const;
} op_gt;
bool
operator_gt::fold_range (irange &r, tree type,
const irange &op1, const irange &op2,
- relation_kind rel) const
+ relation_trio rel) const
{
if (relop_early_resolve (r, type, op1, op2, rel, VREL_GT))
return true;
bool
operator_gt::op1_range (irange &r, tree type,
const irange &lhs, const irange &op2,
- relation_kind rel ATTRIBUTE_UNUSED) const
+ relation_trio) const
{
switch (get_bool_state (r, lhs, type))
{
operator_gt::op2_range (irange &r, tree type,
const irange &lhs,
const irange &op1,
- relation_kind rel ATTRIBUTE_UNUSED) const
+ relation_trio) const
{
switch (get_bool_state (r, lhs, type))
{
virtual bool fold_range (irange &r, tree type,
const irange &op1,
const irange &op2,
- relation_kind rel = VREL_VARYING) const;
+ relation_trio = TRIO_VARYING) const;
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
const irange &op2,
- relation_kind rel = VREL_VARYING) const;
+ relation_trio = TRIO_VARYING) const;
virtual bool op2_range (irange &r, tree type,
const irange &lhs,
const irange &op1,
- relation_kind rel = VREL_VARYING) const;
+ relation_trio = TRIO_VARYING) const;
virtual relation_kind op1_op2_relation (const irange &lhs) const;
} op_ge;
operator_ge::fold_range (irange &r, tree type,
const irange &op1,
const irange &op2,
- relation_kind rel) const
+ relation_trio rel) const
{
if (relop_early_resolve (r, type, op1, op2, rel, VREL_GE))
return true;
operator_ge::op1_range (irange &r, tree type,
const irange &lhs,
const irange &op2,
- relation_kind rel ATTRIBUTE_UNUSED) const
+ relation_trio) const
{
switch (get_bool_state (r, lhs, type))
{
operator_ge::op2_range (irange &r, tree type,
const irange &lhs,
const irange &op1,
- relation_kind rel ATTRIBUTE_UNUSED) const
+ relation_trio) const
{
switch (get_bool_state (r, lhs, type))
{
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
const irange &op2,
- relation_kind rel ATTRIBUTE_UNUSED) const;
+ relation_trio) const;
virtual bool op2_range (irange &r, tree type,
const irange &lhs,
const irange &op1,
- relation_kind rel ATTRIBUTE_UNUSED) const;
+ relation_trio) const;
virtual void wi_fold (irange &r, tree type,
const wide_int &lh_lb,
const wide_int &lh_ub,
operator_plus::op1_range (irange &r, tree type,
const irange &lhs,
const irange &op2,
- relation_kind rel) const
+ relation_trio trio) const
{
if (lhs.undefined_p ())
return false;
if (!minus)
return false;
bool res = minus.fold_range (r, type, lhs, op2);
+ relation_kind rel = trio.lhs_op2 ();
// Check for a relation refinement.
if (res)
adjust_op1_for_overflow (r, op2, rel, true /* PLUS_EXPR */);
operator_plus::op2_range (irange &r, tree type,
const irange &lhs,
const irange &op1,
- relation_kind rel) const
+ relation_trio rel) const
{
- return op1_range (r, type, lhs, op1, rel);
+ return op1_range (r, type, lhs, op1, rel.swap_op1_op2 ());
}
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
const irange &op2,
- relation_kind rel ATTRIBUTE_UNUSED) const;
+ relation_trio) const;
virtual bool op2_range (irange &r, tree type,
const irange &lhs,
const irange &op1,
- relation_kind rel ATTRIBUTE_UNUSED) const;
+ relation_trio) const;
virtual void wi_fold (irange &r, tree type,
const wide_int &lh_lb,
const wide_int &lh_ub,
operator_minus::op1_range (irange &r, tree type,
const irange &lhs,
const irange &op2,
- relation_kind rel ATTRIBUTE_UNUSED) const
+ relation_trio trio) const
{
if (lhs.undefined_p ())
return false;
if (!minus)
return false;
bool res = minus.fold_range (r, type, lhs, op2);
+ relation_kind rel = trio.lhs_op2 ();
if (res)
adjust_op1_for_overflow (r, op2, rel, false /* PLUS_EXPR */);
return res;
operator_minus::op2_range (irange &r, tree type,
const irange &lhs,
const irange &op1,
- relation_kind rel ATTRIBUTE_UNUSED) const
+ relation_trio) const
{
if (lhs.undefined_p ())
return false;
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
const irange &op2,
- relation_kind rel ATTRIBUTE_UNUSED) const;
+ relation_trio) const;
virtual bool op2_range (irange &r, tree type,
const irange &lhs,
const irange &op1,
- relation_kind rel ATTRIBUTE_UNUSED) const;
+ relation_trio) const;
} op_mult;
bool
operator_mult::op1_range (irange &r, tree type,
const irange &lhs, const irange &op2,
- relation_kind rel ATTRIBUTE_UNUSED) const
+ relation_trio) const
{
tree offset;
if (lhs.undefined_p ())
bool
operator_mult::op2_range (irange &r, tree type,
const irange &lhs, const irange &op1,
- relation_kind rel) const
+ relation_trio rel) const
{
- return operator_mult::op1_range (r, type, lhs, op1, rel);
+ return operator_mult::op1_range (r, type, lhs, op1, rel.swap_op1_op2 ());
}
bool
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
const irange &op2,
- relation_kind rel ATTRIBUTE_UNUSED) const;
+ relation_trio) const;
} op_exact_div;
operator_exact_divide::op1_range (irange &r, tree type,
const irange &lhs,
const irange &op2,
- relation_kind rel ATTRIBUTE_UNUSED) const
+ relation_trio) const
{
if (lhs.undefined_p ())
return false;
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
const irange &op2,
- relation_kind rel = VREL_VARYING) const;
+ relation_trio rel = TRIO_VARYING) const;
virtual bool fold_range (irange &r, tree type,
const irange &op1,
const irange &op2,
- relation_kind rel = VREL_VARYING) const;
+ relation_trio rel = TRIO_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_VARYING) const;
+ relation_trio rel = TRIO_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_VARYING) const;
+ relation_trio rel = TRIO_VARYING) const;
virtual relation_kind lhs_op1_relation (const irange &lhs,
const irange &op1,
const irange &op2,
operator_lshift::fold_range (irange &r, tree type,
const irange &op1,
const irange &op2,
- relation_kind rel) const
+ relation_trio rel) const
{
int_range_max shift_range;
if (!get_shift_range (shift_range, type, op2))
tree type,
const irange &lhs,
const irange &op2,
- relation_kind rel ATTRIBUTE_UNUSED) const
+ relation_trio) const
{
if (lhs.undefined_p ())
return false;
tree type,
const irange &lhs,
const irange &op2,
- relation_kind rel ATTRIBUTE_UNUSED) const
+ relation_trio) const
{
tree shift;
if (lhs.undefined_p ())
operator_rshift::fold_range (irange &r, tree type,
const irange &op1,
const irange &op2,
- relation_kind rel) const
+ relation_trio rel) const
{
int_range_max shift;
if (!get_shift_range (shift, type, op2))
virtual bool fold_range (irange &r, tree type,
const irange &op1,
const irange &op2,
- relation_kind rel = VREL_VARYING) const;
+ relation_trio rel = TRIO_VARYING) const;
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
const irange &op2,
- relation_kind rel = VREL_VARYING) const;
+ relation_trio rel = TRIO_VARYING) const;
virtual relation_kind lhs_op1_relation (const irange &lhs,
const irange &op1,
const irange &op2,
operator_cast::fold_range (irange &r, tree type ATTRIBUTE_UNUSED,
const irange &inner,
const irange &outer,
- relation_kind rel ATTRIBUTE_UNUSED) const
+ relation_trio) const
{
if (empty_range_varying (r, type, inner, outer))
return true;
operator_cast::op1_range (irange &r, tree type,
const irange &lhs,
const irange &op2,
- relation_kind rel ATTRIBUTE_UNUSED) const
+ relation_trio) const
{
if (lhs.undefined_p ())
return false;
virtual bool fold_range (irange &r, tree type,
const irange &lh,
const irange &rh,
- relation_kind rel = VREL_VARYING) const;
+ relation_trio rel = TRIO_VARYING) const;
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
const irange &op2,
- relation_kind rel = VREL_VARYING) const;
+ relation_trio rel = TRIO_VARYING) const;
virtual bool op2_range (irange &r, tree type,
const irange &lhs,
const irange &op1,
- relation_kind rel = VREL_VARYING) const;
+ relation_trio rel = TRIO_VARYING) const;
} op_logical_and;
operator_logical_and::fold_range (irange &r, tree type,
const irange &lh,
const irange &rh,
- relation_kind rel ATTRIBUTE_UNUSED) const
+ relation_trio) const
{
if (empty_range_varying (r, type, lh, rh))
return true;
operator_logical_and::op1_range (irange &r, tree type,
const irange &lhs,
const irange &op2 ATTRIBUTE_UNUSED,
- relation_kind rel ATTRIBUTE_UNUSED) const
+ relation_trio) const
{
switch (get_bool_state (r, lhs, type))
{
operator_logical_and::op2_range (irange &r, tree type,
const irange &lhs,
const irange &op1,
- relation_kind rel ATTRIBUTE_UNUSED) const
+ relation_trio) const
{
return operator_logical_and::op1_range (r, type, lhs, op1);
}
virtual bool fold_range (irange &r, tree type,
const irange &lh,
const irange &rh,
- relation_kind rel = VREL_VARYING) const;
+ relation_trio rel = TRIO_VARYING) const;
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
const irange &op2,
- relation_kind rel = VREL_VARYING) const;
+ relation_trio rel = TRIO_VARYING) const;
virtual bool op2_range (irange &r, tree type,
const irange &lhs,
const irange &op1,
- relation_kind rel = VREL_VARYING) const;
+ relation_trio rel = TRIO_VARYING) const;
virtual void wi_fold (irange &r, tree type,
const wide_int &lh_lb,
const wide_int &lh_ub,
operator_bitwise_and::fold_range (irange &r, tree type,
const irange &lh,
const irange &rh,
- relation_kind rel ATTRIBUTE_UNUSED) const
+ relation_trio) const
{
if (range_operator::fold_range (r, type, lh, rh))
{
operator_bitwise_and::op1_range (irange &r, tree type,
const irange &lhs,
const irange &op2,
- relation_kind rel ATTRIBUTE_UNUSED) const
+ relation_trio) const
{
if (lhs.undefined_p ())
return false;
operator_bitwise_and::op2_range (irange &r, tree type,
const irange &lhs,
const irange &op1,
- relation_kind rel ATTRIBUTE_UNUSED) const
+ relation_trio) const
{
return operator_bitwise_and::op1_range (r, type, lhs, op1);
}
virtual bool fold_range (irange &r, tree type,
const irange &lh,
const irange &rh,
- relation_kind rel = VREL_VARYING) const;
+ relation_trio rel = TRIO_VARYING) const;
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
const irange &op2,
- relation_kind rel = VREL_VARYING) const;
+ relation_trio rel = TRIO_VARYING) const;
virtual bool op2_range (irange &r, tree type,
const irange &lhs,
const irange &op1,
- relation_kind rel = VREL_VARYING) const;
+ relation_trio rel = TRIO_VARYING) const;
} op_logical_or;
bool
operator_logical_or::fold_range (irange &r, tree type ATTRIBUTE_UNUSED,
const irange &lh,
const irange &rh,
- relation_kind rel ATTRIBUTE_UNUSED) const
+ relation_trio) const
{
if (empty_range_varying (r, type, lh, rh))
return true;
operator_logical_or::op1_range (irange &r, tree type,
const irange &lhs,
const irange &op2 ATTRIBUTE_UNUSED,
- relation_kind rel ATTRIBUTE_UNUSED) const
+ relation_trio) const
{
switch (get_bool_state (r, lhs, type))
{
operator_logical_or::op2_range (irange &r, tree type,
const irange &lhs,
const irange &op1,
- relation_kind rel ATTRIBUTE_UNUSED) const
+ relation_trio) const
{
return operator_logical_or::op1_range (r, type, lhs, op1);
}
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
const irange &op2,
- relation_kind rel = VREL_VARYING) const;
+ relation_trio rel = TRIO_VARYING) const;
virtual bool op2_range (irange &r, tree type,
const irange &lhs,
const irange &op1,
- relation_kind rel= VREL_VARYING) const;
+ relation_trio rel = TRIO_VARYING) const;
virtual void wi_fold (irange &r, tree type,
const wide_int &lh_lb,
const wide_int &lh_ub,
operator_bitwise_or::op1_range (irange &r, tree type,
const irange &lhs,
const irange &op2,
- relation_kind rel ATTRIBUTE_UNUSED) const
+ relation_trio) const
{
if (lhs.undefined_p ())
return false;
operator_bitwise_or::op2_range (irange &r, tree type,
const irange &lhs,
const irange &op1,
- relation_kind rel ATTRIBUTE_UNUSED) const
+ relation_trio) const
{
return operator_bitwise_or::op1_range (r, type, lhs, op1);
}
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
const irange &op2,
- relation_kind rel = VREL_VARYING) const;
+ relation_trio rel = TRIO_VARYING) const;
virtual bool op2_range (irange &r, tree type,
const irange &lhs,
const irange &op1,
- relation_kind rel = VREL_VARYING) const;
+ relation_trio rel = TRIO_VARYING) const;
virtual bool op1_op2_relation_effect (irange &lhs_range,
tree type,
const irange &op1_range,
operator_bitwise_xor::op1_range (irange &r, tree type,
const irange &lhs,
const irange &op2,
- relation_kind rel ATTRIBUTE_UNUSED) const
+ relation_trio) const
{
if (lhs.undefined_p () || lhs.varying_p ())
{
operator_bitwise_xor::op2_range (irange &r, tree type,
const irange &lhs,
const irange &op1,
- relation_kind rel ATTRIBUTE_UNUSED) const
+ relation_trio) const
{
return operator_bitwise_xor::op1_range (r, type, lhs, op1);
}
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
const irange &op2,
- relation_kind rel ATTRIBUTE_UNUSED) const;
+ relation_trio) const;
virtual bool op2_range (irange &r, tree type,
const irange &lhs,
const irange &op1,
- relation_kind rel ATTRIBUTE_UNUSED) const;
+ relation_trio) const;
} op_trunc_mod;
void
operator_trunc_mod::op1_range (irange &r, tree type,
const irange &lhs,
const irange &,
- relation_kind rel ATTRIBUTE_UNUSED) const
+ relation_trio) const
{
if (lhs.undefined_p ())
return false;
operator_trunc_mod::op2_range (irange &r, tree type,
const irange &lhs,
const irange &,
- relation_kind rel ATTRIBUTE_UNUSED) const
+ relation_trio) const
{
if (lhs.undefined_p ())
return false;
virtual bool fold_range (irange &r, tree type,
const irange &lh,
const irange &rh,
- relation_kind rel = VREL_VARYING) const;
+ relation_trio rel = TRIO_VARYING) const;
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
const irange &op2,
- relation_kind rel = VREL_VARYING) const;
+ relation_trio rel = TRIO_VARYING) const;
} op_logical_not;
// Folding a logical NOT, oddly enough, involves doing nothing on the
operator_logical_not::fold_range (irange &r, tree type,
const irange &lh,
const irange &rh ATTRIBUTE_UNUSED,
- relation_kind rel ATTRIBUTE_UNUSED) const
+ relation_trio) const
{
if (empty_range_varying (r, type, lh, rh))
return true;
tree type,
const irange &lhs,
const irange &op2,
- relation_kind rel ATTRIBUTE_UNUSED) const
+ relation_trio) const
{
// Logical NOT is involutary...do it again.
return fold_range (r, type, lhs, op2);
virtual bool fold_range (irange &r, tree type,
const irange &lh,
const irange &rh,
- relation_kind rel = VREL_VARYING) const;
+ relation_trio rel = TRIO_VARYING) const;
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
const irange &op2,
- relation_kind rel = VREL_VARYING) const;
+ relation_trio rel = TRIO_VARYING) const;
} op_bitwise_not;
bool
operator_bitwise_not::fold_range (irange &r, tree type,
const irange &lh,
const irange &rh,
- relation_kind rel ATTRIBUTE_UNUSED) const
+ relation_trio) const
{
if (empty_range_varying (r, type, lh, rh))
return true;
operator_bitwise_not::op1_range (irange &r, tree type,
const irange &lhs,
const irange &op2,
- relation_kind rel ATTRIBUTE_UNUSED) const
+ relation_trio) const
{
if (lhs.undefined_p ())
return false;
virtual bool fold_range (irange &r, tree type,
const irange &op1,
const irange &op2,
- relation_kind rel = VREL_VARYING) const;
+ relation_trio rel = TRIO_VARYING) const;
} op_integer_cst;
bool
operator_cst::fold_range (irange &r, tree type ATTRIBUTE_UNUSED,
const irange &lh,
const irange &rh ATTRIBUTE_UNUSED,
- relation_kind rel ATTRIBUTE_UNUSED) const
+ relation_trio) const
{
r = lh;
return true;
virtual bool fold_range (irange &r, tree type,
const irange &op1,
const irange &op2,
- relation_kind rel = VREL_VARYING) const;
+ relation_trio rel = TRIO_VARYING) const;
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
const irange &op2,
- relation_kind rel = VREL_VARYING) const;
+ relation_trio rel = TRIO_VARYING) const;
virtual relation_kind lhs_op1_relation (const irange &lhs,
const irange &op1,
const irange &op2,
operator_identity::fold_range (irange &r, tree type ATTRIBUTE_UNUSED,
const irange &lh,
const irange &rh ATTRIBUTE_UNUSED,
- relation_kind rel ATTRIBUTE_UNUSED) const
+ relation_trio) const
{
r = lh;
return true;
operator_identity::op1_range (irange &r, tree type ATTRIBUTE_UNUSED,
const irange &lhs,
const irange &op2 ATTRIBUTE_UNUSED,
- relation_kind rel ATTRIBUTE_UNUSED) const
+ relation_trio) const
{
r = lhs;
return true;
virtual bool fold_range (irange &r, tree type,
const irange &op1,
const irange &op2,
- relation_kind rel = VREL_VARYING) const;
+ relation_trio rel = TRIO_VARYING) const;
} op_unknown;
bool
operator_unknown::fold_range (irange &r, tree type,
const irange &lh ATTRIBUTE_UNUSED,
const irange &rh ATTRIBUTE_UNUSED,
- relation_kind rel ATTRIBUTE_UNUSED) const
+ relation_trio) const
{
r.set_varying (type);
return true;
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
const irange &op2,
- relation_kind rel ATTRIBUTE_UNUSED) const;
+ relation_trio) const;
} op_abs;
void
operator_abs::op1_range (irange &r, tree type,
const irange &lhs,
const irange &op2,
- relation_kind rel ATTRIBUTE_UNUSED) const
+ relation_trio) const
{
if (empty_range_varying (r, type, lhs, op2))
return true;
virtual bool fold_range (irange &r, tree type,
const irange &op1,
const irange &op2,
- relation_kind rel = VREL_VARYING) const;
+ relation_trio rel = TRIO_VARYING) const;
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
const irange &op2,
- relation_kind rel = VREL_VARYING) const;
+ relation_trio rel = TRIO_VARYING) const;
} op_negate;
bool
operator_negate::fold_range (irange &r, tree type,
const irange &lh,
const irange &rh,
- relation_kind rel ATTRIBUTE_UNUSED) const
+ relation_trio) const
{
if (empty_range_varying (r, type, lh, rh))
return true;
operator_negate::op1_range (irange &r, tree type,
const irange &lhs,
const irange &op2,
- relation_kind rel ATTRIBUTE_UNUSED) const
+ relation_trio) const
{
// NEGATE is involutory.
return fold_range (r, type, lhs, op2);
virtual bool fold_range (irange &r, tree type,
const irange &op1,
const irange &op2,
- relation_kind rel = VREL_VARYING) const;
+ relation_trio rel = TRIO_VARYING) const;
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
const irange &op2,
- relation_kind rel = VREL_VARYING) const;
+ relation_trio rel = TRIO_VARYING) const;
} op_addr;
bool
operator_addr_expr::fold_range (irange &r, tree type,
const irange &lh,
const irange &rh,
- relation_kind rel ATTRIBUTE_UNUSED) const
+ relation_trio) const
{
if (empty_range_varying (r, type, lh, rh))
return true;
operator_addr_expr::op1_range (irange &r, tree type,
const irange &lhs,
const irange &op2,
- relation_kind rel ATTRIBUTE_UNUSED) const
+ relation_trio) const
{
return operator_addr_expr::fold_range (r, type, lhs, op2);
}
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
const irange &op2,
- relation_kind rel = VREL_VARYING) const;
+ relation_trio rel = TRIO_VARYING) const;
virtual bool op2_range (irange &r, tree type,
const irange &lhs,
const irange &op1,
- relation_kind rel = VREL_VARYING) const;
+ relation_trio rel = TRIO_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;
pointer_or_operator::op1_range (irange &r, tree type,
const irange &lhs,
const irange &op2 ATTRIBUTE_UNUSED,
- relation_kind rel ATTRIBUTE_UNUSED) const
+ relation_trio) const
{
if (lhs.undefined_p ())
return false;
pointer_or_operator::op2_range (irange &r, tree type,
const irange &lhs,
const irange &op1,
- relation_kind rel ATTRIBUTE_UNUSED) const
+ relation_trio) const
{
return pointer_or_operator::op1_range (r, type, lhs, op1);
}
range_op_handler::fold_range (vrange &r, tree type,
const vrange &lh,
const vrange &rh,
- relation_kind rel) const
+ relation_trio rel) const
{
gcc_checking_assert (m_valid);
if (m_int)
range_op_handler::op1_range (vrange &r, tree type,
const vrange &lhs,
const vrange &op2,
- relation_kind rel) const
+ relation_trio rel) const
{
gcc_checking_assert (m_valid);
range_op_handler::op2_range (vrange &r, tree type,
const vrange &lhs,
const vrange &op1,
- relation_kind rel) const
+ relation_trio rel) const
{
gcc_checking_assert (m_valid);
if (lhs.undefined_p ())
virtual bool fold_range (irange &r, tree type,
const irange &lh,
const irange &rh,
- relation_kind rel = VREL_VARYING) const;
+ 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
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
const irange &op2,
- relation_kind rel = VREL_VARYING) const;
+ relation_trio = TRIO_VARYING) const;
virtual bool op2_range (irange &r, tree type,
const irange &lhs,
const irange &op1,
- relation_kind rel = VREL_VARYING) const;
+ 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,
virtual bool fold_range (frange &r, tree type,
const frange &lh,
const frange &rh,
- relation_kind rel = VREL_VARYING) const;
+ relation_trio = TRIO_VARYING) 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_kind rel = VREL_VARYING) const;
+ relation_trio = TRIO_VARYING) const;
virtual bool fold_range (irange &r, tree type,
const frange &lh,
const frange &rh,
- relation_kind rel = VREL_VARYING) const;
+ relation_trio = TRIO_VARYING) const;
virtual bool op1_range (frange &r, tree type,
const frange &lhs,
const frange &op2,
- relation_kind rel = VREL_VARYING) const;
+ relation_trio = TRIO_VARYING) const;
virtual bool op1_range (frange &r, tree type,
const irange &lhs,
const frange &op2,
- relation_kind rel = VREL_VARYING) const;
+ relation_trio = TRIO_VARYING) const;
virtual bool op2_range (frange &r, tree type,
const frange &lhs,
const frange &op1,
- relation_kind rel = VREL_VARYING) const;
+ relation_trio = TRIO_VARYING) const;
virtual bool op2_range (frange &r, tree type,
const irange &lhs,
const frange &op1,
- relation_kind rel = VREL_VARYING) const;
+ relation_trio = TRIO_VARYING) const;
virtual relation_kind lhs_op1_relation (const frange &lhs,
const frange &op1,
bool fold_range (vrange &r, tree type,
const vrange &lh,
const vrange &rh,
- relation_kind rel = VREL_VARYING) const;
+ relation_trio = TRIO_VARYING) const;
bool op1_range (vrange &r, tree type,
const vrange &lhs,
const vrange &op2,
- relation_kind rel = VREL_VARYING) const;
+ relation_trio = TRIO_VARYING) const;
bool op2_range (vrange &r, tree type,
const vrange &lhs,
const vrange &op1,
- relation_kind rel = VREL_VARYING) const;
+ relation_trio = TRIO_VARYING) const;
relation_kind lhs_op1_relation (const vrange &lhs,
const vrange &op1,
const vrange &op2,
inline bool
relop_early_resolve (irange &r, tree type, const vrange &op1,
- const vrange &op2, relation_kind rel,
+ const vrange &op2, relation_trio trio,
relation_kind my_rel)
{
+ relation_kind rel = trio.op1_op2 ();
// If known relation is a complete subset of this relation, always true.
if (relation_union (rel, my_rel) == my_rel)
{
#include "alloc-pool.h"
#include "dominance.h"
-#define VREL_LAST VREL_PE64
-
-static const char *kind_string[VREL_LAST + 1] =
+static const char *kind_string[VREL_LAST] =
{ "varying", "undefined", "<", "<=", ">", ">=", "==", "!=", "pe8", "pe16",
"pe32", "pe64" };
}
// This table is used to negate the operands. op1 REL op2 -> !(op1 REL op2).
-relation_kind rr_negate_table[VREL_LAST + 1] = {
+relation_kind rr_negate_table[VREL_LAST] = {
VREL_VARYING, VREL_UNDEFINED, VREL_GE, VREL_GT, VREL_LE, VREL_LT, VREL_NE,
VREL_EQ };
}
// This table is used to swap the operands. op1 REL op2 -> op2 REL op1.
-relation_kind rr_swap_table[VREL_LAST + 1] = {
+relation_kind rr_swap_table[VREL_LAST] = {
VREL_VARYING, VREL_UNDEFINED, VREL_GT, VREL_GE, VREL_LT, VREL_LE, VREL_EQ,
VREL_NE };
// This table is used to perform an intersection between 2 relations.
-relation_kind rr_intersect_table[VREL_LAST + 1][VREL_LAST + 1] = {
+relation_kind rr_intersect_table[VREL_LAST][VREL_LAST] = {
// VREL_VARYING
{ VREL_VARYING, VREL_UNDEFINED, VREL_LT, VREL_LE, VREL_GT, VREL_GE, VREL_EQ,
VREL_NE },
// This table is used to perform a union between 2 relations.
-relation_kind rr_union_table[VREL_LAST + 1][VREL_LAST + 1] = {
+relation_kind rr_union_table[VREL_LAST][VREL_LAST] = {
// VREL_VARYING
{ VREL_VARYING, VREL_VARYING, VREL_VARYING, VREL_VARYING, VREL_VARYING,
VREL_VARYING, VREL_VARYING, VREL_VARYING },
// 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_LAST + 1][VREL_LAST + 1] = {
+relation_kind rr_transitive_table[VREL_LAST][VREL_LAST] = {
// VREL_VARYING
{ VREL_VARYING, VREL_VARYING, VREL_VARYING, VREL_VARYING, VREL_VARYING,
VREL_VARYING, VREL_VARYING, VREL_VARYING },
// This vector maps a relation to the equivalent tree code.
-tree_code relation_to_code [VREL_LAST + 1] = {
+tree_code relation_to_code [VREL_LAST] = {
ERROR_MARK, ERROR_MARK, LT_EXPR, LE_EXPR, GT_EXPR, GE_EXPR, EQ_EXPR,
NE_EXPR };
// If the relation cannot be folded for any reason, leave as is.
Value_Range result (boolean_type_node);
- if (!handler.fold_range (result, boolean_type_node, op1, op2, rel))
+ if (!handler.fold_range (result, boolean_type_node, op1, op2,
+ relation_trio::op1_op2 (rel)))
return rel;
// The expression op1 REL op2 using REL should fold to [1,1].
// utilizes the relation information to enhance it's range calculations, this
// is totally transparent to the client, and they are free to make queries.
//
-//
-// relation_kind is a typedef of enum tree_code, but has restricted range
-// and a couple of extra values.
+// relation_kind is a new enum which represents the different relations,
+// often with a direct mapping to treee codes. ie VREL_EQ is equivalent to
+// EQ_EXPR.
//
// A query is made requesting the relation between SSA1 and SSA@ in a basic
// 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_EQ, VREL_NE, VREL_LT, VREL_LE, VREL_GT, and VREL_GE mean the same.
// 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
-// equivlaencies. These are basically bitmaps over ssa_names.
+// The oracle maintains VREL_EQ relations with equivalency sets, so if a
+// relation comes back VREL_EQ, it is also possible to query the set of
+// equivlaencies. These are basically bitmaps over ssa_names. An iterator is
+// provided later for this activity.
//
// Relations are maintained via the dominace trees and are optimized assuming
// they are registered in dominance order. When a new relation is added, it
// and registered at the specified block.
-// 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_VARYING is the
-// first code, and all the rest are contiguous.
+// These codes are arranged such that VREL_VARYING is the first code, and all
+// the rest are contiguous.
typedef enum relation_kind_t
{
VREL_PE8, // 8 bit partial equivalency
VREL_PE16, // 16 bit partial equivalency
VREL_PE32, // 32 bit partial equivalency
- VREL_PE64 // 64 bit partial equivalency
+ VREL_PE64, // 64 bit partial equivalency
+ VREL_LAST // terminate, not a real relation.
} relation_kind;
// General relation kind transformations.
((equiv_name) = iter.get_name (&equiv_rel)); \
iter.next ())
+// -----------------------------------------------------------------------
+
+// Range-ops deals with a LHS and 2 operands. A relation trio is a set of
+// 3 potential relations packed into a single unsigned value.
+// 1 - LHS relation OP1
+// 2 - LHS relation OP2
+// 3 - OP1 relation OP2
+// VREL_VARYING is a value of 0, and is the default for each position.
+class relation_trio
+{
+public:
+ relation_trio ();
+ relation_trio (relation_kind lhs_op1, relation_kind lhs_op2,
+ relation_kind op1_op2);
+ relation_kind lhs_op1 ();
+ relation_kind lhs_op2 ();
+ relation_kind op1_op2 ();
+ relation_trio swap_op1_op2 ();
+
+ static relation_trio lhs_op1 (relation_kind k);
+ static relation_trio lhs_op2 (relation_kind k);
+ static relation_trio op1_op2 (relation_kind k);
+
+protected:
+ unsigned m_val;
+};
+
+// Default VREL_VARYING for all 3 relations.
+#define TRIO_VARYING relation_trio ()
+
+#define TRIO_SHIFT 4
+#define TRIO_MASK 0x000F
+
+// These 3 classes are shortcuts for when a caller has a single relation to
+// pass as a trio, it can simply construct the appropriate one. The other
+// unspecified realtions will be VREL_VARYING.
+
+inline relation_trio::relation_trio ()
+{
+ STATIC_ASSERT (VREL_LAST <= (1 << TRIO_SHIFT));
+ m_val = 0;
+}
+
+inline relation_trio::relation_trio (relation_kind lhs_op1,
+ relation_kind lhs_op2,
+ relation_kind op1_op2)
+{
+ STATIC_ASSERT (VREL_LAST <= (1 << TRIO_SHIFT));
+ unsigned i1 = (unsigned) lhs_op1;
+ unsigned i2 = ((unsigned) lhs_op2) << TRIO_SHIFT;
+ unsigned i3 = ((unsigned) op1_op2) << (TRIO_SHIFT * 2);
+ m_val = i1 | i2 | i3;
+}
+
+inline relation_trio
+relation_trio::lhs_op1 (relation_kind k)
+{
+ return relation_trio (k, VREL_VARYING, VREL_VARYING);
+}
+inline relation_trio
+relation_trio::lhs_op2 (relation_kind k)
+{
+ return relation_trio (VREL_VARYING, k, VREL_VARYING);
+}
+inline relation_trio
+relation_trio::op1_op2 (relation_kind k)
+{
+ return relation_trio (VREL_VARYING, VREL_VARYING, k);
+}
+
+inline relation_kind
+relation_trio::lhs_op1 ()
+{
+ return (relation_kind) (m_val & TRIO_MASK);
+}
+
+inline relation_kind
+relation_trio::lhs_op2 ()
+{
+ return (relation_kind) ((m_val >> TRIO_SHIFT) & TRIO_MASK);
+}
+
+inline relation_kind
+relation_trio::op1_op2 ()
+{
+ return (relation_kind) ((m_val >> (TRIO_SHIFT * 2)) & TRIO_MASK);
+}
+
+inline relation_trio
+relation_trio::swap_op1_op2 ()
+{
+ return relation_trio (lhs_op2 (), lhs_op1 (), relation_swap (op1_op2 ()));
+}
+
+// -----------------------------------------------------------------------
// The value-relation class is used to encapsulate the represention of an
// individual relation between 2 ssa-names, and to facilitate operating on