[COMMITTED,11/23] Implement operator_min and operator_max for prange.

Message ID 20240504083056.139719-12-aldyh@redhat.com
State New
Headers
Series prange: pointer ranges |

Commit Message

Aldy Hernandez May 4, 2024, 8:30 a.m. UTC
  gcc/ChangeLog:

	* range-op-mixed.h: Add overloaded declarations for pointer variants.
	* range-op-ptr.cc (operator_min::fold_range): New.
	(operator_min::pointers_handled_p): New.
	(operator_max::fold_range): New.
	(operator_max::pointers_handled_p): New.
---
 gcc/range-op-mixed.h | 12 ++++++++
 gcc/range-op-ptr.cc  | 70 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 82 insertions(+)
  

Patch

diff --git a/gcc/range-op-mixed.h b/gcc/range-op-mixed.h
index 11b1bf0bca4..b69e674a78b 100644
--- a/gcc/range-op-mixed.h
+++ b/gcc/range-op-mixed.h
@@ -761,12 +761,18 @@  protected:
 class operator_min : public range_operator
 {
 public:
+  using range_operator::fold_range;
   using range_operator::update_bitmask;
+  bool fold_range (prange &r, tree type,
+		   const prange &op1,
+		   const prange &op2,
+		   relation_trio) const final override;
   void update_bitmask (irange &r, const irange &lh,
 		       const irange &rh) const override;
   // Check compatibility of all operands.
   bool operand_check_p (tree t1, tree t2, tree t3) const final override
     { return range_compatible_p (t1, t2) && range_compatible_p (t1, t3); }
+  bool pointers_handled_p (range_op_dispatch_type, unsigned) const final override;
 protected:
   void wi_fold (irange &r, tree type, const wide_int &lh_lb,
 		const wide_int &lh_ub, const wide_int &rh_lb,
@@ -776,12 +782,18 @@  protected:
 class operator_max : public range_operator
 {
 public:
+  using range_operator::fold_range;
   using range_operator::update_bitmask;
+  bool fold_range (prange &r, tree type,
+		   const prange &op1,
+		   const prange &op2,
+		   relation_trio) const final override;
   void update_bitmask (irange &r, const irange &lh,
       const irange &rh) const override;
   // Check compatibility of all operands.
   bool operand_check_p (tree t1, tree t2, tree t3) const final override
     { return range_compatible_p (t1, t2) && range_compatible_p (t1, t3); }
+  bool pointers_handled_p (range_op_dispatch_type, unsigned) const final override;
 protected:
   void wi_fold (irange &r, tree type, const wide_int &lh_lb,
 		const wide_int &lh_ub, const wide_int &rh_lb,
diff --git a/gcc/range-op-ptr.cc b/gcc/range-op-ptr.cc
index b8f86c8e838..0addd1096c2 100644
--- a/gcc/range-op-ptr.cc
+++ b/gcc/range-op-ptr.cc
@@ -951,6 +951,76 @@  operator_cast::pointers_handled_p (range_op_dispatch_type type,
     }
 }
 
+bool
+operator_min::fold_range (prange &r, tree type,
+			  const prange &op1,
+			  const prange &op2,
+			  relation_trio) const
+{
+  // For MIN/MAX expressions with pointers, we only care about
+  // nullness.  If both are non null, then the result is nonnull.
+  // If both are null, then the result is null.  Otherwise they
+  // are varying.
+  if (!range_includes_zero_p (op1)
+      && !range_includes_zero_p (op2))
+    r.set_nonzero (type);
+  else if (op1.zero_p () && op2.zero_p ())
+    r.set_zero (type);
+  else
+    r.set_varying (type);
+
+  update_known_bitmask (r, MIN_EXPR, op1, op2);
+  return true;
+}
+
+bool
+operator_min::pointers_handled_p (range_op_dispatch_type type,
+				  unsigned dispatch) const
+{
+  switch (type)
+    {
+    case DISPATCH_FOLD_RANGE:
+      return dispatch == RO_PPP;
+    default:
+      return true;
+    }
+}
+
+bool
+operator_max::fold_range (prange &r, tree type,
+			  const prange &op1,
+			  const prange &op2,
+			  relation_trio) const
+{
+  // For MIN/MAX expressions with pointers, we only care about
+  // nullness.  If both are non null, then the result is nonnull.
+  // If both are null, then the result is null.  Otherwise they
+  // are varying.
+  if (!range_includes_zero_p (op1)
+      && !range_includes_zero_p (op2))
+    r.set_nonzero (type);
+  else if (op1.zero_p () && op2.zero_p ())
+    r.set_zero (type);
+  else
+    r.set_varying (type);
+
+  update_known_bitmask (r, MAX_EXPR, op1, op2);
+  return true;
+}
+
+bool
+operator_max::pointers_handled_p (range_op_dispatch_type type,
+				  unsigned dispatch) const
+{
+  switch (type)
+    {
+    case DISPATCH_FOLD_RANGE:
+      return dispatch == RO_PPP;
+    default:
+      return true;
+    }
+}
+
 // Initialize any pointer operators to the primary table
 
 void