aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorAldy Hernandez <aldyh@redhat.com>2021-09-03 10:01:25 +0200
committerAldy Hernandez <aldyh@redhat.com>2021-09-03 18:40:02 +0200
commit8af8abfbbace49e6e5e9413d4e661533437106a0 (patch)
tree987311974970cb0b1c6f1e304dfa205995ff3f75 /gcc
parent47543e5f9d1fc502be79f91c87cbeb6eda17e641 (diff)
downloadgcc-8af8abfbbace49e6e5e9413d4e661533437106a0.zip
gcc-8af8abfbbace49e6e5e9413d4e661533437106a0.tar.gz
gcc-8af8abfbbace49e6e5e9413d4e661533437106a0.tar.bz2
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.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/range-op.cc45
1 files changed, 38 insertions, 7 deletions
diff --git a/gcc/range-op.cc b/gcc/range-op.cc
index fee0e83..5e37133 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;
@@ -1441,6 +1442,16 @@ operator_minus::op1_op2_relation_effect (irange &lhs_range, tree type,
}
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,
const irange &op2,
@@ -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);