[COMMITTED] PR tree-optimization/117222 - Implement operator_pointer_diff::fold_range

Message ID c8de56f9-789f-4fe6-a976-feff0b145757@redhat.com
State New
Headers
Series [COMMITTED] PR tree-optimization/117222 - Implement operator_pointer_diff::fold_range |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gcc_build--master-arm fail Patch failed to apply
linaro-tcwg-bot/tcwg_gcc_build--master-aarch64 fail Patch failed to apply

Commit Message

Andrew MacLeod Oct. 23, 2024, 4:23 p.m. UTC
  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
  

Patch

From 774ad67fba458dd1beaa0f2d3e389aac46ca18b5 Mon Sep 17 00:00:00 2001
From: Andrew MacLeod <amacleod@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