--- /dev/null
+// Splay tree utilities                                             -*- C++ -*-
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of GCC.
+//
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+//
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#define INCLUDE_ALGORITHM
+#define INCLUDE_ARRAY
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "pretty-print.h"
+#include "splay-tree-utils.h"
+#include "selftest.h"
+
+#if CHECKING_P
+namespace {
+// A simple test node for rootless_splay_tree.
+struct rootless_test_node
+{
+  int data;
+  rootless_test_node *m_parent;
+  rootless_test_node *m_children[2];
+};
+}
+
+namespace selftest {
+
+// Random input data.
+static const size_t MAX_DATA = 32768;
+static const int data[] = {
+  1379, 14643, 30579, 28160, 31750, 22280, 5502, 4720, 30075, 27595,
+  8395, 19410, 518, 19709, 29694, 19865, 25372, 11752, 15485, 21547,
+  25153, 25072, 10146, 3341, 15625, 3038, 10189, 19943, 1322, 11762,
+  807, 430, 11284, 11841, 23965, 32008, 4547, 8087, 13225, 23054,
+  22284, 13756, 2182, 26450, 30482, 32502, 23348, 20265, 29509, 3290,
+  10807, 1242, 3212, 32178, 25354, 22032, 30509, 16157, 22432, 1295,
+  8348, 23342, 24678, 193, 31016, 10316, 3872, 13521, 19211, 30594,
+  12229, 4794, 25083, 16098, 28144, 27896, 4801, 20689, 31450, 15614,
+  19597, 13731, 30309, 24846, 11042, 31929, 18306, 28520, 16907, 12488,
+  15001, 18487, 3438, 1706, 4829, 20892, 6226, 18204, 15776, 30717,
+  19398, 2480, 19434, 2838, 2605, 3994, 22538, 12269, 6486, 1314,
+  30301, 9919, 31405, 30847, 25000, 24013, 22196, 30220, 31415, 14630,
+  26319, 4880, 21292, 20217, 20078, 14679, 25686, 28675, 13883, 14853,
+  2872, 2428, 3636, 14131, 2952, 2133, 4470, 25808, 12576, 31395,
+  5938, 28393, 14553, 4494, 14928, 24310, 17394, 17436, 23385, 22792,
+  9785, 13118, 22338, 23320, 27059, 17663, 16434, 14954, 16962, 31088,
+  22247, 22600, 7980, 1344, 15635, 13611, 32739, 3283, 12924, 17904,
+  28216, 7542, 9212, 28308, 18873, 3912, 5473, 4666, 11900, 21420,
+  20072, 27662, 16445, 29848, 24444, 31668, 30664, 14287, 13754, 29276,
+  21462, 25517, 17632, 8105, 32510, 16677, 11162, 20734, 26873, 5097
+};
+
+// Look up VALUE in TREE using the single-comparator lookup function.
+static int
+lookup1 (splay_tree<int> &tree, int value)
+{
+  auto compare = [&](splay_tree_node<int> *node)
+    {
+      return value - node->value ();
+    };
+  return tree.lookup (compare);
+}
+
+// Look up VALUE in TREE using the double-comparator lookup function.
+static int
+lookup2 (splay_tree<int> &tree, int value)
+{
+  auto want_something_smaller = [&](splay_tree_node<int> *node)
+    {
+      return value < node->value ();
+    };
+  auto want_something_bigger = [&](splay_tree_node<int> *node)
+    {
+      return value > node->value ();
+    };
+  return tree.lookup (want_something_smaller, want_something_bigger);
+}
+
+// Test printing TREE to a pretty printer.  Don't check the output against
+// anything; just make sure that it doesn't crash.
+static void
+test_print (splay_tree<int> &tree)
+{
+  auto print_node = [](pretty_printer *pp, splay_tree_node<int> *node)
+    {
+      pp_decimal_int (pp, node->value ());
+    };
+  pretty_printer pp;
+  tree.print (&pp, print_node);
+}
+
+// Test various lookups on TREE using LOOKUP, where lookup returns the
+// same kind of value as the rooted_splay_tree lookup functions.
+static void
+test_lookup (splay_tree<int> &tree, int (*lookup) (splay_tree<int> &, int))
+{
+  // Look up values that are known to exist.
+  for (int value : data)
+    ASSERT_EQ (lookup (tree, value), 0);
+
+  // Look up values that are 1 less than values that are known to exist.
+  for (int value : data)
+    {
+      int result = lookup (tree, value - 1);
+      if (result == 0)
+       ASSERT_EQ (tree->value (), value - 1);
+      else if (result < 0)
+       // VALUE - 1 is less than the root.
+       ASSERT_EQ (tree->value (), value);
+      else if (result > 0)
+       {
+         // VALUE - 1 is greater than the root.
+         ASSERT_TRUE (tree->value () < value - 1);
+         if (tree.splay_next_node ())
+           ASSERT_EQ (tree->value (), value);
+       }
+    }
+
+  // Look up values that are 1 greater than values that are known to exist.
+  for (int value : data)
+    {
+      int result = lookup (tree, value + 1);
+      if (result == 0)
+       ASSERT_EQ (tree->value (), value + 1);
+      else if (result < 0)
+       {
+         // VALUE + 1 is less than the root.
+         ASSERT_TRUE (tree->value () > value + 1);
+         if (tree.splay_prev_node ())
+           ASSERT_EQ (tree->value (), value);
+       }
+      else if (result > 0)
+       // VALUE + 1 is greater than the root.
+       ASSERT_EQ (tree->value (), value);
+    }
+}
+
+// Run all tests for this module.
+void
+splay_tree_cc_tests ()
+{
+  obstack ob;
+  gcc_obstack_init (&ob);
+
+  // Build up the splay tree.
+  splay_tree<int> tree;
+  for (int value : data)
+    {
+      auto *node = XOBNEW (&ob, splay_tree_node<int>);
+      new (node) splay_tree_node<int> (value);
+      auto compare = [&](splay_tree_node<int> *other_node)
+       {
+         return value - other_node->value ();
+       };
+      bool inserted = tree.insert (node, compare);
+      ASSERT_TRUE (inserted);
+    }
+
+  // Test the single-comparator lookup function.
+  test_lookup (tree, lookup1);
+
+  // Sort the input data.
+  std::array<int, ARRAY_SIZE (data)> sorted;
+  std::copy (data, data + ARRAY_SIZE (data), sorted.begin ());
+  std::sort (sorted.begin (), sorted.end ());
+
+  // Iterate over the tree in ascending order.
+  tree.splay_min_node ();
+  bool result = true;
+  for (int value : sorted)
+    {
+      ASSERT_TRUE (result);
+      ASSERT_EQ (tree->value (), value);
+      result = tree.splay_next_node ();
+    }
+  ASSERT_FALSE (result);
+  ASSERT_EQ (tree.min_node ()->value (), sorted.front ());
+
+  // Test the double-comparator lookup function.
+  test_lookup (tree, lookup2);
+
+  // Test printing the tree now, while it's still bushy.
+  test_print (tree);
+
+  // Iterate over the tree in descending order.
+  tree.splay_max_node ();
+  result = true;
+  for (auto it = sorted.rbegin (); it != sorted.rend (); ++it)
+    {
+      ASSERT_TRUE (result);
+      ASSERT_EQ (tree->value (), *it);
+      result = tree.splay_prev_node ();
+    }
+  ASSERT_FALSE (result);
+  ASSERT_EQ (tree.max_node ()->value (), sorted.back ());
+
+  // Try splitting the tree into three.
+  int mid_min = sorted[sorted.size () / 3];
+  int mid_max = sorted[sorted.size () * 2 / 3];
+  ASSERT_EQ (lookup1 (tree, mid_min), 0);
+  splay_tree<int> left = tree.split_before_root ();
+  ASSERT_EQ (lookup1 (tree, mid_max), 0);
+  splay_tree<int> right = tree.split_after_root ();
+
+  // Test removing all the nodes from their respective trees.
+  for (int value : data)
+    {
+      splay_tree<int> &t = (value < mid_min ? left
+                           : value > mid_max ? right : tree);
+      ASSERT_EQ (lookup1 (t, value), 0);
+      t.remove_root ();
+    }
+  ASSERT_EQ (left.root (), nullptr);
+  ASSERT_EQ (tree.root (), nullptr);
+  ASSERT_EQ (right.root (), nullptr);
+
+  using rootless = default_rootless_splay_tree<rootless_test_node *>;
+
+  // Build a tree in ascending order with the lowest element as the root.
+  auto *nodes = XOBNEWVEC (&ob, rootless_test_node *, MAX_DATA);
+  rootless_test_node *parent = nullptr;
+  for (int data : sorted)
+    {
+      auto *node = XOBNEW (&ob, rootless_test_node);
+      new (node) rootless_test_node ();
+      node->data = data;
+      nodes[data] = node;
+      if (parent)
+       rootless::insert_child (parent, 1, node);
+      parent = node;
+    }
+
+  // Try comparing nodes to make sure that their order matches the data.
+  for (size_t i = 1; i < ARRAY_SIZE (data); ++i)
+    {
+      int data1 = data[i - 1];
+      int data2 = data[i];
+      int comparison = rootless::compare_nodes (nodes[data1], nodes[data2]);
+      if (data1 < data2)
+       ASSERT_TRUE (comparison < 0);
+      else if (data1 > data2)
+       ASSERT_TRUE (comparison > 0);
+      else
+       ASSERT_EQ (comparison, 0);
+    }
+
+  obstack_free (&ob, nullptr);
+}
+}
+#endif // CHECKING_P
 
