[5/5] Convert ranger and clients to vrange.

Message ID 20220530132751.1752112-5-aldyh@redhat.com
State New
Headers
Series [1/5] Implement abstract vrange class. |

Commit Message

Aldy Hernandez May 30, 2022, 1:27 p.m. UTC
  Finally, the meat of the work.  Convert ranger and associated clients
to vrange.

Everything's relatively mechanical given the previous patches.  I did
include a minor cleanup in the edge code.  There's no need to check
that the type of the switch is an integer as non-integer switches are
invalid.  I verified this with an appropriately coded assert.

Tested on x86-64 & ppc64le Linux.

gcc/ChangeLog:

	* gimple-range-cache.cc (ssa_block_ranges::dump): Convert to vrange.
	(sbr_vector::sbr_vector): Same.
	(sbr_vector::grow): Same.
	(sbr_vector::set_bb_range): Same.
	(sbr_vector::get_bb_range): Same.
	(sbr_sparse_bitmap::sbr_sparse_bitmap): Same.
	(sbr_sparse_bitmap::set_bb_range): Same.
	(sbr_sparse_bitmap::get_bb_range): Same.
	(block_range_cache::set_bb_range): Same.
	(block_range_cache::get_bb_range): Same.
	(block_range_cache::dump): Same.
	(ssa_global_cache::get_global_range): Same.
	(ssa_global_cache::set_global_range): Same.
	(ssa_global_cache::clear): Same.
	(ssa_global_cache::dump): Same.
	(ranger_cache::get_global_range): Same.
	(ranger_cache::set_global_range): Same.
	(ranger_cache::range_of_def): Same.
	(ranger_cache::entry_range): Same.
	(ranger_cache::exit_range): Same.
	(ranger_cache::edge_range): Same.
	(ranger_cache::range_of_expr): Same.
	(ranger_cache::range_on_edge): Same.
	(ranger_cache::block_range): Same.
	(ranger_cache::propagate_cache): Same.
	(ranger_cache::fill_block_cache): Same.
	(ranger_cache::range_from_dom): Same.
	* gimple-range-cache.h: Same.
	* gimple-range-edge.cc (gimple_outgoing_range::get_edge_range):
	Same.
	(gimple_outgoing_range::switch_edge_range): Same.
	(gimple_outgoing_range::edge_range_p): Same.
	* gimple-range-edge.h: Same.
	* gimple-range-fold.cc (fur_source::get_operand): Same.
	(fur_source::get_phi_operand): Same.
	(fur_edge::get_operand): Same.
	(fur_edge::get_phi_operand): Same.
	(fur_stmt::get_operand): Same.
	(fur_stmt::get_phi_operand): Same.
	(fur_list::fur_list): Same.
	(fur_list::get_operand): Same.
	(fur_list::get_phi_operand): Same.
	(fold_range): Same.
	(adjust_imagpart_expr): Same.
	(adjust_realpart_expr): Same.
	(gimple_range_adjustment): Same.
	(fold_using_range::fold_stmt): Same.
	(fold_using_range::range_of_range_op): Same.
	(fold_using_range::range_of_address): Same.
	(fold_using_range::range_of_phi): Same.
	(fold_using_range::range_of_call): Same.
	(fold_using_range::range_of_builtin_call): Same.
	(fold_using_range::range_of_builtin_int_call): Same.
	(fold_using_range::range_of_cond_expr): Same.
	(fur_source::register_outgoing_edges): Same.
	* gimple-range-fold.h (fold_range): Same.
	(gimple_range_type): Same.
	(gimple_range_ssa_p): Same.
	* gimple-range-gori.cc (gimple_range_calc_op1): Same.
	(gimple_range_calc_op2): Same.
	(gori_compute::compute_operand_range_switch): Same.
	(gori_compute::compute_operand_range): Same.
	(gori_compute::logical_combine): Same.
	(gori_compute::compute_logical_operands): Same.
	(gori_compute::compute_operand1_range): Same.
	(gori_compute::compute_operand2_range): Same.
	(gori_compute::compute_operand1_and_operand2_range): Same.
	(gori_compute::outgoing_edge_range_p): Same.
	(gori_compute::condexpr_adjust): Same.
	* gimple-range-gori.h (gimple_range_calc_op1): Same.
	(gimple_range_calc_op2): Same.
	* gimple-range-path.cc (path_range_query::get_cache): Same.
	(path_range_query::set_cache): Same.
	(path_range_query::range_on_path_entry): Same.
	(path_range_query::internal_range_of_expr): Same.
	(path_range_query::range_of_expr): Same.
	(path_range_query::ssa_range_in_phi): Same.
	(path_range_query::range_defined_in_block): Same.
	(path_range_query::compute_ranges_in_phis): Same.
	(path_range_query::compute_ranges_in_block): Same.
	(path_range_query::add_to_imports): Same.
	(path_range_query::range_of_stmt): Same.
	* gimple-range-path.h: Same.
	* gimple-range-side-effect.cc (stmt_side_effects::add_range): Same.
	(side_effect_manager::~side_effect_manager): Same.
	(side_effect_manager::get_nonzero): Same.
	(side_effect_manager::maybe_adjust_range): Same.
	(side_effect_manager::add_range): Same.
	* gimple-range-side-effect.h: Same.
	* gimple-range-tests.cc: Same.
	* gimple-range-trace.cc (range_tracer::trailer): Same.
	(debug_seed_ranger): Same.
	* gimple-range-trace.h: Same.
	* gimple-range.cc (gimple_ranger::range_of_expr): Same.
	(gimple_ranger::range_on_entry): Same.
	(gimple_ranger::range_on_exit): Same.
	(gimple_ranger::range_on_edge): Same.
	(gimple_ranger::fold_range_internal): Same.
	(gimple_ranger::range_of_stmt): Same.
	(gimple_ranger::prefill_name): Same.
	(gimple_ranger::prefill_stmt_dependencies): Same.
	(gimple_ranger::export_global_ranges): Same.
	(gimple_ranger::dump_bb): Same.
	* gimple-range.h: Same.
	* gimple-ssa-warn-access.cc (check_nul_terminated_array): Same.
	(memmodel_to_uhwi): Same.
	* tree-ssa-loop-niter.cc (refine_value_range_using_guard): Same.
	(determine_value_range): Same.
	(record_nonwrapping_iv): Same.
	(infer_loop_bounds_from_signedness): Same.
	(scev_var_range_cant_overflow): Same.
	* tree-ssa-threadedge.cc (hybrid_jt_simplifier::simplify): Same.
	* value-query.cc (range_query::range_on_edge): Same.
	(range_query::range_of_stmt): Same.
	(range_query::value_of_expr): Same.
	(range_query::value_on_edge): Same.
	(range_query::value_of_stmt): Same.
	(range_query::get_tree_range): Same.
	(update_global_range): Same.
	(get_range_global): Same.
	(gimple_range_global): Same.
	(global_range_query::range_of_expr): Same.
	(range_query::query_relation): Same.
	* value-query.h (gimple_range_global): Same.
	(update_global_range): Same.
	* vr-values.cc (vr_values::range_of_expr): Same.
	(bounds_of_var_in_loop): Same.
	(simplify_using_ranges::vrp_visit_cond_stmt): Same.
	* vr-values.h (class vr_values): Same.
---
 gcc/gimple-range-cache.cc       | 136 ++++++++++++++++--------------
 gcc/gimple-range-cache.h        |  32 +++----
 gcc/gimple-range-edge.cc        |  12 +--
 gcc/gimple-range-edge.h         |   2 +-
 gcc/gimple-range-fold.cc        | 144 +++++++++++++++++++-------------
 gcc/gimple-range-fold.h         |  37 ++++----
 gcc/gimple-range-gori.cc        | 116 ++++++++++++++-----------
 gcc/gimple-range-gori.h         |  42 +++++-----
 gcc/gimple-range-path.cc        |  47 ++++++-----
 gcc/gimple-range-path.h         |  16 ++--
 gcc/gimple-range-side-effect.cc |  20 ++---
 gcc/gimple-range-side-effect.h  |  14 ++--
 gcc/gimple-range-tests.cc       |   3 +-
 gcc/gimple-range-trace.cc       |   9 +-
 gcc/gimple-range-trace.h        |   2 +-
 gcc/gimple-range.cc             |  44 ++++++----
 gcc/gimple-range.h              |  14 ++--
 gcc/gimple-ssa-warn-access.cc   |   7 +-
 gcc/tree-ssa-loop-niter.cc      |  16 ++--
 gcc/tree-ssa-threadedge.cc      |   4 +-
 gcc/value-query.cc              |  73 ++++++++--------
 gcc/value-query.h               |  16 ++--
 gcc/vr-values.cc                |  29 ++++---
 gcc/vr-values.h                 |   2 +-
 24 files changed, 457 insertions(+), 380 deletions(-)
  

Comments

Aldy Hernandez June 1, 2022, 9:04 a.m. UTC | #1
Final patch committed.

All users but one of Value_Range::set_type() have been removed in
favor of using a constructor taking a type.   We still need to delay
initialization for one use in gimple_infer_range, as it has an array
of temporaries for which the type is not known until later.

Re-tested on x86-64 Linux.

