pointer_diff depends on range_operator::fold_range to do the generic fold, which invokes wi_fold on subranges. It also in turn invokes op1_op2_relation_effect for relation effects.
This worked fine when pointers were implemented with irange, but when the transition to prange was made, a new version of fold_range is invoked by dispatch which uses prange operators. The default fold_range for prange does nothing, expecting the few pointer operators which need it to implement their own fold_range. As a result all calls to fold_range for pointer_diff were returning false, which translates to VARYING.
This PR demonstrates a dependency on knowing the relation between the operands is VREL_NE, in which case pointer_diff should return a non-zero result instead of varying. This patch implements the pointer_diff version of fold_range.
I am also auditing the other prange operators to see if similar dispatch related issues were missed.
Bootstrapped on x86_64-pc-linux-gnu with no regressions. Pushed. Andrew
From 774ad67fba458dd1beaa0f2d3e389aac46ca18b5 Mon Sep 17 00:00:00 2001 From: Andrew MacLeod <amacl...@redhat.com> Date: Mon, 21 Oct 2024 16:32:00 -0400 Subject: [PATCH] Implement operator_pointer_diff::fold_range prange has no default fold_range processing like irange does, so each pointer specific operator needs to implement its own fold routine. PR tree-optimization/117222 gcc/ * range-op-ptr.cc (operator_pointer_diff::fold_range): New. (operator_pointer_diff::op1_op2_relation_effect): Remove irange variant. (operator_pointer_diff::update_bitmask): Likewise. gcc/testsuite * g++.dg/pr117222.C: New. --- gcc/range-op-ptr.cc | 37 ++++++++++++++++++--------------- gcc/testsuite/g++.dg/pr117222.C | 16 ++++++++++++++ 2 files changed, 36 insertions(+), 17 deletions(-) create mode 100644 gcc/testsuite/g++.dg/pr117222.C diff --git a/gcc/range-op-ptr.cc b/gcc/range-op-ptr.cc index 24e206c00cd..07a551618f9 100644 --- a/gcc/range-op-ptr.cc +++ b/gcc/range-op-ptr.cc @@ -567,25 +567,38 @@ pointer_or_operator::wi_fold (irange &r, tree type, class operator_pointer_diff : public range_operator { + using range_operator::fold_range; using range_operator::update_bitmask; using range_operator::op1_op2_relation_effect; - virtual bool op1_op2_relation_effect (irange &lhs_range, - tree type, - const irange &op1_range, - const irange &op2_range, - relation_kind rel) const; + virtual bool fold_range (irange &r, tree type, + const prange &op1, + const prange &op2, + relation_trio trio) const final override; virtual bool op1_op2_relation_effect (irange &lhs_range, tree type, const prange &op1_range, const prange &op2_range, relation_kind rel) const final override; - void update_bitmask (irange &r, const irange &lh, const irange &rh) const - { update_known_bitmask (r, POINTER_DIFF_EXPR, lh, rh); } void update_bitmask (irange &r, const prange &lh, const prange &rh) const final override { update_known_bitmask (r, POINTER_DIFF_EXPR, lh, rh); } } op_pointer_diff; +bool +operator_pointer_diff::fold_range (irange &r, tree type, + const prange &op1, + const prange &op2, + relation_trio trio) const +{ + gcc_checking_assert (r.supports_type_p (type)); + + r.set_varying (type); + relation_kind rel = trio.op1_op2 (); + op1_op2_relation_effect (r, type, op1, op2, rel); + update_bitmask (r, op1, op2); + return true; +} + bool operator_pointer_diff::op1_op2_relation_effect (irange &lhs_range, tree type, const prange &op1_range, @@ -602,16 +615,6 @@ operator_pointer_diff::op1_op2_relation_effect (irange &lhs_range, tree type, return minus_op1_op2_relation_effect (lhs_range, type, op1, op2, rel); } -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); -} - bool operator_identity::fold_range (prange &r, tree type ATTRIBUTE_UNUSED, const prange &lh ATTRIBUTE_UNUSED, diff --git a/gcc/testsuite/g++.dg/pr117222.C b/gcc/testsuite/g++.dg/pr117222.C new file mode 100644 index 00000000000..60cf6e30ed5 --- /dev/null +++ b/gcc/testsuite/g++.dg/pr117222.C @@ -0,0 +1,16 @@ +// { dg-do compile } +// { dg-require-effective-target c++11 } +// { dg-options "-O3 -fdump-tree-evrp" } + +#include <vector> +int main() +{ + std::vector<int> c {1,2,3,0}; + while(c.size() > 0 && c.back() == 0) + { + auto sz = c.size() -1; + c.resize(sz); + } + return 0; +} +/* { dg-final { scan-tree-dump "Global Exported.*\[-INF, -1\]\[1, +INF\]" "evrp" } } */ -- 2.45.0