diff options
author | Aldy Hernandez <aldyh@redhat.com> | 2024-03-20 07:19:45 +0100 |
---|---|---|
committer | Aldy Hernandez <aldyh@redhat.com> | 2024-05-04 10:25:50 +0200 |
commit | 31377eed515506c9e8ba2ac8fa3ab4e743f8c1f3 (patch) | |
tree | 000468092ebaa85e81e52fabd850d4bae88d6d55 /gcc/range-op.cc | |
parent | ddf039adef5e2695f1cb27e0b6e5056fef4be2ee (diff) | |
download | gcc-31377eed515506c9e8ba2ac8fa3ab4e743f8c1f3.zip gcc-31377eed515506c9e8ba2ac8fa3ab4e743f8c1f3.tar.gz gcc-31377eed515506c9e8ba2ac8fa3ab4e743f8c1f3.tar.bz2 |
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_*.
Diffstat (limited to 'gcc/range-op.cc')
-rw-r--r-- | gcc/range-op.cc | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/gcc/range-op.cc b/gcc/range-op.cc index ab3a4f0..65f3843 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, |