https://gcc.gnu.org/g:31377eed515506c9e8ba2ac8fa3ab4e743f8c1f3

commit r15-148-g31377eed515506c9e8ba2ac8fa3ab4e743f8c1f3
Author: Aldy Hernandez <al...@redhat.com>
Date:   Wed Mar 20 07:19:45 2024 +0100

    Implement range-op dispatch for prange.
    
    This patch adds the range-op dispatch code for prange, and adds some
    temporary sanity checks (for flag_checking only) to make sure we handle
    all the pointer/integer variants.
    
    In order to make sure I got all the combinations right, I started with
    a clean slate, trapping on all pointer operands.  Then I added support
    for each one piecemeal.  To verify the work, I added a
    pointers_handled_p() helper that is implemented for each range-op
    entry and returns TRUE iff the operator can handle a given combination
    of pointers.  If this helper returns false, we will trap, because it
    indicates an operator that was not implemented.  This is temporary
    checking code, and I will rip it out once the the dust has
    settled in a few days.
    
    gcc/ChangeLog:
    
            * range-op-mixed.h: Add using declarator for all classes.
            * range-op-ptr.cc (range_operator::pointers_handled_p): New.
            (range_operator::fold_range): New.
            (range_operator::op1_op2_relation_effect): New.
            (range_operator::op1_range): New.
            (range_operator::op2_range): New.
            (range_operator::op1_op2_relation): New.
            (range_operator::lhs_op1_relation): New.
            (range_operator::update_bitmask): New.
            (class pointer_plus_operator): New.
            (class operator_pointer_diff): New.
            (class hybrid_min_operator): New.
            (class hybrid_max_operator): New.
            * range-op.cc: Add RO_PPP, RO_PPI, RO_IPP, RO_IPI, RO_PIP, RO_PII.
            (range_op_handler::discriminator_fail): New.
            (has_pointer_operand_p): New.
            (range_op_handler::fold_range): Add pointer support.
            (range_op_handler::op1_range): Same.
            (range_op_handler::op2_range): Same.
            (range_op_handler::lhs_op1_relation): Same.
            (range_op_handler::lhs_op2_relation): Same.
            (range_op_handler::op1_op2_relation): Same.
            (class operator_div): Add using.
            (class operator_lshift): Add using.
            (class operator_rshift):Add using.
            (class operator_trunc_mod):Add using.
            (class operator_absu):Add using.
            * range-op.h (enum range_op_dispatch_type): New.
            Add extern definitions for RO_*.

Diff:
---
 gcc/range-op-mixed.h |  19 +++++
 gcc/range-op-ptr.cc  | 220 +++++++++++++++++++++++++++++++++++++++++++++++++++
 gcc/range-op.cc      | 124 +++++++++++++++++++++++++++++
 gcc/range-op.h       | 111 ++++++++++++++++++++++++++
 4 files changed, 474 insertions(+)

diff --git a/gcc/range-op-mixed.h b/gcc/range-op-mixed.h
index 3ee7c9d6e0d..8163a4b53ca 100644
--- a/gcc/range-op-mixed.h
+++ b/gcc/range-op-mixed.h
@@ -111,6 +111,7 @@ public:
   using range_operator::op1_range;
   using range_operator::op2_range;
   using range_operator::op1_op2_relation;
+  using range_operator::update_bitmask;
   bool fold_range (irange &r, tree type,
                   const irange &op1, const irange &op2,
                   relation_trio = TRIO_VARYING) const final override;
@@ -150,6 +151,7 @@ public:
   using range_operator::op1_range;
   using range_operator::op2_range;
   using range_operator::op1_op2_relation;
+  using range_operator::update_bitmask;
   bool fold_range (irange &r, tree type,
                   const irange &op1, const irange &op2,
                   relation_trio = TRIO_VARYING) const final override;
@@ -189,6 +191,7 @@ public:
   using range_operator::op1_range;
   using range_operator::op2_range;
   using range_operator::op1_op2_relation;
+  using range_operator::update_bitmask;
   bool fold_range (irange &r, tree type,
                   const irange &op1, const irange &op2,
                   relation_trio = TRIO_VARYING) const final override;
@@ -225,6 +228,7 @@ public:
   using range_operator::op1_range;
   using range_operator::op2_range;
   using range_operator::op1_op2_relation;
+  using range_operator::update_bitmask;
   bool fold_range (irange &r, tree type,
                   const irange &op1, const irange &op2,
                   relation_trio = TRIO_VARYING) const final override;
@@ -264,6 +268,7 @@ public:
   using range_operator::op1_range;
   using range_operator::op2_range;
   using range_operator::op1_op2_relation;
