@@ -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.
@@ -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
@@ -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,
@@ -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