From: Aldy Hernandez <aldyh@redhat.com>
To: GCC patches <gcc-patches@gcc.gnu.org>
Subject: Re: [PATCH 3/5] Convert range-op.* to vrange.
Date: Wed, 1 Jun 2022 11:01:54 +0200 [thread overview]
Message-ID: <CAGm3qMX_MZdv9icgq5_A199XvX0uVZv2T8C7w6RuSwvkqxWozw@mail.gmail.com> (raw)
In-Reply-To: <20220530132751.1752112-3-aldyh@redhat.com>
[-- Attachment #1: Type: text/plain, Size: 50132 bytes --]
Final patch committed.
Re-tested on x86-64 Linux.
On Mon, May 30, 2022 at 3:28 PM Aldy Hernandez <aldyh@redhat.com> wrote:
>
> This patch provides the infrastructure to make range-ops type agnostic.
>
> First, the range_op_handler function has been replaced with an object
> of the same name. It's coded in such a way to minimize changes to the
> code base, and to encapsulate the dispatch code.
>
> Instead of:
>
> range_operator *op = range_op_handler (code, type);
> if (op)
> op->fold_range (...);
>
> We now do:
> range_op_handler op (code, type);
> if (op)
> op->fold_range (...);
>
> I've folded gimple_range_handler into the range_op_handler class,
> since it's also a query into the range operators.
>
> Instead of:
>
> range_operator *handler = gimple_range_handler (stmt);
>
> We now do:
>
> range_op_handler handler (stmt);
>
> This all has the added benefit of moving all the dispatch code into an
> independent class and avoid polluting range_operator (which we'll
> further split later when frange and prange come live).
>
> There's this annoying "using" keyword that's been added to each
> operator due to hiding rules in C++. The issue is that we will have
> different virtual versions of fold_range() for each combination of
> operands. For example:
>
> // Traditional binary op on irange's.
> fold_range (irange &lhs, const irange &op1, const irange &op2);
> // For POINTER_DIFF_EXPR:
> fold_range (irange &lhs, const prange &op1, const prange &op2);
> // Cast from irange to prange.
> fold_range (prange &lhs, const irange &op1, const irange &op2);
>
> Overloading virtuals when there are multiple same named methods causes
> hidden virtuals warnings from -Woverloaded-virtual, thus the using
> keyword. An alternative would be to have different names:
> fold_range_III, fold_range_IPP, fold_range_PII, but that's uglier
> still.
>
> Tested on x86-64 & ppc64le Linux.
>
> gcc/ChangeLog:
>
> * gimple-range-edge.cc (gimple_outgoing_range_stmt_p): Adjust for
> vrange and convert range_op_handler function calls to use the
> identically named object.
> * gimple-range-fold.cc (gimple_range_operand1): Same.
> (gimple_range_operand2): Same.
> (fold_using_range::fold_stmt): Same.
> (fold_using_range::range_of_range_op): Same.
> (fold_using_range::range_of_builtin_ubsan_call): Same.
> (fold_using_range::relation_fold_and_or): Same.
> (fur_source::register_outgoing_edges): Same.
> * gimple-range-fold.h (gimple_range_handler): Remove.
> * gimple-range-gori.cc (gimple_range_calc_op1): Adjust for vrange.
> (gimple_range_calc_op2): Same.
> (range_def_chain::get_def_chain): Same.
> (gori_compute::compute_operand_range): Same.
> (gori_compute::condexpr_adjust): Same.
> * gimple-range.cc (gimple_ranger::prefill_name): Same.
> (gimple_ranger::prefill_stmt_dependencies): Same.
> * range-op.cc (get_bool_state): Same.
> (class operator_equal): Add using clause.
> (class operator_not_equal): Same.
> (class operator_lt): Same.
> (class operator_le): Same.
> (class operator_gt): Same.
> (class operator_ge): Same.
> (class operator_plus): Same.
> (class operator_minus): Same.
> (class operator_mult): Same.
> (class operator_exact_divide): Same.
> (class operator_lshift): Same.
> (class operator_rshift): Same.
> (class operator_cast): Same.
> (class operator_logical_and): Same.
> (class operator_bitwise_and): Same.
> (class operator_logical_or): Same.
> (class operator_bitwise_or): Same.
> (class operator_bitwise_xor): Same.
> (class operator_trunc_mod): Same.
> (class operator_logical_not): Same.
> (class operator_bitwise_not): Same.
> (class operator_cst): Same.
> (class operator_identity): Same.
> (class operator_unknown): Same.
> (class operator_abs): Same.
> (class operator_negate): Same.
> (class operator_addr_expr): Same.
> (class pointer_or_operator): Same.
> (operator_plus::op1_range): Adjust for vrange.
> (operator_minus::op1_range): Same.
> (operator_mult::op1_range): Same.
> (operator_cast::op1_range): Same.
> (operator_bitwise_not::fold_range): Same.
> (operator_negate::fold_range): Same.
> (range_op_handler): Rename to...
> (get_handler): ...this.
> (range_op_handler::range_op_handler): New.
> (range_op_handler::fold_range): New.
> (range_op_handler::op1_range): New.
> (range_op_handler::op2_range): New.
> (range_op_handler::lhs_op1_relation): New.
> (range_op_handler::lhs_op2_relation): New.
> (range_op_handler::op1_op2_relation): New.
> (range_cast): Adjust for vrange.
> * range-op.h (range_op_handler): Remove function.
> (range_cast): Adjust for vrange.
> (class range_op_handler): New.
> (get_bool_state): Adjust for vrange.
> (empty_range_varying): Same.
> (relop_early_resolve): Same.
> * tree-data-ref.cc (compute_distributive_range): Same.
> * tree-vrp.cc (get_range_op_handler): Remove.
> (range_fold_binary_symbolics_p): Use range_op_handler class
> instead of get_range_op_handler.
> (range_fold_unary_symbolics_p): Same.
> (range_fold_binary_expr): Same.
> (range_fold_unary_expr): Same.
> * value-query.cc (range_query::get_tree_range): Adjust for vrange.
> ---
> gcc/gimple-range-edge.cc | 2 +-
> gcc/gimple-range-fold.cc | 43 ++++----
> gcc/gimple-range-fold.h | 15 ---
> gcc/gimple-range-gori.cc | 41 ++++----
> gcc/gimple-range.cc | 6 +-
> gcc/range-op.cc | 215 ++++++++++++++++++++++++++++++++++-----
> gcc/range-op.h | 45 ++++++--
> gcc/tree-data-ref.cc | 8 +-
> gcc/tree-vrp.cc | 44 ++++----
> gcc/value-query.cc | 8 +-
> 10 files changed, 303 insertions(+), 124 deletions(-)
>
> diff --git a/gcc/gimple-range-edge.cc b/gcc/gimple-range-edge.cc
> index 0bee38ba770..5bbe23ae03d 100644
> --- a/gcc/gimple-range-edge.cc
> +++ b/gcc/gimple-range-edge.cc
> @@ -42,7 +42,7 @@ gimple_outgoing_range_stmt_p (basic_block bb)
> if (!gsi_end_p (gsi))
> {
> gimple *s = gsi_stmt (gsi);
> - if (is_a<gcond *> (s) && gimple_range_handler (s))
> + if (is_a<gcond *> (s) && range_op_handler (s))
> return gsi_stmt (gsi);
> gswitch *sw = dyn_cast<gswitch *> (s);
> if (sw && irange::supports_type_p (TREE_TYPE (gimple_switch_index (sw))))
> diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc
> index 0a947c16c58..c53d2863d5e 100644
> --- a/gcc/gimple-range-fold.cc
> +++ b/gcc/gimple-range-fold.cc
> @@ -482,7 +482,7 @@ gimple_range_base_of_assignment (const gimple *stmt)
> tree
> gimple_range_operand1 (const gimple *stmt)
> {
> - gcc_checking_assert (gimple_range_handler (stmt));
> + gcc_checking_assert (range_op_handler (stmt));
>
> switch (gimple_code (stmt))
> {
> @@ -515,7 +515,7 @@ gimple_range_operand1 (const gimple *stmt)
> tree
> gimple_range_operand2 (const gimple *stmt)
> {
> - gcc_checking_assert (gimple_range_handler (stmt));
> + gcc_checking_assert (range_op_handler (stmt));
>
> switch (gimple_code (stmt))
> {
> @@ -551,7 +551,7 @@ fold_using_range::fold_stmt (irange &r, gimple *s, fur_source &src, tree name)
> && gimple_assign_rhs_code (s) == ADDR_EXPR)
> return range_of_address (r, s, src);
>
> - if (gimple_range_handler (s))
> + if (range_op_handler (s))
> res = range_of_range_op (r, s, src);
> else if (is_a<gphi *>(s))
> res = range_of_phi (r, as_a<gphi *> (s), src);
> @@ -593,7 +593,7 @@ fold_using_range::range_of_range_op (irange &r, gimple *s, fur_source &src)
> tree type = gimple_range_type (s);
> if (!type)
> return false;
> - range_operator *handler = gimple_range_handler (s);
> + range_op_handler handler (s);
> gcc_checking_assert (handler);
>
> tree lhs = gimple_get_lhs (s);
> @@ -606,13 +606,13 @@ fold_using_range::range_of_range_op (irange &r, gimple *s, fur_source &src)
> {
> // Fold range, and register any dependency if available.
> int_range<2> r2 (type);
> - handler->fold_range (r, type, range1, r2);
> + handler.fold_range (r, type, range1, r2);
> if (lhs && gimple_range_ssa_p (op1))
> {
> if (src.gori ())
> src.gori ()->register_dependency (lhs, op1);
> relation_kind rel;
> - rel = handler->lhs_op1_relation (r, range1, range1);
> + rel = handler.lhs_op1_relation (r, range1, range1);
> if (rel != VREL_VARYING)
> src.register_relation (s, rel, lhs, op1);
> }
> @@ -629,7 +629,7 @@ fold_using_range::range_of_range_op (irange &r, gimple *s, fur_source &src)
> fputc ('\n', dump_file);
> }
> // Fold range, and register any dependency if available.
> - handler->fold_range (r, type, range1, range2, rel);
> + handler.fold_range (r, type, range1, range2, rel);
> relation_fold_and_or (r, s, src);
> if (lhs)
> {
> @@ -640,13 +640,13 @@ fold_using_range::range_of_range_op (irange &r, gimple *s, fur_source &src)
> }
> if (gimple_range_ssa_p (op1))
> {
> - rel = handler->lhs_op1_relation (r, range1, range2, rel);
> + rel = handler.lhs_op1_relation (r, range1, range2, rel);
> if (rel != VREL_VARYING)
> src.register_relation (s, rel, lhs, op1);
> }
> if (gimple_range_ssa_p (op2))
> {
> - rel= handler->lhs_op2_relation (r, range1, range2, rel);
> + rel= handler.lhs_op2_relation (r, range1, range2, rel);
> if (rel != VREL_VARYING)
> src.register_relation (s, rel, lhs, op2);
> }
> @@ -921,7 +921,7 @@ fold_using_range::range_of_builtin_ubsan_call (irange &r, gcall *call,
> gcc_checking_assert (code == PLUS_EXPR || code == MINUS_EXPR
> || code == MULT_EXPR);
> tree type = gimple_range_type (call);
> - range_operator *op = range_op_handler (code, type);
> + range_op_handler op (code, type);
> gcc_checking_assert (op);
> int_range_max ir0, ir1;
> tree arg0 = gimple_call_arg (call, 0);
> @@ -935,7 +935,7 @@ fold_using_range::range_of_builtin_ubsan_call (irange &r, gcall *call,
> // Pretend the arithmetic is wrapping. If there is any overflow,
> // we'll complain, but will actually do wrapping operation.
> flag_wrapv = 1;
> - op->fold_range (r, type, ir0, ir1, relation);
> + op.fold_range (r, type, ir0, ir1, relation);
> flag_wrapv = saved_flag_wrapv;
>
> // If for both arguments vrp_valueize returned non-NULL, this should
> @@ -1391,8 +1391,8 @@ fold_using_range::relation_fold_and_or (irange& lhs_range, gimple *s,
> else if (ssa1_dep1 != ssa2_dep2 || ssa1_dep2 != ssa2_dep1)
> return;
>
> - range_operator *handler1 = gimple_range_handler (SSA_NAME_DEF_STMT (ssa1));
> - range_operator *handler2 = gimple_range_handler (SSA_NAME_DEF_STMT (ssa2));
> + range_op_handler handler1 (SSA_NAME_DEF_STMT (ssa1));
> + range_op_handler handler2 (SSA_NAME_DEF_STMT (ssa2));
>
> // If either handler is not present, no relation is found.
> if (!handler1 || !handler2)
> @@ -1400,8 +1400,8 @@ fold_using_range::relation_fold_and_or (irange& lhs_range, gimple *s,
>
> int_range<2> bool_one (boolean_true_node, boolean_true_node);
>
> - relation_kind relation1 = handler1->op1_op2_relation (bool_one);
> - relation_kind relation2 = handler2->op1_op2_relation (bool_one);
> + relation_kind relation1 = handler1.op1_op2_relation (bool_one);
> + relation_kind relation2 = handler2.op1_op2_relation (bool_one);
> if (relation1 == VREL_VARYING || relation2 == VREL_VARYING)
> return;
>
> @@ -1441,7 +1441,6 @@ fur_source::register_outgoing_edges (gcond *s, irange &lhs_range, edge e0, edge
> int_range_max r;
> int_range<2> e0_range, e1_range;
> tree name;
> - range_operator *handler;
> basic_block bb = gimple_bb (s);
>
> if (e0)
> @@ -1472,17 +1471,17 @@ fur_source::register_outgoing_edges (gcond *s, irange &lhs_range, edge e0, edge
> tree ssa2 = gimple_range_ssa_p (gimple_range_operand2 (s));
> if (ssa1 && ssa2)
> {
> - handler = gimple_range_handler (s);
> + range_op_handler handler (s);
> gcc_checking_assert (handler);
> if (e0)
> {
> - relation_kind relation = handler->op1_op2_relation (e0_range);
> + relation_kind relation = handler.op1_op2_relation (e0_range);
> if (relation != VREL_VARYING)
> register_relation (e0, relation, ssa1, ssa2);
> }
> if (e1)
> {
> - relation_kind relation = handler->op1_op2_relation (e1_range);
> + relation_kind relation = handler.op1_op2_relation (e1_range);
> if (relation != VREL_VARYING)
> register_relation (e1, relation, ssa1, ssa2);
> }
> @@ -1501,7 +1500,7 @@ fur_source::register_outgoing_edges (gcond *s, irange &lhs_range, edge e0, edge
> if (TREE_CODE (TREE_TYPE (name)) != BOOLEAN_TYPE)
> continue;
> gimple *stmt = SSA_NAME_DEF_STMT (name);
> - handler = gimple_range_handler (stmt);
> + range_op_handler handler (stmt);
> if (!handler)
> continue;
> tree ssa1 = gimple_range_ssa_p (gimple_range_operand1 (stmt));
> @@ -1511,14 +1510,14 @@ fur_source::register_outgoing_edges (gcond *s, irange &lhs_range, edge e0, edge
> if (e0 && gori ()->outgoing_edge_range_p (r, e0, name, *m_query)
> && r.singleton_p ())
> {
> - relation_kind relation = handler->op1_op2_relation (r);
> + relation_kind relation = handler.op1_op2_relation (r);
> if (relation != VREL_VARYING)
> register_relation (e0, relation, ssa1, ssa2);
> }
> if (e1 && gori ()->outgoing_edge_range_p (r, e1, name, *m_query)
> && r.singleton_p ())
> {
> - relation_kind relation = handler->op1_op2_relation (r);
> + relation_kind relation = handler.op1_op2_relation (r);
> if (relation != VREL_VARYING)
> register_relation (e1, relation, ssa1, ssa2);
> }
> diff --git a/gcc/gimple-range-fold.h b/gcc/gimple-range-fold.h
> index 20cb73dabb9..4b5d4b6e0b8 100644
> --- a/gcc/gimple-range-fold.h
> +++ b/gcc/gimple-range-fold.h
> @@ -41,21 +41,6 @@ bool fold_range (irange &r, gimple *s, irange &r1);
> bool fold_range (irange &r, gimple *s, irange &r1, irange &r2);
> bool fold_range (irange &r, gimple *s, unsigned num_elements, irange *vector);
>
> -// Return the range_operator pointer for this statement. This routine
> -// can also be used to gate whether a routine is range-ops enabled.
> -
> -static inline range_operator *
> -gimple_range_handler (const gimple *s)
> -{
> - if (const gassign *ass = dyn_cast<const gassign *> (s))
> - return range_op_handler (gimple_assign_rhs_code (ass),
> - TREE_TYPE (gimple_assign_lhs (ass)));
> - if (const gcond *cond = dyn_cast<const gcond *> (s))
> - return range_op_handler (gimple_cond_code (cond),
> - TREE_TYPE (gimple_cond_lhs (cond)));
> - return NULL;
> -}
> -
> // Return the type of range which statement S calculates. If the type is
> // unsupported or no type can be determined, return NULL_TREE.
>
> diff --git a/gcc/gimple-range-gori.cc b/gcc/gimple-range-gori.cc
> index 3e15eb5192d..0e0cf2128e7 100644
> --- a/gcc/gimple-range-gori.cc
> +++ b/gcc/gimple-range-gori.cc
> @@ -44,9 +44,9 @@ gimple_range_calc_op1 (irange &r, const gimple *stmt, const irange &lhs_range)
> // Unary operations require the type of the first operand in the
> // second range position.
> tree type = TREE_TYPE (gimple_range_operand1 (stmt));
> - int_range<2> type_range (type);
> - return gimple_range_handler (stmt)->op1_range (r, type, lhs_range,
> - type_range);
> + tmp_range type_range (type);
> + type_range.set_varying (type);
> + return range_op_handler (stmt).op1_range (r, type, lhs_range, type_range);
> }
>
> // Calculate what we can determine of the range of this statement's
> @@ -72,12 +72,12 @@ gimple_range_calc_op1 (irange &r, const gimple *stmt,
> // This is sometimes invoked on single operand stmts.
> if (gimple_num_ops (stmt) < 3)
> return false;
> - int_range<2> trange (TREE_TYPE (gimple_range_operand2 (stmt)));
> - return gimple_range_handler (stmt)->op1_range (r, type, lhs_range,
> - trange);
> + tree op2_type = TREE_TYPE (gimple_range_operand2 (stmt));
> + tmp_range trange (op2_type);
> + trange.set_varying (op2_type);
> + return range_op_handler (stmt).op1_range (r, type, lhs_range, trange);
> }
> - return gimple_range_handler (stmt)->op1_range (r, type, lhs_range,
> - op2_range);
> + return range_op_handler (stmt).op1_range (r, type, lhs_range, op2_range);
> }
>
> // Calculate what we can determine of the range of this statement's
> @@ -97,12 +97,13 @@ gimple_range_calc_op2 (irange &r, const gimple *stmt,
> // If op1 is undefined, solve as if it is varying.
> if (op1_range.undefined_p ())
> {
> - int_range<2> trange (TREE_TYPE (gimple_range_operand1 (stmt)));
> - return gimple_range_handler (stmt)->op2_range (r, type, lhs_range,
> - trange);
> + tree op1_type = TREE_TYPE (gimple_range_operand1 (stmt));
> + tmp_range trange (op1_type);
> + trange.set_varying (op1_type);
> + return range_op_handler (stmt).op2_range (r, type, lhs_range, trange);
> }
> - return gimple_range_handler (stmt)->op2_range (r, type, lhs_range,
> - op1_range);
> + return range_op_handler (stmt).op2_range (r, type, lhs_range,
> + op1_range);
> }
>
> // Return TRUE if GS is a logical && or || expression.
> @@ -346,7 +347,7 @@ range_def_chain::get_def_chain (tree name)
> }
>
> gimple *stmt = SSA_NAME_DEF_STMT (name);
> - if (gimple_range_handler (stmt))
> + if (range_op_handler (stmt))
> {
> ssa1 = gimple_range_ssa_p (gimple_range_operand1 (stmt));
> ssa2 = gimple_range_ssa_p (gimple_range_operand2 (stmt));
> @@ -707,7 +708,7 @@ gori_compute::compute_operand_range (irange &r, gimple *stmt,
> if (is_a<gswitch *> (stmt))
> return compute_operand_range_switch (r, as_a<gswitch *> (stmt), lhs, name,
> src);
> - if (!gimple_range_handler (stmt))
> + if (!range_op_handler (stmt))
> return false;
>
> tree op1 = gimple_range_ssa_p (gimple_range_operand1 (stmt));
> @@ -1328,7 +1329,7 @@ gori_compute::condexpr_adjust (irange &r1, irange &r2, gimple *, tree cond,
> tree type = TREE_TYPE (gimple_assign_rhs1 (cond_def));
> if (!range_compatible_p (type, TREE_TYPE (gimple_assign_rhs2 (cond_def))))
> return false;
> - range_operator *hand = range_op_handler (gimple_assign_rhs_code (cond_def), type);
> + range_op_handler hand (gimple_assign_rhs_code (cond_def), type);
> if (!hand)
> return false;
>
> @@ -1351,18 +1352,18 @@ gori_compute::condexpr_adjust (irange &r1, irange &r2, gimple *, tree cond,
> // the op1 or op2 routines based on its location.
> if (c1)
> {
> - if (!hand->op1_range (cond_false, type, m_bool_zero, cr))
> + if (!hand.op1_range (cond_false, type, m_bool_zero, cr))
> return false;
> - if (!hand->op1_range (cond_true, type, m_bool_one, cr))
> + if (!hand.op1_range (cond_true, type, m_bool_one, cr))
> return false;
> cond_false.intersect (cl);
> cond_true.intersect (cl);
> }
> else
> {
> - if (!hand->op2_range (cond_false, type, m_bool_zero, cl))
> + if (!hand.op2_range (cond_false, type, m_bool_zero, cl))
> return false;
> - if (!hand->op2_range (cond_true, type, m_bool_one, cl))
> + if (!hand.op2_range (cond_true, type, m_bool_one, cl))
> return false;
> cond_false.intersect (cr);
> cond_true.intersect (cr);
> diff --git a/gcc/gimple-range.cc b/gcc/gimple-range.cc
> index f5e9e77bc71..32d57c9e3db 100644
> --- a/gcc/gimple-range.cc
> +++ b/gcc/gimple-range.cc
> @@ -339,7 +339,7 @@ gimple_ranger::prefill_name (irange &r, tree name)
> if (!gimple_range_ssa_p (name))
> return;
> gimple *stmt = SSA_NAME_DEF_STMT (name);
> - if (!gimple_range_handler (stmt) && !is_a<gphi *> (stmt))
> + if (!range_op_handler (stmt) && !is_a<gphi *> (stmt))
> return;
>
> bool current;
> @@ -363,7 +363,7 @@ gimple_ranger::prefill_stmt_dependencies (tree ssa)
> gcc_checking_assert (stmt && gimple_bb (stmt));
>
> // Only pre-process range-ops and phis.
> - if (!gimple_range_handler (stmt) && !is_a<gphi *> (stmt))
> + if (!range_op_handler (stmt) && !is_a<gphi *> (stmt))
> return;
>
> // Mark where on the stack we are starting.
> @@ -419,7 +419,7 @@ gimple_ranger::prefill_stmt_dependencies (tree ssa)
> }
> else
> {
> - gcc_checking_assert (gimple_range_handler (stmt));
> + gcc_checking_assert (range_op_handler (stmt));
> tree op = gimple_range_operand2 (stmt);
> if (op)
> prefill_name (r, op);
> diff --git a/gcc/range-op.cc b/gcc/range-op.cc
> index c88da8caa6c..6f6d2da573a 100644
> --- a/gcc/range-op.cc
> +++ b/gcc/range-op.cc
> @@ -420,7 +420,7 @@ create_possibly_reversed_range (irange &r, tree type,
> // return the equivalent range for TYPE in R; if FALSE/TRUE, do nothing.
>
> bool_range_state
> -get_bool_state (irange &r, const irange &lhs, tree val_type)
> +get_bool_state (vrange &r, const vrange &lhs, tree val_type)
> {
> // If there is no result, then this is unexecutable.
> if (lhs.undefined_p ())
> @@ -446,6 +446,9 @@ get_bool_state (irange &r, const irange &lhs, tree val_type)
>
> class operator_equal : public range_operator
> {
> + using range_operator::fold_range;
> + using range_operator::op1_range;
> + using range_operator::op2_range;
> public:
> virtual bool fold_range (irange &r, tree type,
> const irange &op1,
> @@ -562,6 +565,9 @@ operator_equal::op2_range (irange &r, tree type,
>
> class operator_not_equal : public range_operator
> {
> + using range_operator::fold_range;
> + using range_operator::op1_range;
> + using range_operator::op2_range;
> public:
> virtual bool fold_range (irange &r, tree type,
> const irange &op1,
> @@ -738,6 +744,9 @@ build_ge (irange &r, tree type, const wide_int &val)
>
> class operator_lt : public range_operator
> {
> + using range_operator::fold_range;
> + using range_operator::op1_range;
> + using range_operator::op2_range;
> public:
> virtual bool fold_range (irange &r, tree type,
> const irange &op1,
> @@ -846,6 +855,9 @@ operator_lt::op2_range (irange &r, tree type,
>
> class operator_le : public range_operator
> {
> + using range_operator::fold_range;
> + using range_operator::op1_range;
> + using range_operator::op2_range;
> public:
> virtual bool fold_range (irange &r, tree type,
> const irange &op1,
> @@ -954,6 +966,9 @@ operator_le::op2_range (irange &r, tree type,
>
> class operator_gt : public range_operator
> {
> + using range_operator::fold_range;
> + using range_operator::op1_range;
> + using range_operator::op2_range;
> public:
> virtual bool fold_range (irange &r, tree type,
> const irange &op1,
> @@ -1061,6 +1076,9 @@ operator_gt::op2_range (irange &r, tree type,
>
> class operator_ge : public range_operator
> {
> + using range_operator::fold_range;
> + using range_operator::op1_range;
> + using range_operator::op2_range;
> public:
> virtual bool fold_range (irange &r, tree type,
> const irange &op1,
> @@ -1169,6 +1187,10 @@ operator_ge::op2_range (irange &r, tree type,
>
> class operator_plus : public range_operator
> {
> + using range_operator::op1_range;
> + using range_operator::op2_range;
> + using range_operator::lhs_op1_relation;
> + using range_operator::lhs_op2_relation;
> public:
> virtual bool op1_range (irange &r, tree type,
> const irange &lhs,
> @@ -1286,7 +1308,7 @@ operator_plus::op1_range (irange &r, tree type,
> const irange &op2,
> relation_kind rel ATTRIBUTE_UNUSED) const
> {
> - return range_op_handler (MINUS_EXPR, type)->fold_range (r, type, lhs, op2);
> + return range_op_handler (MINUS_EXPR, type).fold_range (r, type, lhs, op2);
> }
>
> bool
> @@ -1295,12 +1317,15 @@ operator_plus::op2_range (irange &r, tree type,
> const irange &op1,
> relation_kind rel ATTRIBUTE_UNUSED) const
> {
> - return range_op_handler (MINUS_EXPR, type)->fold_range (r, type, lhs, op1);
> + return range_op_handler (MINUS_EXPR, type).fold_range (r, type, lhs, op1);
> }
>
>
> class operator_minus : public range_operator
> {
> + using range_operator::fold_range;
> + using range_operator::op1_range;
> + using range_operator::op2_range;
> public:
> virtual bool op1_range (irange &r, tree type,
> const irange &lhs,
> @@ -1445,7 +1470,7 @@ operator_minus::op1_range (irange &r, tree type,
> const irange &op2,
> relation_kind rel ATTRIBUTE_UNUSED) const
> {
> - return range_op_handler (PLUS_EXPR, type)->fold_range (r, type, lhs, op2);
> + return range_op_handler (PLUS_EXPR, type).fold_range (r, type, lhs, op2);
> }
>
> bool
> @@ -1597,6 +1622,8 @@ cross_product_operator::wi_cross_product (irange &r, tree type,
>
> class operator_mult : public cross_product_operator
> {
> + using range_operator::op1_range;
> + using range_operator::op2_range;
> public:
> virtual void wi_fold (irange &r, tree type,
> const wide_int &lh_lb,
> @@ -1629,8 +1656,8 @@ operator_mult::op1_range (irange &r, tree type,
> return false;
>
> if (op2.singleton_p (&offset) && !integer_zerop (offset))
> - return range_op_handler (TRUNC_DIV_EXPR, type)->fold_range (r, type,
> - lhs, op2);
> + return range_op_handler (TRUNC_DIV_EXPR, type).fold_range (r, type,
> + lhs, op2);
> return false;
> }
>
> @@ -1857,6 +1884,7 @@ operator_div op_ceil_div (CEIL_DIV_EXPR);
>
> class operator_exact_divide : public operator_div
> {
> + using range_operator::op1_range;
> public:
> operator_exact_divide () : operator_div (TRUNC_DIV_EXPR) { }
> virtual bool op1_range (irange &r, tree type,
> @@ -1881,13 +1909,15 @@ operator_exact_divide::op1_range (irange &r, tree type,
> // If op2 is a multiple of 2, we would be able to set some non-zero bits.
> if (op2.singleton_p (&offset)
> && !integer_zerop (offset))
> - return range_op_handler (MULT_EXPR, type)->fold_range (r, type, lhs, op2);
> + return range_op_handler (MULT_EXPR, type).fold_range (r, type, lhs, op2);
> return false;
> }
>
>
> class operator_lshift : public cross_product_operator
> {
> + using range_operator::fold_range;
> + using range_operator::op1_range;
> public:
> virtual bool op1_range (irange &r, tree type,
> const irange &lhs,
> @@ -1909,6 +1939,9 @@ public:
>
> class operator_rshift : public cross_product_operator
> {
> + using range_operator::fold_range;
> + using range_operator::op1_range;
> + using range_operator::lhs_op1_relation;
> public:
> virtual bool fold_range (irange &r, tree type,
> const irange &op1,
> @@ -2248,6 +2281,8 @@ operator_rshift::wi_fold (irange &r, tree type,
>
> class operator_cast: public range_operator
> {
> + using range_operator::fold_range;
> + using range_operator::op1_range;
> public:
> virtual bool fold_range (irange &r, tree type,
> const irange &op1,
> @@ -2417,10 +2452,9 @@ operator_cast::op1_range (irange &r, tree type,
> // Add this to the unsigned LHS range(s).
> int_range_max lim_range (type, lim, lim);
> int_range_max lhs_neg;
> - range_op_handler (PLUS_EXPR, type)->fold_range (lhs_neg,
> - type,
> - converted_lhs,
> - lim_range);
> + range_op_handler (PLUS_EXPR, type).fold_range (lhs_neg, type,
> + converted_lhs,
> + lim_range);
> // lhs_neg now has all the negative versions of the LHS.
> // Now union in all the values from SIGNED MIN (0x80000) to
> // lim-1 in order to fill in all the ranges with the upper
> @@ -2469,6 +2503,9 @@ operator_cast::op1_range (irange &r, tree type,
>
> class operator_logical_and : public range_operator
> {
> + using range_operator::fold_range;
> + using range_operator::op1_range;
> + using range_operator::op2_range;
> public:
> virtual bool fold_range (irange &r, tree type,
> const irange &lh,
> @@ -2542,6 +2579,9 @@ operator_logical_and::op2_range (irange &r, tree type,
>
> class operator_bitwise_and : public range_operator
> {
> + using range_operator::fold_range;
> + using range_operator::op1_range;
> + using range_operator::op2_range;
> public:
> virtual bool fold_range (irange &r, tree type,
> const irange &lh,
> @@ -2988,6 +3028,9 @@ operator_bitwise_and::op2_range (irange &r, tree type,
>
> class operator_logical_or : public range_operator
> {
> + using range_operator::fold_range;
> + using range_operator::op1_range;
> + using range_operator::op2_range;
> public:
> virtual bool fold_range (irange &r, tree type,
> const irange &lh,
> @@ -3051,6 +3094,8 @@ operator_logical_or::op2_range (irange &r, tree type,
>
> class operator_bitwise_or : public range_operator
> {
> + using range_operator::op1_range;
> + using range_operator::op2_range;
> public:
> virtual bool op1_range (irange &r, tree type,
> const irange &lhs,
> @@ -3155,6 +3200,8 @@ operator_bitwise_or::op2_range (irange &r, tree type,
>
> class operator_bitwise_xor : public range_operator
> {
> + using range_operator::op1_range;
> + using range_operator::op2_range;
> public:
> virtual void wi_fold (irange &r, tree type,
> const wide_int &lh_lb,
> @@ -3296,6 +3343,8 @@ operator_bitwise_xor::op2_range (irange &r, tree type,
>
> class operator_trunc_mod : public range_operator
> {
> + using range_operator::op1_range;
> + using range_operator::op2_range;
> public:
> virtual void wi_fold (irange &r, tree type,
> const wide_int &lh_lb,
> @@ -3432,6 +3481,8 @@ operator_trunc_mod::op2_range (irange &r, tree type,
>
> class operator_logical_not : public range_operator
> {
> + using range_operator::fold_range;
> + using range_operator::op1_range;
> public:
> virtual bool fold_range (irange &r, tree type,
> const irange &lh,
> @@ -3487,6 +3538,8 @@ operator_logical_not::op1_range (irange &r,
>
> class operator_bitwise_not : public range_operator
> {
> + using range_operator::fold_range;
> + using range_operator::op1_range;
> public:
> virtual bool fold_range (irange &r, tree type,
> const irange &lh,
> @@ -3513,8 +3566,7 @@ operator_bitwise_not::fold_range (irange &r, tree type,
> // ~X is simply -1 - X.
> int_range<1> minusone (type, wi::minus_one (TYPE_PRECISION (type)),
> wi::minus_one (TYPE_PRECISION (type)));
> - return range_op_handler (MINUS_EXPR, type)->fold_range (r, type, minusone,
> - lh);
> + return range_op_handler (MINUS_EXPR, type).fold_range (r, type, minusone, lh);
> }
>
> bool
> @@ -3533,6 +3585,7 @@ operator_bitwise_not::op1_range (irange &r, tree type,
>
> class operator_cst : public range_operator
> {
> + using range_operator::fold_range;
> public:
> virtual bool fold_range (irange &r, tree type,
> const irange &op1,
> @@ -3553,6 +3606,9 @@ operator_cst::fold_range (irange &r, tree type ATTRIBUTE_UNUSED,
>
> class operator_identity : public range_operator
> {
> + using range_operator::fold_range;
> + using range_operator::op1_range;
> + using range_operator::lhs_op1_relation;
> public:
> virtual bool fold_range (irange &r, tree type,
> const irange &op1,
> @@ -3605,6 +3661,7 @@ operator_identity::op1_range (irange &r, tree type ATTRIBUTE_UNUSED,
>
> class operator_unknown : public range_operator
> {
> + using range_operator::fold_range;
> public:
> virtual bool fold_range (irange &r, tree type,
> const irange &op1,
> @@ -3625,6 +3682,7 @@ operator_unknown::fold_range (irange &r, tree type,
>
> class operator_abs : public range_operator
> {
> + using range_operator::op1_range;
> public:
> virtual void wi_fold (irange &r, tree type,
> const wide_int &lh_lb,
> @@ -3790,6 +3848,8 @@ operator_absu::wi_fold (irange &r, tree type,
>
> class operator_negate : public range_operator
> {
> + using range_operator::fold_range;
> + using range_operator::op1_range;
> public:
> virtual bool fold_range (irange &r, tree type,
> const irange &op1,
> @@ -3810,9 +3870,8 @@ operator_negate::fold_range (irange &r, tree type,
> if (empty_range_varying (r, type, lh, rh))
> return true;
> // -X is simply 0 - X.
> - return range_op_handler (MINUS_EXPR, type)->fold_range (r, type,
> - range_zero (type),
> - lh);
> + return range_op_handler (MINUS_EXPR, type).fold_range (r, type,
> + range_zero (type), lh);
> }
>
> bool
> @@ -3828,6 +3887,8 @@ operator_negate::op1_range (irange &r, tree type,
>
> class operator_addr_expr : public range_operator
> {
> + using range_operator::fold_range;
> + using range_operator::op1_range;
> public:
> virtual bool fold_range (irange &r, tree type,
> const irange &op1,
> @@ -3978,6 +4039,8 @@ pointer_and_operator::wi_fold (irange &r, tree type,
>
> class pointer_or_operator : public range_operator
> {
> + using range_operator::op1_range;
> + using range_operator::op2_range;
> public:
> virtual bool op1_range (irange &r, tree type,
> const irange &lhs,
> @@ -4139,8 +4202,8 @@ pointer_table::pointer_table ()
>
> // The tables are hidden and accessed via a simple extern function.
>
> -range_operator *
> -range_op_handler (enum tree_code code, tree type)
> +static inline range_operator *
> +get_handler (enum tree_code code, tree type)
> {
> // First check if there is a pointer specialization.
> if (POINTER_TYPE_P (type))
> @@ -4150,16 +4213,120 @@ range_op_handler (enum tree_code code, tree type)
> return NULL;
> }
>
> +range_op_handler::range_op_handler (tree_code code, tree type)
> +{
> + m_op = get_handler (code, type);
> +}
> +
> +range_op_handler::range_op_handler (const gimple *s)
> +{
> + if (const gassign *ass = dyn_cast<const gassign *> (s))
> + {
> + enum tree_code code = gimple_assign_rhs_code (ass);
> + // The LHS of a comparison is always an int, so we must look at
> + // the operands.
> + if (TREE_CODE_CLASS (code) == tcc_comparison)
> + m_op = get_handler (code, TREE_TYPE (gimple_assign_rhs1 (ass)));
> + else
> + m_op = get_handler (code, TREE_TYPE (gimple_assign_lhs (ass)));
> + }
> + else if (const gcond *cond = dyn_cast<const gcond *> (s))
> + m_op = get_handler (gimple_cond_code (cond),
> + TREE_TYPE (gimple_cond_lhs (cond)));
> + else
> + m_op = NULL;
> +}
> +
> +bool
> +range_op_handler::fold_range (vrange &r, tree type,
> + const vrange &lh,
> + const vrange &rh,
> + relation_kind rel) const
> +{
> + if (is_a <irange> (lh))
> + return m_op->fold_range (as_a <irange> (r), type,
> + as_a <irange> (lh),
> + as_a <irange> (rh), rel);
> + gcc_unreachable ();
> + return false;
> +}
> +
> +bool
> +range_op_handler::op1_range (vrange &r, tree type,
> + const vrange &lhs,
> + const vrange &op2,
> + relation_kind rel) const
> +{
> + if (is_a <irange> (r))
> + return m_op->op1_range (as_a <irange> (r), type,
> + as_a <irange> (lhs),
> + as_a <irange> (op2), rel);
> + gcc_unreachable ();
> + return false;
> +}
> +
> +bool
> +range_op_handler::op2_range (vrange &r, tree type,
> + const vrange &lhs,
> + const vrange &op1,
> + relation_kind rel) const
> +{
> + if (is_a <irange> (r))
> + return m_op->op2_range (as_a <irange> (r), type,
> + as_a <irange> (lhs),
> + as_a <irange> (op1), rel);
> + gcc_unreachable ();
> + return false;
> +}
> +
> +relation_kind
> +range_op_handler::lhs_op1_relation (const vrange &lhs,
> + const vrange &op1,
> + const vrange &op2,
> + relation_kind rel) const
> +{
> + if (is_a <irange> (op1))
> + return m_op->lhs_op1_relation (as_a <irange> (lhs),
> + as_a <irange> (op1), as_a <irange> (op2), rel);
> + gcc_unreachable ();
> + return VREL_VARYING;
> +}
> +
> +relation_kind
> +range_op_handler::lhs_op2_relation (const vrange &lhs,
> + const vrange &op1,
> + const vrange &op2,
> + relation_kind rel) const
> +{
> + if (is_a <irange> (op1))
> + return m_op->lhs_op2_relation (as_a <irange> (lhs),
> + as_a <irange> (op1), as_a <irange> (op2), rel);
> + gcc_unreachable ();
> + return VREL_VARYING;
> +}
> +
> +relation_kind
> +range_op_handler::op1_op2_relation (const vrange &lhs) const
> +{
> + return m_op->op1_op2_relation (as_a <irange> (lhs));
> +}
> +
> // Cast the range in R to TYPE.
>
> -void
> -range_cast (irange &r, tree type)
> +bool
> +range_cast (vrange &r, tree type)
> {
> - int_range_max tmp = r;
> - range_operator *op = range_op_handler (CONVERT_EXPR, type);
> + tmp_range tmp (r);
> + tmp_range varying (type);
> + varying.set_varying (type);
> + range_op_handler op (CONVERT_EXPR, type);
> // Call op_convert, if it fails, the result is varying.
> - if (!op->fold_range (r, type, tmp, int_range<1> (type)))
> - r.set_varying (type);
> + if (!op || !op.fold_range (r, type, tmp, varying))
> + {
> + r.set_varying (type);
> + return false;
> + }
> + return true;
> }
>
> #if CHECKING_P
> diff --git a/gcc/range-op.h b/gcc/range-op.h
> index 5fdda326d4b..d0f50689897 100644
> --- a/gcc/range-op.h
> +++ b/gcc/range-op.h
> @@ -108,8 +108,39 @@ protected:
> const wide_int &rh_ub) const;
> };
>
> -extern range_operator *range_op_handler (enum tree_code code, tree type);
> -extern void range_cast (irange &, tree type);
> +class range_op_handler
> +{
> +public:
> + range_op_handler (enum tree_code code, tree type);
> + range_op_handler (const gimple *s);
> + operator bool () const { return m_op; }
> +
> + bool fold_range (vrange &r, tree type,
> + const vrange &lh,
> + const vrange &rh,
> + relation_kind rel = VREL_VARYING) const;
> + bool op1_range (vrange &r, tree type,
> + const vrange &lhs,
> + const vrange &op2,
> + relation_kind rel = VREL_VARYING) const;
> + bool op2_range (vrange &r, tree type,
> + const vrange &lhs,
> + const vrange &op1,
> + relation_kind rel = VREL_VARYING) const;
> + relation_kind lhs_op1_relation (const vrange &lhs,
> + const vrange &op1,
> + const vrange &op2,
> + relation_kind = VREL_VARYING) const;
> + relation_kind lhs_op2_relation (const vrange &lhs,
> + const vrange &op1,
> + const vrange &op2,
> + relation_kind = VREL_VARYING) const;
> + relation_kind op1_op2_relation (const vrange &lhs) const;
> +private:
> + range_operator *m_op;
> +};
> +
> +extern bool range_cast (vrange &, tree type);
> extern void wi_set_zero_nonzero_bits (tree type,
> const wide_int &, const wide_int &,
> wide_int &maybe_nonzero,
> @@ -124,7 +155,7 @@ relation_kind gt_op1_op2_relation (const irange &lhs);
> relation_kind ge_op1_op2_relation (const irange &lhs);
>
> enum bool_range_state { BRS_FALSE, BRS_TRUE, BRS_EMPTY, BRS_FULL };
> -bool_range_state get_bool_state (irange &r, const irange &lhs, tree val_type);
> +bool_range_state get_bool_state (vrange &r, const vrange &lhs, tree val_type);
>
> // If the range of either op1 or op2 is undefined, set the result to
> // varying and return TRUE. If the caller truely cares about a result,
> @@ -132,8 +163,8 @@ bool_range_state get_bool_state (irange &r, const irange &lhs, tree val_type);
> // treated as a varying.
>
> inline bool
> -empty_range_varying (irange &r, tree type,
> - const irange &op1, const irange & op2)
> +empty_range_varying (vrange &r, tree type,
> + const vrange &op1, const vrange & op2)
> {
> if (op1.undefined_p () || op2.undefined_p ())
> {
> @@ -150,8 +181,8 @@ empty_range_varying (irange &r, tree type,
> // return false.
>
> inline bool
> -relop_early_resolve (irange &r, tree type, const irange &op1,
> - const irange &op2, relation_kind rel,
> +relop_early_resolve (irange &r, tree type, const vrange &op1,
> + const vrange &op2, relation_kind rel,
> relation_kind my_rel)
> {
> // If known relation is a complete subset of this relation, always true.
> diff --git a/gcc/tree-data-ref.cc b/gcc/tree-data-ref.cc
> index 397792c3584..ae05fe74b95 100644
> --- a/gcc/tree-data-ref.cc
> +++ b/gcc/tree-data-ref.cc
> @@ -593,8 +593,8 @@ compute_distributive_range (tree type, value_range &op0_range,
> gcc_assert (INTEGRAL_TYPE_P (type) && !TYPE_OVERFLOW_TRAPS (type));
> if (result_range)
> {
> - range_operator *op = range_op_handler (code, type);
> - op->fold_range (*result_range, type, op0_range, op1_range);
> + range_op_handler op (code, type);
> + op.fold_range (*result_range, type, op0_range, op1_range);
> }
>
> /* The distributive property guarantees that if TYPE is no narrower
> @@ -639,10 +639,10 @@ compute_distributive_range (tree type, value_range &op0_range,
> range_cast (op0_range, ssizetype);
> range_cast (op1_range, ssizetype);
> value_range wide_range;
> - range_operator *op = range_op_handler (code, ssizetype);
> + range_op_handler op (code, ssizetype);
> bool saved_flag_wrapv = flag_wrapv;
> flag_wrapv = 1;
> - op->fold_range (wide_range, ssizetype, op0_range, op1_range);
> + op.fold_range (wide_range, ssizetype, op0_range, op1_range);
> flag_wrapv = saved_flag_wrapv;
> if (wide_range.num_pairs () != 1 || !range_int_cst_p (&wide_range))
> return false;
> diff --git a/gcc/tree-vrp.cc b/gcc/tree-vrp.cc
> index 0784d658567..3c7b5af4737 100644
> --- a/gcc/tree-vrp.cc
> +++ b/gcc/tree-vrp.cc
> @@ -924,20 +924,6 @@ extract_range_from_plus_minus_expr (value_range *vr,
> vr->set (min, max, kind);
> }
>
> -/* Return the range-ops handler for CODE and EXPR_TYPE. If no
> - suitable operator is found, return NULL and set VR to VARYING. */
> -
> -static const range_operator *
> -get_range_op_handler (value_range *vr,
> - enum tree_code code,
> - tree expr_type)
> -{
> - const range_operator *op = range_op_handler (code, expr_type);
> - if (!op)
> - vr->set_varying (expr_type);
> - return op;
> -}
> -
> /* If the types passed are supported, return TRUE, otherwise set VR to
> VARYING and return FALSE. */
>
> @@ -1005,10 +991,12 @@ range_fold_binary_symbolics_p (value_range *vr,
> &vr0, &vr1);
> return true;
> }
> - const range_operator *op = get_range_op_handler (vr, code, expr_type);
> + range_op_handler op (code, expr_type);
> + if (!op)
> + vr->set_varying (expr_type);
> vr0.normalize_symbolics ();
> vr1.normalize_symbolics ();
> - return op->fold_range (*vr, expr_type, vr0, vr1);
> + return op.fold_range (*vr, expr_type, vr0, vr1);
> }
> return false;
> }
> @@ -1040,10 +1028,12 @@ range_fold_unary_symbolics_p (value_range *vr,
> range_fold_binary_expr (vr, MINUS_EXPR, expr_type, &minusone, vr0);
> return true;
> }
> - const range_operator *op = get_range_op_handler (vr, code, expr_type);
> + range_op_handler op (code, expr_type);
> + if (!op)
> + vr->set_varying (expr_type);
> value_range vr0_cst (*vr0);
> vr0_cst.normalize_symbolics ();
> - return op->fold_range (*vr, expr_type, vr0_cst, value_range (expr_type));
> + return op.fold_range (*vr, expr_type, vr0_cst, value_range (expr_type));
> }
> return false;
> }
> @@ -1060,9 +1050,12 @@ range_fold_binary_expr (value_range *vr,
> if (!supported_types_p (vr, expr_type)
> || !defined_ranges_p (vr, vr0_, vr1_))
> return;
> - const range_operator *op = get_range_op_handler (vr, code, expr_type);
> + range_op_handler op (code, expr_type);
> if (!op)
> - return;
> + {
> + vr->set_varying (expr_type);
> + return;
> + }
>
> if (range_fold_binary_symbolics_p (vr, code, expr_type, vr0_, vr1_))
> return;
> @@ -1075,7 +1068,7 @@ range_fold_binary_expr (value_range *vr,
> vr1.set_varying (expr_type);
> vr0.normalize_addresses ();
> vr1.normalize_addresses ();
> - op->fold_range (*vr, expr_type, vr0, vr1);
> + op.fold_range (*vr, expr_type, vr0, vr1);
> }
>
> /* Perform a unary operation on a range. */
> @@ -1089,16 +1082,19 @@ range_fold_unary_expr (value_range *vr,
> if (!supported_types_p (vr, expr_type, vr0_type)
> || !defined_ranges_p (vr, vr0))
> return;
> - const range_operator *op = get_range_op_handler (vr, code, expr_type);
> + range_op_handler op (code, expr_type);
> if (!op)
> - return;
> + {
> + vr->set_varying (expr_type);
> + return;
> + }
>
> if (range_fold_unary_symbolics_p (vr, code, expr_type, vr0))
> return;
>
> value_range vr0_cst (*vr0);
> vr0_cst.normalize_addresses ();
> - op->fold_range (*vr, expr_type, vr0_cst, value_range (expr_type));
> + op.fold_range (*vr, expr_type, vr0_cst, value_range (expr_type));
> }
>
> /* If the range of values taken by OP can be inferred after STMT executes,
> diff --git a/gcc/value-query.cc b/gcc/value-query.cc
> index 26e3858103b..31e56eeae53 100644
> --- a/gcc/value-query.cc
> +++ b/gcc/value-query.cc
> @@ -234,13 +234,13 @@ range_query::get_tree_range (irange &r, tree expr, gimple *stmt)
> }
> if (BINARY_CLASS_P (expr))
> {
> - range_operator *op = range_op_handler (TREE_CODE (expr), type);
> + range_op_handler op (TREE_CODE (expr), type);
> if (op)
> {
> int_range_max r0, r1;
> range_of_expr (r0, TREE_OPERAND (expr, 0), stmt);
> range_of_expr (r1, TREE_OPERAND (expr, 1), stmt);
> - op->fold_range (r, type, r0, r1);
> + op.fold_range (r, type, r0, r1);
> }
> else
> r.set_varying (type);
> @@ -248,13 +248,13 @@ range_query::get_tree_range (irange &r, tree expr, gimple *stmt)
> }
> if (UNARY_CLASS_P (expr))
> {
> - range_operator *op = range_op_handler (TREE_CODE (expr), type);
> + range_op_handler op (TREE_CODE (expr), type);
> tree op0_type = TREE_TYPE (TREE_OPERAND (expr, 0));
> if (op && irange::supports_type_p (op0_type))
> {
> int_range_max r0;
> range_of_expr (r0, TREE_OPERAND (expr, 0), stmt);
> - op->fold_range (r, type, r0, int_range<1> (type));
> + op.fold_range (r, type, r0, int_range<1> (type));
> }
> else
> r.set_varying (type);
> --
> 2.36.1
>
[-- Attachment #2: 0003-Convert-range-op.-to-vrange.patch --]
[-- Type: text/x-patch, Size: 43951 bytes --]
From cf5bea76f9d84f6218f0a5085db63a50aed9d95a Mon Sep 17 00:00:00 2001
From: Aldy Hernandez <aldyh@redhat.com>
Date: Mon, 14 Mar 2022 13:31:18 +0100
Subject: [PATCH] Convert range-op.* to vrange.
This patch provides the infrastructure to make range-ops type agnostic.
First, the range_op_handler function has been replaced with an object
of the same name. It's coded in such a way to minimize changes to the
code base, and to encapsulate the dispatch code.
Instead of:
range_operator *op = range_op_handler (code, type);
if (op)
op->fold_range (...);
We now do:
range_op_handler op (code, type);
if (op)
op->fold_range (...);
I've folded gimple_range_handler into the range_op_handler class,
since it's also a query into the range operators.
Instead of:
range_operator *handler = gimple_range_handler (stmt);
We now do:
range_op_handler handler (stmt);
This all has the added benefit of moving all the dispatch code into an
independent class and avoid polluting range_operator (which we'll
further split later when frange and prange come live).
There's this annoying "using" keyword that's been added to each
operator due to hiding rules in C++. The issue is that we will have
different virtual versions of fold_range() for each combination of
operands. For example:
// Traditional binary op on irange's.
fold_range (irange &lhs, const irange &op1, const irange &op2);
// For POINTER_DIFF_EXPR:
fold_range (irange &lhs, const prange &op1, const prange &op2);
// Cast from irange to prange.
fold_range (prange &lhs, const irange &op1, const irange &op2);
Overloading virtuals when there are multiple same named methods causes
hidden virtuals warnings from -Woverloaded-virtual, thus the using
keyword. An alternative would be to have different names:
fold_range_III, fold_range_IPP, fold_range_PII, but that's uglier
still.
Tested on x86-64 & ppc64le Linux.
gcc/ChangeLog:
* gimple-range-edge.cc (gimple_outgoing_range_stmt_p): Adjust for
vrange and convert range_op_handler function calls to use the
identically named object.
* gimple-range-fold.cc (gimple_range_operand1): Same.
(gimple_range_operand2): Same.
(fold_using_range::fold_stmt): Same.
(fold_using_range::range_of_range_op): Same.
(fold_using_range::range_of_builtin_ubsan_call): Same.
(fold_using_range::relation_fold_and_or): Same.
(fur_source::register_outgoing_edges): Same.
* gimple-range-fold.h (gimple_range_handler): Remove.
* gimple-range-gori.cc (gimple_range_calc_op1): Adjust for vrange.
(gimple_range_calc_op2): Same.
(range_def_chain::get_def_chain): Same.
(gori_compute::compute_operand_range): Same.
(gori_compute::condexpr_adjust): Same.
* gimple-range.cc (gimple_ranger::prefill_name): Same.
(gimple_ranger::prefill_stmt_dependencies): Same.
* range-op.cc (get_bool_state): Same.
(class operator_equal): Add using clause.
(class operator_not_equal): Same.
(class operator_lt): Same.
(class operator_le): Same.
(class operator_gt): Same.
(class operator_ge): Same.
(class operator_plus): Same.
(class operator_minus): Same.
(class operator_mult): Same.
(class operator_exact_divide): Same.
(class operator_lshift): Same.
(class operator_rshift): Same.
(class operator_cast): Same.
(class operator_logical_and): Same.
(class operator_bitwise_and): Same.
(class operator_logical_or): Same.
(class operator_bitwise_or): Same.
(class operator_bitwise_xor): Same.
(class operator_trunc_mod): Same.
(class operator_logical_not): Same.
(class operator_bitwise_not): Same.
(class operator_cst): Same.
(class operator_identity): Same.
(class operator_unknown): Same.
(class operator_abs): Same.
(class operator_negate): Same.
(class operator_addr_expr): Same.
(class pointer_or_operator): Same.
(operator_plus::op1_range): Adjust for vrange.
(operator_minus::op1_range): Same.
(operator_mult::op1_range): Same.
(operator_cast::op1_range): Same.
(operator_bitwise_not::fold_range): Same.
(operator_negate::fold_range): Same.
(range_op_handler): Rename to...
(get_handler): ...this.
(range_op_handler::range_op_handler): New.
(range_op_handler::fold_range): New.
(range_op_handler::op1_range): New.
(range_op_handler::op2_range): New.
(range_op_handler::lhs_op1_relation): New.
(range_op_handler::lhs_op2_relation): New.
(range_op_handler::op1_op2_relation): New.
(range_cast): Adjust for vrange.
* range-op.h (range_op_handler): Remove function.
(range_cast): Adjust for vrange.
(class range_op_handler): New.
(get_bool_state): Adjust for vrange.
(empty_range_varying): Same.
(relop_early_resolve): Same.
* tree-data-ref.cc (compute_distributive_range): Same.
* tree-vrp.cc (get_range_op_handler): Remove.
(range_fold_binary_symbolics_p): Use range_op_handler class
instead of get_range_op_handler.
(range_fold_unary_symbolics_p): Same.
(range_fold_binary_expr): Same.
(range_fold_unary_expr): Same.
* value-query.cc (range_query::get_tree_range): Adjust for vrange.
---
gcc/gimple-range-edge.cc | 2 +-
gcc/gimple-range-fold.cc | 43 ++++----
gcc/gimple-range-fold.h | 15 ---
gcc/gimple-range-gori.cc | 41 ++++----
gcc/gimple-range.cc | 6 +-
gcc/range-op.cc | 215 ++++++++++++++++++++++++++++++++++-----
gcc/range-op.h | 45 ++++++--
gcc/tree-data-ref.cc | 8 +-
gcc/tree-vrp.cc | 44 ++++----
gcc/value-query.cc | 8 +-
10 files changed, 303 insertions(+), 124 deletions(-)
diff --git a/gcc/gimple-range-edge.cc b/gcc/gimple-range-edge.cc
index 0bee38ba770..5bbe23ae03d 100644
--- a/gcc/gimple-range-edge.cc
+++ b/gcc/gimple-range-edge.cc
@@ -42,7 +42,7 @@ gimple_outgoing_range_stmt_p (basic_block bb)
if (!gsi_end_p (gsi))
{
gimple *s = gsi_stmt (gsi);
- if (is_a<gcond *> (s) && gimple_range_handler (s))
+ if (is_a<gcond *> (s) && range_op_handler (s))
return gsi_stmt (gsi);
gswitch *sw = dyn_cast<gswitch *> (s);
if (sw && irange::supports_type_p (TREE_TYPE (gimple_switch_index (sw))))
diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc
index 0a947c16c58..c53d2863d5e 100644
--- a/gcc/gimple-range-fold.cc
+++ b/gcc/gimple-range-fold.cc
@@ -482,7 +482,7 @@ gimple_range_base_of_assignment (const gimple *stmt)
tree
gimple_range_operand1 (const gimple *stmt)
{
- gcc_checking_assert (gimple_range_handler (stmt));
+ gcc_checking_assert (range_op_handler (stmt));
switch (gimple_code (stmt))
{
@@ -515,7 +515,7 @@ gimple_range_operand1 (const gimple *stmt)
tree
gimple_range_operand2 (const gimple *stmt)
{
- gcc_checking_assert (gimple_range_handler (stmt));
+ gcc_checking_assert (range_op_handler (stmt));
switch (gimple_code (stmt))
{
@@ -551,7 +551,7 @@ fold_using_range::fold_stmt (irange &r, gimple *s, fur_source &src, tree name)
&& gimple_assign_rhs_code (s) == ADDR_EXPR)
return range_of_address (r, s, src);
- if (gimple_range_handler (s))
+ if (range_op_handler (s))
res = range_of_range_op (r, s, src);
else if (is_a<gphi *>(s))
res = range_of_phi (r, as_a<gphi *> (s), src);
@@ -593,7 +593,7 @@ fold_using_range::range_of_range_op (irange &r, gimple *s, fur_source &src)
tree type = gimple_range_type (s);
if (!type)
return false;
- range_operator *handler = gimple_range_handler (s);
+ range_op_handler handler (s);
gcc_checking_assert (handler);
tree lhs = gimple_get_lhs (s);
@@ -606,13 +606,13 @@ fold_using_range::range_of_range_op (irange &r, gimple *s, fur_source &src)
{
// Fold range, and register any dependency if available.
int_range<2> r2 (type);
- handler->fold_range (r, type, range1, r2);
+ handler.fold_range (r, type, range1, r2);
if (lhs && gimple_range_ssa_p (op1))
{
if (src.gori ())
src.gori ()->register_dependency (lhs, op1);
relation_kind rel;
- rel = handler->lhs_op1_relation (r, range1, range1);
+ rel = handler.lhs_op1_relation (r, range1, range1);
if (rel != VREL_VARYING)
src.register_relation (s, rel, lhs, op1);
}
@@ -629,7 +629,7 @@ fold_using_range::range_of_range_op (irange &r, gimple *s, fur_source &src)
fputc ('\n', dump_file);
}
// Fold range, and register any dependency if available.
- handler->fold_range (r, type, range1, range2, rel);
+ handler.fold_range (r, type, range1, range2, rel);
relation_fold_and_or (r, s, src);
if (lhs)
{
@@ -640,13 +640,13 @@ fold_using_range::range_of_range_op (irange &r, gimple *s, fur_source &src)
}
if (gimple_range_ssa_p (op1))
{
- rel = handler->lhs_op1_relation (r, range1, range2, rel);
+ rel = handler.lhs_op1_relation (r, range1, range2, rel);
if (rel != VREL_VARYING)
src.register_relation (s, rel, lhs, op1);
}
if (gimple_range_ssa_p (op2))
{
- rel= handler->lhs_op2_relation (r, range1, range2, rel);
+ rel= handler.lhs_op2_relation (r, range1, range2, rel);
if (rel != VREL_VARYING)
src.register_relation (s, rel, lhs, op2);
}
@@ -921,7 +921,7 @@ fold_using_range::range_of_builtin_ubsan_call (irange &r, gcall *call,
gcc_checking_assert (code == PLUS_EXPR || code == MINUS_EXPR
|| code == MULT_EXPR);
tree type = gimple_range_type (call);
- range_operator *op = range_op_handler (code, type);
+ range_op_handler op (code, type);
gcc_checking_assert (op);
int_range_max ir0, ir1;
tree arg0 = gimple_call_arg (call, 0);
@@ -935,7 +935,7 @@ fold_using_range::range_of_builtin_ubsan_call (irange &r, gcall *call,
// Pretend the arithmetic is wrapping. If there is any overflow,
// we'll complain, but will actually do wrapping operation.
flag_wrapv = 1;
- op->fold_range (r, type, ir0, ir1, relation);
+ op.fold_range (r, type, ir0, ir1, relation);
flag_wrapv = saved_flag_wrapv;
// If for both arguments vrp_valueize returned non-NULL, this should
@@ -1391,8 +1391,8 @@ fold_using_range::relation_fold_and_or (irange& lhs_range, gimple *s,
else if (ssa1_dep1 != ssa2_dep2 || ssa1_dep2 != ssa2_dep1)
return;
- range_operator *handler1 = gimple_range_handler (SSA_NAME_DEF_STMT (ssa1));
- range_operator *handler2 = gimple_range_handler (SSA_NAME_DEF_STMT (ssa2));
+ range_op_handler handler1 (SSA_NAME_DEF_STMT (ssa1));
+ range_op_handler handler2 (SSA_NAME_DEF_STMT (ssa2));
// If either handler is not present, no relation is found.
if (!handler1 || !handler2)
@@ -1400,8 +1400,8 @@ fold_using_range::relation_fold_and_or (irange& lhs_range, gimple *s,
int_range<2> bool_one (boolean_true_node, boolean_true_node);
- relation_kind relation1 = handler1->op1_op2_relation (bool_one);
- relation_kind relation2 = handler2->op1_op2_relation (bool_one);
+ relation_kind relation1 = handler1.op1_op2_relation (bool_one);
+ relation_kind relation2 = handler2.op1_op2_relation (bool_one);
if (relation1 == VREL_VARYING || relation2 == VREL_VARYING)
return;
@@ -1441,7 +1441,6 @@ fur_source::register_outgoing_edges (gcond *s, irange &lhs_range, edge e0, edge
int_range_max r;
int_range<2> e0_range, e1_range;
tree name;
- range_operator *handler;
basic_block bb = gimple_bb (s);
if (e0)
@@ -1472,17 +1471,17 @@ fur_source::register_outgoing_edges (gcond *s, irange &lhs_range, edge e0, edge
tree ssa2 = gimple_range_ssa_p (gimple_range_operand2 (s));
if (ssa1 && ssa2)
{
- handler = gimple_range_handler (s);
+ range_op_handler handler (s);
gcc_checking_assert (handler);
if (e0)
{
- relation_kind relation = handler->op1_op2_relation (e0_range);
+ relation_kind relation = handler.op1_op2_relation (e0_range);
if (relation != VREL_VARYING)
register_relation (e0, relation, ssa1, ssa2);
}
if (e1)
{
- relation_kind relation = handler->op1_op2_relation (e1_range);
+ relation_kind relation = handler.op1_op2_relation (e1_range);
if (relation != VREL_VARYING)
register_relation (e1, relation, ssa1, ssa2);
}
@@ -1501,7 +1500,7 @@ fur_source::register_outgoing_edges (gcond *s, irange &lhs_range, edge e0, edge
if (TREE_CODE (TREE_TYPE (name)) != BOOLEAN_TYPE)
continue;
gimple *stmt = SSA_NAME_DEF_STMT (name);
- handler = gimple_range_handler (stmt);
+ range_op_handler handler (stmt);
if (!handler)
continue;
tree ssa1 = gimple_range_ssa_p (gimple_range_operand1 (stmt));
@@ -1511,14 +1510,14 @@ fur_source::register_outgoing_edges (gcond *s, irange &lhs_range, edge e0, edge
if (e0 && gori ()->outgoing_edge_range_p (r, e0, name, *m_query)
&& r.singleton_p ())
{
- relation_kind relation = handler->op1_op2_relation (r);
+ relation_kind relation = handler.op1_op2_relation (r);
if (relation != VREL_VARYING)
register_relation (e0, relation, ssa1, ssa2);
}
if (e1 && gori ()->outgoing_edge_range_p (r, e1, name, *m_query)
&& r.singleton_p ())
{
- relation_kind relation = handler->op1_op2_relation (r);
+ relation_kind relation = handler.op1_op2_relation (r);
if (relation != VREL_VARYING)
register_relation (e1, relation, ssa1, ssa2);
}
diff --git a/gcc/gimple-range-fold.h b/gcc/gimple-range-fold.h
index 20cb73dabb9..4b5d4b6e0b8 100644
--- a/gcc/gimple-range-fold.h
+++ b/gcc/gimple-range-fold.h
@@ -41,21 +41,6 @@ bool fold_range (irange &r, gimple *s, irange &r1);
bool fold_range (irange &r, gimple *s, irange &r1, irange &r2);
bool fold_range (irange &r, gimple *s, unsigned num_elements, irange *vector);
-// Return the range_operator pointer for this statement. This routine
-// can also be used to gate whether a routine is range-ops enabled.
-
-static inline range_operator *
-gimple_range_handler (const gimple *s)
-{
- if (const gassign *ass = dyn_cast<const gassign *> (s))
- return range_op_handler (gimple_assign_rhs_code (ass),
- TREE_TYPE (gimple_assign_lhs (ass)));
- if (const gcond *cond = dyn_cast<const gcond *> (s))
- return range_op_handler (gimple_cond_code (cond),
- TREE_TYPE (gimple_cond_lhs (cond)));
- return NULL;
-}
-
// Return the type of range which statement S calculates. If the type is
// unsupported or no type can be determined, return NULL_TREE.
diff --git a/gcc/gimple-range-gori.cc b/gcc/gimple-range-gori.cc
index 3e15eb5192d..72032132cac 100644
--- a/gcc/gimple-range-gori.cc
+++ b/gcc/gimple-range-gori.cc
@@ -44,9 +44,9 @@ gimple_range_calc_op1 (irange &r, const gimple *stmt, const irange &lhs_range)
// Unary operations require the type of the first operand in the
// second range position.
tree type = TREE_TYPE (gimple_range_operand1 (stmt));
- int_range<2> type_range (type);
- return gimple_range_handler (stmt)->op1_range (r, type, lhs_range,
- type_range);
+ Value_Range type_range (type);
+ type_range.set_varying (type);
+ return range_op_handler (stmt).op1_range (r, type, lhs_range, type_range);
}
// Calculate what we can determine of the range of this statement's
@@ -72,12 +72,12 @@ gimple_range_calc_op1 (irange &r, const gimple *stmt,
// This is sometimes invoked on single operand stmts.
if (gimple_num_ops (stmt) < 3)
return false;
- int_range<2> trange (TREE_TYPE (gimple_range_operand2 (stmt)));
- return gimple_range_handler (stmt)->op1_range (r, type, lhs_range,
- trange);
+ tree op2_type = TREE_TYPE (gimple_range_operand2 (stmt));
+ Value_Range trange (op2_type);
+ trange.set_varying (op2_type);
+ return range_op_handler (stmt).op1_range (r, type, lhs_range, trange);
}
- return gimple_range_handler (stmt)->op1_range (r, type, lhs_range,
- op2_range);
+ return range_op_handler (stmt).op1_range (r, type, lhs_range, op2_range);
}
// Calculate what we can determine of the range of this statement's
@@ -97,12 +97,13 @@ gimple_range_calc_op2 (irange &r, const gimple *stmt,
// If op1 is undefined, solve as if it is varying.
if (op1_range.undefined_p ())
{
- int_range<2> trange (TREE_TYPE (gimple_range_operand1 (stmt)));
- return gimple_range_handler (stmt)->op2_range (r, type, lhs_range,
- trange);
+ tree op1_type = TREE_TYPE (gimple_range_operand1 (stmt));
+ Value_Range trange (op1_type);
+ trange.set_varying (op1_type);
+ return range_op_handler (stmt).op2_range (r, type, lhs_range, trange);
}
- return gimple_range_handler (stmt)->op2_range (r, type, lhs_range,
- op1_range);
+ return range_op_handler (stmt).op2_range (r, type, lhs_range,
+ op1_range);
}
// Return TRUE if GS is a logical && or || expression.
@@ -346,7 +347,7 @@ range_def_chain::get_def_chain (tree name)
}
gimple *stmt = SSA_NAME_DEF_STMT (name);
- if (gimple_range_handler (stmt))
+ if (range_op_handler (stmt))
{
ssa1 = gimple_range_ssa_p (gimple_range_operand1 (stmt));
ssa2 = gimple_range_ssa_p (gimple_range_operand2 (stmt));
@@ -707,7 +708,7 @@ gori_compute::compute_operand_range (irange &r, gimple *stmt,
if (is_a<gswitch *> (stmt))
return compute_operand_range_switch (r, as_a<gswitch *> (stmt), lhs, name,
src);
- if (!gimple_range_handler (stmt))
+ if (!range_op_handler (stmt))
return false;
tree op1 = gimple_range_ssa_p (gimple_range_operand1 (stmt));
@@ -1328,7 +1329,7 @@ gori_compute::condexpr_adjust (irange &r1, irange &r2, gimple *, tree cond,
tree type = TREE_TYPE (gimple_assign_rhs1 (cond_def));
if (!range_compatible_p (type, TREE_TYPE (gimple_assign_rhs2 (cond_def))))
return false;
- range_operator *hand = range_op_handler (gimple_assign_rhs_code (cond_def), type);
+ range_op_handler hand (gimple_assign_rhs_code (cond_def), type);
if (!hand)
return false;
@@ -1351,18 +1352,18 @@ gori_compute::condexpr_adjust (irange &r1, irange &r2, gimple *, tree cond,
// the op1 or op2 routines based on its location.
if (c1)
{
- if (!hand->op1_range (cond_false, type, m_bool_zero, cr))
+ if (!hand.op1_range (cond_false, type, m_bool_zero, cr))
return false;
- if (!hand->op1_range (cond_true, type, m_bool_one, cr))
+ if (!hand.op1_range (cond_true, type, m_bool_one, cr))
return false;
cond_false.intersect (cl);
cond_true.intersect (cl);
}
else
{
- if (!hand->op2_range (cond_false, type, m_bool_zero, cl))
+ if (!hand.op2_range (cond_false, type, m_bool_zero, cl))
return false;
- if (!hand->op2_range (cond_true, type, m_bool_one, cl))
+ if (!hand.op2_range (cond_true, type, m_bool_one, cl))
return false;
cond_false.intersect (cr);
cond_true.intersect (cr);
diff --git a/gcc/gimple-range.cc b/gcc/gimple-range.cc
index 53f4865af3b..0a99787fc75 100644
--- a/gcc/gimple-range.cc
+++ b/gcc/gimple-range.cc
@@ -339,7 +339,7 @@ gimple_ranger::prefill_name (irange &r, tree name)
if (!gimple_range_ssa_p (name))
return;
gimple *stmt = SSA_NAME_DEF_STMT (name);
- if (!gimple_range_handler (stmt) && !is_a<gphi *> (stmt))
+ if (!range_op_handler (stmt) && !is_a<gphi *> (stmt))
return;
bool current;
@@ -363,7 +363,7 @@ gimple_ranger::prefill_stmt_dependencies (tree ssa)
gcc_checking_assert (stmt && gimple_bb (stmt));
// Only pre-process range-ops and phis.
- if (!gimple_range_handler (stmt) && !is_a<gphi *> (stmt))
+ if (!range_op_handler (stmt) && !is_a<gphi *> (stmt))
return;
// Mark where on the stack we are starting.
@@ -419,7 +419,7 @@ gimple_ranger::prefill_stmt_dependencies (tree ssa)
}
else
{
- gcc_checking_assert (gimple_range_handler (stmt));
+ gcc_checking_assert (range_op_handler (stmt));
tree op = gimple_range_operand2 (stmt);
if (op)
prefill_name (r, op);
diff --git a/gcc/range-op.cc b/gcc/range-op.cc
index c88da8caa6c..028b4b7237c 100644
--- a/gcc/range-op.cc
+++ b/gcc/range-op.cc
@@ -420,7 +420,7 @@ create_possibly_reversed_range (irange &r, tree type,
// return the equivalent range for TYPE in R; if FALSE/TRUE, do nothing.
bool_range_state
-get_bool_state (irange &r, const irange &lhs, tree val_type)
+get_bool_state (vrange &r, const vrange &lhs, tree val_type)
{
// If there is no result, then this is unexecutable.
if (lhs.undefined_p ())
@@ -446,6 +446,9 @@ get_bool_state (irange &r, const irange &lhs, tree val_type)
class operator_equal : public range_operator
{
+ using range_operator::fold_range;
+ using range_operator::op1_range;
+ using range_operator::op2_range;
public:
virtual bool fold_range (irange &r, tree type,
const irange &op1,
@@ -562,6 +565,9 @@ operator_equal::op2_range (irange &r, tree type,
class operator_not_equal : public range_operator
{
+ using range_operator::fold_range;
+ using range_operator::op1_range;
+ using range_operator::op2_range;
public:
virtual bool fold_range (irange &r, tree type,
const irange &op1,
@@ -738,6 +744,9 @@ build_ge (irange &r, tree type, const wide_int &val)
class operator_lt : public range_operator
{
+ using range_operator::fold_range;
+ using range_operator::op1_range;
+ using range_operator::op2_range;
public:
virtual bool fold_range (irange &r, tree type,
const irange &op1,
@@ -846,6 +855,9 @@ operator_lt::op2_range (irange &r, tree type,
class operator_le : public range_operator
{
+ using range_operator::fold_range;
+ using range_operator::op1_range;
+ using range_operator::op2_range;
public:
virtual bool fold_range (irange &r, tree type,
const irange &op1,
@@ -954,6 +966,9 @@ operator_le::op2_range (irange &r, tree type,
class operator_gt : public range_operator
{
+ using range_operator::fold_range;
+ using range_operator::op1_range;
+ using range_operator::op2_range;
public:
virtual bool fold_range (irange &r, tree type,
const irange &op1,
@@ -1061,6 +1076,9 @@ operator_gt::op2_range (irange &r, tree type,
class operator_ge : public range_operator
{
+ using range_operator::fold_range;
+ using range_operator::op1_range;
+ using range_operator::op2_range;
public:
virtual bool fold_range (irange &r, tree type,
const irange &op1,
@@ -1169,6 +1187,10 @@ operator_ge::op2_range (irange &r, tree type,
class operator_plus : public range_operator
{
+ using range_operator::op1_range;
+ using range_operator::op2_range;
+ using range_operator::lhs_op1_relation;
+ using range_operator::lhs_op2_relation;
public:
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
@@ -1286,7 +1308,7 @@ operator_plus::op1_range (irange &r, tree type,
const irange &op2,
relation_kind rel ATTRIBUTE_UNUSED) const
{
- return range_op_handler (MINUS_EXPR, type)->fold_range (r, type, lhs, op2);
+ return range_op_handler (MINUS_EXPR, type).fold_range (r, type, lhs, op2);
}
bool
@@ -1295,12 +1317,15 @@ operator_plus::op2_range (irange &r, tree type,
const irange &op1,
relation_kind rel ATTRIBUTE_UNUSED) const
{
- return range_op_handler (MINUS_EXPR, type)->fold_range (r, type, lhs, op1);
+ return range_op_handler (MINUS_EXPR, type).fold_range (r, type, lhs, op1);
}
class operator_minus : public range_operator
{
+ using range_operator::fold_range;
+ using range_operator::op1_range;
+ using range_operator::op2_range;
public:
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
@@ -1445,7 +1470,7 @@ operator_minus::op1_range (irange &r, tree type,
const irange &op2,
relation_kind rel ATTRIBUTE_UNUSED) const
{
- return range_op_handler (PLUS_EXPR, type)->fold_range (r, type, lhs, op2);
+ return range_op_handler (PLUS_EXPR, type).fold_range (r, type, lhs, op2);
}
bool
@@ -1597,6 +1622,8 @@ cross_product_operator::wi_cross_product (irange &r, tree type,
class operator_mult : public cross_product_operator
{
+ using range_operator::op1_range;
+ using range_operator::op2_range;
public:
virtual void wi_fold (irange &r, tree type,
const wide_int &lh_lb,
@@ -1629,8 +1656,8 @@ operator_mult::op1_range (irange &r, tree type,
return false;
if (op2.singleton_p (&offset) && !integer_zerop (offset))
- return range_op_handler (TRUNC_DIV_EXPR, type)->fold_range (r, type,
- lhs, op2);
+ return range_op_handler (TRUNC_DIV_EXPR, type).fold_range (r, type,
+ lhs, op2);
return false;
}
@@ -1857,6 +1884,7 @@ operator_div op_ceil_div (CEIL_DIV_EXPR);
class operator_exact_divide : public operator_div
{
+ using range_operator::op1_range;
public:
operator_exact_divide () : operator_div (TRUNC_DIV_EXPR) { }
virtual bool op1_range (irange &r, tree type,
@@ -1881,13 +1909,15 @@ operator_exact_divide::op1_range (irange &r, tree type,
// If op2 is a multiple of 2, we would be able to set some non-zero bits.
if (op2.singleton_p (&offset)
&& !integer_zerop (offset))
- return range_op_handler (MULT_EXPR, type)->fold_range (r, type, lhs, op2);
+ return range_op_handler (MULT_EXPR, type).fold_range (r, type, lhs, op2);
return false;
}
class operator_lshift : public cross_product_operator
{
+ using range_operator::fold_range;
+ using range_operator::op1_range;
public:
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
@@ -1909,6 +1939,9 @@ public:
class operator_rshift : public cross_product_operator
{
+ using range_operator::fold_range;
+ using range_operator::op1_range;
+ using range_operator::lhs_op1_relation;
public:
virtual bool fold_range (irange &r, tree type,
const irange &op1,
@@ -2248,6 +2281,8 @@ operator_rshift::wi_fold (irange &r, tree type,
class operator_cast: public range_operator
{
+ using range_operator::fold_range;
+ using range_operator::op1_range;
public:
virtual bool fold_range (irange &r, tree type,
const irange &op1,
@@ -2417,10 +2452,9 @@ operator_cast::op1_range (irange &r, tree type,
// Add this to the unsigned LHS range(s).
int_range_max lim_range (type, lim, lim);
int_range_max lhs_neg;
- range_op_handler (PLUS_EXPR, type)->fold_range (lhs_neg,
- type,
- converted_lhs,
- lim_range);
+ range_op_handler (PLUS_EXPR, type).fold_range (lhs_neg, type,
+ converted_lhs,
+ lim_range);
// lhs_neg now has all the negative versions of the LHS.
// Now union in all the values from SIGNED MIN (0x80000) to
// lim-1 in order to fill in all the ranges with the upper
@@ -2469,6 +2503,9 @@ operator_cast::op1_range (irange &r, tree type,
class operator_logical_and : public range_operator
{
+ using range_operator::fold_range;
+ using range_operator::op1_range;
+ using range_operator::op2_range;
public:
virtual bool fold_range (irange &r, tree type,
const irange &lh,
@@ -2542,6 +2579,9 @@ operator_logical_and::op2_range (irange &r, tree type,
class operator_bitwise_and : public range_operator
{
+ using range_operator::fold_range;
+ using range_operator::op1_range;
+ using range_operator::op2_range;
public:
virtual bool fold_range (irange &r, tree type,
const irange &lh,
@@ -2988,6 +3028,9 @@ operator_bitwise_and::op2_range (irange &r, tree type,
class operator_logical_or : public range_operator
{
+ using range_operator::fold_range;
+ using range_operator::op1_range;
+ using range_operator::op2_range;
public:
virtual bool fold_range (irange &r, tree type,
const irange &lh,
@@ -3051,6 +3094,8 @@ operator_logical_or::op2_range (irange &r, tree type,
class operator_bitwise_or : public range_operator
{
+ using range_operator::op1_range;
+ using range_operator::op2_range;
public:
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
@@ -3155,6 +3200,8 @@ operator_bitwise_or::op2_range (irange &r, tree type,
class operator_bitwise_xor : public range_operator
{
+ using range_operator::op1_range;
+ using range_operator::op2_range;
public:
virtual void wi_fold (irange &r, tree type,
const wide_int &lh_lb,
@@ -3296,6 +3343,8 @@ operator_bitwise_xor::op2_range (irange &r, tree type,
class operator_trunc_mod : public range_operator
{
+ using range_operator::op1_range;
+ using range_operator::op2_range;
public:
virtual void wi_fold (irange &r, tree type,
const wide_int &lh_lb,
@@ -3432,6 +3481,8 @@ operator_trunc_mod::op2_range (irange &r, tree type,
class operator_logical_not : public range_operator
{
+ using range_operator::fold_range;
+ using range_operator::op1_range;
public:
virtual bool fold_range (irange &r, tree type,
const irange &lh,
@@ -3487,6 +3538,8 @@ operator_logical_not::op1_range (irange &r,
class operator_bitwise_not : public range_operator
{
+ using range_operator::fold_range;
+ using range_operator::op1_range;
public:
virtual bool fold_range (irange &r, tree type,
const irange &lh,
@@ -3513,8 +3566,7 @@ operator_bitwise_not::fold_range (irange &r, tree type,
// ~X is simply -1 - X.
int_range<1> minusone (type, wi::minus_one (TYPE_PRECISION (type)),
wi::minus_one (TYPE_PRECISION (type)));
- return range_op_handler (MINUS_EXPR, type)->fold_range (r, type, minusone,
- lh);
+ return range_op_handler (MINUS_EXPR, type).fold_range (r, type, minusone, lh);
}
bool
@@ -3533,6 +3585,7 @@ operator_bitwise_not::op1_range (irange &r, tree type,
class operator_cst : public range_operator
{
+ using range_operator::fold_range;
public:
virtual bool fold_range (irange &r, tree type,
const irange &op1,
@@ -3553,6 +3606,9 @@ operator_cst::fold_range (irange &r, tree type ATTRIBUTE_UNUSED,
class operator_identity : public range_operator
{
+ using range_operator::fold_range;
+ using range_operator::op1_range;
+ using range_operator::lhs_op1_relation;
public:
virtual bool fold_range (irange &r, tree type,
const irange &op1,
@@ -3605,6 +3661,7 @@ operator_identity::op1_range (irange &r, tree type ATTRIBUTE_UNUSED,
class operator_unknown : public range_operator
{
+ using range_operator::fold_range;
public:
virtual bool fold_range (irange &r, tree type,
const irange &op1,
@@ -3625,6 +3682,7 @@ operator_unknown::fold_range (irange &r, tree type,
class operator_abs : public range_operator
{
+ using range_operator::op1_range;
public:
virtual void wi_fold (irange &r, tree type,
const wide_int &lh_lb,
@@ -3790,6 +3848,8 @@ operator_absu::wi_fold (irange &r, tree type,
class operator_negate : public range_operator
{
+ using range_operator::fold_range;
+ using range_operator::op1_range;
public:
virtual bool fold_range (irange &r, tree type,
const irange &op1,
@@ -3810,9 +3870,8 @@ operator_negate::fold_range (irange &r, tree type,
if (empty_range_varying (r, type, lh, rh))
return true;
// -X is simply 0 - X.
- return range_op_handler (MINUS_EXPR, type)->fold_range (r, type,
- range_zero (type),
- lh);
+ return range_op_handler (MINUS_EXPR, type).fold_range (r, type,
+ range_zero (type), lh);
}
bool
@@ -3828,6 +3887,8 @@ operator_negate::op1_range (irange &r, tree type,
class operator_addr_expr : public range_operator
{
+ using range_operator::fold_range;
+ using range_operator::op1_range;
public:
virtual bool fold_range (irange &r, tree type,
const irange &op1,
@@ -3978,6 +4039,8 @@ pointer_and_operator::wi_fold (irange &r, tree type,
class pointer_or_operator : public range_operator
{
+ using range_operator::op1_range;
+ using range_operator::op2_range;
public:
virtual bool op1_range (irange &r, tree type,
const irange &lhs,
@@ -4139,8 +4202,8 @@ pointer_table::pointer_table ()
// The tables are hidden and accessed via a simple extern function.
-range_operator *
-range_op_handler (enum tree_code code, tree type)
+static inline range_operator *
+get_handler (enum tree_code code, tree type)
{
// First check if there is a pointer specialization.
if (POINTER_TYPE_P (type))
@@ -4150,16 +4213,120 @@ range_op_handler (enum tree_code code, tree type)
return NULL;
}
+range_op_handler::range_op_handler (tree_code code, tree type)
+{
+ m_op = get_handler (code, type);
+}
+
+range_op_handler::range_op_handler (const gimple *s)
+{
+ if (const gassign *ass = dyn_cast<const gassign *> (s))
+ {
+ enum tree_code code = gimple_assign_rhs_code (ass);
+ // The LHS of a comparison is always an int, so we must look at
+ // the operands.
+ if (TREE_CODE_CLASS (code) == tcc_comparison)
+ m_op = get_handler (code, TREE_TYPE (gimple_assign_rhs1 (ass)));
+ else
+ m_op = get_handler (code, TREE_TYPE (gimple_assign_lhs (ass)));
+ }
+ else if (const gcond *cond = dyn_cast<const gcond *> (s))
+ m_op = get_handler (gimple_cond_code (cond),
+ TREE_TYPE (gimple_cond_lhs (cond)));
+ else
+ m_op = NULL;
+}
+
+bool
+range_op_handler::fold_range (vrange &r, tree type,
+ const vrange &lh,
+ const vrange &rh,
+ relation_kind rel) const
+{
+ if (is_a <irange> (lh))
+ return m_op->fold_range (as_a <irange> (r), type,
+ as_a <irange> (lh),
+ as_a <irange> (rh), rel);
+ gcc_unreachable ();
+ return false;
+}
+
+bool
+range_op_handler::op1_range (vrange &r, tree type,
+ const vrange &lhs,
+ const vrange &op2,
+ relation_kind rel) const
+{
+ if (is_a <irange> (r))
+ return m_op->op1_range (as_a <irange> (r), type,
+ as_a <irange> (lhs),
+ as_a <irange> (op2), rel);
+ gcc_unreachable ();
+ return false;
+}
+
+bool
+range_op_handler::op2_range (vrange &r, tree type,
+ const vrange &lhs,
+ const vrange &op1,
+ relation_kind rel) const
+{
+ if (is_a <irange> (r))
+ return m_op->op2_range (as_a <irange> (r), type,
+ as_a <irange> (lhs),
+ as_a <irange> (op1), rel);
+ gcc_unreachable ();
+ return false;
+}
+
+relation_kind
+range_op_handler::lhs_op1_relation (const vrange &lhs,
+ const vrange &op1,
+ const vrange &op2,
+ relation_kind rel) const
+{
+ if (is_a <irange> (op1))
+ return m_op->lhs_op1_relation (as_a <irange> (lhs),
+ as_a <irange> (op1), as_a <irange> (op2), rel);
+ gcc_unreachable ();
+ return VREL_VARYING;
+}
+
+relation_kind
+range_op_handler::lhs_op2_relation (const vrange &lhs,
+ const vrange &op1,
+ const vrange &op2,
+ relation_kind rel) const
+{
+ if (is_a <irange> (op1))
+ return m_op->lhs_op2_relation (as_a <irange> (lhs),
+ as_a <irange> (op1), as_a <irange> (op2), rel);
+ gcc_unreachable ();
+ return VREL_VARYING;
+}
+
+relation_kind
+range_op_handler::op1_op2_relation (const vrange &lhs) const
+{
+ return m_op->op1_op2_relation (as_a <irange> (lhs));
+}
+
// Cast the range in R to TYPE.
-void
-range_cast (irange &r, tree type)
+bool
+range_cast (vrange &r, tree type)
{
- int_range_max tmp = r;
- range_operator *op = range_op_handler (CONVERT_EXPR, type);
+ Value_Range tmp (r);
+ Value_Range varying (type);
+ varying.set_varying (type);
+ range_op_handler op (CONVERT_EXPR, type);
// Call op_convert, if it fails, the result is varying.
- if (!op->fold_range (r, type, tmp, int_range<1> (type)))
- r.set_varying (type);
+ if (!op || !op.fold_range (r, type, tmp, varying))
+ {
+ r.set_varying (type);
+ return false;
+ }
+ return true;
}
#if CHECKING_P
diff --git a/gcc/range-op.h b/gcc/range-op.h
index 300974fbb78..262c796180d 100644
--- a/gcc/range-op.h
+++ b/gcc/range-op.h
@@ -108,8 +108,39 @@ protected:
const wide_int &rh_ub) const;
};
-extern range_operator *range_op_handler (enum tree_code code, tree type);
-extern void range_cast (irange &, tree type);
+class range_op_handler
+{
+public:
+ range_op_handler (enum tree_code code, tree type);
+ range_op_handler (const gimple *s);
+ operator bool () const { return m_op; }
+
+ bool fold_range (vrange &r, tree type,
+ const vrange &lh,
+ const vrange &rh,
+ relation_kind rel = VREL_VARYING) const;
+ bool op1_range (vrange &r, tree type,
+ const vrange &lhs,
+ const vrange &op2,
+ relation_kind rel = VREL_VARYING) const;
+ bool op2_range (vrange &r, tree type,
+ const vrange &lhs,
+ const vrange &op1,
+ relation_kind rel = VREL_VARYING) const;
+ relation_kind lhs_op1_relation (const vrange &lhs,
+ const vrange &op1,
+ const vrange &op2,
+ relation_kind = VREL_VARYING) const;
+ relation_kind lhs_op2_relation (const vrange &lhs,
+ const vrange &op1,
+ const vrange &op2,
+ relation_kind = VREL_VARYING) const;
+ relation_kind op1_op2_relation (const vrange &lhs) const;
+private:
+ range_operator *m_op;
+};
+
+extern bool range_cast (vrange &, tree type);
extern void wi_set_zero_nonzero_bits (tree type,
const wide_int &, const wide_int &,
wide_int &maybe_nonzero,
@@ -124,7 +155,7 @@ relation_kind gt_op1_op2_relation (const irange &lhs);
relation_kind ge_op1_op2_relation (const irange &lhs);
enum bool_range_state { BRS_FALSE, BRS_TRUE, BRS_EMPTY, BRS_FULL };
-bool_range_state get_bool_state (irange &r, const irange &lhs, tree val_type);
+bool_range_state get_bool_state (vrange &r, const vrange &lhs, tree val_type);
// If the range of either op1 or op2 is undefined, set the result to
// varying and return TRUE. If the caller truely cares about a result,
@@ -132,8 +163,8 @@ bool_range_state get_bool_state (irange &r, const irange &lhs, tree val_type);
// treated as a varying.
inline bool
-empty_range_varying (irange &r, tree type,
- const irange &op1, const irange & op2)
+empty_range_varying (vrange &r, tree type,
+ const vrange &op1, const vrange & op2)
{
if (op1.undefined_p () || op2.undefined_p ())
{
@@ -150,8 +181,8 @@ empty_range_varying (irange &r, tree type,
// return false.
inline bool
-relop_early_resolve (irange &r, tree type, const irange &op1,
- const irange &op2, relation_kind rel,
+relop_early_resolve (irange &r, tree type, const vrange &op1,
+ const vrange &op2, relation_kind rel,
relation_kind my_rel)
{
// If known relation is a complete subset of this relation, always true.
diff --git a/gcc/tree-data-ref.cc b/gcc/tree-data-ref.cc
index 397792c3584..ae05fe74b95 100644
--- a/gcc/tree-data-ref.cc
+++ b/gcc/tree-data-ref.cc
@@ -593,8 +593,8 @@ compute_distributive_range (tree type, value_range &op0_range,
gcc_assert (INTEGRAL_TYPE_P (type) && !TYPE_OVERFLOW_TRAPS (type));
if (result_range)
{
- range_operator *op = range_op_handler (code, type);
- op->fold_range (*result_range, type, op0_range, op1_range);
+ range_op_handler op (code, type);
+ op.fold_range (*result_range, type, op0_range, op1_range);
}
/* The distributive property guarantees that if TYPE is no narrower
@@ -639,10 +639,10 @@ compute_distributive_range (tree type, value_range &op0_range,
range_cast (op0_range, ssizetype);
range_cast (op1_range, ssizetype);
value_range wide_range;
- range_operator *op = range_op_handler (code, ssizetype);
+ range_op_handler op (code, ssizetype);
bool saved_flag_wrapv = flag_wrapv;
flag_wrapv = 1;
- op->fold_range (wide_range, ssizetype, op0_range, op1_range);
+ op.fold_range (wide_range, ssizetype, op0_range, op1_range);
flag_wrapv = saved_flag_wrapv;
if (wide_range.num_pairs () != 1 || !range_int_cst_p (&wide_range))
return false;
diff --git a/gcc/tree-vrp.cc b/gcc/tree-vrp.cc
index 62ae5a967f3..74277617b66 100644
--- a/gcc/tree-vrp.cc
+++ b/gcc/tree-vrp.cc
@@ -924,20 +924,6 @@ extract_range_from_plus_minus_expr (value_range *vr,
vr->set (min, max, kind);
}
-/* Return the range-ops handler for CODE and EXPR_TYPE. If no
- suitable operator is found, return NULL and set VR to VARYING. */
-
-static const range_operator *
-get_range_op_handler (value_range *vr,
- enum tree_code code,
- tree expr_type)
-{
- const range_operator *op = range_op_handler (code, expr_type);
- if (!op)
- vr->set_varying (expr_type);
- return op;
-}
-
/* If the types passed are supported, return TRUE, otherwise set VR to
VARYING and return FALSE. */
@@ -1005,10 +991,12 @@ range_fold_binary_symbolics_p (value_range *vr,
&vr0, &vr1);
return true;
}
- const range_operator *op = get_range_op_handler (vr, code, expr_type);
+ range_op_handler op (code, expr_type);
+ if (!op)
+ vr->set_varying (expr_type);
vr0.normalize_symbolics ();
vr1.normalize_symbolics ();
- return op->fold_range (*vr, expr_type, vr0, vr1);
+ return op.fold_range (*vr, expr_type, vr0, vr1);
}
return false;
}
@@ -1040,10 +1028,12 @@ range_fold_unary_symbolics_p (value_range *vr,
range_fold_binary_expr (vr, MINUS_EXPR, expr_type, &minusone, vr0);
return true;
}
- const range_operator *op = get_range_op_handler (vr, code, expr_type);
+ range_op_handler op (code, expr_type);
+ if (!op)
+ vr->set_varying (expr_type);
value_range vr0_cst (*vr0);
vr0_cst.normalize_symbolics ();
- return op->fold_range (*vr, expr_type, vr0_cst, value_range (expr_type));
+ return op.fold_range (*vr, expr_type, vr0_cst, value_range (expr_type));
}
return false;
}
@@ -1060,9 +1050,12 @@ range_fold_binary_expr (value_range *vr,
if (!supported_types_p (vr, expr_type)
|| !defined_ranges_p (vr, vr0_, vr1_))
return;
- const range_operator *op = get_range_op_handler (vr, code, expr_type);
+ range_op_handler op (code, expr_type);
if (!op)
- return;
+ {
+ vr->set_varying (expr_type);
+ return;
+ }
if (range_fold_binary_symbolics_p (vr, code, expr_type, vr0_, vr1_))
return;
@@ -1075,7 +1068,7 @@ range_fold_binary_expr (value_range *vr,
vr1.set_varying (expr_type);
vr0.normalize_addresses ();
vr1.normalize_addresses ();
- op->fold_range (*vr, expr_type, vr0, vr1);
+ op.fold_range (*vr, expr_type, vr0, vr1);
}
/* Perform a unary operation on a range. */
@@ -1089,16 +1082,19 @@ range_fold_unary_expr (value_range *vr,
if (!supported_types_p (vr, expr_type, vr0_type)
|| !defined_ranges_p (vr, vr0))
return;
- const range_operator *op = get_range_op_handler (vr, code, expr_type);
+ range_op_handler op (code, expr_type);
if (!op)
- return;
+ {
+ vr->set_varying (expr_type);
+ return;
+ }
if (range_fold_unary_symbolics_p (vr, code, expr_type, vr0))
return;
value_range vr0_cst (*vr0);
vr0_cst.normalize_addresses ();
- op->fold_range (*vr, expr_type, vr0_cst, value_range (expr_type));
+ op.fold_range (*vr, expr_type, vr0_cst, value_range (expr_type));
}
/* If the range of values taken by OP can be inferred after STMT executes,
diff --git a/gcc/value-query.cc b/gcc/value-query.cc
index 26e3858103b..31e56eeae53 100644
--- a/gcc/value-query.cc
+++ b/gcc/value-query.cc
@@ -234,13 +234,13 @@ range_query::get_tree_range (irange &r, tree expr, gimple *stmt)
}
if (BINARY_CLASS_P (expr))
{
- range_operator *op = range_op_handler (TREE_CODE (expr), type);
+ range_op_handler op (TREE_CODE (expr), type);
if (op)
{
int_range_max r0, r1;
range_of_expr (r0, TREE_OPERAND (expr, 0), stmt);
range_of_expr (r1, TREE_OPERAND (expr, 1), stmt);
- op->fold_range (r, type, r0, r1);
+ op.fold_range (r, type, r0, r1);
}
else
r.set_varying (type);
@@ -248,13 +248,13 @@ range_query::get_tree_range (irange &r, tree expr, gimple *stmt)
}
if (UNARY_CLASS_P (expr))
{
- range_operator *op = range_op_handler (TREE_CODE (expr), type);
+ range_op_handler op (TREE_CODE (expr), type);
tree op0_type = TREE_TYPE (TREE_OPERAND (expr, 0));
if (op && irange::supports_type_p (op0_type))
{
int_range_max r0;
range_of_expr (r0, TREE_OPERAND (expr, 0), stmt);
- op->fold_range (r, type, r0, int_range<1> (type));
+ op.fold_range (r, type, r0, int_range<1> (type));
}
else
r.set_varying (type);
--
2.36.1
next prev parent reply other threads:[~2022-06-01 9:02 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-05-30 13:27 [PATCH 1/5] Implement abstract vrange class Aldy Hernandez
2022-05-30 13:27 ` [PATCH 2/5] Implement generic range temporaries Aldy Hernandez
2022-05-30 14:56 ` Andrew MacLeod
2022-05-31 6:21 ` Aldy Hernandez
2022-05-31 16:40 ` Andrew MacLeod
2022-06-01 9:01 ` Aldy Hernandez
2022-05-30 13:27 ` [PATCH 3/5] Convert range-op.* to vrange Aldy Hernandez
2022-06-01 9:01 ` Aldy Hernandez [this message]
2022-05-30 13:27 ` [PATCH 4/5] Revamp irange_allocator to handle vranges Aldy Hernandez
2022-06-01 9:02 ` Aldy Hernandez
2022-05-30 13:27 ` [PATCH 5/5] Convert ranger and clients to vrange Aldy Hernandez
2022-06-01 9:04 ` Aldy Hernandez
2022-06-27 0:33 ` Xi Ruoyao
2022-06-01 8:57 ` [PATCH 1/5] Implement abstract vrange class Aldy Hernandez
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=CAGm3qMX_MZdv9icgq5_A199XvX0uVZv2T8C7w6RuSwvkqxWozw@mail.gmail.com \
--to=aldyh@redhat.com \
--cc=gcc-patches@gcc.gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).