public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
From: Aldy Hernandez <aldyh@gcc.gnu.org>
To: gcc-cvs@gcc.gnu.org
Subject: [gcc r15-154] Implement pointer_plus_operator for prange.
Date: Sat,  4 May 2024 08:28:28 +0000 (GMT)	[thread overview]
Message-ID: <20240504082828.619683846079@sourceware.org> (raw)

https://gcc.gnu.org/g:86ff3c45ea82452888244476f26a4f628b148ace

commit r15-154-g86ff3c45ea82452888244476f26a4f628b148ace
Author: Aldy Hernandez <aldyh@redhat.com>
Date:   Wed Mar 20 10:04:41 2024 +0100

    Implement pointer_plus_operator for prange.
    
    gcc/ChangeLog:
    
            * range-op-ptr.cc (class pointer_plus_operator): Add overloaded declarations
            for pointer variants.
            (pointer_plus_operator::fold_range): New.
            (pointer_plus_operator::op2_range): New.
            (pointer_plus_operator::pointers_handled_p): New.

Diff:
---
 gcc/range-op-ptr.cc | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 98 insertions(+)

diff --git a/gcc/range-op-ptr.cc b/gcc/range-op-ptr.cc
index 38d9f65566f..a4418215613 100644
--- a/gcc/range-op-ptr.cc
+++ b/gcc/range-op-ptr.cc
@@ -265,8 +265,17 @@ range_operator::update_bitmask (irange &,
 class pointer_plus_operator : public range_operator
 {
   using range_operator::update_bitmask;
+  using range_operator::fold_range;
   using range_operator::op2_range;
 public:
+  virtual bool fold_range (prange &r, tree type,
+			   const prange &op1,
+			   const irange &op2,
+			   relation_trio) const final override;
+  virtual bool op2_range (irange &r, tree type,
+			  const prange &lhs,
+			  const prange &op1,
+			  relation_trio = TRIO_VARYING) const final override;
   virtual void wi_fold (irange &r, tree type,
 			const wide_int &lh_lb,
 			const wide_int &lh_ub,
@@ -276,10 +285,99 @@ public:
 			  const irange &lhs,
 			  const irange &op1,
 			  relation_trio = TRIO_VARYING) const;
+  bool pointers_handled_p (range_op_dispatch_type, unsigned) const final override;
   void update_bitmask (irange &r, const irange &lh, const irange &rh) const
     { update_known_bitmask (r, POINTER_PLUS_EXPR, lh, rh); }
 } op_pointer_plus;
 
+bool
+pointer_plus_operator::fold_range (prange &r, tree type,
+				   const prange &op1,
+				   const irange &op2,
+				   relation_trio) const
+{
+  if (empty_range_varying (r, type, op1, op2))
+    return true;
+
+  const wide_int lh_lb = op1.lower_bound ();
+  const wide_int lh_ub = op1.upper_bound ();
+  const wide_int rh_lb = op2.lower_bound ();
+  const wide_int rh_ub = op2.upper_bound ();
+
+  // Check for [0,0] + const, and simply return the const.
+  if (lh_lb == 0 && lh_ub == 0 && rh_lb == rh_ub)
+    {
+      r.set (type, rh_lb, rh_lb);
+      return true;
+    }
+
+  // For pointer types, we are really only interested in asserting
+  // whether the expression evaluates to non-NULL.
+  //
+  // With -fno-delete-null-pointer-checks we need to be more
+  // conservative.  As some object might reside at address 0,
+  // then some offset could be added to it and the same offset
+  // subtracted again and the result would be NULL.
+  // E.g.
+  // static int a[12]; where &a[0] is NULL and
+  // ptr = &a[6];
+  // ptr -= 6;
+  // ptr will be NULL here, even when there is POINTER_PLUS_EXPR
+  // where the first range doesn't include zero and the second one
+  // doesn't either.  As the second operand is sizetype (unsigned),
+  // consider all ranges where the MSB could be set as possible
+  // subtractions where the result might be NULL.
+  if ((!wi_includes_zero_p (type, lh_lb, lh_ub)
+       || !wi_includes_zero_p (type, rh_lb, rh_ub))
+      && !TYPE_OVERFLOW_WRAPS (type)
+      && (flag_delete_null_pointer_checks
+	  || !wi::sign_mask (rh_ub)))
+    r.set_nonzero (type);
+  else if (lh_lb == lh_ub && lh_lb == 0
+	   && rh_lb == rh_ub && rh_lb == 0)
+    r.set_zero (type);
+  else
+   r.set_varying (type);
+
+  update_known_bitmask (r, POINTER_PLUS_EXPR, op1, op2);
+  return true;
+}
+
+bool
+pointer_plus_operator::op2_range (irange &r, tree type,
+				  const prange &lhs ATTRIBUTE_UNUSED,
+				  const prange &op1 ATTRIBUTE_UNUSED,
+				  relation_trio trio) const
+{
+  relation_kind rel = trio.lhs_op1 ();
+  r.set_varying (type);
+
+  // If the LHS and OP1 are equal, the op2 must be zero.
+  if (rel == VREL_EQ)
+    r.set_zero (type);
+  // If the LHS and OP1 are not equal, the offset must be non-zero.
+  else if (rel == VREL_NE)
+    r.set_nonzero (type);
+  else
+    return false;
+  return true;
+}
+
+bool
+pointer_plus_operator::pointers_handled_p (range_op_dispatch_type type,
+					   unsigned dispatch) const
+{
+  switch (type)
+    {
+    case DISPATCH_FOLD_RANGE:
+      return dispatch == RO_PPI;
+    case DISPATCH_OP2_RANGE:
+      return dispatch == RO_IPP;
+    default:
+      return true;
+    }
+}
+
 void
 pointer_plus_operator::wi_fold (irange &r, tree type,
 				const wide_int &lh_lb,

                 reply	other threads:[~2024-05-04  8:28 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240504082828.619683846079@sourceware.org \
    --to=aldyh@gcc.gnu.org \
    --cc=gcc-cvs@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).