https://gcc.gnu.org/g:bcb226924f50d9b84ca32b6f39abb63b43e23229

commit r15-159-gbcb226924f50d9b84ca32b6f39abb63b43e23229
Author: Aldy Hernandez <al...@redhat.com>
Date:   Wed Mar 20 10:54:39 2024 +0100

    Implement operator_equal for prange.
    
    gcc/ChangeLog:
    
            * range-op-mixed.h: Add overloaded declarations for pointer 
variants.
            * range-op-ptr.cc (operator_equal::fold_range): New.
            (operator_equal::op1_range): New.
            (operator_equal::op2_range): New.
            (operator_equal::op1_op2_relation): New.
            (operator_equal::pointers_handled_p): New.

Diff:
---
 gcc/range-op-mixed.h |  12 ++++++
 gcc/range-op-ptr.cc  | 117 +++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 129 insertions(+)

diff --git a/gcc/range-op-mixed.h b/gcc/range-op-mixed.h
index 980611dc339..ee8d9dd328f 100644
--- a/gcc/range-op-mixed.h
+++ b/gcc/range-op-mixed.h
@@ -115,6 +115,9 @@ public:
   bool fold_range (irange &r, tree type,
                   const irange &op1, const irange &op2,
                   relation_trio = TRIO_VARYING) const final override;
+  bool fold_range (irange &r, tree type,
+                  const prange &op1, const prange &op2,
+                  relation_trio = TRIO_VARYING) const final override;
   bool fold_range (irange &r, tree type,
                   const frange &op1, const frange &op2,
                   relation_trio = TRIO_VARYING) const final override;
@@ -122,6 +125,9 @@ public:
   bool op1_range (irange &r, tree type,
                  const irange &lhs, const irange &val,
                  relation_trio = TRIO_VARYING) const final override;
+  bool op1_range (prange &r, tree type,
+                 const irange &lhs, const prange &val,
+                 relation_trio = TRIO_VARYING) const final override;
   bool op1_range (frange &r, tree type,
                  const irange &lhs, const frange &op2,
                  relation_trio = TRIO_VARYING) const final override;
@@ -129,12 +135,17 @@ public:
   bool op2_range (irange &r, tree type,
                  const irange &lhs, const irange &val,
                  relation_trio = TRIO_VARYING) const final override;
+  bool op2_range (prange &r, tree type,
+                 const irange &lhs, const prange &val,
+                 relation_trio = TRIO_VARYING) const final override;
   bool op2_range (frange &r, tree type,
                  const irange &lhs, const frange &op1,
                  relation_trio rel = TRIO_VARYING) const final override;
 
   relation_kind op1_op2_relation (const irange &lhs, const irange &,
                                  const irange &) const final override;
+  relation_kind op1_op2_relation (const irange &lhs, const prange &,
+                                 const prange &) const final override;
   relation_kind op1_op2_relation (const irange &lhs, const frange &,
                                  const frange &) const final override;
   void update_bitmask (irange &r, const irange &lh,
@@ -142,6 +153,7 @@ public:
   // Check op1 and op2 for compatibility.
   bool operand_check_p (tree, tree t1, tree t2) const final override
     { return range_compatible_p (t1, t2); }
+  bool pointers_handled_p (range_op_dispatch_type, unsigned) const final 
override;
 };
 
 class operator_not_equal : public range_operator
diff --git a/gcc/range-op-ptr.cc b/gcc/range-op-ptr.cc
index 081e8fdba1f..fb2888bf079 100644
--- a/gcc/range-op-ptr.cc
+++ b/gcc/range-op-ptr.cc
@@ -1230,6 +1230,123 @@ operator_bitwise_or::pointers_handled_p 
(range_op_dispatch_type,
   return false;
 }
 
+bool
+operator_equal::fold_range (irange &r, tree type,
+                           const prange &op1,
+                           const prange &op2,
+                           relation_trio rel) const
+{
+  if (relop_early_resolve (r, type, op1, op2, rel, VREL_EQ))
+    return true;
+
+  // We can be sure the values are always equal or not if both ranges
+  // consist of a single value, and then compare them.
+  bool op1_const = wi::eq_p (op1.lower_bound (), op1.upper_bound ());
+  bool op2_const = wi::eq_p (op2.lower_bound (), op2.upper_bound ());
+  if (op1_const && op2_const)
+    {
+      if (wi::eq_p (op1.lower_bound (), op2.upper_bound()))
+       r = range_true ();
+      else
+       r = range_false ();
+    }
+  else
+    {
+      // If ranges do not intersect, we know the range is not equal,
+      // otherwise we don't know anything for sure.
+      prange tmp = op1;
+      tmp.intersect (op2);
+      if (tmp.undefined_p ())
+       r = range_false ();
+      // Check if a constant cannot satisfy the bitmask requirements.
+      else if (op2_const && !op1.get_bitmask ().member_p (op2.lower_bound ()))
+        r = range_false ();
+      else if (op1_const && !op2.get_bitmask ().member_p (op1.lower_bound ()))
+        r = range_false ();
+      else
+       r = range_true_and_false ();
+    }
+
+  //update_known_bitmask (r, EQ_EXPR, op1, op2);
+  return true;
+}
+
+bool
+operator_equal::op1_range (prange &r, tree type,
+                          const irange &lhs,
+                          const prange &op2,
+                          relation_trio) const
+{
+  switch (get_bool_state (r, lhs, type))
+    {
+    case BRS_TRUE:
+      // If it's true, the result is the same as OP2.
+      r = op2;
+      break;
+
+    case BRS_FALSE:
+      // If the result is false, the only time we know anything is
+      // if OP2 is a constant.
+      if (!op2.undefined_p ()
+         && wi::eq_p (op2.lower_bound(), op2.upper_bound()))
+       {
+         r = op2;
+         r.invert ();
+       }
+      else
+       r.set_varying (type);
+      break;
+
+    default:
+      break;
+    }
+  return true;
+}
+
+bool
+operator_equal::op2_range (prange &r, tree type,
+                          const irange &lhs,
+                          const prange &op1,
+                          relation_trio rel) const
+{
+  return operator_equal::op1_range (r, type, lhs, op1, rel.swap_op1_op2 ());
+}
+
+relation_kind
+operator_equal::op1_op2_relation (const irange &lhs, const prange &,
+                                 const prange &) const
+{
+  if (lhs.undefined_p ())
+    return VREL_UNDEFINED;
+
+  // FALSE = op1 == op2 indicates NE_EXPR.
+  if (lhs.zero_p ())
+    return VREL_NE;
+
+  // TRUE = op1 == op2 indicates EQ_EXPR.
+  if (!range_includes_zero_p (lhs))
+    return VREL_EQ;
+  return VREL_VARYING;
+}
+
+bool
+operator_equal::pointers_handled_p (range_op_dispatch_type type,
+                                   unsigned dispatch) const
+{
+  switch (type)
+    {
+    case DISPATCH_FOLD_RANGE:
+      return dispatch == RO_IPP;
+    case DISPATCH_OP1_RANGE:
+    case DISPATCH_OP2_RANGE:
+      return dispatch == RO_PIP;
+    case DISPATCH_OP1_OP2_RELATION:
+      return dispatch == RO_IPP;
+    default:
+      return true;
+    }
+}
+
 bool
 operator_not_equal::fold_range (irange &r, tree type,
                                const prange &op1,

Reply via email to