Implement POINTER_DIFF_EXPR entry in range-op.
I've seen cases in the upcoming jump threader enhancements where we see a difference of two pointers that are known to be equivalent, and yet we fail to return 0 for the range. This is because we have no working range-op entry for POINTER_DIFF_EXPR. The entry we currently have is a mere placeholder to avoid ignoring POINTER_DIFF_EXPR's so adjust_pointer_diff_expr() could get a whack at it here: // def = __builtin_memchr (arg, 0, sz) // n = def - arg // // The range for N can be narrowed to [0, PTRDIFF_MAX - 1]. This patch adds the relational magic to range-op, which we can just steal from the minus_expr code. gcc/ChangeLog: * range-op.cc (operator_minus::op1_op2_relation_effect): Abstract out to... (minus_op1_op2_relation_effect): ...here. (class operator_pointer_diff): New. (operator_pointer_diff::op1_op2_relation_effect): Call minus_op1_op2_relation_effect. (integral_table::integral_table): Add entry for POINTER_DIFF_EXPR.
This commit is contained in:
parent
47543e5f9d
commit
8af8abfbba
@ -1372,13 +1372,14 @@ operator_minus::wi_fold (irange &r, tree type,
|
||||
}
|
||||
|
||||
// Check to see if the relation REL between OP1 and OP2 has any effect on the
|
||||
// LHS of the expression. If so, apply it to LHS_RANGE.
|
||||
// LHS of the expression. If so, apply it to LHS_RANGE. This is a helper
|
||||
// function for both MINUS_EXPR and POINTER_DIFF_EXPR.
|
||||
|
||||
bool
|
||||
operator_minus::op1_op2_relation_effect (irange &lhs_range, tree type,
|
||||
const irange &op1_range ATTRIBUTE_UNUSED,
|
||||
const irange &op2_range ATTRIBUTE_UNUSED,
|
||||
relation_kind rel) const
|
||||
static bool
|
||||
minus_op1_op2_relation_effect (irange &lhs_range, tree type,
|
||||
const irange &op1_range ATTRIBUTE_UNUSED,
|
||||
const irange &op2_range ATTRIBUTE_UNUSED,
|
||||
relation_kind rel)
|
||||
{
|
||||
if (rel == VREL_NONE)
|
||||
return false;
|
||||
@ -1440,6 +1441,16 @@ operator_minus::op1_op2_relation_effect (irange &lhs_range, tree type,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
operator_minus::op1_op2_relation_effect (irange &lhs_range, tree type,
|
||||
const irange &op1_range,
|
||||
const irange &op2_range,
|
||||
relation_kind rel) const
|
||||
{
|
||||
return minus_op1_op2_relation_effect (lhs_range, type, op1_range, op2_range,
|
||||
rel);
|
||||
}
|
||||
|
||||
bool
|
||||
operator_minus::op1_range (irange &r, tree type,
|
||||
const irange &lhs,
|
||||
@ -1459,6 +1470,26 @@ operator_minus::op2_range (irange &r, tree type,
|
||||
}
|
||||
|
||||
|
||||
class operator_pointer_diff : public range_operator
|
||||
{
|
||||
virtual bool op1_op2_relation_effect (irange &lhs_range,
|
||||
tree type,
|
||||
const irange &op1_range,
|
||||
const irange &op2_range,
|
||||
relation_kind rel) const;
|
||||
} op_pointer_diff;
|
||||
|
||||
bool
|
||||
operator_pointer_diff::op1_op2_relation_effect (irange &lhs_range, tree type,
|
||||
const irange &op1_range,
|
||||
const irange &op2_range,
|
||||
relation_kind rel) const
|
||||
{
|
||||
return minus_op1_op2_relation_effect (lhs_range, type, op1_range, op2_range,
|
||||
rel);
|
||||
}
|
||||
|
||||
|
||||
class operator_min : public range_operator
|
||||
{
|
||||
public:
|
||||
@ -4018,7 +4049,7 @@ integral_table::integral_table ()
|
||||
set (OBJ_TYPE_REF, op_identity);
|
||||
set (IMAGPART_EXPR, op_unknown);
|
||||
set (REALPART_EXPR, op_unknown);
|
||||
set (POINTER_DIFF_EXPR, op_unknown);
|
||||
set (POINTER_DIFF_EXPR, op_pointer_diff);
|
||||
set (ABS_EXPR, op_abs);
|
||||
set (ABSU_EXPR, op_absu);
|
||||
set (NEGATE_EXPR, op_negate);
|
||||
|
Loading…
Reference in New Issue
Block a user