]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Add lhs_op1 relation to pointer_plus
authorAndrew MacLeod <amacleod@redhat.com>
Tue, 22 Apr 2025 14:36:26 +0000 (10:36 -0400)
committerAndrew MacLeod <amacleod@redhat.com>
Mon, 28 Apr 2025 21:17:30 +0000 (17:17 -0400)
When prange was split from irange, the functionality of lhs_op1_relation
did not get ported.  This patch adds that functionality back, and is
also good example of how to add new dispatch patterns to range-ops
as lhs_op1_relation had no prange/prange/irange combination.

* range-op-ptr.cc (range_operator::lhs_op1_relation): Add
prange/prange/irange (PPI) default.
(pointer_plus_operator::lhs_op1_relation): New.
* range-op.cc (range_op_handler::lhs_op1_relation): Add RO_PPI case.
* range-op.h (range_op_handler::lhs_op1_relation): Add prototype.

gcc/range-op-ptr.cc
gcc/range-op.cc
gcc/range-op.h

index dd51c2e0c926a27217a6ddeafa3c90729eaf0c9c..36e9dfc20baf49f5ddcd86dc538cc814b11c5c7f 100644 (file)
@@ -218,6 +218,15 @@ range_operator::lhs_op1_relation (const prange &lhs ATTRIBUTE_UNUSED,
   return VREL_VARYING;
 }
 
+relation_kind
+range_operator::lhs_op1_relation (const prange &lhs ATTRIBUTE_UNUSED,
+                                 const prange &op1 ATTRIBUTE_UNUSED,
+                                 const irange &op2 ATTRIBUTE_UNUSED,
+                                 relation_kind rel ATTRIBUTE_UNUSED) const
+{
+  return VREL_VARYING;
+}
+
 void
 range_operator::update_bitmask (irange &,
                                const prange &,
@@ -293,6 +302,7 @@ class pointer_plus_operator : public range_operator
   using range_operator::update_bitmask;
   using range_operator::fold_range;
   using range_operator::op2_range;
+  using range_operator::lhs_op1_relation;
 public:
   virtual bool fold_range (prange &r, tree type,
                           const prange &op1,
@@ -302,6 +312,10 @@ public:
                          const prange &lhs,
                          const prange &op1,
                          relation_trio = TRIO_VARYING) const final override;
+  virtual relation_kind lhs_op1_relation (const prange &lhs,
+                                         const prange &op1,
+                                         const irange &op2,
+                                         relation_kind) const;
   void update_bitmask (prange &r, const prange &lh, const irange &rh) const
     { update_known_bitmask (r, POINTER_PLUS_EXPR, lh, rh); }
 } op_pointer_plus;
@@ -379,6 +393,51 @@ pointer_plus_operator::op2_range (irange &r, tree type,
   return true;
 }
 
+// Return the relation between the LHS and OP1 based on the value of the
+// operand being added.  Pointer_plus is define to have a size_type for
+// operand 2 which can be interpreted as negative, so always used SIGNED.
+// Any overflow is considered UB and thus ignored.
+
+relation_kind
+pointer_plus_operator::lhs_op1_relation (const prange &lhs,
+                                        const prange &op1,
+                                        const irange &op2,
+                                        relation_kind) const
+{
+  if (lhs.undefined_p () || op1.undefined_p () || op2.undefined_p ())
+    return VREL_VARYING;
+
+  unsigned prec = TYPE_PRECISION (op2.type ());
+
+  // LHS = OP1 + 0  indicates LHS == OP1.
+  if (op2.zero_p ())
+    return VREL_EQ;
+
+  tree val;
+  // Only deal with singletons for now.
+  if (TYPE_OVERFLOW_UNDEFINED (lhs.type ()) && op2.singleton_p (&val))
+    {
+      // Always interpret VALUE as a signed value.  Positive will increase
+      // the pointer value, and negative will decrease the poiinter value.
+      // It cannot be zero or the earlier zero_p () condition will catch it.
+      wide_int value = wi::to_wide (val);
+
+      // Positive op2 means lhs > op1.
+      if (wi::gt_p (value, wi::zero (prec), SIGNED))
+       return VREL_GT;
+
+      // Negative op2 means lhs < op1.
+      if (wi::lt_p (value, wi::zero (prec), SIGNED))
+       return VREL_LT;
+    }
+
+  // If op2 does not contain 0, then LHS and OP1 can never be equal.
+  if (!range_includes_zero_p (op2))
+    return VREL_NE;
+
+  return VREL_VARYING;
+}
+
 bool
 operator_bitwise_or::fold_range (prange &r, tree type,
                                 const prange &op1,
index 5c0bcdc3b37d433c8334992ed31be554235930f8..35b3e18ebed2127ece20ec26b963e617f6b35e33 100644 (file)
@@ -390,6 +390,10 @@ range_op_handler::lhs_op1_relation (const vrange &lhs,
        return m_operator->lhs_op1_relation (as_a <prange> (lhs),
                                             as_a <irange> (op1),
                                             as_a <irange> (op2), rel);
+      case RO_PPI:
+       return m_operator->lhs_op1_relation (as_a <prange> (lhs),
+                                            as_a <prange> (op1),
+                                            as_a <irange> (op2), rel);
       case RO_IFF:
        return m_operator->lhs_op1_relation (as_a <irange> (lhs),
                                             as_a <frange> (op1),
index 5dcb3fbae61ccb0404ba82ea18c3359db9f9197b..594e6782dc38dfb993515274e90869fc78b46226 100644 (file)
@@ -189,6 +189,10 @@ public:
                                          const prange &op1,
                                          const prange &op2,
                                          relation_kind = VREL_VARYING) const;
+  virtual relation_kind lhs_op1_relation (const prange &lhs,
+                                         const prange &op1,
+                                         const irange &op2,
+                                         relation_kind = VREL_VARYING) const;
   virtual relation_kind lhs_op1_relation (const frange &lhs,
                                          const frange &op1,
                                          const frange &op2,