--- /dev/null
+// Splay tree utilities                                             -*- C++ -*-
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of GCC.
+//
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+//
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// Implement splay tree node accessors for a class that stores its
+// two child nodes in a member variable of the form:
+//
+//    Node m_children[2];
+template<typename Node>
+class default_splay_tree_accessors
+{
+public:
+  using node_type = Node;
+
+  static auto
+  child (node_type node, unsigned int index)
+    -> decltype (node->m_children[index]) &
+  {
+    return node->m_children[index];
+  }
+};
+
+// Implement splay tree node accessors for a class that stores its
+// two child nodes in a member variable of the form:
+//
+//    Node m_children[2];
+//
+// and also stores its parent node in a member variable of the form:
+//
+//    Node m_parent;
+template<typename Node>
+class default_splay_tree_accessors_with_parent
+  : public default_splay_tree_accessors<Node>
+{
+public:
+  using node_type = Node;
+
+  static auto
+  parent (node_type node) -> decltype (node->m_parent) &
+  {
+    return node->m_parent;
+  }
+};
+
+// Base is a splay tree accessor class for nodes that have no parent field.
+// Base therefore provides a Base::child method but does not provide a
+// Base::parent method.  Extend Base with dummy routines for setting the
+// parent, which is a no-op when the parent is not stored.
+template<typename Base>
+class splay_tree_accessors_without_parent : public Base
+{
+public:
+  using typename Base::node_type;
+
+  static void set_parent (node_type, node_type) {}
+};
+
+// Base is splay tree accessor class for nodes that have a parent field.
+// Base therefore provides both Base::child and Base::parent methods.
+// Extend Base with routines for setting the parent.
+template<typename Base>
+class splay_tree_accessors_with_parent : public Base
+{
+public:
+  using typename Base::node_type;
+
+  // Record that NODE's parent is now NEW_PARENT.
+  static void
+  set_parent (node_type node, node_type new_parent)
+  {
+    Base::parent (node) = new_parent;
+  }
+};
+
+// A base class that provides some splay tree operations that are common
+// to both rooted_splay_tree and rootless_splay_tree.
+//
+// Nodes in the splay tree have type Accessors::node_type; this is
+// usually a pointer type.  The Accessors class provides the following
+// static member functions for accessing nodes:
+//
+// - Accessors::child (NODE, INDEX)
+//     INDEX is guaranteed to be 0 or 1.  If INDEX is 0, return a reference
+//     to where NODE's left child is stored, otherwise return a reference
+//     to where NODE's right child is stored.
+//
+// - Accessors::set_parent (NODE, PARENT)
+//     Record that NODE's parent node is now PARENT.
+template<typename Accessors>
+class base_splay_tree : protected Accessors
+{
+public:
+  using typename Accessors::node_type;
+
+  // INDEX is either 0 or 1.  If INDEX is 0, insert CHILD immediately
+  // before NODE, otherwise insert CHILD immediately after NODE.
+  //
+  // Complexity: O(1).
+  static void insert_child (node_type node, unsigned int index,
+                           node_type child);
+
+  // Print NODE and its child nodes to PP for debugging purposes,
+  // using PRINTER (PP, N) to print the data for node N.
+  template<typename Printer>
+  static void print (pretty_printer *pp, node_type node, Printer printer);
+
+protected:
+  using Accessors::set_parent;
+
+  static node_type get_child (node_type, unsigned int);
+  static void set_child (node_type, unsigned int, node_type);
+  static node_type promote_child (node_type, unsigned int);
+  static void promote_child (node_type, unsigned int, node_type);
+
+  template<unsigned int N>
+  static node_type splay_limit (node_type);
+
+  static node_type remove_node_internal (node_type);
+
+  template<typename Printer>
+  static void print (pretty_printer *pp, node_type node, Printer printer,
+                    char, vec<char> &);
+};
+
+// This class provides splay tree routines for cases in which the root
+// of the splay tree is known.  It works with both nodes that store
+// their parent node and nodes that don't.
+//
+// The class is lightweight: it only contains a single root node.
+template<typename Accessors>
+class rooted_splay_tree : public base_splay_tree<Accessors>
+{
+  using parent = base_splay_tree<Accessors>;
+
+public:
+  using typename Accessors::node_type;
+
+protected:
+  // The root of the splay tree, or node_type () if the tree is empty.
+  node_type m_root;
+
+public:
+  rooted_splay_tree () : m_root () {}
+
+  // Construct a tree with the specified root node.
+  rooted_splay_tree (node_type root) : m_root (root) {}
+
+  // Return the root of the tree.
+  node_type root () const { return m_root; }
+
+  // Return true if the tree contains any nodes.
+  explicit operator bool () const { return m_root; }
+
+  // Dereference the root node.
+  node_type operator-> () { return m_root; }
+
+  // Insert NEW_NODE into the splay tree, if no equivalent node already
+  // exists.  For a given node N, COMPARE (N) should return:
+  //
+  // - a negative value if NEW_NODE should come before N
+  // - zero if NEW_NODE and N are the same
+  // - a positive value if NEW_NODE should come after N
+  //
+  // Return true if NEW_NODE was inserted.
+  //
+  // On return, NEW_NODE or its equivalent is the root of the tree.
+  //
+  // Complexity: amortized O(C log N), worst-cast O(C N), where C is
+  // the complexity of the comparison.
+  template<typename Comparator>
+  bool insert (node_type new_node, Comparator compare);
+
+  // Insert NEW_NODE into the splay tree, given that NEW_NODE is the
+  // maximum node of the new tree.  On return, NEW_NODE is also the
+  // root of the tree.
+  //
+  // Complexity: O(1).
+  void insert_max_node (node_type new_node);
+
+  // Splice NEXT_TREE onto this one, given that all nodes in NEXT_TREE
+  // are greater than the maximum node in this tree.  NEXT_TREE should
+  // not be used afterwards.
+  //
+  // Complexity: O(1) if the root of the splay tree is already the maximum
+  // node.  Otherwise amortized O(log N), worst-cast O(N).
+  void splice_next_tree (rooted_splay_tree next_tree);
+
+  // The root of the tree is currently the maximum node.  Replace it
+  // with NEW_NODE.
+  //
+  // Complexity: O(1).
+  void replace_max_node_at_root (node_type new_node);
+
+  // Remove the root node of the splay tree.
+  //
+  // Complexity: O(1) if removing the maximum or minimum node.
+  // Otherwise amortized O(log N), worst-cast O(N).
+  void remove_root ();
+
+  // Split the left child of the current root out into a separate tree
+  // and return the new tree.
+  rooted_splay_tree split_before_root ();
+
+  // Split the right child of the current root out into a separate tree
+  // and return the new tree.
+  rooted_splay_tree split_after_root ();
+
+  // If the root is not the minimum node of the splay tree, bring the previous
+  // node to the root and return true, otherwise return false.
+  //
+  // Complexity: amortized O(log N), worst-cast O(N).
+  bool splay_prev_node ();
+
+  // If the root is not the maximum node of the splay tree, bring the next
+  // node to the root and return true, otherwise return false.
+  //
+  // Complexity: amortized O(log N), worst-cast O(N).
+  bool splay_next_node ();
+
+  // Bring the minimum node of the splay tree to the root.
+  //
+  // Complexity: amortized O(log N), worst-cast O(N).
+  void splay_min_node ();
+
+  // Bring the maximum node of the splay tree to the root.
+  //
+  // Complexity: amortized O(log N), worst-cast O(N).
+  void splay_max_node ();
+
+  // Return the minimum node of the splay tree, or node_type () if the
+  // tree is empty.  On return, the minimum node (if any) is also the
+  // root of the tree.
+  //
+  // Complexity: amortized O(log N), worst-cast O(N).
+  node_type min_node ();
+
+  // Return the maximum node of the splay tree, or node_type () if the
+  // tree is empty.  On return, the maximum node (if any) is also the
+  // root of the tree.
+  //
+  // Complexity: amortized O(log N), worst-cast O(N).
+  node_type max_node ();
+
+  // Search the splay tree.  For a given node N, COMPARE (N) should return:
+  //
+  // - a negative value if N is bigger than the node being searched for
+  // - zero if N is the node being searched for
+  // - a positive value if N is smaller than the node being searched for
+  //
+  // If the node that COMPARE is looking for exists, install it as the root
+  // node of the splay tree.  Otherwise, arbitrarily pick either:
+  //
+  // - the maximum node that is smaller than the node being searched for or
+  // - the minimum node that is bigger than the node being searched for
+  //
+  // and install that node as the root instead.
+  //
+  // Return the result of COMPARE for the new root.
+  //
+  // This form of lookup is intended for cases in which both the following
+  // are true:
+  //
+  // (a) The work that COMPARE needs to do to detect if a node is too big
+  //     is the same as the work that COMPARE needs to do to detect if a
+  //     node is too small.  (This is not true of range comparisons,
+  //     for example.)
+  //
+  // (b) COMPARE is (or might be) relatively complex.
+  //
+  // This form of lookup is also useful if the items being compared naturally
+  // provide a <=>-style comparison result, without the result having to be
+  // forced by the equivalent of a ?: expression.
+  //
+  // The implementation only invokes COMPARE once per node.
+  //
+  // Complexity: amortized O(C log N), worst-cast O(C N), where C is
+  // the complexity of the comparison.
+  template<typename Comparator>
+  auto lookup (Comparator compare) -> decltype (compare (m_root));
+
+  // Search the splay tree.  For a given node N, WANT_SOMETHING_SMALLER (N)
+  // is true if N is too big and WANT_SOMETHING_BIGGER (N) is true if N
+  // is too small.  Both functions return false if N is the node being
+  // searched for.
+  //
+  // If the node that is being searched for exists, install it as the root
+  // node of the splay tree and return 0.  Otherwise, arbitrarily choose
+  // between these two options:
+  //
+  // - Install the maximum node that is smaller than the node being
+  //   searched for as the root of the splay tree and return 1.
+  //
+  // - Install the minimum node that is bigger than the node being
+  //   searched for and return -1.
+  //
+  // This form of lookup is intended for cases in which either of the
+  // following are true:
+  //
+  // (a) WANT_SOMETHING_SMALLER and WANT_SOMETHING_BIGGER test different
+  //     parts of the node's data.  For example, when comparing ranges,
+  //     WANT_SOMETHING_SMALLER would test the lower limit of the given
+  //     node's range while WANT_SOMETHING_BIGGER would test the upper
+  //     limit of the given node's range.
+  //
+  // (b) There is no significant overhead to calling both
+  //     WANT_SOMETHING_SMALLER and WANT_SOMETHING_BIGGER for the same node.
+  //
+  // Complexity: amortized O(C log N), worst-cast O(C N), where C is
+  // the complexity of the comparisons.
+  template<typename LeftPredicate, typename RightPredicate>
+  int lookup (LeftPredicate want_something_smaller,
+             RightPredicate want_something_bigger);
+
+  // Keep the ability to print subtrees.
+  using parent::print;
+
+  // Print the tree to PP for debugging purposes, using PRINTER (PP, N)
+  // to print the data for node N.
+  template<typename Printer>
+  void print (pretty_printer *pp, Printer printer) const;
+
+protected:
+  using parent::get_child;
+  using parent::set_child;
+  using parent::promote_child;
+
+  using parent::set_parent;
+
+  template<unsigned int N>
+  bool splay_neighbor ();
+};
+
+// Provide splay tree routines for nodes of type Accessors::node_type,
+// which doesn't have a parent field.  Use Accessors::child to access
+// the children of a node.
+template<typename Accessors>
+using splay_tree_without_parent
+  = rooted_splay_tree<splay_tree_accessors_without_parent<Accessors>>;
+
+// A splay tree for nodes of type Node, which is usually a pointer type.
+// The child nodes are stored in a member variable:
+//
+//    Node m_children[2];
+//
+// Node does not have a parent field.
+template<typename Node>
+using default_splay_tree
+  = splay_tree_without_parent<default_splay_tree_accessors<Node>>;
+
+// A simple splay tree node that stores a value of type T.
+template<typename T>
+class splay_tree_node
+{
+  friend class default_splay_tree_accessors<splay_tree_node *>;
+
+public:
+  splay_tree_node () = default;
+  splay_tree_node (T value) : m_value (value), m_children () {}
+
+  T &value () { return m_value; }
+  const T &value () const { return m_value; }
+
+private:
+  T m_value;
+  splay_tree_node *m_children[2];
+};
+
+// A splay tree whose nodes hold values of type T.
+template<typename T>
+using splay_tree = default_splay_tree<splay_tree_node<T> *>;
+
+// Provide splay tree routines for cases in which the root of the tree
+// is not explicitly stored.
+//
+// The nodes of the tree have type Accessors::node_type, which is usually
+// a pointer type.  The nodes have a link back to their parent.
+//
+// The Accessors class provides the following static member functions:
+//
+// - Accessors::child (NODE, INDEX)
+//     INDEX is guaranteed to be 0 or 1.  If INDEX is 0, return a reference
+//     to where NODE's left child is stored, otherwise return a reference
+//     to where NODE's right child is stored.
+//
+// - Accessors::parent (NODE)
+//     Return a reference to where NODE's parent is stored.
+template<typename Accessors>
+class rootless_splay_tree
+  : public base_splay_tree<splay_tree_accessors_with_parent<Accessors>>
+{
+  using full_accessors = splay_tree_accessors_with_parent<Accessors>;
+  using parent = base_splay_tree<full_accessors>;
+
+public:
+  using rooted = rooted_splay_tree<full_accessors>;
+
+  using typename Accessors::node_type;
+
+  // Remove NODE from the splay tree.  Return the node that replaces it,
+  // or null if NODE had no children.
+  //
+  // Complexity: O(1) if removing the maximum or minimum node.
+  // Otherwise amortized O(log N), worst-cast O(N).
+  static node_type remove_node (node_type node);
+
+  // Splay NODE so that it becomes the root of the splay tree.
+  //
+  // Complexity: amortized O(log N), worst-cast O(N).
+  static void splay (node_type node);
+
+  // Like splay, but take advantage of the fact that NODE is known to be
+  // the minimum node in the tree.
+  //
+  // Complexity: amortized O(log N), worst-cast O(N).
+  static void splay_known_min_node (node_type node);
+
+  // Like splay, but take advantage of the fact that NODE is known to be
+  // the maximum node in the tree.
+  //
+  // Complexity: amortized O(log N), worst-cast O(N).
+  static void splay_known_max_node (node_type node);
+
+  // Splay NODE while looking for an ancestor node N for which PREDICATE (N)
+  // is true.  If such an ancestor node exists, stop the splay operation
+  // early and return PREDICATE (N).  Otherwise, complete the splay operation
+  // and return DEFAULT_RESULT.  In the latter case, NODE is now the root of
+  // the splay tree.
+  //
+  // Note that this routine only examines nodes that happen to be ancestors
+  // of NODE.  It does not search the full tree.
+  //
+  // Complexity: amortized O(P log N), worst-cast O(P N), where P is the
+  // complexity of the predicate.
+  template<typename DefaultResult, typename Predicate>
+  static auto splay_and_search (node_type node, DefaultResult default_result,
+                               Predicate predicate)
+    -> decltype (predicate (node, 0));
+
+  // NODE1 and NODE2 are known to belong to the same splay tree.  Return:
+  //
+  // -1 if NODE1 < NODE2
+  // 0 if NODE1 == NODE2
+  // 1 if NODE1 > NODE2
+  //
+  // Complexity: amortized O(log N), worst-cast O(N).
+  static int compare_nodes (node_type node1, node_type node2);
+
+protected:
+  using parent::get_child;
+  using parent::set_child;
+  using parent::promote_child;
+
+  static node_type get_parent (node_type);
+  using parent::set_parent;
+
+  static unsigned int child_index (node_type, node_type);
+
+  static int compare_nodes_one_way (node_type, node_type);
+
+  template<unsigned int N>
+  static void splay_known_limit (node_type);
+};
+
+// Provide rootless splay tree routines for nodes of type Node.
+// The child nodes are stored in a member variable:
+//
+//    Node m_children[2];
+//
+// and the parent node is stored in a member variable:
+//
+//    Node m_parent;
+template<typename Node>
+using default_rootless_splay_tree
+  = rootless_splay_tree<default_splay_tree_accessors_with_parent<Node>>;
+
+#include "splay-tree-utils.tcc"
 