+  using range_operator::update_bitmask;
   bool fold_range (irange &r, tree type,
                   const irange &op1, const irange &op2,
                   relation_trio = TRIO_VARYING) const final override;
@@ -302,6 +307,7 @@ public:
   using range_operator::op1_range;
   using range_operator::op2_range;
   using range_operator::op1_op2_relation;
+  using range_operator::update_bitmask;
   bool fold_range (irange &r, tree type,
                   const irange &op1, const irange &op2,
                   relation_trio = TRIO_VARYING) const final override;
@@ -376,6 +382,7 @@ public:
   using range_operator::fold_range;
   using range_operator::op1_range;
   using range_operator::lhs_op1_relation;
+  using range_operator::update_bitmask;
   bool fold_range (irange &r, tree type,
                   const irange &op1, const irange &op2,
                   relation_trio rel = TRIO_VARYING) const final override;
@@ -402,6 +409,7 @@ public:
   using range_operator::op2_range;
   using range_operator::lhs_op1_relation;
   using range_operator::lhs_op2_relation;
+  using range_operator::update_bitmask;
   bool op1_range (irange &r, tree type,
                  const irange &lhs, const irange &op2,
                  relation_trio) const final override;
@@ -445,6 +453,7 @@ class operator_abs : public range_operator
  public:
   using range_operator::fold_range;
   using range_operator::op1_range;
+  using range_operator::update_bitmask;
   bool fold_range (frange &r, tree type,
                   const frange &op1, const frange &,
                   relation_trio = TRIO_VARYING) const final override;
@@ -473,6 +482,8 @@ public:
   using range_operator::op1_range;
   using range_operator::op2_range;
   using range_operator::lhs_op1_relation;
+  using range_operator::op1_op2_relation_effect;
+  using range_operator::update_bitmask;
   bool op1_range (irange &r, tree type,
                  const irange &lhs, const irange &op2,
                  relation_trio) const final override;
@@ -556,6 +567,7 @@ class operator_mult : public cross_product_operator
 public:
   using range_operator::op1_range;
   using range_operator::op2_range;
+  using range_operator::update_bitmask;
   bool op1_range (irange &r, tree type,
                  const irange &lhs, const irange &op2,
                  relation_trio) const final override;
@@ -608,6 +620,7 @@ class operator_bitwise_not : public range_operator
 public:
   using range_operator::fold_range;
   using range_operator::op1_range;
+  using range_operator::update_bitmask;
   bool fold_range (irange &r, tree type,
                   const irange &lh, const irange &rh,
                   relation_trio rel = TRIO_VARYING) const final override;
@@ -626,6 +639,8 @@ class operator_bitwise_xor : public range_operator
 public:
   using range_operator::op1_range;
   using range_operator::op2_range;
+  using range_operator::op1_op2_relation_effect;
+  using range_operator::update_bitmask;
   bool op1_range (irange &r, tree type,
                  const irange &lhs, const irange &op2,
                  relation_trio rel = TRIO_VARYING) const final override;
@@ -654,6 +669,7 @@ public:
   using range_operator::op1_range;
   using range_operator::op2_range;
   using range_operator::lhs_op1_relation;
+  using range_operator::update_bitmask;
   bool op1_range (irange &r, tree type,
                  const irange &lhs, const irange &op2,
                  relation_trio rel = TRIO_VARYING) const override;
@@ -682,6 +698,7 @@ class operator_bitwise_or : public range_operator
 public:
   using range_operator::op1_range;
   using range_operator::op2_range;
+  using range_operator::update_bitmask;
   bool op1_range (irange &r, tree type,
                  const irange &lhs, const irange &op2,
                  relation_trio rel = TRIO_VARYING) const override;
