bool
gori_compute::compute_operand_range (vrange &r, gimple *stmt,
const vrange &lhs, tree name,
- fur_source &src)
+ fur_source &src, value_relation *rel)
{
+ value_relation vrel;
+ value_relation *vrel_ptr = rel;
// If the lhs doesn't tell us anything, neither will unwinding further.
if (lhs.varying_p ())
return false;
tree op1 = gimple_range_ssa_p (handler.operand1 ());
tree op2 = gimple_range_ssa_p (handler.operand2 ());
+ // If there is a relation, use it instead of any passed in. This will allow
+ // multiple relations to be processed in compound logicals.
+ if (op1 && op2)
+ {
+ relation_kind k = handler.op1_op2_relation (lhs);
+ if (k != VREL_VARYING)
+ {
+ vrel.set_relation (k, op1, op2);
+ vrel_ptr = &vrel;
+ }
+ }
+
// Handle end of lookup first.
if (op1 == name)
- return compute_operand1_range (r, handler, lhs, name, src);
+ return compute_operand1_range (r, handler, lhs, name, src, vrel_ptr);
if (op2 == name)
- return compute_operand2_range (r, handler, lhs, name, src);
+ return compute_operand2_range (r, handler, lhs, name, src, vrel_ptr);
// NAME is not in this stmt, but one of the names in it ought to be
// derived from it.
}
// Follow the appropriate operands now.
else if (op1_in_chain && op2_in_chain)
- res = compute_operand1_and_operand2_range (r, handler, lhs, name, src);
+ res = compute_operand1_and_operand2_range (r, handler, lhs, name, src,
+ vrel_ptr);
else if (op1_in_chain)
- res = compute_operand1_range (r, handler, lhs, name, src);
+ res = compute_operand1_range (r, handler, lhs, name, src, vrel_ptr);
else if (op2_in_chain)
- res = compute_operand2_range (r, handler, lhs, name, src);
+ res = compute_operand2_range (r, handler, lhs, name, src, vrel_ptr);
else
gcc_unreachable ();
gori_compute::compute_operand1_range (vrange &r,
gimple_range_op_handler &handler,
const vrange &lhs, tree name,
- fur_source &src)
+ fur_source &src, value_relation *rel)
{
gimple *stmt = handler.stmt ();
tree op1 = handler.operand1 ();
gcc_checking_assert (src_stmt);
// Then feed this range back as the LHS of the defining statement.
- return compute_operand_range (r, src_stmt, op1_range, name, src);
+ return compute_operand_range (r, src_stmt, op1_range, name, src, rel);
}
gori_compute::compute_operand2_range (vrange &r,
gimple_range_op_handler &handler,
const vrange &lhs, tree name,
- fur_source &src)
+ fur_source &src, value_relation *rel)
{
gimple *stmt = handler.stmt ();
tree op1 = handler.operand1 ();
// gcc_checking_assert (!is_import_p (op2, find.bb));
// Then feed this range back as the LHS of the defining statement.
- return compute_operand_range (r, src_stmt, op2_range, name, src);
+ return compute_operand_range (r, src_stmt, op2_range, name, src, rel);
}
// Calculate a range for NAME from both operand positions of S
&handler,
const vrange &lhs,
tree name,
- fur_source &src)
+ fur_source &src,
+ value_relation *rel)
{
Value_Range op_range (TREE_TYPE (name));
// Calculate a good a range for op2. Since op1 == op2, this will
// have already included whatever the actual range of name is.
- if (!compute_operand2_range (op_range, handler, lhs, name, src))
+ if (!compute_operand2_range (op_range, handler, lhs, name, src, rel))
return false;
// Now get the range thru op1.
- if (!compute_operand1_range (r, handler, lhs, name, src))
+ if (!compute_operand1_range (r, handler, lhs, name, src, rel))
return false;
// Both operands have to be simultaneously true, so perform an intersection.
//
// The remaining routines are internal use only.
+class value_relation;
+
class gori_compute : public gori_map
{
public:
bool may_recompute_p (tree name, edge e);
bool may_recompute_p (tree name, basic_block bb = NULL);
bool compute_operand_range (vrange &r, gimple *stmt, const vrange &lhs,
- tree name, class fur_source &src);
+ tree name, class fur_source &src,
+ value_relation *rel = NULL);
bool compute_operand_range_switch (vrange &r, gswitch *s, const vrange &lhs,
tree name, fur_source &src);
bool compute_operand1_range (vrange &r, gimple_range_op_handler &handler,
- const vrange &lhs, tree name, fur_source &src);
+ const vrange &lhs, tree name, fur_source &src,
+ value_relation *rel = NULL);
bool compute_operand2_range (vrange &r, gimple_range_op_handler &handler,
- const vrange &lhs, tree name, fur_source &src);
+ const vrange &lhs, tree name, fur_source &src,
+ value_relation *rel = NULL);
bool compute_operand1_and_operand2_range (vrange &r,
gimple_range_op_handler &handler,
const vrange &lhs, tree name,
- fur_source &src);
+ fur_source &src,
+ value_relation *rel = NULL);
void compute_logical_operands (vrange &true_range, vrange &false_range,
gimple_range_op_handler &handler,
const irange &lhs, tree name, fur_source &src,
bool
gimple_range_op_handler::calc_op1 (vrange &r, const vrange &lhs_range,
- const vrange &op2_range)
+ const vrange &op2_range, relation_kind k)
{
// Give up on empty ranges.
if (lhs_range.undefined_p ())
op2_type = TREE_TYPE (operand1 ());
Value_Range trange (op2_type);
trange.set_varying (op2_type);
- return op1_range (r, type, lhs_range, trange);
+ return op1_range (r, type, lhs_range, trange, k);
}
- return op1_range (r, type, lhs_range, op2_range);
+ return op1_range (r, type, lhs_range, op2_range, k);
}
// Calculate what we can determine of the range of this statement's
bool
gimple_range_op_handler::calc_op2 (vrange &r, const vrange &lhs_range,
- const vrange &op1_range)
+ const vrange &op1_range, relation_kind k)
{
// Give up on empty ranges.
if (lhs_range.undefined_p ())
tree op1_type = TREE_TYPE (operand1 ());
Value_Range trange (op1_type);
trange.set_varying (op1_type);
- return op2_range (r, type, lhs_range, trange);
+ return op2_range (r, type, lhs_range, trange, k);
}
- return op2_range (r, type, lhs_range, op1_range);
+ return op2_range (r, type, lhs_range, op1_range, k);
}
// --------------------------------------------------------------------