From 8af8abfbbace49e6e5e9413d4e661533437106a0 Mon Sep 17 00:00:00 2001 From: Aldy Hernandez Date: Fri, 3 Sep 2021 10:01:25 +0200 Subject: [PATCH] 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. --- gcc/range-op.cc | 45 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 38 insertions(+), 7 deletions(-) diff --git a/gcc/range-op.cc b/gcc/range-op.cc index fee0e834c23..5e37133026d 100644 --- a/gcc/range-op.cc +++ b/gcc/range-op.cc @@ -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);