]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Implement operator_min and operator_max for prange.
authorAldy Hernandez <aldyh@redhat.com>
Wed, 20 Mar 2024 07:44:49 +0000 (08:44 +0100)
committerAldy Hernandez <aldyh@redhat.com>
Sat, 4 May 2024 08:25:51 +0000 (10:25 +0200)
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
gcc/range-op-ptr.cc

index 11b1bf0bca4b5f7443e7e9440845d8b836307d64..b69e674a78bde75c35570bd910740d65864146c0 100644 (file)
@@ -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,
index b8f86c8e838ad6458b7dcdb50271ea75bbfc4f0f..0addd1096c21d0c2237c0638fe9bf17ae4fcee1e 100644 (file)
@@ -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