@@ -702,6 +719,7 @@ protected:
 class operator_min : public range_operator
 {
 public:
+  using range_operator::update_bitmask;
   void update_bitmask (irange &r, const irange &lh,
                       const irange &rh) const override;
   // Check compatibility of all operands.
@@ -716,6 +734,7 @@ protected:
 class operator_max : public range_operator
 {
 public:
+  using range_operator::update_bitmask;
   void update_bitmask (irange &r, const irange &lh,
       const irange &rh) const override;
   // Check compatibility of all operands.
diff --git a/gcc/range-op-ptr.cc b/gcc/range-op-ptr.cc
index 7343ef635f3..560c798b90a 100644
--- a/gcc/range-op-ptr.cc
+++ b/gcc/range-op-ptr.cc
@@ -49,8 +49,222 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-ssa-ccp.h"
 #include "range-op-mixed.h"
 
+// Return TRUE if a range-op folder TYPE either handles or can safely
+// ignore the dispatch pattern in DISPATCH.  Return FALSE for any
+// combination not handled, which will result in a hard fail up the
+// chain.
+
+bool
+range_operator::pointers_handled_p (range_op_dispatch_type ATTRIBUTE_UNUSED,
+                                   unsigned dispatch ATTRIBUTE_UNUSED) const
+{
+  return false;
+}
+
+bool
+range_operator::fold_range (prange &r, tree type,
+                           const prange &op1,
+                           const prange &op2,
+                           relation_trio trio) const
+{
+  relation_kind rel = trio.op1_op2 ();
+  r.set_varying (type);
+  op1_op2_relation_effect (r, type, op1, op2, rel);
+  return true;
+}
+
+bool
+range_operator::fold_range (prange &r, tree type,
+                           const prange &op1,
+                           const irange &op2,
+                           relation_trio trio) const
+{
+  relation_kind rel = trio.op1_op2 ();
+  r.set_varying (type);
+  op1_op2_relation_effect (r, type, op1, op2, rel);
+  return true;
+}
+
+bool
+range_operator::fold_range (irange &r, tree type,
+                           const prange &op1,
+                           const prange &op2,
+                           relation_trio trio) const
+{
+  relation_kind rel = trio.op1_op2 ();
+  r.set_varying (type);
+  op1_op2_relation_effect (r, type, op1, op2, rel);
+  return true;
+}
+
+bool
+range_operator::fold_range (prange &r, tree type,
+                           const irange &op1,
+                           const prange &op2,
+                           relation_trio trio) const
+{
+  relation_kind rel = trio.op1_op2 ();
+  r.set_varying (type);
+  op1_op2_relation_effect (r, type, op1, op2, rel);
+  return true;
+}
+
+bool
+range_operator::fold_range (irange &r, tree type,
+                           const prange &op1,
+                           const irange &op2,
+                           relation_trio trio) const
+{
+  relation_kind rel = trio.op1_op2 ();
+  r.set_varying (type);
+  op1_op2_relation_effect (r, type, op1, op2, rel);
+  return true;
+}
+
+bool
+range_operator::op1_op2_relation_effect (prange &, tree,
+                                        const prange &,
+                                        const prange &,
+                                        relation_kind) const
+{
+  return false;
+}
+
+bool
+range_operator::op1_op2_relation_effect (prange &, tree,
+                                        const prange &,
+                                        const irange &,
+                                        relation_kind) const
+{
+  return false;
+}
+
+bool
+range_operator::op1_op2_relation_effect (irange &, tree,
+                                        const prange &,
+                                        const prange &,
+                                        relation_kind) const
+{
+  return false;
+}
+
+bool
+range_operator::op1_op2_relation_effect (prange &, tree,
+                                        const irange &,
+                                        const prange &,
+                                        relation_kind) const
+{
+  return false;
+}
+
+bool
+range_operator::op1_op2_relation_effect (irange &, tree,
+                                        const prange &,
+                                        const irange &,
+                                        relation_kind) const
+{
+  return false;
+}
+
+bool
+range_operator::op1_range (prange &, tree,
+                          const prange &lhs ATTRIBUTE_UNUSED,
+                          const prange &op2 ATTRIBUTE_UNUSED,
+                          relation_trio) const
+{
+  return false;
+}
+
+bool
+range_operator::op1_range (prange &, tree,
+                          const irange &lhs ATTRIBUTE_UNUSED,
+                          const prange &op2 ATTRIBUTE_UNUSED,
+                          relation_trio) const
+{
+  return false;
+}
+
+bool
+range_operator::op1_range (prange &, tree,
+                          const prange &lhs ATTRIBUTE_UNUSED,
+                          const irange &op2 ATTRIBUTE_UNUSED,
+                          relation_trio) const
+{
+  return false;
+}
+
+bool
+range_operator::op1_range (irange &, tree,
+                          const prange &lhs ATTRIBUTE_UNUSED,
+                          const irange &op2 ATTRIBUTE_UNUSED,
+                          relation_trio) const
+{
+  return false;
+}
+
+bool
+range_operator::op2_range (prange &, tree,
+                          const irange &lhs ATTRIBUTE_UNUSED,
+                          const prange &op1 ATTRIBUTE_UNUSED,
+                          relation_trio) const
+{
+  return false;
+}
+
+bool
+range_operator::op2_range (irange &, tree,
+                          const prange &lhs ATTRIBUTE_UNUSED,
+                          const prange &op1 ATTRIBUTE_UNUSED,
+                          relation_trio) const
+{
+  return false;
+}
+
+relation_kind
+range_operator::op1_op2_relation (const irange &lhs ATTRIBUTE_UNUSED,
+                                 const prange &op1 ATTRIBUTE_UNUSED,
+                                 const prange &op2 ATTRIBUTE_UNUSED) const
+{
+  return VREL_VARYING;
+}
+
+relation_kind
+range_operator::lhs_op1_relation (const prange &lhs ATTRIBUTE_UNUSED,
+                                 const irange &op1 ATTRIBUTE_UNUSED,
+                                 const irange &op2 ATTRIBUTE_UNUSED,
+                                 relation_kind rel ATTRIBUTE_UNUSED) const
+{
+  return VREL_VARYING;
+}
+
+relation_kind
+range_operator::lhs_op1_relation (const irange &lhs ATTRIBUTE_UNUSED,
+                                 const prange &op1 ATTRIBUTE_UNUSED,
+                                 const prange &op2 ATTRIBUTE_UNUSED,
+                                 relation_kind rel ATTRIBUTE_UNUSED) const
+{
+  return VREL_VARYING;
+}
+
+relation_kind
+range_operator::lhs_op1_relation (const prange &lhs ATTRIBUTE_UNUSED,
+                                 const prange &op1 ATTRIBUTE_UNUSED,
+                                 const prange &op2 ATTRIBUTE_UNUSED,
+                                 relation_kind rel ATTRIBUTE_UNUSED) const
+{
+  return VREL_VARYING;
+}
+
+void
+range_operator::update_bitmask (irange &,
+                               const prange &,
+                               const prange &) const
+{
+}
+
 class pointer_plus_operator : public range_operator
 {
+  using range_operator::update_bitmask;
   using range_operator::op2_range;
 public:
   virtual void wi_fold (irange &r, tree type,
@@ -245,6 +459,8 @@ pointer_or_operator::wi_fold (irange &r, tree type,
 
 class operator_pointer_diff : public range_operator
 {
+  using range_operator::update_bitmask;
+  using range_operator::op1_op2_relation_effect;
   virtual bool op1_op2_relation_effect (irange &lhs_range,
                                        tree type,
                                        const irange &op1_range,
@@ -274,6 +490,7 @@ operator_pointer_diff::op1_op2_relation_effect (irange 
&lhs_range, tree type,
 class hybrid_and_operator : public operator_bitwise_and
 {
 public:
+  using range_operator::update_bitmask;
   using range_operator::op1_range;
   using range_operator::op2_range;
   using range_operator::lhs_op1_relation;
@@ -330,6 +547,7 @@ public:
 class hybrid_or_operator : public operator_bitwise_or
 {
 public:
+  using range_operator::update_bitmask;
   using range_operator::op1_range;
   using range_operator::op2_range;
   using range_operator::lhs_op1_relation;
@@ -376,6 +594,7 @@ public:
 
 class hybrid_min_operator : public operator_min
 {
+  using range_operator::update_bitmask;
 public:
   void update_bitmask (irange &r, const irange &lh,
                       const irange &rh) const final override
@@ -397,6 +616,7 @@ public:
 
 class hybrid_max_operator : public operator_max
 {
+  using range_operator::update_bitmask;
 public:
   void update_bitmask (irange &r, const irange &lh,
                       const irange &rh) const final override
diff --git a/gcc/range-op.cc b/gcc/range-op.cc
index ab3a4f0b200..65f3843227d 100644
--- a/gcc/range-op.cc
+++ b/gcc/range-op.cc
@@ -181,6 +181,12 @@ const unsigned RO_IFF = dispatch_trio (VR_IRANGE, 
VR_FRANGE, VR_FRANGE);
 const unsigned RO_FFF = dispatch_trio (VR_FRANGE, VR_FRANGE, VR_FRANGE);
 const unsigned RO_FIF = dispatch_trio (VR_FRANGE, VR_IRANGE, VR_FRANGE);
 const unsigned RO_FII = dispatch_trio (VR_FRANGE, VR_IRANGE, VR_IRANGE);
+const unsigned RO_PPP = dispatch_trio (VR_PRANGE, VR_PRANGE, VR_PRANGE);
+const unsigned RO_PPI = dispatch_trio (VR_PRANGE, VR_PRANGE, VR_IRANGE);
+const unsigned RO_IPP = dispatch_trio (VR_IRANGE, VR_PRANGE, VR_PRANGE);
+const unsigned RO_IPI = dispatch_trio (VR_IRANGE, VR_PRANGE, VR_IRANGE);
+const unsigned RO_PIP = dispatch_trio (VR_PRANGE, VR_IRANGE, VR_PRANGE);
+const unsigned RO_PII = dispatch_trio (VR_PRANGE, VR_IRANGE, VR_IRANGE);
 
 // Return a dispatch value for parameter types LHS, OP1 and OP2.
 
@@ -192,6 +198,28 @@ range_op_handler::dispatch_kind (const vrange &lhs, const 
vrange &op1,
                        op2.m_discriminator);
 }
 
+void
+range_op_handler::discriminator_fail (const vrange &r1,
+                                     const vrange &r2,
+                                     const vrange &r3) const
+{
+  const char name[] = "IPF";
+  gcc_checking_assert (r1.m_discriminator < sizeof (name) - 1);
+  gcc_checking_assert (r2.m_discriminator < sizeof (name) - 1);
+  gcc_checking_assert (r3.m_discriminator < sizeof (name) - 1);
+  fprintf (stderr, "DISCRIMINATOR FAIL.  Dispatch ====> RO_%c%c%c <====\n",
+          name[r1.m_discriminator],
+          name[r2.m_discriminator],
+          name[r3.m_discriminator]);
+  gcc_unreachable ();
+}
+
+static inline bool
+has_pointer_operand_p (const vrange &r1, const vrange &r2, const vrange &r3)
+{
+  return is_a <prange> (r1) || is_a <prange> (r2) || is_a <prange> (r3);
+}
+
 // Dispatch a call to fold_range based on the types of R, LH and RH.
 
 bool
@@ -204,6 +232,10 @@ range_op_handler::fold_range (vrange &r, tree type,
 #if CHECKING_P
   if (!lh.undefined_p () && !rh.undefined_p ())
     gcc_assert (m_operator->operand_check_p (type, lh.type (), rh.type ()));
+  if (has_pointer_operand_p (r, lh, rh)
+      && !m_operator->pointers_handled_p (DISPATCH_FOLD_RANGE,
+                                         dispatch_kind (r, lh, rh)))
+    discriminator_fail (r, lh, rh);
 #endif
   switch (dispatch_kind (r, lh, rh))
     {
@@ -227,6 +259,26 @@ range_op_handler::fold_range (vrange &r, tree type,
        return m_operator->fold_range (as_a <frange> (r), type,
                                       as_a <irange> (lh),
                                       as_a <irange> (rh), rel);
+      case RO_PPP:
+       return m_operator->fold_range (as_a <prange> (r), type,
+                                      as_a <prange> (lh),
+                                      as_a <prange> (rh), rel);
+      case RO_PPI:
+       return m_operator->fold_range (as_a <prange> (r), type,
+                                      as_a <prange> (lh),
+                                      as_a <irange> (rh), rel);
+      case RO_IPP:
+       return m_operator->fold_range (as_a <irange> (r), type,
+                                      as_a <prange> (lh),
+                                      as_a <prange> (rh), rel);
+      case RO_PIP:
+       return m_operator->fold_range (as_a <prange> (r), type,
+                                      as_a <irange> (lh),
+                                      as_a <prange> (rh), rel);
+      case RO_IPI:
+       return m_operator->fold_range (as_a <irange> (r), type,
+                                      as_a <prange> (lh),
+                                      as_a <irange> (rh), rel);
       default:
        return false;
     }
@@ -246,6 +298,10 @@ range_op_handler::op1_range (vrange &r, tree type,
 #if CHECKING_P
   if (!op2.undefined_p ())
     gcc_assert (m_operator->operand_check_p (lhs.type (), type, op2.type ()));
+  if (has_pointer_operand_p (r, lhs, op2)
+      && !m_operator->pointers_handled_p (DISPATCH_OP1_RANGE,
+                                         dispatch_kind (r, lhs, op2)))
+    discriminator_fail (r, lhs, op2);
 #endif
   switch (dispatch_kind (r, lhs, op2))
     {
@@ -253,6 +309,22 @@ range_op_handler::op1_range (vrange &r, tree type,
        return m_operator->op1_range (as_a <irange> (r), type,
                                      as_a <irange> (lhs),
                                      as_a <irange> (op2), rel);
+      case RO_PPP:
+       return m_operator->op1_range (as_a <prange> (r), type,
+                                     as_a <prange> (lhs),
+                                     as_a <prange> (op2), rel);
+      case RO_PIP:
+       return m_operator->op1_range (as_a <prange> (r), type,
+                                     as_a <irange> (lhs),
+                                     as_a <prange> (op2), rel);
+      case RO_PPI:
+       return m_operator->op1_range (as_a <prange> (r), type,
+                                     as_a <prange> (lhs),
+                                     as_a <irange> (op2), rel);
+      case RO_IPI:
+       return m_operator->op1_range (as_a <irange> (r), type,
+                                     as_a <prange> (lhs),
+                                     as_a <irange> (op2), rel);
       case RO_FIF:
        return m_operator->op1_range (as_a <frange> (r), type,
                                      as_a <irange> (lhs),
@@ -280,6 +352,10 @@ range_op_handler::op2_range (vrange &r, tree type,
 #if CHECKING_P
   if (!op1.undefined_p ())
     gcc_assert (m_operator->operand_check_p (lhs.type (), op1.type (), type));
+  if (has_pointer_operand_p (r, lhs, op1)
+      && !m_operator->pointers_handled_p (DISPATCH_OP2_RANGE,
+                                         dispatch_kind (r, lhs, op1)))
+    discriminator_fail (r, lhs, op1);
 #endif
   switch (dispatch_kind (r, lhs, op1))
     {
@@ -287,6 +363,14 @@ range_op_handler::op2_range (vrange &r, tree type,
        return m_operator->op2_range (as_a <irange> (r), type,
                                      as_a <irange> (lhs),
                                      as_a <irange> (op1), rel);
+      case RO_PIP:
+       return m_operator->op2_range (as_a <prange> (r), type,
+                                     as_a <irange> (lhs),
+                                     as_a <prange> (op1), rel);
+      case RO_IPP:
+       return m_operator->op2_range (as_a <irange> (r), type,
+                                     as_a <prange> (lhs),
+                                     as_a <prange> (op1), rel);
       case RO_FIF:
        return m_operator->op2_range (as_a <frange> (r), type,
                                      as_a <irange> (lhs),
@@ -309,6 +393,12 @@ range_op_handler::lhs_op1_relation (const vrange &lhs,
                                    relation_kind rel) const
 {
   gcc_checking_assert (m_operator);
+#if CHECKING_P
+  if (has_pointer_operand_p (lhs, op1, op2)
+      && !m_operator->pointers_handled_p (DISPATCH_LHS_OP1_RELATION,
+                                         dispatch_kind (lhs, op1, op2)))
+    discriminator_fail (lhs, op1, op2);
+#endif
 
   switch (dispatch_kind (lhs, op1, op2))
     {
@@ -316,6 +406,18 @@ range_op_handler::lhs_op1_relation (const vrange &lhs,
        return m_operator->lhs_op1_relation (as_a <irange> (lhs),
                                             as_a <irange> (op1),
                                             as_a <irange> (op2), rel);
+      case RO_PPP:
+       return m_operator->lhs_op1_relation (as_a <prange> (lhs),
+                                            as_a <prange> (op1),
+                                            as_a <prange> (op2), rel);
+      case RO_IPP:
+       return m_operator->lhs_op1_relation (as_a <irange> (lhs),
+                                            as_a <prange> (op1),
+                                            as_a <prange> (op2), rel);
+      case RO_PII:
+       return m_operator->lhs_op1_relation (as_a <prange> (lhs),
+                                            as_a <irange> (op1),
+                                            as_a <irange> (op2), rel);
       case RO_IFF:
        return m_operator->lhs_op1_relation (as_a <irange> (lhs),
                                             as_a <frange> (op1),
@@ -338,6 +440,12 @@ range_op_handler::lhs_op2_relation (const vrange &lhs,
                                    relation_kind rel) const
 {
   gcc_checking_assert (m_operator);
+#if CHECKING_P
+  if (has_pointer_operand_p (lhs, op1, op2)
+      && !m_operator->pointers_handled_p (DISPATCH_LHS_OP2_RELATION,
+                                         dispatch_kind (lhs, op1, op2)))
+    discriminator_fail (lhs, op1, op2);
+#endif
   switch (dispatch_kind (lhs, op1, op2))
     {
       case RO_III:
@@ -365,6 +473,12 @@ range_op_handler::op1_op2_relation (const vrange &lhs,
                                    const vrange &op2) const
 {
   gcc_checking_assert (m_operator);
+#if CHECKING_P
+  if (has_pointer_operand_p (lhs, op1, op2)
+      && !m_operator->pointers_handled_p (DISPATCH_OP1_OP2_RELATION,
+                                         dispatch_kind (lhs, op1, op2)))
+    discriminator_fail (lhs, op1, op2);
+#endif
   switch (dispatch_kind (lhs, op1, op2))
     {
       case RO_III:
@@ -372,6 +486,11 @@ range_op_handler::op1_op2_relation (const vrange &lhs,
                                             as_a <irange> (op1),
                                             as_a <irange> (op2));
 
+      case RO_IPP:
+       return m_operator->op1_op2_relation (as_a <irange> (lhs),
+                                            as_a <prange> (op1),
+                                            as_a <prange> (op2));
+
       case RO_IFF:
        return m_operator->op1_op2_relation (as_a <irange> (lhs),
                                             as_a <frange> (op1),
@@ -2327,6 +2446,7 @@ operator_widen_mult_unsigned::wi_fold (irange &r, tree 
type,
 
 class operator_div : public cross_product_operator
 {
+  using range_operator::update_bitmask;
 public:
   operator_div (tree_code div_kind) { m_code = div_kind; }
   virtual void wi_fold (irange &r, tree type,
@@ -2474,6 +2594,7 @@ class operator_lshift : public cross_product_operator
 {
   using range_operator::fold_range;
   using range_operator::op1_range;
+  using range_operator::update_bitmask;
 public:
   virtual bool op1_range (irange &r, tree type, const irange &lhs,
                          const irange &op2, relation_trio rel = TRIO_VARYING)
@@ -2503,6 +2624,7 @@ class operator_rshift : public cross_product_operator
   using range_operator::fold_range;
   using range_operator::op1_range;
   using range_operator::lhs_op1_relation;
+  using range_operator::update_bitmask;
 public:
   virtual bool fold_range (irange &r, tree type, const irange &op1,
                           const irange &op2, relation_trio rel = TRIO_VARYING)
@@ -3883,6 +4005,7 @@ class operator_trunc_mod : public range_operator
 {
   using range_operator::op1_range;
   using range_operator::op2_range;
+  using range_operator::update_bitmask;
 public:
   virtual void wi_fold (irange &r, tree type,
                        const wide_int &lh_lb,
@@ -4305,6 +4428,7 @@ operator_abs::update_bitmask (irange &r, const irange &lh,
 
 class operator_absu : public range_operator
 {
+  using range_operator::update_bitmask;
  public:
   virtual void wi_fold (irange &r, tree type,
                        const wide_int &lh_lb, const wide_int &lh_ub,
diff --git a/gcc/range-op.h b/gcc/range-op.h
index 44a3e4f009f..2bad5a90e11 100644
--- a/gcc/range-op.h
+++ b/gcc/range-op.h
@@ -22,6 +22,16 @@ along with GCC; see the file COPYING3.  If not see
 #ifndef GCC_RANGE_OP_H
 #define GCC_RANGE_OP_H
 
+enum range_op_dispatch_type
+{
+  DISPATCH_FOLD_RANGE,
+  DISPATCH_OP1_RANGE,
+  DISPATCH_OP2_RANGE,
+  DISPATCH_LHS_OP1_RELATION,
+  DISPATCH_LHS_OP2_RELATION,
+  DISPATCH_OP1_OP2_RELATION
+};
+
 // This class is implemented for each kind of operator supported by
 // the range generator.  It serves various purposes.
 //
@@ -76,6 +86,26 @@ public:
                           const irange &lh,
                           const irange &rh,
                           relation_trio = TRIO_VARYING) const;
+  virtual bool fold_range (prange &r, tree type,
+                          const prange &lh,
+                          const prange &rh,
+                          relation_trio = TRIO_VARYING) const;
+  virtual bool fold_range (prange &r, tree type,
+                          const prange &lh,
+                          const irange &rh,
+                          relation_trio = TRIO_VARYING) const;
+  virtual bool fold_range (irange &r, tree type,
+                          const prange &lh,
+                          const prange &rh,
+                          relation_trio = TRIO_VARYING) const;
+  virtual bool fold_range (prange &r, tree type,
+                          const irange &lh,
+                          const prange &rh,
+                          relation_trio = TRIO_VARYING) const;
+  virtual bool fold_range (irange &r, tree type,
+                          const prange &lh,
+                          const irange &rh,
+                          relation_trio = TRIO_VARYING) const;
 
   // Return the range for op[12] in the general case.  LHS is the range for
   // the LHS of the expression, OP[12]is the range for the other
@@ -92,6 +122,22 @@ public:
                          const irange &lhs,
                          const irange &op2,
                          relation_trio = TRIO_VARYING) const;
+  virtual bool op1_range (prange &r, tree type,
+                         const prange &lhs,
+                         const prange &op2,
+                         relation_trio = TRIO_VARYING) const;
+  virtual bool op1_range (prange &r, tree type,
+                         const irange &lhs,
+                         const prange &op2,
+                         relation_trio = TRIO_VARYING) const;
+  virtual bool op1_range (prange &r, tree type,
+                         const prange &lhs,
+                         const irange &op2,
+                         relation_trio = TRIO_VARYING) const;
+  virtual bool op1_range (irange &r, tree type,
+                         const prange &lhs,
+                         const irange &op2,
+                         relation_trio = TRIO_VARYING) const;
   virtual bool op1_range (frange &r, tree type,
                          const frange &lhs,
                          const frange &op2,
@@ -106,6 +152,14 @@ public:
                          const irange &lhs,
                          const irange &op1,
                          relation_trio = TRIO_VARYING) const;
+  virtual bool op2_range (prange &r, tree type,
+                         const irange &lhs,
+                         const prange &op1,
+                         relation_trio = TRIO_VARYING) const;
+  virtual bool op2_range (irange &r, tree type,
+                         const prange &lhs,
+                         const prange &op1,
+                         relation_trio = TRIO_VARYING) const;
   virtual bool op2_range (frange &r, tree type,
                          const frange &lhs,
                          const frange &op1,
@@ -123,6 +177,18 @@ public:
                                          const irange &op1,
                                          const irange &op2,
                                          relation_kind = VREL_VARYING) const;
+  virtual relation_kind lhs_op1_relation (const prange &lhs,
+                                         const prange &op1,
+                                         const prange &op2,
+                                         relation_kind = VREL_VARYING) const;
+  virtual relation_kind lhs_op1_relation (const prange &lhs,
+                                         const irange &op1,
+                                         const irange &op2,
+                                         relation_kind = VREL_VARYING) const;
+  virtual relation_kind lhs_op1_relation (const irange &lhs,
+                                         const prange &op1,
+                                         const prange &op2,
+                                         relation_kind = VREL_VARYING) const;
   virtual relation_kind lhs_op1_relation (const frange &lhs,
                                          const frange &op1,
                                          const frange &op2,
@@ -148,6 +214,9 @@ public:
   virtual relation_kind op1_op2_relation (const irange &lhs,
                                          const irange &op1,
                                          const irange &op2) const;
+  virtual relation_kind op1_op2_relation (const irange &lhs,
+                                         const prange &op1,
+                                         const prange &op2) const;
   virtual relation_kind op1_op2_relation (const irange &lhs,
                                          const frange &op1,
                                          const frange &op2) const;
@@ -160,6 +229,7 @@ public:
 
   // Compatability check for operands.
   virtual bool operand_check_p (tree, tree, tree) const;
+  virtual bool pointers_handled_p (enum range_op_dispatch_type, unsigned) 
const;
 
 protected:
   // Perform an integral operation between 2 sub-ranges and return it.
@@ -173,6 +243,26 @@ protected:
                                        const irange &op1_range,
                                        const irange &op2_range,
                                        relation_kind rel) const;
+  virtual bool op1_op2_relation_effect (prange &lhs_range, tree type,
+                                       const prange &op1_range,
+                                       const prange &op2_range,
+                                       relation_kind rel) const;
+  virtual bool op1_op2_relation_effect (prange &lhs_range, tree type,
+                                       const prange &op1_range,
+                                       const irange &op2_range,
+                                       relation_kind rel) const;
+  virtual bool op1_op2_relation_effect (irange &lhs_range, tree type,
+                                       const prange &op1_range,
+                                       const prange &op2_range,
+                                       relation_kind rel) const;
+  virtual bool op1_op2_relation_effect (prange &lhs_range, tree type,
+                                       const irange &op1_range,
+                                       const prange &op2_range,
+                                       relation_kind rel) const;
+  virtual bool op1_op2_relation_effect (irange &lhs_range, tree type,
+                                       const prange &op1_range,
+                                       const irange &op2_range,
+                                       relation_kind rel) const;
   // Called by fold range to split small subranges into parts.
   void wi_fold_in_parts (irange &r, tree type,
                         const wide_int &lh_lb,
@@ -187,6 +277,7 @@ protected:
                               unsigned limit) const;
   // Apply any bitmasks implied by these ranges.
   virtual void update_bitmask (irange &, const irange &, const irange &) const;
+  virtual void update_bitmask (irange &, const prange &, const prange &) const;
 
   // Perform an float operation between 2 ranges and return it.
   virtual void rv_fold (frange &r, tree type,
@@ -234,6 +325,9 @@ public:
 protected:
   unsigned dispatch_kind (const vrange &lhs, const vrange &op1,
                          const vrange& op2) const;
+  void discriminator_fail (const vrange &,
+                          const vrange &,
+                          const vrange &) const;
   range_operator *m_operator;
 };
 
@@ -316,4 +410,21 @@ protected:
   void initialize_pointer_ops ();
   void initialize_float_ops ();
 };
+
+// Temporary exports so the pointers_handled_p() sanity code can see
+// which pointer combination is being attempted.  This will be deleted
+// once pointers_handled_p is gone.
+extern const unsigned RO_III;
+extern const unsigned RO_IFI;
+extern const unsigned RO_IFF;
+extern const unsigned RO_FFF;
+extern const unsigned RO_FIF;
+extern const unsigned RO_FII;
+extern const unsigned RO_PPP;
+extern const unsigned RO_PPI;
+extern const unsigned RO_IPP;
+extern const unsigned RO_IPI;
+extern const unsigned RO_PIP;
+extern const unsigned RO_PII;
+
 #endif // GCC_RANGE_OP_H

Reply via email to