On Mon, May 30, 2022 at 3:28 PM Aldy Hernandez <aldyh@redhat.com> wrote:
>
> Finally, the meat of the work.  Convert ranger and associated clients
> to vrange.
>
> Everything's relatively mechanical given the previous patches.  I did
> include a minor cleanup in the edge code.  There's no need to check
> that the type of the switch is an integer as non-integer switches are
> invalid.  I verified this with an appropriately coded assert.
>
> Tested on x86-64 & ppc64le Linux.
>
> gcc/ChangeLog:
>
>         * gimple-range-cache.cc (ssa_block_ranges::dump): Convert to vrange.
>         (sbr_vector::sbr_vector): Same.
>         (sbr_vector::grow): Same.
>         (sbr_vector::set_bb_range): Same.
>         (sbr_vector::get_bb_range): Same.
>         (sbr_sparse_bitmap::sbr_sparse_bitmap): Same.
>         (sbr_sparse_bitmap::set_bb_range): Same.
>         (sbr_sparse_bitmap::get_bb_range): Same.
>         (block_range_cache::set_bb_range): Same.
>         (block_range_cache::get_bb_range): Same.
>         (block_range_cache::dump): Same.
>         (ssa_global_cache::get_global_range): Same.
>         (ssa_global_cache::set_global_range): Same.
>         (ssa_global_cache::clear): Same.
>         (ssa_global_cache::dump): Same.
>         (ranger_cache::get_global_range): Same.
>         (ranger_cache::set_global_range): Same.
>         (ranger_cache::range_of_def): Same.
>         (ranger_cache::entry_range): Same.
>         (ranger_cache::exit_range): Same.
>         (ranger_cache::edge_range): Same.
>         (ranger_cache::range_of_expr): Same.
>         (ranger_cache::range_on_edge): Same.
>         (ranger_cache::block_range): Same.
>         (ranger_cache::propagate_cache): Same.
>         (ranger_cache::fill_block_cache): Same.
>         (ranger_cache::range_from_dom): Same.
>         * gimple-range-cache.h: Same.
>         * gimple-range-edge.cc (gimple_outgoing_range::get_edge_range):
>         Same.
>         (gimple_outgoing_range::switch_edge_range): Same.
>         (gimple_outgoing_range::edge_range_p): Same.
>         * gimple-range-edge.h: Same.
>         * gimple-range-fold.cc (fur_source::get_operand): Same.
>         (fur_source::get_phi_operand): Same.
>         (fur_edge::get_operand): Same.
>         (fur_edge::get_phi_operand): Same.
>         (fur_stmt::get_operand): Same.
>         (fur_stmt::get_phi_operand): Same.
>         (fur_list::fur_list): Same.
>         (fur_list::get_operand): Same.
>         (fur_list::get_phi_operand): Same.
>         (fold_range): Same.
>         (adjust_imagpart_expr): Same.
>         (adjust_realpart_expr): Same.
>         (gimple_range_adjustment): Same.
>         (fold_using_range::fold_stmt): Same.
>         (fold_using_range::range_of_range_op): Same.
>         (fold_using_range::range_of_address): Same.
>         (fold_using_range::range_of_phi): Same.
>         (fold_using_range::range_of_call): Same.
>         (fold_using_range::range_of_builtin_call): Same.
>         (fold_using_range::range_of_builtin_int_call): Same.
>         (fold_using_range::range_of_cond_expr): Same.
>         (fur_source::register_outgoing_edges): Same.
>         * gimple-range-fold.h (fold_range): Same.
>         (gimple_range_type): Same.
>         (gimple_range_ssa_p): Same.
>         * gimple-range-gori.cc (gimple_range_calc_op1): Same.
>         (gimple_range_calc_op2): Same.
>         (gori_compute::compute_operand_range_switch): Same.
>         (gori_compute::compute_operand_range): Same.
>         (gori_compute::logical_combine): Same.
>         (gori_compute::compute_logical_operands): Same.
>         (gori_compute::compute_operand1_range): Same.
>         (gori_compute::compute_operand2_range): Same.
>         (gori_compute::compute_operand1_and_operand2_range): Same.
>         (gori_compute::outgoing_edge_range_p): Same.
>         (gori_compute::condexpr_adjust): Same.
>         * gimple-range-gori.h (gimple_range_calc_op1): Same.
>         (gimple_range_calc_op2): Same.
>         * gimple-range-path.cc (path_range_query::get_cache): Same.
>         (path_range_query::set_cache): Same.
>         (path_range_query::range_on_path_entry): Same.
>         (path_range_query::internal_range_of_expr): Same.
>         (path_range_query::range_of_expr): Same.
>         (path_range_query::ssa_range_in_phi): Same.
>         (path_range_query::range_defined_in_block): Same.
>         (path_range_query::compute_ranges_in_phis): Same.
>         (path_range_query::compute_ranges_in_block): Same.
>         (path_range_query::add_to_imports): Same.
>         (path_range_query::range_of_stmt): Same.
>         * gimple-range-path.h: Same.
>         * gimple-range-side-effect.cc (stmt_side_effects::add_range): Same.
>         (side_effect_manager::~side_effect_manager): Same.
>         (side_effect_manager::get_nonzero): Same.
>         (side_effect_manager::maybe_adjust_range): Same.
>         (side_effect_manager::add_range): Same.
>         * gimple-range-side-effect.h: Same.
>         * gimple-range-tests.cc: Same.
>         * gimple-range-trace.cc (range_tracer::trailer): Same.
>         (debug_seed_ranger): Same.
>         * gimple-range-trace.h: Same.
>         * gimple-range.cc (gimple_ranger::range_of_expr): Same.
>         (gimple_ranger::range_on_entry): Same.
>         (gimple_ranger::range_on_exit): Same.
>         (gimple_ranger::range_on_edge): Same.
>         (gimple_ranger::fold_range_internal): Same.
>         (gimple_ranger::range_of_stmt): Same.
>         (gimple_ranger::prefill_name): Same.
>         (gimple_ranger::prefill_stmt_dependencies): Same.
>         (gimple_ranger::export_global_ranges): Same.
>         (gimple_ranger::dump_bb): Same.
>         * gimple-range.h: Same.
>         * gimple-ssa-warn-access.cc (check_nul_terminated_array): Same.
>         (memmodel_to_uhwi): Same.
>         * tree-ssa-loop-niter.cc (refine_value_range_using_guard): Same.
>         (determine_value_range): Same.
>         (record_nonwrapping_iv): Same.
>         (infer_loop_bounds_from_signedness): Same.
>         (scev_var_range_cant_overflow): Same.
>         * tree-ssa-threadedge.cc (hybrid_jt_simplifier::simplify): Same.
>         * value-query.cc (range_query::range_on_edge): Same.
>         (range_query::range_of_stmt): Same.
>         (range_query::value_of_expr): Same.
>         (range_query::value_on_edge): Same.
>         (range_query::value_of_stmt): Same.
>         (range_query::get_tree_range): Same.
>         (update_global_range): Same.
>         (get_range_global): Same.
>         (gimple_range_global): Same.
>         (global_range_query::range_of_expr): Same.
>         (range_query::query_relation): Same.
>         * value-query.h (gimple_range_global): Same.
>         (update_global_range): Same.
>         * vr-values.cc (vr_values::range_of_expr): Same.
>         (bounds_of_var_in_loop): Same.
>         (simplify_using_ranges::vrp_visit_cond_stmt): Same.
>         * vr-values.h (class vr_values): Same.
> ---
>  gcc/gimple-range-cache.cc       | 136 ++++++++++++++++--------------
>  gcc/gimple-range-cache.h        |  32 +++----
>  gcc/gimple-range-edge.cc        |  12 +--
>  gcc/gimple-range-edge.h         |   2 +-
>  gcc/gimple-range-fold.cc        | 144 +++++++++++++++++++-------------
>  gcc/gimple-range-fold.h         |  37 ++++----
>  gcc/gimple-range-gori.cc        | 116 ++++++++++++++-----------
>  gcc/gimple-range-gori.h         |  42 +++++-----
>  gcc/gimple-range-path.cc        |  47 ++++++-----
>  gcc/gimple-range-path.h         |  16 ++--
>  gcc/gimple-range-side-effect.cc |  20 ++---
>  gcc/gimple-range-side-effect.h  |  14 ++--
>  gcc/gimple-range-tests.cc       |   3 +-
>  gcc/gimple-range-trace.cc       |   9 +-
>  gcc/gimple-range-trace.h        |   2 +-
>  gcc/gimple-range.cc             |  44 ++++++----
>  gcc/gimple-range.h              |  14 ++--
>  gcc/gimple-ssa-warn-access.cc   |   7 +-
>  gcc/tree-ssa-loop-niter.cc      |  16 ++--
>  gcc/tree-ssa-threadedge.cc      |   4 +-
>  gcc/value-query.cc              |  73 ++++++++--------
>  gcc/value-query.h               |  16 ++--
>  gcc/vr-values.cc                |  29 ++++---
>  gcc/vr-values.h                 |   2 +-
>  24 files changed, 457 insertions(+), 380 deletions(-)
>
> diff --git a/gcc/gimple-range-cache.cc b/gcc/gimple-range-cache.cc
> index 9c541993fb6..4983e4d3aa7 100644
> --- a/gcc/gimple-range-cache.cc
> +++ b/gcc/gimple-range-cache.cc
> @@ -44,11 +44,14 @@ along with GCC; see the file COPYING3.  If not see
>  class ssa_block_ranges
>  {
>  public:
> -  virtual bool set_bb_range (const_basic_block bb, const irange &r) = 0;
> -  virtual bool get_bb_range (irange &r, const_basic_block bb) = 0;
> +  ssa_block_ranges (tree t) : m_type (t) { }
> +  virtual bool set_bb_range (const_basic_block bb, const vrange &r) = 0;
> +  virtual bool get_bb_range (vrange &r, const_basic_block bb) = 0;
>    virtual bool bb_range_p (const_basic_block bb) = 0;
>
>    void dump(FILE *f);
> +private:
> +  tree m_type;
>  };
>
>  // Print the list of known ranges for file F in a nice format.
> @@ -57,7 +60,7 @@ void
>  ssa_block_ranges::dump (FILE *f)
>  {
>    basic_block bb;
> -  int_range_max r;
> +  tmp_range r (m_type);
>
>    FOR_EACH_BB_FN (bb, cfun)
>      if (get_bb_range (r, bb))
> @@ -77,14 +80,14 @@ class sbr_vector : public ssa_block_ranges
>  public:
>    sbr_vector (tree t, vrange_allocator *allocator);
>
> -  virtual bool set_bb_range (const_basic_block bb, const irange &r) override;
> -  virtual bool get_bb_range (irange &r, const_basic_block bb) override;
> +  virtual bool set_bb_range (const_basic_block bb, const vrange &r) override;
> +  virtual bool get_bb_range (vrange &r, const_basic_block bb) override;
>    virtual bool bb_range_p (const_basic_block bb) override;
>  protected:
> -  irange **m_tab;      // Non growing vector.
> +  vrange **m_tab;      // Non growing vector.
>    int m_tab_size;
> -  int_range<2> m_varying;
> -  int_range<2> m_undefined;
> +  vrange *m_varying;
> +  vrange *m_undefined;
>    tree m_type;
>    vrange_allocator *m_range_allocator;
>    void grow ();
> @@ -94,18 +97,21 @@ protected:
>  // Initialize a block cache for an ssa_name of type T.
>
>  sbr_vector::sbr_vector (tree t, vrange_allocator *allocator)
> +  : ssa_block_ranges (t)
>  {
>    gcc_checking_assert (TYPE_P (t));
>    m_type = t;
>    m_range_allocator = allocator;
>    m_tab_size = last_basic_block_for_fn (cfun) + 1;
> -  m_tab = static_cast <irange **>
> -    (allocator->alloc (m_tab_size * sizeof (irange *)));
> -  memset (m_tab, 0, m_tab_size * sizeof (irange *));
> +  m_tab = static_cast <vrange **>
> +    (allocator->alloc (m_tab_size * sizeof (vrange *)));
> +  memset (m_tab, 0, m_tab_size * sizeof (vrange *));
>
>    // Create the cached type range.
> -  m_varying.set_varying (t);
> -  m_undefined.set_undefined ();
> +  m_varying = m_range_allocator->alloc_vrange (t);
> +  m_undefined = m_range_allocator->alloc_vrange (t);
> +  m_varying->set_varying (t);
> +  m_undefined->set_undefined ();
>  }
>
>  // Grow the vector when the CFG has increased in size.
> @@ -122,10 +128,10 @@ sbr_vector::grow ()
>    int new_size = inc + curr_bb_size;
>
>    // Allocate new memory, copy the old vector and clear the new space.
> -  irange **t = static_cast <irange **>
> -    (m_range_allocator->alloc (new_size * sizeof (irange *)));
> -  memcpy (t, m_tab, m_tab_size * sizeof (irange *));
> -  memset (t + m_tab_size, 0, (new_size - m_tab_size) * sizeof (irange *));
> +  vrange **t = static_cast <vrange **>
> +    (m_range_allocator->alloc (new_size * sizeof (vrange *)));
> +  memcpy (t, m_tab, m_tab_size * sizeof (vrange *));
> +  memset (t + m_tab_size, 0, (new_size - m_tab_size) * sizeof (vrange *));
>
>    m_tab = t;
>    m_tab_size = new_size;
> @@ -134,15 +140,15 @@ sbr_vector::grow ()
>  // Set the range for block BB to be R.
>
>  bool
> -sbr_vector::set_bb_range (const_basic_block bb, const irange &r)
> +sbr_vector::set_bb_range (const_basic_block bb, const vrange &r)
>  {
> -  irange *m;
> +  vrange *m;
>    if (bb->index >= m_tab_size)
>      grow ();
>    if (r.varying_p ())
> -    m = &m_varying;
> +    m = m_varying;
>    else if (r.undefined_p ())
> -    m = &m_undefined;
> +    m = m_undefined;
>    else
>      m = m_range_allocator->clone (r);
>    m_tab[bb->index] = m;
> @@ -153,11 +159,11 @@ sbr_vector::set_bb_range (const_basic_block bb, const irange &r)
>  // there is no range.
>
>  bool
> -sbr_vector::get_bb_range (irange &r, const_basic_block bb)
> +sbr_vector::get_bb_range (vrange &r, const_basic_block bb)
>  {
>    if (bb->index >= m_tab_size)
>      return false;
> -  irange *m = m_tab[bb->index];
> +  vrange *m = m_tab[bb->index];
>    if (m)
>      {
>        r = *m;
> @@ -193,14 +199,14 @@ class sbr_sparse_bitmap : public ssa_block_ranges
>  {
>  public:
>    sbr_sparse_bitmap (tree t, vrange_allocator *allocator, bitmap_obstack *bm);
> -  virtual bool set_bb_range (const_basic_block bb, const irange &r) override;
> -  virtual bool get_bb_range (irange &r, const_basic_block bb) override;
> +  virtual bool set_bb_range (const_basic_block bb, const vrange &r) override;
> +  virtual bool get_bb_range (vrange &r, const_basic_block bb) override;
>    virtual bool bb_range_p (const_basic_block bb) override;
>  private:
>    void bitmap_set_quad (bitmap head, int quad, int quad_value);
>    int bitmap_get_quad (const_bitmap head, int quad);
>    vrange_allocator *m_range_allocator;
> -  irange *m_range[SBR_NUM];
> +  vrange *m_range[SBR_NUM];
>    bitmap_head bitvec;
>    tree m_type;
>  };
> @@ -209,6 +215,7 @@ private:
>
>  sbr_sparse_bitmap::sbr_sparse_bitmap (tree t, vrange_allocator *allocator,
>                                       bitmap_obstack *bm)
> +  : ssa_block_ranges (t)
>  {
>    gcc_checking_assert (TYPE_P (t));
>    m_type = t;
> @@ -216,16 +223,14 @@ sbr_sparse_bitmap::sbr_sparse_bitmap (tree t, vrange_allocator *allocator,
>    bitmap_tree_view (&bitvec);
>    m_range_allocator = allocator;
>    // Pre-cache varying.
> -  m_range[0] = static_cast <irange *> (m_range_allocator->alloc_vrange (t));
> +  m_range[0] = m_range_allocator->alloc_vrange (t);
>    m_range[0]->set_varying (t);
>    // Pre-cache zero and non-zero values for pointers.
>    if (POINTER_TYPE_P (t))
>      {
> -      m_range[1]
> -       = static_cast <irange *> (m_range_allocator->alloc_vrange (t));
> +      m_range[1] = m_range_allocator->alloc_vrange (t);
>        m_range[1]->set_nonzero (t);
> -      m_range[2]
> -       = static_cast <irange *> (m_range_allocator->alloc_vrange (t));
> +      m_range[2] = m_range_allocator->alloc_vrange (t);
>        m_range[2]->set_zero (t);
>      }
>    else
> @@ -257,7 +262,7 @@ sbr_sparse_bitmap::bitmap_get_quad (const_bitmap head, int quad)
>  // Set the range on entry to basic block BB to R.
>
>  bool
> -sbr_sparse_bitmap::set_bb_range (const_basic_block bb, const irange &r)
> +sbr_sparse_bitmap::set_bb_range (const_basic_block bb, const vrange &r)
>  {
>    if (r.undefined_p ())
>      {
> @@ -283,7 +288,7 @@ sbr_sparse_bitmap::set_bb_range (const_basic_block bb, const irange &r)
>  // there is no range.
>
>  bool
> -sbr_sparse_bitmap::get_bb_range (irange &r, const_basic_block bb)
> +sbr_sparse_bitmap::get_bb_range (vrange &r, const_basic_block bb)
>  {
>    int value = bitmap_get_quad (&bitvec, bb->index);
>
> @@ -333,7 +338,7 @@ block_range_cache::~block_range_cache ()
>
>  bool
>  block_range_cache::set_bb_range (tree name, const_basic_block bb,
> -                                const irange &r)
> +                                const vrange &r)
>  {
>    unsigned v = SSA_NAME_VERSION (name);
>    if (v >= m_ssa_ranges.length ())
> @@ -379,7 +384,7 @@ block_range_cache::query_block_ranges (tree name)
>  // is one.
>
>  bool
> -block_range_cache::get_bb_range (irange &r, tree name, const_basic_block bb)
> +block_range_cache::get_bb_range (vrange &r, tree name, const_basic_block bb)
>  {
>    ssa_block_ranges *ptr = query_block_ranges (name);
>    if (ptr)
> @@ -423,12 +428,13 @@ void
>  block_range_cache::dump (FILE *f, basic_block bb, bool print_varying)
>  {
>    unsigned x;
> -  int_range_max r;
>    bool summarize_varying = false;
>    for (x = 1; x < m_ssa_ranges.length (); ++x)
>      {
>        if (!gimple_range_ssa_p (ssa_name (x)))
>         continue;
> +
> +      tmp_range r (TREE_TYPE (ssa_name (x)));
>        if (m_ssa_ranges[x] && m_ssa_ranges[x]->get_bb_range (r, bb))
>         {
>           if (!print_varying && r.varying_p ())
> @@ -450,6 +456,8 @@ block_range_cache::dump (FILE *f, basic_block bb, bool print_varying)
>         {
>           if (!gimple_range_ssa_p (ssa_name (x)))
>             continue;
> +
> +         tmp_range r (TREE_TYPE (ssa_name (x)));
>           if (m_ssa_ranges[x] && m_ssa_ranges[x]->get_bb_range (r, bb))
>             {
>               if (r.varying_p ())
> @@ -485,13 +493,13 @@ ssa_global_cache::~ssa_global_cache ()
>  // Return the value in R.
>
>  bool
> -ssa_global_cache::get_global_range (irange &r, tree name) const
> +ssa_global_cache::get_global_range (vrange &r, tree name) const
>  {
>    unsigned v = SSA_NAME_VERSION (name);
>    if (v >= m_tab.length ())
>      return false;
>
> -  irange *stow = m_tab[v];
> +  vrange *stow = m_tab[v];
>    if (!stow)
>      return false;
>    r = *stow;
> @@ -502,13 +510,13 @@ ssa_global_cache::get_global_range (irange &r, tree name) const
>  // Return TRUE if there was already a range set, otherwise false.
>
>  bool
> -ssa_global_cache::set_global_range (tree name, const irange &r)
> +ssa_global_cache::set_global_range (tree name, const vrange &r)
>  {
>    unsigned v = SSA_NAME_VERSION (name);
>    if (v >= m_tab.length ())
>      m_tab.safe_grow_cleared (num_ssa_names + 1);
>
> -  irange *m = m_tab[v];
> +  vrange *m = m_tab[v];
>    if (m && m->fits_p (r))
>      *m = r;
>    else
> @@ -533,7 +541,7 @@ void
>  ssa_global_cache::clear ()
>  {
>    if (m_tab.address ())
> -    memset (m_tab.address(), 0, m_tab.length () * sizeof (irange *));
> +    memset (m_tab.address(), 0, m_tab.length () * sizeof (vrange *));
>  }
>
>  // Dump the contents of the global cache to F.
> @@ -545,8 +553,9 @@ ssa_global_cache::dump (FILE *f)
>    bool print_header = true;
>    for (unsigned x = 1; x < num_ssa_names; x++)
>      {
> -      int_range_max r;
> +      tmp_range r;
>        if (gimple_range_ssa_p (ssa_name (x)) &&
> +         r.init (TREE_TYPE (ssa_name (x))) &&
>           get_global_range (r, ssa_name (x))  && !r.varying_p ())
>         {
>           if (print_header)
> @@ -809,11 +818,11 @@ ranger_cache::dump_bb (FILE *f, basic_block bb)
>  // global range is not set, and return the legacy global value in R.
>
>  bool
> -ranger_cache::get_global_range (irange &r, tree name) const
> +ranger_cache::get_global_range (vrange &r, tree name) const
>  {
>    if (m_globals.get_global_range (r, name))
>      return true;
> -  r = gimple_range_global (name);
> +  gimple_range_global (r, name);
>    return false;
>  }
>
> @@ -825,7 +834,7 @@ ranger_cache::get_global_range (irange &r, tree name) const
>  // After this call, the global cache will have a value.
>
>  bool
> -ranger_cache::get_global_range (irange &r, tree name, bool &current_p)
> +ranger_cache::get_global_range (vrange &r, tree name, bool &current_p)
>  {
>    bool had_global = get_global_range (r, name);
>
> @@ -847,7 +856,7 @@ ranger_cache::get_global_range (irange &r, tree name, bool &current_p)
>  //  Set the global range of NAME to R and give it a timestamp.
>
>  void
> -ranger_cache::set_global_range (tree name, const irange &r)
> +ranger_cache::set_global_range (tree name, const vrange &r)
>  {
>    if (m_globals.set_global_range (name, r))
>      {
> @@ -882,7 +891,7 @@ ranger_cache::set_global_range (tree name, const irange &r)
>  // get the best global value available.
>
>  void
> -ranger_cache::range_of_def (irange &r, tree name, basic_block bb)
> +ranger_cache::range_of_def (vrange &r, tree name, basic_block bb)
>  {
>    gcc_checking_assert (gimple_range_ssa_p (name));
>    gcc_checking_assert (!bb || bb == gimple_bb (SSA_NAME_DEF_STMT (name)));
> @@ -895,7 +904,7 @@ ranger_cache::range_of_def (irange &r, tree name, basic_block bb)
>        if (gimple_get_lhs (s) == name)
>         fold_range (r, s, get_global_range_query ());
>        else
> -       r = gimple_range_global (name);
> +       gimple_range_global (r, name);
>      }
>  }
>
> @@ -903,12 +912,12 @@ ranger_cache::range_of_def (irange &r, tree name, basic_block bb)
>  // lookups.
>
>  void
> -ranger_cache::entry_range (irange &r, tree name, basic_block bb,
> +ranger_cache::entry_range (vrange &r, tree name, basic_block bb,
>                            enum rfd_mode mode)
>  {
>    if (bb == ENTRY_BLOCK_PTR_FOR_FN (cfun))
>      {
> -      r = gimple_range_global (name);
> +      gimple_range_global (r, name);
>        return;
>      }
>
> @@ -923,12 +932,12 @@ ranger_cache::entry_range (irange &r, tree name, basic_block bb,
>  // lookups.
>
>  void
> -ranger_cache::exit_range (irange &r, tree name, basic_block bb,
> +ranger_cache::exit_range (vrange &r, tree name, basic_block bb,
>                           enum rfd_mode mode)
>  {
>    if (bb == ENTRY_BLOCK_PTR_FOR_FN (cfun))
>      {
> -      r = gimple_range_global (name);
> +      gimple_range_global (r, name);
>        return;
>      }
>
> @@ -944,7 +953,7 @@ ranger_cache::exit_range (irange &r, tree name, basic_block bb,
>  // Always returns a range and true.
>
>  bool
> -ranger_cache::edge_range (irange &r, edge e, tree name, enum rfd_mode mode)
> +ranger_cache::edge_range (vrange &r, edge e, tree name, enum rfd_mode mode)
>  {
>    exit_range (r, name, e->src, mode);
>    // If this is not an abnormal edge, check for side effects on exit.
> @@ -961,7 +970,7 @@ ranger_cache::edge_range (irange &r, edge e, tree name, enum rfd_mode mode)
>  // Implement range_of_expr.
>
>  bool
> -ranger_cache::range_of_expr (irange &r, tree name, gimple *stmt)
> +ranger_cache::range_of_expr (vrange &r, tree name, gimple *stmt)
>  {
>    if (!gimple_range_ssa_p (name))
>      {
> @@ -985,7 +994,7 @@ ranger_cache::range_of_expr (irange &r, tree name, gimple *stmt)
>  // the current cache values.
>
>  bool
> -ranger_cache::range_on_edge (irange &r, edge e, tree expr)
> +ranger_cache::range_on_edge (vrange &r, edge e, tree expr)
>  {
>    if (gimple_range_ssa_p (expr))
>      return edge_range (r, e, expr, RFD_NONE);
> @@ -997,7 +1006,7 @@ ranger_cache::range_on_edge (irange &r, edge e, tree expr)
>  // def block for NAME.  Otherwise, return false if the cache is empty.
>
>  bool
> -ranger_cache::block_range (irange &r, basic_block bb, tree name, bool calc)
> +ranger_cache::block_range (vrange &r, basic_block bb, tree name, bool calc)
>  {
>    gcc_checking_assert (gimple_range_ssa_p (name));
>
> @@ -1041,9 +1050,10 @@ ranger_cache::propagate_cache (tree name)
>    basic_block bb;
>    edge_iterator ei;
>    edge e;
> -  int_range_max new_range;
> -  int_range_max current_range;
> -  int_range_max e_range;
> +  tree type = TREE_TYPE (name);
> +  tmp_range new_range (type);
> +  tmp_range current_range (type);
> +  tmp_range e_range (type);
>
>    // Process each block by seeing if its calculated range on entry is
>    // the same as its cached value. If there is a difference, update
> @@ -1178,8 +1188,8 @@ ranger_cache::fill_block_cache (tree name, basic_block bb, basic_block def_bb)
>  {
>    edge_iterator ei;
>    edge e;
> -  int_range_max block_result;
> -  int_range_max undefined;
> +  tmp_range block_result (TREE_TYPE (name));
> +  tmp_range undefined (TREE_TYPE (name));
>
>    // At this point we shouldn't be looking at the def, entry or exit block.
>    gcc_checking_assert (bb != def_bb && bb != ENTRY_BLOCK_PTR_FOR_FN (cfun) &&
> @@ -1232,7 +1242,7 @@ ranger_cache::fill_block_cache (tree name, basic_block bb, basic_block def_bb)
>        FOR_EACH_EDGE (e, ei, node->preds)
>         {
>           basic_block pred = e->src;
> -         int_range_max r;
> +         tmp_range r (TREE_TYPE (name));
>
>           if (DEBUG_RANGE_CACHE)
>             fprintf (dump_file, "  %d->%d ",e->src->index, e->dest->index);
> @@ -1306,7 +1316,7 @@ ranger_cache::fill_block_cache (tree name, basic_block bb, basic_block def_bb)
>  // dominator tree based on MODE.
>
>  bool
> -ranger_cache::range_from_dom (irange &r, tree name, basic_block start_bb,
> +ranger_cache::range_from_dom (vrange &r, tree name, basic_block start_bb,
>                               enum rfd_mode mode)
>  {
>    if (mode == RFD_NONE || !dom_info_available_p (CDI_DOMINATORS))
> diff --git a/gcc/gimple-range-cache.h b/gcc/gimple-range-cache.h
> index 2472cd04f47..d17950c7154 100644
> --- a/gcc/gimple-range-cache.h
> +++ b/gcc/gimple-range-cache.h
> @@ -34,8 +34,8 @@ public:
>    block_range_cache ();
>    ~block_range_cache ();
>
> -  bool set_bb_range (tree name, const_basic_block bb, const irange &r);
> -  bool get_bb_range (irange &r, tree name, const_basic_block bb);
> +  bool set_bb_range (tree name, const_basic_block bb, const vrange &v);
> +  bool get_bb_range (vrange &v, tree name, const_basic_block bb);
>    bool bb_range_p (tree name, const_basic_block bb);
>
>    void dump (FILE *f);
> @@ -57,13 +57,13 @@ class ssa_global_cache
>  public:
>    ssa_global_cache ();
>    ~ssa_global_cache ();
> -  bool get_global_range (irange &r, tree name) const;
> -  bool set_global_range (tree name, const irange &r);
> +  bool get_global_range (vrange &r, tree name) const;
> +  bool set_global_range (tree name, const vrange &r);
>    void clear_global_range (tree name);
>    void clear ();
>    void dump (FILE *f = stderr);
>  private:
> -  vec<irange *> m_tab;
> +  vec<vrange *> m_tab;
>    vrange_allocator *m_range_allocator;
>  };
>
> @@ -77,13 +77,13 @@ public:
>    ranger_cache (int not_executable_flag, bool use_imm_uses);
>    ~ranger_cache ();
>
> -  virtual bool range_of_expr (irange &r, tree name, gimple *stmt);
> -  virtual bool range_on_edge (irange &r, edge e, tree expr);
> -  bool block_range (irange &r, basic_block bb, tree name, bool calc = true);
> +  virtual bool range_of_expr (vrange &r, tree name, gimple *stmt);
> +  virtual bool range_on_edge (vrange &r, edge e, tree expr);
> +  bool block_range (vrange &r, basic_block bb, tree name, bool calc = true);
>
> -  bool get_global_range (irange &r, tree name) const;
> -  bool get_global_range (irange &r, tree name, bool &current_p);
> -  void set_global_range (tree name, const irange &r);
> +  bool get_global_range (vrange &r, tree name) const;
> +  bool get_global_range (vrange &r, tree name, bool &current_p);
> +  void set_global_range (tree name, const vrange &r);
>
>    void propagate_updated_value (tree name, basic_block bb);
>
> @@ -106,11 +106,11 @@ private:
>        RFD_READ_ONLY,   // Scan DOM tree, do not write to cache.
>        RFD_FILL         // Scan DOM tree, updating important nodes.
>      };
> -  bool range_from_dom (irange &r, tree name, basic_block bb, enum rfd_mode);
> -  void range_of_def (irange &r, tree name, basic_block bb = NULL);
> -  void entry_range (irange &r, tree expr, basic_block bb, enum rfd_mode);
> -  void exit_range (irange &r, tree expr, basic_block bb, enum rfd_mode);
> -  bool edge_range (irange &r, edge e, tree name, enum rfd_mode);
> +  bool range_from_dom (vrange &r, tree name, basic_block bb, enum rfd_mode);
> +  void range_of_def (vrange &r, tree name, basic_block bb = NULL);
> +  void entry_range (vrange &r, tree expr, basic_block bb, enum rfd_mode);
> +  void exit_range (vrange &r, tree expr, basic_block bb, enum rfd_mode);
> +  bool edge_range (vrange &r, edge e, tree name, enum rfd_mode);
>
>    vec<basic_block> m_workback;
>    class update_list *m_update;
> diff --git a/gcc/gimple-range-edge.cc b/gcc/gimple-range-edge.cc
> index 5264e627c9a..6fe33408f7e 100644
> --- a/gcc/gimple-range-edge.cc
> +++ b/gcc/gimple-range-edge.cc
> @@ -83,11 +83,8 @@ gimple_outgoing_range::~gimple_outgoing_range ()
>  // Use a cached value if it exists, or calculate it if not.
>
>  bool
> -gimple_outgoing_range::get_edge_range (irange &r, gimple *s, edge e)
> +gimple_outgoing_range::switch_edge_range (irange &r, gswitch *sw, edge e)
>  {
> -  gcc_checking_assert (is_a<gswitch *> (s));
> -  gswitch *sw = as_a<gswitch *> (s);
> -
>    // ADA currently has cases where the index is 64 bits and the case
>    // arguments are 32 bit, causing a trap when we create a case_range.
>    // Until this is resolved (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87798)
> @@ -204,12 +201,9 @@ gimple_outgoing_range::edge_range_p (irange &r, edge e)
>
>    gcc_checking_assert (is_a<gswitch *> (s));
>    gswitch *sw = as_a<gswitch *> (s);
> -  tree type = TREE_TYPE (gimple_switch_index (sw));
> -
> -  if (!irange::supports_type_p (type))
> -    return NULL;
>
> -  if (get_edge_range (r, sw, e))
> +  // Switches can only be integers.
> +  if (switch_edge_range (as_a <irange> (r), sw, e))
>      return s;
>
>    return NULL;
> diff --git a/gcc/gimple-range-edge.h b/gcc/gimple-range-edge.h
> index ce383b0aa6f..a9c4af8715b 100644
> --- a/gcc/gimple-range-edge.h
> +++ b/gcc/gimple-range-edge.h
> @@ -43,7 +43,7 @@ public:
>    gimple *edge_range_p (irange &r, edge e);
>  private:
>    void calc_switch_ranges (gswitch *sw);
> -  bool get_edge_range (irange &r, gimple *s, edge e);
> +  bool switch_edge_range (irange &r, gswitch *sw, edge e);
>
>    int m_max_edges;
>    hash_map<edge, irange *> *m_edge_table;
> diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc
> index c53d2863d5e..7fed5a99513 100644
> --- a/gcc/gimple-range-fold.cc
> +++ b/gcc/gimple-range-fold.cc
> @@ -60,7 +60,7 @@ fur_source::fur_source (range_query *q)
>  // Invoke range_of_expr on EXPR.
>
>  bool
> -fur_source::get_operand (irange &r, tree expr)
> +fur_source::get_operand (vrange &r, tree expr)
>  {
>    return m_query->range_of_expr (r, expr);
>  }
> @@ -69,7 +69,7 @@ fur_source::get_operand (irange &r, tree expr)
>  // range_query to get the range on the edge.
>
>  bool
> -fur_source::get_phi_operand (irange &r, tree expr, edge e)
> +fur_source::get_phi_operand (vrange &r, tree expr, edge e)
>  {
>    return m_query->range_on_edge (r, e, expr);
>  }
> @@ -109,8 +109,8 @@ class fur_edge : public fur_source
>  {
>  public:
>    fur_edge (edge e, range_query *q = NULL);
> -  virtual bool get_operand (irange &r, tree expr) override;
> -  virtual bool get_phi_operand (irange &r, tree expr, edge e) override;
> +  virtual bool get_operand (vrange &r, tree expr) override;
> +  virtual bool get_phi_operand (vrange &r, tree expr, edge e) override;
>  private:
>    edge m_edge;
>  };
> @@ -126,7 +126,7 @@ fur_edge::fur_edge (edge e, range_query *q) : fur_source (q)
>  // Get the value of EXPR on edge m_edge.
>
>  bool
> -fur_edge::get_operand (irange &r, tree expr)
> +fur_edge::get_operand (vrange &r, tree expr)
>  {
>    return m_query->range_on_edge (r, m_edge, expr);
>  }
> @@ -135,7 +135,7 @@ fur_edge::get_operand (irange &r, tree expr)
>  // range_query to get the range on the edge.
>
>  bool
> -fur_edge::get_phi_operand (irange &r, tree expr, edge e)
> +fur_edge::get_phi_operand (vrange &r, tree expr, edge e)
>  {
>    // Edge to edge recalculations not supoprted yet, until we sort it out.
>    gcc_checking_assert (e == m_edge);
> @@ -152,7 +152,7 @@ fur_stmt::fur_stmt (gimple *s, range_query *q) : fur_source (q)
>  // Retreive range of EXPR as it occurs as a use on stmt M_STMT.
>
>  bool
> -fur_stmt::get_operand (irange &r, tree expr)
> +fur_stmt::get_operand (vrange &r, tree expr)
>  {
>    return m_query->range_of_expr (r, expr, m_stmt);
>  }
> @@ -161,7 +161,7 @@ fur_stmt::get_operand (irange &r, tree expr)
>  // range_query to get the range on the edge.
>
>  bool
> -fur_stmt::get_phi_operand (irange &r, tree expr, edge e)
> +fur_stmt::get_phi_operand (vrange &r, tree expr, edge e)
>  {
>    // Pick up the range of expr from edge E.
>    fur_edge e_src (e, m_query);
> @@ -214,42 +214,42 @@ fur_depend::register_relation (edge e, relation_kind k, tree op1, tree op2)
>  class fur_list : public fur_source
>  {
>  public:
> -  fur_list (irange &r1);
> -  fur_list (irange &r1, irange &r2);
> -  fur_list (unsigned num, irange *list);
> -  virtual bool get_operand (irange &r, tree expr) override;
> -  virtual bool get_phi_operand (irange &r, tree expr, edge e) override;
> +  fur_list (vrange &r1);
> +  fur_list (vrange &r1, vrange &r2);
> +  fur_list (unsigned num, vrange **list);
> +  virtual bool get_operand (vrange &r, tree expr) override;
> +  virtual bool get_phi_operand (vrange &r, tree expr, edge e) override;
>  private:
> -  int_range_max m_local[2];
> -  irange *m_list;
> +  vrange *m_local[2];
> +  vrange **m_list;
>    unsigned m_index;
>    unsigned m_limit;
>  };
>
>  // One range supplied for unary operations.
>
> -fur_list::fur_list (irange &r1) : fur_source (NULL)
> +fur_list::fur_list (vrange &r1) : fur_source (NULL)
>  {
>    m_list = m_local;
>    m_index = 0;
>    m_limit = 1;
> -  m_local[0] = r1;
> +  m_local[0] = &r1;
>  }
>
>  // Two ranges supplied for binary operations.
>
> -fur_list::fur_list (irange &r1, irange &r2) : fur_source (NULL)
> +fur_list::fur_list (vrange &r1, vrange &r2) : fur_source (NULL)
>  {
>    m_list = m_local;
>    m_index = 0;
>    m_limit = 2;
> -  m_local[0] = r1;
> -  m_local[1] = r2;
> +  m_local[0] = &r1;
> +  m_local[1] = &r2;
>  }
>
>  // Arbitrary number of ranges in a vector.
>
> -fur_list::fur_list (unsigned num, irange *list) : fur_source (NULL)
> +fur_list::fur_list (unsigned num, vrange **list) : fur_source (NULL)
>  {
>    m_list = list;
>    m_index = 0;
> @@ -259,18 +259,18 @@ fur_list::fur_list (unsigned num, irange *list) : fur_source (NULL)
>  // Get the next operand from the vector, ensure types are compatible.
>
>  bool
> -fur_list::get_operand (irange &r, tree expr)
> +fur_list::get_operand (vrange &r, tree expr)
>  {
>    if (m_index >= m_limit)
>      return m_query->range_of_expr (r, expr);
> -  r = m_list[m_index++];
> +  r = *m_list[m_index++];
>    gcc_checking_assert (range_compatible_p (TREE_TYPE (expr), r.type ()));
>    return true;
>  }
>
>  // This will simply pick the next operand from the vector.
>  bool
> -fur_list::get_phi_operand (irange &r, tree expr, edge e ATTRIBUTE_UNUSED)
> +fur_list::get_phi_operand (vrange &r, tree expr, edge e ATTRIBUTE_UNUSED)
>  {
>    return get_operand (r, expr);
>  }
> @@ -278,7 +278,7 @@ fur_list::get_phi_operand (irange &r, tree expr, edge e ATTRIBUTE_UNUSED)
>  // Fold stmt S into range R using R1 as the first operand.
>
>  bool
> -fold_range (irange &r, gimple *s, irange &r1)
> +fold_range (vrange &r, gimple *s, vrange &r1)
>  {
>    fold_using_range f;
>    fur_list src (r1);
> @@ -288,7 +288,7 @@ fold_range (irange &r, gimple *s, irange &r1)
>  // Fold stmt S into range R using R1  and R2 as the first two operands.
>
>  bool
> -fold_range (irange &r, gimple *s, irange &r1, irange &r2)
> +fold_range (vrange &r, gimple *s, vrange &r1, vrange &r2)
>  {
>    fold_using_range f;
>    fur_list src (r1, r2);
> @@ -299,7 +299,7 @@ fold_range (irange &r, gimple *s, irange &r1, irange &r2)
>  // operands encountered.
>
>  bool
> -fold_range (irange &r, gimple *s, unsigned num_elements, irange *vector)
> +fold_range (vrange &r, gimple *s, unsigned num_elements, vrange **vector)
>  {
>    fold_using_range f;
>    fur_list src (num_elements, vector);
> @@ -309,7 +309,7 @@ fold_range (irange &r, gimple *s, unsigned num_elements, irange *vector)
>  // Fold stmt S into range R using range query Q.
>
>  bool
> -fold_range (irange &r, gimple *s, range_query *q)
> +fold_range (vrange &r, gimple *s, range_query *q)
>  {
>    fold_using_range f;
>    fur_stmt src (s, q);
> @@ -319,7 +319,7 @@ fold_range (irange &r, gimple *s, range_query *q)
>  // Recalculate stmt S into R using range query Q as if it were on edge ON_EDGE.
>
>  bool
> -fold_range (irange &r, gimple *s, edge on_edge, range_query *q)
> +fold_range (vrange &r, gimple *s, edge on_edge, range_query *q)
>  {
>    fold_using_range f;
>    fur_edge src (on_edge, q);
> @@ -370,7 +370,7 @@ adjust_pointer_diff_expr (irange &res, const gimple *diff_stmt)
>  // Adjust the range for an IMAGPART_EXPR.
>
>  static void
> -adjust_imagpart_expr (irange &res, const gimple *stmt)
> +adjust_imagpart_expr (vrange &res, const gimple *stmt)
>  {
>    tree name = TREE_OPERAND (gimple_assign_rhs1 (stmt), 0);
>
> @@ -413,7 +413,7 @@ adjust_imagpart_expr (irange &res, const gimple *stmt)
>  // Adjust the range for a REALPART_EXPR.
>
>  static void
> -adjust_realpart_expr (irange &res, const gimple *stmt)
> +adjust_realpart_expr (vrange &res, const gimple *stmt)
>  {
>    tree name = TREE_OPERAND (gimple_assign_rhs1 (stmt), 0);
>
> @@ -442,12 +442,12 @@ adjust_realpart_expr (irange &res, const gimple *stmt)
>  // this statement.
>
>  static void
> -gimple_range_adjustment (irange &res, const gimple *stmt)
> +gimple_range_adjustment (vrange &res, const gimple *stmt)
>  {
>    switch (gimple_expr_code (stmt))
>      {
>      case POINTER_DIFF_EXPR:
> -      adjust_pointer_diff_expr (res, stmt);
> +      adjust_pointer_diff_expr (as_a <irange> (res), stmt);
>        return;
>
>      case IMAGPART_EXPR:
> @@ -536,7 +536,7 @@ gimple_range_operand2 (const gimple *stmt)
>  // be calculated, return false.
>
>  bool
> -fold_using_range::fold_stmt (irange &r, gimple *s, fur_source &src, tree name)
> +fold_using_range::fold_stmt (vrange &r, gimple *s, fur_source &src, tree name)
>  {
>    bool res = false;
>    // If name and S are specified, make sure it is an LHS of S.
> @@ -549,7 +549,7 @@ fold_using_range::fold_stmt (irange &r, gimple *s, fur_source &src, tree name)
>    // Process addresses.
>    if (gimple_code (s) == GIMPLE_ASSIGN
>        && gimple_assign_rhs_code (s) == ADDR_EXPR)
> -    return range_of_address (r, s, src);
> +    return range_of_address (as_a <irange> (r), s, src);
>
>    if (range_op_handler (s))
>      res = range_of_range_op (r, s, src);
> @@ -566,7 +566,7 @@ fold_using_range::fold_stmt (irange &r, gimple *s, fur_source &src, tree name)
>        if (!name || !gimple_range_ssa_p (name))
>         return false;
>        // We don't understand the stmt, so return the global range.
> -      r = gimple_range_global (name);
> +      gimple_range_global (r, name);
>        return true;
>      }
>
> @@ -587,9 +587,8 @@ fold_using_range::fold_stmt (irange &r, gimple *s, fur_source &src, tree name)
>  // If a range cannot be calculated, return false.
>
>  bool
> -fold_using_range::range_of_range_op (irange &r, gimple *s, fur_source &src)
> +fold_using_range::range_of_range_op (vrange &r, gimple *s, fur_source &src)
>  {
> -  int_range_max range1, range2;
>    tree type = gimple_range_type (s);
>    if (!type)
>      return false;
> @@ -599,13 +598,16 @@ fold_using_range::range_of_range_op (irange &r, gimple *s, fur_source &src)
>    tree lhs = gimple_get_lhs (s);
>    tree op1 = gimple_range_operand1 (s);
>    tree op2 = gimple_range_operand2 (s);
> +  tmp_range range1 (TREE_TYPE (op1));
> +  tmp_range range2;
>
>    if (src.get_operand (range1, op1))
>      {
>        if (!op2)
>         {
>           // Fold range, and register any dependency if available.
> -         int_range<2> r2 (type);
> +         tmp_range r2 (type);
> +         r2.set_varying (type);
>           handler.fold_range (r, type, range1, r2);
>           if (lhs && gimple_range_ssa_p (op1))
>             {
> @@ -617,7 +619,8 @@ fold_using_range::range_of_range_op (irange &r, gimple *s, fur_source &src)
>                 src.register_relation (s, rel, lhs, op1);
>             }
>         }
> -      else if (src.get_operand (range2, op2))
> +      else if (range2.init (TREE_TYPE (op2))
> +              && src.get_operand (range2, op2))
>         {
>           relation_kind rel = src.query_relation (op1, op2);
>           if (dump_file && (dump_flags & TDF_DETAILS) && rel != VREL_VARYING)
> @@ -630,7 +633,8 @@ fold_using_range::range_of_range_op (irange &r, gimple *s, fur_source &src)
>             }
>           // Fold range, and register any dependency if available.
>           handler.fold_range (r, type, range1, range2, rel);
> -         relation_fold_and_or (r, s, src);
> +         if (irange::supports_type_p (type))
> +           relation_fold_and_or (as_a <irange> (r), s, src);
>           if (lhs)
>             {
>               if (src.gori ())
> @@ -663,7 +667,8 @@ fold_using_range::range_of_range_op (irange &r, gimple *s, fur_source &src)
>                 e0 = NULL;
>               if (!single_pred_p (e1->dest))
>                 e1 = NULL;
> -             src.register_outgoing_edges (as_a<gcond *> (s), r, e0, e1);
> +             src.register_outgoing_edges (as_a<gcond *> (s),
> +                                          as_a <irange> (r), e0, e1);
>             }
>         }
>        else
> @@ -729,12 +734,12 @@ fold_using_range::range_of_address (irange &r, gimple *stmt, fur_source &src)
>         {
>           /* For -fdelete-null-pointer-checks -fno-wrapv-pointer we don't
>              allow going from non-NULL pointer to NULL.  */
> -         if (!range_includes_zero_p (&r))
> +         if (r.undefined_p () || !r.contains_p (build_zero_cst (r.type ())))
>             {
>               /* We could here instead adjust r by off >> LOG2_BITS_PER_UNIT
>                  using POINTER_PLUS_EXPR if off_cst and just fall back to
>                  this.  */
> -             r = range_nonzero (TREE_TYPE (gimple_assign_rhs1 (stmt)));
> +             r.set_nonzero (TREE_TYPE (gimple_assign_rhs1 (stmt)));
>               return true;
>             }
>         }
> @@ -746,22 +751,22 @@ fold_using_range::range_of_address (irange &r, gimple *stmt, fur_source &src)
>           && known_ne (off, 0)
>           && (flag_delete_null_pointer_checks || known_gt (off, 0)))
>         {
> -         r = range_nonzero (TREE_TYPE (gimple_assign_rhs1 (stmt)));
> +         r.set_nonzero (TREE_TYPE (gimple_assign_rhs1 (stmt)));
>           return true;
>         }
> -      r = int_range<2> (TREE_TYPE (gimple_assign_rhs1 (stmt)));
> +      r.set_varying (TREE_TYPE (gimple_assign_rhs1 (stmt)));
>        return true;
>      }
>
>    // Handle "= &a".
>    if (tree_single_nonzero_warnv_p (expr, &strict_overflow_p))
>      {
> -      r = range_nonzero (TREE_TYPE (gimple_assign_rhs1 (stmt)));
> +      r.set_nonzero (TREE_TYPE (gimple_assign_rhs1 (stmt)));
>        return true;
>      }
>
>    // Otherwise return varying.
> -  r = int_range<2> (TREE_TYPE (gimple_assign_rhs1 (stmt)));
> +  r.set_varying (TREE_TYPE (gimple_assign_rhs1 (stmt)));
>    return true;
>  }
>
> @@ -769,12 +774,12 @@ fold_using_range::range_of_address (irange &r, gimple *stmt, fur_source &src)
>  // If a range cannot be calculated, return false.
>
>  bool
> -fold_using_range::range_of_phi (irange &r, gphi *phi, fur_source &src)
> +fold_using_range::range_of_phi (vrange &r, gphi *phi, fur_source &src)
>  {
>    tree phi_def = gimple_phi_result (phi);
>    tree type = gimple_range_type (phi);
> -  int_range_max arg_range;
> -  int_range_max equiv_range;
> +  tmp_range arg_range (type);
> +  tmp_range equiv_range (type);
>    unsigned x;
>
>    if (!type)
> @@ -881,7 +886,7 @@ fold_using_range::range_of_phi (irange &r, gphi *phi, fur_source &src)
>  // If a range cannot be calculated, return false.
>
>  bool
> -fold_using_range::range_of_call (irange &r, gcall *call, fur_source &src)
> +fold_using_range::range_of_call (vrange &r, gcall *call, fur_source &src)
>  {
>    tree type = gimple_range_type (call);
>    if (!type)
> @@ -893,18 +898,18 @@ fold_using_range::range_of_call (irange &r, gcall *call, fur_source &src)
>    if (range_of_builtin_call (r, call, src))
>      ;
>    else if (gimple_stmt_nonnegative_warnv_p (call, &strict_overflow_p))
> -    r.set (build_int_cst (type, 0), TYPE_MAX_VALUE (type));
> +    r.set_nonnegative (type);
>    else if (gimple_call_nonnull_result_p (call)
>            || gimple_call_nonnull_arg (call))
> -    r = range_nonzero (type);
> +    r.set_nonzero (type);
>    else
>      r.set_varying (type);
>
>    // If there is an LHS, intersect that with what is known.
>    if (lhs)
>      {
> -      value_range def;
> -      def = gimple_range_global (lhs);
> +      tmp_range def (TREE_TYPE (lhs));
> +      gimple_range_global (def, lhs);
>        r.intersect (def);
>      }
>    return true;
> @@ -971,13 +976,30 @@ get_letter_range (tree type, irange &lowers, irange &uppers)
>  // TRUE.  Otherwise return FALSE.
>
>  bool
> -fold_using_range::range_of_builtin_call (irange &r, gcall *call,
> +fold_using_range::range_of_builtin_call (vrange &r, gcall *call,
>                                          fur_source &src)
>  {
>    combined_fn func = gimple_call_combined_fn (call);
>    if (func == CFN_LAST)
>      return false;
>
> +  tree type = gimple_range_type (call);
> +  gcc_checking_assert (type);
> +
> +  if (irange::supports_type_p (type))
> +    return range_of_builtin_int_call (as_a <irange> (r), call, src);
> +
> +  return false;
> +}
> +
> +bool
> +fold_using_range::range_of_builtin_int_call (irange &r, gcall *call,
> +                                            fur_source &src)
> +{
> +  combined_fn func = gimple_call_combined_fn (call);
> +  if (func == CFN_LAST)
> +    return false;
> +
>    tree type = gimple_range_type (call);
>    tree arg;
>    int mini, maxi, zerov = 0, prec;
> @@ -1256,9 +1278,8 @@ fold_using_range::range_of_builtin_call (irange &r, gcall *call,
>  // If a range cannot be calculated, return false.
>
>  bool
> -fold_using_range::range_of_cond_expr  (irange &r, gassign *s, fur_source &src)
> +fold_using_range::range_of_cond_expr  (vrange &r, gassign *s, fur_source &src)
>  {
> -  int_range_max cond_range, range1, range2;
>    tree cond = gimple_assign_rhs1 (s);
>    tree op1 = gimple_assign_rhs2 (s);
>    tree op2 = gimple_assign_rhs3 (s);
> @@ -1267,6 +1288,9 @@ fold_using_range::range_of_cond_expr  (irange &r, gassign *s, fur_source &src)
>    if (!type)
>      return false;
>
> +  tmp_range range1 (TREE_TYPE (op1));
> +  tmp_range range2 (TREE_TYPE (op2));
> +  tmp_range cond_range (TREE_TYPE (cond));
>    gcc_checking_assert (gimple_assign_rhs_code (s) == COND_EXPR);
>    gcc_checking_assert (range_compatible_p (TREE_TYPE (op1), TREE_TYPE (op2)));
>    src.get_operand (cond_range, cond);
> @@ -1438,7 +1462,6 @@ fold_using_range::relation_fold_and_or (irange& lhs_range, gimple *s,
>  void
>  fur_source::register_outgoing_edges (gcond *s, irange &lhs_range, edge e0, edge e1)
>  {
> -  int_range_max r;
>    int_range<2> e0_range, e1_range;
>    tree name;
>    basic_block bb = gimple_bb (s);
> @@ -1505,6 +1528,7 @@ fur_source::register_outgoing_edges (gcond *s, irange &lhs_range, edge e0, edge
>         continue;
>        tree ssa1 = gimple_range_ssa_p (gimple_range_operand1 (stmt));
>        tree ssa2 = gimple_range_ssa_p (gimple_range_operand2 (stmt));
> +      tmp_range r (TREE_TYPE (name));
>        if (ssa1 && ssa2)
>         {
>           if (e0 && gori ()->outgoing_edge_range_p (r, e0, name, *m_query)
> diff --git a/gcc/gimple-range-fold.h b/gcc/gimple-range-fold.h
> index 4b5d4b6e0b8..df24280ee40 100644
> --- a/gcc/gimple-range-fold.h
> +++ b/gcc/gimple-range-fold.h
> @@ -23,7 +23,7 @@ along with GCC; see the file COPYING3.  If not see
>  #define GCC_GIMPLE_RANGE_FOLD_H
>
>  // This file is the main include point for gimple range folding.
> -// These routines will fold stmt S into the result irange R.
> +// These routines will fold stmt S into the result range R.
>  // Any ssa_names on the stmt will be calculated using the range_query
>  // parameter via a call to range_of_expr.
>  // If no range_query is provided, current global range info will be used.
> @@ -31,15 +31,15 @@ along with GCC; see the file COPYING3.  If not see
>  // it appeared on that edge.
>
>  // Fold stmt S into range R using range query Q.
> -bool fold_range (irange &r, gimple *s, range_query *q = NULL);
> +bool fold_range (vrange &r, gimple *s, range_query *q = NULL);
>  // Recalculate stmt S into R using range query Q as if it were on edge ON_EDGE.
> -bool fold_range (irange &r, gimple *s, edge on_edge, range_query *q = NULL);
> +bool fold_range (vrange &v, gimple *s, edge on_edge, range_query *q = NULL);
>
>  // These routines the operands to be specified when manually folding.
>  // Any excess queries will be drawn from the current range_query.
> -bool fold_range (irange &r, gimple *s, irange &r1);
> -bool fold_range (irange &r, gimple *s, irange &r1, irange &r2);
> -bool fold_range (irange &r, gimple *s, unsigned num_elements, irange *vector);
> +bool fold_range (vrange &r, gimple *s, vrange &r1);
> +bool fold_range (vrange &r, gimple *s, vrange &r1, vrange &r2);
> +bool fold_range (vrange &r, gimple *s, unsigned num_elements, vrange **vector);
>
>  // Return the type of range which statement S calculates.  If the type is
>  // unsupported or no type can be determined, return NULL_TREE.
> @@ -66,7 +66,7 @@ gimple_range_type (const gimple *s)
>             type = TREE_TYPE (type);
>         }
>      }
> -  if (type && irange::supports_type_p (type))
> +  if (type && vrange::supports_type_p (type))
>      return type;
>    return NULL_TREE;
>  }
> @@ -79,7 +79,7 @@ gimple_range_ssa_p (tree exp)
>    if (exp && TREE_CODE (exp) == SSA_NAME &&
>        !SSA_NAME_IS_VIRTUAL_OPERAND (exp) &&
>        !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (exp) &&
> -      irange::supports_type_p (TREE_TYPE (exp)))
> +      vrange::supports_type_p (TREE_TYPE (exp)))
>      return exp;
>    return NULL_TREE;
>  }
> @@ -108,8 +108,8 @@ public:
>    fur_source (range_query *q = NULL);
>    inline range_query *query () { return m_query; }
>    inline class gori_compute *gori () { return m_gori; };
> -  virtual bool get_operand (irange &r, tree expr);
> -  virtual bool get_phi_operand (irange &r, tree expr, edge e);
> +  virtual bool get_operand (vrange &r, tree expr);
> +  virtual bool get_phi_operand (vrange &r, tree expr, edge e);
>    virtual relation_kind query_relation (tree op1, tree op2);
>    virtual void register_relation (gimple *stmt, relation_kind k, tree op1,
>                                   tree op2);
> @@ -128,8 +128,8 @@ class fur_stmt : public fur_source
>  {
>  public:
>    fur_stmt (gimple *s, range_query *q = NULL);
> -  virtual bool get_operand (irange &r, tree expr) override;
> -  virtual bool get_phi_operand (irange &r, tree expr, edge e) override;
> +  virtual bool get_operand (vrange &r, tree expr) override;
> +  virtual bool get_phi_operand (vrange &r, tree expr, edge e) override;
>    virtual relation_kind query_relation (tree op1, tree op2) override;
>  private:
>    gimple *m_stmt;
> @@ -161,17 +161,18 @@ extern tree gimple_range_operand2 (const gimple *s);
>  class fold_using_range
>  {
>  public:
> -  bool fold_stmt (irange &r, gimple *s, class fur_source &src,
> +  bool fold_stmt (vrange &r, gimple *s, class fur_source &src,
>                   tree name = NULL_TREE);
>  protected:
> -  bool range_of_range_op (irange &r, gimple *s, fur_source &src);
> -  bool range_of_call (irange &r, gcall *call, fur_source &src);
> -  bool range_of_cond_expr (irange &r, gassign* cond, fur_source &src);
> +  bool range_of_range_op (vrange &r, gimple *s, fur_source &src);
> +  bool range_of_call (vrange &r, gcall *call, fur_source &src);
> +  bool range_of_cond_expr (vrange &r, gassign* cond, fur_source &src);
>    bool range_of_address (irange &r, gimple *s, fur_source &src);
> -  bool range_of_builtin_call (irange &r, gcall *call, fur_source &src);
> +  bool range_of_builtin_call (vrange &r, gcall *call, fur_source &src);
> +  bool range_of_builtin_int_call (irange &r, gcall *call, fur_source &src);
>    void range_of_builtin_ubsan_call (irange &r, gcall *call, tree_code code,
>                                     fur_source &src);
> -  bool range_of_phi (irange &r, gphi *phi, fur_source &src);
> +  bool range_of_phi (vrange &r, gphi *phi, fur_source &src);
>    void range_of_ssa_name_with_loop_info (irange &, tree, class loop *, gphi *,
>                                          fur_source &src);
>    void relation_fold_and_or (irange& lhs_range, gimple *s, fur_source &src);
> diff --git a/gcc/gimple-range-gori.cc b/gcc/gimple-range-gori.cc
> index 0e0cf2128e7..47d0dab8cb9 100644
> --- a/gcc/gimple-range-gori.cc
> +++ b/gcc/gimple-range-gori.cc
> @@ -34,7 +34,7 @@ along with GCC; see the file COPYING3.  If not see
>  // LHS_RANGE.  Return false if nothing can be determined.
>
>  bool
> -gimple_range_calc_op1 (irange &r, const gimple *stmt, const irange &lhs_range)
> +gimple_range_calc_op1 (vrange &r, const gimple *stmt, const vrange &lhs_range)
>  {
>    gcc_checking_assert (gimple_num_ops (stmt) < 3);
>    // Give up on empty ranges.
> @@ -55,8 +55,8 @@ gimple_range_calc_op1 (irange &r, const gimple *stmt, const irange &lhs_range)
>  // nothing can be determined.
>
>  bool
> -gimple_range_calc_op1 (irange &r, const gimple *stmt,
> -                      const irange &lhs_range, const irange &op2_range)
> +gimple_range_calc_op1 (vrange &r, const gimple *stmt,
> +                      const vrange &lhs_range, const vrange &op2_range)
>  {
>    // Give up on empty ranges.
>    if (lhs_range.undefined_p ())
> @@ -86,8 +86,8 @@ gimple_range_calc_op1 (irange &r, const gimple *stmt,
>  // nothing can be determined.
>
>  bool
> -gimple_range_calc_op2 (irange &r, const gimple *stmt,
> -                      const irange &lhs_range, const irange &op1_range)
> +gimple_range_calc_op2 (vrange &r, const gimple *stmt,
> +                      const vrange &lhs_range, const vrange &op1_range)
>  {
>    // Give up on empty ranges.
>    if (lhs_range.undefined_p ())
> @@ -663,8 +663,8 @@ gori_compute::gori_compute (int not_executable_flag)
>  // was not resolvable.
>
>  bool
> -gori_compute::compute_operand_range_switch (irange &r, gswitch *s,
> -                                           const irange &lhs,
> +gori_compute::compute_operand_range_switch (vrange &r, gswitch *s,
> +                                           const vrange &lhs,
>                                             tree name, fur_source &src)
>  {
>    tree op1 = gimple_switch_index (s);
> @@ -691,8 +691,8 @@ gori_compute::compute_operand_range_switch (irange &r, gswitch *s,
>  // store the evaluation in R, otherwise return FALSE.
>
>  bool
> -gori_compute::compute_operand_range (irange &r, gimple *stmt,
> -                                    const irange &lhs, tree name,
> +gori_compute::compute_operand_range (vrange &r, gimple *stmt,
> +                                    const vrange &lhs, tree name,
>                                      fur_source &src)
>  {
>    // If the lhs doesn't tell us anything, neither will unwinding further.
> @@ -743,13 +743,18 @@ gori_compute::compute_operand_range (irange &r, gimple *stmt,
>           print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
>         }
>
> -      int_range_max op1_trange, op1_frange;
> -      int_range_max op2_trange, op2_frange;
> -      compute_logical_operands (op1_trange, op1_frange, stmt, lhs,
> +      tree type = TREE_TYPE (name);
> +      tmp_range op1_trange (type), op1_frange (type);
> +      tmp_range op2_trange (type), op2_frange (type);
> +      compute_logical_operands (op1_trange, op1_frange, stmt,
> +                               as_a <irange> (lhs),
>                                 name, src, op1, op1_in_chain);
> -      compute_logical_operands (op2_trange, op2_frange, stmt, lhs,
> +      compute_logical_operands (op2_trange, op2_frange, stmt,
> +                               as_a <irange> (lhs),
>                                 name, src, op2, op2_in_chain);
> -      res = logical_combine (r, gimple_expr_code (stmt), lhs,
> +      res = logical_combine (r,
> +                            gimple_expr_code (stmt),
> +                            as_a <irange> (lhs),
>                              op1_trange, op1_frange, op2_trange, op2_frange);
>        if (idx)
>         tracer.trailer (idx, "compute_operand", res, name, r);
> @@ -789,10 +794,10 @@ range_is_either_true_or_false (const irange &r)
>  // the LHS.
>
>  bool
> -gori_compute::logical_combine (irange &r, enum tree_code code,
> +gori_compute::logical_combine (vrange &r, enum tree_code code,
>                                const irange &lhs,
> -                              const irange &op1_true, const irange &op1_false,
> -                              const irange &op2_true, const irange &op2_false)
> +                              const vrange &op1_true, const vrange &op1_false,
> +                              const vrange &op2_true, const vrange &op2_false)
>  {
>    if (op1_true.varying_p () && op1_false.varying_p ()
>        && op2_true.varying_p () && op2_false.varying_p ())
> @@ -868,7 +873,7 @@ gori_compute::logical_combine (irange &r, enum tree_code code,
>    if (!range_is_either_true_or_false (lhs))
>      {
>        bool res;
> -      int_range_max r1;
> +      tmp_range r1 (r);
>        if (logical_combine (r1, code, m_bool_zero, op1_true, op1_false,
>                            op2_true, op2_false)
>           && logical_combine (r, code, m_bool_one, op1_true, op1_false,
> @@ -898,11 +903,11 @@ gori_compute::logical_combine (irange &r, enum tree_code code,
>         else
>           {
>             // The FALSE side is the union of the other 3 cases.
> -           int_range_max ff (op1_false);
> +           tmp_range ff (op1_false);
>             ff.intersect (op2_false);
> -           int_range_max tf (op1_true);
> +           tmp_range tf (op1_true);
>             tf.intersect (op2_false);
> -           int_range_max ft (op1_false);
> +           tmp_range ft (op1_false);
>             ft.intersect (op2_true);
>             r = ff;
>             r.union_ (tf);
> @@ -925,11 +930,11 @@ gori_compute::logical_combine (irange &r, enum tree_code code,
>           {
>             // The TRUE side of an OR operation will be the union of
>             // the other three combinations.
> -           int_range_max tt (op1_true);
> +           tmp_range tt (op1_true);
>             tt.intersect (op2_true);
> -           int_range_max tf (op1_true);
> +           tmp_range tf (op1_true);
>             tf.intersect (op2_false);
> -           int_range_max ft (op1_false);
> +           tmp_range ft (op1_false);
>             ft.intersect (op2_true);
>             r = tt;
>             r.union_ (tf);
> @@ -951,7 +956,7 @@ gori_compute::logical_combine (irange &r, enum tree_code code,
>  // OP_IN_CHAIN is true.
>
>  void
> -gori_compute::compute_logical_operands (irange &true_range, irange &false_range,
> +gori_compute::compute_logical_operands (vrange &true_range, vrange &false_range,
>                                         gimple *stmt,
>                                         const irange &lhs,
>                                         tree name, fur_source &src,
> @@ -1007,13 +1012,15 @@ gori_compute::compute_logical_operands (irange &true_range, irange &false_range,
>  // R, or false if no range could be calculated.
>
>  bool
> -gori_compute::compute_operand1_range (irange &r, gimple *stmt,
> -                                     const irange &lhs, tree name,
> +gori_compute::compute_operand1_range (vrange &r, gimple *stmt,
> +                                     const vrange &lhs, tree name,
>                                       fur_source &src)
>  {
> -  int_range_max op1_range, op2_range;
>    tree op1 = gimple_range_operand1 (stmt);
>    tree op2 = gimple_range_operand2 (stmt);
> +  tmp_range op1_range (TREE_TYPE (op1));
> +  tmp_range tmp (TREE_TYPE (op1));
> +  tmp_range op2_range;
>
>    // Fetch the known range for op1 in this block.
>    src.get_operand (op1_range, op1);
> @@ -1021,8 +1028,9 @@ gori_compute::compute_operand1_range (irange &r, gimple *stmt,
>    // Now range-op calcuate and put that result in r.
>    if (op2)
>      {
> +      op2_range.init (TREE_TYPE (op2));
>        src.get_operand (op2_range, op2);
> -      if (!gimple_range_calc_op1 (r, stmt, lhs, op2_range))
> +      if (!gimple_range_calc_op1 (tmp, stmt, lhs, op2_range))
>         return false;
>      }
>    else
> @@ -1030,7 +1038,7 @@ gori_compute::compute_operand1_range (irange &r, gimple *stmt,
>        // We pass op1_range to the unary operation.  Nomally it's a
>        // hidden range_for_type parameter, but sometimes having the
>        // actual range can result in better information.
> -      if (!gimple_range_calc_op1 (r, stmt, lhs, op1_range))
> +      if (!gimple_range_calc_op1 (tmp, stmt, lhs, op1_range))
>         return false;
>      }
>
> @@ -1053,7 +1061,7 @@ gori_compute::compute_operand1_range (irange &r, gimple *stmt,
>        tracer.print (idx, "Computes ");
>        print_generic_expr (dump_file, op1, TDF_SLIM);
>        fprintf (dump_file, " = ");
> -      r.dump (dump_file);
> +      tmp.dump (dump_file);
>        fprintf (dump_file, " intersect Known range : ");
>        op1_range.dump (dump_file);
>        fputc ('\n', dump_file);
> @@ -1061,13 +1069,14 @@ gori_compute::compute_operand1_range (irange &r, gimple *stmt,
>    // Intersect the calculated result with the known result and return if done.
>    if (op1 == name)
>      {
> -      r.intersect (op1_range);
> +      tmp.intersect (op1_range);
> +      r = tmp;
>        if (idx)
>         tracer.trailer (idx, "produces ", true, name, r);
>        return true;
>      }
>    // If the calculation continues, we're using op1_range as the new LHS.
> -  op1_range.intersect (r);
> +  op1_range.intersect (tmp);
>
>    if (idx)
>      tracer.trailer (idx, "produces ", true, op1, op1_range);
> @@ -1084,19 +1093,21 @@ gori_compute::compute_operand1_range (irange &r, gimple *stmt,
>  // R, or false if no range could be calculated.
>
>  bool
> -gori_compute::compute_operand2_range (irange &r, gimple *stmt,
> -                                     const irange &lhs, tree name,
> +gori_compute::compute_operand2_range (vrange &r, gimple *stmt,
> +                                     const vrange &lhs, tree name,
>                                       fur_source &src)
>  {
> -  int_range_max op1_range, op2_range;
>    tree op1 = gimple_range_operand1 (stmt);
>    tree op2 = gimple_range_operand2 (stmt);
> +  tmp_range op1_range (TREE_TYPE (op1));
> +  tmp_range op2_range (TREE_TYPE (op2));
> +  tmp_range tmp (TREE_TYPE (op2));
>
>    src.get_operand (op1_range, op1);
>    src.get_operand (op2_range, op2);
>
>    // Intersect with range for op2 based on lhs and op1.
> -  if (!gimple_range_calc_op2 (r, stmt, lhs, op1_range))
> +  if (!gimple_range_calc_op2 (tmp, stmt, lhs, op1_range))
>      return false;
>
>    unsigned idx;
> @@ -1118,7 +1129,7 @@ gori_compute::compute_operand2_range (irange &r, gimple *stmt,
>        tracer.print (idx, "Computes ");
>        print_generic_expr (dump_file, op2, TDF_SLIM);
>        fprintf (dump_file, " = ");
> -      r.dump (dump_file);
> +      tmp.dump (dump_file);
>        fprintf (dump_file, " intersect Known range : ");
>        op2_range.dump (dump_file);
>        fputc ('\n', dump_file);
> @@ -1126,13 +1137,14 @@ gori_compute::compute_operand2_range (irange &r, gimple *stmt,
>    // Intersect the calculated result with the known result and return if done.
>    if (op2 == name)
>      {
> -      r.intersect (op2_range);
> +      tmp.intersect (op2_range);
> +      r = tmp;
>        if (idx)
>         tracer.trailer (idx, " produces ", true, NULL_TREE, r);
>        return true;
>      }
>    // If the calculation continues, we're using op2_range as the new LHS.
> -  op2_range.intersect (r);
> +  op2_range.intersect (tmp);
>
>    if (idx)
>      tracer.trailer (idx, " produces ", true, op2, op2_range);
> @@ -1149,13 +1161,13 @@ gori_compute::compute_operand2_range (irange &r, gimple *stmt,
>  // R, or false if no range could be calculated.
>
>  bool
> -gori_compute::compute_operand1_and_operand2_range (irange &r,
> +gori_compute::compute_operand1_and_operand2_range (vrange &r,
>                                                    gimple *stmt,
> -                                                  const irange &lhs,
> +                                                  const vrange &lhs,
>                                                    tree name,
>                                                    fur_source &src)
>  {
> -  int_range_max op_range;
> +  tmp_range op_range (TREE_TYPE (name));
>
>    // Calculate a good a range for op2.  Since op1 == op2, this will
>    // have already included whatever the actual range of name is.
> @@ -1236,10 +1248,9 @@ gori_compute::has_edge_range_p (tree name, edge e)
>  // control edge or NAME is not defined by this edge.
>
>  bool
> -gori_compute::outgoing_edge_range_p (irange &r, edge e, tree name,
> +gori_compute::outgoing_edge_range_p (vrange &r, edge e, tree name,
>                                      range_query &q)
>  {
> -  int_range_max lhs;
>    unsigned idx;
>
>    if ((e->flags & m_not_executable_flag))
> @@ -1252,6 +1263,7 @@ gori_compute::outgoing_edge_range_p (irange &r, edge e, tree name,
>      }
>
>    gcc_checking_assert (gimple_range_ssa_p (name));
> +  int_range_max lhs;
>    // Determine if there is an outgoing edge.
>    gimple *stmt = outgoing.edge_range_p (lhs, e);
>    if (!stmt)
> @@ -1312,10 +1324,9 @@ gori_compute::outgoing_edge_range_p (irange &r, edge e, tree name,
>  // edge and OP2 on the false edge.
>
>  bool
> -gori_compute::condexpr_adjust (irange &r1, irange &r2, gimple *, tree cond,
> +gori_compute::condexpr_adjust (vrange &r1, vrange &r2, gimple *, tree cond,
>                                tree op1, tree op2, fur_source &src)
>  {
> -  int_range_max tmp, cond_true, cond_false;
>    tree ssa1 = gimple_range_ssa_p (op1);
>    tree ssa2 = gimple_range_ssa_p (op2);
>    if (!ssa1 && !ssa2)
> @@ -1341,15 +1352,19 @@ gori_compute::condexpr_adjust (irange &r1, irange &r2, gimple *, tree cond,
>      return false;
>
>    // Pick up the current values of each part of the condition.
> -  int_range_max cl, cr;
> -  src.get_operand (cl, gimple_assign_rhs1 (cond_def));
> -  src.get_operand (cr, gimple_assign_rhs2 (cond_def));
> +  tree rhs1 = gimple_assign_rhs1 (cond_def);
> +  tree rhs2 = gimple_assign_rhs2 (cond_def);
> +  tmp_range cl (TREE_TYPE (rhs1));
> +  tmp_range cr (TREE_TYPE (rhs2));
> +  src.get_operand (cl, rhs1);
> +  src.get_operand (cr, rhs2);
>
>    tree cond_name = c1 ? c1 : c2;
>    gimple *def_stmt = SSA_NAME_DEF_STMT (cond_name);
>
>    // Evaluate the value of COND_NAME on the true and false edges, using either
>    // the op1 or op2 routines based on its location.
> +  tmp_range cond_true (type), cond_false (type);
>    if (c1)
>      {
>        if (!hand.op1_range (cond_false, type, m_bool_zero, cr))
> @@ -1380,6 +1395,7 @@ gori_compute::condexpr_adjust (irange &r1, irange &r2, gimple *, tree cond,
>      }
>
>     // Now solve for SSA1 or SSA2 if they are in the dependency chain.
> +  tmp_range tmp (type);
>     if (ssa1 && in_chain_p (ssa1, cond_name))
>      {
>        if (compute_operand_range (tmp, def_stmt, cond_true, ssa1, src))
> diff --git a/gcc/gimple-range-gori.h b/gcc/gimple-range-gori.h
> index 605884e2e53..f5f691fe424 100644
> --- a/gcc/gimple-range-gori.h
> +++ b/gcc/gimple-range-gori.h
> @@ -121,7 +121,7 @@ private:
>  //   on *ANY* edge that has been seen.  FALSE indicates that the global value
>  //   is applicable everywhere that has been processed.
>  //
> -// outgoing_edge_range_p (irange &range, edge e, tree name)
> +// outgoing_edge_range_p (vrange &range, edge e, tree name)
>  //   Actually does the calculation of RANGE for name on E
>  //   This represents application of whatever static range effect edge E
>  //   may have on NAME, not any cumulative effect.
> @@ -157,8 +157,8 @@ class gori_compute : public gori_map
>  {
>  public:
>    gori_compute (int not_executable_flag = 0);
> -  bool outgoing_edge_range_p (irange &r, edge e, tree name, range_query &q);
> -  bool condexpr_adjust (irange &r1, irange &r2, gimple *s, tree cond, tree op1,
> +  bool outgoing_edge_range_p (vrange &r, edge e, tree name, range_query &q);
> +  bool condexpr_adjust (vrange &r1, vrange &r2, gimple *s, tree cond, tree op1,
>                         tree op2, fur_source &src);
>    bool has_edge_range_p (tree name, basic_block bb = NULL);
>    bool has_edge_range_p (tree name, edge e);
> @@ -166,24 +166,24 @@ public:
>  private:
>    bool may_recompute_p (tree name, edge e);
>    bool may_recompute_p (tree name, basic_block bb = NULL);
> -  bool compute_operand_range (irange &r, gimple *stmt, const irange &lhs,
> +  bool compute_operand_range (vrange &r, gimple *stmt, const vrange &lhs,
>                               tree name, class fur_source &src);
> -  bool compute_operand_range_switch (irange &r, gswitch *s, const irange &lhs,
> +  bool compute_operand_range_switch (vrange &r, gswitch *s, const vrange &lhs,
>                                      tree name, fur_source &src);
> -  bool compute_operand1_range (irange &r, gimple *stmt, const irange &lhs,
> +  bool compute_operand1_range (vrange &r, gimple *stmt, const vrange &lhs,
>                                tree name, fur_source &src);
> -  bool compute_operand2_range (irange &r, gimple *stmt, const irange &lhs,
> +  bool compute_operand2_range (vrange &r, gimple *stmt, const vrange &lhs,
>                                tree name, fur_source &src);
> -  bool compute_operand1_and_operand2_range (irange &r, gimple *stmt,
> -                                           const irange &lhs, tree name,
> +  bool compute_operand1_and_operand2_range (vrange &r, gimple *stmt,
> +                                           const vrange &lhs, tree name,
>                                             fur_source &src);
> -  void compute_logical_operands (irange &true_range, irange &false_range,
> +  void compute_logical_operands (vrange &true_range, vrange &false_range,
>                                  gimple *stmt, const irange &lhs,
>                                  tree name, fur_source &src, tree op,
>                                  bool op_in_chain);
> -  bool logical_combine (irange &r, enum tree_code code, const irange &lhs,
> -                       const irange &op1_true, const irange &op1_false,
> -                       const irange &op2_true, const irange &op2_false);
> +  bool logical_combine (vrange &r, enum tree_code code, const irange &lhs,
> +                       const vrange &op1_true, const vrange &op1_false,
> +                       const vrange &op2_true, const vrange &op2_false);
>    int_range<2> m_bool_zero;    // Boolean false cached.
>    int_range<2> m_bool_one;     // Boolean true cached.
>
> @@ -193,14 +193,14 @@ private:
>  };
>
>  // These routines provide a GIMPLE interface to the range-ops code.
> -extern bool gimple_range_calc_op1 (irange &r, const gimple *s,
> -                                  const irange &lhs_range);
> -extern bool gimple_range_calc_op1 (irange &r, const gimple *s,
> -                                  const irange &lhs_range,
> -                                  const irange &op2_range);
> -extern bool gimple_range_calc_op2 (irange &r, const gimple *s,
> -                                  const irange &lhs_range,
> -                                  const irange &op1_range);
> +extern bool gimple_range_calc_op1 (vrange &r, const gimple *s,
> +                                  const vrange &lhs_range);
> +extern bool gimple_range_calc_op1 (vrange &r, const gimple *s,
> +                                  const vrange &lhs_range,
> +                                  const vrange &op2_range);
> +extern bool gimple_range_calc_op2 (vrange &r, const gimple *s,
> +                                  const vrange &lhs_range,
> +                                  const vrange &op1_range);
>
>  // For each name that is an import into BB's exports..
>  #define FOR_EACH_GORI_IMPORT_NAME(gori, bb, name)                      \
> diff --git a/gcc/gimple-range-path.cc b/gcc/gimple-range-path.cc
> index 66f433dd1d5..4819332f358 100644
> --- a/gcc/gimple-range-path.cc
> +++ b/gcc/gimple-range-path.cc
> @@ -83,7 +83,7 @@ path_range_query::clear_cache (tree name)
>  // If NAME has a cache entry, return it in R, and return TRUE.
>
>  inline bool
> -path_range_query::get_cache (irange &r, tree name)
> +path_range_query::get_cache (vrange &r, tree name)
>  {
>    if (!gimple_range_ssa_p (name))
>      return get_global_range_query ()->range_of_expr (r, name);
> @@ -98,7 +98,7 @@ path_range_query::get_cache (irange &r, tree name)
>  // Set the cache entry for NAME to R.
>
>  void
> -path_range_query::set_cache (const irange &r, tree name)
> +path_range_query::set_cache (const vrange &r, tree name)
>  {
>    unsigned v = SSA_NAME_VERSION (name);
>    bitmap_set_bit (m_has_cache_entry, v);
> @@ -149,7 +149,7 @@ path_range_query::defined_outside_path (tree name)
>  // Return the range of NAME on entry to the path.
>
>  void
> -path_range_query::range_on_path_entry (irange &r, tree name)
> +path_range_query::range_on_path_entry (vrange &r, tree name)
>  {
>    gcc_checking_assert (defined_outside_path (name));
>    basic_block entry = entry_bb ();
> @@ -168,7 +168,7 @@ path_range_query::range_on_path_entry (irange &r, tree name)
>    // block.  This can happen when we're querying a block with only an
>    // outgoing edge (no statement but the fall through edge), but for
>    // which we can determine a range on entry to the block.
> -  int_range_max tmp;
> +  tmp_range tmp (TREE_TYPE (name));
>    bool changed = false;
>    r.set_undefined ();
>    for (unsigned i = 0; i < EDGE_COUNT (entry->preds); ++i)
> @@ -190,9 +190,9 @@ path_range_query::range_on_path_entry (irange &r, tree name)
>  // Return the range of NAME at the end of the path being analyzed.
>
>  bool
> -path_range_query::internal_range_of_expr (irange &r, tree name, gimple *stmt)
> +path_range_query::internal_range_of_expr (vrange &r, tree name, gimple *stmt)
>  {
> -  if (!irange::supports_type_p (TREE_TYPE (name)))
> +  if (!vrange::supports_type_p (TREE_TYPE (name)))
>      return false;
>
>    if (get_cache (r, name))
> @@ -209,18 +209,22 @@ path_range_query::internal_range_of_expr (irange &r, tree name, gimple *stmt)
>        && range_defined_in_block (r, name, gimple_bb (stmt)))
>      {
>        if (TREE_CODE (name) == SSA_NAME)
> -       r.intersect (gimple_range_global (name));
> +       {
> +         tmp_range glob (TREE_TYPE (name));
> +         gimple_range_global (glob, name);
> +         r.intersect (glob);
> +       }
>
>        set_cache (r, name);
>        return true;
>      }
>
> -  r = gimple_range_global (name);
> +  gimple_range_global (r, name);
>    return true;
>  }
>
>  bool
> -path_range_query::range_of_expr (irange &r, tree name, gimple *stmt)
> +path_range_query::range_of_expr (vrange &r, tree name, gimple *stmt)
>  {
>    if (internal_range_of_expr (r, name, stmt))
>      {
> @@ -269,7 +273,7 @@ path_range_query::ssa_defined_in_bb (tree name, basic_block bb)
>  // calculating the PHI's range must not trigger additional lookups.
>
>  void
> -path_range_query::ssa_range_in_phi (irange &r, gphi *phi)
> +path_range_query::ssa_range_in_phi (vrange &r, gphi *phi)
>  {
>    tree name = gimple_phi_result (phi);
>    basic_block bb = gimple_bb (phi);
> @@ -283,7 +287,7 @@ path_range_query::ssa_range_in_phi (irange &r, gphi *phi)
>        // Try to fold the phi exclusively with global or cached values.
>        // This will get things like PHI <5(99), 6(88)>.  We do this by
>        // calling range_of_expr with no context.
> -      int_range_max arg_range;
> +      tmp_range arg_range (TREE_TYPE (name));
>        r.set_undefined ();
>        for (size_t i = 0; i < nargs; ++i)
>         {
> @@ -312,7 +316,7 @@ path_range_query::ssa_range_in_phi (irange &r, gphi *phi)
>           {
>             if (m_resolve)
>               {
> -               int_range_max tmp;
> +               tmp_range tmp (TREE_TYPE (name));
>                 // Using both the range on entry to the path, and the
>                 // range on this edge yields significantly better
>                 // results.
> @@ -335,7 +339,7 @@ path_range_query::ssa_range_in_phi (irange &r, gphi *phi)
>  // TRUE.  Otherwise, return FALSE.
>
>  bool
> -path_range_query::range_defined_in_block (irange &r, tree name, basic_block bb)
> +path_range_query::range_defined_in_block (vrange &r, tree name, basic_block bb)
>  {
>    gimple *def_stmt = SSA_NAME_DEF_STMT (name);
>    basic_block def_bb = gimple_bb (def_stmt);
> @@ -377,7 +381,6 @@ path_range_query::range_defined_in_block (irange &r, tree name, basic_block bb)
>  void
>  path_range_query::compute_ranges_in_phis (basic_block bb)
>  {
> -  int_range_max r;
>    auto_bitmap phi_set;
>
>    // PHIs must be resolved simultaneously on entry to the block
> @@ -390,7 +393,11 @@ path_range_query::compute_ranges_in_phis (basic_block bb)
>        gphi *phi = iter.phi ();
>        tree name = gimple_phi_result (phi);
>
> -      if (import_p (name) && range_defined_in_block (r, name, bb))
> +      if (!import_p (name))
> +       continue;
> +
> +      tmp_range r (TREE_TYPE (name));
> +      if (range_defined_in_block (r, name, bb))
>         {
>           unsigned v = SSA_NAME_VERSION (name);
>           set_cache (r, name);
> @@ -423,7 +430,6 @@ void
>  path_range_query::compute_ranges_in_block (basic_block bb)
>  {
>    bitmap_iterator bi;
> -  int_range_max r, cached_range;
>    unsigned i;
>
>    if (m_resolve && !at_entry ())
> @@ -444,6 +450,7 @@ path_range_query::compute_ranges_in_block (basic_block bb)
>    EXECUTE_IF_SET_IN_BITMAP (m_imports, 0, i, bi)
>      {
>        tree name = ssa_name (i);
> +      tmp_range r (TREE_TYPE (name));
>
>        if (gimple_code (SSA_NAME_DEF_STMT (name)) != GIMPLE_PHI
>           && range_defined_in_block (r, name, bb))
> @@ -480,8 +487,10 @@ path_range_query::compute_ranges_in_block (basic_block bb)
>
>        if (bitmap_bit_p (exports, i))
>         {
> +         tmp_range r (TREE_TYPE (name));
>           if (g.outgoing_edge_range_p (r, e, name, *this))
>             {
> +             tmp_range cached_range (TREE_TYPE (name));
>               if (get_cache (cached_range, name))
>                 r.intersect (cached_range);
>
> @@ -539,7 +548,7 @@ bool
>  path_range_query::add_to_imports (tree name, bitmap imports)
>  {
>    if (TREE_CODE (name) == SSA_NAME
> -      && irange::supports_type_p (TREE_TYPE (name)))
> +      && vrange::supports_type_p (TREE_TYPE (name)))
>      return bitmap_set_bit (imports, SSA_NAME_VERSION (name));
>    return false;
>  }
> @@ -751,11 +760,11 @@ jt_fur_source::query_relation (tree op1, tree op2)
>  // Return the range of STMT at the end of the path being analyzed.
>
>  bool
> -path_range_query::range_of_stmt (irange &r, gimple *stmt, tree)
> +path_range_query::range_of_stmt (vrange &r, gimple *stmt, tree)
>  {
>    tree type = gimple_range_type (stmt);
>
> -  if (!type || !irange::supports_type_p (type))
> +  if (!type || !vrange::supports_type_p (type))
>      return false;
>
>    // If resolving unknowns, fold the statement making use of any
> diff --git a/gcc/gimple-range-path.h b/gcc/gimple-range-path.h
> index 914983bb0aa..2c4624e4cef 100644
> --- a/gcc/gimple-range-path.h
> +++ b/gcc/gimple-range-path.h
> @@ -38,29 +38,29 @@ public:
>                        const bitmap_head *imports = NULL);
>    void compute_ranges (edge e);
>    void compute_imports (bitmap imports, basic_block exit);
> -  bool range_of_expr (irange &r, tree name, gimple * = NULL) override;
> -  bool range_of_stmt (irange &r, gimple *, tree name = NULL) override;
> +  bool range_of_expr (vrange &r, tree name, gimple * = NULL) override;
> +  bool range_of_stmt (vrange &r, gimple *, tree name = NULL) override;
>    bool unreachable_path_p ();
>    void dump (FILE *) override;
>    void debug ();
>
>  private:
> -  bool internal_range_of_expr (irange &r, tree name, gimple *);
> +  bool internal_range_of_expr (vrange &r, tree name, gimple *);
>    bool defined_outside_path (tree name);
> -  void range_on_path_entry (irange &r, tree name);
> +  void range_on_path_entry (vrange &r, tree name);
>    path_oracle *get_path_oracle () { return (path_oracle *)m_oracle; }
>
>    // Cache manipulation.
> -  void set_cache (const irange &r, tree name);
> -  bool get_cache (irange &r, tree name);
> +  void set_cache (const vrange &r, tree name);
> +  bool get_cache (vrange &r, tree name);
>    void clear_cache (tree name);
>
>    // Methods to compute ranges for the given path.
> -  bool range_defined_in_block (irange &, tree name, basic_block bb);
> +  bool range_defined_in_block (vrange &, tree name, basic_block bb);
>    void compute_ranges_in_block (basic_block bb);
>    void compute_ranges_in_phis (basic_block bb);
>    void adjust_for_non_null_uses (basic_block bb);
> -  void ssa_range_in_phi (irange &r, gphi *phi);
> +  void ssa_range_in_phi (vrange &r, gphi *phi);
>    void compute_outgoing_relations (basic_block bb, basic_block next);
>    void compute_phi_relations (basic_block bb, basic_block prev);
>    void maybe_register_phi_relation (gphi *, edge e);
> diff --git a/gcc/gimple-range-side-effect.cc b/gcc/gimple-range-side-effect.cc
> index 8d2ac35bc8d..aae087b7227 100644
> --- a/gcc/gimple-range-side-effect.cc
> +++ b/gcc/gimple-range-side-effect.cc
> @@ -58,7 +58,7 @@ non_null_loadstore (gimple *, tree op, tree, void *data)
>  // Add NAME and RANGE to the the side effect summary.
>
>  void
> -stmt_side_effects::add_range (tree name, irange &range)
> +stmt_side_effects::add_range (tree name, vrange &range)
>  {
>    m_names[num_args] = name;
>    m_ranges[num_args] = range;
> @@ -126,7 +126,7 @@ class exit_range
>  {
>  public:
>    tree name;
> -  irange *range;
> +  vrange *range;
>    exit_range *next;
>  };
>
> @@ -181,7 +181,7 @@ side_effect_manager::~side_effect_manager ()
>  // Return a non-zero range value of the appropriate type for NAME from
>  // the cache, creating it if necessary.
>
> -const irange&
> +const vrange&
>  side_effect_manager::get_nonzero (tree name)
>  {
>    unsigned v = SSA_NAME_VERSION (name);
> @@ -189,10 +189,8 @@ side_effect_manager::get_nonzero (tree name)
>      m_nonzero.safe_grow_cleared (num_ssa_names + 20);
>    if (!m_nonzero[v])
>      {
> -      tree type = TREE_TYPE (name);
> -      m_nonzero[v]
> -       = static_cast <irange *> (m_range_allocator.alloc_vrange (type));
> -      m_nonzero[v]->set_nonzero (type);
> +      m_nonzero[v] = m_range_allocator.alloc_vrange (TREE_TYPE (name));
> +      m_nonzero[v]->set_nonzero (TREE_TYPE (name));
>      }
>    return *(m_nonzero[v]);
>  }
> @@ -219,7 +217,7 @@ side_effect_manager::has_range_p (tree name, basic_block bb)
>  // to include it.
>
>  bool
> -side_effect_manager::maybe_adjust_range (irange &r, tree name, basic_block bb)
> +side_effect_manager::maybe_adjust_range (vrange &r, tree name, basic_block bb)
>  {
>    if (!has_range_p (name, bb))
>      return false;
> @@ -232,7 +230,7 @@ side_effect_manager::maybe_adjust_range (irange &r, tree name, basic_block bb)
>  // Add range R as a side effect for NAME in block BB.
>
>  void
> -side_effect_manager::add_range (tree name, basic_block bb, const irange &r)
> +side_effect_manager::add_range (tree name, basic_block bb, const vrange &r)
>  {
>    if (bb->index >= (int)m_on_exit.length ())
>      m_on_exit.safe_grow_cleared (last_basic_block_for_fn (cfun) + 1);
> @@ -254,7 +252,7 @@ side_effect_manager::add_range (tree name, basic_block bb, const irange &r)
>    exit_range *ptr = m_on_exit[bb->index].find_ptr (name);
>    if (ptr)
>      {
> -      int_range_max cur = r;
> +      tmp_range cur (r);
>        // If no new info is added, just return.
>        if (!cur.intersect (*(ptr->range)))
>         return;
> @@ -263,7 +261,7 @@ side_effect_manager::add_range (tree name, basic_block bb, const irange &r)
>        else
>         {
>           vrange &v = cur;
> -         ptr->range = static_cast <irange *> (m_range_allocator.clone (v));
> +         ptr->range = m_range_allocator.clone (v);
>         }
>        return;
>      }
> diff --git a/gcc/gimple-range-side-effect.h b/gcc/gimple-range-side-effect.h
> index d76d6eb34f2..a7625646ed1 100644
> --- a/gcc/gimple-range-side-effect.h
> +++ b/gcc/gimple-range-side-effect.h
> @@ -33,15 +33,15 @@ public:
>    inline unsigned num () const { return num_args; }
>    inline tree name (unsigned index) const
>      { gcc_checking_assert (index < num_args); return m_names[index]; }
> -  inline const irange& range (unsigned index) const
> +  inline const vrange& range (unsigned index) const
>      { gcc_checking_assert (index < num_args); return m_ranges[index]; }
> -  void add_range (tree name, irange &range);
> +  void add_range (tree name, vrange &range);
>    void add_nonzero (tree name);
>  private:
>    unsigned num_args;
>    static const int size_limit = 10;
>    tree m_names[size_limit];
> -  int_range<3> m_ranges[size_limit];
> +  tmp_range m_ranges[size_limit];
>    inline void bump_index () { if (num_args < size_limit - 1) num_args++; }
>  };
>
> @@ -56,10 +56,10 @@ class side_effect_manager
>  public:
>    side_effect_manager (bool do_search);
>    ~side_effect_manager ();
> -  void add_range (tree name, basic_block bb, const irange &r);
> +  void add_range (tree name, basic_block bb, const vrange &r);
>    void add_nonzero (tree name, basic_block bb);
>    bool has_range_p (tree name, basic_block bb);
> -  bool maybe_adjust_range (irange &r, tree name, basic_block bb);
> +  bool maybe_adjust_range (vrange &r, tree name, basic_block bb);
>  private:
>    class exit_range_head
>    {
> @@ -71,8 +71,8 @@ private:
>    };
>    void register_all_uses (tree name);
>    vec <exit_range_head> m_on_exit;
> -  const irange &get_nonzero (tree name);
> -  vec <irange *> m_nonzero;
> +  const vrange &get_nonzero (tree name);
> +  vec <vrange *> m_nonzero;
>    bitmap m_seen;
>    bitmap_obstack m_bitmaps;
>    struct obstack m_list_obstack;
> diff --git a/gcc/gimple-range-tests.cc b/gcc/gimple-range-tests.cc
> index 572acd33d7f..84ecc486889 100644
> --- a/gcc/gimple-range-tests.cc
> +++ b/gcc/gimple-range-tests.cc
> @@ -42,8 +42,9 @@ public:
>      ASSERT_TRUE (r == expect);
>    }
>
> -  virtual bool range_of_expr (irange &r, tree expr, gimple * = NULL) override
> +  virtual bool range_of_expr (vrange &v, tree expr, gimple * = NULL) override
>    {
> +    irange &r = as_a <irange> (v);
>      if (expr == op0)
>        {
>         r.set (build_int_cst (type, 5), build_int_cst (type, 10));
> diff --git a/gcc/gimple-range-trace.cc b/gcc/gimple-range-trace.cc
> index 39971093e6d..37cf37ca885 100644
> --- a/gcc/gimple-range-trace.cc
> +++ b/gcc/gimple-range-trace.cc
> @@ -102,7 +102,7 @@ range_tracer::print (unsigned counter, const char *str)
>
>  void
>  range_tracer::trailer (unsigned counter, const char *caller, bool result,
> -                     tree name, const irange &r)
> +                     tree name, const vrange &r)
>  {
>    gcc_checking_assert (tracing && counter != 0);
>
> @@ -141,7 +141,6 @@ debug_seed_ranger (gimple_ranger &ranger)
>      }
>
>    basic_block bb;
> -  int_range_max r;
>    gimple_stmt_iterator gsi;
>    FOR_EACH_BB_FN (bb, cfun)
>      for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
> @@ -151,7 +150,11 @@ debug_seed_ranger (gimple_ranger &ranger)
>         if (is_gimple_debug (stmt))
>           continue;
>
> -       ranger.range_of_stmt (r, stmt);
> +       if (tree type = gimple_range_type (stmt))
> +         {
> +           tmp_range r (type);
> +           ranger.range_of_stmt (r, stmt);
> +         }
>        }
>  }
>
> diff --git a/gcc/gimple-range-trace.h b/gcc/gimple-range-trace.h
> index 302afda3104..3f92e51803b 100644
> --- a/gcc/gimple-range-trace.h
> +++ b/gcc/gimple-range-trace.h
> @@ -32,7 +32,7 @@ public:
>    range_tracer (const char *name = "");
>    unsigned header (const char *str);
>    void trailer (unsigned counter, const char *caller, bool result, tree name,
> -               const irange &r);
> +               const vrange &r);
>    void print (unsigned counter, const char *str);
>    inline void enable_trace () { tracing = true; }
>    inline void disable_trace () { tracing = false; }
> diff --git a/gcc/gimple-range.cc b/gcc/gimple-range.cc
> index 32d57c9e3db..1118feb41a5 100644
> --- a/gcc/gimple-range.cc
> +++ b/gcc/gimple-range.cc
> @@ -71,7 +71,7 @@ gimple_ranger::~gimple_ranger ()
>  }
>
>  bool
> -gimple_ranger::range_of_expr (irange &r, tree expr, gimple *stmt)
> +gimple_ranger::range_of_expr (vrange &r, tree expr, gimple *stmt)
>  {
>    unsigned idx;
>    if (!gimple_range_ssa_p (expr))
> @@ -93,7 +93,7 @@ gimple_ranger::range_of_expr (irange &r, tree expr, gimple *stmt)
>    // If there is no statement, just get the global value.
>    if (!stmt)
>      {
> -      int_range_max tmp;
> +      tmp_range tmp (TREE_TYPE (expr));
>        m_cache.get_global_range (r, expr);
>        // Pick up implied context information from the on-entry cache
>        // if current_bb is set.  Do not attempt any new calculations.
> @@ -137,9 +137,9 @@ gimple_ranger::range_of_expr (irange &r, tree expr, gimple *stmt)
>  // Return the range of NAME on entry to block BB in R.
>
>  void
> -gimple_ranger::range_on_entry (irange &r, basic_block bb, tree name)
> +gimple_ranger::range_on_entry (vrange &r, basic_block bb, tree name)
>  {
> -  int_range_max entry_range;
> +  tmp_range entry_range (TREE_TYPE (name));
>    gcc_checking_assert (gimple_range_ssa_p (name));
>
>    unsigned idx;
> @@ -164,7 +164,7 @@ gimple_ranger::range_on_entry (irange &r, basic_block bb, tree name)
>  // Return false if no range can be calculated.
>
>  void
> -gimple_ranger::range_on_exit (irange &r, basic_block bb, tree name)
> +gimple_ranger::range_on_exit (vrange &r, basic_block bb, tree name)
>  {
>    // on-exit from the exit block?
>    gcc_checking_assert (bb != EXIT_BLOCK_PTR_FOR_FN (cfun));
> @@ -198,10 +198,10 @@ gimple_ranger::range_on_exit (irange &r, basic_block bb, tree name)
>  // Calculate a range for NAME on edge E and return it in R.
>
>  bool
> -gimple_ranger::range_on_edge (irange &r, edge e, tree name)
> +gimple_ranger::range_on_edge (vrange &r, edge e, tree name)
>  {
> -  int_range_max edge_range;
> -  gcc_checking_assert (irange::supports_type_p (TREE_TYPE (name)));
> +  tmp_range edge_range (TREE_TYPE (name));
> +  gcc_checking_assert (vrange::supports_type_p (TREE_TYPE (name)));
>
>    // Do not process values along abnormal edges.
>    if (e->flags & EDGE_ABNORMAL)
> @@ -249,7 +249,7 @@ gimple_ranger::range_on_edge (irange &r, edge e, tree name)
>  // fold_range wrapper for range_of_stmt to use as an internal client.
>
>  bool
> -gimple_ranger::fold_range_internal (irange &r, gimple *s, tree name)
> +gimple_ranger::fold_range_internal (vrange &r, gimple *s, tree name)
>  {
>    fold_using_range f;
>    fur_depend src (s, &(gori ()), this);
> @@ -263,7 +263,7 @@ gimple_ranger::fold_range_internal (irange &r, gimple *s, tree name)
>  // avoided.  If a range cannot be calculated, return false and UNDEFINED.
>
>  bool
> -gimple_ranger::range_of_stmt (irange &r, gimple *s, tree name)
> +gimple_ranger::range_of_stmt (vrange &r, gimple *s, tree name)
>  {
>    bool res;
>    r.set_undefined ();
> @@ -313,7 +313,7 @@ gimple_ranger::range_of_stmt (irange &r, gimple *s, tree name)
>         prefill_stmt_dependencies (name);
>
>        // Calculate a new value.
> -      int_range_max tmp;
> +      tmp_range tmp (TREE_TYPE (name));
>        fold_range_internal (tmp, s, name);
>
>        // Combine the new value with the old value.  This is required because
> @@ -334,7 +334,7 @@ gimple_ranger::range_of_stmt (irange &r, gimple *s, tree name)
>  // stack if so.  R is a scratch range.
>
>  inline void
> -gimple_ranger::prefill_name (irange &r, tree name)
> +gimple_ranger::prefill_name (tmp_range &r, tree name)
>  {
>    if (!gimple_range_ssa_p (name))
>      return;
> @@ -343,6 +343,7 @@ gimple_ranger::prefill_name (irange &r, tree name)
>      return;
>
>    bool current;
> +  r.init (TREE_TYPE (name));
>    // If this op has not been processed yet, then push it on the stack
>    if (!m_cache.get_global_range (r, name, current))
>      m_stmt_list.safe_push (name);
> @@ -357,7 +358,7 @@ gimple_ranger::prefill_stmt_dependencies (tree ssa)
>    if (SSA_NAME_IS_DEFAULT_DEF (ssa))
>      return;
>
> -  int_range_max r;
> +  tmp_range r;
>    unsigned idx;
>    gimple *stmt = SSA_NAME_DEF_STMT (ssa);
>    gcc_checking_assert (stmt && gimple_bb (stmt));
> @@ -388,6 +389,7 @@ gimple_ranger::prefill_stmt_dependencies (tree ssa)
>             {
>               // Fold and save the value for NAME.
>               stmt = SSA_NAME_DEF_STMT (name);
> +             r.init (TREE_TYPE (name));
>               fold_range_internal (r, stmt, name);
>               // Make sure we don't lose any current global info.
>               int_range_max tmp;
> @@ -488,10 +490,11 @@ gimple_ranger::export_global_ranges ()
>    bool print_header = true;
>    for (unsigned x = 1; x < num_ssa_names; x++)
>      {
> -      int_range_max r;
> +      tmp_range r;
>        tree name = ssa_name (x);
>        if (name && !SSA_NAME_IN_FREE_LIST (name)
>           && gimple_range_ssa_p (name)
> +         && r.init (TREE_TYPE (name))
>           && m_cache.get_global_range (r, name)
>           && !r.varying_p())
>         {
> @@ -508,13 +511,17 @@ gimple_ranger::export_global_ranges ()
>               print_header = false;
>             }
>
> -         value_range vr = r;
> +         if (!irange::supports_type_p (TREE_TYPE (name)))
> +           continue;
> +
> +         vrange &v = r;
> +         value_range vr = as_a <irange> (v);
>           print_generic_expr (dump_file, name , TDF_SLIM);
>           fprintf (dump_file, "  : ");
>           vr.dump (dump_file);
>           fprintf (dump_file, "\n");
>           int_range_max same = vr;
> -         if (same != r)
> +         if (same != as_a <irange> (v))
>             {
>               fprintf (dump_file, "         irange : ");
>               r.dump (dump_file);
> @@ -532,7 +539,7 @@ gimple_ranger::dump_bb (FILE *f, basic_block bb)
>    unsigned x;
>    edge_iterator ei;
>    edge e;
> -  int_range_max range, tmp_range;
> +  tmp_range range, tmp_range;
>    fprintf (f, "\n=========== BB %d ============\n", bb->index);
>    m_cache.dump_bb (f, bb);
>
> @@ -543,6 +550,7 @@ gimple_ranger::dump_bb (FILE *f, basic_block bb)
>      {
>        tree name = ssa_name (x);
>        if (gimple_range_ssa_p (name) && SSA_NAME_DEF_STMT (name) &&
> +         range.init (TREE_TYPE (name)) &&
>           gimple_bb (SSA_NAME_DEF_STMT (name)) == bb &&
>           m_cache.get_global_range (range, name))
>         {
> @@ -564,9 +572,11 @@ gimple_ranger::dump_bb (FILE *f, basic_block bb)
>         {
>           tree name = gimple_range_ssa_p (ssa_name (x));
>           if (name && gori ().has_edge_range_p (name, e)
> +             && range.init (TREE_TYPE (name))
>               && m_cache.range_on_edge (range, e, name))
>             {
>               gimple *s = SSA_NAME_DEF_STMT (name);
> +             tmp_range.init (TREE_TYPE (name));
>               // Only print the range if this is the def block, or
>               // the on entry cache for either end of the edge is
>               // set.
> diff --git a/gcc/gimple-range.h b/gcc/gimple-range.h
> index 13d4c77883e..ca5a33e65c6 100644
> --- a/gcc/gimple-range.h
> +++ b/gcc/gimple-range.h
> @@ -48,11 +48,11 @@ class gimple_ranger : public range_query
>  public:
>    gimple_ranger (bool use_imm_uses = true);
>    ~gimple_ranger ();
> -  virtual bool range_of_stmt (irange &r, gimple *, tree name = NULL) override;
> -  virtual bool range_of_expr (irange &r, tree name, gimple * = NULL) override;
> -  virtual bool range_on_edge (irange &r, edge e, tree name) override;
> -  void range_on_entry (irange &r, basic_block bb, tree name);
> -  void range_on_exit (irange &r, basic_block bb, tree name);
> +  virtual bool range_of_stmt (vrange &r, gimple *, tree name = NULL) override;
> +  virtual bool range_of_expr (vrange &r, tree name, gimple * = NULL) override;
> +  virtual bool range_on_edge (vrange &r, edge e, tree name) override;
> +  void range_on_entry (vrange &r, basic_block bb, tree name);
> +  void range_on_exit (vrange &r, basic_block bb, tree name);
>    void export_global_ranges ();
>    inline gori_compute &gori ()  { return m_cache.m_gori; }
>    virtual void dump (FILE *f) override;
> @@ -62,8 +62,8 @@ public:
>    bool fold_stmt (gimple_stmt_iterator *gsi, tree (*) (tree));
>    void register_side_effects (gimple *s);
>  protected:
> -  bool fold_range_internal (irange &r, gimple *s, tree name);
> -  void prefill_name (irange &r, tree name);
> +  bool fold_range_internal (vrange &r, gimple *s, tree name);
> +  void prefill_name (tmp_range &r, tree name);
>    void prefill_stmt_dependencies (tree ssa);
>    ranger_cache m_cache;
>    range_tracer tracer;
> diff --git a/gcc/gimple-ssa-warn-access.cc b/gcc/gimple-ssa-warn-access.cc
> index 9357a4e576a..132d82a5240 100644
> --- a/gcc/gimple-ssa-warn-access.cc
> +++ b/gcc/gimple-ssa-warn-access.cc
> @@ -328,11 +328,11 @@ check_nul_terminated_array (GimpleOrTree expr, tree src, tree bound)
>    wide_int bndrng[2];
>    if (bound)
>      {
> -      value_range r;
> +      tmp_range r (TREE_TYPE (bound));
>
>        get_global_range_query ()->range_of_expr (r, bound);
>
> -      if (r.kind () != VR_RANGE)
> +      if (r.undefined_p () || r.varying_p ())
>         return true;
>
>        bndrng[0] = r.lower_bound ();
> @@ -2790,9 +2790,8 @@ memmodel_to_uhwi (tree ord, gimple *stmt, unsigned HOST_WIDE_INT *cstval)
>      {
>        /* Use the range query to determine constant values in the absence
>          of constant propagation (such as at -O0).  */
> -      value_range rng;
> +      tmp_range rng (TREE_TYPE (ord));
>        if (!get_range_query (cfun)->range_of_expr (rng, ord, stmt)
> -         || !rng.constant_p ()
>           || !rng.singleton_p (&ord))
>         return false;
>
> diff --git a/gcc/tree-ssa-loop-niter.cc b/gcc/tree-ssa-loop-niter.cc
> index afa51064953..8907e310c19 100644
> --- a/gcc/tree-ssa-loop-niter.cc
> +++ b/gcc/tree-ssa-loop-niter.cc
> @@ -221,7 +221,7 @@ refine_value_range_using_guard (tree type, tree var,
>    get_type_static_bounds (type, mint, maxt);
>    mpz_init (minc1);
>    mpz_init (maxc1);
> -  value_range r;
> +  tmp_range r (TREE_TYPE (varc1));
>    /* Setup range information for varc1.  */
>    if (integer_zerop (varc1))
>      {
> @@ -374,7 +374,7 @@ determine_value_range (class loop *loop, tree type, tree var, mpz_t off,
>        gphi_iterator gsi;
>
>        /* Either for VAR itself...  */
> -      value_range var_range;
> +      tmp_range var_range (TREE_TYPE (var));
>        get_range_query (cfun)->range_of_expr (var_range, var);
>        rtype = var_range.kind ();
>        if (!var_range.undefined_p ())
> @@ -385,10 +385,10 @@ determine_value_range (class loop *loop, tree type, tree var, mpz_t off,
>
>        /* Or for PHI results in loop->header where VAR is used as
>          PHI argument from the loop preheader edge.  */
> +      tmp_range phi_range (TREE_TYPE (var));
>        for (gsi = gsi_start_phis (loop->header); !gsi_end_p (gsi); gsi_next (&gsi))
>         {
>           gphi *phi = gsi.phi ();
> -         value_range phi_range;
>           if (PHI_ARG_DEF_FROM_EDGE (phi, e) == var
>               && get_range_query (cfun)->range_of_expr (phi_range,
>                                                     gimple_phi_result (phi))
> @@ -410,7 +410,7 @@ determine_value_range (class loop *loop, tree type, tree var, mpz_t off,
>                      involved.  */
>                   if (wi::gt_p (minv, maxv, sgn))
>                     {
> -                     value_range vr;
> +                     tmp_range vr (TREE_TYPE (var));
>                       get_range_query (cfun)->range_of_expr (vr, var);
>                       rtype = vr.kind ();
>                       if (!vr.undefined_p ())
> @@ -3650,7 +3650,7 @@ record_nonwrapping_iv (class loop *loop, tree base, tree step, gimple *stmt,
>    if (tree_int_cst_sign_bit (step))
>      {
>        wide_int max;
> -      value_range base_range;
> +      tmp_range base_range (TREE_TYPE (orig_base));
>        if (get_range_query (cfun)->range_of_expr (base_range, orig_base)
>           && !base_range.undefined_p ())
>         max = base_range.upper_bound ();
> @@ -3672,7 +3672,7 @@ record_nonwrapping_iv (class loop *loop, tree base, tree step, gimple *stmt,
>    else
>      {
>        wide_int min;
> -      value_range base_range;
> +      tmp_range base_range (TREE_TYPE (orig_base));
>        if (get_range_query (cfun)->range_of_expr (base_range, orig_base)
>           && !base_range.undefined_p ())
>         min = base_range.lower_bound ();
> @@ -3947,7 +3947,7 @@ infer_loop_bounds_from_signedness (class loop *loop, gimple *stmt)
>
>    low = lower_bound_in_type (type, type);
>    high = upper_bound_in_type (type, type);
> -  value_range r;
> +  tmp_range r (TREE_TYPE (def));
>    get_range_query (cfun)->range_of_expr (r, def);
>    if (r.kind () == VR_RANGE)
>      {
> @@ -4997,7 +4997,7 @@ scev_var_range_cant_overflow (tree var, tree step, class loop *loop)
>    if (!def_bb || !dominated_by_p (CDI_DOMINATORS, loop->latch, def_bb))
>      return false;
>
> -  value_range r;
> +  tmp_range r (TREE_TYPE (var));
>    get_range_query (cfun)->range_of_expr (r, var);
>    if (r.kind () != VR_RANGE)
>      return false;
> diff --git a/gcc/tree-ssa-threadedge.cc b/gcc/tree-ssa-threadedge.cc
> index 4eb65ca7cac..d5e285d5d4d 100644
> --- a/gcc/tree-ssa-threadedge.cc
> +++ b/gcc/tree-ssa-threadedge.cc
> @@ -1409,19 +1409,19 @@ tree
>  hybrid_jt_simplifier::simplify (gimple *stmt, gimple *, basic_block,
>                                 jt_state *state)
>  {
> -  int_range_max r;
> -
>    compute_ranges_from_state (stmt, state);
>
>    if (gimple_code (stmt) == GIMPLE_COND
>        || gimple_code (stmt) == GIMPLE_ASSIGN)
>      {
> +      tmp_range r (gimple_range_type (stmt));
>        tree ret;
>        if (m_query->range_of_stmt (r, stmt) && r.singleton_p (&ret))
>         return ret;
>      }
>    else if (gimple_code (stmt) == GIMPLE_SWITCH)
>      {
> +      int_range_max r;
>        gswitch *switch_stmt = dyn_cast <gswitch *> (stmt);
>        tree index = gimple_switch_index (switch_stmt);
>        if (m_query->range_of_expr (r, index, stmt))
> diff --git a/gcc/value-query.cc b/gcc/value-query.cc
> index 31e56eeae53..463ac179a00 100644
> --- a/gcc/value-query.cc
> +++ b/gcc/value-query.cc
> @@ -57,13 +57,13 @@ value_query::value_of_stmt (gimple *stmt, tree name)
>  // range_query default methods.
>
>  bool
> -range_query::range_on_edge (irange &r, edge, tree expr)
> +range_query::range_on_edge (vrange &r, edge, tree expr)
>  {
>    return range_of_expr (r, expr);
>  }
>
>  bool
> -range_query::range_of_stmt (irange &r, gimple *stmt, tree name)
> +range_query::range_of_stmt (vrange &r, gimple *stmt, tree name)
>  {
>    if (!name)
>      name = gimple_get_lhs (stmt);
> @@ -79,11 +79,12 @@ tree
>  range_query::value_of_expr (tree expr, gimple *stmt)
>  {
>    tree t;
> -  int_range_max r;
>
> -  if (!irange::supports_type_p (TREE_TYPE (expr)))
> +  if (!vrange::supports_type_p (TREE_TYPE (expr)))
>      return NULL_TREE;
>
> +  tmp_range r (TREE_TYPE (expr));
> +
>    if (range_of_expr (r, expr, stmt))
>      {
>        // A constant used in an unreachable block oftens returns as UNDEFINED.
> @@ -100,10 +101,10 @@ tree
>  range_query::value_on_edge (edge e, tree expr)
>  {
>    tree t;
> -  int_range_max r;
>
> -  if (!irange::supports_type_p (TREE_TYPE (expr)))
> +  if (!vrange::supports_type_p (TREE_TYPE (expr)))
>      return NULL_TREE;
> +  tmp_range r (TREE_TYPE (expr));
>    if (range_on_edge (r, e, expr))
>      {
>        // A constant used in an unreachable block oftens returns as UNDEFINED.
> @@ -121,15 +122,15 @@ tree
>  range_query::value_of_stmt (gimple *stmt, tree name)
>  {
>    tree t;
> -  int_range_max r;
>
>    if (!name)
>      name = gimple_get_lhs (stmt);
>
>    gcc_checking_assert (!name || name == gimple_get_lhs (stmt));
>
> -  if (!name || !irange::supports_type_p (TREE_TYPE (name)))
> +  if (!name || !vrange::supports_type_p (TREE_TYPE (name)))
>      return NULL_TREE;
> +  tmp_range r (TREE_TYPE (name));
>    if (range_of_stmt (r, stmt, name) && r.singleton_p (&t))
>      return t;
>    return NULL_TREE;
> @@ -187,7 +188,7 @@ range_query::~range_query ()
>  // representable, and UNDEFINED/false if not.
>
>  bool
> -range_query::get_tree_range (irange &r, tree expr, gimple *stmt)
> +range_query::get_tree_range (vrange &r, tree expr, gimple *stmt)
>  {
>    tree type;
>    if (TYPE_P (expr))
> @@ -195,7 +196,7 @@ range_query::get_tree_range (irange &r, tree expr, gimple *stmt)
>    else
>      type = TREE_TYPE (expr);
>
> -  if (!irange::supports_type_p (type))
> +  if (!vrange::supports_type_p (type))
>      {
>        r.set_undefined ();
>        return false;
> @@ -214,7 +215,7 @@ range_query::get_tree_range (irange &r, tree expr, gimple *stmt)
>        return true;
>
>      case SSA_NAME:
> -      r = gimple_range_global (expr);
> +      gimple_range_global (r, expr);
>        return true;
>
>      case ADDR_EXPR:
> @@ -223,7 +224,7 @@ range_query::get_tree_range (irange &r, tree expr, gimple *stmt)
>         bool ov;
>         if (tree_single_nonzero_warnv_p (expr, &ov))
>           {
> -           r = range_nonzero (type);
> +           r.set_nonzero (type);
>             return true;
>           }
>         break;
> @@ -237,7 +238,8 @@ range_query::get_tree_range (irange &r, tree expr, gimple *stmt)
>        range_op_handler op (TREE_CODE (expr), type);
>        if (op)
>         {
> -         int_range_max r0, r1;
> +         tmp_range r0 (TREE_TYPE (TREE_OPERAND (expr, 0)));
> +         tmp_range r1 (TREE_TYPE (TREE_OPERAND (expr, 1)));
>           range_of_expr (r0, TREE_OPERAND (expr, 0), stmt);
>           range_of_expr (r1, TREE_OPERAND (expr, 1), stmt);
>           op.fold_range (r, type, r0, r1);
> @@ -250,11 +252,13 @@ range_query::get_tree_range (irange &r, tree expr, gimple *stmt)
>      {
>        range_op_handler op (TREE_CODE (expr), type);
>        tree op0_type = TREE_TYPE (TREE_OPERAND (expr, 0));
> -      if (op && irange::supports_type_p (op0_type))
> +      if (op && vrange::supports_type_p (op0_type))
>         {
> -         int_range_max r0;
> +         tmp_range r0 (TREE_TYPE (TREE_OPERAND (expr, 0)));
> +         tmp_range r1 (type);
> +         r1.set_varying (type);
>           range_of_expr (r0, TREE_OPERAND (expr, 0), stmt);
> -         op.fold_range (r, type, r0, int_range<1> (type));
> +         op.fold_range (r, type, r0, r1);
>         }
>        else
>         r.set_varying (type);
> @@ -311,7 +315,7 @@ get_ssa_name_ptr_info_nonnull (const_tree name)
>  // updated.
>
>  bool
> -update_global_range (irange &r, tree name)
> +update_global_range (vrange &r, tree name)
>  {
>    tree type = TREE_TYPE (name);
>
> @@ -330,8 +334,7 @@ update_global_range (irange &r, tree name)
>        if (r.undefined_p ())
>         return false;
>
> -      value_range vr = r;
> -      set_range_info (name, vr);
> +      set_range_info (name, as_a <irange> (r));
>        return true;
>      }
>    else if (POINTER_TYPE_P (type))
> @@ -349,7 +352,7 @@ update_global_range (irange &r, tree name)
>  // return VARYING.
>
>  static void
> -get_range_global (irange &r, tree name)
> +get_range_global (vrange &r, tree name)
>  {
>    tree type = TREE_TYPE (name);
>
> @@ -369,7 +372,7 @@ get_range_global (irange &r, tree name)
>             r.set_nonzero (type);
>           else if (INTEGRAL_TYPE_P (type))
>             {
> -             get_ssa_name_range_info (r, name);
> +             get_ssa_name_range_info (as_a <irange> (r), name);
>               if (r.undefined_p ())
>                 r.set_varying (type);
>             }
> @@ -384,7 +387,8 @@ get_range_global (irange &r, tree name)
>     }
>    else if (!POINTER_TYPE_P (type) && SSA_NAME_RANGE_INFO (name))
>      {
> -      get_ssa_name_range_info (r, name);
> +      gcc_checking_assert (irange::supports_type_p (TREE_TYPE (name)));
> +      get_ssa_name_range_info (as_a <irange> (r), name);
>        if (r.undefined_p ())
>         r.set_varying (type);
>      }
> @@ -414,21 +418,19 @@ get_range_global (irange &r, tree name)
>  // See discussion here:
>  // https://gcc.gnu.org/pipermail/gcc-patches/2021-June/571709.html
>
> -value_range
> -gimple_range_global (tree name)
> +void
> +gimple_range_global (vrange &r, tree name)
>  {
>    tree type = TREE_TYPE (name);
> -  gcc_checking_assert (TREE_CODE (name) == SSA_NAME
> -                      && irange::supports_type_p (type));
> +  gcc_checking_assert (TREE_CODE (name) == SSA_NAME);
>
>    if (SSA_NAME_IS_DEFAULT_DEF (name) || (cfun && cfun->after_inlining)
>        || is_a<gphi *> (SSA_NAME_DEF_STMT (name)))
>      {
> -      value_range vr;
> -      get_range_global (vr, name);
> -      return vr;
> +      get_range_global (r, name);
> +      return;
>      }
> -  return value_range (type);
> +  r.set_varying (type);
>  }
>
>  // ----------------------------------------------
> @@ -437,7 +439,7 @@ gimple_range_global (tree name)
>  global_range_query global_ranges;
>
>  bool
> -global_range_query::range_of_expr (irange &r, tree expr, gimple *stmt)
> +global_range_query::range_of_expr (vrange &r, tree expr, gimple *stmt)
>  {
>    tree type = TREE_TYPE (expr);
>
> @@ -456,15 +458,16 @@ global_range_query::range_of_expr (irange &r, tree expr, gimple *stmt)
>  relation_kind
>  range_query::query_relation (gimple *s, tree ssa1, tree ssa2, bool get_range)
>  {
> -  int_range_max tmp;
>    if (!m_oracle || TREE_CODE (ssa1) != SSA_NAME || TREE_CODE (ssa2) != SSA_NAME)
>      return VREL_VARYING;
>
>    // Ensure ssa1 and ssa2 have both been evaluated.
>    if (get_range)
>      {
> -      range_of_expr (tmp, ssa1, s);
> -      range_of_expr (tmp, ssa2, s);
> +      tmp_range tmp1 (TREE_TYPE (ssa1));
> +      tmp_range tmp2 (TREE_TYPE (ssa2));
> +      range_of_expr (tmp1, ssa1, s);
> +      range_of_expr (tmp2, ssa2, s);
>      }
>    return m_oracle->query_relation (gimple_bb (s), ssa1, ssa2);
>  }
> @@ -477,7 +480,6 @@ relation_kind
>  range_query::query_relation (edge e, tree ssa1, tree ssa2, bool get_range)
>  {
>    basic_block bb;
> -  int_range_max tmp;
>    if (!m_oracle || TREE_CODE (ssa1) != SSA_NAME || TREE_CODE (ssa2) != SSA_NAME)
>      return VREL_VARYING;
>
> @@ -492,6 +494,7 @@ range_query::query_relation (edge e, tree ssa1, tree ssa2, bool get_range)
>    // Ensure ssa1 and ssa2 have both been evaluated.
>    if (get_range)
>      {
> +      tmp_range tmp (TREE_TYPE (ssa1));
>        range_on_edge (tmp, e, ssa1);
>        range_on_edge (tmp, e, ssa2);
>      }
> diff --git a/gcc/value-query.h b/gcc/value-query.h
> index cf1a1d74de3..280e47e3f6b 100644
> --- a/gcc/value-query.h
> +++ b/gcc/value-query.h
> @@ -89,9 +89,9 @@ public:
>    //
>    // Note that range_of_expr must always return TRUE unless ranges are
>    // unsupported for EXPR's type (supports_type_p is false).
> -  virtual bool range_of_expr (irange &r, tree expr, gimple * = NULL) = 0;
> -  virtual bool range_on_edge (irange &r, edge, tree expr);
> -  virtual bool range_of_stmt (irange &r, gimple *, tree name = NULL);
> +  virtual bool range_of_expr (vrange &r, tree expr, gimple * = NULL) = 0;
> +  virtual bool range_on_edge (vrange &r, edge, tree expr);
> +  virtual bool range_of_stmt (vrange &r, gimple *, tree name = NULL);
>
>    // Query if there is any relation between SSA1 and SSA2.
>    relation_kind query_relation (gimple *s, tree ssa1, tree ssa2,
> @@ -110,8 +110,8 @@ public:
>  protected:
>    class value_range_equiv *allocate_value_range_equiv ();
>    void free_value_range_equiv (class value_range_equiv *);
> -  bool get_tree_range (irange &r, tree expr, gimple *stmt);
> -  bool get_arith_expr_range (irange &r, tree expr, gimple *stmt);
> +  bool get_tree_range (vrange &v, tree expr, gimple *stmt);
> +  bool get_arith_expr_range (vrange &r, tree expr, gimple *stmt);
>    relation_oracle *m_oracle;
>
>  private:
> @@ -123,7 +123,7 @@ private:
>  class global_range_query : public range_query
>  {
>  public:
> -  bool range_of_expr (irange &r, tree expr, gimple * = NULL) override;
> +  bool range_of_expr (vrange &r, tree expr, gimple * = NULL) override;
>  };
>
>  extern global_range_query global_ranges;
> @@ -143,7 +143,7 @@ get_range_query (const struct function *fun)
>    return fun->x_range_query ? fun->x_range_query : &global_ranges;
>  }
>
> -extern value_range gimple_range_global (tree name);
> -extern bool update_global_range (irange &r, tree name);
> +extern void gimple_range_global (vrange &v, tree name);
> +extern bool update_global_range (vrange &v, tree name);
>
>  #endif // GCC_QUERY_H
> diff --git a/gcc/vr-values.cc b/gcc/vr-values.cc
> index 6f8583c8d01..9b681a46905 100644
> --- a/gcc/vr-values.cc
> +++ b/gcc/vr-values.cc
> @@ -177,7 +177,7 @@ vr_values::get_value_range (const_tree var,
>  }
>
>  bool
> -vr_values::range_of_expr (irange &r, tree expr, gimple *stmt)
> +vr_values::range_of_expr (vrange &r, tree expr, gimple *stmt)
>  {
>    if (!gimple_range_ssa_p (expr))
>      return get_tree_range (r, expr, stmt);
> @@ -1640,6 +1640,8 @@ bounds_of_var_in_loop (tree *min, tree *max, range_query *query,
>  {
>    tree init, step, chrec, tmin, tmax, type = TREE_TYPE (var);
>    enum ev_direction dir;
> +  tmp_range trange;
> +  int_range<2> r;
>
>    chrec = instantiate_parameters (loop, analyze_scalar_evolution (loop, var));
>
> @@ -1661,11 +1663,15 @@ bounds_of_var_in_loop (tree *min, tree *max, range_query *query,
>
>    /* If INIT is an SSA with a singleton range, set INIT to said
>       singleton, otherwise leave INIT alone.  */
> -  if (TREE_CODE (init) == SSA_NAME)
> -    query->get_value_range (init, stmt)->singleton_p (&init);
> +  if (TREE_CODE (init) == SSA_NAME
> +      && trange.init (TREE_TYPE (init))
> +      && query->range_of_expr (trange, init, stmt))
> +    trange.singleton_p (&init);
>    /* Likewise for step.  */
> -  if (TREE_CODE (step) == SSA_NAME)
> -    query->get_value_range (step, stmt)->singleton_p (&step);
> +  if (TREE_CODE (step) == SSA_NAME
> +      && trange.init (TREE_TYPE (step))
> +      && query->range_of_expr (trange, step, stmt))
> +    trange.singleton_p (&step);
>
>    /* If STEP is symbolic, we can't know whether INIT will be the
>       minimum or maximum value in the range.  Also, unless INIT is
> @@ -1699,7 +1705,8 @@ bounds_of_var_in_loop (tree *min, tree *max, range_query *query,
>    if (TREE_CODE (step) == INTEGER_CST
>        && is_gimple_val (init)
>        && (TREE_CODE (init) != SSA_NAME
> -         || query->get_value_range (init, stmt)->kind () == VR_RANGE))
> +         || (query->range_of_expr (r, init, stmt)
> +             && r.kind () == VR_RANGE)))
>      {
>        widest_int nit;
>
> @@ -1724,7 +1731,7 @@ bounds_of_var_in_loop (tree *min, tree *max, range_query *query,
>             {
>               value_range maxvr, vr0, vr1;
>               if (TREE_CODE (init) == SSA_NAME)
> -               vr0 = *(query->get_value_range (init, stmt));
> +               query->range_of_expr (vr0, init, stmt);
>               else if (is_gimple_min_invariant (init))
>                 vr0.set (init);
>               else
> @@ -1737,10 +1744,10 @@ bounds_of_var_in_loop (tree *min, tree *max, range_query *query,
>               /* Likewise if the addition did.  */
>               if (maxvr.kind () == VR_RANGE)
>                 {
> -                 value_range initvr;
> +                 int_range<2> initvr;
>
>                   if (TREE_CODE (init) == SSA_NAME)
> -                   initvr = *(query->get_value_range (init, stmt));
> +                   query->range_of_expr (initvr, init, stmt);
>                   else if (is_gimple_min_invariant (init))
>                     initvr.set (init);
>                   else
> @@ -2446,7 +2453,9 @@ simplify_using_ranges::vrp_visit_cond_stmt (gcond *stmt, edge *taken_edge_p)
>           fprintf (dump_file, "\t");
>           print_generic_expr (dump_file, use);
>           fprintf (dump_file, ": ");
> -         dump_value_range (dump_file, query->get_value_range (use, stmt));
> +         tmp_range r (TREE_TYPE (use));
> +         query->range_of_expr (r, use, stmt);
> +         r.dump (dump_file);
>         }
>
>        fprintf (dump_file, "\n");
> diff --git a/gcc/vr-values.h b/gcc/vr-values.h
> index 7a377cebd01..f018d0dfc4b 100644
> --- a/gcc/vr-values.h
> +++ b/gcc/vr-values.h
> @@ -109,7 +109,7 @@ class vr_values : public range_query
>    vr_values (void);
>    ~vr_values (void);
>
> -  virtual bool range_of_expr (irange &r, tree expr, gimple *stmt) override;
> +  virtual bool range_of_expr (vrange &r, tree expr, gimple *stmt) override;
>    virtual tree value_of_expr (tree, gimple * = NULL) override;
>    virtual tree value_on_edge (edge, tree) override;
>    virtual tree value_of_stmt (gimple *, tree = NULL_TREE) override;
> --
> 2.36.1
>
  
Xi Ruoyao June 27, 2022, 12:33 a.m. UTC | #2
On Wed, 2022-06-01 at 11:04 +0200, Aldy Hernandez via Gcc-patches wrote:
> Final patch committed.
> 
> All users but one of Value_Range::set_type() have been removed in
> favor of using a constructor taking a type.   We still need to delay
> initialization for one use in gimple_infer_range, as it has an array
> of temporaries for which the type is not known until later.
> 
> Re-tested on x86-64 Linux.

Bootstrap on loongarch64-linux-gnu is broken since r13-911.  I've
created https://gcc.gnu.org/PR106096 and put all information I've
gathered so far in the PR.
  

Patch

diff --git a/gcc/gimple-range-cache.cc b/gcc/gimple-range-cache.cc
index 9c541993fb6..4983e4d3aa7 100644
--- a/gcc/gimple-range-cache.cc
+++ b/gcc/gimple-range-cache.cc
@@ -44,11 +44,14 @@  along with GCC; see the file COPYING3.  If not see
 class ssa_block_ranges
 {
 public:
-  virtual bool set_bb_range (const_basic_block bb, const irange &r) = 0;
-  virtual bool get_bb_range (irange &r, const_basic_block bb) = 0;
+  ssa_block_ranges (tree t) : m_type (t) { }
+  virtual bool set_bb_range (const_basic_block bb, const vrange &r) = 0;
+  virtual bool get_bb_range (vrange &r, const_basic_block bb) = 0;
   virtual bool bb_range_p (const_basic_block bb) = 0;
 
   void dump(FILE *f);
+private:
+  tree m_type;
 };
 
 // Print the list of known ranges for file F in a nice format.
@@ -57,7 +60,7 @@  void
 ssa_block_ranges::dump (FILE *f)
 {
   basic_block bb;
-  int_range_max r;
+  tmp_range r (m_type);
 
   FOR_EACH_BB_FN (bb, cfun)
     if (get_bb_range (r, bb))
@@ -77,14 +80,14 @@  class sbr_vector : public ssa_block_ranges
 public:
   sbr_vector (tree t, vrange_allocator *allocator);
 
-  virtual bool set_bb_range (const_basic_block bb, const irange &r) override;
-  virtual bool get_bb_range (irange &r, const_basic_block bb) override;
+  virtual bool set_bb_range (const_basic_block bb, const vrange &r) override;
+  virtual bool get_bb_range (vrange &r, const_basic_block bb) override;
   virtual bool bb_range_p (const_basic_block bb) override;
 protected:
-  irange **m_tab;	// Non growing vector.
+  vrange **m_tab;	// Non growing vector.
   int m_tab_size;
-  int_range<2> m_varying;
-  int_range<2> m_undefined;
+  vrange *m_varying;
+  vrange *m_undefined;
   tree m_type;
   vrange_allocator *m_range_allocator;
   void grow ();
@@ -94,18 +97,21 @@  protected:
 // Initialize a block cache for an ssa_name of type T.
 
 sbr_vector::sbr_vector (tree t, vrange_allocator *allocator)
+  : ssa_block_ranges (t)
 {
   gcc_checking_assert (TYPE_P (t));
   m_type = t;
   m_range_allocator = allocator;
   m_tab_size = last_basic_block_for_fn (cfun) + 1;
-  m_tab = static_cast <irange **>
-    (allocator->alloc (m_tab_size * sizeof (irange *)));
-  memset (m_tab, 0, m_tab_size * sizeof (irange *));
+  m_tab = static_cast <vrange **>
+    (allocator->alloc (m_tab_size * sizeof (vrange *)));
+  memset (m_tab, 0, m_tab_size * sizeof (vrange *));
 
   // Create the cached type range.
-  m_varying.set_varying (t);
-  m_undefined.set_undefined ();
+  m_varying = m_range_allocator->alloc_vrange (t);
+  m_undefined = m_range_allocator->alloc_vrange (t);
+  m_varying->set_varying (t);
+  m_undefined->set_undefined ();
 }
 
 // Grow the vector when the CFG has increased in size.
@@ -122,10 +128,10 @@  sbr_vector::grow ()
   int new_size = inc + curr_bb_size;
 
   // Allocate new memory, copy the old vector and clear the new space.
-  irange **t = static_cast <irange **>
-    (m_range_allocator->alloc (new_size * sizeof (irange *)));
-  memcpy (t, m_tab, m_tab_size * sizeof (irange *));
-  memset (t + m_tab_size, 0, (new_size - m_tab_size) * sizeof (irange *));
+  vrange **t = static_cast <vrange **>
+    (m_range_allocator->alloc (new_size * sizeof (vrange *)));
+  memcpy (t, m_tab, m_tab_size * sizeof (vrange *));
+  memset (t + m_tab_size, 0, (new_size - m_tab_size) * sizeof (vrange *));
 
   m_tab = t;
   m_tab_size = new_size;
@@ -134,15 +140,15 @@  sbr_vector::grow ()
 // Set the range for block BB to be R.
 
 bool
-sbr_vector::set_bb_range (const_basic_block bb, const irange &r)
+sbr_vector::set_bb_range (const_basic_block bb, const vrange &r)
 {
-  irange *m;
+  vrange *m;
   if (bb->index >= m_tab_size)
     grow ();
   if (r.varying_p ())
-    m = &m_varying;
+    m = m_varying;
   else if (r.undefined_p ())
-    m = &m_undefined;
+    m = m_undefined;
   else
     m = m_range_allocator->clone (r);
   m_tab[bb->index] = m;
@@ -153,11 +159,11 @@  sbr_vector::set_bb_range (const_basic_block bb, const irange &r)
 // there is no range.
 
 bool
-sbr_vector::get_bb_range (irange &r, const_basic_block bb)
+sbr_vector::get_bb_range (vrange &r, const_basic_block bb)
 {
   if (bb->index >= m_tab_size)
     return false;
-  irange *m = m_tab[bb->index];
+  vrange *m = m_tab[bb->index];
   if (m)
     {
       r = *m;
@@ -193,14 +199,14 @@  class sbr_sparse_bitmap : public ssa_block_ranges
 {
 public:
   sbr_sparse_bitmap (tree t, vrange_allocator *allocator, bitmap_obstack *bm);
-  virtual bool set_bb_range (const_basic_block bb, const irange &r) override;
-  virtual bool get_bb_range (irange &r, const_basic_block bb) override;
+  virtual bool set_bb_range (const_basic_block bb, const vrange &r) override;
+  virtual bool get_bb_range (vrange &r, const_basic_block bb) override;
   virtual bool bb_range_p (const_basic_block bb) override;
 private:
   void bitmap_set_quad (bitmap head, int quad, int quad_value);
   int bitmap_get_quad (const_bitmap head, int quad);
   vrange_allocator *m_range_allocator;
-  irange *m_range[SBR_NUM];
+  vrange *m_range[SBR_NUM];
   bitmap_head bitvec;
   tree m_type;
 };
@@ -209,6 +215,7 @@  private:
 
 sbr_sparse_bitmap::sbr_sparse_bitmap (tree t, vrange_allocator *allocator,
 				      bitmap_obstack *bm)
+  : ssa_block_ranges (t)
 {
   gcc_checking_assert (TYPE_P (t));
   m_type = t;
@@ -216,16 +223,14 @@  sbr_sparse_bitmap::sbr_sparse_bitmap (tree t, vrange_allocator *allocator,
   bitmap_tree_view (&bitvec);
   m_range_allocator = allocator;
   // Pre-cache varying.
-  m_range[0] = static_cast <irange *> (m_range_allocator->alloc_vrange (t));
+  m_range[0] = m_range_allocator->alloc_vrange (t);
   m_range[0]->set_varying (t);
   // Pre-cache zero and non-zero values for pointers.
   if (POINTER_TYPE_P (t))
     {
-      m_range[1]
-	= static_cast <irange *> (m_range_allocator->alloc_vrange (t));
+      m_range[1] = m_range_allocator->alloc_vrange (t);
       m_range[1]->set_nonzero (t);
-      m_range[2]
-	= static_cast <irange *> (m_range_allocator->alloc_vrange (t));
+      m_range[2] = m_range_allocator->alloc_vrange (t);
       m_range[2]->set_zero (t);
     }
   else
@@ -257,7 +262,7 @@  sbr_sparse_bitmap::bitmap_get_quad (const_bitmap head, int quad)
 // Set the range on entry to basic block BB to R.
 
 bool
-sbr_sparse_bitmap::set_bb_range (const_basic_block bb, const irange &r)
+sbr_sparse_bitmap::set_bb_range (const_basic_block bb, const vrange &r)
 {
   if (r.undefined_p ())
     {
@@ -283,7 +288,7 @@  sbr_sparse_bitmap::set_bb_range (const_basic_block bb, const irange &r)
 // there is no range.
 
 bool
-sbr_sparse_bitmap::get_bb_range (irange &r, const_basic_block bb)
+sbr_sparse_bitmap::get_bb_range (vrange &r, const_basic_block bb)
 {
   int value = bitmap_get_quad (&bitvec, bb->index);
 
@@ -333,7 +338,7 @@  block_range_cache::~block_range_cache ()
 
 bool
 block_range_cache::set_bb_range (tree name, const_basic_block bb,
-				 const irange &r)
+				 const vrange &r)
 {
   unsigned v = SSA_NAME_VERSION (name);
   if (v >= m_ssa_ranges.length ())
@@ -379,7 +384,7 @@  block_range_cache::query_block_ranges (tree name)
 // is one.
 
 bool
-block_range_cache::get_bb_range (irange &r, tree name, const_basic_block bb)
+block_range_cache::get_bb_range (vrange &r, tree name, const_basic_block bb)
 {
   ssa_block_ranges *ptr = query_block_ranges (name);
   if (ptr)
@@ -423,12 +428,13 @@  void
 block_range_cache::dump (FILE *f, basic_block bb, bool print_varying)
 {
   unsigned x;
-  int_range_max r;
   bool summarize_varying = false;
   for (x = 1; x < m_ssa_ranges.length (); ++x)
     {
       if (!gimple_range_ssa_p (ssa_name (x)))
 	continue;
+
+      tmp_range r (TREE_TYPE (ssa_name (x)));
       if (m_ssa_ranges[x] && m_ssa_ranges[x]->get_bb_range (r, bb))
 	{
 	  if (!print_varying && r.varying_p ())
@@ -450,6 +456,8 @@  block_range_cache::dump (FILE *f, basic_block bb, bool print_varying)
 	{
 	  if (!gimple_range_ssa_p (ssa_name (x)))
 	    continue;
+
+	  tmp_range r (TREE_TYPE (ssa_name (x)));
 	  if (m_ssa_ranges[x] && m_ssa_ranges[x]->get_bb_range (r, bb))
 	    {
 	      if (r.varying_p ())
@@ -485,13 +493,13 @@  ssa_global_cache::~ssa_global_cache ()
 // Return the value in R.
 
 bool
-ssa_global_cache::get_global_range (irange &r, tree name) const
+ssa_global_cache::get_global_range (vrange &r, tree name) const
 {
   unsigned v = SSA_NAME_VERSION (name);
   if (v >= m_tab.length ())
     return false;
 
-  irange *stow = m_tab[v];
+  vrange *stow = m_tab[v];
   if (!stow)
     return false;
   r = *stow;
@@ -502,13 +510,13 @@  ssa_global_cache::get_global_range (irange &r, tree name) const
 // Return TRUE if there was already a range set, otherwise false.
 
 bool
-ssa_global_cache::set_global_range (tree name, const irange &r)
+ssa_global_cache::set_global_range (tree name, const vrange &r)
 {
   unsigned v = SSA_NAME_VERSION (name);
   if (v >= m_tab.length ())
     m_tab.safe_grow_cleared (num_ssa_names + 1);
 
-  irange *m = m_tab[v];
+  vrange *m = m_tab[v];
   if (m && m->fits_p (r))
     *m = r;
   else
@@ -533,7 +541,7 @@  void
 ssa_global_cache::clear ()
 {
   if (m_tab.address ())
-    memset (m_tab.address(), 0, m_tab.length () * sizeof (irange *));
+    memset (m_tab.address(), 0, m_tab.length () * sizeof (vrange *));
 }
 
 // Dump the contents of the global cache to F.
@@ -545,8 +553,9 @@  ssa_global_cache::dump (FILE *f)
   bool print_header = true;
   for (unsigned x = 1; x < num_ssa_names; x++)
     {
-      int_range_max r;
+      tmp_range r;
       if (gimple_range_ssa_p (ssa_name (x)) &&
+	  r.init (TREE_TYPE (ssa_name (x))) &&
 	  get_global_range (r, ssa_name (x))  && !r.varying_p ())
 	{
 	  if (print_header)
@@ -809,11 +818,11 @@  ranger_cache::dump_bb (FILE *f, basic_block bb)
 // global range is not set, and return the legacy global value in R.
 
 bool
-ranger_cache::get_global_range (irange &r, tree name) const
+ranger_cache::get_global_range (vrange &r, tree name) const
 {
   if (m_globals.get_global_range (r, name))
     return true;
-  r = gimple_range_global (name);
+  gimple_range_global (r, name);
   return false;
 }
 
@@ -825,7 +834,7 @@  ranger_cache::get_global_range (irange &r, tree name) const
 // After this call, the global cache will have a value.
 
 bool
-ranger_cache::get_global_range (irange &r, tree name, bool &current_p)
+ranger_cache::get_global_range (vrange &r, tree name, bool &current_p)
 {
   bool had_global = get_global_range (r, name);
 
@@ -847,7 +856,7 @@  ranger_cache::get_global_range (irange &r, tree name, bool &current_p)
 //  Set the global range of NAME to R and give it a timestamp.
 
 void
-ranger_cache::set_global_range (tree name, const irange &r)
+ranger_cache::set_global_range (tree name, const vrange &r)
 {
   if (m_globals.set_global_range (name, r))
     {
@@ -882,7 +891,7 @@  ranger_cache::set_global_range (tree name, const irange &r)
 // get the best global value available.
 
 void
-ranger_cache::range_of_def (irange &r, tree name, basic_block bb)
+ranger_cache::range_of_def (vrange &r, tree name, basic_block bb)
 {
   gcc_checking_assert (gimple_range_ssa_p (name));
   gcc_checking_assert (!bb || bb == gimple_bb (SSA_NAME_DEF_STMT (name)));
@@ -895,7 +904,7 @@  ranger_cache::range_of_def (irange &r, tree name, basic_block bb)
       if (gimple_get_lhs (s) == name)
 	fold_range (r, s, get_global_range_query ());
       else
-	r = gimple_range_global (name);
+	gimple_range_global (r, name);
     }
 }
 
@@ -903,12 +912,12 @@  ranger_cache::range_of_def (irange &r, tree name, basic_block bb)
 // lookups.
 
 void
-ranger_cache::entry_range (irange &r, tree name, basic_block bb,
+ranger_cache::entry_range (vrange &r, tree name, basic_block bb,
 			   enum rfd_mode mode)
 {
   if (bb == ENTRY_BLOCK_PTR_FOR_FN (cfun))
     {
-      r = gimple_range_global (name);
+      gimple_range_global (r, name);
       return;
     }
 
@@ -923,12 +932,12 @@  ranger_cache::entry_range (irange &r, tree name, basic_block bb,
 // lookups.
 
 void
-ranger_cache::exit_range (irange &r, tree name, basic_block bb,
+ranger_cache::exit_range (vrange &r, tree name, basic_block bb,
 			  enum rfd_mode mode)
 {
   if (bb == ENTRY_BLOCK_PTR_FOR_FN (cfun))
     {
-      r = gimple_range_global (name);
+      gimple_range_global (r, name);
       return;
     }
 
@@ -944,7 +953,7 @@  ranger_cache::exit_range (irange &r, tree name, basic_block bb,
 // Always returns a range and true.
 
 bool
-ranger_cache::edge_range (irange &r, edge e, tree name, enum rfd_mode mode)
+ranger_cache::edge_range (vrange &r, edge e, tree name, enum rfd_mode mode)
 {
   exit_range (r, name, e->src, mode);
   // If this is not an abnormal edge, check for side effects on exit.
@@ -961,7 +970,7 @@  ranger_cache::edge_range (irange &r, edge e, tree name, enum rfd_mode mode)
 // Implement range_of_expr.
 
 bool
-ranger_cache::range_of_expr (irange &r, tree name, gimple *stmt)
+ranger_cache::range_of_expr (vrange &r, tree name, gimple *stmt)
 {
   if (!gimple_range_ssa_p (name))
     {
@@ -985,7 +994,7 @@  ranger_cache::range_of_expr (irange &r, tree name, gimple *stmt)
 // the current cache values.
 
 bool
-ranger_cache::range_on_edge (irange &r, edge e, tree expr)
+ranger_cache::range_on_edge (vrange &r, edge e, tree expr)
 {
   if (gimple_range_ssa_p (expr))
     return edge_range (r, e, expr, RFD_NONE);
@@ -997,7 +1006,7 @@  ranger_cache::range_on_edge (irange &r, edge e, tree expr)
 // def block for NAME.  Otherwise, return false if the cache is empty.
 
 bool
-ranger_cache::block_range (irange &r, basic_block bb, tree name, bool calc)
+ranger_cache::block_range (vrange &r, basic_block bb, tree name, bool calc)
 {
   gcc_checking_assert (gimple_range_ssa_p (name));
 
@@ -1041,9 +1050,10 @@  ranger_cache::propagate_cache (tree name)
   basic_block bb;
   edge_iterator ei;
   edge e;
-  int_range_max new_range;
-  int_range_max current_range;
-  int_range_max e_range;
+  tree type = TREE_TYPE (name);
+  tmp_range new_range (type);
+  tmp_range current_range (type);
+  tmp_range e_range (type);
 
   // Process each block by seeing if its calculated range on entry is
   // the same as its cached value. If there is a difference, update
@@ -1178,8 +1188,8 @@  ranger_cache::fill_block_cache (tree name, basic_block bb, basic_block def_bb)
 {
   edge_iterator ei;
   edge e;
-  int_range_max block_result;
-  int_range_max undefined;
+  tmp_range block_result (TREE_TYPE (name));
+  tmp_range undefined (TREE_TYPE (name));
 
   // At this point we shouldn't be looking at the def, entry or exit block.
   gcc_checking_assert (bb != def_bb && bb != ENTRY_BLOCK_PTR_FOR_FN (cfun) &&
@@ -1232,7 +1242,7 @@  ranger_cache::fill_block_cache (tree name, basic_block bb, basic_block def_bb)
       FOR_EACH_EDGE (e, ei, node->preds)
 	{
 	  basic_block pred = e->src;
-	  int_range_max r;
+	  tmp_range r (TREE_TYPE (name));
 
 	  if (DEBUG_RANGE_CACHE)
 	    fprintf (dump_file, "  %d->%d ",e->src->index, e->dest->index);
@@ -1306,7 +1316,7 @@  ranger_cache::fill_block_cache (tree name, basic_block bb, basic_block def_bb)
 // dominator tree based on MODE.
 
 bool
-ranger_cache::range_from_dom (irange &r, tree name, basic_block start_bb,
+ranger_cache::range_from_dom (vrange &r, tree name, basic_block start_bb,
 			      enum rfd_mode mode)
 {
   if (mode == RFD_NONE || !dom_info_available_p (CDI_DOMINATORS))
diff --git a/gcc/gimple-range-cache.h b/gcc/gimple-range-cache.h
index 2472cd04f47..d17950c7154 100644
--- a/gcc/gimple-range-cache.h
+++ b/gcc/gimple-range-cache.h
@@ -34,8 +34,8 @@  public:
   block_range_cache ();
   ~block_range_cache ();
 
-  bool set_bb_range (tree name, const_basic_block bb, const irange &r);
-  bool get_bb_range (irange &r, tree name, const_basic_block bb);
+  bool set_bb_range (tree name, const_basic_block bb, const vrange &v);
+  bool get_bb_range (vrange &v, tree name, const_basic_block bb);
   bool bb_range_p (tree name, const_basic_block bb);
 
   void dump (FILE *f);
@@ -57,13 +57,13 @@  class ssa_global_cache
 public:
   ssa_global_cache ();
   ~ssa_global_cache ();
-  bool get_global_range (irange &r, tree name) const;
-  bool set_global_range (tree name, const irange &r);
+  bool get_global_range (vrange &r, tree name) const;
+  bool set_global_range (tree name, const vrange &r);
   void clear_global_range (tree name);
   void clear ();
   void dump (FILE *f = stderr);
 private:
-  vec<irange *> m_tab;
+  vec<vrange *> m_tab;
   vrange_allocator *m_range_allocator;
 };
 
@@ -77,13 +77,13 @@  public:
   ranger_cache (int not_executable_flag, bool use_imm_uses);
   ~ranger_cache ();
 
-  virtual bool range_of_expr (irange &r, tree name, gimple *stmt);
-  virtual bool range_on_edge (irange &r, edge e, tree expr);
-  bool block_range (irange &r, basic_block bb, tree name, bool calc = true);
+  virtual bool range_of_expr (vrange &r, tree name, gimple *stmt);
+  virtual bool range_on_edge (vrange &r, edge e, tree expr);
+  bool block_range (vrange &r, basic_block bb, tree name, bool calc = true);
 
-  bool get_global_range (irange &r, tree name) const;
-  bool get_global_range (irange &r, tree name, bool &current_p);
-  void set_global_range (tree name, const irange &r);
+  bool get_global_range (vrange &r, tree name) const;
+  bool get_global_range (vrange &r, tree name, bool &current_p);
+  void set_global_range (tree name, const vrange &r);
 
   void propagate_updated_value (tree name, basic_block bb);
 
@@ -106,11 +106,11 @@  private:
       RFD_READ_ONLY,	// Scan DOM tree, do not write to cache.
       RFD_FILL		// Scan DOM tree, updating important nodes.
     };
-  bool range_from_dom (irange &r, tree name, basic_block bb, enum rfd_mode);
-  void range_of_def (irange &r, tree name, basic_block bb = NULL);
-  void entry_range (irange &r, tree expr, basic_block bb, enum rfd_mode);
-  void exit_range (irange &r, tree expr, basic_block bb, enum rfd_mode);
-  bool edge_range (irange &r, edge e, tree name, enum rfd_mode);
+  bool range_from_dom (vrange &r, tree name, basic_block bb, enum rfd_mode);
+  void range_of_def (vrange &r, tree name, basic_block bb = NULL);
+  void entry_range (vrange &r, tree expr, basic_block bb, enum rfd_mode);
+  void exit_range (vrange &r, tree expr, basic_block bb, enum rfd_mode);
+  bool edge_range (vrange &r, edge e, tree name, enum rfd_mode);
 
   vec<basic_block> m_workback;
   class update_list *m_update;
diff --git a/gcc/gimple-range-edge.cc b/gcc/gimple-range-edge.cc
index 5264e627c9a..6fe33408f7e 100644
--- a/gcc/gimple-range-edge.cc
+++ b/gcc/gimple-range-edge.cc
@@ -83,11 +83,8 @@  gimple_outgoing_range::~gimple_outgoing_range ()
 // Use a cached value if it exists, or calculate it if not.
 
 bool
-gimple_outgoing_range::get_edge_range (irange &r, gimple *s, edge e)
+gimple_outgoing_range::switch_edge_range (irange &r, gswitch *sw, edge e)
 {
-  gcc_checking_assert (is_a<gswitch *> (s));
-  gswitch *sw = as_a<gswitch *> (s);
-
   // ADA currently has cases where the index is 64 bits and the case
   // arguments are 32 bit, causing a trap when we create a case_range.
   // Until this is resolved (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87798)
@@ -204,12 +201,9 @@  gimple_outgoing_range::edge_range_p (irange &r, edge e)
 
   gcc_checking_assert (is_a<gswitch *> (s));
   gswitch *sw = as_a<gswitch *> (s);
-  tree type = TREE_TYPE (gimple_switch_index (sw));
-
-  if (!irange::supports_type_p (type))
-    return NULL;
 
-  if (get_edge_range (r, sw, e))
+  // Switches can only be integers.
+  if (switch_edge_range (as_a <irange> (r), sw, e))
     return s;
 
   return NULL;
diff --git a/gcc/gimple-range-edge.h b/gcc/gimple-range-edge.h
index ce383b0aa6f..a9c4af8715b 100644
--- a/gcc/gimple-range-edge.h
+++ b/gcc/gimple-range-edge.h
@@ -43,7 +43,7 @@  public:
   gimple *edge_range_p (irange &r, edge e);
 private:
   void calc_switch_ranges (gswitch *sw);
-  bool get_edge_range (irange &r, gimple *s, edge e);
+  bool switch_edge_range (irange &r, gswitch *sw, edge e);
 
   int m_max_edges;
   hash_map<edge, irange *> *m_edge_table;
diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc
index c53d2863d5e..7fed5a99513 100644
--- a/gcc/gimple-range-fold.cc
+++ b/gcc/gimple-range-fold.cc
@@ -60,7 +60,7 @@  fur_source::fur_source (range_query *q)
 // Invoke range_of_expr on EXPR.
 
 bool
-fur_source::get_operand (irange &r, tree expr)
+fur_source::get_operand (vrange &r, tree expr)
 {
   return m_query->range_of_expr (r, expr);
 }
@@ -69,7 +69,7 @@  fur_source::get_operand (irange &r, tree expr)
 // range_query to get the range on the edge.
 
 bool
-fur_source::get_phi_operand (irange &r, tree expr, edge e)
+fur_source::get_phi_operand (vrange &r, tree expr, edge e)
 {
   return m_query->range_on_edge (r, e, expr);
 }
@@ -109,8 +109,8 @@  class fur_edge : public fur_source
 {
 public:
   fur_edge (edge e, range_query *q = NULL);
-  virtual bool get_operand (irange &r, tree expr) override;
-  virtual bool get_phi_operand (irange &r, tree expr, edge e) override;
+  virtual bool get_operand (vrange &r, tree expr) override;
+  virtual bool get_phi_operand (vrange &r, tree expr, edge e) override;
 private:
   edge m_edge;
 };
@@ -126,7 +126,7 @@  fur_edge::fur_edge (edge e, range_query *q) : fur_source (q)
 // Get the value of EXPR on edge m_edge.
 
 bool
-fur_edge::get_operand (irange &r, tree expr)
+fur_edge::get_operand (vrange &r, tree expr)
 {
   return m_query->range_on_edge (r, m_edge, expr);
 }
@@ -135,7 +135,7 @@  fur_edge::get_operand (irange &r, tree expr)
 // range_query to get the range on the edge.
 
 bool
-fur_edge::get_phi_operand (irange &r, tree expr, edge e)
+fur_edge::get_phi_operand (vrange &r, tree expr, edge e)
 {
   // Edge to edge recalculations not supoprted yet, until we sort it out.
   gcc_checking_assert (e == m_edge);
@@ -152,7 +152,7 @@  fur_stmt::fur_stmt (gimple *s, range_query *q) : fur_source (q)
 // Retreive range of EXPR as it occurs as a use on stmt M_STMT.
 
 bool
-fur_stmt::get_operand (irange &r, tree expr)
+fur_stmt::get_operand (vrange &r, tree expr)
 {
   return m_query->range_of_expr (r, expr, m_stmt);
 }
@@ -161,7 +161,7 @@  fur_stmt::get_operand (irange &r, tree expr)
 // range_query to get the range on the edge.
 
 bool
-fur_stmt::get_phi_operand (irange &r, tree expr, edge e)
+fur_stmt::get_phi_operand (vrange &r, tree expr, edge e)
 {
   // Pick up the range of expr from edge E.
   fur_edge e_src (e, m_query);
@@ -214,42 +214,42 @@  fur_depend::register_relation (edge e, relation_kind k, tree op1, tree op2)
 class fur_list : public fur_source
 {
 public:
-  fur_list (irange &r1);
-  fur_list (irange &r1, irange &r2);
-  fur_list (unsigned num, irange *list);
-  virtual bool get_operand (irange &r, tree expr) override;
-  virtual bool get_phi_operand (irange &r, tree expr, edge e) override;
+  fur_list (vrange &r1);
+  fur_list (vrange &r1, vrange &r2);
+  fur_list (unsigned num, vrange **list);
+  virtual bool get_operand (vrange &r, tree expr) override;
+  virtual bool get_phi_operand (vrange &r, tree expr, edge e) override;
 private:
-  int_range_max m_local[2];
-  irange *m_list;
+  vrange *m_local[2];
+  vrange **m_list;
   unsigned m_index;
   unsigned m_limit;
 };
 
 // One range supplied for unary operations.
 
-fur_list::fur_list (irange &r1) : fur_source (NULL)
+fur_list::fur_list (vrange &r1) : fur_source (NULL)
 {
   m_list = m_local;
   m_index = 0;
   m_limit = 1;
-  m_local[0] = r1;
+  m_local[0] = &r1;
 }
 
 // Two ranges supplied for binary operations.
 
-fur_list::fur_list (irange &r1, irange &r2) : fur_source (NULL)
+fur_list::fur_list (vrange &r1, vrange &r2) : fur_source (NULL)
 {
   m_list = m_local;
   m_index = 0;
   m_limit = 2;
-  m_local[0] = r1;
-  m_local[1] = r2;
+  m_local[0] = &r1;
+  m_local[1] = &r2;
 }
 
 // Arbitrary number of ranges in a vector.
 
-fur_list::fur_list (unsigned num, irange *list) : fur_source (NULL)
+fur_list::fur_list (unsigned num, vrange **list) : fur_source (NULL)
 {
   m_list = list;
   m_index = 0;
@@ -259,18 +259,18 @@  fur_list::fur_list (unsigned num, irange *list) : fur_source (NULL)
 // Get the next operand from the vector, ensure types are compatible.
 
 bool
-fur_list::get_operand (irange &r, tree expr)
+fur_list::get_operand (vrange &r, tree expr)
 {
   if (m_index >= m_limit)
     return m_query->range_of_expr (r, expr);
-  r = m_list[m_index++];
+  r = *m_list[m_index++];
   gcc_checking_assert (range_compatible_p (TREE_TYPE (expr), r.type ()));
   return true;
 }
 
 // This will simply pick the next operand from the vector.
 bool
-fur_list::get_phi_operand (irange &r, tree expr, edge e ATTRIBUTE_UNUSED)
+fur_list::get_phi_operand (vrange &r, tree expr, edge e ATTRIBUTE_UNUSED)
 {
   return get_operand (r, expr);
 }
@@ -278,7 +278,7 @@  fur_list::get_phi_operand (irange &r, tree expr, edge e ATTRIBUTE_UNUSED)
 // Fold stmt S into range R using R1 as the first operand.
 
 bool
-fold_range (irange &r, gimple *s, irange &r1)
+fold_range (vrange &r, gimple *s, vrange &r1)
 {
   fold_using_range f;
   fur_list src (r1);
@@ -288,7 +288,7 @@  fold_range (irange &r, gimple *s, irange &r1)
 // Fold stmt S into range R using R1  and R2 as the first two operands.
 
 bool
-fold_range (irange &r, gimple *s, irange &r1, irange &r2)
+fold_range (vrange &r, gimple *s, vrange &r1, vrange &r2)
 {
   fold_using_range f;
   fur_list src (r1, r2);
@@ -299,7 +299,7 @@  fold_range (irange &r, gimple *s, irange &r1, irange &r2)
 // operands encountered.
 
 bool
-fold_range (irange &r, gimple *s, unsigned num_elements, irange *vector)
+fold_range (vrange &r, gimple *s, unsigned num_elements, vrange **vector)
 {
   fold_using_range f;
   fur_list src (num_elements, vector);
@@ -309,7 +309,7 @@  fold_range (irange &r, gimple *s, unsigned num_elements, irange *vector)
 // Fold stmt S into range R using range query Q.
 
 bool
-fold_range (irange &r, gimple *s, range_query *q)
+fold_range (vrange &r, gimple *s, range_query *q)
 {
   fold_using_range f;
   fur_stmt src (s, q);
@@ -319,7 +319,7 @@  fold_range (irange &r, gimple *s, range_query *q)
 // Recalculate stmt S into R using range query Q as if it were on edge ON_EDGE.
 
 bool
-fold_range (irange &r, gimple *s, edge on_edge, range_query *q)
+fold_range (vrange &r, gimple *s, edge on_edge, range_query *q)
 {
   fold_using_range f;
   fur_edge src (on_edge, q);
@@ -370,7 +370,7 @@  adjust_pointer_diff_expr (irange &res, const gimple *diff_stmt)
 // Adjust the range for an IMAGPART_EXPR.
 
 static void
-adjust_imagpart_expr (irange &res, const gimple *stmt)
+adjust_imagpart_expr (vrange &res, const gimple *stmt)
 {
   tree name = TREE_OPERAND (gimple_assign_rhs1 (stmt), 0);
 
@@ -413,7 +413,7 @@  adjust_imagpart_expr (irange &res, const gimple *stmt)
 // Adjust the range for a REALPART_EXPR.
 
 static void
-adjust_realpart_expr (irange &res, const gimple *stmt)
+adjust_realpart_expr (vrange &res, const gimple *stmt)
 {
   tree name = TREE_OPERAND (gimple_assign_rhs1 (stmt), 0);
 
@@ -442,12 +442,12 @@  adjust_realpart_expr (irange &res, const gimple *stmt)
 // this statement.
 
 static void
-gimple_range_adjustment (irange &res, const gimple *stmt)
+gimple_range_adjustment (vrange &res, const gimple *stmt)
 {
   switch (gimple_expr_code (stmt))
     {
     case POINTER_DIFF_EXPR:
-      adjust_pointer_diff_expr (res, stmt);
+      adjust_pointer_diff_expr (as_a <irange> (res), stmt);
       return;
 
     case IMAGPART_EXPR:
@@ -536,7 +536,7 @@  gimple_range_operand2 (const gimple *stmt)
 // be calculated, return false.
 
 bool
-fold_using_range::fold_stmt (irange &r, gimple *s, fur_source &src, tree name)
+fold_using_range::fold_stmt (vrange &r, gimple *s, fur_source &src, tree name)
 {
   bool res = false;
   // If name and S are specified, make sure it is an LHS of S.
@@ -549,7 +549,7 @@  fold_using_range::fold_stmt (irange &r, gimple *s, fur_source &src, tree name)
   // Process addresses.
   if (gimple_code (s) == GIMPLE_ASSIGN
       && gimple_assign_rhs_code (s) == ADDR_EXPR)
-    return range_of_address (r, s, src);
+    return range_of_address (as_a <irange> (r), s, src);
 
   if (range_op_handler (s))
     res = range_of_range_op (r, s, src);
@@ -566,7 +566,7 @@  fold_using_range::fold_stmt (irange &r, gimple *s, fur_source &src, tree name)
       if (!name || !gimple_range_ssa_p (name))
 	return false;
       // We don't understand the stmt, so return the global range.
-      r = gimple_range_global (name);
+      gimple_range_global (r, name);
       return true;
     }
 
@@ -587,9 +587,8 @@  fold_using_range::fold_stmt (irange &r, gimple *s, fur_source &src, tree name)
 // If a range cannot be calculated, return false.
 
 bool
-fold_using_range::range_of_range_op (irange &r, gimple *s, fur_source &src)
+fold_using_range::range_of_range_op (vrange &r, gimple *s, fur_source &src)
 {
-  int_range_max range1, range2;
   tree type = gimple_range_type (s);
   if (!type)
     return false;
@@ -599,13 +598,16 @@  fold_using_range::range_of_range_op (irange &r, gimple *s, fur_source &src)
   tree lhs = gimple_get_lhs (s);
   tree op1 = gimple_range_operand1 (s);
   tree op2 = gimple_range_operand2 (s);
+  tmp_range range1 (TREE_TYPE (op1));
+  tmp_range range2;
 
   if (src.get_operand (range1, op1))
     {
       if (!op2)
 	{
 	  // Fold range, and register any dependency if available.
-	  int_range<2> r2 (type);
+	  tmp_range r2 (type);
+	  r2.set_varying (type);
 	  handler.fold_range (r, type, range1, r2);
 	  if (lhs && gimple_range_ssa_p (op1))
 	    {
@@ -617,7 +619,8 @@  fold_using_range::range_of_range_op (irange &r, gimple *s, fur_source &src)
 		src.register_relation (s, rel, lhs, op1);
 	    }
 	}
-      else if (src.get_operand (range2, op2))
+      else if (range2.init (TREE_TYPE (op2))
+	       && src.get_operand (range2, op2))
 	{
 	  relation_kind rel = src.query_relation (op1, op2);
 	  if (dump_file && (dump_flags & TDF_DETAILS) && rel != VREL_VARYING)
@@ -630,7 +633,8 @@  fold_using_range::range_of_range_op (irange &r, gimple *s, fur_source &src)
 	    }
 	  // Fold range, and register any dependency if available.
 	  handler.fold_range (r, type, range1, range2, rel);
-	  relation_fold_and_or (r, s, src);
+	  if (irange::supports_type_p (type))
+	    relation_fold_and_or (as_a <irange> (r), s, src);
 	  if (lhs)
 	    {
 	      if (src.gori ())
@@ -663,7 +667,8 @@  fold_using_range::range_of_range_op (irange &r, gimple *s, fur_source &src)
 		e0 = NULL;
 	      if (!single_pred_p (e1->dest))
 		e1 = NULL;
-	      src.register_outgoing_edges (as_a<gcond *> (s), r, e0, e1);
+	      src.register_outgoing_edges (as_a<gcond *> (s),
+					   as_a <irange> (r), e0, e1);
 	    }
 	}
       else
@@ -729,12 +734,12 @@  fold_using_range::range_of_address (irange &r, gimple *stmt, fur_source &src)
 	{
 	  /* For -fdelete-null-pointer-checks -fno-wrapv-pointer we don't
 	     allow going from non-NULL pointer to NULL.  */
-	  if (!range_includes_zero_p (&r))
+	  if (r.undefined_p () || !r.contains_p (build_zero_cst (r.type ())))
 	    {
 	      /* We could here instead adjust r by off >> LOG2_BITS_PER_UNIT
 		 using POINTER_PLUS_EXPR if off_cst and just fall back to
 		 this.  */
-	      r = range_nonzero (TREE_TYPE (gimple_assign_rhs1 (stmt)));
+	      r.set_nonzero (TREE_TYPE (gimple_assign_rhs1 (stmt)));
 	      return true;
 	    }
 	}
@@ -746,22 +751,22 @@  fold_using_range::range_of_address (irange &r, gimple *stmt, fur_source &src)
 	  && known_ne (off, 0)
 	  && (flag_delete_null_pointer_checks || known_gt (off, 0)))
 	{
-	  r = range_nonzero (TREE_TYPE (gimple_assign_rhs1 (stmt)));
+	  r.set_nonzero (TREE_TYPE (gimple_assign_rhs1 (stmt)));
 	  return true;
 	}
-      r = int_range<2> (TREE_TYPE (gimple_assign_rhs1 (stmt)));
+      r.set_varying (TREE_TYPE (gimple_assign_rhs1 (stmt)));
       return true;
     }
 
   // Handle "= &a".
   if (tree_single_nonzero_warnv_p (expr, &strict_overflow_p))
     {
-      r = range_nonzero (TREE_TYPE (gimple_assign_rhs1 (stmt)));
+      r.set_nonzero (TREE_TYPE (gimple_assign_rhs1 (stmt)));
       return true;
     }
 
   // Otherwise return varying.
-  r = int_range<2> (TREE_TYPE (gimple_assign_rhs1 (stmt)));
+  r.set_varying (TREE_TYPE (gimple_assign_rhs1 (stmt)));
   return true;
 }
 
@@ -769,12 +774,12 @@  fold_using_range::range_of_address (irange &r, gimple *stmt, fur_source &src)
 // If a range cannot be calculated, return false.
 
 bool
-fold_using_range::range_of_phi (irange &r, gphi *phi, fur_source &src)
+fold_using_range::range_of_phi (vrange &r, gphi *phi, fur_source &src)
 {
   tree phi_def = gimple_phi_result (phi);
   tree type = gimple_range_type (phi);
-  int_range_max arg_range;
-  int_range_max equiv_range;
+  tmp_range arg_range (type);
+  tmp_range equiv_range (type);
   unsigned x;
 
   if (!type)
@@ -881,7 +886,7 @@  fold_using_range::range_of_phi (irange &r, gphi *phi, fur_source &src)
 // If a range cannot be calculated, return false.
 
 bool
-fold_using_range::range_of_call (irange &r, gcall *call, fur_source &src)
+fold_using_range::range_of_call (vrange &r, gcall *call, fur_source &src)
 {
   tree type = gimple_range_type (call);
   if (!type)
@@ -893,18 +898,18 @@  fold_using_range::range_of_call (irange &r, gcall *call, fur_source &src)
   if (range_of_builtin_call (r, call, src))
     ;
   else if (gimple_stmt_nonnegative_warnv_p (call, &strict_overflow_p))
-    r.set (build_int_cst (type, 0), TYPE_MAX_VALUE (type));
+    r.set_nonnegative (type);
   else if (gimple_call_nonnull_result_p (call)
 	   || gimple_call_nonnull_arg (call))
-    r = range_nonzero (type);
+    r.set_nonzero (type);
   else
     r.set_varying (type);
 
   // If there is an LHS, intersect that with what is known.
   if (lhs)
     {
-      value_range def;
-      def = gimple_range_global (lhs);
+      tmp_range def (TREE_TYPE (lhs));
+      gimple_range_global (def, lhs);
       r.intersect (def);
     }
   return true;
@@ -971,13 +976,30 @@  get_letter_range (tree type, irange &lowers, irange &uppers)
 // TRUE.  Otherwise return FALSE.
 
 bool
-fold_using_range::range_of_builtin_call (irange &r, gcall *call,
+fold_using_range::range_of_builtin_call (vrange &r, gcall *call,
 					 fur_source &src)
 {
   combined_fn func = gimple_call_combined_fn (call);
   if (func == CFN_LAST)
     return false;
 
+  tree type = gimple_range_type (call);
+  gcc_checking_assert (type);
+
+  if (irange::supports_type_p (type))
+    return range_of_builtin_int_call (as_a <irange> (r), call, src);
+
+  return false;
+}
+
+bool
+fold_using_range::range_of_builtin_int_call (irange &r, gcall *call,
+					     fur_source &src)
+{
+  combined_fn func = gimple_call_combined_fn (call);
+  if (func == CFN_LAST)
+    return false;
+
   tree type = gimple_range_type (call);
   tree arg;
   int mini, maxi, zerov = 0, prec;
@@ -1256,9 +1278,8 @@  fold_using_range::range_of_builtin_call (irange &r, gcall *call,
 // If a range cannot be calculated, return false.
 
 bool
-fold_using_range::range_of_cond_expr  (irange &r, gassign *s, fur_source &src)
+fold_using_range::range_of_cond_expr  (vrange &r, gassign *s, fur_source &src)
 {
-  int_range_max cond_range, range1, range2;
   tree cond = gimple_assign_rhs1 (s);
   tree op1 = gimple_assign_rhs2 (s);
   tree op2 = gimple_assign_rhs3 (s);
@@ -1267,6 +1288,9 @@  fold_using_range::range_of_cond_expr  (irange &r, gassign *s, fur_source &src)
   if (!type)
     return false;
 
+  tmp_range range1 (TREE_TYPE (op1));
+  tmp_range range2 (TREE_TYPE (op2));
+  tmp_range cond_range (TREE_TYPE (cond));
   gcc_checking_assert (gimple_assign_rhs_code (s) == COND_EXPR);
   gcc_checking_assert (range_compatible_p (TREE_TYPE (op1), TREE_TYPE (op2)));
   src.get_operand (cond_range, cond);
@@ -1438,7 +1462,6 @@  fold_using_range::relation_fold_and_or (irange& lhs_range, gimple *s,
 void
 fur_source::register_outgoing_edges (gcond *s, irange &lhs_range, edge e0, edge e1)
 {
-  int_range_max r;
   int_range<2> e0_range, e1_range;
   tree name;
   basic_block bb = gimple_bb (s);
@@ -1505,6 +1528,7 @@  fur_source::register_outgoing_edges (gcond *s, irange &lhs_range, edge e0, edge
 	continue;
       tree ssa1 = gimple_range_ssa_p (gimple_range_operand1 (stmt));
       tree ssa2 = gimple_range_ssa_p (gimple_range_operand2 (stmt));
+      tmp_range r (TREE_TYPE (name));
       if (ssa1 && ssa2)
 	{
 	  if (e0 && gori ()->outgoing_edge_range_p (r, e0, name, *m_query)
diff --git a/gcc/gimple-range-fold.h b/gcc/gimple-range-fold.h
index 4b5d4b6e0b8..df24280ee40 100644
--- a/gcc/gimple-range-fold.h
+++ b/gcc/gimple-range-fold.h
@@ -23,7 +23,7 @@  along with GCC; see the file COPYING3.  If not see
 #define GCC_GIMPLE_RANGE_FOLD_H
 
 // This file is the main include point for gimple range folding.
-// These routines will fold stmt S into the result irange R.
+// These routines will fold stmt S into the result range R.
 // Any ssa_names on the stmt will be calculated using the range_query
 // parameter via a call to range_of_expr.
 // If no range_query is provided, current global range info will be used.
@@ -31,15 +31,15 @@  along with GCC; see the file COPYING3.  If not see
 // it appeared on that edge.
 
 // Fold stmt S into range R using range query Q.
-bool fold_range (irange &r, gimple *s, range_query *q = NULL);
+bool fold_range (vrange &r, gimple *s, range_query *q = NULL);
 // Recalculate stmt S into R using range query Q as if it were on edge ON_EDGE.
-bool fold_range (irange &r, gimple *s, edge on_edge, range_query *q = NULL);
+bool fold_range (vrange &v, gimple *s, edge on_edge, range_query *q = NULL);
 
 // These routines the operands to be specified when manually folding.
 // Any excess queries will be drawn from the current range_query.
-bool fold_range (irange &r, gimple *s, irange &r1);
-bool fold_range (irange &r, gimple *s, irange &r1, irange &r2);
-bool fold_range (irange &r, gimple *s, unsigned num_elements, irange *vector);
+bool fold_range (vrange &r, gimple *s, vrange &r1);
+bool fold_range (vrange &r, gimple *s, vrange &r1, vrange &r2);
+bool fold_range (vrange &r, gimple *s, unsigned num_elements, vrange **vector);
 
 // Return the type of range which statement S calculates.  If the type is
 // unsupported or no type can be determined, return NULL_TREE.
@@ -66,7 +66,7 @@  gimple_range_type (const gimple *s)
 	    type = TREE_TYPE (type);
 	}
     }
-  if (type && irange::supports_type_p (type))
+  if (type && vrange::supports_type_p (type))
     return type;
   return NULL_TREE;
 }
@@ -79,7 +79,7 @@  gimple_range_ssa_p (tree exp)
   if (exp && TREE_CODE (exp) == SSA_NAME &&
       !SSA_NAME_IS_VIRTUAL_OPERAND (exp) &&
       !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (exp) &&
-      irange::supports_type_p (TREE_TYPE (exp)))
+      vrange::supports_type_p (TREE_TYPE (exp)))
     return exp;
   return NULL_TREE;
 }
@@ -108,8 +108,8 @@  public:
   fur_source (range_query *q = NULL);
   inline range_query *query () { return m_query; }
   inline class gori_compute *gori () { return m_gori; };
-  virtual bool get_operand (irange &r, tree expr);
-  virtual bool get_phi_operand (irange &r, tree expr, edge e);
+  virtual bool get_operand (vrange &r, tree expr);
+  virtual bool get_phi_operand (vrange &r, tree expr, edge e);
   virtual relation_kind query_relation (tree op1, tree op2);
   virtual void register_relation (gimple *stmt, relation_kind k, tree op1,
 				  tree op2);
@@ -128,8 +128,8 @@  class fur_stmt : public fur_source
 {
 public:
   fur_stmt (gimple *s, range_query *q = NULL);
-  virtual bool get_operand (irange &r, tree expr) override;
-  virtual bool get_phi_operand (irange &r, tree expr, edge e) override;
+  virtual bool get_operand (vrange &r, tree expr) override;
+  virtual bool get_phi_operand (vrange &r, tree expr, edge e) override;
   virtual relation_kind query_relation (tree op1, tree op2) override;
 private:
   gimple *m_stmt;
@@ -161,17 +161,18 @@  extern tree gimple_range_operand2 (const gimple *s);
 class fold_using_range
 {
 public:
-  bool fold_stmt (irange &r, gimple *s, class fur_source &src,
+  bool fold_stmt (vrange &r, gimple *s, class fur_source &src,
 		  tree name = NULL_TREE);
 protected:
-  bool range_of_range_op (irange &r, gimple *s, fur_source &src);
-  bool range_of_call (irange &r, gcall *call, fur_source &src);
-  bool range_of_cond_expr (irange &r, gassign* cond, fur_source &src);
+  bool range_of_range_op (vrange &r, gimple *s, fur_source &src);
+  bool range_of_call (vrange &r, gcall *call, fur_source &src);
+  bool range_of_cond_expr (vrange &r, gassign* cond, fur_source &src);
   bool range_of_address (irange &r, gimple *s, fur_source &src);
-  bool range_of_builtin_call (irange &r, gcall *call, fur_source &src);
+  bool range_of_builtin_call (vrange &r, gcall *call, fur_source &src);
+  bool range_of_builtin_int_call (irange &r, gcall *call, fur_source &src);
   void range_of_builtin_ubsan_call (irange &r, gcall *call, tree_code code,
 				    fur_source &src);
-  bool range_of_phi (irange &r, gphi *phi, fur_source &src);
+  bool range_of_phi (vrange &r, gphi *phi, fur_source &src);
   void range_of_ssa_name_with_loop_info (irange &, tree, class loop *, gphi *,
 					 fur_source &src);
   void relation_fold_and_or (irange& lhs_range, gimple *s, fur_source &src);
diff --git a/gcc/gimple-range-gori.cc b/gcc/gimple-range-gori.cc
index 0e0cf2128e7..47d0dab8cb9 100644
--- a/gcc/gimple-range-gori.cc
+++ b/gcc/gimple-range-gori.cc
@@ -34,7 +34,7 @@  along with GCC; see the file COPYING3.  If not see
 // LHS_RANGE.  Return false if nothing can be determined.
 
 bool
-gimple_range_calc_op1 (irange &r, const gimple *stmt, const irange &lhs_range)
+gimple_range_calc_op1 (vrange &r, const gimple *stmt, const vrange &lhs_range)
 {
   gcc_checking_assert (gimple_num_ops (stmt) < 3);
   // Give up on empty ranges.
@@ -55,8 +55,8 @@  gimple_range_calc_op1 (irange &r, const gimple *stmt, const irange &lhs_range)
 // nothing can be determined.
 
 bool
-gimple_range_calc_op1 (irange &r, const gimple *stmt,
-		       const irange &lhs_range, const irange &op2_range)
+gimple_range_calc_op1 (vrange &r, const gimple *stmt,
+		       const vrange &lhs_range, const vrange &op2_range)
 {
   // Give up on empty ranges.
   if (lhs_range.undefined_p ())
@@ -86,8 +86,8 @@  gimple_range_calc_op1 (irange &r, const gimple *stmt,
 // nothing can be determined.
 
 bool
-gimple_range_calc_op2 (irange &r, const gimple *stmt,
-		       const irange &lhs_range, const irange &op1_range)
+gimple_range_calc_op2 (vrange &r, const gimple *stmt,
+		       const vrange &lhs_range, const vrange &op1_range)
 {
   // Give up on empty ranges.
   if (lhs_range.undefined_p ())
@@ -663,8 +663,8 @@  gori_compute::gori_compute (int not_executable_flag)
 // was not resolvable.
 
 bool
-gori_compute::compute_operand_range_switch (irange &r, gswitch *s,
-					    const irange &lhs,
+gori_compute::compute_operand_range_switch (vrange &r, gswitch *s,
+					    const vrange &lhs,
 					    tree name, fur_source &src)
 {
   tree op1 = gimple_switch_index (s);
@@ -691,8 +691,8 @@  gori_compute::compute_operand_range_switch (irange &r, gswitch *s,
 // store the evaluation in R, otherwise return FALSE.
 
 bool
-gori_compute::compute_operand_range (irange &r, gimple *stmt,
-				     const irange &lhs, tree name,
+gori_compute::compute_operand_range (vrange &r, gimple *stmt,
+				     const vrange &lhs, tree name,
 				     fur_source &src)
 {
   // If the lhs doesn't tell us anything, neither will unwinding further.
@@ -743,13 +743,18 @@  gori_compute::compute_operand_range (irange &r, gimple *stmt,
 	  print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
 	}
 
-      int_range_max op1_trange, op1_frange;
-      int_range_max op2_trange, op2_frange;
-      compute_logical_operands (op1_trange, op1_frange, stmt, lhs,
+      tree type = TREE_TYPE (name);
+      tmp_range op1_trange (type), op1_frange (type);
+      tmp_range op2_trange (type), op2_frange (type);
+      compute_logical_operands (op1_trange, op1_frange, stmt,
+				as_a <irange> (lhs),
 				name, src, op1, op1_in_chain);
-      compute_logical_operands (op2_trange, op2_frange, stmt, lhs,
+      compute_logical_operands (op2_trange, op2_frange, stmt,
+				as_a <irange> (lhs),
 				name, src, op2, op2_in_chain);
-      res = logical_combine (r, gimple_expr_code (stmt), lhs,
+      res = logical_combine (r,
+			     gimple_expr_code (stmt),
+			     as_a <irange> (lhs),
 			     op1_trange, op1_frange, op2_trange, op2_frange);
       if (idx)
 	tracer.trailer (idx, "compute_operand", res, name, r);
@@ -789,10 +794,10 @@  range_is_either_true_or_false (const irange &r)
 // the LHS.
 
 bool
-gori_compute::logical_combine (irange &r, enum tree_code code,
+gori_compute::logical_combine (vrange &r, enum tree_code code,
 			       const irange &lhs,
-			       const irange &op1_true, const irange &op1_false,
-			       const irange &op2_true, const irange &op2_false)
+			       const vrange &op1_true, const vrange &op1_false,
+			       const vrange &op2_true, const vrange &op2_false)
 {
   if (op1_true.varying_p () && op1_false.varying_p ()
       && op2_true.varying_p () && op2_false.varying_p ())
@@ -868,7 +873,7 @@  gori_compute::logical_combine (irange &r, enum tree_code code,
   if (!range_is_either_true_or_false (lhs))
     {
       bool res;
-      int_range_max r1;
+      tmp_range r1 (r);
       if (logical_combine (r1, code, m_bool_zero, op1_true, op1_false,
 			   op2_true, op2_false)
 	  && logical_combine (r, code, m_bool_one, op1_true, op1_false,
@@ -898,11 +903,11 @@  gori_compute::logical_combine (irange &r, enum tree_code code,
 	else
 	  {
 	    // The FALSE side is the union of the other 3 cases.
-	    int_range_max ff (op1_false);
+	    tmp_range ff (op1_false);
 	    ff.intersect (op2_false);
-	    int_range_max tf (op1_true);
+	    tmp_range tf (op1_true);
 	    tf.intersect (op2_false);
-	    int_range_max ft (op1_false);
+	    tmp_range ft (op1_false);
 	    ft.intersect (op2_true);
 	    r = ff;
 	    r.union_ (tf);
@@ -925,11 +930,11 @@  gori_compute::logical_combine (irange &r, enum tree_code code,
 	  {
 	    // The TRUE side of an OR operation will be the union of
 	    // the other three combinations.
-	    int_range_max tt (op1_true);
+	    tmp_range tt (op1_true);
 	    tt.intersect (op2_true);
-	    int_range_max tf (op1_true);
+	    tmp_range tf (op1_true);
 	    tf.intersect (op2_false);
-	    int_range_max ft (op1_false);
+	    tmp_range ft (op1_false);
 	    ft.intersect (op2_true);
 	    r = tt;
 	    r.union_ (tf);
@@ -951,7 +956,7 @@  gori_compute::logical_combine (irange &r, enum tree_code code,
 // OP_IN_CHAIN is true.
 
 void
-gori_compute::compute_logical_operands (irange &true_range, irange &false_range,
+gori_compute::compute_logical_operands (vrange &true_range, vrange &false_range,
 					gimple *stmt,
 					const irange &lhs,
 					tree name, fur_source &src,
@@ -1007,13 +1012,15 @@  gori_compute::compute_logical_operands (irange &true_range, irange &false_range,
 // R, or false if no range could be calculated.
 
 bool
-gori_compute::compute_operand1_range (irange &r, gimple *stmt,
-				      const irange &lhs, tree name,
+gori_compute::compute_operand1_range (vrange &r, gimple *stmt,
+				      const vrange &lhs, tree name,
 				      fur_source &src)
 {
-  int_range_max op1_range, op2_range;
   tree op1 = gimple_range_operand1 (stmt);
   tree op2 = gimple_range_operand2 (stmt);
+  tmp_range op1_range (TREE_TYPE (op1));
+  tmp_range tmp (TREE_TYPE (op1));
+  tmp_range op2_range;
 
   // Fetch the known range for op1 in this block.
   src.get_operand (op1_range, op1);
@@ -1021,8 +1028,9 @@  gori_compute::compute_operand1_range (irange &r, gimple *stmt,
   // Now range-op calcuate and put that result in r.
   if (op2)
     {
+      op2_range.init (TREE_TYPE (op2));
       src.get_operand (op2_range, op2);
-      if (!gimple_range_calc_op1 (r, stmt, lhs, op2_range))
+      if (!gimple_range_calc_op1 (tmp, stmt, lhs, op2_range))
 	return false;
     }
   else
@@ -1030,7 +1038,7 @@  gori_compute::compute_operand1_range (irange &r, gimple *stmt,
       // We pass op1_range to the unary operation.  Nomally it's a
       // hidden range_for_type parameter, but sometimes having the
       // actual range can result in better information.
-      if (!gimple_range_calc_op1 (r, stmt, lhs, op1_range))
+      if (!gimple_range_calc_op1 (tmp, stmt, lhs, op1_range))
 	return false;
     }
 
@@ -1053,7 +1061,7 @@  gori_compute::compute_operand1_range (irange &r, gimple *stmt,
       tracer.print (idx, "Computes ");
       print_generic_expr (dump_file, op1, TDF_SLIM);
       fprintf (dump_file, " = ");
-      r.dump (dump_file);
+      tmp.dump (dump_file);
       fprintf (dump_file, " intersect Known range : ");
       op1_range.dump (dump_file);
       fputc ('\n', dump_file);
@@ -1061,13 +1069,14 @@  gori_compute::compute_operand1_range (irange &r, gimple *stmt,
   // Intersect the calculated result with the known result and return if done.
   if (op1 == name)
     {
-      r.intersect (op1_range);
+      tmp.intersect (op1_range);
+      r = tmp;
       if (idx)
 	tracer.trailer (idx, "produces ", true, name, r);
       return true;
     }
   // If the calculation continues, we're using op1_range as the new LHS.
-  op1_range.intersect (r);
+  op1_range.intersect (tmp);
 
   if (idx)
     tracer.trailer (idx, "produces ", true, op1, op1_range);
@@ -1084,19 +1093,21 @@  gori_compute::compute_operand1_range (irange &r, gimple *stmt,
 // R, or false if no range could be calculated.
 
 bool
-gori_compute::compute_operand2_range (irange &r, gimple *stmt,
-				      const irange &lhs, tree name,
+gori_compute::compute_operand2_range (vrange &r, gimple *stmt,
+				      const vrange &lhs, tree name,
 				      fur_source &src)
 {
-  int_range_max op1_range, op2_range;
   tree op1 = gimple_range_operand1 (stmt);
   tree op2 = gimple_range_operand2 (stmt);
+  tmp_range op1_range (TREE_TYPE (op1));
+  tmp_range op2_range (TREE_TYPE (op2));
+  tmp_range tmp (TREE_TYPE (op2));
 
   src.get_operand (op1_range, op1);
   src.get_operand (op2_range, op2);
 
   // Intersect with range for op2 based on lhs and op1.
-  if (!gimple_range_calc_op2 (r, stmt, lhs, op1_range))
+  if (!gimple_range_calc_op2 (tmp, stmt, lhs, op1_range))
     return false;
 
   unsigned idx;
@@ -1118,7 +1129,7 @@  gori_compute::compute_operand2_range (irange &r, gimple *stmt,
       tracer.print (idx, "Computes ");
       print_generic_expr (dump_file, op2, TDF_SLIM);
       fprintf (dump_file, " = ");
-      r.dump (dump_file);
+      tmp.dump (dump_file);
       fprintf (dump_file, " intersect Known range : ");
       op2_range.dump (dump_file);
       fputc ('\n', dump_file);
@@ -1126,13 +1137,14 @@  gori_compute::compute_operand2_range (irange &r, gimple *stmt,
   // Intersect the calculated result with the known result and return if done.
   if (op2 == name)
     {
-      r.intersect (op2_range);
+      tmp.intersect (op2_range);
+      r = tmp;
       if (idx)
 	tracer.trailer (idx, " produces ", true, NULL_TREE, r);
       return true;
     }
   // If the calculation continues, we're using op2_range as the new LHS.
-  op2_range.intersect (r);
+  op2_range.intersect (tmp);
 
   if (idx)
     tracer.trailer (idx, " produces ", true, op2, op2_range);
@@ -1149,13 +1161,13 @@  gori_compute::compute_operand2_range (irange &r, gimple *stmt,
 // R, or false if no range could be calculated.
 
 bool
-gori_compute::compute_operand1_and_operand2_range (irange &r,
+gori_compute::compute_operand1_and_operand2_range (vrange &r,
 						   gimple *stmt,
-						   const irange &lhs,
+						   const vrange &lhs,
 						   tree name,
 						   fur_source &src)
 {
-  int_range_max op_range;
+  tmp_range op_range (TREE_TYPE (name));
 
   // Calculate a good a range for op2.  Since op1 == op2, this will
   // have already included whatever the actual range of name is.
@@ -1236,10 +1248,9 @@  gori_compute::has_edge_range_p (tree name, edge e)
 // control edge or NAME is not defined by this edge.
 
 bool
-gori_compute::outgoing_edge_range_p (irange &r, edge e, tree name,
+gori_compute::outgoing_edge_range_p (vrange &r, edge e, tree name,
 				     range_query &q)
 {
-  int_range_max lhs;
   unsigned idx;
 
   if ((e->flags & m_not_executable_flag))
@@ -1252,6 +1263,7 @@  gori_compute::outgoing_edge_range_p (irange &r, edge e, tree name,
     }
 
   gcc_checking_assert (gimple_range_ssa_p (name));
+  int_range_max lhs;
   // Determine if there is an outgoing edge.
   gimple *stmt = outgoing.edge_range_p (lhs, e);
   if (!stmt)
@@ -1312,10 +1324,9 @@  gori_compute::outgoing_edge_range_p (irange &r, edge e, tree name,
 // edge and OP2 on the false edge.
 
 bool
-gori_compute::condexpr_adjust (irange &r1, irange &r2, gimple *, tree cond,
+gori_compute::condexpr_adjust (vrange &r1, vrange &r2, gimple *, tree cond,
 			       tree op1, tree op2, fur_source &src)
 {
-  int_range_max tmp, cond_true, cond_false;
   tree ssa1 = gimple_range_ssa_p (op1);
   tree ssa2 = gimple_range_ssa_p (op2);
   if (!ssa1 && !ssa2)
@@ -1341,15 +1352,19 @@  gori_compute::condexpr_adjust (irange &r1, irange &r2, gimple *, tree cond,
     return false;
 
   // Pick up the current values of each part of the condition.
-  int_range_max cl, cr;
-  src.get_operand (cl, gimple_assign_rhs1 (cond_def));
-  src.get_operand (cr, gimple_assign_rhs2 (cond_def));
+  tree rhs1 = gimple_assign_rhs1 (cond_def);
+  tree rhs2 = gimple_assign_rhs2 (cond_def);
+  tmp_range cl (TREE_TYPE (rhs1));
+  tmp_range cr (TREE_TYPE (rhs2));
+  src.get_operand (cl, rhs1);
+  src.get_operand (cr, rhs2);
 
   tree cond_name = c1 ? c1 : c2;
   gimple *def_stmt = SSA_NAME_DEF_STMT (cond_name);
 
   // Evaluate the value of COND_NAME on the true and false edges, using either
   // the op1 or op2 routines based on its location.
+  tmp_range cond_true (type), cond_false (type);
   if (c1)
     {
       if (!hand.op1_range (cond_false, type, m_bool_zero, cr))
@@ -1380,6 +1395,7 @@  gori_compute::condexpr_adjust (irange &r1, irange &r2, gimple *, tree cond,
     }
 
    // Now solve for SSA1 or SSA2 if they are in the dependency chain.
+  tmp_range tmp (type);
    if (ssa1 && in_chain_p (ssa1, cond_name))
     {
       if (compute_operand_range (tmp, def_stmt, cond_true, ssa1, src))
diff --git a/gcc/gimple-range-gori.h b/gcc/gimple-range-gori.h
index 605884e2e53..f5f691fe424 100644
--- a/gcc/gimple-range-gori.h
+++ b/gcc/gimple-range-gori.h
@@ -121,7 +121,7 @@  private:
 //   on *ANY* edge that has been seen.  FALSE indicates that the global value
 //   is applicable everywhere that has been processed.
 //
-// outgoing_edge_range_p (irange &range, edge e, tree name)
+// outgoing_edge_range_p (vrange &range, edge e, tree name)
 //   Actually does the calculation of RANGE for name on E
 //   This represents application of whatever static range effect edge E
 //   may have on NAME, not any cumulative effect.
@@ -157,8 +157,8 @@  class gori_compute : public gori_map
 {
 public:
   gori_compute (int not_executable_flag = 0);
-  bool outgoing_edge_range_p (irange &r, edge e, tree name, range_query &q);
-  bool condexpr_adjust (irange &r1, irange &r2, gimple *s, tree cond, tree op1,
+  bool outgoing_edge_range_p (vrange &r, edge e, tree name, range_query &q);
+  bool condexpr_adjust (vrange &r1, vrange &r2, gimple *s, tree cond, tree op1,
 			tree op2, fur_source &src);
   bool has_edge_range_p (tree name, basic_block bb = NULL);
   bool has_edge_range_p (tree name, edge e);
@@ -166,24 +166,24 @@  public:
 private:
   bool may_recompute_p (tree name, edge e);
   bool may_recompute_p (tree name, basic_block bb = NULL);
-  bool compute_operand_range (irange &r, gimple *stmt, const irange &lhs,
+  bool compute_operand_range (vrange &r, gimple *stmt, const vrange &lhs,
 			      tree name, class fur_source &src);
-  bool compute_operand_range_switch (irange &r, gswitch *s, const irange &lhs,
+  bool compute_operand_range_switch (vrange &r, gswitch *s, const vrange &lhs,
 				     tree name, fur_source &src);
-  bool compute_operand1_range (irange &r, gimple *stmt, const irange &lhs,
+  bool compute_operand1_range (vrange &r, gimple *stmt, const vrange &lhs,
 			       tree name, fur_source &src);
-  bool compute_operand2_range (irange &r, gimple *stmt, const irange &lhs,
+  bool compute_operand2_range (vrange &r, gimple *stmt, const vrange &lhs,
 			       tree name, fur_source &src);
-  bool compute_operand1_and_operand2_range (irange &r, gimple *stmt,
-					    const irange &lhs, tree name,
+  bool compute_operand1_and_operand2_range (vrange &r, gimple *stmt,
+					    const vrange &lhs, tree name,
 					    fur_source &src);
-  void compute_logical_operands (irange &true_range, irange &false_range,
+  void compute_logical_operands (vrange &true_range, vrange &false_range,
 				 gimple *stmt, const irange &lhs,
 				 tree name, fur_source &src, tree op,
 				 bool op_in_chain);
-  bool logical_combine (irange &r, enum tree_code code, const irange &lhs,
-			const irange &op1_true, const irange &op1_false,
-			const irange &op2_true, const irange &op2_false);
+  bool logical_combine (vrange &r, enum tree_code code, const irange &lhs,
+			const vrange &op1_true, const vrange &op1_false,
+			const vrange &op2_true, const vrange &op2_false);
   int_range<2> m_bool_zero;	// Boolean false cached.
   int_range<2> m_bool_one;	// Boolean true cached.
 
@@ -193,14 +193,14 @@  private:
 };
 
 // These routines provide a GIMPLE interface to the range-ops code.
-extern bool gimple_range_calc_op1 (irange &r, const gimple *s,
-				   const irange &lhs_range);
-extern bool gimple_range_calc_op1 (irange &r, const gimple *s,
-				   const irange &lhs_range,
-				   const irange &op2_range);
-extern bool gimple_range_calc_op2 (irange &r, const gimple *s,
-				   const irange &lhs_range,
-				   const irange &op1_range);
+extern bool gimple_range_calc_op1 (vrange &r, const gimple *s,
+				   const vrange &lhs_range);
+extern bool gimple_range_calc_op1 (vrange &r, const gimple *s,
+				   const vrange &lhs_range,
+				   const vrange &op2_range);
+extern bool gimple_range_calc_op2 (vrange &r, const gimple *s,
+				   const vrange &lhs_range,
+				   const vrange &op1_range);
 
 // For each name that is an import into BB's exports..
 #define FOR_EACH_GORI_IMPORT_NAME(gori, bb, name)			\
diff --git a/gcc/gimple-range-path.cc b/gcc/gimple-range-path.cc
index 66f433dd1d5..4819332f358 100644
--- a/gcc/gimple-range-path.cc
+++ b/gcc/gimple-range-path.cc
@@ -83,7 +83,7 @@  path_range_query::clear_cache (tree name)
 // If NAME has a cache entry, return it in R, and return TRUE.
 
 inline bool
-path_range_query::get_cache (irange &r, tree name)
+path_range_query::get_cache (vrange &r, tree name)
 {
   if (!gimple_range_ssa_p (name))
     return get_global_range_query ()->range_of_expr (r, name);
@@ -98,7 +98,7 @@  path_range_query::get_cache (irange &r, tree name)
 // Set the cache entry for NAME to R.
 
 void
-path_range_query::set_cache (const irange &r, tree name)
+path_range_query::set_cache (const vrange &r, tree name)
 {
   unsigned v = SSA_NAME_VERSION (name);
   bitmap_set_bit (m_has_cache_entry, v);
@@ -149,7 +149,7 @@  path_range_query::defined_outside_path (tree name)
 // Return the range of NAME on entry to the path.
 
 void
-path_range_query::range_on_path_entry (irange &r, tree name)
+path_range_query::range_on_path_entry (vrange &r, tree name)
 {
   gcc_checking_assert (defined_outside_path (name));
   basic_block entry = entry_bb ();
@@ -168,7 +168,7 @@  path_range_query::range_on_path_entry (irange &r, tree name)
   // block.  This can happen when we're querying a block with only an
   // outgoing edge (no statement but the fall through edge), but for
   // which we can determine a range on entry to the block.
-  int_range_max tmp;
+  tmp_range tmp (TREE_TYPE (name));
   bool changed = false;
   r.set_undefined ();
   for (unsigned i = 0; i < EDGE_COUNT (entry->preds); ++i)
@@ -190,9 +190,9 @@  path_range_query::range_on_path_entry (irange &r, tree name)
 // Return the range of NAME at the end of the path being analyzed.
 
 bool
-path_range_query::internal_range_of_expr (irange &r, tree name, gimple *stmt)
+path_range_query::internal_range_of_expr (vrange &r, tree name, gimple *stmt)
 {
-  if (!irange::supports_type_p (TREE_TYPE (name)))
+  if (!vrange::supports_type_p (TREE_TYPE (name)))
     return false;
 
   if (get_cache (r, name))
@@ -209,18 +209,22 @@  path_range_query::internal_range_of_expr (irange &r, tree name, gimple *stmt)
       && range_defined_in_block (r, name, gimple_bb (stmt)))
     {
       if (TREE_CODE (name) == SSA_NAME)
-	r.intersect (gimple_range_global (name));
+	{
+	  tmp_range glob (TREE_TYPE (name));
+	  gimple_range_global (glob, name);
+	  r.intersect (glob);
+	}
 
       set_cache (r, name);
       return true;
     }
 
-  r = gimple_range_global (name);
+  gimple_range_global (r, name);
   return true;
 }
 
 bool
-path_range_query::range_of_expr (irange &r, tree name, gimple *stmt)
+path_range_query::range_of_expr (vrange &r, tree name, gimple *stmt)
 {
   if (internal_range_of_expr (r, name, stmt))
     {
@@ -269,7 +273,7 @@  path_range_query::ssa_defined_in_bb (tree name, basic_block bb)
 // calculating the PHI's range must not trigger additional lookups.
 
 void
-path_range_query::ssa_range_in_phi (irange &r, gphi *phi)
+path_range_query::ssa_range_in_phi (vrange &r, gphi *phi)
 {
   tree name = gimple_phi_result (phi);
   basic_block bb = gimple_bb (phi);
@@ -283,7 +287,7 @@  path_range_query::ssa_range_in_phi (irange &r, gphi *phi)
       // Try to fold the phi exclusively with global or cached values.
       // This will get things like PHI <5(99), 6(88)>.  We do this by
       // calling range_of_expr with no context.
-      int_range_max arg_range;
+      tmp_range arg_range (TREE_TYPE (name));
       r.set_undefined ();
       for (size_t i = 0; i < nargs; ++i)
 	{
@@ -312,7 +316,7 @@  path_range_query::ssa_range_in_phi (irange &r, gphi *phi)
 	  {
 	    if (m_resolve)
 	      {
-		int_range_max tmp;
+		tmp_range tmp (TREE_TYPE (name));
 		// Using both the range on entry to the path, and the
 		// range on this edge yields significantly better
 		// results.
@@ -335,7 +339,7 @@  path_range_query::ssa_range_in_phi (irange &r, gphi *phi)
 // TRUE.  Otherwise, return FALSE.
 
 bool
-path_range_query::range_defined_in_block (irange &r, tree name, basic_block bb)
+path_range_query::range_defined_in_block (vrange &r, tree name, basic_block bb)
 {
   gimple *def_stmt = SSA_NAME_DEF_STMT (name);
   basic_block def_bb = gimple_bb (def_stmt);
@@ -377,7 +381,6 @@  path_range_query::range_defined_in_block (irange &r, tree name, basic_block bb)
 void
 path_range_query::compute_ranges_in_phis (basic_block bb)
 {
-  int_range_max r;
   auto_bitmap phi_set;
 
   // PHIs must be resolved simultaneously on entry to the block
@@ -390,7 +393,11 @@  path_range_query::compute_ranges_in_phis (basic_block bb)
       gphi *phi = iter.phi ();
       tree name = gimple_phi_result (phi);
 
-      if (import_p (name) && range_defined_in_block (r, name, bb))
+      if (!import_p (name))
+	continue;
+
+      tmp_range r (TREE_TYPE (name));
+      if (range_defined_in_block (r, name, bb))
 	{
 	  unsigned v = SSA_NAME_VERSION (name);
 	  set_cache (r, name);
@@ -423,7 +430,6 @@  void
 path_range_query::compute_ranges_in_block (basic_block bb)
 {
   bitmap_iterator bi;
-  int_range_max r, cached_range;
   unsigned i;
 
   if (m_resolve && !at_entry ())
@@ -444,6 +450,7 @@  path_range_query::compute_ranges_in_block (basic_block bb)
   EXECUTE_IF_SET_IN_BITMAP (m_imports, 0, i, bi)
     {
       tree name = ssa_name (i);
+      tmp_range r (TREE_TYPE (name));
 
       if (gimple_code (SSA_NAME_DEF_STMT (name)) != GIMPLE_PHI
 	  && range_defined_in_block (r, name, bb))
@@ -480,8 +487,10 @@  path_range_query::compute_ranges_in_block (basic_block bb)
 
       if (bitmap_bit_p (exports, i))
 	{
+	  tmp_range r (TREE_TYPE (name));
 	  if (g.outgoing_edge_range_p (r, e, name, *this))
 	    {
+	      tmp_range cached_range (TREE_TYPE (name));
 	      if (get_cache (cached_range, name))
 		r.intersect (cached_range);
 
@@ -539,7 +548,7 @@  bool
 path_range_query::add_to_imports (tree name, bitmap imports)
 {
   if (TREE_CODE (name) == SSA_NAME
-      && irange::supports_type_p (TREE_TYPE (name)))
+      && vrange::supports_type_p (TREE_TYPE (name)))
     return bitmap_set_bit (imports, SSA_NAME_VERSION (name));
   return false;
 }
@@ -751,11 +760,11 @@  jt_fur_source::query_relation (tree op1, tree op2)
 // Return the range of STMT at the end of the path being analyzed.
 
 bool
-path_range_query::range_of_stmt (irange &r, gimple *stmt, tree)
+path_range_query::range_of_stmt (vrange &r, gimple *stmt, tree)
 {
   tree type = gimple_range_type (stmt);
 
-  if (!type || !irange::supports_type_p (type))
+  if (!type || !vrange::supports_type_p (type))
     return false;
 
   // If resolving unknowns, fold the statement making use of any
diff --git a/gcc/gimple-range-path.h b/gcc/gimple-range-path.h
index 914983bb0aa..2c4624e4cef 100644
--- a/gcc/gimple-range-path.h
+++ b/gcc/gimple-range-path.h
@@ -38,29 +38,29 @@  public:
 		       const bitmap_head *imports = NULL);
   void compute_ranges (edge e);
   void compute_imports (bitmap imports, basic_block exit);
-  bool range_of_expr (irange &r, tree name, gimple * = NULL) override;
-  bool range_of_stmt (irange &r, gimple *, tree name = NULL) override;
+  bool range_of_expr (vrange &r, tree name, gimple * = NULL) override;
+  bool range_of_stmt (vrange &r, gimple *, tree name = NULL) override;
   bool unreachable_path_p ();
   void dump (FILE *) override;
   void debug ();
 
 private:
-  bool internal_range_of_expr (irange &r, tree name, gimple *);
+  bool internal_range_of_expr (vrange &r, tree name, gimple *);
   bool defined_outside_path (tree name);
-  void range_on_path_entry (irange &r, tree name);
+  void range_on_path_entry (vrange &r, tree name);
   path_oracle *get_path_oracle () { return (path_oracle *)m_oracle; }
 
   // Cache manipulation.
-  void set_cache (const irange &r, tree name);
-  bool get_cache (irange &r, tree name);
+  void set_cache (const vrange &r, tree name);
+  bool get_cache (vrange &r, tree name);
   void clear_cache (tree name);
 
   // Methods to compute ranges for the given path.
-  bool range_defined_in_block (irange &, tree name, basic_block bb);
+  bool range_defined_in_block (vrange &, tree name, basic_block bb);
   void compute_ranges_in_block (basic_block bb);
   void compute_ranges_in_phis (basic_block bb);
   void adjust_for_non_null_uses (basic_block bb);
-  void ssa_range_in_phi (irange &r, gphi *phi);
+  void ssa_range_in_phi (vrange &r, gphi *phi);
   void compute_outgoing_relations (basic_block bb, basic_block next);
   void compute_phi_relations (basic_block bb, basic_block prev);
   void maybe_register_phi_relation (gphi *, edge e);
diff --git a/gcc/gimple-range-side-effect.cc b/gcc/gimple-range-side-effect.cc
index 8d2ac35bc8d..aae087b7227 100644
--- a/gcc/gimple-range-side-effect.cc
+++ b/gcc/gimple-range-side-effect.cc
@@ -58,7 +58,7 @@  non_null_loadstore (gimple *, tree op, tree, void *data)
 // Add NAME and RANGE to the the side effect summary.
 
 void
-stmt_side_effects::add_range (tree name, irange &range)
+stmt_side_effects::add_range (tree name, vrange &range)
 {
   m_names[num_args] = name;
   m_ranges[num_args] = range;
@@ -126,7 +126,7 @@  class exit_range
 {
 public:
   tree name;
-  irange *range;
+  vrange *range;
   exit_range *next;
 };
 
@@ -181,7 +181,7 @@  side_effect_manager::~side_effect_manager ()
 // Return a non-zero range value of the appropriate type for NAME from
 // the cache, creating it if necessary.
 
-const irange&
+const vrange&
 side_effect_manager::get_nonzero (tree name)
 {
   unsigned v = SSA_NAME_VERSION (name);
@@ -189,10 +189,8 @@  side_effect_manager::get_nonzero (tree name)
     m_nonzero.safe_grow_cleared (num_ssa_names + 20);
   if (!m_nonzero[v])
     {
-      tree type = TREE_TYPE (name);
-      m_nonzero[v]
-	= static_cast <irange *> (m_range_allocator.alloc_vrange (type));
-      m_nonzero[v]->set_nonzero (type);
+      m_nonzero[v] = m_range_allocator.alloc_vrange (TREE_TYPE (name));
+      m_nonzero[v]->set_nonzero (TREE_TYPE (name));
     }
   return *(m_nonzero[v]);
 }
@@ -219,7 +217,7 @@  side_effect_manager::has_range_p (tree name, basic_block bb)
 // to include it.
 
 bool
-side_effect_manager::maybe_adjust_range (irange &r, tree name, basic_block bb)
+side_effect_manager::maybe_adjust_range (vrange &r, tree name, basic_block bb)
 {
   if (!has_range_p (name, bb))
     return false;
@@ -232,7 +230,7 @@  side_effect_manager::maybe_adjust_range (irange &r, tree name, basic_block bb)
 // Add range R as a side effect for NAME in block BB.
 
 void
-side_effect_manager::add_range (tree name, basic_block bb, const irange &r)
+side_effect_manager::add_range (tree name, basic_block bb, const vrange &r)
 {
   if (bb->index >= (int)m_on_exit.length ())
     m_on_exit.safe_grow_cleared (last_basic_block_for_fn (cfun) + 1);
@@ -254,7 +252,7 @@  side_effect_manager::add_range (tree name, basic_block bb, const irange &r)
   exit_range *ptr = m_on_exit[bb->index].find_ptr (name);
   if (ptr)
     {
-      int_range_max cur = r;
+      tmp_range cur (r);
       // If no new info is added, just return.
       if (!cur.intersect (*(ptr->range)))
 	return;
@@ -263,7 +261,7 @@  side_effect_manager::add_range (tree name, basic_block bb, const irange &r)
       else
 	{
 	  vrange &v = cur;
-	  ptr->range = static_cast <irange *> (m_range_allocator.clone (v));
+	  ptr->range = m_range_allocator.clone (v);
 	}
       return;
     }
diff --git a/gcc/gimple-range-side-effect.h b/gcc/gimple-range-side-effect.h
index d76d6eb34f2..a7625646ed1 100644
--- a/gcc/gimple-range-side-effect.h
+++ b/gcc/gimple-range-side-effect.h
@@ -33,15 +33,15 @@  public:
   inline unsigned num () const { return num_args; }
   inline tree name (unsigned index) const
     { gcc_checking_assert (index < num_args); return m_names[index]; }
-  inline const irange& range (unsigned index) const
+  inline const vrange& range (unsigned index) const
     { gcc_checking_assert (index < num_args); return m_ranges[index]; }
-  void add_range (tree name, irange &range);
+  void add_range (tree name, vrange &range);
   void add_nonzero (tree name);
 private:
   unsigned num_args;
   static const int size_limit = 10;
   tree m_names[size_limit];
-  int_range<3> m_ranges[size_limit];
+  tmp_range m_ranges[size_limit];
   inline void bump_index () { if (num_args < size_limit - 1) num_args++; }
 };
 
@@ -56,10 +56,10 @@  class side_effect_manager
 public:
   side_effect_manager (bool do_search);
   ~side_effect_manager ();
-  void add_range (tree name, basic_block bb, const irange &r);
+  void add_range (tree name, basic_block bb, const vrange &r);
   void add_nonzero (tree name, basic_block bb);
   bool has_range_p (tree name, basic_block bb);
-  bool maybe_adjust_range (irange &r, tree name, basic_block bb);
+  bool maybe_adjust_range (vrange &r, tree name, basic_block bb);
 private:
   class exit_range_head
   {
@@ -71,8 +71,8 @@  private:
   };
   void register_all_uses (tree name);
   vec <exit_range_head> m_on_exit;
-  const irange &get_nonzero (tree name);
-  vec <irange *> m_nonzero;
+  const vrange &get_nonzero (tree name);
+  vec <vrange *> m_nonzero;
   bitmap m_seen;
   bitmap_obstack m_bitmaps;
   struct obstack m_list_obstack;
diff --git a/gcc/gimple-range-tests.cc b/gcc/gimple-range-tests.cc
index 572acd33d7f..84ecc486889 100644
--- a/gcc/gimple-range-tests.cc
+++ b/gcc/gimple-range-tests.cc
@@ -42,8 +42,9 @@  public:
     ASSERT_TRUE (r == expect);
   }
 
-  virtual bool range_of_expr (irange &r, tree expr, gimple * = NULL) override
+  virtual bool range_of_expr (vrange &v, tree expr, gimple * = NULL) override
   {
+    irange &r = as_a <irange> (v);
     if (expr == op0)
       {
 	r.set (build_int_cst (type, 5), build_int_cst (type, 10));
diff --git a/gcc/gimple-range-trace.cc b/gcc/gimple-range-trace.cc
index 39971093e6d..37cf37ca885 100644
--- a/gcc/gimple-range-trace.cc
+++ b/gcc/gimple-range-trace.cc
@@ -102,7 +102,7 @@  range_tracer::print (unsigned counter, const char *str)
 
 void
 range_tracer::trailer (unsigned counter, const char *caller, bool result,
-		      tree name, const irange &r)
+		      tree name, const vrange &r)
 {
   gcc_checking_assert (tracing && counter != 0);
 
@@ -141,7 +141,6 @@  debug_seed_ranger (gimple_ranger &ranger)
     }
 
   basic_block bb;
-  int_range_max r;
   gimple_stmt_iterator gsi;
   FOR_EACH_BB_FN (bb, cfun)
     for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
@@ -151,7 +150,11 @@  debug_seed_ranger (gimple_ranger &ranger)
 	if (is_gimple_debug (stmt))
 	  continue;
 
-	ranger.range_of_stmt (r, stmt);
+	if (tree type = gimple_range_type (stmt))
+	  {
+	    tmp_range r (type);
+	    ranger.range_of_stmt (r, stmt);
+	  }
       }
 }
 
diff --git a/gcc/gimple-range-trace.h b/gcc/gimple-range-trace.h
index 302afda3104..3f92e51803b 100644
--- a/gcc/gimple-range-trace.h
+++ b/gcc/gimple-range-trace.h
@@ -32,7 +32,7 @@  public:
   range_tracer (const char *name = "");
   unsigned header (const char *str);
   void trailer (unsigned counter, const char *caller, bool result, tree name,
-		const irange &r);
+		const vrange &r);
   void print (unsigned counter, const char *str);
   inline void enable_trace () { tracing = true; }
   inline void disable_trace () { tracing = false; }
diff --git a/gcc/gimple-range.cc b/gcc/gimple-range.cc
index 32d57c9e3db..1118feb41a5 100644
--- a/gcc/gimple-range.cc
+++ b/gcc/gimple-range.cc
@@ -71,7 +71,7 @@  gimple_ranger::~gimple_ranger ()
 }
 
 bool
-gimple_ranger::range_of_expr (irange &r, tree expr, gimple *stmt)
+gimple_ranger::range_of_expr (vrange &r, tree expr, gimple *stmt)
 {
   unsigned idx;
   if (!gimple_range_ssa_p (expr))
@@ -93,7 +93,7 @@  gimple_ranger::range_of_expr (irange &r, tree expr, gimple *stmt)
   // If there is no statement, just get the global value.
   if (!stmt)
     {
-      int_range_max tmp;
+      tmp_range tmp (TREE_TYPE (expr));
       m_cache.get_global_range (r, expr);
       // Pick up implied context information from the on-entry cache
       // if current_bb is set.  Do not attempt any new calculations.
@@ -137,9 +137,9 @@  gimple_ranger::range_of_expr (irange &r, tree expr, gimple *stmt)
 // Return the range of NAME on entry to block BB in R.
 
 void
-gimple_ranger::range_on_entry (irange &r, basic_block bb, tree name)
+gimple_ranger::range_on_entry (vrange &r, basic_block bb, tree name)
 {
-  int_range_max entry_range;
+  tmp_range entry_range (TREE_TYPE (name));
   gcc_checking_assert (gimple_range_ssa_p (name));
 
   unsigned idx;
@@ -164,7 +164,7 @@  gimple_ranger::range_on_entry (irange &r, basic_block bb, tree name)
 // Return false if no range can be calculated.
 
 void
-gimple_ranger::range_on_exit (irange &r, basic_block bb, tree name)
+gimple_ranger::range_on_exit (vrange &r, basic_block bb, tree name)
 {
   // on-exit from the exit block?
   gcc_checking_assert (bb != EXIT_BLOCK_PTR_FOR_FN (cfun));
@@ -198,10 +198,10 @@  gimple_ranger::range_on_exit (irange &r, basic_block bb, tree name)
 // Calculate a range for NAME on edge E and return it in R.
 
 bool
-gimple_ranger::range_on_edge (irange &r, edge e, tree name)
+gimple_ranger::range_on_edge (vrange &r, edge e, tree name)
 {
-  int_range_max edge_range;
-  gcc_checking_assert (irange::supports_type_p (TREE_TYPE (name)));
+  tmp_range edge_range (TREE_TYPE (name));
+  gcc_checking_assert (vrange::supports_type_p (TREE_TYPE (name)));
 
   // Do not process values along abnormal edges.
   if (e->flags & EDGE_ABNORMAL)
@@ -249,7 +249,7 @@  gimple_ranger::range_on_edge (irange &r, edge e, tree name)
 // fold_range wrapper for range_of_stmt to use as an internal client.
 
 bool
-gimple_ranger::fold_range_internal (irange &r, gimple *s, tree name)
+gimple_ranger::fold_range_internal (vrange &r, gimple *s, tree name)
 {
   fold_using_range f;
   fur_depend src (s, &(gori ()), this);
@@ -263,7 +263,7 @@  gimple_ranger::fold_range_internal (irange &r, gimple *s, tree name)
 // avoided.  If a range cannot be calculated, return false and UNDEFINED.
 
 bool
-gimple_ranger::range_of_stmt (irange &r, gimple *s, tree name)
+gimple_ranger::range_of_stmt (vrange &r, gimple *s, tree name)
 {
   bool res;
   r.set_undefined ();
@@ -313,7 +313,7 @@  gimple_ranger::range_of_stmt (irange &r, gimple *s, tree name)
 	prefill_stmt_dependencies (name);
 
       // Calculate a new value.
-      int_range_max tmp;
+      tmp_range tmp (TREE_TYPE (name));
       fold_range_internal (tmp, s, name);
 
       // Combine the new value with the old value.  This is required because
@@ -334,7 +334,7 @@  gimple_ranger::range_of_stmt (irange &r, gimple *s, tree name)
 // stack if so.  R is a scratch range.
 
 inline void
-gimple_ranger::prefill_name (irange &r, tree name)
+gimple_ranger::prefill_name (tmp_range &r, tree name)
 {
   if (!gimple_range_ssa_p (name))
     return;
@@ -343,6 +343,7 @@  gimple_ranger::prefill_name (irange &r, tree name)
     return;
 
   bool current;
+  r.init (TREE_TYPE (name));
   // If this op has not been processed yet, then push it on the stack
   if (!m_cache.get_global_range (r, name, current))
     m_stmt_list.safe_push (name);
@@ -357,7 +358,7 @@  gimple_ranger::prefill_stmt_dependencies (tree ssa)
   if (SSA_NAME_IS_DEFAULT_DEF (ssa))
     return;
 
-  int_range_max r;
+  tmp_range r;
   unsigned idx;
   gimple *stmt = SSA_NAME_DEF_STMT (ssa);
   gcc_checking_assert (stmt && gimple_bb (stmt));
@@ -388,6 +389,7 @@  gimple_ranger::prefill_stmt_dependencies (tree ssa)
 	    {
 	      // Fold and save the value for NAME.
 	      stmt = SSA_NAME_DEF_STMT (name);
+	      r.init (TREE_TYPE (name));
 	      fold_range_internal (r, stmt, name);
 	      // Make sure we don't lose any current global info.
 	      int_range_max tmp;
@@ -488,10 +490,11 @@  gimple_ranger::export_global_ranges ()
   bool print_header = true;
   for (unsigned x = 1; x < num_ssa_names; x++)
     {
-      int_range_max r;
+      tmp_range r;
       tree name = ssa_name (x);
       if (name && !SSA_NAME_IN_FREE_LIST (name)
 	  && gimple_range_ssa_p (name)
+	  && r.init (TREE_TYPE (name))
 	  && m_cache.get_global_range (r, name)
 	  && !r.varying_p())
 	{
@@ -508,13 +511,17 @@  gimple_ranger::export_global_ranges ()
 	      print_header = false;
 	    }
 
-	  value_range vr = r;
+	  if (!irange::supports_type_p (TREE_TYPE (name)))
+	    continue;
+
+	  vrange &v = r;
+	  value_range vr = as_a <irange> (v);
 	  print_generic_expr (dump_file, name , TDF_SLIM);
 	  fprintf (dump_file, "  : ");
 	  vr.dump (dump_file);
 	  fprintf (dump_file, "\n");
 	  int_range_max same = vr;
-	  if (same != r)
+	  if (same != as_a <irange> (v))
 	    {
 	      fprintf (dump_file, "         irange : ");
 	      r.dump (dump_file);
@@ -532,7 +539,7 @@  gimple_ranger::dump_bb (FILE *f, basic_block bb)
   unsigned x;
   edge_iterator ei;
   edge e;
-  int_range_max range, tmp_range;
+  tmp_range range, tmp_range;
   fprintf (f, "\n=========== BB %d ============\n", bb->index);
   m_cache.dump_bb (f, bb);
 
@@ -543,6 +550,7 @@  gimple_ranger::dump_bb (FILE *f, basic_block bb)
     {
       tree name = ssa_name (x);
       if (gimple_range_ssa_p (name) && SSA_NAME_DEF_STMT (name) &&
+	  range.init (TREE_TYPE (name)) &&
 	  gimple_bb (SSA_NAME_DEF_STMT (name)) == bb &&
 	  m_cache.get_global_range (range, name))
 	{
@@ -564,9 +572,11 @@  gimple_ranger::dump_bb (FILE *f, basic_block bb)
 	{
 	  tree name = gimple_range_ssa_p (ssa_name (x));
 	  if (name && gori ().has_edge_range_p (name, e)
+	      && range.init (TREE_TYPE (name))
 	      && m_cache.range_on_edge (range, e, name))
 	    {
 	      gimple *s = SSA_NAME_DEF_STMT (name);
+	      tmp_range.init (TREE_TYPE (name));
 	      // Only print the range if this is the def block, or
 	      // the on entry cache for either end of the edge is
 	      // set.
diff --git a/gcc/gimple-range.h b/gcc/gimple-range.h
index 13d4c77883e..ca5a33e65c6 100644
--- a/gcc/gimple-range.h
+++ b/gcc/gimple-range.h
@@ -48,11 +48,11 @@  class gimple_ranger : public range_query
 public:
   gimple_ranger (bool use_imm_uses = true);
   ~gimple_ranger ();
-  virtual bool range_of_stmt (irange &r, gimple *, tree name = NULL) override;
-  virtual bool range_of_expr (irange &r, tree name, gimple * = NULL) override;
-  virtual bool range_on_edge (irange &r, edge e, tree name) override;
-  void range_on_entry (irange &r, basic_block bb, tree name);
-  void range_on_exit (irange &r, basic_block bb, tree name);
+  virtual bool range_of_stmt (vrange &r, gimple *, tree name = NULL) override;
+  virtual bool range_of_expr (vrange &r, tree name, gimple * = NULL) override;
+  virtual bool range_on_edge (vrange &r, edge e, tree name) override;
+  void range_on_entry (vrange &r, basic_block bb, tree name);
+  void range_on_exit (vrange &r, basic_block bb, tree name);
   void export_global_ranges ();
   inline gori_compute &gori ()  { return m_cache.m_gori; }
   virtual void dump (FILE *f) override;
@@ -62,8 +62,8 @@  public:
   bool fold_stmt (gimple_stmt_iterator *gsi, tree (*) (tree));
   void register_side_effects (gimple *s);
 protected:
-  bool fold_range_internal (irange &r, gimple *s, tree name);
-  void prefill_name (irange &r, tree name);
+  bool fold_range_internal (vrange &r, gimple *s, tree name);
+  void prefill_name (tmp_range &r, tree name);
   void prefill_stmt_dependencies (tree ssa);
   ranger_cache m_cache;
   range_tracer tracer;
diff --git a/gcc/gimple-ssa-warn-access.cc b/gcc/gimple-ssa-warn-access.cc
index 9357a4e576a..132d82a5240 100644
--- a/gcc/gimple-ssa-warn-access.cc
+++ b/gcc/gimple-ssa-warn-access.cc
@@ -328,11 +328,11 @@  check_nul_terminated_array (GimpleOrTree expr, tree src, tree bound)
   wide_int bndrng[2];
   if (bound)
     {
-      value_range r;
+      tmp_range r (TREE_TYPE (bound));
 
       get_global_range_query ()->range_of_expr (r, bound);
 
-      if (r.kind () != VR_RANGE)
+      if (r.undefined_p () || r.varying_p ())
 	return true;
 
       bndrng[0] = r.lower_bound ();
@@ -2790,9 +2790,8 @@  memmodel_to_uhwi (tree ord, gimple *stmt, unsigned HOST_WIDE_INT *cstval)
     {
       /* Use the range query to determine constant values in the absence
 	 of constant propagation (such as at -O0).  */
-      value_range rng;
+      tmp_range rng (TREE_TYPE (ord));
       if (!get_range_query (cfun)->range_of_expr (rng, ord, stmt)
-	  || !rng.constant_p ()
 	  || !rng.singleton_p (&ord))
 	return false;
 
diff --git a/gcc/tree-ssa-loop-niter.cc b/gcc/tree-ssa-loop-niter.cc
index afa51064953..8907e310c19 100644
--- a/gcc/tree-ssa-loop-niter.cc
+++ b/gcc/tree-ssa-loop-niter.cc
@@ -221,7 +221,7 @@  refine_value_range_using_guard (tree type, tree var,
   get_type_static_bounds (type, mint, maxt);
   mpz_init (minc1);
   mpz_init (maxc1);
-  value_range r;
+  tmp_range r (TREE_TYPE (varc1));
   /* Setup range information for varc1.  */
   if (integer_zerop (varc1))
     {
@@ -374,7 +374,7 @@  determine_value_range (class loop *loop, tree type, tree var, mpz_t off,
       gphi_iterator gsi;
 
       /* Either for VAR itself...  */
-      value_range var_range;
+      tmp_range var_range (TREE_TYPE (var));
       get_range_query (cfun)->range_of_expr (var_range, var);
       rtype = var_range.kind ();
       if (!var_range.undefined_p ())
@@ -385,10 +385,10 @@  determine_value_range (class loop *loop, tree type, tree var, mpz_t off,
 
       /* Or for PHI results in loop->header where VAR is used as
 	 PHI argument from the loop preheader edge.  */
+      tmp_range phi_range (TREE_TYPE (var));
       for (gsi = gsi_start_phis (loop->header); !gsi_end_p (gsi); gsi_next (&gsi))
 	{
 	  gphi *phi = gsi.phi ();
-	  value_range phi_range;
 	  if (PHI_ARG_DEF_FROM_EDGE (phi, e) == var
 	      && get_range_query (cfun)->range_of_expr (phi_range,
 						    gimple_phi_result (phi))
@@ -410,7 +410,7 @@  determine_value_range (class loop *loop, tree type, tree var, mpz_t off,
 		     involved.  */
 		  if (wi::gt_p (minv, maxv, sgn))
 		    {
-		      value_range vr;
+		      tmp_range vr (TREE_TYPE (var));
 		      get_range_query (cfun)->range_of_expr (vr, var);
 		      rtype = vr.kind ();
 		      if (!vr.undefined_p ())
@@ -3650,7 +3650,7 @@  record_nonwrapping_iv (class loop *loop, tree base, tree step, gimple *stmt,
   if (tree_int_cst_sign_bit (step))
     {
       wide_int max;
-      value_range base_range;
+      tmp_range base_range (TREE_TYPE (orig_base));
       if (get_range_query (cfun)->range_of_expr (base_range, orig_base)
 	  && !base_range.undefined_p ())
 	max = base_range.upper_bound ();
@@ -3672,7 +3672,7 @@  record_nonwrapping_iv (class loop *loop, tree base, tree step, gimple *stmt,
   else
     {
       wide_int min;
-      value_range base_range;
+      tmp_range base_range (TREE_TYPE (orig_base));
       if (get_range_query (cfun)->range_of_expr (base_range, orig_base)
 	  && !base_range.undefined_p ())
 	min = base_range.lower_bound ();
@@ -3947,7 +3947,7 @@  infer_loop_bounds_from_signedness (class loop *loop, gimple *stmt)
 
   low = lower_bound_in_type (type, type);
   high = upper_bound_in_type (type, type);
-  value_range r;
+  tmp_range r (TREE_TYPE (def));
   get_range_query (cfun)->range_of_expr (r, def);
   if (r.kind () == VR_RANGE)
     {
@@ -4997,7 +4997,7 @@  scev_var_range_cant_overflow (tree var, tree step, class loop *loop)
   if (!def_bb || !dominated_by_p (CDI_DOMINATORS, loop->latch, def_bb))
     return false;
 
-  value_range r;
+  tmp_range r (TREE_TYPE (var));
   get_range_query (cfun)->range_of_expr (r, var);
   if (r.kind () != VR_RANGE)
     return false;
diff --git a/gcc/tree-ssa-threadedge.cc b/gcc/tree-ssa-threadedge.cc
index 4eb65ca7cac..d5e285d5d4d 100644
--- a/gcc/tree-ssa-threadedge.cc
+++ b/gcc/tree-ssa-threadedge.cc
@@ -1409,19 +1409,19 @@  tree
 hybrid_jt_simplifier::simplify (gimple *stmt, gimple *, basic_block,
 				jt_state *state)
 {
-  int_range_max r;
-
   compute_ranges_from_state (stmt, state);
 
   if (gimple_code (stmt) == GIMPLE_COND
       || gimple_code (stmt) == GIMPLE_ASSIGN)
     {
+      tmp_range r (gimple_range_type (stmt));
       tree ret;
       if (m_query->range_of_stmt (r, stmt) && r.singleton_p (&ret))
 	return ret;
     }
   else if (gimple_code (stmt) == GIMPLE_SWITCH)
     {
+      int_range_max r;
       gswitch *switch_stmt = dyn_cast <gswitch *> (stmt);
       tree index = gimple_switch_index (switch_stmt);
       if (m_query->range_of_expr (r, index, stmt))
diff --git a/gcc/value-query.cc b/gcc/value-query.cc
index 31e56eeae53..463ac179a00 100644
--- a/gcc/value-query.cc
+++ b/gcc/value-query.cc
@@ -57,13 +57,13 @@  value_query::value_of_stmt (gimple *stmt, tree name)
 // range_query default methods.
 
 bool
-range_query::range_on_edge (irange &r, edge, tree expr)
+range_query::range_on_edge (vrange &r, edge, tree expr)
 {
   return range_of_expr (r, expr);
 }
 
 bool
-range_query::range_of_stmt (irange &r, gimple *stmt, tree name)
+range_query::range_of_stmt (vrange &r, gimple *stmt, tree name)
 {
   if (!name)
     name = gimple_get_lhs (stmt);
@@ -79,11 +79,12 @@  tree
 range_query::value_of_expr (tree expr, gimple *stmt)
 {
   tree t;
-  int_range_max r;
 
-  if (!irange::supports_type_p (TREE_TYPE (expr)))
+  if (!vrange::supports_type_p (TREE_TYPE (expr)))
     return NULL_TREE;
 
+  tmp_range r (TREE_TYPE (expr));
+
   if (range_of_expr (r, expr, stmt))
     {
       // A constant used in an unreachable block oftens returns as UNDEFINED.
@@ -100,10 +101,10 @@  tree
 range_query::value_on_edge (edge e, tree expr)
 {
   tree t;
-  int_range_max r;
 
-  if (!irange::supports_type_p (TREE_TYPE (expr)))
+  if (!vrange::supports_type_p (TREE_TYPE (expr)))
     return NULL_TREE;
+  tmp_range r (TREE_TYPE (expr));
   if (range_on_edge (r, e, expr))
     {
       // A constant used in an unreachable block oftens returns as UNDEFINED.
@@ -121,15 +122,15 @@  tree
 range_query::value_of_stmt (gimple *stmt, tree name)
 {
   tree t;
-  int_range_max r;
 
   if (!name)
     name = gimple_get_lhs (stmt);
 
   gcc_checking_assert (!name || name == gimple_get_lhs (stmt));
 
-  if (!name || !irange::supports_type_p (TREE_TYPE (name)))
+  if (!name || !vrange::supports_type_p (TREE_TYPE (name)))
     return NULL_TREE;
+  tmp_range r (TREE_TYPE (name));
   if (range_of_stmt (r, stmt, name) && r.singleton_p (&t))
     return t;
   return NULL_TREE;
@@ -187,7 +188,7 @@  range_query::~range_query ()
 // representable, and UNDEFINED/false if not.
 
 bool
-range_query::get_tree_range (irange &r, tree expr, gimple *stmt)
+range_query::get_tree_range (vrange &r, tree expr, gimple *stmt)
 {
   tree type;
   if (TYPE_P (expr))
@@ -195,7 +196,7 @@  range_query::get_tree_range (irange &r, tree expr, gimple *stmt)
   else
     type = TREE_TYPE (expr);
 
-  if (!irange::supports_type_p (type))
+  if (!vrange::supports_type_p (type))
     {
       r.set_undefined ();
       return false;
@@ -214,7 +215,7 @@  range_query::get_tree_range (irange &r, tree expr, gimple *stmt)
       return true;
 
     case SSA_NAME:
-      r = gimple_range_global (expr);
+      gimple_range_global (r, expr);
       return true;
 
     case ADDR_EXPR:
@@ -223,7 +224,7 @@  range_query::get_tree_range (irange &r, tree expr, gimple *stmt)
 	bool ov;
 	if (tree_single_nonzero_warnv_p (expr, &ov))
 	  {
-	    r = range_nonzero (type);
+	    r.set_nonzero (type);
 	    return true;
 	  }
 	break;
@@ -237,7 +238,8 @@  range_query::get_tree_range (irange &r, tree expr, gimple *stmt)
       range_op_handler op (TREE_CODE (expr), type);
       if (op)
 	{
-	  int_range_max r0, r1;
+	  tmp_range r0 (TREE_TYPE (TREE_OPERAND (expr, 0)));
+	  tmp_range r1 (TREE_TYPE (TREE_OPERAND (expr, 1)));
 	  range_of_expr (r0, TREE_OPERAND (expr, 0), stmt);
 	  range_of_expr (r1, TREE_OPERAND (expr, 1), stmt);
 	  op.fold_range (r, type, r0, r1);
@@ -250,11 +252,13 @@  range_query::get_tree_range (irange &r, tree expr, gimple *stmt)
     {
       range_op_handler op (TREE_CODE (expr), type);
       tree op0_type = TREE_TYPE (TREE_OPERAND (expr, 0));
-      if (op && irange::supports_type_p (op0_type))
+      if (op && vrange::supports_type_p (op0_type))
 	{
-	  int_range_max r0;
+	  tmp_range r0 (TREE_TYPE (TREE_OPERAND (expr, 0)));
+	  tmp_range r1 (type);
+	  r1.set_varying (type);
 	  range_of_expr (r0, TREE_OPERAND (expr, 0), stmt);
-	  op.fold_range (r, type, r0, int_range<1> (type));
+	  op.fold_range (r, type, r0, r1);
 	}
       else
 	r.set_varying (type);
@@ -311,7 +315,7 @@  get_ssa_name_ptr_info_nonnull (const_tree name)
 // updated.
 
 bool
-update_global_range (irange &r, tree name)
+update_global_range (vrange &r, tree name)
 {
   tree type = TREE_TYPE (name);
 
@@ -330,8 +334,7 @@  update_global_range (irange &r, tree name)
       if (r.undefined_p ())
 	return false;
 
-      value_range vr = r;
-      set_range_info (name, vr);
+      set_range_info (name, as_a <irange> (r));
       return true;
     }
   else if (POINTER_TYPE_P (type))
@@ -349,7 +352,7 @@  update_global_range (irange &r, tree name)
 // return VARYING.
 
 static void
-get_range_global (irange &r, tree name)
+get_range_global (vrange &r, tree name)
 {
   tree type = TREE_TYPE (name);
 
@@ -369,7 +372,7 @@  get_range_global (irange &r, tree name)
 	    r.set_nonzero (type);
 	  else if (INTEGRAL_TYPE_P (type))
 	    {
-	      get_ssa_name_range_info (r, name);
+	      get_ssa_name_range_info (as_a <irange> (r), name);
 	      if (r.undefined_p ())
 		r.set_varying (type);
 	    }
@@ -384,7 +387,8 @@  get_range_global (irange &r, tree name)
    }
   else if (!POINTER_TYPE_P (type) && SSA_NAME_RANGE_INFO (name))
     {
-      get_ssa_name_range_info (r, name);
+      gcc_checking_assert (irange::supports_type_p (TREE_TYPE (name)));
+      get_ssa_name_range_info (as_a <irange> (r), name);
       if (r.undefined_p ())
 	r.set_varying (type);
     }
@@ -414,21 +418,19 @@  get_range_global (irange &r, tree name)
 // See discussion here:
 // https://gcc.gnu.org/pipermail/gcc-patches/2021-June/571709.html
 
-value_range
-gimple_range_global (tree name)
+void
+gimple_range_global (vrange &r, tree name)
 {
   tree type = TREE_TYPE (name);
-  gcc_checking_assert (TREE_CODE (name) == SSA_NAME
-		       && irange::supports_type_p (type));
+  gcc_checking_assert (TREE_CODE (name) == SSA_NAME);
 
   if (SSA_NAME_IS_DEFAULT_DEF (name) || (cfun && cfun->after_inlining)
       || is_a<gphi *> (SSA_NAME_DEF_STMT (name)))
     {
-      value_range vr;
-      get_range_global (vr, name);
-      return vr;
+      get_range_global (r, name);
+      return;
     }
-  return value_range (type);
+  r.set_varying (type);
 }
 
 // ----------------------------------------------
@@ -437,7 +439,7 @@  gimple_range_global (tree name)
 global_range_query global_ranges;
 
 bool
-global_range_query::range_of_expr (irange &r, tree expr, gimple *stmt)
+global_range_query::range_of_expr (vrange &r, tree expr, gimple *stmt)
 {
   tree type = TREE_TYPE (expr);
 
@@ -456,15 +458,16 @@  global_range_query::range_of_expr (irange &r, tree expr, gimple *stmt)
 relation_kind
 range_query::query_relation (gimple *s, tree ssa1, tree ssa2, bool get_range)
 {
-  int_range_max tmp;
   if (!m_oracle || TREE_CODE (ssa1) != SSA_NAME || TREE_CODE (ssa2) != SSA_NAME)
     return VREL_VARYING;
 
   // Ensure ssa1 and ssa2 have both been evaluated.
   if (get_range)
     {
-      range_of_expr (tmp, ssa1, s);
-      range_of_expr (tmp, ssa2, s);
+      tmp_range tmp1 (TREE_TYPE (ssa1));
+      tmp_range tmp2 (TREE_TYPE (ssa2));
+      range_of_expr (tmp1, ssa1, s);
+      range_of_expr (tmp2, ssa2, s);
     }
   return m_oracle->query_relation (gimple_bb (s), ssa1, ssa2);
 }
@@ -477,7 +480,6 @@  relation_kind
 range_query::query_relation (edge e, tree ssa1, tree ssa2, bool get_range)
 {
   basic_block bb;
-  int_range_max tmp;
   if (!m_oracle || TREE_CODE (ssa1) != SSA_NAME || TREE_CODE (ssa2) != SSA_NAME)
     return VREL_VARYING;
 
@@ -492,6 +494,7 @@  range_query::query_relation (edge e, tree ssa1, tree ssa2, bool get_range)
   // Ensure ssa1 and ssa2 have both been evaluated.
   if (get_range)
     {
+      tmp_range tmp (TREE_TYPE (ssa1));
       range_on_edge (tmp, e, ssa1);
       range_on_edge (tmp, e, ssa2);
     }
diff --git a/gcc/value-query.h b/gcc/value-query.h
index cf1a1d74de3..280e47e3f6b 100644
--- a/gcc/value-query.h
+++ b/gcc/value-query.h
@@ -89,9 +89,9 @@  public:
   //
   // Note that range_of_expr must always return TRUE unless ranges are
   // unsupported for EXPR's type (supports_type_p is false).
-  virtual bool range_of_expr (irange &r, tree expr, gimple * = NULL) = 0;
-  virtual bool range_on_edge (irange &r, edge, tree expr);
-  virtual bool range_of_stmt (irange &r, gimple *, tree name = NULL);
+  virtual bool range_of_expr (vrange &r, tree expr, gimple * = NULL) = 0;
+  virtual bool range_on_edge (vrange &r, edge, tree expr);
+  virtual bool range_of_stmt (vrange &r, gimple *, tree name = NULL);
 
   // Query if there is any relation between SSA1 and SSA2.
   relation_kind query_relation (gimple *s, tree ssa1, tree ssa2,
@@ -110,8 +110,8 @@  public:
 protected:
   class value_range_equiv *allocate_value_range_equiv ();
   void free_value_range_equiv (class value_range_equiv *);
-  bool get_tree_range (irange &r, tree expr, gimple *stmt);
-  bool get_arith_expr_range (irange &r, tree expr, gimple *stmt);
+  bool get_tree_range (vrange &v, tree expr, gimple *stmt);
+  bool get_arith_expr_range (vrange &r, tree expr, gimple *stmt);
   relation_oracle *m_oracle;
 
 private:
@@ -123,7 +123,7 @@  private:
 class global_range_query : public range_query
 {
 public:
-  bool range_of_expr (irange &r, tree expr, gimple * = NULL) override;
+  bool range_of_expr (vrange &r, tree expr, gimple * = NULL) override;
 };
 
 extern global_range_query global_ranges;
@@ -143,7 +143,7 @@  get_range_query (const struct function *fun)
   return fun->x_range_query ? fun->x_range_query : &global_ranges;
 }
 
-extern value_range gimple_range_global (tree name);
-extern bool update_global_range (irange &r, tree name);
+extern void gimple_range_global (vrange &v, tree name);
+extern bool update_global_range (vrange &v, tree name);
 
 #endif // GCC_QUERY_H
diff --git a/gcc/vr-values.cc b/gcc/vr-values.cc
index 6f8583c8d01..9b681a46905 100644
--- a/gcc/vr-values.cc
+++ b/gcc/vr-values.cc
@@ -177,7 +177,7 @@  vr_values::get_value_range (const_tree var,
 }
 
 bool
-vr_values::range_of_expr (irange &r, tree expr, gimple *stmt)
+vr_values::range_of_expr (vrange &r, tree expr, gimple *stmt)
 {
   if (!gimple_range_ssa_p (expr))
     return get_tree_range (r, expr, stmt);
@@ -1640,6 +1640,8 @@  bounds_of_var_in_loop (tree *min, tree *max, range_query *query,
 {
   tree init, step, chrec, tmin, tmax, type = TREE_TYPE (var);
   enum ev_direction dir;
+  tmp_range trange;
+  int_range<2> r;
 
   chrec = instantiate_parameters (loop, analyze_scalar_evolution (loop, var));
 
@@ -1661,11 +1663,15 @@  bounds_of_var_in_loop (tree *min, tree *max, range_query *query,
 
   /* If INIT is an SSA with a singleton range, set INIT to said
      singleton, otherwise leave INIT alone.  */
-  if (TREE_CODE (init) == SSA_NAME)
-    query->get_value_range (init, stmt)->singleton_p (&init);
+  if (TREE_CODE (init) == SSA_NAME
+      && trange.init (TREE_TYPE (init))
+      && query->range_of_expr (trange, init, stmt))
+    trange.singleton_p (&init);
   /* Likewise for step.  */
-  if (TREE_CODE (step) == SSA_NAME)
-    query->get_value_range (step, stmt)->singleton_p (&step);
+  if (TREE_CODE (step) == SSA_NAME
+      && trange.init (TREE_TYPE (step))
+      && query->range_of_expr (trange, step, stmt))
+    trange.singleton_p (&step);
 
   /* If STEP is symbolic, we can't know whether INIT will be the
      minimum or maximum value in the range.  Also, unless INIT is
@@ -1699,7 +1705,8 @@  bounds_of_var_in_loop (tree *min, tree *max, range_query *query,
   if (TREE_CODE (step) == INTEGER_CST
       && is_gimple_val (init)
       && (TREE_CODE (init) != SSA_NAME
-	  || query->get_value_range (init, stmt)->kind () == VR_RANGE))
+	  || (query->range_of_expr (r, init, stmt)
+	      && r.kind () == VR_RANGE)))
     {
       widest_int nit;
 
@@ -1724,7 +1731,7 @@  bounds_of_var_in_loop (tree *min, tree *max, range_query *query,
 	    {
 	      value_range maxvr, vr0, vr1;
 	      if (TREE_CODE (init) == SSA_NAME)
-		vr0 = *(query->get_value_range (init, stmt));
+		query->range_of_expr (vr0, init, stmt);
 	      else if (is_gimple_min_invariant (init))
 		vr0.set (init);
 	      else
@@ -1737,10 +1744,10 @@  bounds_of_var_in_loop (tree *min, tree *max, range_query *query,
 	      /* Likewise if the addition did.  */
 	      if (maxvr.kind () == VR_RANGE)
 		{
-		  value_range initvr;
+		  int_range<2> initvr;
 
 		  if (TREE_CODE (init) == SSA_NAME)
-		    initvr = *(query->get_value_range (init, stmt));
+		    query->range_of_expr (initvr, init, stmt);
 		  else if (is_gimple_min_invariant (init))
 		    initvr.set (init);
 		  else
@@ -2446,7 +2453,9 @@  simplify_using_ranges::vrp_visit_cond_stmt (gcond *stmt, edge *taken_edge_p)
 	  fprintf (dump_file, "\t");
 	  print_generic_expr (dump_file, use);
 	  fprintf (dump_file, ": ");
-	  dump_value_range (dump_file, query->get_value_range (use, stmt));
+	  tmp_range r (TREE_TYPE (use));
+	  query->range_of_expr (r, use, stmt);
+	  r.dump (dump_file);
 	}
 
       fprintf (dump_file, "\n");
diff --git a/gcc/vr-values.h b/gcc/vr-values.h
index 7a377cebd01..f018d0dfc4b 100644
--- a/gcc/vr-values.h
+++ b/gcc/vr-values.h
@@ -109,7 +109,7 @@  class vr_values : public range_query
   vr_values (void);
   ~vr_values (void);
 
-  virtual bool range_of_expr (irange &r, tree expr, gimple *stmt) override;
+  virtual bool range_of_expr (vrange &r, tree expr, gimple *stmt) override;
   virtual tree value_of_expr (tree, gimple * = NULL) override;
   virtual tree value_on_edge (edge, tree) override;
   virtual tree value_of_stmt (gimple *, tree = NULL_TREE) override;