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_*. --- 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 -- 2.44.0