Commit Message
With DOM converted to ranger, there are no longer any uses of the EVRP
engine. For that matter, we haven't used the legacy mode in quite a
while, so I think it's safe to remove any associated code.
There are some methods in vr_values which should now be private, but I
didn't bother changing them, as most of the vr_values class will be
removed when VRP1 is converted to ranger.
Does anyone have any issues with me pushing this?
gcc/ChangeLog:
* Makefile.in: Remove gimple-ssa-evrp.o and gimple-ssa-evrp-analyze.o.
* flag-types.h (enum evrp_mode): Remove.
* params.opt: Remove --param=evrp-mode.
* tree-vrp.cc (make_pass_early_vrp): New.
(pass_vrp::execute): Call early VRP instance.
* gimple-ssa-evrp-analyze.cc: Removed.
* gimple-ssa-evrp-analyze.h: Removed.
* gimple-ssa-evrp.cc: Removed.
---
gcc/Makefile.in | 2 -
gcc/flag-types.h | 9 -
gcc/gimple-ssa-evrp-analyze.cc | 456 --------------------------------
gcc/gimple-ssa-evrp-analyze.h | 58 ----
gcc/gimple-ssa-evrp.cc | 395 ---------------------------
gcc/params.opt | 19 --
gcc/testsuite/g++.dg/pr100774.C | 2 +-
gcc/testsuite/gcc.dg/pr100781.c | 2 +-
gcc/tree-vrp.cc | 34 ++-
9 files changed, 31 insertions(+), 946 deletions(-)
delete mode 100644 gcc/gimple-ssa-evrp-analyze.cc
delete mode 100644 gcc/gimple-ssa-evrp-analyze.h
delete mode 100644 gcc/gimple-ssa-evrp.cc
Comments
On Mon, Jun 27, 2022 at 9:04 PM Aldy Hernandez <aldyh@redhat.com> wrote:
>
> With DOM converted to ranger, there are no longer any uses of the EVRP
> engine. For that matter, we haven't used the legacy mode in quite a
> while, so I think it's safe to remove any associated code.
>
> There are some methods in vr_values which should now be private, but I
> didn't bother changing them, as most of the vr_values class will be
> removed when VRP1 is converted to ranger.
>
> Does anyone have any issues with me pushing this?
Fine with me.
> gcc/ChangeLog:
>
> * Makefile.in: Remove gimple-ssa-evrp.o and gimple-ssa-evrp-analyze.o.
> * flag-types.h (enum evrp_mode): Remove.
> * params.opt: Remove --param=evrp-mode.
> * tree-vrp.cc (make_pass_early_vrp): New.
> (pass_vrp::execute): Call early VRP instance.
> * gimple-ssa-evrp-analyze.cc: Removed.
> * gimple-ssa-evrp-analyze.h: Removed.
> * gimple-ssa-evrp.cc: Removed.
> ---
> gcc/Makefile.in | 2 -
> gcc/flag-types.h | 9 -
> gcc/gimple-ssa-evrp-analyze.cc | 456 --------------------------------
> gcc/gimple-ssa-evrp-analyze.h | 58 ----
> gcc/gimple-ssa-evrp.cc | 395 ---------------------------
> gcc/params.opt | 19 --
> gcc/testsuite/g++.dg/pr100774.C | 2 +-
> gcc/testsuite/gcc.dg/pr100781.c | 2 +-
> gcc/tree-vrp.cc | 34 ++-
> 9 files changed, 31 insertions(+), 946 deletions(-)
> delete mode 100644 gcc/gimple-ssa-evrp-analyze.cc
> delete mode 100644 gcc/gimple-ssa-evrp-analyze.h
> delete mode 100644 gcc/gimple-ssa-evrp.cc
>
> diff --git a/gcc/Makefile.in b/gcc/Makefile.in
> index b6dcc45a58a..86257a8b84f 100644
> --- a/gcc/Makefile.in
> +++ b/gcc/Makefile.in
> @@ -1413,8 +1413,6 @@ OBJS = \
> gimple-range-infer.o \
> gimple-range-trace.o \
> gimple-ssa-backprop.o \
> - gimple-ssa-evrp.o \
> - gimple-ssa-evrp-analyze.o \
> gimple-ssa-isolate-paths.o \
> gimple-ssa-nonnull-compare.o \
> gimple-ssa-split-paths.o \
> diff --git a/gcc/flag-types.h b/gcc/flag-types.h
> index 2c8498169e0..a11f99af887 100644
> --- a/gcc/flag-types.h
> +++ b/gcc/flag-types.h
> @@ -479,15 +479,6 @@ enum threader_debug
> THREADER_DEBUG_ALL = 1
> };
>
> -/* EVRP mode. */
> -enum evrp_mode
> -{
> - EVRP_MODE_RVRP_ONLY,
> - EVRP_MODE_EVRP_ONLY,
> - EVRP_MODE_EVRP_FIRST,
> - EVRP_MODE_RVRP_FIRST
> -};
> -
> /* VRP modes. */
> enum vrp_mode
> {
> diff --git a/gcc/gimple-ssa-evrp-analyze.cc b/gcc/gimple-ssa-evrp-analyze.cc
> deleted file mode 100644
> index 82142db7976..00000000000
> --- a/gcc/gimple-ssa-evrp-analyze.cc
> +++ /dev/null
> @@ -1,456 +0,0 @@
> -/* Support routines for Value Range Propagation (VRP).
> - Copyright (C) 2005-2022 Free Software Foundation, Inc.
> -
> -This file is part of GCC.
> -
> -GCC is free software; you can redistribute it and/or modify
> -it under the terms of the GNU General Public License as published by
> -the Free Software Foundation; either version 3, or (at your option)
> -any later version.
> -
> -GCC is distributed in the hope that it will be useful,
> -but WITHOUT ANY WARRANTY; without even the implied warranty of
> -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> -GNU General Public License for more details.
> -
> -You should have received a copy of the GNU General Public License
> -along with GCC; see the file COPYING3. If not see
> -<http://www.gnu.org/licenses/>. */
> -
> -#include "config.h"
> -#include "system.h"
> -#include "coretypes.h"
> -#include "backend.h"
> -#include "tree.h"
> -#include "gimple.h"
> -#include "tree-pass.h"
> -#include "ssa.h"
> -#include "gimple-pretty-print.h"
> -#include "cfganal.h"
> -#include "gimple-iterator.h"
> -#include "gimple-fold.h"
> -#include "tree-eh.h"
> -#include "tree-cfg.h"
> -#include "tree-ssa-loop-manip.h"
> -#include "tree-ssa-loop.h"
> -#include "cfgloop.h"
> -#include "tree-scalar-evolution.h"
> -#include "tree-ssa-propagate.h"
> -#include "alloc-pool.h"
> -#include "domwalk.h"
> -#include "tree-cfgcleanup.h"
> -#include "vr-values.h"
> -#include "gimple-ssa-evrp-analyze.h"
> -
> -evrp_range_analyzer::evrp_range_analyzer (bool update_global_ranges)
> - : stack (10), m_update_global_ranges (update_global_ranges)
> -{
> - edge e;
> - edge_iterator ei;
> - basic_block bb;
> - FOR_EACH_BB_FN (bb, cfun)
> - {
> - bb->flags &= ~BB_VISITED;
> - FOR_EACH_EDGE (e, ei, bb->preds)
> - e->flags |= EDGE_EXECUTABLE;
> - }
> -}
> -
> -/* Push an unwinding marker onto the unwinding stack. */
> -
> -void
> -evrp_range_analyzer::push_marker ()
> -{
> - stack.safe_push (std::make_pair (NULL_TREE, (value_range_equiv *)NULL));
> -}
> -
> -/* Analyze ranges as we enter basic block BB. */
> -
> -void
> -evrp_range_analyzer::enter (basic_block bb)
> -{
> - if (!optimize)
> - return;
> - push_marker ();
> - record_ranges_from_incoming_edge (bb);
> - record_ranges_from_phis (bb);
> - bb->flags |= BB_VISITED;
> -}
> -
> -/* Find new range for NAME such that (OP CODE LIMIT) is true. */
> -value_range_equiv *
> -evrp_range_analyzer::try_find_new_range (tree name,
> - tree op, tree_code code, tree limit)
> -{
> - value_range_equiv vr;
> - const value_range_equiv *old_vr = get_value_range (name);
> -
> - /* Discover VR when condition is true. */
> - extract_range_for_var_from_comparison_expr (name, code, op, limit, &vr);
> - /* If we found any usable VR, set the VR to ssa_name and create a
> - PUSH old value in the stack with the old VR. */
> - if (!vr.undefined_p () && !vr.varying_p ())
> - {
> - if (old_vr->equal_p (vr, /*ignore_equivs=*/true))
> - return NULL;
> - value_range_equiv *new_vr = allocate_value_range_equiv ();
> - new_vr->move (&vr);
> - return new_vr;
> - }
> - return NULL;
> -}
> -
> -/* For LHS record VR in the SSA info. */
> -void
> -evrp_range_analyzer::set_ssa_range_info (tree lhs, value_range_equiv *vr)
> -{
> - gcc_assert (m_update_global_ranges);
> -
> - /* Set the SSA with the value range. */
> - if (INTEGRAL_TYPE_P (TREE_TYPE (lhs)))
> - {
> - if (!vr->varying_p () && vr->constant_p ())
> - set_range_info (lhs, *vr);
> - }
> - else if (POINTER_TYPE_P (TREE_TYPE (lhs))
> - && range_includes_zero_p (vr) == 0)
> - set_ptr_nonnull (lhs);
> -}
> -
> -/* Return true if all uses of NAME are dominated by STMT or feed STMT
> - via a chain of single immediate uses. */
> -
> -static bool
> -all_uses_feed_or_dominated_by_stmt (tree name, gimple *stmt)
> -{
> - use_operand_p use_p, use2_p;
> - imm_use_iterator iter;
> - basic_block stmt_bb = gimple_bb (stmt);
> -
> - FOR_EACH_IMM_USE_FAST (use_p, iter, name)
> - {
> - gimple *use_stmt = USE_STMT (use_p), *use_stmt2;
> - if (use_stmt == stmt
> - || is_gimple_debug (use_stmt)
> - || (gimple_bb (use_stmt) != stmt_bb
> - && dominated_by_p (CDI_DOMINATORS,
> - gimple_bb (use_stmt), stmt_bb)))
> - continue;
> - while (use_stmt != stmt
> - && is_gimple_assign (use_stmt)
> - && TREE_CODE (gimple_assign_lhs (use_stmt)) == SSA_NAME
> - && single_imm_use (gimple_assign_lhs (use_stmt),
> - &use2_p, &use_stmt2))
> - use_stmt = use_stmt2;
> - if (use_stmt != stmt)
> - return false;
> - }
> - return true;
> -}
> -
> -void
> -evrp_range_analyzer::record_ranges_from_incoming_edge (basic_block bb)
> -{
> - edge pred_e = single_pred_edge_ignoring_loop_edges (bb, false);
> - if (pred_e)
> - {
> - gimple *stmt = last_stmt (pred_e->src);
> - tree op0 = NULL_TREE;
> -
> - if (stmt
> - && gimple_code (stmt) == GIMPLE_COND
> - && (op0 = gimple_cond_lhs (stmt))
> - && TREE_CODE (op0) == SSA_NAME
> - && (INTEGRAL_TYPE_P (TREE_TYPE (gimple_cond_lhs (stmt)))
> - || POINTER_TYPE_P (TREE_TYPE (gimple_cond_lhs (stmt)))))
> - {
> - if (dump_file && (dump_flags & TDF_DETAILS))
> - {
> - fprintf (dump_file, "Visiting controlling predicate ");
> - print_gimple_stmt (dump_file, stmt, 0);
> - }
> - /* Entering a new scope. Try to see if we can find a VR
> - here. */
> - tree op1 = gimple_cond_rhs (stmt);
> - if (TREE_OVERFLOW_P (op1))
> - op1 = drop_tree_overflow (op1);
> - tree_code code = gimple_cond_code (stmt);
> -
> - auto_vec<assert_info, 8> asserts;
> - register_edge_assert_for (op0, pred_e, code, op0, op1, asserts);
> - if (TREE_CODE (op1) == SSA_NAME)
> - register_edge_assert_for (op1, pred_e, code, op0, op1, asserts);
> -
> - auto_vec<std::pair<tree, value_range_equiv *>, 8> vrs;
> - for (unsigned i = 0; i < asserts.length (); ++i)
> - {
> - value_range_equiv *vr
> - = try_find_new_range (asserts[i].name,
> - asserts[i].expr,
> - asserts[i].comp_code,
> - asserts[i].val);
> - if (vr)
> - vrs.safe_push (std::make_pair (asserts[i].name, vr));
> - }
> -
> - /* If pred_e is really a fallthru we can record value ranges
> - in SSA names as well. */
> - bool is_fallthru = assert_unreachable_fallthru_edge_p (pred_e);
> -
> - /* Push updated ranges only after finding all of them to avoid
> - ordering issues that can lead to worse ranges. */
> - for (unsigned i = 0; i < vrs.length (); ++i)
> - {
> - /* But make sure we do not weaken ranges like when
> - getting first [64, +INF] and then ~[0, 0] from
> - conditions like (s & 0x3cc0) == 0). */
> - const value_range_equiv *old_vr
> - = get_value_range (vrs[i].first);
> - value_range tem (*old_vr);
> - tem.legacy_verbose_intersect (vrs[i].second);
> - if (tem.equal_p (*old_vr))
> - {
> - free_value_range (vrs[i].second);
> - continue;
> - }
> - push_value_range (vrs[i].first, vrs[i].second);
> - if (is_fallthru
> - && m_update_global_ranges
> - && all_uses_feed_or_dominated_by_stmt (vrs[i].first, stmt)
> - /* The condition must post-dominate the definition point. */
> - && (SSA_NAME_IS_DEFAULT_DEF (vrs[i].first)
> - || (gimple_bb (SSA_NAME_DEF_STMT (vrs[i].first))
> - == pred_e->src)))
> - {
> - set_ssa_range_info (vrs[i].first, vrs[i].second);
> - maybe_set_nonzero_bits (pred_e, vrs[i].first);
> - }
> - }
> - }
> - }
> -}
> -
> -void
> -evrp_range_analyzer::record_ranges_from_phis (basic_block bb)
> -{
> - /* Visit PHI stmts and discover any new VRs possible. */
> - bool has_unvisited_preds = false;
> - edge_iterator ei;
> - edge e;
> - FOR_EACH_EDGE (e, ei, bb->preds)
> - if (e->flags & EDGE_EXECUTABLE
> - && !(e->src->flags & BB_VISITED))
> - {
> - has_unvisited_preds = true;
> - break;
> - }
> -
> - for (gphi_iterator gpi = gsi_start_phis (bb);
> - !gsi_end_p (gpi); gsi_next (&gpi))
> - {
> - gphi *phi = gpi.phi ();
> - tree lhs = PHI_RESULT (phi);
> - if (virtual_operand_p (lhs))
> - continue;
> -
> - /* Skips floats and other things we can't represent in a
> - range. */
> - if (!value_range_equiv::supports_p (TREE_TYPE (lhs)))
> - continue;
> -
> - value_range_equiv vr_result;
> - bool interesting = stmt_interesting_for_vrp (phi);
> - if (!has_unvisited_preds && interesting)
> - extract_range_from_phi_node (phi, &vr_result);
> - else
> - {
> - vr_result.set_varying (TREE_TYPE (lhs));
> - /* When we have an unvisited executable predecessor we can't
> - use PHI arg ranges which may be still UNDEFINED but have
> - to use VARYING for them. But we can still resort to
> - SCEV for loop header PHIs. */
> - class loop *l;
> - if (scev_initialized_p ()
> - && interesting
> - && (l = loop_containing_stmt (phi))
> - && l->header == gimple_bb (phi))
> - adjust_range_with_scev (&vr_result, l, phi, lhs);
> - }
> - update_value_range (lhs, &vr_result);
> -
> - /* Set the SSA with the value range. */
> - if (m_update_global_ranges)
> - set_ssa_range_info (lhs, &vr_result);
> - }
> -}
> -
> -/* Record ranges from STMT into our VR_VALUES class. If TEMPORARY is
> - true, then this is a temporary equivalence and should be recorded
> - into the unwind table. Othewise record the equivalence into the
> - global table. */
> -
> -void
> -evrp_range_analyzer::record_ranges_from_stmt (gimple *stmt, bool temporary)
> -{
> - tree output = NULL_TREE;
> -
> - if (!optimize)
> - return;
> -
> - if (dyn_cast <gcond *> (stmt))
> - ;
> - else if (stmt_interesting_for_vrp (stmt))
> - {
> - edge taken_edge;
> - value_range_equiv vr;
> - extract_range_from_stmt (stmt, &taken_edge, &output, &vr);
> - if (output)
> - {
> - /* Set the SSA with the value range. There are two cases to
> - consider. First (the the most common) is we are processing
> - STMT in a context where its resulting range globally holds
> - and thus it can be reflected into the global ranges and need
> - not be unwound as we leave scope.
> -
> - The second case occurs if we are processing a statement in
> - a context where the resulting range must not be reflected
> - into the global tables and must be unwound as we leave
> - the current context. This happens in jump threading for
> - example. */
> - if (!temporary)
> - {
> - /* Case one. We can just update the underlying range
> - information as well as the global information. */
> - update_value_range (output, &vr);
> - if (m_update_global_ranges)
> - set_ssa_range_info (output, &vr);
> - }
> - else
> - {
> - /* We're going to need to unwind this range. We cannot
> - use VR as that's a stack object. We have to allocate
> - a new range and push the old range onto the stack. We
> - also have to be very careful about sharing the underlying
> - bitmaps. Ugh. */
> - value_range_equiv *new_vr = allocate_value_range_equiv ();
> - new_vr->set (vr.min (), vr.max (), NULL, vr.kind ());
> - vr.equiv_clear ();
> - push_value_range (output, new_vr);
> - }
> - }
> - else
> - set_defs_to_varying (stmt);
> - }
> - else
> - set_defs_to_varying (stmt);
> -
> - /* See if we can derive a range for any of STMT's operands. */
> - tree op;
> - ssa_op_iter i;
> - FOR_EACH_SSA_TREE_OPERAND (op, stmt, i, SSA_OP_USE)
> - {
> - tree value;
> - enum tree_code comp_code;
> -
> - /* If OP is used in such a way that we can infer a value
> - range for it, and we don't find a previous assertion for
> - it, create a new assertion location node for OP. */
> - if (infer_value_range (stmt, op, &comp_code, &value))
> - {
> - /* If we are able to infer a nonzero value range for OP,
> - then walk backwards through the use-def chain to see if OP
> - was set via a typecast.
> - If so, then we can also infer a nonzero value range
> - for the operand of the NOP_EXPR. */
> - if (comp_code == NE_EXPR && integer_zerop (value))
> - {
> - tree t = op;
> - gimple *def_stmt = SSA_NAME_DEF_STMT (t);
> - while (is_gimple_assign (def_stmt)
> - && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def_stmt))
> - && TREE_CODE
> - (gimple_assign_rhs1 (def_stmt)) == SSA_NAME
> - && POINTER_TYPE_P
> - (TREE_TYPE (gimple_assign_rhs1 (def_stmt))))
> - {
> - t = gimple_assign_rhs1 (def_stmt);
> - def_stmt = SSA_NAME_DEF_STMT (t);
> -
> - /* Add VR when (T COMP_CODE value) condition is
> - true. */
> - value_range_equiv *op_range
> - = try_find_new_range (t, t, comp_code, value);
> - if (op_range)
> - push_value_range (t, op_range);
> - }
> - }
> - /* Add VR when (OP COMP_CODE value) condition is true. */
> - value_range_equiv *op_range = try_find_new_range (op, op,
> - comp_code, value);
> - if (op_range)
> - push_value_range (op, op_range);
> - }
> - }
> -}
> -
> -/* Unwind recorded ranges to their most recent state. */
> -
> -void
> -evrp_range_analyzer::pop_to_marker (void)
> -{
> - gcc_checking_assert (!stack.is_empty ());
> - while (stack.last ().first != NULL_TREE)
> - pop_value_range ();
> - stack.pop ();
> -}
> -
> -/* Restore/pop VRs valid only for BB when we leave BB. */
> -
> -void
> -evrp_range_analyzer::leave (basic_block bb ATTRIBUTE_UNUSED)
> -{
> - if (!optimize)
> - return;
> - pop_to_marker ();
> -}
> -
> -
> -/* Push the Value Range of VAR to the stack and update it with new VR. */
> -
> -void
> -evrp_range_analyzer::push_value_range (tree var, value_range_equiv *vr)
> -{
> - if (dump_file && (dump_flags & TDF_DETAILS))
> - {
> - fprintf (dump_file, "pushing new range for ");
> - print_generic_expr (dump_file, var);
> - fprintf (dump_file, ": ");
> - dump_value_range (dump_file, vr);
> - fprintf (dump_file, "\n");
> - }
> - value_range_equiv *old_vr = swap_vr_value (var, vr);
> - stack.safe_push (std::make_pair (var, old_vr));
> -}
> -
> -/* Pop a Value Range from the vrp_stack. */
> -
> -void
> -evrp_range_analyzer::pop_value_range ()
> -{
> - std::pair<tree, value_range_equiv *> e = stack.pop ();
> - tree var = e.first;
> - value_range_equiv *vr = e.second;
> - if (dump_file && (dump_flags & TDF_DETAILS))
> - {
> - fprintf (dump_file, "popping range for ");
> - print_generic_expr (dump_file, var);
> - fprintf (dump_file, ", restoring ");
> - dump_value_range (dump_file, vr);
> - fprintf (dump_file, "\n");
> - }
> - /* We saved off a lattice entry, now give it back and release
> - the one we popped. */
> - value_range_equiv *popped_vr = swap_vr_value (var, vr);
> - if (popped_vr)
> - free_value_range (popped_vr);
> -}
> diff --git a/gcc/gimple-ssa-evrp-analyze.h b/gcc/gimple-ssa-evrp-analyze.h
> deleted file mode 100644
> index 51c32099dc5..00000000000
> --- a/gcc/gimple-ssa-evrp-analyze.h
> +++ /dev/null
> @@ -1,58 +0,0 @@
> -/* Support routines for Value Range Propagation (VRP).
> - Copyright (C) 2016-2022 Free Software Foundation, Inc.
> -
> -This file is part of GCC.
> -
> -GCC is free software; you can redistribute it and/or modify
> -it under the terms of the GNU General Public License as published by
> -the Free Software Foundation; either version 3, or (at your option)
> -any later version.
> -
> -GCC is distributed in the hope that it will be useful,
> -but WITHOUT ANY WARRANTY; without even the implied warranty of
> -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> -GNU General Public License for more details.
> -
> -You should have received a copy of the GNU General Public License
> -along with GCC; see the file COPYING3. If not see
> -<http://www.gnu.org/licenses/>. */
> -
> -#ifndef GCC_GIMPLE_SSA_EVRP_ANALYZE_H
> -#define GCC_GIMPLE_SSA_EVRP_ANALYZE_H
> -
> -class evrp_range_analyzer : public vr_values
> -{
> - public:
> - evrp_range_analyzer (bool update_global_ranges);
> - ~evrp_range_analyzer (void)
> - {
> - stack.release ();
> - }
> -
> - void enter (basic_block);
> - void push_marker (void);
> - void pop_to_marker (void);
> - void leave (basic_block);
> - void record_ranges_from_stmt (gimple *, bool);
> -
> - /* Record a new unwindable range. */
> - void push_value_range (tree var, value_range_equiv *vr);
> -
> - private:
> - DISABLE_COPY_AND_ASSIGN (evrp_range_analyzer);
> -
> - void pop_value_range ();
> - value_range_equiv *try_find_new_range (tree, tree op, tree_code code,
> - tree limit);
> - void record_ranges_from_incoming_edge (basic_block);
> - void record_ranges_from_phis (basic_block);
> - void set_ssa_range_info (tree, value_range_equiv *);
> -
> - /* STACK holds the old VR. */
> - auto_vec<std::pair <tree, value_range_equiv *> > stack;
> -
> - /* True if we are updating global ranges, false otherwise. */
> - bool m_update_global_ranges;
> -};
> -
> -#endif /* GCC_GIMPLE_SSA_EVRP_ANALYZE_H */
> diff --git a/gcc/gimple-ssa-evrp.cc b/gcc/gimple-ssa-evrp.cc
> deleted file mode 100644
> index 20388ed5431..00000000000
> --- a/gcc/gimple-ssa-evrp.cc
> +++ /dev/null
> @@ -1,395 +0,0 @@
> -/* Support routines for Value Range Propagation (VRP).
> - Copyright (C) 2005-2022 Free Software Foundation, Inc.
> -
> -This file is part of GCC.
> -
> -GCC is free software; you can redistribute it and/or modify
> -it under the terms of the GNU General Public License as published by
> -the Free Software Foundation; either version 3, or (at your option)
> -any later version.
> -
> -GCC is distributed in the hope that it will be useful,
> -but WITHOUT ANY WARRANTY; without even the implied warranty of
> -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> -GNU General Public License for more details.
> -
> -You should have received a copy of the GNU General Public License
> -along with GCC; see the file COPYING3. If not see
> -<http://www.gnu.org/licenses/>. */
> -
> -#include "config.h"
> -#include "system.h"
> -#include "coretypes.h"
> -#include "backend.h"
> -#include "tree.h"
> -#include "gimple.h"
> -#include "tree-pass.h"
> -#include "ssa.h"
> -#include "gimple-pretty-print.h"
> -#include "cfganal.h"
> -#include "gimple-iterator.h"
> -#include "gimple-fold.h"
> -#include "tree-eh.h"
> -#include "tree-cfg.h"
> -#include "tree-ssa-loop-manip.h"
> -#include "tree-ssa-loop.h"
> -#include "cfgloop.h"
> -#include "tree-scalar-evolution.h"
> -#include "tree-ssa-propagate.h"
> -#include "alloc-pool.h"
> -#include "domwalk.h"
> -#include "tree-cfgcleanup.h"
> -#include "vr-values.h"
> -#include "gimple-ssa-evrp-analyze.h"
> -#include "gimple-range.h"
> -#include "fold-const.h"
> -#include "value-pointer-equiv.h"
> -#include "tree-vrp.h"
> -
> -// This is the classic EVRP folder which uses a dominator walk and pushes
> -// ranges into the next block if it is a single predecessor block.
> -
> -class evrp_folder : public substitute_and_fold_engine
> -{
> -public:
> - evrp_folder () :
> - substitute_and_fold_engine (),
> - m_range_analyzer (/*update_global_ranges=*/true),
> - simplifier (&m_range_analyzer)
> - { }
> -
> - ~evrp_folder ()
> - {
> - if (dump_file)
> - {
> - fprintf (dump_file, "\nValue ranges after Early VRP:\n\n");
> - m_range_analyzer.dump (dump_file);
> - fprintf (dump_file, "\n");
> - }
> - }
> -
> - tree value_of_expr (tree name, gimple *stmt) override
> - {
> - return m_range_analyzer.value_of_expr (name, stmt);
> - }
> -
> - void pre_fold_bb (basic_block bb) override
> - {
> - if (dump_file && (dump_flags & TDF_DETAILS))
> - fprintf (dump_file, "evrp visiting BB%d\n", bb->index);
> - m_range_analyzer.enter (bb);
> - }
> -
> - void pre_fold_stmt (gimple *stmt) override
> - {
> - if (dump_file && (dump_flags & TDF_DETAILS))
> - {
> - fprintf (dump_file, "evrp visiting stmt ");
> - print_gimple_stmt (dump_file, stmt, 0);
> - }
> - m_range_analyzer.record_ranges_from_stmt (stmt, false);
> - }
> -
> - bool fold_stmt (gimple_stmt_iterator *gsi) override
> - {
> - return simplifier.simplify (gsi);
> - }
> -
> - void post_fold_bb (basic_block bb) override
> - {
> - m_range_analyzer.leave (bb);
> - }
> -
> - void post_new_stmt (gimple *stmt) override
> - {
> - m_range_analyzer.set_defs_to_varying (stmt);
> - }
> -
> -protected:
> - DISABLE_COPY_AND_ASSIGN (evrp_folder);
> - evrp_range_analyzer m_range_analyzer;
> - simplify_using_ranges simplifier;
> -};
> -
> -// In a hybrid folder, start with an EVRP folder, and add the required
> -// fold_stmt bits to either try the ranger first or second.
> -//
> -// The 3 value_* routines will always query both EVRP and the ranger for
> -// a result, and ensure they return the same value. If either returns a value
> -// when the other doesn't, it is flagged in the listing, and the discoverd
> -// value is returned.
> -//
> -// The simplifier is unable to process 2 different sources, thus we try to
> -// use one engine, and if it fails to simplify, try using the other engine.
> -// It is reported when the first attempt fails and the second succeeds.
> -
> -class hybrid_folder : public evrp_folder
> -{
> -public:
> - hybrid_folder (bool evrp_first)
> - {
> - m_ranger = enable_ranger (cfun);
> -
> - if (evrp_first)
> - {
> - first = &m_range_analyzer;
> - first_exec_flag = 0;
> - second = m_ranger;
> - second_exec_flag = m_ranger->non_executable_edge_flag;
> - }
> - else
> - {
> - first = m_ranger;
> - first_exec_flag = m_ranger->non_executable_edge_flag;
> - second = &m_range_analyzer;
> - second_exec_flag = 0;
> - }
> - m_pta = new pointer_equiv_analyzer (m_ranger);
> - }
> -
> - ~hybrid_folder ()
> - {
> - if (dump_file && (dump_flags & TDF_DETAILS))
> - m_ranger->dump (dump_file);
> -
> - m_ranger->export_global_ranges ();
> - disable_ranger (cfun);
> - delete m_pta;
> - }
> -
> - bool fold_stmt (gimple_stmt_iterator *gsi) override
> - {
> - simplifier.set_range_query (first, first_exec_flag);
> - if (simplifier.simplify (gsi))
> - return true;
> -
> - simplifier.set_range_query (second, second_exec_flag);
> - if (simplifier.simplify (gsi))
> - {
> - if (dump_file)
> - fprintf (dump_file, "EVRP:hybrid: Second query simplifed stmt\n");
> - return true;
> - }
> - return false;
> - }
> -
> - void pre_fold_stmt (gimple *stmt) override
> - {
> - evrp_folder::pre_fold_stmt (stmt);
> - m_pta->visit_stmt (stmt);
> - }
> -
> - void pre_fold_bb (basic_block bb) override
> - {
> - evrp_folder::pre_fold_bb (bb);
> - m_pta->enter (bb);
> - }
> -
> - void post_fold_bb (basic_block bb) override
> - {
> - evrp_folder::post_fold_bb (bb);
> - m_pta->leave (bb);
> - }
> -
> - tree value_of_expr (tree name, gimple *) override;
> - tree value_on_edge (edge, tree name) override;
> - tree value_of_stmt (gimple *, tree name) override;
> -
> -private:
> - DISABLE_COPY_AND_ASSIGN (hybrid_folder);
> - gimple_ranger *m_ranger;
> - range_query *first;
> - int first_exec_flag;
> - range_query *second;
> - int second_exec_flag;
> - pointer_equiv_analyzer *m_pta;
> - tree choose_value (tree evrp_val, tree ranger_val);
> -};
> -
> -
> -tree
> -hybrid_folder::value_of_expr (tree op, gimple *stmt)
> -{
> - tree evrp_ret = evrp_folder::value_of_expr (op, stmt);
> - tree ranger_ret;
> - if (TREE_CODE (op) == SSA_NAME && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op))
> - ranger_ret = NULL;
> - else
> - {
> - ranger_ret = m_ranger->value_of_expr (op, stmt);
> - if (!ranger_ret && supported_pointer_equiv_p (op))
> - ranger_ret = m_pta->get_equiv (op);
> - }
> - return choose_value (evrp_ret, ranger_ret);
> -}
> -
> -tree
> -hybrid_folder::value_on_edge (edge e, tree op)
> -{
> - // Call evrp::value_of_expr directly. Otherwise another dual call is made
> - // via hybrid_folder::value_of_expr, but without an edge.
> - tree evrp_ret = evrp_folder::value_of_expr (op, NULL);
> - tree ranger_ret;
> - if (TREE_CODE (op) == SSA_NAME && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op))
> - ranger_ret = NULL;
> - else
> - {
> - ranger_ret = m_ranger->value_on_edge (e, op);
> - if (!ranger_ret && supported_pointer_equiv_p (op))
> - ranger_ret = m_pta->get_equiv (op);
> - }
> - return choose_value (evrp_ret, ranger_ret);
> -}
> -
> -tree
> -hybrid_folder::value_of_stmt (gimple *stmt, tree op)
> -{
> - // Call evrp::value_of_expr directly. Otherwise another dual call is made
> - // via hybrid_folder::value_of_expr, but without a stmt.
> - tree evrp_ret;
> - if (op)
> - evrp_ret = evrp_folder::value_of_expr (op, NULL);
> - else
> - evrp_ret = NULL_TREE;
> -
> - tree ranger_ret;
> - if (op && TREE_CODE (op) == SSA_NAME && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op))
> - ranger_ret = NULL;
> - else
> - ranger_ret = m_ranger->value_of_stmt (stmt, op);
> - return choose_value (evrp_ret, ranger_ret);
> -}
> -
> -// Given trees returned by EVRP and Ranger, choose/report the value to use
> -// by the folder.
> -
> -tree
> -hybrid_folder::choose_value (tree evrp_val, tree ranger_val)
> -{
> - // If both found the same value, just return it.
> - if (evrp_val && ranger_val && !compare_values (evrp_val, ranger_val))
> - return evrp_val;
> -
> - // If neither returned a value, return NULL_TREE.
> - if (!ranger_val && !evrp_val)
> - return NULL_TREE;
> -
> - // Otherwise there is a discrepancy to flag.
> - if (dump_file)
> - {
> - if (evrp_val && ranger_val)
> - fprintf (dump_file, "EVRP:hybrid: Disagreement\n");
> - if (evrp_val)
> - {
> - fprintf (dump_file, "EVRP:hybrid: EVRP found singleton ");
> - print_generic_expr (dump_file, evrp_val);
> - fprintf (dump_file, "\n");
> - }
> - if (ranger_val)
> - {
> - fprintf (dump_file, "EVRP:hybrid: RVRP found singleton ");
> - print_generic_expr (dump_file, ranger_val);
> - fprintf (dump_file, "\n");
> - }
> - }
> -
> - // If one value was found, return it.
> - if (!evrp_val)
> - return ranger_val;
> - if (!ranger_val)
> - return evrp_val;
> -
> - // If values are different, return the first calculated value.
> - if (param_evrp_mode == EVRP_MODE_RVRP_FIRST)
> - return ranger_val;
> - return evrp_val;
> -}
> -
> -/* Main entry point for the early vrp pass which is a simplified non-iterative
> - version of vrp where basic blocks are visited in dominance order. Value
> - ranges discovered in early vrp will also be used by ipa-vrp. */
> -
> -static unsigned int
> -execute_early_vrp ()
> -{
> - if (param_evrp_mode == EVRP_MODE_RVRP_ONLY)
> - return execute_ranger_vrp (cfun, false);
> -
> - /* Ideally this setup code would move into the ctor for the folder
> - However, this setup can change the number of blocks which
> - invalidates the internal arrays that are set up by the dominator
> - walker in substitute_and_fold_engine. */
> - loop_optimizer_init (LOOPS_NORMAL | LOOPS_HAVE_RECORDED_EXITS);
> - rewrite_into_loop_closed_ssa (NULL, TODO_update_ssa);
> - scev_initialize ();
> - calculate_dominance_info (CDI_DOMINATORS);
> -
> - // Only the last 2 bits matter for choosing the folder.
> - switch (param_evrp_mode)
> - {
> - case EVRP_MODE_EVRP_ONLY:
> - {
> - evrp_folder folder;
> - folder.substitute_and_fold ();
> - break;
> - }
> - case EVRP_MODE_EVRP_FIRST:
> - {
> - hybrid_folder folder (true);
> - folder.substitute_and_fold ();
> - break;
> - }
> - case EVRP_MODE_RVRP_FIRST:
> - {
> - hybrid_folder folder (false);
> - folder.substitute_and_fold ();
> - break;
> - }
> - default:
> - gcc_unreachable ();
> - }
> -
> - scev_finalize ();
> - loop_optimizer_finalize ();
> - return 0;
> -}
> -
> -namespace {
> -
> -const pass_data pass_data_early_vrp =
> -{
> - GIMPLE_PASS, /* type */
> - "evrp", /* name */
> - OPTGROUP_NONE, /* optinfo_flags */
> - TV_TREE_EARLY_VRP, /* tv_id */
> - PROP_ssa, /* properties_required */
> - 0, /* properties_provided */
> - 0, /* properties_destroyed */
> - 0, /* todo_flags_start */
> - ( TODO_cleanup_cfg | TODO_update_ssa | TODO_verify_all ),
> -};
> -
> -class pass_early_vrp : public gimple_opt_pass
> -{
> -public:
> - pass_early_vrp (gcc::context *ctxt)
> - : gimple_opt_pass (pass_data_early_vrp, ctxt)
> - {}
> -
> - /* opt_pass methods: */
> - opt_pass * clone () { return new pass_early_vrp (m_ctxt); }
> - virtual bool gate (function *)
> - {
> - return flag_tree_vrp != 0;
> - }
> - virtual unsigned int execute (function *)
> - { return execute_early_vrp (); }
> -
> -}; // class pass_vrp
> -} // anon namespace
> -
> -gimple_opt_pass *
> -make_pass_early_vrp (gcc::context *ctxt)
> -{
> - return new pass_early_vrp (ctxt);
> -}
> diff --git a/gcc/params.opt b/gcc/params.opt
> index bcf1423671a..2f9c9cf27dd 100644
> --- a/gcc/params.opt
> +++ b/gcc/params.opt
> @@ -134,25 +134,6 @@ Maximum number of basic blocks before EVRP uses a sparse cache.
> Common Joined UInteger Var(param_evrp_switch_limit) Init(50) Optimization Param
> Maximum number of outgoing edges in a switch before EVRP will not process it.
>
> --param=evrp-mode=
> -Common Joined Var(param_evrp_mode) Enum(evrp_mode) Init(EVRP_MODE_RVRP_ONLY) Param Optimization
> ---param=evrp-mode=[legacy|ranger|legacy-first|ranger-first] Specifies the mode Early VRP should operate in.
> -
> -Enum
> -Name(evrp_mode) Type(enum evrp_mode) UnknownError(unknown evrp mode %qs)
> -
> -EnumValue
> -Enum(evrp_mode) String(legacy) Value(EVRP_MODE_EVRP_ONLY)
> -
> -EnumValue
> -Enum(evrp_mode) String(ranger) Value(EVRP_MODE_RVRP_ONLY)
> -
> -EnumValue
> -Enum(evrp_mode) String(legacy-first) Value(EVRP_MODE_EVRP_FIRST)
> -
> -EnumValue
> -Enum(evrp_mode) String(ranger-first) Value(EVRP_MODE_RVRP_FIRST)
> -
> -param=fsm-scale-path-blocks=
> Common Joined UInteger Var(param_fsm_scale_path_blocks) Init(3) IntegerRange(1, 10) Param Optimization
> Scale factor to apply to the number of blocks in a threading path when comparing to the number of (scaled) statements.
> diff --git a/gcc/testsuite/g++.dg/pr100774.C b/gcc/testsuite/g++.dg/pr100774.C
> index 345fcfa0d01..63320ef73fc 100644
> --- a/gcc/testsuite/g++.dg/pr100774.C
> +++ b/gcc/testsuite/g++.dg/pr100774.C
> @@ -1,5 +1,5 @@
> /* { dg-do compile } */
> -/* { dg-options "-O2 -fno-tree-forwprop --param=evrp-mode=ranger -fcompare-debug " } */
> +/* { dg-options "-O2 -fno-tree-forwprop -fcompare-debug " } */
>
> extern void __attribute__((noreturn)) error();
>
> diff --git a/gcc/testsuite/gcc.dg/pr100781.c b/gcc/testsuite/gcc.dg/pr100781.c
> index c0e008a3ba5..96f0a7a6012 100644
> --- a/gcc/testsuite/gcc.dg/pr100781.c
> +++ b/gcc/testsuite/gcc.dg/pr100781.c
> @@ -1,5 +1,5 @@
> /* { dg-do compile } */
> -/* { dg-options "-O2 --param=evrp-mode=ranger -fcompare-debug " } */
> +/* { dg-options "-O2 -fcompare-debug " } */
>
> struct a {
> int b;
> diff --git a/gcc/tree-vrp.cc b/gcc/tree-vrp.cc
> index 30022dac108..7b4e2917340 100644
> --- a/gcc/tree-vrp.cc
> +++ b/gcc/tree-vrp.cc
> @@ -4388,17 +4388,30 @@ const pass_data pass_data_vrp =
> ( TODO_cleanup_cfg | TODO_update_ssa ), /* todo_flags_finish */
> };
>
> +const pass_data pass_data_early_vrp =
> +{
> + GIMPLE_PASS, /* type */
> + "evrp", /* name */
> + OPTGROUP_NONE, /* optinfo_flags */
> + TV_TREE_EARLY_VRP, /* tv_id */
> + PROP_ssa, /* properties_required */
> + 0, /* properties_provided */
> + 0, /* properties_destroyed */
> + 0, /* todo_flags_start */
> + ( TODO_cleanup_cfg | TODO_update_ssa | TODO_verify_all ),
> +};
> +
> static int vrp_pass_num = 0;
> class pass_vrp : public gimple_opt_pass
> {
> public:
> - pass_vrp (gcc::context *ctxt)
> - : gimple_opt_pass (pass_data_vrp, ctxt), warn_array_bounds_p (false),
> - my_pass (++vrp_pass_num)
> + pass_vrp (gcc::context *ctxt, const pass_data &data_)
> + : gimple_opt_pass (data_, ctxt), data (data_), warn_array_bounds_p (false),
> + my_pass (vrp_pass_num++)
> {}
>
> /* opt_pass methods: */
> - opt_pass * clone () { return new pass_vrp (m_ctxt); }
> + opt_pass * clone () { return new pass_vrp (m_ctxt, data); }
> void set_pass_param (unsigned int n, bool param)
> {
> gcc_assert (n == 0);
> @@ -4407,6 +4420,10 @@ public:
> virtual bool gate (function *) { return flag_tree_vrp != 0; }
> virtual unsigned int execute (function *fun)
> {
> + // Early VRP pass.
> + if (my_pass == 0)
> + return execute_ranger_vrp (fun, /*warn_array_bounds_p=*/false);
> +
> if ((my_pass == 1 && param_vrp1_mode == VRP_MODE_RANGER)
> || (my_pass == 2 && param_vrp2_mode == VRP_MODE_RANGER))
> return execute_ranger_vrp (fun, warn_array_bounds_p);
> @@ -4414,6 +4431,7 @@ public:
> }
>
> private:
> + const pass_data &data;
> bool warn_array_bounds_p;
> int my_pass;
> }; // class pass_vrp
> @@ -4423,5 +4441,11 @@ public:
> gimple_opt_pass *
> make_pass_vrp (gcc::context *ctxt)
> {
> - return new pass_vrp (ctxt);
> + return new pass_vrp (ctxt, pass_data_vrp);
> +}
> +
> +gimple_opt_pass *
> +make_pass_early_vrp (gcc::context *ctxt)
> +{
> + return new pass_vrp (ctxt, pass_data_early_vrp);
> }
> --
> 2.36.1
>
Since Andrew, Jeff, and Richi have all agreed, I have pushed the patch.
Thanks.
Aldy
On Tue, Jun 28, 2022 at 9:37 AM Richard Biener
<richard.guenther@gmail.com> wrote:
>
> On Mon, Jun 27, 2022 at 9:04 PM Aldy Hernandez <aldyh@redhat.com> wrote:
> >
> > With DOM converted to ranger, there are no longer any uses of the EVRP
> > engine. For that matter, we haven't used the legacy mode in quite a
> > while, so I think it's safe to remove any associated code.
> >
> > There are some methods in vr_values which should now be private, but I
> > didn't bother changing them, as most of the vr_values class will be
> > removed when VRP1 is converted to ranger.
> >
> > Does anyone have any issues with me pushing this?
>
> Fine with me.
>
> > gcc/ChangeLog:
> >
> > * Makefile.in: Remove gimple-ssa-evrp.o and gimple-ssa-evrp-analyze.o.
> > * flag-types.h (enum evrp_mode): Remove.
> > * params.opt: Remove --param=evrp-mode.
> > * tree-vrp.cc (make_pass_early_vrp): New.
> > (pass_vrp::execute): Call early VRP instance.
> > * gimple-ssa-evrp-analyze.cc: Removed.
> > * gimple-ssa-evrp-analyze.h: Removed.
> > * gimple-ssa-evrp.cc: Removed.
> > ---
> > gcc/Makefile.in | 2 -
> > gcc/flag-types.h | 9 -
> > gcc/gimple-ssa-evrp-analyze.cc | 456 --------------------------------
> > gcc/gimple-ssa-evrp-analyze.h | 58 ----
> > gcc/gimple-ssa-evrp.cc | 395 ---------------------------
> > gcc/params.opt | 19 --
> > gcc/testsuite/g++.dg/pr100774.C | 2 +-
> > gcc/testsuite/gcc.dg/pr100781.c | 2 +-
> > gcc/tree-vrp.cc | 34 ++-
> > 9 files changed, 31 insertions(+), 946 deletions(-)
> > delete mode 100644 gcc/gimple-ssa-evrp-analyze.cc
> > delete mode 100644 gcc/gimple-ssa-evrp-analyze.h
> > delete mode 100644 gcc/gimple-ssa-evrp.cc
> >
> > diff --git a/gcc/Makefile.in b/gcc/Makefile.in
> > index b6dcc45a58a..86257a8b84f 100644
> > --- a/gcc/Makefile.in
> > +++ b/gcc/Makefile.in
> > @@ -1413,8 +1413,6 @@ OBJS = \
> > gimple-range-infer.o \
> > gimple-range-trace.o \
> > gimple-ssa-backprop.o \
> > - gimple-ssa-evrp.o \
> > - gimple-ssa-evrp-analyze.o \
> > gimple-ssa-isolate-paths.o \
> > gimple-ssa-nonnull-compare.o \
> > gimple-ssa-split-paths.o \
> > diff --git a/gcc/flag-types.h b/gcc/flag-types.h
> > index 2c8498169e0..a11f99af887 100644
> > --- a/gcc/flag-types.h
> > +++ b/gcc/flag-types.h
> > @@ -479,15 +479,6 @@ enum threader_debug
> > THREADER_DEBUG_ALL = 1
> > };
> >
> > -/* EVRP mode. */
> > -enum evrp_mode
> > -{
> > - EVRP_MODE_RVRP_ONLY,
> > - EVRP_MODE_EVRP_ONLY,
> > - EVRP_MODE_EVRP_FIRST,
> > - EVRP_MODE_RVRP_FIRST
> > -};
> > -
> > /* VRP modes. */
> > enum vrp_mode
> > {
> > diff --git a/gcc/gimple-ssa-evrp-analyze.cc b/gcc/gimple-ssa-evrp-analyze.cc
> > deleted file mode 100644
> > index 82142db7976..00000000000
> > --- a/gcc/gimple-ssa-evrp-analyze.cc
> > +++ /dev/null
> > @@ -1,456 +0,0 @@
> > -/* Support routines for Value Range Propagation (VRP).
> > - Copyright (C) 2005-2022 Free Software Foundation, Inc.
> > -
> > -This file is part of GCC.
> > -
> > -GCC is free software; you can redistribute it and/or modify
> > -it under the terms of the GNU General Public License as published by
> > -the Free Software Foundation; either version 3, or (at your option)
> > -any later version.
> > -
> > -GCC is distributed in the hope that it will be useful,
> > -but WITHOUT ANY WARRANTY; without even the implied warranty of
> > -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> > -GNU General Public License for more details.
> > -
> > -You should have received a copy of the GNU General Public License
> > -along with GCC; see the file COPYING3. If not see
> > -<http://www.gnu.org/licenses/>. */
> > -
> > -#include "config.h"
> > -#include "system.h"
> > -#include "coretypes.h"
> > -#include "backend.h"
> > -#include "tree.h"
> > -#include "gimple.h"
> > -#include "tree-pass.h"
> > -#include "ssa.h"
> > -#include "gimple-pretty-print.h"
> > -#include "cfganal.h"
> > -#include "gimple-iterator.h"
> > -#include "gimple-fold.h"
> > -#include "tree-eh.h"
> > -#include "tree-cfg.h"
> > -#include "tree-ssa-loop-manip.h"
> > -#include "tree-ssa-loop.h"
> > -#include "cfgloop.h"
> > -#include "tree-scalar-evolution.h"
> > -#include "tree-ssa-propagate.h"
> > -#include "alloc-pool.h"
> > -#include "domwalk.h"
> > -#include "tree-cfgcleanup.h"
> > -#include "vr-values.h"
> > -#include "gimple-ssa-evrp-analyze.h"
> > -
> > -evrp_range_analyzer::evrp_range_analyzer (bool update_global_ranges)
> > - : stack (10), m_update_global_ranges (update_global_ranges)
> > -{
> > - edge e;
> > - edge_iterator ei;
> > - basic_block bb;
> > - FOR_EACH_BB_FN (bb, cfun)
> > - {
> > - bb->flags &= ~BB_VISITED;
> > - FOR_EACH_EDGE (e, ei, bb->preds)
> > - e->flags |= EDGE_EXECUTABLE;
> > - }
> > -}
> > -
> > -/* Push an unwinding marker onto the unwinding stack. */
> > -
> > -void
> > -evrp_range_analyzer::push_marker ()
> > -{
> > - stack.safe_push (std::make_pair (NULL_TREE, (value_range_equiv *)NULL));
> > -}
> > -
> > -/* Analyze ranges as we enter basic block BB. */
> > -
> > -void
> > -evrp_range_analyzer::enter (basic_block bb)
> > -{
> > - if (!optimize)
> > - return;
> > - push_marker ();
> > - record_ranges_from_incoming_edge (bb);
> > - record_ranges_from_phis (bb);
> > - bb->flags |= BB_VISITED;
> > -}
> > -
> > -/* Find new range for NAME such that (OP CODE LIMIT) is true. */
> > -value_range_equiv *
> > -evrp_range_analyzer::try_find_new_range (tree name,
> > - tree op, tree_code code, tree limit)
> > -{
> > - value_range_equiv vr;
> > - const value_range_equiv *old_vr = get_value_range (name);
> > -
> > - /* Discover VR when condition is true. */
> > - extract_range_for_var_from_comparison_expr (name, code, op, limit, &vr);
> > - /* If we found any usable VR, set the VR to ssa_name and create a
> > - PUSH old value in the stack with the old VR. */
> > - if (!vr.undefined_p () && !vr.varying_p ())
> > - {
> > - if (old_vr->equal_p (vr, /*ignore_equivs=*/true))
> > - return NULL;
> > - value_range_equiv *new_vr = allocate_value_range_equiv ();
> > - new_vr->move (&vr);
> > - return new_vr;
> > - }
> > - return NULL;
> > -}
> > -
> > -/* For LHS record VR in the SSA info. */
> > -void
> > -evrp_range_analyzer::set_ssa_range_info (tree lhs, value_range_equiv *vr)
> > -{
> > - gcc_assert (m_update_global_ranges);
> > -
> > - /* Set the SSA with the value range. */
> > - if (INTEGRAL_TYPE_P (TREE_TYPE (lhs)))
> > - {
> > - if (!vr->varying_p () && vr->constant_p ())
> > - set_range_info (lhs, *vr);
> > - }
> > - else if (POINTER_TYPE_P (TREE_TYPE (lhs))
> > - && range_includes_zero_p (vr) == 0)
> > - set_ptr_nonnull (lhs);
> > -}
> > -
> > -/* Return true if all uses of NAME are dominated by STMT or feed STMT
> > - via a chain of single immediate uses. */
> > -
> > -static bool
> > -all_uses_feed_or_dominated_by_stmt (tree name, gimple *stmt)
> > -{
> > - use_operand_p use_p, use2_p;
> > - imm_use_iterator iter;
> > - basic_block stmt_bb = gimple_bb (stmt);
> > -
> > - FOR_EACH_IMM_USE_FAST (use_p, iter, name)
> > - {
> > - gimple *use_stmt = USE_STMT (use_p), *use_stmt2;
> > - if (use_stmt == stmt
> > - || is_gimple_debug (use_stmt)
> > - || (gimple_bb (use_stmt) != stmt_bb
> > - && dominated_by_p (CDI_DOMINATORS,
> > - gimple_bb (use_stmt), stmt_bb)))
> > - continue;
> > - while (use_stmt != stmt
> > - && is_gimple_assign (use_stmt)
> > - && TREE_CODE (gimple_assign_lhs (use_stmt)) == SSA_NAME
> > - && single_imm_use (gimple_assign_lhs (use_stmt),
> > - &use2_p, &use_stmt2))
> > - use_stmt = use_stmt2;
> > - if (use_stmt != stmt)
> > - return false;
> > - }
> > - return true;
> > -}
> > -
> > -void
> > -evrp_range_analyzer::record_ranges_from_incoming_edge (basic_block bb)
> > -{
> > - edge pred_e = single_pred_edge_ignoring_loop_edges (bb, false);
> > - if (pred_e)
> > - {
> > - gimple *stmt = last_stmt (pred_e->src);
> > - tree op0 = NULL_TREE;
> > -
> > - if (stmt
> > - && gimple_code (stmt) == GIMPLE_COND
> > - && (op0 = gimple_cond_lhs (stmt))
> > - && TREE_CODE (op0) == SSA_NAME
> > - && (INTEGRAL_TYPE_P (TREE_TYPE (gimple_cond_lhs (stmt)))
> > - || POINTER_TYPE_P (TREE_TYPE (gimple_cond_lhs (stmt)))))
> > - {
> > - if (dump_file && (dump_flags & TDF_DETAILS))
> > - {
> > - fprintf (dump_file, "Visiting controlling predicate ");
> > - print_gimple_stmt (dump_file, stmt, 0);
> > - }
> > - /* Entering a new scope. Try to see if we can find a VR
> > - here. */
> > - tree op1 = gimple_cond_rhs (stmt);
> > - if (TREE_OVERFLOW_P (op1))
> > - op1 = drop_tree_overflow (op1);
> > - tree_code code = gimple_cond_code (stmt);
> > -
> > - auto_vec<assert_info, 8> asserts;
> > - register_edge_assert_for (op0, pred_e, code, op0, op1, asserts);
> > - if (TREE_CODE (op1) == SSA_NAME)
> > - register_edge_assert_for (op1, pred_e, code, op0, op1, asserts);
> > -
> > - auto_vec<std::pair<tree, value_range_equiv *>, 8> vrs;
> > - for (unsigned i = 0; i < asserts.length (); ++i)
> > - {
> > - value_range_equiv *vr
> > - = try_find_new_range (asserts[i].name,
> > - asserts[i].expr,
> > - asserts[i].comp_code,
> > - asserts[i].val);
> > - if (vr)
> > - vrs.safe_push (std::make_pair (asserts[i].name, vr));
> > - }
> > -
> > - /* If pred_e is really a fallthru we can record value ranges
> > - in SSA names as well. */
> > - bool is_fallthru = assert_unreachable_fallthru_edge_p (pred_e);
> > -
> > - /* Push updated ranges only after finding all of them to avoid
> > - ordering issues that can lead to worse ranges. */
> > - for (unsigned i = 0; i < vrs.length (); ++i)
> > - {
> > - /* But make sure we do not weaken ranges like when
> > - getting first [64, +INF] and then ~[0, 0] from
> > - conditions like (s & 0x3cc0) == 0). */
> > - const value_range_equiv *old_vr
> > - = get_value_range (vrs[i].first);
> > - value_range tem (*old_vr);
> > - tem.legacy_verbose_intersect (vrs[i].second);
> > - if (tem.equal_p (*old_vr))
> > - {
> > - free_value_range (vrs[i].second);
> > - continue;
> > - }
> > - push_value_range (vrs[i].first, vrs[i].second);
> > - if (is_fallthru
> > - && m_update_global_ranges
> > - && all_uses_feed_or_dominated_by_stmt (vrs[i].first, stmt)
> > - /* The condition must post-dominate the definition point. */
> > - && (SSA_NAME_IS_DEFAULT_DEF (vrs[i].first)
> > - || (gimple_bb (SSA_NAME_DEF_STMT (vrs[i].first))
> > - == pred_e->src)))
> > - {
> > - set_ssa_range_info (vrs[i].first, vrs[i].second);
> > - maybe_set_nonzero_bits (pred_e, vrs[i].first);
> > - }
> > - }
> > - }
> > - }
> > -}
> > -
> > -void
> > -evrp_range_analyzer::record_ranges_from_phis (basic_block bb)
> > -{
> > - /* Visit PHI stmts and discover any new VRs possible. */
> > - bool has_unvisited_preds = false;
> > - edge_iterator ei;
> > - edge e;
> > - FOR_EACH_EDGE (e, ei, bb->preds)
> > - if (e->flags & EDGE_EXECUTABLE
> > - && !(e->src->flags & BB_VISITED))
> > - {
> > - has_unvisited_preds = true;
> > - break;
> > - }
> > -
> > - for (gphi_iterator gpi = gsi_start_phis (bb);
> > - !gsi_end_p (gpi); gsi_next (&gpi))
> > - {
> > - gphi *phi = gpi.phi ();
> > - tree lhs = PHI_RESULT (phi);
> > - if (virtual_operand_p (lhs))
> > - continue;
> > -
> > - /* Skips floats and other things we can't represent in a
> > - range. */
> > - if (!value_range_equiv::supports_p (TREE_TYPE (lhs)))
> > - continue;
> > -
> > - value_range_equiv vr_result;
> > - bool interesting = stmt_interesting_for_vrp (phi);
> > - if (!has_unvisited_preds && interesting)
> > - extract_range_from_phi_node (phi, &vr_result);
> > - else
> > - {
> > - vr_result.set_varying (TREE_TYPE (lhs));
> > - /* When we have an unvisited executable predecessor we can't
> > - use PHI arg ranges which may be still UNDEFINED but have
> > - to use VARYING for them. But we can still resort to
> > - SCEV for loop header PHIs. */
> > - class loop *l;
> > - if (scev_initialized_p ()
> > - && interesting
> > - && (l = loop_containing_stmt (phi))
> > - && l->header == gimple_bb (phi))
> > - adjust_range_with_scev (&vr_result, l, phi, lhs);
> > - }
> > - update_value_range (lhs, &vr_result);
> > -
> > - /* Set the SSA with the value range. */
> > - if (m_update_global_ranges)
> > - set_ssa_range_info (lhs, &vr_result);
> > - }
> > -}
> > -
> > -/* Record ranges from STMT into our VR_VALUES class. If TEMPORARY is
> > - true, then this is a temporary equivalence and should be recorded
> > - into the unwind table. Othewise record the equivalence into the
> > - global table. */
> > -
> > -void
> > -evrp_range_analyzer::record_ranges_from_stmt (gimple *stmt, bool temporary)
> > -{
> > - tree output = NULL_TREE;
> > -
> > - if (!optimize)
> > - return;
> > -
> > - if (dyn_cast <gcond *> (stmt))
> > - ;
> > - else if (stmt_interesting_for_vrp (stmt))
> > - {
> > - edge taken_edge;
> > - value_range_equiv vr;
> > - extract_range_from_stmt (stmt, &taken_edge, &output, &vr);
> > - if (output)
> > - {
> > - /* Set the SSA with the value range. There are two cases to
> > - consider. First (the the most common) is we are processing
> > - STMT in a context where its resulting range globally holds
> > - and thus it can be reflected into the global ranges and need
> > - not be unwound as we leave scope.
> > -
> > - The second case occurs if we are processing a statement in
> > - a context where the resulting range must not be reflected
> > - into the global tables and must be unwound as we leave
> > - the current context. This happens in jump threading for
> > - example. */
> > - if (!temporary)
> > - {
> > - /* Case one. We can just update the underlying range
> > - information as well as the global information. */
> > - update_value_range (output, &vr);
> > - if (m_update_global_ranges)
> > - set_ssa_range_info (output, &vr);
> > - }
> > - else
> > - {
> > - /* We're going to need to unwind this range. We cannot
> > - use VR as that's a stack object. We have to allocate
> > - a new range and push the old range onto the stack. We
> > - also have to be very careful about sharing the underlying
> > - bitmaps. Ugh. */
> > - value_range_equiv *new_vr = allocate_value_range_equiv ();
> > - new_vr->set (vr.min (), vr.max (), NULL, vr.kind ());
> > - vr.equiv_clear ();
> > - push_value_range (output, new_vr);
> > - }
> > - }
> > - else
> > - set_defs_to_varying (stmt);
> > - }
> > - else
> > - set_defs_to_varying (stmt);
> > -
> > - /* See if we can derive a range for any of STMT's operands. */
> > - tree op;
> > - ssa_op_iter i;
> > - FOR_EACH_SSA_TREE_OPERAND (op, stmt, i, SSA_OP_USE)
> > - {
> > - tree value;
> > - enum tree_code comp_code;
> > -
> > - /* If OP is used in such a way that we can infer a value
> > - range for it, and we don't find a previous assertion for
> > - it, create a new assertion location node for OP. */
> > - if (infer_value_range (stmt, op, &comp_code, &value))
> > - {
> > - /* If we are able to infer a nonzero value range for OP,
> > - then walk backwards through the use-def chain to see if OP
> > - was set via a typecast.
> > - If so, then we can also infer a nonzero value range
> > - for the operand of the NOP_EXPR. */
> > - if (comp_code == NE_EXPR && integer_zerop (value))
> > - {
> > - tree t = op;
> > - gimple *def_stmt = SSA_NAME_DEF_STMT (t);
> > - while (is_gimple_assign (def_stmt)
> > - && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def_stmt))
> > - && TREE_CODE
> > - (gimple_assign_rhs1 (def_stmt)) == SSA_NAME
> > - && POINTER_TYPE_P
> > - (TREE_TYPE (gimple_assign_rhs1 (def_stmt))))
> > - {
> > - t = gimple_assign_rhs1 (def_stmt);
> > - def_stmt = SSA_NAME_DEF_STMT (t);
> > -
> > - /* Add VR when (T COMP_CODE value) condition is
> > - true. */
> > - value_range_equiv *op_range
> > - = try_find_new_range (t, t, comp_code, value);
> > - if (op_range)
> > - push_value_range (t, op_range);
> > - }
> > - }
> > - /* Add VR when (OP COMP_CODE value) condition is true. */
> > - value_range_equiv *op_range = try_find_new_range (op, op,
> > - comp_code, value);
> > - if (op_range)
> > - push_value_range (op, op_range);
> > - }
> > - }
> > -}
> > -
> > -/* Unwind recorded ranges to their most recent state. */
> > -
> > -void
> > -evrp_range_analyzer::pop_to_marker (void)
> > -{
> > - gcc_checking_assert (!stack.is_empty ());
> > - while (stack.last ().first != NULL_TREE)
> > - pop_value_range ();
> > - stack.pop ();
> > -}
> > -
> > -/* Restore/pop VRs valid only for BB when we leave BB. */
> > -
> > -void
> > -evrp_range_analyzer::leave (basic_block bb ATTRIBUTE_UNUSED)
> > -{
> > - if (!optimize)
> > - return;
> > - pop_to_marker ();
> > -}
> > -
> > -
> > -/* Push the Value Range of VAR to the stack and update it with new VR. */
> > -
> > -void
> > -evrp_range_analyzer::push_value_range (tree var, value_range_equiv *vr)
> > -{
> > - if (dump_file && (dump_flags & TDF_DETAILS))
> > - {
> > - fprintf (dump_file, "pushing new range for ");
> > - print_generic_expr (dump_file, var);
> > - fprintf (dump_file, ": ");
> > - dump_value_range (dump_file, vr);
> > - fprintf (dump_file, "\n");
> > - }
> > - value_range_equiv *old_vr = swap_vr_value (var, vr);
> > - stack.safe_push (std::make_pair (var, old_vr));
> > -}
> > -
> > -/* Pop a Value Range from the vrp_stack. */
> > -
> > -void
> > -evrp_range_analyzer::pop_value_range ()
> > -{
> > - std::pair<tree, value_range_equiv *> e = stack.pop ();
> > - tree var = e.first;
> > - value_range_equiv *vr = e.second;
> > - if (dump_file && (dump_flags & TDF_DETAILS))
> > - {
> > - fprintf (dump_file, "popping range for ");
> > - print_generic_expr (dump_file, var);
> > - fprintf (dump_file, ", restoring ");
> > - dump_value_range (dump_file, vr);
> > - fprintf (dump_file, "\n");
> > - }
> > - /* We saved off a lattice entry, now give it back and release
> > - the one we popped. */
> > - value_range_equiv *popped_vr = swap_vr_value (var, vr);
> > - if (popped_vr)
> > - free_value_range (popped_vr);
> > -}
> > diff --git a/gcc/gimple-ssa-evrp-analyze.h b/gcc/gimple-ssa-evrp-analyze.h
> > deleted file mode 100644
> > index 51c32099dc5..00000000000
> > --- a/gcc/gimple-ssa-evrp-analyze.h
> > +++ /dev/null
> > @@ -1,58 +0,0 @@
> > -/* Support routines for Value Range Propagation (VRP).
> > - Copyright (C) 2016-2022 Free Software Foundation, Inc.
> > -
> > -This file is part of GCC.
> > -
> > -GCC is free software; you can redistribute it and/or modify
> > -it under the terms of the GNU General Public License as published by
> > -the Free Software Foundation; either version 3, or (at your option)
> > -any later version.
> > -
> > -GCC is distributed in the hope that it will be useful,
> > -but WITHOUT ANY WARRANTY; without even the implied warranty of
> > -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> > -GNU General Public License for more details.
> > -
> > -You should have received a copy of the GNU General Public License
> > -along with GCC; see the file COPYING3. If not see
> > -<http://www.gnu.org/licenses/>. */
> > -
> > -#ifndef GCC_GIMPLE_SSA_EVRP_ANALYZE_H
> > -#define GCC_GIMPLE_SSA_EVRP_ANALYZE_H
> > -
> > -class evrp_range_analyzer : public vr_values
> > -{
> > - public:
> > - evrp_range_analyzer (bool update_global_ranges);
> > - ~evrp_range_analyzer (void)
> > - {
> > - stack.release ();
> > - }
> > -
> > - void enter (basic_block);
> > - void push_marker (void);
> > - void pop_to_marker (void);
> > - void leave (basic_block);
> > - void record_ranges_from_stmt (gimple *, bool);
> > -
> > - /* Record a new unwindable range. */
> > - void push_value_range (tree var, value_range_equiv *vr);
> > -
> > - private:
> > - DISABLE_COPY_AND_ASSIGN (evrp_range_analyzer);
> > -
> > - void pop_value_range ();
> > - value_range_equiv *try_find_new_range (tree, tree op, tree_code code,
> > - tree limit);
> > - void record_ranges_from_incoming_edge (basic_block);
> > - void record_ranges_from_phis (basic_block);
> > - void set_ssa_range_info (tree, value_range_equiv *);
> > -
> > - /* STACK holds the old VR. */
> > - auto_vec<std::pair <tree, value_range_equiv *> > stack;
> > -
> > - /* True if we are updating global ranges, false otherwise. */
> > - bool m_update_global_ranges;
> > -};
> > -
> > -#endif /* GCC_GIMPLE_SSA_EVRP_ANALYZE_H */
> > diff --git a/gcc/gimple-ssa-evrp.cc b/gcc/gimple-ssa-evrp.cc
> > deleted file mode 100644
> > index 20388ed5431..00000000000
> > --- a/gcc/gimple-ssa-evrp.cc
> > +++ /dev/null
> > @@ -1,395 +0,0 @@
> > -/* Support routines for Value Range Propagation (VRP).
> > - Copyright (C) 2005-2022 Free Software Foundation, Inc.
> > -
> > -This file is part of GCC.
> > -
> > -GCC is free software; you can redistribute it and/or modify
> > -it under the terms of the GNU General Public License as published by
> > -the Free Software Foundation; either version 3, or (at your option)
> > -any later version.
> > -
> > -GCC is distributed in the hope that it will be useful,
> > -but WITHOUT ANY WARRANTY; without even the implied warranty of
> > -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> > -GNU General Public License for more details.
> > -
> > -You should have received a copy of the GNU General Public License
> > -along with GCC; see the file COPYING3. If not see
> > -<http://www.gnu.org/licenses/>. */
> > -
> > -#include "config.h"
> > -#include "system.h"
> > -#include "coretypes.h"
> > -#include "backend.h"
> > -#include "tree.h"
> > -#include "gimple.h"
> > -#include "tree-pass.h"
> > -#include "ssa.h"
> > -#include "gimple-pretty-print.h"
> > -#include "cfganal.h"
> > -#include "gimple-iterator.h"
> > -#include "gimple-fold.h"
> > -#include "tree-eh.h"
> > -#include "tree-cfg.h"
> > -#include "tree-ssa-loop-manip.h"
> > -#include "tree-ssa-loop.h"
> > -#include "cfgloop.h"
> > -#include "tree-scalar-evolution.h"
> > -#include "tree-ssa-propagate.h"
> > -#include "alloc-pool.h"
> > -#include "domwalk.h"
> > -#include "tree-cfgcleanup.h"
> > -#include "vr-values.h"
> > -#include "gimple-ssa-evrp-analyze.h"
> > -#include "gimple-range.h"
> > -#include "fold-const.h"
> > -#include "value-pointer-equiv.h"
> > -#include "tree-vrp.h"
> > -
> > -// This is the classic EVRP folder which uses a dominator walk and pushes
> > -// ranges into the next block if it is a single predecessor block.
> > -
> > -class evrp_folder : public substitute_and_fold_engine
> > -{
> > -public:
> > - evrp_folder () :
> > - substitute_and_fold_engine (),
> > - m_range_analyzer (/*update_global_ranges=*/true),
> > - simplifier (&m_range_analyzer)
> > - { }
> > -
> > - ~evrp_folder ()
> > - {
> > - if (dump_file)
> > - {
> > - fprintf (dump_file, "\nValue ranges after Early VRP:\n\n");
> > - m_range_analyzer.dump (dump_file);
> > - fprintf (dump_file, "\n");
> > - }
> > - }
> > -
> > - tree value_of_expr (tree name, gimple *stmt) override
> > - {
> > - return m_range_analyzer.value_of_expr (name, stmt);
> > - }
> > -
> > - void pre_fold_bb (basic_block bb) override
> > - {
> > - if (dump_file && (dump_flags & TDF_DETAILS))
> > - fprintf (dump_file, "evrp visiting BB%d\n", bb->index);
> > - m_range_analyzer.enter (bb);
> > - }
> > -
> > - void pre_fold_stmt (gimple *stmt) override
> > - {
> > - if (dump_file && (dump_flags & TDF_DETAILS))
> > - {
> > - fprintf (dump_file, "evrp visiting stmt ");
> > - print_gimple_stmt (dump_file, stmt, 0);
> > - }
> > - m_range_analyzer.record_ranges_from_stmt (stmt, false);
> > - }
> > -
> > - bool fold_stmt (gimple_stmt_iterator *gsi) override
> > - {
> > - return simplifier.simplify (gsi);
> > - }
> > -
> > - void post_fold_bb (basic_block bb) override
> > - {
> > - m_range_analyzer.leave (bb);
> > - }
> > -
> > - void post_new_stmt (gimple *stmt) override
> > - {
> > - m_range_analyzer.set_defs_to_varying (stmt);
> > - }
> > -
> > -protected:
> > - DISABLE_COPY_AND_ASSIGN (evrp_folder);
> > - evrp_range_analyzer m_range_analyzer;
> > - simplify_using_ranges simplifier;
> > -};
> > -
> > -// In a hybrid folder, start with an EVRP folder, and add the required
> > -// fold_stmt bits to either try the ranger first or second.
> > -//
> > -// The 3 value_* routines will always query both EVRP and the ranger for
> > -// a result, and ensure they return the same value. If either returns a value
> > -// when the other doesn't, it is flagged in the listing, and the discoverd
> > -// value is returned.
> > -//
> > -// The simplifier is unable to process 2 different sources, thus we try to
> > -// use one engine, and if it fails to simplify, try using the other engine.
> > -// It is reported when the first attempt fails and the second succeeds.
> > -
> > -class hybrid_folder : public evrp_folder
> > -{
> > -public:
> > - hybrid_folder (bool evrp_first)
> > - {
> > - m_ranger = enable_ranger (cfun);
> > -
> > - if (evrp_first)
> > - {
> > - first = &m_range_analyzer;
> > - first_exec_flag = 0;
> > - second = m_ranger;
> > - second_exec_flag = m_ranger->non_executable_edge_flag;
> > - }
> > - else
> > - {
> > - first = m_ranger;
> > - first_exec_flag = m_ranger->non_executable_edge_flag;
> > - second = &m_range_analyzer;
> > - second_exec_flag = 0;
> > - }
> > - m_pta = new pointer_equiv_analyzer (m_ranger);
> > - }
> > -
> > - ~hybrid_folder ()
> > - {
> > - if (dump_file && (dump_flags & TDF_DETAILS))
> > - m_ranger->dump (dump_file);
> > -
> > - m_ranger->export_global_ranges ();
> > - disable_ranger (cfun);
> > - delete m_pta;
> > - }
> > -
> > - bool fold_stmt (gimple_stmt_iterator *gsi) override
> > - {
> > - simplifier.set_range_query (first, first_exec_flag);
> > - if (simplifier.simplify (gsi))
> > - return true;
> > -
> > - simplifier.set_range_query (second, second_exec_flag);
> > - if (simplifier.simplify (gsi))
> > - {
> > - if (dump_file)
> > - fprintf (dump_file, "EVRP:hybrid: Second query simplifed stmt\n");
> > - return true;
> > - }
> > - return false;
> > - }
> > -
> > - void pre_fold_stmt (gimple *stmt) override
> > - {
> > - evrp_folder::pre_fold_stmt (stmt);
> > - m_pta->visit_stmt (stmt);
> > - }
> > -
> > - void pre_fold_bb (basic_block bb) override
> > - {
> > - evrp_folder::pre_fold_bb (bb);
> > - m_pta->enter (bb);
> > - }
> > -
> > - void post_fold_bb (basic_block bb) override
> > - {
> > - evrp_folder::post_fold_bb (bb);
> > - m_pta->leave (bb);
> > - }
> > -
> > - tree value_of_expr (tree name, gimple *) override;
> > - tree value_on_edge (edge, tree name) override;
> > - tree value_of_stmt (gimple *, tree name) override;
> > -
> > -private:
> > - DISABLE_COPY_AND_ASSIGN (hybrid_folder);
> > - gimple_ranger *m_ranger;
> > - range_query *first;
> > - int first_exec_flag;
> > - range_query *second;
> > - int second_exec_flag;
> > - pointer_equiv_analyzer *m_pta;
> > - tree choose_value (tree evrp_val, tree ranger_val);
> > -};
> > -
> > -
> > -tree
> > -hybrid_folder::value_of_expr (tree op, gimple *stmt)
> > -{
> > - tree evrp_ret = evrp_folder::value_of_expr (op, stmt);
> > - tree ranger_ret;
> > - if (TREE_CODE (op) == SSA_NAME && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op))
> > - ranger_ret = NULL;
> > - else
> > - {
> > - ranger_ret = m_ranger->value_of_expr (op, stmt);
> > - if (!ranger_ret && supported_pointer_equiv_p (op))
> > - ranger_ret = m_pta->get_equiv (op);
> > - }
> > - return choose_value (evrp_ret, ranger_ret);
> > -}
> > -
> > -tree
> > -hybrid_folder::value_on_edge (edge e, tree op)
> > -{
> > - // Call evrp::value_of_expr directly. Otherwise another dual call is made
> > - // via hybrid_folder::value_of_expr, but without an edge.
> > - tree evrp_ret = evrp_folder::value_of_expr (op, NULL);
> > - tree ranger_ret;
> > - if (TREE_CODE (op) == SSA_NAME && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op))
> > - ranger_ret = NULL;
> > - else
> > - {
> > - ranger_ret = m_ranger->value_on_edge (e, op);
> > - if (!ranger_ret && supported_pointer_equiv_p (op))
> > - ranger_ret = m_pta->get_equiv (op);
> > - }
> > - return choose_value (evrp_ret, ranger_ret);
> > -}
> > -
> > -tree
> > -hybrid_folder::value_of_stmt (gimple *stmt, tree op)
> > -{
> > - // Call evrp::value_of_expr directly. Otherwise another dual call is made
> > - // via hybrid_folder::value_of_expr, but without a stmt.
> > - tree evrp_ret;
> > - if (op)
> > - evrp_ret = evrp_folder::value_of_expr (op, NULL);
> > - else
> > - evrp_ret = NULL_TREE;
> > -
> > - tree ranger_ret;
> > - if (op && TREE_CODE (op) == SSA_NAME && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op))
> > - ranger_ret = NULL;
> > - else
> > - ranger_ret = m_ranger->value_of_stmt (stmt, op);
> > - return choose_value (evrp_ret, ranger_ret);
> > -}
> > -
> > -// Given trees returned by EVRP and Ranger, choose/report the value to use
> > -// by the folder.
> > -
> > -tree
> > -hybrid_folder::choose_value (tree evrp_val, tree ranger_val)
> > -{
> > - // If both found the same value, just return it.
> > - if (evrp_val && ranger_val && !compare_values (evrp_val, ranger_val))
> > - return evrp_val;
> > -
> > - // If neither returned a value, return NULL_TREE.
> > - if (!ranger_val && !evrp_val)
> > - return NULL_TREE;
> > -
> > - // Otherwise there is a discrepancy to flag.
> > - if (dump_file)
> > - {
> > - if (evrp_val && ranger_val)
> > - fprintf (dump_file, "EVRP:hybrid: Disagreement\n");
> > - if (evrp_val)
> > - {
> > - fprintf (dump_file, "EVRP:hybrid: EVRP found singleton ");
> > - print_generic_expr (dump_file, evrp_val);
> > - fprintf (dump_file, "\n");
> > - }
> > - if (ranger_val)
> > - {
> > - fprintf (dump_file, "EVRP:hybrid: RVRP found singleton ");
> > - print_generic_expr (dump_file, ranger_val);
> > - fprintf (dump_file, "\n");
> > - }
> > - }
> > -
> > - // If one value was found, return it.
> > - if (!evrp_val)
> > - return ranger_val;
> > - if (!ranger_val)
> > - return evrp_val;
> > -
> > - // If values are different, return the first calculated value.
> > - if (param_evrp_mode == EVRP_MODE_RVRP_FIRST)
> > - return ranger_val;
> > - return evrp_val;
> > -}
> > -
> > -/* Main entry point for the early vrp pass which is a simplified non-iterative
> > - version of vrp where basic blocks are visited in dominance order. Value
> > - ranges discovered in early vrp will also be used by ipa-vrp. */
> > -
> > -static unsigned int
> > -execute_early_vrp ()
> > -{
> > - if (param_evrp_mode == EVRP_MODE_RVRP_ONLY)
> > - return execute_ranger_vrp (cfun, false);
> > -
> > - /* Ideally this setup code would move into the ctor for the folder
> > - However, this setup can change the number of blocks which
> > - invalidates the internal arrays that are set up by the dominator
> > - walker in substitute_and_fold_engine. */
> > - loop_optimizer_init (LOOPS_NORMAL | LOOPS_HAVE_RECORDED_EXITS);
> > - rewrite_into_loop_closed_ssa (NULL, TODO_update_ssa);
> > - scev_initialize ();
> > - calculate_dominance_info (CDI_DOMINATORS);
> > -
> > - // Only the last 2 bits matter for choosing the folder.
> > - switch (param_evrp_mode)
> > - {
> > - case EVRP_MODE_EVRP_ONLY:
> > - {
> > - evrp_folder folder;
> > - folder.substitute_and_fold ();
> > - break;
> > - }
> > - case EVRP_MODE_EVRP_FIRST:
> > - {
> > - hybrid_folder folder (true);
> > - folder.substitute_and_fold ();
> > - break;
> > - }
> > - case EVRP_MODE_RVRP_FIRST:
> > - {
> > - hybrid_folder folder (false);
> > - folder.substitute_and_fold ();
> > - break;
> > - }
> > - default:
> > - gcc_unreachable ();
> > - }
> > -
> > - scev_finalize ();
> > - loop_optimizer_finalize ();
> > - return 0;
> > -}
> > -
> > -namespace {
> > -
> > -const pass_data pass_data_early_vrp =
> > -{
> > - GIMPLE_PASS, /* type */
> > - "evrp", /* name */
> > - OPTGROUP_NONE, /* optinfo_flags */
> > - TV_TREE_EARLY_VRP, /* tv_id */
> > - PROP_ssa, /* properties_required */
> > - 0, /* properties_provided */
> > - 0, /* properties_destroyed */
> > - 0, /* todo_flags_start */
> > - ( TODO_cleanup_cfg | TODO_update_ssa | TODO_verify_all ),
> > -};
> > -
> > -class pass_early_vrp : public gimple_opt_pass
> > -{
> > -public:
> > - pass_early_vrp (gcc::context *ctxt)
> > - : gimple_opt_pass (pass_data_early_vrp, ctxt)
> > - {}
> > -
> > - /* opt_pass methods: */
> > - opt_pass * clone () { return new pass_early_vrp (m_ctxt); }
> > - virtual bool gate (function *)
> > - {
> > - return flag_tree_vrp != 0;
> > - }
> > - virtual unsigned int execute (function *)
> > - { return execute_early_vrp (); }
> > -
> > -}; // class pass_vrp
> > -} // anon namespace
> > -
> > -gimple_opt_pass *
> > -make_pass_early_vrp (gcc::context *ctxt)
> > -{
> > - return new pass_early_vrp (ctxt);
> > -}
> > diff --git a/gcc/params.opt b/gcc/params.opt
> > index bcf1423671a..2f9c9cf27dd 100644
> > --- a/gcc/params.opt
> > +++ b/gcc/params.opt
> > @@ -134,25 +134,6 @@ Maximum number of basic blocks before EVRP uses a sparse cache.
> > Common Joined UInteger Var(param_evrp_switch_limit) Init(50) Optimization Param
> > Maximum number of outgoing edges in a switch before EVRP will not process it.
> >
> > --param=evrp-mode=
> > -Common Joined Var(param_evrp_mode) Enum(evrp_mode) Init(EVRP_MODE_RVRP_ONLY) Param Optimization
> > ---param=evrp-mode=[legacy|ranger|legacy-first|ranger-first] Specifies the mode Early VRP should operate in.
> > -
> > -Enum
> > -Name(evrp_mode) Type(enum evrp_mode) UnknownError(unknown evrp mode %qs)
> > -
> > -EnumValue
> > -Enum(evrp_mode) String(legacy) Value(EVRP_MODE_EVRP_ONLY)
> > -
> > -EnumValue
> > -Enum(evrp_mode) String(ranger) Value(EVRP_MODE_RVRP_ONLY)
> > -
> > -EnumValue
> > -Enum(evrp_mode) String(legacy-first) Value(EVRP_MODE_EVRP_FIRST)
> > -
> > -EnumValue
> > -Enum(evrp_mode) String(ranger-first) Value(EVRP_MODE_RVRP_FIRST)
> > -
> > -param=fsm-scale-path-blocks=
> > Common Joined UInteger Var(param_fsm_scale_path_blocks) Init(3) IntegerRange(1, 10) Param Optimization
> > Scale factor to apply to the number of blocks in a threading path when comparing to the number of (scaled) statements.
> > diff --git a/gcc/testsuite/g++.dg/pr100774.C b/gcc/testsuite/g++.dg/pr100774.C
> > index 345fcfa0d01..63320ef73fc 100644
> > --- a/gcc/testsuite/g++.dg/pr100774.C
> > +++ b/gcc/testsuite/g++.dg/pr100774.C
> > @@ -1,5 +1,5 @@
> > /* { dg-do compile } */
> > -/* { dg-options "-O2 -fno-tree-forwprop --param=evrp-mode=ranger -fcompare-debug " } */
> > +/* { dg-options "-O2 -fno-tree-forwprop -fcompare-debug " } */
> >
> > extern void __attribute__((noreturn)) error();
> >
> > diff --git a/gcc/testsuite/gcc.dg/pr100781.c b/gcc/testsuite/gcc.dg/pr100781.c
> > index c0e008a3ba5..96f0a7a6012 100644
> > --- a/gcc/testsuite/gcc.dg/pr100781.c
> > +++ b/gcc/testsuite/gcc.dg/pr100781.c
> > @@ -1,5 +1,5 @@
> > /* { dg-do compile } */
> > -/* { dg-options "-O2 --param=evrp-mode=ranger -fcompare-debug " } */
> > +/* { dg-options "-O2 -fcompare-debug " } */
> >
> > struct a {
> > int b;
> > diff --git a/gcc/tree-vrp.cc b/gcc/tree-vrp.cc
> > index 30022dac108..7b4e2917340 100644
> > --- a/gcc/tree-vrp.cc
> > +++ b/gcc/tree-vrp.cc
> > @@ -4388,17 +4388,30 @@ const pass_data pass_data_vrp =
> > ( TODO_cleanup_cfg | TODO_update_ssa ), /* todo_flags_finish */
> > };
> >
> > +const pass_data pass_data_early_vrp =
> > +{
> > + GIMPLE_PASS, /* type */
> > + "evrp", /* name */
> > + OPTGROUP_NONE, /* optinfo_flags */
> > + TV_TREE_EARLY_VRP, /* tv_id */
> > + PROP_ssa, /* properties_required */
> > + 0, /* properties_provided */
> > + 0, /* properties_destroyed */
> > + 0, /* todo_flags_start */
> > + ( TODO_cleanup_cfg | TODO_update_ssa | TODO_verify_all ),
> > +};
> > +
> > static int vrp_pass_num = 0;
> > class pass_vrp : public gimple_opt_pass
> > {
> > public:
> > - pass_vrp (gcc::context *ctxt)
> > - : gimple_opt_pass (pass_data_vrp, ctxt), warn_array_bounds_p (false),
> > - my_pass (++vrp_pass_num)
> > + pass_vrp (gcc::context *ctxt, const pass_data &data_)
> > + : gimple_opt_pass (data_, ctxt), data (data_), warn_array_bounds_p (false),
> > + my_pass (vrp_pass_num++)
> > {}
> >
> > /* opt_pass methods: */
> > - opt_pass * clone () { return new pass_vrp (m_ctxt); }
> > + opt_pass * clone () { return new pass_vrp (m_ctxt, data); }
> > void set_pass_param (unsigned int n, bool param)
> > {
> > gcc_assert (n == 0);
> > @@ -4407,6 +4420,10 @@ public:
> > virtual bool gate (function *) { return flag_tree_vrp != 0; }
> > virtual unsigned int execute (function *fun)
> > {
> > + // Early VRP pass.
> > + if (my_pass == 0)
> > + return execute_ranger_vrp (fun, /*warn_array_bounds_p=*/false);
> > +
> > if ((my_pass == 1 && param_vrp1_mode == VRP_MODE_RANGER)
> > || (my_pass == 2 && param_vrp2_mode == VRP_MODE_RANGER))
> > return execute_ranger_vrp (fun, warn_array_bounds_p);
> > @@ -4414,6 +4431,7 @@ public:
> > }
> >
> > private:
> > + const pass_data &data;
> > bool warn_array_bounds_p;
> > int my_pass;
> > }; // class pass_vrp
> > @@ -4423,5 +4441,11 @@ public:
> > gimple_opt_pass *
> > make_pass_vrp (gcc::context *ctxt)
> > {
> > - return new pass_vrp (ctxt);
> > + return new pass_vrp (ctxt, pass_data_vrp);
> > +}
> > +
> > +gimple_opt_pass *
> > +make_pass_early_vrp (gcc::context *ctxt)
> > +{
> > + return new pass_vrp (ctxt, pass_data_early_vrp);
> > }
> > --
> > 2.36.1
> >
>
On 6/28/2022 1:37 AM, Richard Biener via Gcc-patches wrote:
> On Mon, Jun 27, 2022 at 9:04 PM Aldy Hernandez <aldyh@redhat.com> wrote:
>> With DOM converted to ranger, there are no longer any uses of the EVRP
>> engine. For that matter, we haven't used the legacy mode in quite a
>> while, so I think it's safe to remove any associated code.
>>
>> There are some methods in vr_values which should now be private, but I
>> didn't bother changing them, as most of the vr_values class will be
>> removed when VRP1 is converted to ranger.
>>
>> Does anyone have any issues with me pushing this?
> Fine with me.
Likewise.
jeff
@@ -1413,8 +1413,6 @@ OBJS = \
gimple-range-infer.o \
gimple-range-trace.o \
gimple-ssa-backprop.o \
- gimple-ssa-evrp.o \
- gimple-ssa-evrp-analyze.o \
gimple-ssa-isolate-paths.o \
gimple-ssa-nonnull-compare.o \
gimple-ssa-split-paths.o \
@@ -479,15 +479,6 @@ enum threader_debug
THREADER_DEBUG_ALL = 1
};
-/* EVRP mode. */
-enum evrp_mode
-{
- EVRP_MODE_RVRP_ONLY,
- EVRP_MODE_EVRP_ONLY,
- EVRP_MODE_EVRP_FIRST,
- EVRP_MODE_RVRP_FIRST
-};
-
/* VRP modes. */
enum vrp_mode
{
deleted file mode 100644
@@ -1,456 +0,0 @@
-/* Support routines for Value Range Propagation (VRP).
- Copyright (C) 2005-2022 Free Software Foundation, Inc.
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
-
-GCC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "backend.h"
-#include "tree.h"
-#include "gimple.h"
-#include "tree-pass.h"
-#include "ssa.h"
-#include "gimple-pretty-print.h"
-#include "cfganal.h"
-#include "gimple-iterator.h"
-#include "gimple-fold.h"
-#include "tree-eh.h"
-#include "tree-cfg.h"
-#include "tree-ssa-loop-manip.h"
-#include "tree-ssa-loop.h"
-#include "cfgloop.h"
-#include "tree-scalar-evolution.h"
-#include "tree-ssa-propagate.h"
-#include "alloc-pool.h"
-#include "domwalk.h"
-#include "tree-cfgcleanup.h"
-#include "vr-values.h"
-#include "gimple-ssa-evrp-analyze.h"
-
-evrp_range_analyzer::evrp_range_analyzer (bool update_global_ranges)
- : stack (10), m_update_global_ranges (update_global_ranges)
-{
- edge e;
- edge_iterator ei;
- basic_block bb;
- FOR_EACH_BB_FN (bb, cfun)
- {
- bb->flags &= ~BB_VISITED;
- FOR_EACH_EDGE (e, ei, bb->preds)
- e->flags |= EDGE_EXECUTABLE;
- }
-}
-
-/* Push an unwinding marker onto the unwinding stack. */
-
-void
-evrp_range_analyzer::push_marker ()
-{
- stack.safe_push (std::make_pair (NULL_TREE, (value_range_equiv *)NULL));
-}
-
-/* Analyze ranges as we enter basic block BB. */
-
-void
-evrp_range_analyzer::enter (basic_block bb)
-{
- if (!optimize)
- return;
- push_marker ();
- record_ranges_from_incoming_edge (bb);
- record_ranges_from_phis (bb);
- bb->flags |= BB_VISITED;
-}
-
-/* Find new range for NAME such that (OP CODE LIMIT) is true. */
-value_range_equiv *
-evrp_range_analyzer::try_find_new_range (tree name,
- tree op, tree_code code, tree limit)
-{
- value_range_equiv vr;
- const value_range_equiv *old_vr = get_value_range (name);
-
- /* Discover VR when condition is true. */
- extract_range_for_var_from_comparison_expr (name, code, op, limit, &vr);
- /* If we found any usable VR, set the VR to ssa_name and create a
- PUSH old value in the stack with the old VR. */
- if (!vr.undefined_p () && !vr.varying_p ())
- {
- if (old_vr->equal_p (vr, /*ignore_equivs=*/true))
- return NULL;
- value_range_equiv *new_vr = allocate_value_range_equiv ();
- new_vr->move (&vr);
- return new_vr;
- }
- return NULL;
-}
-
-/* For LHS record VR in the SSA info. */
-void
-evrp_range_analyzer::set_ssa_range_info (tree lhs, value_range_equiv *vr)
-{
- gcc_assert (m_update_global_ranges);
-
- /* Set the SSA with the value range. */
- if (INTEGRAL_TYPE_P (TREE_TYPE (lhs)))
- {
- if (!vr->varying_p () && vr->constant_p ())
- set_range_info (lhs, *vr);
- }
- else if (POINTER_TYPE_P (TREE_TYPE (lhs))
- && range_includes_zero_p (vr) == 0)
- set_ptr_nonnull (lhs);
-}
-
-/* Return true if all uses of NAME are dominated by STMT or feed STMT
- via a chain of single immediate uses. */
-
-static bool
-all_uses_feed_or_dominated_by_stmt (tree name, gimple *stmt)
-{
- use_operand_p use_p, use2_p;
- imm_use_iterator iter;
- basic_block stmt_bb = gimple_bb (stmt);
-
- FOR_EACH_IMM_USE_FAST (use_p, iter, name)
- {
- gimple *use_stmt = USE_STMT (use_p), *use_stmt2;
- if (use_stmt == stmt
- || is_gimple_debug (use_stmt)
- || (gimple_bb (use_stmt) != stmt_bb
- && dominated_by_p (CDI_DOMINATORS,
- gimple_bb (use_stmt), stmt_bb)))
- continue;
- while (use_stmt != stmt
- && is_gimple_assign (use_stmt)
- && TREE_CODE (gimple_assign_lhs (use_stmt)) == SSA_NAME
- && single_imm_use (gimple_assign_lhs (use_stmt),
- &use2_p, &use_stmt2))
- use_stmt = use_stmt2;
- if (use_stmt != stmt)
- return false;
- }
- return true;
-}
-
-void
-evrp_range_analyzer::record_ranges_from_incoming_edge (basic_block bb)
-{
- edge pred_e = single_pred_edge_ignoring_loop_edges (bb, false);
- if (pred_e)
- {
- gimple *stmt = last_stmt (pred_e->src);
- tree op0 = NULL_TREE;
-
- if (stmt
- && gimple_code (stmt) == GIMPLE_COND
- && (op0 = gimple_cond_lhs (stmt))
- && TREE_CODE (op0) == SSA_NAME
- && (INTEGRAL_TYPE_P (TREE_TYPE (gimple_cond_lhs (stmt)))
- || POINTER_TYPE_P (TREE_TYPE (gimple_cond_lhs (stmt)))))
- {
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file, "Visiting controlling predicate ");
- print_gimple_stmt (dump_file, stmt, 0);
- }
- /* Entering a new scope. Try to see if we can find a VR
- here. */
- tree op1 = gimple_cond_rhs (stmt);
- if (TREE_OVERFLOW_P (op1))
- op1 = drop_tree_overflow (op1);
- tree_code code = gimple_cond_code (stmt);
-
- auto_vec<assert_info, 8> asserts;
- register_edge_assert_for (op0, pred_e, code, op0, op1, asserts);
- if (TREE_CODE (op1) == SSA_NAME)
- register_edge_assert_for (op1, pred_e, code, op0, op1, asserts);
-
- auto_vec<std::pair<tree, value_range_equiv *>, 8> vrs;
- for (unsigned i = 0; i < asserts.length (); ++i)
- {
- value_range_equiv *vr
- = try_find_new_range (asserts[i].name,
- asserts[i].expr,
- asserts[i].comp_code,
- asserts[i].val);
- if (vr)
- vrs.safe_push (std::make_pair (asserts[i].name, vr));
- }
-
- /* If pred_e is really a fallthru we can record value ranges
- in SSA names as well. */
- bool is_fallthru = assert_unreachable_fallthru_edge_p (pred_e);
-
- /* Push updated ranges only after finding all of them to avoid
- ordering issues that can lead to worse ranges. */
- for (unsigned i = 0; i < vrs.length (); ++i)
- {
- /* But make sure we do not weaken ranges like when
- getting first [64, +INF] and then ~[0, 0] from
- conditions like (s & 0x3cc0) == 0). */
- const value_range_equiv *old_vr
- = get_value_range (vrs[i].first);
- value_range tem (*old_vr);
- tem.legacy_verbose_intersect (vrs[i].second);
- if (tem.equal_p (*old_vr))
- {
- free_value_range (vrs[i].second);
- continue;
- }
- push_value_range (vrs[i].first, vrs[i].second);
- if (is_fallthru
- && m_update_global_ranges
- && all_uses_feed_or_dominated_by_stmt (vrs[i].first, stmt)
- /* The condition must post-dominate the definition point. */
- && (SSA_NAME_IS_DEFAULT_DEF (vrs[i].first)
- || (gimple_bb (SSA_NAME_DEF_STMT (vrs[i].first))
- == pred_e->src)))
- {
- set_ssa_range_info (vrs[i].first, vrs[i].second);
- maybe_set_nonzero_bits (pred_e, vrs[i].first);
- }
- }
- }
- }
-}
-
-void
-evrp_range_analyzer::record_ranges_from_phis (basic_block bb)
-{
- /* Visit PHI stmts and discover any new VRs possible. */
- bool has_unvisited_preds = false;
- edge_iterator ei;
- edge e;
- FOR_EACH_EDGE (e, ei, bb->preds)
- if (e->flags & EDGE_EXECUTABLE
- && !(e->src->flags & BB_VISITED))
- {
- has_unvisited_preds = true;
- break;
- }
-
- for (gphi_iterator gpi = gsi_start_phis (bb);
- !gsi_end_p (gpi); gsi_next (&gpi))
- {
- gphi *phi = gpi.phi ();
- tree lhs = PHI_RESULT (phi);
- if (virtual_operand_p (lhs))
- continue;
-
- /* Skips floats and other things we can't represent in a
- range. */
- if (!value_range_equiv::supports_p (TREE_TYPE (lhs)))
- continue;
-
- value_range_equiv vr_result;
- bool interesting = stmt_interesting_for_vrp (phi);
- if (!has_unvisited_preds && interesting)
- extract_range_from_phi_node (phi, &vr_result);
- else
- {
- vr_result.set_varying (TREE_TYPE (lhs));
- /* When we have an unvisited executable predecessor we can't
- use PHI arg ranges which may be still UNDEFINED but have
- to use VARYING for them. But we can still resort to
- SCEV for loop header PHIs. */
- class loop *l;
- if (scev_initialized_p ()
- && interesting
- && (l = loop_containing_stmt (phi))
- && l->header == gimple_bb (phi))
- adjust_range_with_scev (&vr_result, l, phi, lhs);
- }
- update_value_range (lhs, &vr_result);
-
- /* Set the SSA with the value range. */
- if (m_update_global_ranges)
- set_ssa_range_info (lhs, &vr_result);
- }
-}
-
-/* Record ranges from STMT into our VR_VALUES class. If TEMPORARY is
- true, then this is a temporary equivalence and should be recorded
- into the unwind table. Othewise record the equivalence into the
- global table. */
-
-void
-evrp_range_analyzer::record_ranges_from_stmt (gimple *stmt, bool temporary)
-{
- tree output = NULL_TREE;
-
- if (!optimize)
- return;
-
- if (dyn_cast <gcond *> (stmt))
- ;
- else if (stmt_interesting_for_vrp (stmt))
- {
- edge taken_edge;
- value_range_equiv vr;
- extract_range_from_stmt (stmt, &taken_edge, &output, &vr);
- if (output)
- {
- /* Set the SSA with the value range. There are two cases to
- consider. First (the the most common) is we are processing
- STMT in a context where its resulting range globally holds
- and thus it can be reflected into the global ranges and need
- not be unwound as we leave scope.
-
- The second case occurs if we are processing a statement in
- a context where the resulting range must not be reflected
- into the global tables and must be unwound as we leave
- the current context. This happens in jump threading for
- example. */
- if (!temporary)
- {
- /* Case one. We can just update the underlying range
- information as well as the global information. */
- update_value_range (output, &vr);
- if (m_update_global_ranges)
- set_ssa_range_info (output, &vr);
- }
- else
- {
- /* We're going to need to unwind this range. We cannot
- use VR as that's a stack object. We have to allocate
- a new range and push the old range onto the stack. We
- also have to be very careful about sharing the underlying
- bitmaps. Ugh. */
- value_range_equiv *new_vr = allocate_value_range_equiv ();
- new_vr->set (vr.min (), vr.max (), NULL, vr.kind ());
- vr.equiv_clear ();
- push_value_range (output, new_vr);
- }
- }
- else
- set_defs_to_varying (stmt);
- }
- else
- set_defs_to_varying (stmt);
-
- /* See if we can derive a range for any of STMT's operands. */
- tree op;
- ssa_op_iter i;
- FOR_EACH_SSA_TREE_OPERAND (op, stmt, i, SSA_OP_USE)
- {
- tree value;
- enum tree_code comp_code;
-
- /* If OP is used in such a way that we can infer a value
- range for it, and we don't find a previous assertion for
- it, create a new assertion location node for OP. */
- if (infer_value_range (stmt, op, &comp_code, &value))
- {
- /* If we are able to infer a nonzero value range for OP,
- then walk backwards through the use-def chain to see if OP
- was set via a typecast.
- If so, then we can also infer a nonzero value range
- for the operand of the NOP_EXPR. */
- if (comp_code == NE_EXPR && integer_zerop (value))
- {
- tree t = op;
- gimple *def_stmt = SSA_NAME_DEF_STMT (t);
- while (is_gimple_assign (def_stmt)
- && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def_stmt))
- && TREE_CODE
- (gimple_assign_rhs1 (def_stmt)) == SSA_NAME
- && POINTER_TYPE_P
- (TREE_TYPE (gimple_assign_rhs1 (def_stmt))))
- {
- t = gimple_assign_rhs1 (def_stmt);
- def_stmt = SSA_NAME_DEF_STMT (t);
-
- /* Add VR when (T COMP_CODE value) condition is
- true. */
- value_range_equiv *op_range
- = try_find_new_range (t, t, comp_code, value);
- if (op_range)
- push_value_range (t, op_range);
- }
- }
- /* Add VR when (OP COMP_CODE value) condition is true. */
- value_range_equiv *op_range = try_find_new_range (op, op,
- comp_code, value);
- if (op_range)
- push_value_range (op, op_range);
- }
- }
-}
-
-/* Unwind recorded ranges to their most recent state. */
-
-void
-evrp_range_analyzer::pop_to_marker (void)
-{
- gcc_checking_assert (!stack.is_empty ());
- while (stack.last ().first != NULL_TREE)
- pop_value_range ();
- stack.pop ();
-}
-
-/* Restore/pop VRs valid only for BB when we leave BB. */
-
-void
-evrp_range_analyzer::leave (basic_block bb ATTRIBUTE_UNUSED)
-{
- if (!optimize)
- return;
- pop_to_marker ();
-}
-
-
-/* Push the Value Range of VAR to the stack and update it with new VR. */
-
-void
-evrp_range_analyzer::push_value_range (tree var, value_range_equiv *vr)
-{
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file, "pushing new range for ");
- print_generic_expr (dump_file, var);
- fprintf (dump_file, ": ");
- dump_value_range (dump_file, vr);
- fprintf (dump_file, "\n");
- }
- value_range_equiv *old_vr = swap_vr_value (var, vr);
- stack.safe_push (std::make_pair (var, old_vr));
-}
-
-/* Pop a Value Range from the vrp_stack. */
-
-void
-evrp_range_analyzer::pop_value_range ()
-{
- std::pair<tree, value_range_equiv *> e = stack.pop ();
- tree var = e.first;
- value_range_equiv *vr = e.second;
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file, "popping range for ");
- print_generic_expr (dump_file, var);
- fprintf (dump_file, ", restoring ");
- dump_value_range (dump_file, vr);
- fprintf (dump_file, "\n");
- }
- /* We saved off a lattice entry, now give it back and release
- the one we popped. */
- value_range_equiv *popped_vr = swap_vr_value (var, vr);
- if (popped_vr)
- free_value_range (popped_vr);
-}
deleted file mode 100644
@@ -1,58 +0,0 @@
-/* Support routines for Value Range Propagation (VRP).
- Copyright (C) 2016-2022 Free Software Foundation, Inc.
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
-
-GCC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
-
-#ifndef GCC_GIMPLE_SSA_EVRP_ANALYZE_H
-#define GCC_GIMPLE_SSA_EVRP_ANALYZE_H
-
-class evrp_range_analyzer : public vr_values
-{
- public:
- evrp_range_analyzer (bool update_global_ranges);
- ~evrp_range_analyzer (void)
- {
- stack.release ();
- }
-
- void enter (basic_block);
- void push_marker (void);
- void pop_to_marker (void);
- void leave (basic_block);
- void record_ranges_from_stmt (gimple *, bool);
-
- /* Record a new unwindable range. */
- void push_value_range (tree var, value_range_equiv *vr);
-
- private:
- DISABLE_COPY_AND_ASSIGN (evrp_range_analyzer);
-
- void pop_value_range ();
- value_range_equiv *try_find_new_range (tree, tree op, tree_code code,
- tree limit);
- void record_ranges_from_incoming_edge (basic_block);
- void record_ranges_from_phis (basic_block);
- void set_ssa_range_info (tree, value_range_equiv *);
-
- /* STACK holds the old VR. */
- auto_vec<std::pair <tree, value_range_equiv *> > stack;
-
- /* True if we are updating global ranges, false otherwise. */
- bool m_update_global_ranges;
-};
-
-#endif /* GCC_GIMPLE_SSA_EVRP_ANALYZE_H */
deleted file mode 100644
@@ -1,395 +0,0 @@
-/* Support routines for Value Range Propagation (VRP).
- Copyright (C) 2005-2022 Free Software Foundation, Inc.
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
-
-GCC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "backend.h"
-#include "tree.h"
-#include "gimple.h"
-#include "tree-pass.h"
-#include "ssa.h"
-#include "gimple-pretty-print.h"
-#include "cfganal.h"
-#include "gimple-iterator.h"
-#include "gimple-fold.h"
-#include "tree-eh.h"
-#include "tree-cfg.h"
-#include "tree-ssa-loop-manip.h"
-#include "tree-ssa-loop.h"
-#include "cfgloop.h"
-#include "tree-scalar-evolution.h"
-#include "tree-ssa-propagate.h"
-#include "alloc-pool.h"
-#include "domwalk.h"
-#include "tree-cfgcleanup.h"
-#include "vr-values.h"
-#include "gimple-ssa-evrp-analyze.h"
-#include "gimple-range.h"
-#include "fold-const.h"
-#include "value-pointer-equiv.h"
-#include "tree-vrp.h"
-
-// This is the classic EVRP folder which uses a dominator walk and pushes
-// ranges into the next block if it is a single predecessor block.
-
-class evrp_folder : public substitute_and_fold_engine
-{
-public:
- evrp_folder () :
- substitute_and_fold_engine (),
- m_range_analyzer (/*update_global_ranges=*/true),
- simplifier (&m_range_analyzer)
- { }
-
- ~evrp_folder ()
- {
- if (dump_file)
- {
- fprintf (dump_file, "\nValue ranges after Early VRP:\n\n");
- m_range_analyzer.dump (dump_file);
- fprintf (dump_file, "\n");
- }
- }
-
- tree value_of_expr (tree name, gimple *stmt) override
- {
- return m_range_analyzer.value_of_expr (name, stmt);
- }
-
- void pre_fold_bb (basic_block bb) override
- {
- if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, "evrp visiting BB%d\n", bb->index);
- m_range_analyzer.enter (bb);
- }
-
- void pre_fold_stmt (gimple *stmt) override
- {
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file, "evrp visiting stmt ");
- print_gimple_stmt (dump_file, stmt, 0);
- }
- m_range_analyzer.record_ranges_from_stmt (stmt, false);
- }
-
- bool fold_stmt (gimple_stmt_iterator *gsi) override
- {
- return simplifier.simplify (gsi);
- }
-
- void post_fold_bb (basic_block bb) override
- {
- m_range_analyzer.leave (bb);
- }
-
- void post_new_stmt (gimple *stmt) override
- {
- m_range_analyzer.set_defs_to_varying (stmt);
- }
-
-protected:
- DISABLE_COPY_AND_ASSIGN (evrp_folder);
- evrp_range_analyzer m_range_analyzer;
- simplify_using_ranges simplifier;
-};
-
-// In a hybrid folder, start with an EVRP folder, and add the required
-// fold_stmt bits to either try the ranger first or second.
-//
-// The 3 value_* routines will always query both EVRP and the ranger for
-// a result, and ensure they return the same value. If either returns a value
-// when the other doesn't, it is flagged in the listing, and the discoverd
-// value is returned.
-//
-// The simplifier is unable to process 2 different sources, thus we try to
-// use one engine, and if it fails to simplify, try using the other engine.
-// It is reported when the first attempt fails and the second succeeds.
-
-class hybrid_folder : public evrp_folder
-{
-public:
- hybrid_folder (bool evrp_first)
- {
- m_ranger = enable_ranger (cfun);
-
- if (evrp_first)
- {
- first = &m_range_analyzer;
- first_exec_flag = 0;
- second = m_ranger;
- second_exec_flag = m_ranger->non_executable_edge_flag;
- }
- else
- {
- first = m_ranger;
- first_exec_flag = m_ranger->non_executable_edge_flag;
- second = &m_range_analyzer;
- second_exec_flag = 0;
- }
- m_pta = new pointer_equiv_analyzer (m_ranger);
- }
-
- ~hybrid_folder ()
- {
- if (dump_file && (dump_flags & TDF_DETAILS))
- m_ranger->dump (dump_file);
-
- m_ranger->export_global_ranges ();
- disable_ranger (cfun);
- delete m_pta;
- }
-
- bool fold_stmt (gimple_stmt_iterator *gsi) override
- {
- simplifier.set_range_query (first, first_exec_flag);
- if (simplifier.simplify (gsi))
- return true;
-
- simplifier.set_range_query (second, second_exec_flag);
- if (simplifier.simplify (gsi))
- {
- if (dump_file)
- fprintf (dump_file, "EVRP:hybrid: Second query simplifed stmt\n");
- return true;
- }
- return false;
- }
-
- void pre_fold_stmt (gimple *stmt) override
- {
- evrp_folder::pre_fold_stmt (stmt);
- m_pta->visit_stmt (stmt);
- }
-
- void pre_fold_bb (basic_block bb) override
- {
- evrp_folder::pre_fold_bb (bb);
- m_pta->enter (bb);
- }
-
- void post_fold_bb (basic_block bb) override
- {
- evrp_folder::post_fold_bb (bb);
- m_pta->leave (bb);
- }
-
- tree value_of_expr (tree name, gimple *) override;
- tree value_on_edge (edge, tree name) override;
- tree value_of_stmt (gimple *, tree name) override;
-
-private:
- DISABLE_COPY_AND_ASSIGN (hybrid_folder);
- gimple_ranger *m_ranger;
- range_query *first;
- int first_exec_flag;
- range_query *second;
- int second_exec_flag;
- pointer_equiv_analyzer *m_pta;
- tree choose_value (tree evrp_val, tree ranger_val);
-};
-
-
-tree
-hybrid_folder::value_of_expr (tree op, gimple *stmt)
-{
- tree evrp_ret = evrp_folder::value_of_expr (op, stmt);
- tree ranger_ret;
- if (TREE_CODE (op) == SSA_NAME && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op))
- ranger_ret = NULL;
- else
- {
- ranger_ret = m_ranger->value_of_expr (op, stmt);
- if (!ranger_ret && supported_pointer_equiv_p (op))
- ranger_ret = m_pta->get_equiv (op);
- }
- return choose_value (evrp_ret, ranger_ret);
-}
-
-tree
-hybrid_folder::value_on_edge (edge e, tree op)
-{
- // Call evrp::value_of_expr directly. Otherwise another dual call is made
- // via hybrid_folder::value_of_expr, but without an edge.
- tree evrp_ret = evrp_folder::value_of_expr (op, NULL);
- tree ranger_ret;
- if (TREE_CODE (op) == SSA_NAME && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op))
- ranger_ret = NULL;
- else
- {
- ranger_ret = m_ranger->value_on_edge (e, op);
- if (!ranger_ret && supported_pointer_equiv_p (op))
- ranger_ret = m_pta->get_equiv (op);
- }
- return choose_value (evrp_ret, ranger_ret);
-}
-
-tree
-hybrid_folder::value_of_stmt (gimple *stmt, tree op)
-{
- // Call evrp::value_of_expr directly. Otherwise another dual call is made
- // via hybrid_folder::value_of_expr, but without a stmt.
- tree evrp_ret;
- if (op)
- evrp_ret = evrp_folder::value_of_expr (op, NULL);
- else
- evrp_ret = NULL_TREE;
-
- tree ranger_ret;
- if (op && TREE_CODE (op) == SSA_NAME && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op))
- ranger_ret = NULL;
- else
- ranger_ret = m_ranger->value_of_stmt (stmt, op);
- return choose_value (evrp_ret, ranger_ret);
-}
-
-// Given trees returned by EVRP and Ranger, choose/report the value to use
-// by the folder.
-
-tree
-hybrid_folder::choose_value (tree evrp_val, tree ranger_val)
-{
- // If both found the same value, just return it.
- if (evrp_val && ranger_val && !compare_values (evrp_val, ranger_val))
- return evrp_val;
-
- // If neither returned a value, return NULL_TREE.
- if (!ranger_val && !evrp_val)
- return NULL_TREE;
-
- // Otherwise there is a discrepancy to flag.
- if (dump_file)
- {
- if (evrp_val && ranger_val)
- fprintf (dump_file, "EVRP:hybrid: Disagreement\n");
- if (evrp_val)
- {
- fprintf (dump_file, "EVRP:hybrid: EVRP found singleton ");
- print_generic_expr (dump_file, evrp_val);
- fprintf (dump_file, "\n");
- }
- if (ranger_val)
- {
- fprintf (dump_file, "EVRP:hybrid: RVRP found singleton ");
- print_generic_expr (dump_file, ranger_val);
- fprintf (dump_file, "\n");
- }
- }
-
- // If one value was found, return it.
- if (!evrp_val)
- return ranger_val;
- if (!ranger_val)
- return evrp_val;
-
- // If values are different, return the first calculated value.
- if (param_evrp_mode == EVRP_MODE_RVRP_FIRST)
- return ranger_val;
- return evrp_val;
-}
-
-/* Main entry point for the early vrp pass which is a simplified non-iterative
- version of vrp where basic blocks are visited in dominance order. Value
- ranges discovered in early vrp will also be used by ipa-vrp. */
-
-static unsigned int
-execute_early_vrp ()
-{
- if (param_evrp_mode == EVRP_MODE_RVRP_ONLY)
- return execute_ranger_vrp (cfun, false);
-
- /* Ideally this setup code would move into the ctor for the folder
- However, this setup can change the number of blocks which
- invalidates the internal arrays that are set up by the dominator
- walker in substitute_and_fold_engine. */
- loop_optimizer_init (LOOPS_NORMAL | LOOPS_HAVE_RECORDED_EXITS);
- rewrite_into_loop_closed_ssa (NULL, TODO_update_ssa);
- scev_initialize ();
- calculate_dominance_info (CDI_DOMINATORS);
-
- // Only the last 2 bits matter for choosing the folder.
- switch (param_evrp_mode)
- {
- case EVRP_MODE_EVRP_ONLY:
- {
- evrp_folder folder;
- folder.substitute_and_fold ();
- break;
- }
- case EVRP_MODE_EVRP_FIRST:
- {
- hybrid_folder folder (true);
- folder.substitute_and_fold ();
- break;
- }
- case EVRP_MODE_RVRP_FIRST:
- {
- hybrid_folder folder (false);
- folder.substitute_and_fold ();
- break;
- }
- default:
- gcc_unreachable ();
- }
-
- scev_finalize ();
- loop_optimizer_finalize ();
- return 0;
-}
-
-namespace {
-
-const pass_data pass_data_early_vrp =
-{
- GIMPLE_PASS, /* type */
- "evrp", /* name */
- OPTGROUP_NONE, /* optinfo_flags */
- TV_TREE_EARLY_VRP, /* tv_id */
- PROP_ssa, /* properties_required */
- 0, /* properties_provided */
- 0, /* properties_destroyed */
- 0, /* todo_flags_start */
- ( TODO_cleanup_cfg | TODO_update_ssa | TODO_verify_all ),
-};
-
-class pass_early_vrp : public gimple_opt_pass
-{
-public:
- pass_early_vrp (gcc::context *ctxt)
- : gimple_opt_pass (pass_data_early_vrp, ctxt)
- {}
-
- /* opt_pass methods: */
- opt_pass * clone () { return new pass_early_vrp (m_ctxt); }
- virtual bool gate (function *)
- {
- return flag_tree_vrp != 0;
- }
- virtual unsigned int execute (function *)
- { return execute_early_vrp (); }
-
-}; // class pass_vrp
-} // anon namespace
-
-gimple_opt_pass *
-make_pass_early_vrp (gcc::context *ctxt)
-{
- return new pass_early_vrp (ctxt);
-}
@@ -134,25 +134,6 @@ Maximum number of basic blocks before EVRP uses a sparse cache.
Common Joined UInteger Var(param_evrp_switch_limit) Init(50) Optimization Param
Maximum number of outgoing edges in a switch before EVRP will not process it.
--param=evrp-mode=
-Common Joined Var(param_evrp_mode) Enum(evrp_mode) Init(EVRP_MODE_RVRP_ONLY) Param Optimization
---param=evrp-mode=[legacy|ranger|legacy-first|ranger-first] Specifies the mode Early VRP should operate in.
-
-Enum
-Name(evrp_mode) Type(enum evrp_mode) UnknownError(unknown evrp mode %qs)
-
-EnumValue
-Enum(evrp_mode) String(legacy) Value(EVRP_MODE_EVRP_ONLY)
-
-EnumValue
-Enum(evrp_mode) String(ranger) Value(EVRP_MODE_RVRP_ONLY)
-
-EnumValue
-Enum(evrp_mode) String(legacy-first) Value(EVRP_MODE_EVRP_FIRST)
-
-EnumValue
-Enum(evrp_mode) String(ranger-first) Value(EVRP_MODE_RVRP_FIRST)
-
-param=fsm-scale-path-blocks=
Common Joined UInteger Var(param_fsm_scale_path_blocks) Init(3) IntegerRange(1, 10) Param Optimization
Scale factor to apply to the number of blocks in a threading path when comparing to the number of (scaled) statements.
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fno-tree-forwprop --param=evrp-mode=ranger -fcompare-debug " } */
+/* { dg-options "-O2 -fno-tree-forwprop -fcompare-debug " } */
extern void __attribute__((noreturn)) error();
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 --param=evrp-mode=ranger -fcompare-debug " } */
+/* { dg-options "-O2 -fcompare-debug " } */
struct a {
int b;
@@ -4388,17 +4388,30 @@ const pass_data pass_data_vrp =
( TODO_cleanup_cfg | TODO_update_ssa ), /* todo_flags_finish */
};
+const pass_data pass_data_early_vrp =
+{
+ GIMPLE_PASS, /* type */
+ "evrp", /* name */
+ OPTGROUP_NONE, /* optinfo_flags */
+ TV_TREE_EARLY_VRP, /* tv_id */
+ PROP_ssa, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ ( TODO_cleanup_cfg | TODO_update_ssa | TODO_verify_all ),
+};
+
static int vrp_pass_num = 0;
class pass_vrp : public gimple_opt_pass
{
public:
- pass_vrp (gcc::context *ctxt)
- : gimple_opt_pass (pass_data_vrp, ctxt), warn_array_bounds_p (false),
- my_pass (++vrp_pass_num)
+ pass_vrp (gcc::context *ctxt, const pass_data &data_)
+ : gimple_opt_pass (data_, ctxt), data (data_), warn_array_bounds_p (false),
+ my_pass (vrp_pass_num++)
{}
/* opt_pass methods: */
- opt_pass * clone () { return new pass_vrp (m_ctxt); }
+ opt_pass * clone () { return new pass_vrp (m_ctxt, data); }
void set_pass_param (unsigned int n, bool param)
{
gcc_assert (n == 0);
@@ -4407,6 +4420,10 @@ public:
virtual bool gate (function *) { return flag_tree_vrp != 0; }
virtual unsigned int execute (function *fun)
{
+ // Early VRP pass.
+ if (my_pass == 0)
+ return execute_ranger_vrp (fun, /*warn_array_bounds_p=*/false);
+
if ((my_pass == 1 && param_vrp1_mode == VRP_MODE_RANGER)
|| (my_pass == 2 && param_vrp2_mode == VRP_MODE_RANGER))
return execute_ranger_vrp (fun, warn_array_bounds_p);
@@ -4414,6 +4431,7 @@ public:
}
private:
+ const pass_data &data;
bool warn_array_bounds_p;
int my_pass;
}; // class pass_vrp
@@ -4423,5 +4441,11 @@ public:
gimple_opt_pass *
make_pass_vrp (gcc::context *ctxt)
{
- return new pass_vrp (ctxt);
+ return new pass_vrp (ctxt, pass_data_vrp);
+}
+
+gimple_opt_pass *
+make_pass_early_vrp (gcc::context *ctxt)
+{
+ return new pass_vrp (ctxt, pass_data_early_vrp);
}