aboutsummaryrefslogtreecommitdiff
path: root/gcc/range-op.cc
diff options
context:
space:
mode:
authorAldy Hernandez <aldyh@redhat.com>2024-03-20 07:19:45 +0100
committerAldy Hernandez <aldyh@redhat.com>2024-05-04 10:25:50 +0200
commit31377eed515506c9e8ba2ac8fa3ab4e743f8c1f3 (patch)
tree000468092ebaa85e81e52fabd850d4bae88d6d55 /gcc/range-op.cc
parentddf039adef5e2695f1cb27e0b6e5056fef4be2ee (diff)
downloadgcc-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.cc124
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,