diff --git a/gcc/gimple-range-cache.cc b/gcc/gimple-range-cache.cc
index 5bb52d5f70f..9be8bc6123b 100644
--- a/gcc/gimple-range-cache.cc
+++ b/gcc/gimple-range-cache.cc
@@ -28,6 +28,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "ssa.h"
 #include "gimple-pretty-print.h"
 #include "gimple-range.h"
+#include "value-range-storage.h"
 #include "tree-cfg.h"
 #include "target.h"
 #include "attribs.h"
diff --git a/gcc/gimple-range-cache.h b/gcc/gimple-range-cache.h
index a784eba8345..0341192c9cb 100644
--- a/gcc/gimple-range-cache.h
+++ b/gcc/gimple-range-cache.h
@@ -44,7 +44,7 @@ private:
   vec<class ssa_block_ranges *> m_ssa_ranges;
   ssa_block_ranges &get_block_ranges (tree name);
   ssa_block_ranges *query_block_ranges (tree name);
-  vrange_allocator *m_range_allocator;
+  class vrange_allocator *m_range_allocator;
   bitmap_obstack m_bitmaps;
 };
 
diff --git a/gcc/gimple-range-edge.cc b/gcc/gimple-range-edge.cc
index 03a804ac2be..194e8f87a4b 100644
--- a/gcc/gimple-range-edge.cc
+++ b/gcc/gimple-range-edge.cc
@@ -31,6 +31,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "gimple-iterator.h"
 #include "tree-cfg.h"
 #include "gimple-range.h"
+#include "value-range-storage.h"
 
 // If there is a range control statment at the end of block BB, return it.
 // Otherwise return NULL.
@@ -68,6 +69,7 @@ gimple_outgoing_range::gimple_outgoing_range (int max_sw_edges)
 {
   m_edge_table = NULL;
   m_max_edges = max_sw_edges;
+  m_range_allocator = new obstack_vrange_allocator;
 }
 
 
@@ -75,6 +77,7 @@ gimple_outgoing_range::~gimple_outgoing_range ()
 {
   if (m_edge_table)
     delete m_edge_table;
+  delete m_range_allocator;
 }
 
 
@@ -162,13 +165,13 @@ gimple_outgoing_range::calc_switch_ranges (gswitch *sw)
       // If there was an existing range and it doesn't fit, we lose the memory.
       // It'll get reclaimed when the obstack is freed.  This seems less
       // intrusive than allocating max ranges for each case.
-      slot = m_range_allocator.clone <irange> (case_range);
+      slot = m_range_allocator->clone <irange> (case_range);
     }
 
   irange *&slot = m_edge_table->get_or_insert (default_edge, &existed);
   // This should be the first call into this switch.
   gcc_checking_assert (!existed);
-  irange *dr = m_range_allocator.clone <irange> (default_range);
+  irange *dr = m_range_allocator->clone <irange> (default_range);
   slot = dr;
 }
 
diff --git a/gcc/gimple-range-edge.h b/gcc/gimple-range-edge.h
index c81b943dae6..1a4dee9f41b 100644
--- a/gcc/gimple-range-edge.h
+++ b/gcc/gimple-range-edge.h
@@ -47,7 +47,7 @@ private:
 
   int m_max_edges;
   hash_map<edge, irange *> *m_edge_table;
-  obstack_vrange_allocator m_range_allocator;
+  class obstack_vrange_allocator *m_range_allocator;
 };
 
 // If there is a range control statement at the end of block BB, return it.
diff --git a/gcc/gimple-range-infer.cc b/gcc/gimple-range-infer.cc
index eee149104b4..2d12f86ce89 100644
--- a/gcc/gimple-range-infer.cc
+++ b/gcc/gimple-range-infer.cc
@@ -28,6 +28,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "ssa.h"
 #include "gimple-pretty-print.h"
 #include "gimple-range.h"
+#include "value-range-storage.h"
 #include "tree-cfg.h"
 #include "target.h"
 #include "attribs.h"
@@ -166,6 +167,7 @@ infer_range_manager::infer_range_manager (bool do_search)
   // Non-zero elements are very common, so cache them for each ssa-name.
   m_nonzero.create (0);
   m_nonzero.safe_grow_cleared (num_ssa_names + 1);
+  m_range_allocator = new obstack_vrange_allocator;
 }
 
 // Destruct a range infer manager.
@@ -176,6 +178,7 @@ infer_range_manager::~infer_range_manager ()
   obstack_free (&m_list_obstack, NULL);
   m_on_exit.release ();
   bitmap_obstack_release (&m_bitmaps);
+  delete m_range_allocator;
 }
 
 // Return a non-zero range value of the appropriate type for NAME from
