From 3c4399657d35a0b5bf7caeb88c6ddc0461322d3f Mon Sep 17 00:00:00 2001 From: Andrew MacLeod Date: Sat, 10 Jun 2023 16:59:38 -0400 Subject: [PATCH 15/17] Provide a default range_operator via range_op_handler. range_op_handler now provides a default range_operator for any opcode, so there is no longer a need to check for a valid operator. * gimple-range-op.cc (gimple_range_op_handler): Set m_operator manually as there is no access to the default operator. (cfn_copysign::fold_range): Don't check for validity. (cfn_ubsan::fold_range): Ditto. (gimple_range_op_handler::maybe_builtin_call): Don't set to NULL. * range-op.cc (default_operator): New. (range_op_handler::range_op_handler): Use default_operator instead of NULL. (range_op_handler::operator bool): Move from header, compare against default operator. (range_op_handler::range_op): New. * range-op.h (range_op_handler::operator bool): Move. --- gcc/gimple-range-op.cc | 28 +++++++++++++--------------- gcc/range-op.cc | 32 ++++++++++++++++++++++++++++++-- gcc/range-op.h | 3 ++- 3 files changed, 45 insertions(+), 18 deletions(-) diff --git a/gcc/gimple-range-op.cc b/gcc/gimple-range-op.cc index 4cbc981ee04..021a9108ecf 100644 --- a/gcc/gimple-range-op.cc +++ b/gcc/gimple-range-op.cc @@ -120,21 +120,22 @@ gimple_range_op_handler::supported_p (gimple *s) // Construct a handler object for statement S. gimple_range_op_handler::gimple_range_op_handler (gimple *s) - : range_op_handler (get_code (s)) { + range_op_handler oper (get_code (s)); m_stmt = s; m_op1 = NULL_TREE; m_op2 = NULL_TREE; - if (m_operator) + if (oper) switch (gimple_code (m_stmt)) { case GIMPLE_COND: m_op1 = gimple_cond_lhs (m_stmt); m_op2 = gimple_cond_rhs (m_stmt); // Check that operands are supported types. One check is enough. - if (!Value_Range::supports_type_p (TREE_TYPE (m_op1))) - m_operator = NULL; + if (Value_Range::supports_type_p (TREE_TYPE (m_op1))) + m_operator = oper.range_op (); + gcc_checking_assert (m_operator); return; case GIMPLE_ASSIGN: m_op1 = gimple_range_base_of_assignment (m_stmt); @@ -153,7 +154,9 @@ gimple_range_op_handler::gimple_range_op_handler (gimple *s) m_op2 = gimple_assign_rhs2 (m_stmt); // Check that operands are supported types. One check is enough. if ((m_op1 && !Value_Range::supports_type_p (TREE_TYPE (m_op1)))) - m_operator = NULL; + return; + m_operator = oper.range_op (); + gcc_checking_assert (m_operator); return; default: gcc_unreachable (); @@ -165,6 +168,7 @@ gimple_range_op_handler::gimple_range_op_handler (gimple *s) maybe_builtin_call (); else maybe_non_standard (); + gcc_checking_assert (m_operator); } // Calculate what we can determine of the range of this unary @@ -364,11 +368,10 @@ public: const frange &rh, relation_trio) const override { frange neg; - range_op_handler abs_op (ABS_EXPR); - range_op_handler neg_op (NEGATE_EXPR); - if (!abs_op || !abs_op.fold_range (r, type, lh, frange (type))) + if (!range_op_handler (ABS_EXPR).fold_range (r, type, lh, frange (type))) return false; - if (!neg_op || !neg_op.fold_range (neg, type, r, frange (type))) + if (!range_op_handler (NEGATE_EXPR).fold_range (neg, type, r, + frange (type))) return false; bool signbit; @@ -1073,14 +1076,11 @@ public: virtual bool fold_range (irange &r, tree type, const irange &lh, const irange &rh, relation_trio rel) const { - range_op_handler handler (m_code); - gcc_checking_assert (handler); - bool saved_flag_wrapv = flag_wrapv; // Pretend the arithmetic is wrapping. If there is any overflow, // we'll complain, but will actually do wrapping operation. flag_wrapv = 1; - bool result = handler.fold_range (r, type, lh, rh, rel); + bool result = range_op_handler (m_code).fold_range (r, type, lh, rh, rel); flag_wrapv = saved_flag_wrapv; // If for both arguments vrp_valueize returned non-NULL, this should @@ -1230,8 +1230,6 @@ gimple_range_op_handler::maybe_builtin_call () m_operator = &op_cfn_constant_p; else if (frange::supports_p (TREE_TYPE (m_op1))) m_operator = &op_cfn_constant_float_p; - else - m_operator = NULL; break; CASE_FLT_FN (CFN_BUILT_IN_SIGNBIT): diff --git a/gcc/range-op.cc b/gcc/range-op.cc index 382f5d50ffa..a271e00fa07 100644 --- a/gcc/range-op.cc +++ b/gcc/range-op.cc @@ -121,16 +121,44 @@ range_op_table::range_op_table () // set (MAX_EXPR, op_max); } +// Instantiate a default range operator for opcodes with no entry. + +range_operator default_operator; + +// Create a default range_op_handler. + range_op_handler::range_op_handler () { - m_operator = NULL; + m_operator = &default_operator; } -// Constructing without a type must come from the unified table. +// Create a range_op_handler for CODE. Use a default operatoer if CODE +// does not have an entry. range_op_handler::range_op_handler (tree_code code) { m_operator = operator_table[code]; + if (!m_operator) + m_operator = &default_operator; +} + +// Return TRUE if this handler has a non-default operator. + +range_op_handler::operator bool () const +{ + return m_operator != &default_operator; +} + +// Return a pointer to the range operator assocaited with this handler. +// If it is a default operator, return NULL. +// This is the equivalent of indexing the range table. + +range_operator * +range_op_handler::range_op () const +{ + if (m_operator != &default_operator) + return m_operator; + return NULL; } // Create a dispatch pattern for value range discriminators LHS, OP1, and OP2. diff --git a/gcc/range-op.h b/gcc/range-op.h index 328910d0ec5..8243258eea5 100644 --- a/gcc/range-op.h +++ b/gcc/range-op.h @@ -186,7 +186,8 @@ class range_op_handler public: range_op_handler (); range_op_handler (enum tree_code code); - inline operator bool () const { return m_operator != NULL; } + operator bool () const; + range_operator *range_op () const; bool fold_range (vrange &r, tree type, const vrange &lh, -- 2.40.1