From 8adb8b2fd5797706e9fbb353d52fda123545431d Mon Sep 17 00:00:00 2001 From: Andrew MacLeod Date: Sat, 10 Jun 2023 16:28:40 -0400 Subject: [PATCH 09/17] Add a hybrid BIT_AND_EXPR operator for integer and pointer. This adds an operator to the unified table for BIT_AND_EXPR which will select either the pointer or integer version based on the type passed to the method. This is for use until we have a seperate PRANGE class. * range-op-mixed.h (operator_bitwise_and): Remove final. * range-op-ptr.cc (pointer_table::pointer_table): Remove BIT_AND_EXPR. (class hybrid_and_operator): New. (range_op_table::initialize_pointer_ops): Add hybrid_and_operator. * range-op.cc (unified_table::unified_table): Comment out BIT_AND_EXPR. --- gcc/range-op-mixed.h | 12 ++++----- gcc/range-op-ptr.cc | 62 +++++++++++++++++++++++++++++++++++++++++++- gcc/range-op.cc | 9 ++++--- 3 files changed, 73 insertions(+), 10 deletions(-) diff --git a/gcc/range-op-mixed.h b/gcc/range-op-mixed.h index b188f5a516e..4177818e4b9 100644 --- a/gcc/range-op-mixed.h +++ b/gcc/range-op-mixed.h @@ -584,19 +584,19 @@ public: using range_operator::lhs_op1_relation; bool op1_range (irange &r, tree type, const irange &lhs, const irange &op2, - relation_trio rel = TRIO_VARYING) const final override; + relation_trio rel = TRIO_VARYING) const override; bool op2_range (irange &r, tree type, const irange &lhs, const irange &op1, - relation_trio rel = TRIO_VARYING) const final override; + relation_trio rel = TRIO_VARYING) const override; relation_kind lhs_op1_relation (const irange &lhs, const irange &op1, const irange &op2, - relation_kind) const final override; + relation_kind) const override; void update_bitmask (irange &r, const irange &lh, - const irange &rh) const final override; -private: + const irange &rh) const override; +protected: void wi_fold (irange &r, tree type, const wide_int &lh_lb, const wide_int &lh_ub, const wide_int &rh_lb, - const wide_int &rh_ub) const final override; + const wide_int &rh_ub) const override; void simple_op1_range_solver (irange &r, tree type, const irange &lhs, const irange &op2) const; diff --git a/gcc/range-op-ptr.cc b/gcc/range-op-ptr.cc index 55c37cc8c86..941026994ed 100644 --- a/gcc/range-op-ptr.cc +++ b/gcc/range-op-ptr.cc @@ -270,12 +270,71 @@ operator_pointer_diff::op1_op2_relation_effect (irange &lhs_range, tree type, pointer_table::pointer_table () { - set (BIT_AND_EXPR, op_pointer_and); set (BIT_IOR_EXPR, op_pointer_or); set (MIN_EXPR, op_ptr_min_max); set (MAX_EXPR, op_ptr_min_max); } +// ---------------------------------------------------------------------- +// Hybrid operators for the 4 operations which integer and pointers share, +// but which have different implementations. Simply check the type in +// the call and choose the appropriate method. +// Once there is a PRANGE signature, simply add the appropriate +// prototypes in the rmixed range class, and remove these hybrid classes. + +class hybrid_and_operator : public operator_bitwise_and +{ +public: + using range_operator::op1_range; + using range_operator::op2_range; + using range_operator::lhs_op1_relation; + bool op1_range (irange &r, tree type, + const irange &lhs, const irange &op2, + relation_trio rel = TRIO_VARYING) const final override + { + if (INTEGRAL_TYPE_P (type)) + return operator_bitwise_and::op1_range (r, type, lhs, op2, rel); + else + return false; + } + bool op2_range (irange &r, tree type, + const irange &lhs, const irange &op1, + relation_trio rel = TRIO_VARYING) const final override + { + if (INTEGRAL_TYPE_P (type)) + return operator_bitwise_and::op2_range (r, type, lhs, op1, rel); + else + return false; + } + relation_kind lhs_op1_relation (const irange &lhs, + const irange &op1, const irange &op2, + relation_kind rel) const final override + { + if (!lhs.undefined_p () && INTEGRAL_TYPE_P (lhs.type ())) + return operator_bitwise_and::lhs_op1_relation (lhs, op1, op2, rel); + else + return VREL_VARYING; + } + void update_bitmask (irange &r, const irange &lh, + const irange &rh) const final override + { + if (!r.undefined_p () && INTEGRAL_TYPE_P (r.type ())) + operator_bitwise_and::update_bitmask (r, lh, rh); + } + + void wi_fold (irange &r, tree type, const wide_int &lh_lb, + const wide_int &lh_ub, const wide_int &rh_lb, + const wide_int &rh_ub) const final override + { + if (INTEGRAL_TYPE_P (type)) + return operator_bitwise_and::wi_fold (r, type, lh_lb, lh_ub, + rh_lb, rh_ub); + else + return op_pointer_and.wi_fold (r, type, lh_lb, lh_ub, rh_lb, rh_ub); + } +} op_hybrid_and; + + // Initialize any pointer operators to the primary table void @@ -283,4 +342,5 @@ range_op_table::initialize_pointer_ops () { set (POINTER_PLUS_EXPR, op_pointer_plus); set (POINTER_DIFF_EXPR, op_pointer_diff); + set (BIT_AND_EXPR, op_hybrid_and); } diff --git a/gcc/range-op.cc b/gcc/range-op.cc index e0cd1b10790..dcb922143ce 100644 --- a/gcc/range-op.cc +++ b/gcc/range-op.cc @@ -116,9 +116,12 @@ unified_table::unified_table () set (BIT_XOR_EXPR, op_bitwise_xor); // These are in both integer and pointer tables, but pointer has a different - // implementation. These also remain in the pointer table until a pointer - // speifc version is provided. - set (BIT_AND_EXPR, op_bitwise_and); + // implementation. + // If commented out, there is a hybrid version in range-op-ptr.cc which + // is used until there is a pointer range class. Then we can simply + // uncomment the operator here and use the unified version. + + //set (BIT_AND_EXPR, op_bitwise_and); set (BIT_IOR_EXPR, op_bitwise_or); set (MIN_EXPR, op_min); set (MAX_EXPR, op_max); -- 2.40.1