@@ -189,7 +192,7 @@ infer_range_manager::get_nonzero (tree name)
     m_nonzero.safe_grow_cleared (num_ssa_names + 20);
   if (!m_nonzero[v])
     {
-      m_nonzero[v] = m_range_allocator.alloc_vrange (TREE_TYPE (name));
+      m_nonzero[v] = m_range_allocator->alloc_vrange (TREE_TYPE (name));
       m_nonzero[v]->set_nonzero (TREE_TYPE (name));
     }
   return *(m_nonzero[v]);
@@ -261,7 +264,7 @@ infer_range_manager::add_range (tree name, basic_block bb, const vrange &r)
       else
 	{
 	  vrange &v = cur;
-	  ptr->range = m_range_allocator.clone (v);
+	  ptr->range = m_range_allocator->clone (v);
 	}
       return;
     }
@@ -269,7 +272,7 @@ infer_range_manager::add_range (tree name, basic_block bb, const vrange &r)
   // Otherwise create a record.
   bitmap_set_bit (m_on_exit[bb->index].m_names, SSA_NAME_VERSION (name));
   ptr = (exit_range *)obstack_alloc (&m_list_obstack, sizeof (exit_range));
-  ptr->range = m_range_allocator.clone (r);
+  ptr->range = m_range_allocator->clone (r);
   ptr->name = name;
   ptr->next = m_on_exit[bb->index].head;
   m_on_exit[bb->index].head = ptr;
diff --git a/gcc/gimple-range-infer.h b/gcc/gimple-range-infer.h
index bf27d0d3423..468b7d11286 100644
--- a/gcc/gimple-range-infer.h
+++ b/gcc/gimple-range-infer.h
@@ -78,7 +78,7 @@ private:
   bitmap m_seen;
   bitmap_obstack m_bitmaps;
   struct obstack m_list_obstack;
-  obstack_vrange_allocator m_range_allocator;
+  class obstack_vrange_allocator *m_range_allocator;
 };
 
 #endif // GCC_GIMPLE_RANGE_SIDE_H
diff --git a/gcc/value-range-storage.h b/gcc/value-range-storage.h
index 58c5e114320..7e005e4db56 100644
--- a/gcc/value-range-storage.h
+++ b/gcc/value-range-storage.h
@@ -21,6 +21,27 @@ along with GCC; see the file COPYING3.  If not see
 #ifndef GCC_VALUE_RANGE_STORAGE_H
 #define GCC_VALUE_RANGE_STORAGE_H
 
+// This class is used to allocate the minimum amount of storage needed
+// for a given range.  Storage is automatically freed at destruction
+// of the class.
+
+class vrange_allocator
+{
+public:
+  vrange_allocator () { }
+  virtual ~vrange_allocator () { }
+  // Allocate a range of TYPE.
+  vrange *alloc_vrange (tree type);
+  // Allocate a memory block of BYTES.
+  virtual void *alloc (unsigned bytes) = 0;
+  virtual void free (void *p) = 0;
+  // Return a clone of SRC.
+  template <typename T> T *clone (const T &src);
+private:
+  irange *alloc_irange (unsigned pairs);
+  void operator= (const vrange_allocator &) = delete;
+};
+
 // This class is used to allocate chunks of memory that can store
 // ranges as memory efficiently as possible.  It is meant to be used
 // when long term storage of a range is needed.  The class can be used
@@ -40,10 +61,6 @@ private:
   vrange_allocator *m_alloc;
 };
 
-
-// INTERNAL USE ONLY.  The remaining interfaces are only exposed for
-// the GTY machinery to play nice with tree_ssa_name.
-
 // A chunk of memory pointing to an irange storage.
 
 class GTY ((variable_size)) irange_storage_slot
@@ -82,4 +99,92 @@ private:
   trailing_wide_ints<MAX_INTS> m_ints;
 };
 