--- /dev/null
+// Splay tree utilities                                             -*- C++ -*-
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of GCC.
+//
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+//
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// INDEX is either 0 or 1.  If it is 0, return NODE's left child,
+// otherwise return NODE's right child.
+template<typename Accessors>
+inline typename base_splay_tree<Accessors>::node_type
+base_splay_tree<Accessors>::get_child (node_type node, unsigned int index)
+{
+  return Accessors::child (node, index);
+}
+
+// INDEX is either 0 or 1.  If it is 0, change NODE's left child to CHILD,
+// otherwise change NODE's right child to CHILD.  If CHILD has a parent
+// field, record that its parent is now NODE.
+template<typename Accessors>
+inline void
+base_splay_tree<Accessors>::set_child (node_type node, unsigned int index,
+                                      node_type child)
+{
+  Accessors::child (node, index) = child;
+  if (child)
+    set_parent (child, node);
+}
+
+// Rotate the tree to promote child number INDEX of NODE, so that that
+// child becomes a parent of NODE.  Return the promoted node.
+//
+// The caller has the responsibility of assigning a correct parent
+// to the returned node.
+template<typename Accessors>
+inline typename base_splay_tree<Accessors>::node_type
+base_splay_tree<Accessors>::promote_child (node_type node, unsigned int index)
+{
+  node_type promoted = get_child (node, index);
+  set_child (node, index, get_child (promoted, 1 - index));
+  set_child (promoted, 1 - index, node);
+  return promoted;
+}
+
+// Treat child number INDEX of NODE as being CHILD and rotate the tree
+// so that CHILD becomes a parent of NODE.
+//
+// The caller has the responsibility of assigning a correct parent to CHILD.
+template<typename Accessors>
+inline void
+base_splay_tree<Accessors>::promote_child (node_type node, unsigned int index,
+                                          node_type child)
+{
+  set_child (node, index, get_child (child, 1 - index));
+  set_child (child, 1 - index, node);
+}
+
+// Print NODE to PP, using PRINTER (PP, N) to print the contents of node N.
+// Prefix each new line with INDENT_STRING.  CODE is 'T' if NODE is the root
+// node, 'L' if NODE is the left child of its parent, or 'R' if NODE is the
+// right child of its parent.
+template<typename Accessors>
+template<typename Printer>
+void
+base_splay_tree<Accessors>::print (pretty_printer *pp, node_type node,
+                                  Printer printer, char code,
+                                  vec<char> &indent_string)
+{
+  // In the comments below, PREFIX refers to the incoming contents
+  // of INDENT_STRING.
+  node_type left = get_child (node, 0);
+  node_type right = get_child (node, 1);
+
+  auto orig_indent_len = indent_string.length ();
+  indent_string.safe_grow (orig_indent_len + 3);
+  char *extra_indent = indent_string.address () + orig_indent_len;
+
+  // Print [T], [L], or [R].
+  extra_indent[0] = '[';
+  extra_indent[1] = code;
+  extra_indent[2] = ']';
+  pp_append_text (pp, extra_indent, indent_string.end ());
+  pp_space (pp);
+
+  // Print the node itself, using PREFIX + " | " or PREFIX + "   " to indent
+  // new lines under the "[_]" that we just printed.
+  extra_indent[0] = ' ';
+  extra_indent[1] = (left || right ? '|' : ' ');
+  extra_indent[2] = ' ';
+  {
+    pretty_printer sub_pp;
+    printer (&sub_pp, node);
+    const char *text = pp_formatted_text (&sub_pp);
+    while (const char *end = strchr (text, '\n'))
+      {
+       pp_append_text (pp, text, end);
+       pp_newline_and_indent (pp, 0);
+       pp_append_text (pp, indent_string.begin (), indent_string.end ());
+       text = end + 1;
+      }
+    pp_string (pp, text);
+  }
+
+  if (left)
+    {
+      // Print PREFIX + " +-" for the first line of the left subtree,
+      // to be followed by "[L]".
+      extra_indent[1] = '+';
+      extra_indent[2] = '-';
+      pp_newline_and_indent (pp, 0);
+      pp_append_text (pp, indent_string.begin (), indent_string.end ());
+
+      // Print the left subtree, using PREFIX + " | " or PREFIX + "   "
+      // to indent under the PREFIX + " +-" that we just printed.
+      extra_indent[1] = right ? '|' : ' ';
+      extra_indent[2] = ' ';
+      print (pp, left, printer, 'L', indent_string);
+      extra_indent = indent_string.address () + orig_indent_len;
+
+      // If LEFT is not a leaf and we also have a right subtree, use a
+      // PREFIX + " |" line to separate them.
+      if (right && (get_child (left, 0) || get_child (left, 1)))
+       {
+         pp_newline_and_indent (pp, 0);
+         pp_append_text (pp, indent_string.begin (), &extra_indent[2]);
+       }
+    }
+  if (right)
+    {
+      // Print PREFIX + " +-" for the first line of the right subtree,
+      // to be followed by "[R]".
+      extra_indent[1] = '+';
+      extra_indent[2] = '-';
+      pp_newline_and_indent (pp, 0);
+      pp_append_text (pp, indent_string.begin (), indent_string.end ());
+
+      // Print the right subtree, using PREFIX + "   " to indent under the
+      // PREFIX + " +-" that we just printed.
+      extra_indent[1] = ' ';
+      extra_indent[2] = ' ';
+      print (pp, right, printer, 'R', indent_string);
+    }
+  indent_string.truncate (orig_indent_len);
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+template<typename Printer>
+void
+base_splay_tree<Accessors>::print (pretty_printer *pp, node_type node,
+                                  Printer printer)
+{
+  if (!node)
+    {
+      pp_string (pp, "null");
+      return;
+    }
+  auto_vec<char, 64> indent_string;
+  print (pp, node, printer, 'T', indent_string);
+}
+
+// If N is 1, splay the last (rightmost) node reachable from START
+// to the position that START current holds and return the splayed node.
+// START is not itself the last node.
+//
+// If N is 0, splay the first (leftmost) node reachable from START
+// to the position that START current holds and return the splayed node.
+// START is not itself the first node.
+//
+// The caller has the responsibility of updating the parent of the
+// returned node.
+template<typename Accessors>
+template<unsigned int N>
+typename base_splay_tree<Accessors>::node_type
+base_splay_tree<Accessors>::splay_limit (node_type start)
+{
+  // This essentially follows the simpilfied top-down method described
+  // in Sleator and Tarjan's "Self-adjusting Binary Search Trees", but
+  // specialized for the case in which the comparison result is fixed.
+  // The first iteration is peeled to avoid the need for stack temporaries.
+  //
+  // The comments and names reflect the behavior for N == 1, but the
+  // N == 0 case behaves analogously.
+
+  // Rotate the tree to promote the right child of START to the root.
+  node_type node = promote_child (start, N);
+  if (node_type right = get_child (node, N))
+    {
+      // Perform the link left step, which for this first iteration
+      // means making NODE the root of the left tree.
+      //
+      // NODE will become left child of the final node.  For a right
+      // spine starting at NODE of the form:
+      //
+      //  1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> ... -> N
+      //  |    |    |    |    |    |    |           |
+      //  V    V    V    V    V    V    V           V
+      //  A    B    C    D    E    F    G           NL
+      //
+      // the next step is to create a subtree of N whose right spine contains
+      // the odd-numbered nodes, as follows:
+      //
+      //  N
+      //  |
+      //  V
+      //  1 ------> 3 ------> 5 ------> 7 -> .... -> NL
+      //  |         |         |         |
+      //  V         V         V         V
+      //  A         2 -> C    4 -> E    6 -> G
+      //            |         |         |
+      //            V         V         V
+      //            B         D         F
+      //
+      // First record 1 as the left child of the final root (N) and move
+      // on to node 2.
+      node_type final_child = node;
+      node_type new_spine_end = node;
+      node = right;
+      while (node_type right = get_child (node, N))
+       {
+         // Perform another rotate left step.
+         //
+         // We've built the tree rooted at 1 in the diagram above up to,
+         // but not including, an even-numbered node NODE on the original
+         // right spine.  Rotate the tree at NODE to promote the following
+         // odd-numbered node.
+         promote_child (node, N, right);
+         node = right;
+         if (node_type right = get_child (node, N))
+           {
+             // Perform another link left step.
+             //
+             // Add the promoted odd-numbered node to the right spine of the
+             // tree rooted at 1 and move on to the next even-numbered node.
+             set_child (new_spine_end, N, node);
+             new_spine_end = node;
+             node = right;
+           }
+       }
+      // Perform the assembly step.
+      //
+      // Add NL to the new spine and make N the new root.
+      set_child (new_spine_end, N, get_child (node, 1 - N));
+      set_child (node, 1 - N, final_child);
+    }
+  return node;
+}
+
+// Remove NODE from its position in the splay tree.  If NODE has at least
+// one child node, return the node that should now hold NODE's position in
+// the splay tree.  If NODE has no children, return null.
+//
+// The caller has the responsibility of updating the parent of the
+// returned node.
+template<typename Accessors>
+inline typename base_splay_tree<Accessors>::node_type
+base_splay_tree<Accessors>::remove_node_internal (node_type node)
+{
+  node_type left = get_child (node, 0);
+  node_type right = get_child (node, 1);
+  if (!left)
+    return right;
+
+  if (!right)
+    return left;
+
+  if (get_child (left, 1))
+    {
+      left = splay_limit<1> (left);
+      gcc_checking_assert (!get_child (left, 1));
+    }
+  set_child (left, 1, right);
+  return left;
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+inline void
+base_splay_tree<Accessors>::insert_child (node_type node, unsigned int index,
+                                         node_type child)
+{
+  gcc_checking_assert (!get_child (child, 0) && !get_child (child, 1));
+  set_child (child, index, get_child (node, index));
+  set_child (node, index, child);
+}
+
+// Implement splay_next_node if N == 1 and splay_prev_node if N == 0.
+template<typename Accessors>
+template<unsigned int N>
+bool
+rooted_splay_tree<Accessors>::splay_neighbor ()
+{
+  node_type node = m_root;
+  node_type new_root = get_child (node, N);
+  if (!new_root)
+    return false;
+
+  if (get_child (new_root, 1 - N))
+    {
+      // NEW_ROOT is not itself the required node, so splay the required
+      // node into its place.
+      new_root = parent::template splay_limit<1 - N> (new_root);
+      gcc_checking_assert (!get_child (new_root, 1 - N));
+      set_child (node, N, node_type ());
+      set_child (new_root, 1 - N, node);
+    }
+  else
+    promote_child (node, N, new_root);
+  set_parent (new_root, node_type ());
+  m_root = new_root;
+  return true;
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+template<typename Comparator>
+bool
+rooted_splay_tree<Accessors>::insert (node_type new_node, Comparator compare)
+{
+  gcc_checking_assert (!get_child (new_node, 0) && !get_child (new_node, 1));
+  if (!m_root)
+    {
+      m_root = new_node;
+      return true;
+    }
+
+  int comparison = lookup (compare);
+  if (comparison == 0)
+    return false;
+
+  // Insert NEW_NODE before M_ROOT if COMPARISON < 0 and after M_ROOT
+  // otherwise.
+  set_child (new_node, comparison < 0, m_root);
+  set_child (new_node, comparison > 0, get_child (m_root, comparison > 0));
+  set_child (m_root, comparison > 0, nullptr);
+  m_root = new_node;
+  return true;
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+inline void
+rooted_splay_tree<Accessors>::insert_max_node (node_type new_node)
+{
+  gcc_checking_assert (!get_child (new_node, 0) && !get_child (new_node, 1));
+  set_child (new_node, 0, m_root);
+  m_root = new_node;
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+inline void
+rooted_splay_tree<Accessors>::splice_next_tree (rooted_splay_tree next_tree)
+{
+  splay_max_node ();
+  set_child (m_root, 1, next_tree.m_root);
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+inline void
+rooted_splay_tree<Accessors>::replace_max_node_at_root (node_type new_node)
+{
+  node_type old_node = m_root;
+  gcc_checking_assert (!get_child (new_node, 0)
+                      && !get_child (new_node, 1)
+                      && !get_child (old_node, 1));
+  set_child (new_node, 0, get_child (old_node, 0));
+  // Clear the links from OLD_NODE.  Its parent and right child are
+  // already node_type ().
+  set_child (old_node, 0, node_type ());
+  m_root = new_node;
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+inline void
+rooted_splay_tree<Accessors>::remove_root ()
+{
+  node_type node = m_root;
+  m_root = parent::remove_node_internal (node);
+  if (m_root)
+    set_parent (m_root, node_type ());
+  // Clear the links from NODE.  Its parent is already node_type ().
+  set_child (node, 0, node_type ());
+  set_child (node, 1, node_type ());
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+inline rooted_splay_tree<Accessors>
+rooted_splay_tree<Accessors>::split_before_root ()
+{
+  node_type new_root = get_child (m_root, 0);
+  set_child (m_root, 0, node_type ());
+  set_parent (new_root, node_type ());
+  return new_root;
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+inline rooted_splay_tree<Accessors>
+rooted_splay_tree<Accessors>::split_after_root ()
+{
+  node_type new_root = get_child (m_root, 1);
+  set_child (m_root, 1, node_type ());
+  set_parent (new_root, node_type ());
+  return new_root;
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+inline bool
+rooted_splay_tree<Accessors>::splay_prev_node ()
+{
+  return splay_neighbor<0> ();
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+inline bool
+rooted_splay_tree<Accessors>::splay_next_node ()
+{
+  return splay_neighbor<1> ();
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+inline void
+rooted_splay_tree<Accessors>::splay_min_node ()
+{
+  if (m_root && get_child (m_root, 0))
+    {
+      m_root = parent::template splay_limit<0> (m_root);
+      set_parent (m_root, node_type ());
+    }
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+inline void
+rooted_splay_tree<Accessors>::splay_max_node ()
+{
+  if (m_root && get_child (m_root, 1))
+    {
+      m_root = parent::template splay_limit<1> (m_root);
+      set_parent (m_root, node_type ());
+    }
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+inline typename rooted_splay_tree<Accessors>::node_type
+rooted_splay_tree<Accessors>::min_node ()
+{
+  splay_min_node ();
+  return m_root;
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+inline typename rooted_splay_tree<Accessors>::node_type
+rooted_splay_tree<Accessors>::max_node ()
+{
+  splay_max_node ();
+  return m_root;
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+template<typename Comparator>
+auto
+rooted_splay_tree<Accessors>::lookup (Comparator compare)
+  -> decltype (compare (m_root))
+{
+  // This essentially follows the simpilfied top-down method described
+  // in Sleator and Tarjan's "Self-adjusting Binary Search Trees", but
+  // with the complication that the comparisons are done only once.
+  using result_type = decltype (compare (m_root));
+
+  // The roots of the left and right trees.
+  node_type link_left_root = node_type ();
+  node_type link_right_root = node_type ();
+
+  // Where to add new nodes to the left and right trees.
+  node_type *link_left_ptr = &link_left_root;
+  node_type *link_right_ptr = &link_right_root;
+
+  // The nodes that contain *LINK_LEFT_PTR and *LINK_RIGHT_PTR,
+  // once they no longer point to the roots above.
+  node_type link_left_parent = node_type ();
+  node_type link_right_parent = node_type ();
+
+  auto link_left = [&](node_type node)
+    {
+      *link_left_ptr = node;
+      link_left_ptr = &Accessors::child (node, 1);
+      set_parent (node, link_left_parent);
+      link_left_parent = node;
+    };
+
+  auto link_right = [&](node_type node)
+    {
+      *link_right_ptr = node;
+      link_right_ptr = &Accessors::child (node, 0);
+      set_parent (node, link_right_parent);
+      link_right_parent = node;
+    };
+
+  node_type node = m_root;
+  node_type parent = node_type ();
+  result_type result;
+  result_type old_result = 0;
+  while (1)
+    {
+      // OLD_RESULT is 0 if NODE is the root of the middle tree.
+      // Otherwise, PARENT is the root of the middle tree and OLD_RESULT
+      // is how it compared.
+      //
+      // Results are:
+      // < 0 if we want something smaller.
+      // = 0 if we found the right node.
+      // > 0 if we want something bigger.
+      result = compare (node);
+      if (old_result < 0)
+       {
+         if (result < 0)
+           {
+             // SEARCH < NODE < PARENT
+             //
+             // Promote NODE (rotate right).
+             promote_child (parent, 0, node);
+             node_type next = get_child (node, 0);
+             if (!next)
+               break;
+
+             link_right (node);
+
+             // NEXT is now the root of the middle tree.
+             node = next;
+             old_result = 0;
+             continue;
+           }
+
+         // SEARCH >= NODE, NODE < PARENT
+         link_right (parent);
+       }
+      else if (old_result > 0)
+       {
+         if (result > 0)
+           {
+             // SEARCH > NODE > PARENT
+             //
+             // Promote NODE (rotate left).
+             promote_child (parent, 1, node);
+             node_type next = get_child (node, 1);
+             if (!next)
+               break;
+
+             link_left (node);
+
+             // NEXT is now the root of the middle tree.
+             node = next;
+             old_result = 0;
+             continue;
+           }
+
+         // SEARCH <= NODE, NODE > PARENT
+         link_left (parent);
+       }
+
+      // Microoptimization to allow NODE to be read even if RESULT == 0.
+      node_type next = get_child (node, result >= 0);
+      if (result == 0 || !next)
+       break;
+
+      // NODE is now the root of the tree.
+      parent = node;
+      node = next;
+      old_result = result;
+    }
+
+  node_type new_left = link_left_root;
+  node_type new_right = link_right_root;
+
+  if (new_left)
+    {
+      node_type old_left = get_child (node, 0);
+      *link_left_ptr = old_left;
+      if (old_left)
+       set_parent (old_left, link_left_parent);
+      set_child (node, 0, new_left);
+    }
+
+  if (new_right)
+    {
+      node_type old_right = get_child (node, 1);
+      *link_right_ptr = old_right;
+      if (old_right)
+       set_parent (old_right, link_right_parent);
+      set_child (node, 1, new_right);
+    }
+
+  set_parent (node, node_type ());
+  m_root = node;
+  return result;
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+template<typename LeftPredicate, typename RightPredicate>
+int
+rooted_splay_tree<Accessors>::lookup (LeftPredicate want_something_smaller,
+                                     RightPredicate want_something_bigger)
+{
+  // This essentially follows the simpilfied top-down method described
+  // in Sleator and Tarjan's "Self-adjusting Binary Search Trees"
+  // (and follows it more closely than the single-comparator version above).
+
+  // The roots of the left and right trees.
+  node_type link_left_root = node_type ();
+  node_type link_right_root = node_type ();
+
+  // Where to add new nodes to the left and right trees.
+  node_type *link_left_ptr = &link_left_root;
+  node_type *link_right_ptr = &link_right_root;
+
+  // The nodes that contain *LINK_LEFT_PTR and *LINK_RIGHT_PTR,
+  // once they no longer point to the roots above.
+  node_type link_left_parent = node_type ();
+  node_type link_right_parent = node_type ();
+
+  node_type node = m_root;
+  int result;
+  for (;;)
+    {
+      // NODE is the root of the middle tree.
+      if (want_something_smaller (node))
+       {
+         result = -1;
+         node_type next = get_child (node, 0);
+         if (!next)
+           break;
+
+         if (want_something_smaller (next))
+           {
+             // Promote NODE (rotate right).
+             promote_child (node, 0, next);
+             node = next;
+             next = get_child (node, 0);
+             if (!next)
+               break;
+           }
+
+         // Add NODE to the right tree (link right).
+         *link_right_ptr = node;
+         link_right_ptr = &Accessors::child (node, 0);
+         set_parent (node, link_right_parent);
+         link_right_parent = node;
+
+         node = next;
+       }
+      else if (want_something_bigger (node))
+       {
+         result = 1;
+         node_type next = get_child (node, 1);
+         if (!next)
+           break;
+
+         if (want_something_bigger (next))
+           {
+             // Promote NODE (rotate left).
+             promote_child (node, 1, next);
+             node = next;
+             next = get_child (node, 1);
+             if (!next)
+               break;
+           }
+
+         // Add NODE to the left tree (link left).
+         *link_left_ptr = node;
+         link_left_ptr = &Accessors::child (node, 1);
+         set_parent (node, link_left_parent);
+         link_left_parent = node;
+
+         node = next;
+       }
+      else
+       {
+         result = 0;
+         break;
+       }
+    }
+
+  node_type new_left = link_left_root;
+  node_type new_right = link_right_root;
+
+  if (new_left)
+    {
+      node_type old_left = get_child (node, 0);
+      *link_left_ptr = old_left;
+      if (old_left)
+       set_parent (old_left, link_left_parent);
+      set_child (node, 0, new_left);
+    }
+
+  if (new_right)
+    {
+      node_type old_right = get_child (node, 1);
+      *link_right_ptr = old_right;
+      if (old_right)
+       set_parent (old_right, link_right_parent);
+      set_child (node, 1, new_right);
+    }
+
+  set_parent (node, node_type ());
+  m_root = node;
+  return result;
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+template<typename Printer>
+inline void
+rooted_splay_tree<Accessors>::print (pretty_printer *pp, Printer printer) const
+{
+  print (pp, m_root, printer);
+}
+
+// Return NODE's current parent.
+template<typename Accessors>
+inline typename rootless_splay_tree<Accessors>::node_type
+rootless_splay_tree<Accessors>::get_parent (node_type node)
+{
+  return Accessors::parent (node);
+}
+
+// CHILD is known to be a child of PARENT.  Return which index it has.
+template<typename Accessors>
+inline unsigned int
+rootless_splay_tree<Accessors>::child_index (node_type parent, node_type child)
+{
+  return get_child (parent, 1) == child;
+}
+
+// If N == 1, implement splay_known_max_node, otherwise implement
+// splay_known_min_node.
+template<typename Accessors>
+template<unsigned int N>
+inline void
+rootless_splay_tree<Accessors>::splay_known_limit (node_type node)
+{
+  node_type child = node;
+  node_type parent = get_parent (child);
+  if (!parent)
+    return;
+
+  do
+    // At this point, NODE conceptually replaces CHILD as a child of
+    // PARENT, but we haven't yet updated PARENT accordingly.
+    if (node_type grandparent = get_parent (parent))
+      {
+       node_type greatgrandparent = get_parent (grandparent);
+       promote_child (grandparent, N, parent);
+       promote_child (parent, N, node);
+       child = grandparent;
+       parent = greatgrandparent;
+      }
+    else
+      {
+       promote_child (parent, N, node);
+       break;
+      }
+  while (parent);
+  set_parent (node, node_type ());
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+typename rootless_splay_tree<Accessors>::node_type
+rootless_splay_tree<Accessors>::remove_node (node_type node)
+{
+  node_type replacement = parent::remove_node_internal (node);
+  if (node_type parent = get_parent (node))
+    set_child (parent, child_index (parent, node), replacement);
+  else if (replacement)
+    set_parent (replacement, node_type ());
+  // Clear the links from NODE.
+  set_parent (node, node_type ());
+  set_child (node, 0, node_type ());
+  set_child (node, 1, node_type ());
+  return replacement;
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+void
+rootless_splay_tree<Accessors>::splay (node_type node)
+{
+  node_type child = node;
+  node_type parent = get_parent (child);
+  if (!parent)
+    return;
+
+  do
+    {
+      // At this point, NODE conceptually replaces CHILD as a child of
+      // PARENT, but we haven't yet updated PARENT accordingly.
+      unsigned int index = child_index (parent, child);
+      if (node_type grandparent = get_parent (parent))
+       {
+         node_type greatgrandparent = get_parent (grandparent);
+         unsigned int parent_index = child_index (grandparent, parent);
+         if (index == parent_index)
+           {
+             promote_child (grandparent, parent_index, parent);
+             promote_child (parent, index, node);
+           }
+         else
+           {
+             promote_child (parent, index, node);
+             promote_child (grandparent, parent_index, node);
+           }
+         child = grandparent;
+         parent = greatgrandparent;
+       }
+      else
+       {
+         promote_child (parent, index, node);
+         break;
+       }
+    }
+  while (parent);
+  set_parent (node, node_type ());
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+inline void
+rootless_splay_tree<Accessors>::splay_known_min_node (node_type node)
+{
+  splay_known_limit<0> (node);
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+inline void
+rootless_splay_tree<Accessors>::splay_known_max_node (node_type node)
+{
+  splay_known_limit<1> (node);
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+template<typename DefaultResult, typename Predicate>
+auto
+rootless_splay_tree<Accessors>::
+splay_and_search (node_type node, DefaultResult default_result,
+                 Predicate predicate)
+  -> decltype (predicate (node, 0))
+{
+  using Result = decltype (predicate (node, 0));
+
+  node_type child = node;
+  node_type parent = get_parent (child);
+  if (!parent)
+    return default_result;
+
+  do
+    {
+      // At this point, NODE conceptually replaces CHILD as a child of
+      // PARENT, but we haven't yet updated PARENT accordingly.
+      unsigned int index = child_index (parent, child);
+      if (Result result = predicate (parent, index))
+       {
+         set_child (parent, index, node);
+         return result;
+       }
+      if (node_type grandparent = get_parent (parent))
+       {
+         node_type greatgrandparent = get_parent (grandparent);
+         unsigned int parent_index = child_index (grandparent, parent);
+         if (Result result = predicate (grandparent, parent_index))
+           {
+             set_child (parent, index, node);
+             return result;
+           }
+         if (index == parent_index)
+           {
+             promote_child (grandparent, parent_index, parent);
+             promote_child (parent, index, node);
+           }
+         else
+           {
+             promote_child (parent, index, node);
+             promote_child (grandparent, parent_index, node);
+           }
+         child = grandparent;
+         parent = greatgrandparent;
+       }
+      else
+       {
+         promote_child (parent, index, node);
+         break;
+       }
+    }
+  while (parent);
+  set_parent (node, node_type ());
+  return default_result;
+}
+
+// Splay NODE1 looking to see if one of its ancestors is NODE2.  If it is,
+// return -1 if NODE1 comes before NODE2 or 1 if NODE1 comes after NODE2.
+// Return 0 if NODE2 is not an ancestor of NODE1.
+template<typename Accessors>
+int
+rootless_splay_tree<Accessors>::compare_nodes_one_way (node_type node1,
+                                                      node_type node2)
+{
+  auto compare = [&](node_type parent, unsigned int index) -> int
+    {
+      if (parent == node2)
+       return index ? 1 : -1;
+      return 0;
+    };
+  return splay_and_search (node1, 0, compare);
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+int
+rootless_splay_tree<Accessors>::compare_nodes (node_type node1,
+                                              node_type node2)
+{
+  if (node1 == node2)
+    return 0;
+
+  // Splay NODE1 looking for NODE2.
+  int cmp = compare_nodes_one_way (node1, node2);
+  if (cmp)
+    return cmp;
+
+  // That failed, but NODE1 is now the root of the tree.  Splay NODE2
+  // to see on which side of NODE1 it falls.
+  cmp = compare_nodes_one_way (node2, node1);
+  gcc_checking_assert (cmp);
+  return -cmp;
+}