+class obstack_vrange_allocator : public vrange_allocator
+{
+public:
+  obstack_vrange_allocator ()
+  {
+    obstack_init (&m_obstack);
+  }
+  virtual ~obstack_vrange_allocator () final override
+  {
+    obstack_free (&m_obstack, NULL);
+  }
+  virtual void *alloc (unsigned bytes) final override
+  {
+    return obstack_alloc (&m_obstack, bytes);
+  }
+  virtual void free (void *) final override { }
+private:
+  obstack m_obstack;
+};
+
+class ggc_vrange_allocator : public vrange_allocator
+{
+public:
+  ggc_vrange_allocator () { }
+  virtual ~ggc_vrange_allocator () final override { }
+  virtual void *alloc (unsigned bytes) final override
+  {
+    return ggc_internal_alloc (bytes);
+  }
+  virtual void free (void *p) final override
+  {
+    return ggc_free (p);
+  }
+};
+
+// Return a new range to hold ranges of TYPE.  The newly allocated
+// range is initialized to VR_UNDEFINED.
+
+inline vrange *
+vrange_allocator::alloc_vrange (tree type)
+{
+  if (irange::supports_p (type))
+    return alloc_irange (2);
+
+  gcc_unreachable ();
+}
+
+// Return a new range with NUM_PAIRS.
+
+inline irange *
+vrange_allocator::alloc_irange (unsigned num_pairs)
+{
+  // Never allocate 0 pairs.
+  // Don't allocate 1 either, or we get legacy value_range's.
+  if (num_pairs < 2)
+    num_pairs = 2;
+
+  size_t nbytes = sizeof (tree) * 2 * num_pairs;
+
+  // Allocate the irange and required memory for the vector.
+  void *r = alloc (sizeof (irange));
+  tree *mem = static_cast <tree *> (alloc (nbytes));
+  return new (r) irange (mem, num_pairs);
+}
+
+// Return a clone of an irange.
+
+template <>
+inline irange *
+vrange_allocator::clone <irange> (const irange &src)
+{
+  irange *r = alloc_irange (src.num_pairs ());
+  *r = src;
+  return r;
+}
+
+// Return a clone of a vrange.
+
+template <>
+inline vrange *
+vrange_allocator::clone <vrange> (const vrange &src)
+{
+  if (is_a <irange> (src))
+    return clone <irange> (as_a <irange> (src));
+
+  gcc_unreachable ();
+}
+
 #endif // GCC_VALUE_RANGE_STORAGE_H
diff --git a/gcc/value-range.h b/gcc/value-range.h
index 627d221fe0f..8ee7793baeb 100644
--- a/gcc/value-range.h
+++ b/gcc/value-range.h
@@ -896,113 +896,4 @@ vrp_val_min (const_tree type)
   return NULL_TREE;
 }
 
-// This is the range storage class.  It is used to allocate the
-// minimum amount of storage needed for a given range.  Storage is
-// automatically freed at destruction of the class.
-
-class vrange_allocator
-{
-public:
-  vrange_allocator () { }
-  virtual ~vrange_allocator () { }
-  // Allocate a range of TYPE.
-  vrange *alloc_vrange (tree type);
-  // Allocate a memory block of BYTES.
-  virtual void *alloc (unsigned bytes) = 0;
-  virtual void free (void *p) = 0;
-  // Return a clone of SRC.
-  template <typename T> T *clone (const T &src);
-private:
-  irange *alloc_irange (unsigned pairs);
-  void operator= (const vrange_allocator &) = delete;
-};
-
-class obstack_vrange_allocator : public vrange_allocator
-{
-public:
-  obstack_vrange_allocator ()
-  {
-    obstack_init (&m_obstack);
-  }
-  virtual ~obstack_vrange_allocator () final override
-  {
-    obstack_free (&m_obstack, NULL);
-  }
-  virtual void *alloc (unsigned bytes) final override
-  {
-    return obstack_alloc (&m_obstack, bytes);
-  }
-  virtual void free (void *) final override { }
-private:
-  obstack m_obstack;
-};
-
-class ggc_vrange_allocator : public vrange_allocator
-{
-public:
-  ggc_vrange_allocator () { }
-  virtual ~ggc_vrange_allocator () final override { }
-  virtual void *alloc (unsigned bytes) final override
-  {
-    return ggc_internal_alloc (bytes);
-  }
-  virtual void free (void *p) final override
-  {
-    return ggc_free (p);
-  }
-};
-
-// Return a new range to hold ranges of TYPE.  The newly allocated
-// range is initialized to VR_UNDEFINED.
-
-inline vrange *
-vrange_allocator::alloc_vrange (tree type)
-{
-  if (irange::supports_p (type))
-    return alloc_irange (2);
-
-  gcc_unreachable ();
-}
-
-// Return a new range with NUM_PAIRS.
-
-inline irange *
-vrange_allocator::alloc_irange (unsigned num_pairs)
-{
-  // Never allocate 0 pairs.
-  // Don't allocate 1 either, or we get legacy value_range's.
-  if (num_pairs < 2)
-    num_pairs = 2;
-
-  size_t nbytes = sizeof (tree) * 2 * num_pairs;
-
-  // Allocate the irange and required memory for the vector.
-  void *r = alloc (sizeof (irange));
-  tree *mem = static_cast <tree *> (alloc (nbytes));
-  return new (r) irange (mem, num_pairs);
-}
-
-// Return a clone of an irange.
-
-template <>
-inline irange *
-vrange_allocator::clone <irange> (const irange &src)
-{
-  irange *r = alloc_irange (src.num_pairs ());
-  *r = src;
-  return r;
-}
-
-// Return a clone of a vrange.
-
-template <>
-inline vrange *
-vrange_allocator::clone <vrange> (const vrange &src)
-{
-  if (is_a <irange> (src))
-    return clone <irange> (as_a <irange> (src));
-
-  gcc_unreachable ();
-}
-
 #endif // GCC_VALUE_RANGE_H
