Eliminate Subzero's dependency on llvm::FoldingSet

Bug: b/155971541
Change-Id: I039fb24b31f01fff1ca2190fd6fe3b3e8118990e
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/44929
Kokoro-Result: kokoro <noreply+kokoro@google.com>
Tested-by: Nicolas Capens <nicolascapens@google.com>
Reviewed-by: Sean Risser <srisser@google.com>
diff --git a/src/Reactor/BUILD.gn b/src/Reactor/BUILD.gn
index 737e00f..eb72fd9 100644
--- a/src/Reactor/BUILD.gn
+++ b/src/Reactor/BUILD.gn
@@ -222,7 +222,6 @@
       "$subzero_llvm_dir/lib/Support/Debug.cpp",
       "$subzero_llvm_dir/lib/Support/Errno.cpp",
       "$subzero_llvm_dir/lib/Support/ErrorHandling.cpp",
-      "$subzero_llvm_dir/lib/Support/FoldingSet.cpp",
       "$subzero_llvm_dir/lib/Support/Hashing.cpp",
       "$subzero_llvm_dir/lib/Support/ManagedStatic.cpp",
       "$subzero_llvm_dir/lib/Support/MemoryBuffer.cpp",
diff --git a/third_party/llvm-subzero/Android.bp b/third_party/llvm-subzero/Android.bp
index bf70dc5..f5e1c3a 100644
--- a/third_party/llvm-subzero/Android.bp
+++ b/third_party/llvm-subzero/Android.bp
@@ -82,7 +82,6 @@
         "lib/Support/Debug.cpp",
         "lib/Support/Errno.cpp",
         "lib/Support/ErrorHandling.cpp",
-        "lib/Support/FoldingSet.cpp",
         "lib/Support/Hashing.cpp",
         "lib/Support/ManagedStatic.cpp",
         "lib/Support/MemoryBuffer.cpp",
diff --git a/third_party/llvm-subzero/CMakeLists.txt b/third_party/llvm-subzero/CMakeLists.txt
index 03b63b7..d8be547 100644
--- a/third_party/llvm-subzero/CMakeLists.txt
+++ b/third_party/llvm-subzero/CMakeLists.txt
@@ -44,7 +44,6 @@
     "include/llvm/ADT/DenseMapInfo.h"
     "include/llvm/ADT/edit_distance.h"
     "include/llvm/ADT/EpochTracker.h"
-    "include/llvm/ADT/FoldingSet.h"
     "include/llvm/ADT/Hashing.h"
     "include/llvm/ADT/ilist_base.h"
     "include/llvm/ADT/ilist_iterator.h"
@@ -166,7 +165,6 @@
     "lib/Support/Debug.cpp"
     "lib/Support/Errno.cpp"
     "lib/Support/ErrorHandling.cpp"
-    "lib/Support/FoldingSet.cpp"
     "lib/Support/Hashing.cpp"
     "lib/Support/ManagedStatic.cpp"
     "lib/Support/MemoryBuffer.cpp"
diff --git a/third_party/llvm-subzero/include/llvm/ADT/FoldingSet.h b/third_party/llvm-subzero/include/llvm/ADT/FoldingSet.h
deleted file mode 100644
index dab1829..0000000
--- a/third_party/llvm-subzero/include/llvm/ADT/FoldingSet.h
+++ /dev/null
@@ -1,777 +0,0 @@
-//===-- llvm/ADT/FoldingSet.h - Uniquing Hash Set ---------------*- C++ -*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines a hash set that can be used to remove duplication of nodes
-// in a graph.  This code was originally created by Chris Lattner for use with
-// SelectionDAGCSEMap, but was isolated to provide use across the llvm code set.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_ADT_FOLDINGSET_H
-#define LLVM_ADT_FOLDINGSET_H
-
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/iterator.h"
-#include "llvm/Support/Allocator.h"
-#include <cassert>
-#include <cstddef>
-#include <cstdint>
-#include <utility>
-
-namespace llvm {
-
-/// This folding set used for two purposes:
-///   1. Given information about a node we want to create, look up the unique
-///      instance of the node in the set.  If the node already exists, return
-///      it, otherwise return the bucket it should be inserted into.
-///   2. Given a node that has already been created, remove it from the set.
-///
-/// This class is implemented as a single-link chained hash table, where the
-/// "buckets" are actually the nodes themselves (the next pointer is in the
-/// node).  The last node points back to the bucket to simplify node removal.
-///
-/// Any node that is to be included in the folding set must be a subclass of
-/// FoldingSetNode.  The node class must also define a Profile method used to
-/// establish the unique bits of data for the node.  The Profile method is
-/// passed a FoldingSetNodeID object which is used to gather the bits.  Just
-/// call one of the Add* functions defined in the FoldingSetImpl::NodeID class.
-/// NOTE: That the folding set does not own the nodes and it is the
-/// responsibility of the user to dispose of the nodes.
-///
-/// Eg.
-///    class MyNode : public FoldingSetNode {
-///    private:
-///      std::string Name;
-///      unsigned Value;
-///    public:
-///      MyNode(const char *N, unsigned V) : Name(N), Value(V) {}
-///       ...
-///      void Profile(FoldingSetNodeID &ID) const {
-///        ID.AddString(Name);
-///        ID.AddInteger(Value);
-///      }
-///      ...
-///    };
-///
-/// To define the folding set itself use the FoldingSet template;
-///
-/// Eg.
-///    FoldingSet<MyNode> MyFoldingSet;
-///
-/// Four public methods are available to manipulate the folding set;
-///
-/// 1) If you have an existing node that you want add to the set but unsure
-/// that the node might already exist then call;
-///
-///    MyNode *M = MyFoldingSet.GetOrInsertNode(N);
-///
-/// If The result is equal to the input then the node has been inserted.
-/// Otherwise, the result is the node existing in the folding set, and the
-/// input can be discarded (use the result instead.)
-///
-/// 2) If you are ready to construct a node but want to check if it already
-/// exists, then call FindNodeOrInsertPos with a FoldingSetNodeID of the bits to
-/// check;
-///
-///   FoldingSetNodeID ID;
-///   ID.AddString(Name);
-///   ID.AddInteger(Value);
-///   void *InsertPoint;
-///
-///    MyNode *M = MyFoldingSet.FindNodeOrInsertPos(ID, InsertPoint);
-///
-/// If found then M with be non-NULL, else InsertPoint will point to where it
-/// should be inserted using InsertNode.
-///
-/// 3) If you get a NULL result from FindNodeOrInsertPos then you can as a new
-/// node with FindNodeOrInsertPos;
-///
-///    InsertNode(N, InsertPoint);
-///
-/// 4) Finally, if you want to remove a node from the folding set call;
-///
-///    bool WasRemoved = RemoveNode(N);
-///
-/// The result indicates whether the node existed in the folding set.
-
-class FoldingSetNodeID;
-class StringRef;
-
-//===----------------------------------------------------------------------===//
-/// FoldingSetImpl - Implements the folding set functionality.  The main
-/// structure is an array of buckets.  Each bucket is indexed by the hash of
-/// the nodes it contains.  The bucket itself points to the nodes contained
-/// in the bucket via a singly linked list.  The last node in the list points
-/// back to the bucket to facilitate node removal.
-///
-class FoldingSetImpl {
-  virtual void anchor(); // Out of line virtual method.
-
-protected:
-  /// Buckets - Array of bucket chains.
-  ///
-  void **Buckets;
-
-  /// NumBuckets - Length of the Buckets array.  Always a power of 2.
-  ///
-  unsigned NumBuckets;
-
-  /// NumNodes - Number of nodes in the folding set. Growth occurs when NumNodes
-  /// is greater than twice the number of buckets.
-  unsigned NumNodes;
-
-  explicit FoldingSetImpl(unsigned Log2InitSize = 6);
-  FoldingSetImpl(FoldingSetImpl &&Arg);
-  FoldingSetImpl &operator=(FoldingSetImpl &&RHS);
-  ~FoldingSetImpl();
-
-public:
-  //===--------------------------------------------------------------------===//
-  /// Node - This class is used to maintain the singly linked bucket list in
-  /// a folding set.
-  ///
-  class Node {
-  private:
-    // NextInFoldingSetBucket - next link in the bucket list.
-    void *NextInFoldingSetBucket;
-
-  public:
-    Node() : NextInFoldingSetBucket(nullptr) {}
-
-    // Accessors
-    void *getNextInBucket() const { return NextInFoldingSetBucket; }
-    void SetNextInBucket(void *N) { NextInFoldingSetBucket = N; }
-  };
-
-  /// clear - Remove all nodes from the folding set.
-  void clear();
-
-  /// RemoveNode - Remove a node from the folding set, returning true if one
-  /// was removed or false if the node was not in the folding set.
-  bool RemoveNode(Node *N);
-
-  /// GetOrInsertNode - If there is an existing simple Node exactly
-  /// equal to the specified node, return it.  Otherwise, insert 'N' and return
-  /// it instead.
-  Node *GetOrInsertNode(Node *N);
-
-  /// FindNodeOrInsertPos - Look up the node specified by ID.  If it exists,
-  /// return it.  If not, return the insertion token that will make insertion
-  /// faster.
-  Node *FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos);
-
-  /// InsertNode - Insert the specified node into the folding set, knowing that
-  /// it is not already in the folding set.  InsertPos must be obtained from
-  /// FindNodeOrInsertPos.
-  void InsertNode(Node *N, void *InsertPos);
-
-  /// InsertNode - Insert the specified node into the folding set, knowing that
-  /// it is not already in the folding set.
-  void InsertNode(Node *N) {
-    Node *Inserted = GetOrInsertNode(N);
-    (void)Inserted;
-    assert(Inserted == N && "Node already inserted!");
-  }
-
-  /// size - Returns the number of nodes in the folding set.
-  unsigned size() const { return NumNodes; }
-
-  /// empty - Returns true if there are no nodes in the folding set.
-  bool empty() const { return NumNodes == 0; }
-
-  /// reserve - Increase the number of buckets such that adding the
-  /// EltCount-th node won't cause a rebucket operation. reserve is permitted
-  /// to allocate more space than requested by EltCount.
-  void reserve(unsigned EltCount);
-
-  /// capacity - Returns the number of nodes permitted in the folding set
-  /// before a rebucket operation is performed.
-  unsigned capacity() {
-    // We allow a load factor of up to 2.0,
-    // so that means our capacity is NumBuckets * 2
-    return NumBuckets * 2;
-  }
-
-private:
-  /// GrowHashTable - Double the size of the hash table and rehash everything.
-  void GrowHashTable();
-
-  /// GrowBucketCount - resize the hash table and rehash everything.
-  /// NewBucketCount must be a power of two, and must be greater than the old
-  /// bucket count.
-  void GrowBucketCount(unsigned NewBucketCount);
-
-protected:
-  /// GetNodeProfile - Instantiations of the FoldingSet template implement
-  /// this function to gather data bits for the given node.
-  virtual void GetNodeProfile(Node *N, FoldingSetNodeID &ID) const = 0;
-
-  /// NodeEquals - Instantiations of the FoldingSet template implement
-  /// this function to compare the given node with the given ID.
-  virtual bool NodeEquals(Node *N, const FoldingSetNodeID &ID, unsigned IDHash,
-                          FoldingSetNodeID &TempID) const=0;
-
-  /// ComputeNodeHash - Instantiations of the FoldingSet template implement
-  /// this function to compute a hash value for the given node.
-  virtual unsigned ComputeNodeHash(Node *N, FoldingSetNodeID &TempID) const = 0;
-};
-
-//===----------------------------------------------------------------------===//
-
-/// DefaultFoldingSetTrait - This class provides default implementations
-/// for FoldingSetTrait implementations.
-///
-template<typename T> struct DefaultFoldingSetTrait {
-  static void Profile(const T &X, FoldingSetNodeID &ID) {
-    X.Profile(ID);
-  }
-  static void Profile(T &X, FoldingSetNodeID &ID) {
-    X.Profile(ID);
-  }
-
-  // Equals - Test if the profile for X would match ID, using TempID
-  // to compute a temporary ID if necessary. The default implementation
-  // just calls Profile and does a regular comparison. Implementations
-  // can override this to provide more efficient implementations.
-  static inline bool Equals(T &X, const FoldingSetNodeID &ID, unsigned IDHash,
-                            FoldingSetNodeID &TempID);
-
-  // ComputeHash - Compute a hash value for X, using TempID to
-  // compute a temporary ID if necessary. The default implementation
-  // just calls Profile and does a regular hash computation.
-  // Implementations can override this to provide more efficient
-  // implementations.
-  static inline unsigned ComputeHash(T &X, FoldingSetNodeID &TempID);
-};
-
-/// FoldingSetTrait - This trait class is used to define behavior of how
-/// to "profile" (in the FoldingSet parlance) an object of a given type.
-/// The default behavior is to invoke a 'Profile' method on an object, but
-/// through template specialization the behavior can be tailored for specific
-/// types.  Combined with the FoldingSetNodeWrapper class, one can add objects
-/// to FoldingSets that were not originally designed to have that behavior.
-template<typename T> struct FoldingSetTrait
-  : public DefaultFoldingSetTrait<T> {};
-
-/// DefaultContextualFoldingSetTrait - Like DefaultFoldingSetTrait, but
-/// for ContextualFoldingSets.
-template<typename T, typename Ctx>
-struct DefaultContextualFoldingSetTrait {
-  static void Profile(T &X, FoldingSetNodeID &ID, Ctx Context) {
-    X.Profile(ID, Context);
-  }
-
-  static inline bool Equals(T &X, const FoldingSetNodeID &ID, unsigned IDHash,
-                            FoldingSetNodeID &TempID, Ctx Context);
-  static inline unsigned ComputeHash(T &X, FoldingSetNodeID &TempID,
-                                     Ctx Context);
-};
-
-/// ContextualFoldingSetTrait - Like FoldingSetTrait, but for
-/// ContextualFoldingSets.
-template<typename T, typename Ctx> struct ContextualFoldingSetTrait
-  : public DefaultContextualFoldingSetTrait<T, Ctx> {};
-
-//===--------------------------------------------------------------------===//
-/// FoldingSetNodeIDRef - This class describes a reference to an interned
-/// FoldingSetNodeID, which can be a useful to store node id data rather
-/// than using plain FoldingSetNodeIDs, since the 32-element SmallVector
-/// is often much larger than necessary, and the possibility of heap
-/// allocation means it requires a non-trivial destructor call.
-class FoldingSetNodeIDRef {
-  const unsigned *Data = nullptr;
-  size_t Size = 0;
-
-public:
-  FoldingSetNodeIDRef() = default;
-  FoldingSetNodeIDRef(const unsigned *D, size_t S) : Data(D), Size(S) {}
-
-  /// ComputeHash - Compute a strong hash value for this FoldingSetNodeIDRef,
-  /// used to lookup the node in the FoldingSetImpl.
-  unsigned ComputeHash() const;
-
-  bool operator==(FoldingSetNodeIDRef) const;
-
-  bool operator!=(FoldingSetNodeIDRef RHS) const { return !(*this == RHS); }
-
-  /// Used to compare the "ordering" of two nodes as defined by the
-  /// profiled bits and their ordering defined by memcmp().
-  bool operator<(FoldingSetNodeIDRef) const;
-
-  const unsigned *getData() const { return Data; }
-  size_t getSize() const { return Size; }
-};
-
-//===--------------------------------------------------------------------===//
-/// FoldingSetNodeID - This class is used to gather all the unique data bits of
-/// a node.  When all the bits are gathered this class is used to produce a
-/// hash value for the node.
-///
-class FoldingSetNodeID {
-  /// Bits - Vector of all the data bits that make the node unique.
-  /// Use a SmallVector to avoid a heap allocation in the common case.
-  SmallVector<unsigned, 32> Bits;
-
-public:
-  FoldingSetNodeID() = default;
-
-  FoldingSetNodeID(FoldingSetNodeIDRef Ref)
-    : Bits(Ref.getData(), Ref.getData() + Ref.getSize()) {}
-
-  /// Add* - Add various data types to Bit data.
-  ///
-  void AddPointer(const void *Ptr);
-  void AddInteger(signed I);
-  void AddInteger(unsigned I);
-  void AddInteger(long I);
-  void AddInteger(unsigned long I);
-  void AddInteger(long long I);
-  void AddInteger(unsigned long long I);
-  void AddBoolean(bool B) { AddInteger(B ? 1U : 0U); }
-  void AddString(StringRef String);
-  void AddNodeID(const FoldingSetNodeID &ID);
-
-  template <typename T>
-  inline void Add(const T &x) { FoldingSetTrait<T>::Profile(x, *this); }
-
-  /// clear - Clear the accumulated profile, allowing this FoldingSetNodeID
-  /// object to be used to compute a new profile.
-  inline void clear() { Bits.clear(); }
-
-  /// ComputeHash - Compute a strong hash value for this FoldingSetNodeID, used
-  /// to lookup the node in the FoldingSetImpl.
-  unsigned ComputeHash() const;
-
-  /// operator== - Used to compare two nodes to each other.
-  ///
-  bool operator==(const FoldingSetNodeID &RHS) const;
-  bool operator==(const FoldingSetNodeIDRef RHS) const;
-
-  bool operator!=(const FoldingSetNodeID &RHS) const { return !(*this == RHS); }
-  bool operator!=(const FoldingSetNodeIDRef RHS) const { return !(*this ==RHS);}
-
-  /// Used to compare the "ordering" of two nodes as defined by the
-  /// profiled bits and their ordering defined by memcmp().
-  bool operator<(const FoldingSetNodeID &RHS) const;
-  bool operator<(const FoldingSetNodeIDRef RHS) const;
-
-  /// Intern - Copy this node's data to a memory region allocated from the
-  /// given allocator and return a FoldingSetNodeIDRef describing the
-  /// interned data.
-  FoldingSetNodeIDRef Intern(BumpPtrAllocator &Allocator) const;
-};
-
-// Convenience type to hide the implementation of the folding set.
-typedef FoldingSetImpl::Node FoldingSetNode;
-template<class T> class FoldingSetIterator;
-template<class T> class FoldingSetBucketIterator;
-
-// Definitions of FoldingSetTrait and ContextualFoldingSetTrait functions, which
-// require the definition of FoldingSetNodeID.
-template<typename T>
-inline bool
-DefaultFoldingSetTrait<T>::Equals(T &X, const FoldingSetNodeID &ID,
-                                  unsigned /*IDHash*/,
-                                  FoldingSetNodeID &TempID) {
-  FoldingSetTrait<T>::Profile(X, TempID);
-  return TempID == ID;
-}
-template<typename T>
-inline unsigned
-DefaultFoldingSetTrait<T>::ComputeHash(T &X, FoldingSetNodeID &TempID) {
-  FoldingSetTrait<T>::Profile(X, TempID);
-  return TempID.ComputeHash();
-}
-template<typename T, typename Ctx>
-inline bool
-DefaultContextualFoldingSetTrait<T, Ctx>::Equals(T &X,
-                                                 const FoldingSetNodeID &ID,
-                                                 unsigned /*IDHash*/,
-                                                 FoldingSetNodeID &TempID,
-                                                 Ctx Context) {
-  ContextualFoldingSetTrait<T, Ctx>::Profile(X, TempID, Context);
-  return TempID == ID;
-}
-template<typename T, typename Ctx>
-inline unsigned
-DefaultContextualFoldingSetTrait<T, Ctx>::ComputeHash(T &X,
-                                                      FoldingSetNodeID &TempID,
-                                                      Ctx Context) {
-  ContextualFoldingSetTrait<T, Ctx>::Profile(X, TempID, Context);
-  return TempID.ComputeHash();
-}
-
-//===----------------------------------------------------------------------===//
-/// FoldingSet - This template class is used to instantiate a specialized
-/// implementation of the folding set to the node class T.  T must be a
-/// subclass of FoldingSetNode and implement a Profile function.
-///
-/// Note that this set type is movable and move-assignable. However, its
-/// moved-from state is not a valid state for anything other than
-/// move-assigning and destroying. This is primarily to enable movable APIs
-/// that incorporate these objects.
-template <class T> class FoldingSet final : public FoldingSetImpl {
-private:
-  /// GetNodeProfile - Each instantiatation of the FoldingSet needs to provide a
-  /// way to convert nodes into a unique specifier.
-  void GetNodeProfile(Node *N, FoldingSetNodeID &ID) const override {
-    T *TN = static_cast<T *>(N);
-    FoldingSetTrait<T>::Profile(*TN, ID);
-  }
-
-  /// NodeEquals - Instantiations may optionally provide a way to compare a
-  /// node with a specified ID.
-  bool NodeEquals(Node *N, const FoldingSetNodeID &ID, unsigned IDHash,
-                  FoldingSetNodeID &TempID) const override {
-    T *TN = static_cast<T *>(N);
-    return FoldingSetTrait<T>::Equals(*TN, ID, IDHash, TempID);
-  }
-
-  /// ComputeNodeHash - Instantiations may optionally provide a way to compute a
-  /// hash value directly from a node.
-  unsigned ComputeNodeHash(Node *N, FoldingSetNodeID &TempID) const override {
-    T *TN = static_cast<T *>(N);
-    return FoldingSetTrait<T>::ComputeHash(*TN, TempID);
-  }
-
-public:
-  explicit FoldingSet(unsigned Log2InitSize = 6)
-      : FoldingSetImpl(Log2InitSize) {}
-
-  FoldingSet(FoldingSet &&Arg) : FoldingSetImpl(std::move(Arg)) {}
-  FoldingSet &operator=(FoldingSet &&RHS) {
-    (void)FoldingSetImpl::operator=(std::move(RHS));
-    return *this;
-  }
-
-  typedef FoldingSetIterator<T> iterator;
-  iterator begin() { return iterator(Buckets); }
-  iterator end() { return iterator(Buckets+NumBuckets); }
-
-  typedef FoldingSetIterator<const T> const_iterator;
-  const_iterator begin() const { return const_iterator(Buckets); }
-  const_iterator end() const { return const_iterator(Buckets+NumBuckets); }
-
-  typedef FoldingSetBucketIterator<T> bucket_iterator;
-
-  bucket_iterator bucket_begin(unsigned hash) {
-    return bucket_iterator(Buckets + (hash & (NumBuckets-1)));
-  }
-
-  bucket_iterator bucket_end(unsigned hash) {
-    return bucket_iterator(Buckets + (hash & (NumBuckets-1)), true);
-  }
-
-  /// GetOrInsertNode - If there is an existing simple Node exactly
-  /// equal to the specified node, return it.  Otherwise, insert 'N' and
-  /// return it instead.
-  T *GetOrInsertNode(Node *N) {
-    return static_cast<T *>(FoldingSetImpl::GetOrInsertNode(N));
-  }
-
-  /// FindNodeOrInsertPos - Look up the node specified by ID.  If it exists,
-  /// return it.  If not, return the insertion token that will make insertion
-  /// faster.
-  T *FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos) {
-    return static_cast<T *>(FoldingSetImpl::FindNodeOrInsertPos(ID, InsertPos));
-  }
-};
-
-//===----------------------------------------------------------------------===//
-/// ContextualFoldingSet - This template class is a further refinement
-/// of FoldingSet which provides a context argument when calling
-/// Profile on its nodes.  Currently, that argument is fixed at
-/// initialization time.
-///
-/// T must be a subclass of FoldingSetNode and implement a Profile
-/// function with signature
-///   void Profile(FoldingSetNodeID &, Ctx);
-template <class T, class Ctx>
-class ContextualFoldingSet final : public FoldingSetImpl {
-  // Unfortunately, this can't derive from FoldingSet<T> because the
-  // construction vtable for FoldingSet<T> requires
-  // FoldingSet<T>::GetNodeProfile to be instantiated, which in turn
-  // requires a single-argument T::Profile().
-
-private:
-  Ctx Context;
-
-  /// GetNodeProfile - Each instantiatation of the FoldingSet needs to provide a
-  /// way to convert nodes into a unique specifier.
-  void GetNodeProfile(FoldingSetImpl::Node *N,
-                      FoldingSetNodeID &ID) const override {
-    T *TN = static_cast<T *>(N);
-    ContextualFoldingSetTrait<T, Ctx>::Profile(*TN, ID, Context);
-  }
-
-  bool NodeEquals(FoldingSetImpl::Node *N, const FoldingSetNodeID &ID,
-                  unsigned IDHash, FoldingSetNodeID &TempID) const override {
-    T *TN = static_cast<T *>(N);
-    return ContextualFoldingSetTrait<T, Ctx>::Equals(*TN, ID, IDHash, TempID,
-                                                     Context);
-  }
-
-  unsigned ComputeNodeHash(FoldingSetImpl::Node *N,
-                           FoldingSetNodeID &TempID) const override {
-    T *TN = static_cast<T *>(N);
-    return ContextualFoldingSetTrait<T, Ctx>::ComputeHash(*TN, TempID, Context);
-  }
-
-public:
-  explicit ContextualFoldingSet(Ctx Context, unsigned Log2InitSize = 6)
-  : FoldingSetImpl(Log2InitSize), Context(Context)
-  {}
-
-  Ctx getContext() const { return Context; }
-
-  typedef FoldingSetIterator<T> iterator;
-  iterator begin() { return iterator(Buckets); }
-  iterator end() { return iterator(Buckets+NumBuckets); }
-
-  typedef FoldingSetIterator<const T> const_iterator;
-  const_iterator begin() const { return const_iterator(Buckets); }
-  const_iterator end() const { return const_iterator(Buckets+NumBuckets); }
-
-  typedef FoldingSetBucketIterator<T> bucket_iterator;
-
-  bucket_iterator bucket_begin(unsigned hash) {
-    return bucket_iterator(Buckets + (hash & (NumBuckets-1)));
-  }
-
-  bucket_iterator bucket_end(unsigned hash) {
-    return bucket_iterator(Buckets + (hash & (NumBuckets-1)), true);
-  }
-
-  /// GetOrInsertNode - If there is an existing simple Node exactly
-  /// equal to the specified node, return it.  Otherwise, insert 'N'
-  /// and return it instead.
-  T *GetOrInsertNode(Node *N) {
-    return static_cast<T *>(FoldingSetImpl::GetOrInsertNode(N));
-  }
-
-  /// FindNodeOrInsertPos - Look up the node specified by ID.  If it
-  /// exists, return it.  If not, return the insertion token that will
-  /// make insertion faster.
-  T *FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos) {
-    return static_cast<T *>(FoldingSetImpl::FindNodeOrInsertPos(ID, InsertPos));
-  }
-};
-
-//===----------------------------------------------------------------------===//
-/// FoldingSetVector - This template class combines a FoldingSet and a vector
-/// to provide the interface of FoldingSet but with deterministic iteration
-/// order based on the insertion order. T must be a subclass of FoldingSetNode
-/// and implement a Profile function.
-template <class T, class VectorT = SmallVector<T*, 8>>
-class FoldingSetVector {
-  FoldingSet<T> Set;
-  VectorT Vector;
-
-public:
-  explicit FoldingSetVector(unsigned Log2InitSize = 6)
-      : Set(Log2InitSize) {
-  }
-
-  typedef pointee_iterator<typename VectorT::iterator> iterator;
-  iterator begin() { return Vector.begin(); }
-  iterator end()   { return Vector.end(); }
-
-  typedef pointee_iterator<typename VectorT::const_iterator> const_iterator;
-  const_iterator begin() const { return Vector.begin(); }
-  const_iterator end()   const { return Vector.end(); }
-
-  /// clear - Remove all nodes from the folding set.
-  void clear() { Set.clear(); Vector.clear(); }
-
-  /// FindNodeOrInsertPos - Look up the node specified by ID.  If it exists,
-  /// return it.  If not, return the insertion token that will make insertion
-  /// faster.
-  T *FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos) {
-    return Set.FindNodeOrInsertPos(ID, InsertPos);
-  }
-
-  /// GetOrInsertNode - If there is an existing simple Node exactly
-  /// equal to the specified node, return it.  Otherwise, insert 'N' and
-  /// return it instead.
-  T *GetOrInsertNode(T *N) {
-    T *Result = Set.GetOrInsertNode(N);
-    if (Result == N) Vector.push_back(N);
-    return Result;
-  }
-
-  /// InsertNode - Insert the specified node into the folding set, knowing that
-  /// it is not already in the folding set.  InsertPos must be obtained from
-  /// FindNodeOrInsertPos.
-  void InsertNode(T *N, void *InsertPos) {
-    Set.InsertNode(N, InsertPos);
-    Vector.push_back(N);
-  }
-
-  /// InsertNode - Insert the specified node into the folding set, knowing that
-  /// it is not already in the folding set.
-  void InsertNode(T *N) {
-    Set.InsertNode(N);
-    Vector.push_back(N);
-  }
-
-  /// size - Returns the number of nodes in the folding set.
-  unsigned size() const { return Set.size(); }
-
-  /// empty - Returns true if there are no nodes in the folding set.
-  bool empty() const { return Set.empty(); }
-};
-
-//===----------------------------------------------------------------------===//
-/// FoldingSetIteratorImpl - This is the common iterator support shared by all
-/// folding sets, which knows how to walk the folding set hash table.
-class FoldingSetIteratorImpl {
-protected:
-  FoldingSetNode *NodePtr;
-
-  FoldingSetIteratorImpl(void **Bucket);
-
-  void advance();
-
-public:
-  bool operator==(const FoldingSetIteratorImpl &RHS) const {
-    return NodePtr == RHS.NodePtr;
-  }
-  bool operator!=(const FoldingSetIteratorImpl &RHS) const {
-    return NodePtr != RHS.NodePtr;
-  }
-};
-
-template <class T> class FoldingSetIterator : public FoldingSetIteratorImpl {
-public:
-  explicit FoldingSetIterator(void **Bucket) : FoldingSetIteratorImpl(Bucket) {}
-
-  T &operator*() const {
-    return *static_cast<T*>(NodePtr);
-  }
-
-  T *operator->() const {
-    return static_cast<T*>(NodePtr);
-  }
-
-  inline FoldingSetIterator &operator++() {          // Preincrement
-    advance();
-    return *this;
-  }
-  FoldingSetIterator operator++(int) {        // Postincrement
-    FoldingSetIterator tmp = *this; ++*this; return tmp;
-  }
-};
-
-//===----------------------------------------------------------------------===//
-/// FoldingSetBucketIteratorImpl - This is the common bucket iterator support
-/// shared by all folding sets, which knows how to walk a particular bucket
-/// of a folding set hash table.
-
-class FoldingSetBucketIteratorImpl {
-protected:
-  void *Ptr;
-
-  explicit FoldingSetBucketIteratorImpl(void **Bucket);
-
-  FoldingSetBucketIteratorImpl(void **Bucket, bool)
-    : Ptr(Bucket) {}
-
-  void advance() {
-    void *Probe = static_cast<FoldingSetNode*>(Ptr)->getNextInBucket();
-    uintptr_t x = reinterpret_cast<uintptr_t>(Probe) & ~0x1;
-    Ptr = reinterpret_cast<void*>(x);
-  }
-
-public:
-  bool operator==(const FoldingSetBucketIteratorImpl &RHS) const {
-    return Ptr == RHS.Ptr;
-  }
-  bool operator!=(const FoldingSetBucketIteratorImpl &RHS) const {
-    return Ptr != RHS.Ptr;
-  }
-};
-
-template <class T>
-class FoldingSetBucketIterator : public FoldingSetBucketIteratorImpl {
-public:
-  explicit FoldingSetBucketIterator(void **Bucket) :
-    FoldingSetBucketIteratorImpl(Bucket) {}
-
-  FoldingSetBucketIterator(void **Bucket, bool) :
-    FoldingSetBucketIteratorImpl(Bucket, true) {}
-
-  T &operator*() const { return *static_cast<T*>(Ptr); }
-  T *operator->() const { return static_cast<T*>(Ptr); }
-
-  inline FoldingSetBucketIterator &operator++() { // Preincrement
-    advance();
-    return *this;
-  }
-  FoldingSetBucketIterator operator++(int) {      // Postincrement
-    FoldingSetBucketIterator tmp = *this; ++*this; return tmp;
-  }
-};
-
-//===----------------------------------------------------------------------===//
-/// FoldingSetNodeWrapper - This template class is used to "wrap" arbitrary
-/// types in an enclosing object so that they can be inserted into FoldingSets.
-template <typename T>
-class FoldingSetNodeWrapper : public FoldingSetNode {
-  T data;
-
-public:
-  template <typename... Ts>
-  explicit FoldingSetNodeWrapper(Ts &&... Args)
-      : data(std::forward<Ts>(Args)...) {}
-
-  void Profile(FoldingSetNodeID &ID) { FoldingSetTrait<T>::Profile(data, ID); }
-
-  T &getValue() { return data; }
-  const T &getValue() const { return data; }
-
-  operator T&() { return data; }
-  operator const T&() const { return data; }
-};
-
-//===----------------------------------------------------------------------===//
-/// FastFoldingSetNode - This is a subclass of FoldingSetNode which stores
-/// a FoldingSetNodeID value rather than requiring the node to recompute it
-/// each time it is needed. This trades space for speed (which can be
-/// significant if the ID is long), and it also permits nodes to drop
-/// information that would otherwise only be required for recomputing an ID.
-class FastFoldingSetNode : public FoldingSetNode {
-  FoldingSetNodeID FastID;
-
-protected:
-  explicit FastFoldingSetNode(const FoldingSetNodeID &ID) : FastID(ID) {}
-
-public:
-  void Profile(FoldingSetNodeID &ID) const { ID.AddNodeID(FastID); }
-};
-
-//===----------------------------------------------------------------------===//
-// Partial specializations of FoldingSetTrait.
-
-template<typename T> struct FoldingSetTrait<T*> {
-  static inline void Profile(T *X, FoldingSetNodeID &ID) {
-    ID.AddPointer(X);
-  }
-};
-template <typename T1, typename T2>
-struct FoldingSetTrait<std::pair<T1, T2>> {
-  static inline void Profile(const std::pair<T1, T2> &P,
-                             FoldingSetNodeID &ID) {
-    ID.Add(P.first);
-    ID.Add(P.second);
-  }
-};
-
-} // end namespace llvm
-
-#endif // LLVM_ADT_FOLDINGSET_H
diff --git a/third_party/llvm-subzero/include/llvm/IR/Attributes.h b/third_party/llvm-subzero/include/llvm/IR/Attributes.h
index 1578385..cbcefd8 100644
--- a/third_party/llvm-subzero/include/llvm/IR/Attributes.h
+++ b/third_party/llvm-subzero/include/llvm/IR/Attributes.h
@@ -16,12 +16,11 @@
 #ifndef LLVM_IR_ATTRIBUTES_H
 #define LLVM_IR_ATTRIBUTES_H
 
+#include "llvm-c/Types.h"
 #include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/FoldingSet.h"
 #include "llvm/ADT/Optional.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/PointerLikeTypeTraits.h"
-#include "llvm-c/Types.h"
 #include <bitset>
 #include <cassert>
 #include <map>
@@ -167,10 +166,6 @@
   /// \brief Less-than operator. Useful for sorting the attributes list.
   bool operator<(Attribute A) const;
 
-  void Profile(FoldingSetNodeID &ID) const {
-    ID.AddPointer(pImpl);
-  }
-
   /// \brief Return a raw pointer that uniquely identifies this attribute.
   void *getRawPointer() const {
     return pImpl;
diff --git a/third_party/llvm-subzero/include/llvm/Support/CommandLine.h b/third_party/llvm-subzero/include/llvm/Support/CommandLine.h
index 204672f..37c2856 100644
--- a/third_party/llvm-subzero/include/llvm/Support/CommandLine.h
+++ b/third_party/llvm-subzero/include/llvm/Support/CommandLine.h
@@ -21,13 +21,13 @@
 #define LLVM_SUPPORT_COMMANDLINE_H
 
 #include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/iterator_range.h"
+#include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/Twine.h"
+#include "llvm/ADT/iterator_range.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/ManagedStatic.h"
 #include <cassert>
diff --git a/third_party/llvm-subzero/lib/Support/APInt.cpp b/third_party/llvm-subzero/lib/Support/APInt.cpp
index 0c0b498..d7f56f5 100644
--- a/third_party/llvm-subzero/lib/Support/APInt.cpp
+++ b/third_party/llvm-subzero/lib/Support/APInt.cpp
@@ -14,7 +14,6 @@
 
 #include "llvm/ADT/APInt.h"
 #include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/FoldingSet.h"
 #include "llvm/ADT/Hashing.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/StringRef.h"
@@ -163,20 +162,6 @@
   return clearUnusedBits();
 }
 
-/// This method 'profiles' an APInt for use with FoldingSet.
-void APInt::Profile(FoldingSetNodeID& ID) const {
-  ID.AddInteger(BitWidth);
-
-  if (isSingleWord()) {
-    ID.AddInteger(VAL);
-    return;
-  }
-
-  unsigned NumWords = getNumWords();
-  for (unsigned i = 0; i < NumWords; ++i)
-    ID.AddInteger(pVal[i]);
-}
-
 /// This function adds a single "digit" integer, y, to the multiple
 /// "digit" integer array,  x[]. x[] is modified to reflect the addition and
 /// 1 is returned if there is a carry out, otherwise 0 is returned.
diff --git a/third_party/llvm-subzero/lib/Support/FoldingSet.cpp b/third_party/llvm-subzero/lib/Support/FoldingSet.cpp
deleted file mode 100644
index c9bca7f..0000000
--- a/third_party/llvm-subzero/lib/Support/FoldingSet.cpp
+++ /dev/null
@@ -1,462 +0,0 @@
-//===-- Support/FoldingSet.cpp - Uniquing Hash Set --------------*- C++ -*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements a hash set that can be used to remove duplication of
-// nodes in a graph.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/ADT/FoldingSet.h"
-#include "llvm/ADT/Hashing.h"
-#include "llvm/Support/Allocator.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/Host.h"
-#include "llvm/Support/MathExtras.h"
-#include <cassert>
-#include <cstring>
-using namespace llvm;
-
-//===----------------------------------------------------------------------===//
-// FoldingSetNodeIDRef Implementation
-
-/// ComputeHash - Compute a strong hash value for this FoldingSetNodeIDRef,
-/// used to lookup the node in the FoldingSetImpl.
-unsigned FoldingSetNodeIDRef::ComputeHash() const {
-  return static_cast<unsigned>(hash_combine_range(Data, Data+Size));
-}
-
-bool FoldingSetNodeIDRef::operator==(FoldingSetNodeIDRef RHS) const {
-  if (Size != RHS.Size) return false;
-  return memcmp(Data, RHS.Data, Size*sizeof(*Data)) == 0;
-}
-
-/// Used to compare the "ordering" of two nodes as defined by the
-/// profiled bits and their ordering defined by memcmp().
-bool FoldingSetNodeIDRef::operator<(FoldingSetNodeIDRef RHS) const {
-  if (Size != RHS.Size)
-    return Size < RHS.Size;
-  return memcmp(Data, RHS.Data, Size*sizeof(*Data)) < 0;
-}
-
-//===----------------------------------------------------------------------===//
-// FoldingSetNodeID Implementation
-
-/// Add* - Add various data types to Bit data.
-///
-void FoldingSetNodeID::AddPointer(const void *Ptr) {
-  // Note: this adds pointers to the hash using sizes and endianness that
-  // depend on the host. It doesn't matter, however, because hashing on
-  // pointer values is inherently unstable. Nothing should depend on the
-  // ordering of nodes in the folding set.
-  static_assert(sizeof(uintptr_t) <= sizeof(unsigned long long),
-                "unexpected pointer size");
-  AddInteger(reinterpret_cast<uintptr_t>(Ptr));
-}
-void FoldingSetNodeID::AddInteger(signed I) {
-  Bits.push_back(I);
-}
-void FoldingSetNodeID::AddInteger(unsigned I) {
-  Bits.push_back(I);
-}
-void FoldingSetNodeID::AddInteger(long I) {
-  AddInteger((unsigned long)I);
-}
-void FoldingSetNodeID::AddInteger(unsigned long I) {
-  if (sizeof(long) == sizeof(int))
-    AddInteger(unsigned(I));
-  else if (sizeof(long) == sizeof(long long)) {
-    AddInteger((unsigned long long)I);
-  } else {
-    llvm_unreachable("unexpected sizeof(long)");
-  }
-}
-void FoldingSetNodeID::AddInteger(long long I) {
-  AddInteger((unsigned long long)I);
-}
-void FoldingSetNodeID::AddInteger(unsigned long long I) {
-  AddInteger(unsigned(I));
-  AddInteger(unsigned(I >> 32));
-}
-
-void FoldingSetNodeID::AddString(StringRef String) {
-  unsigned Size =  String.size();
-  Bits.push_back(Size);
-  if (!Size) return;
-
-  unsigned Units = Size / 4;
-  unsigned Pos = 0;
-  const unsigned *Base = (const unsigned*) String.data();
-  
-  // If the string is aligned do a bulk transfer.
-  if (!((intptr_t)Base & 3)) {
-    Bits.append(Base, Base + Units);
-    Pos = (Units + 1) * 4;
-  } else {
-    // Otherwise do it the hard way.
-    // To be compatible with above bulk transfer, we need to take endianness
-    // into account.
-    static_assert(sys::IsBigEndianHost || sys::IsLittleEndianHost,
-                  "Unexpected host endianness");
-    if (sys::IsBigEndianHost) {
-      for (Pos += 4; Pos <= Size; Pos += 4) {
-        unsigned V = ((unsigned char)String[Pos - 4] << 24) |
-                     ((unsigned char)String[Pos - 3] << 16) |
-                     ((unsigned char)String[Pos - 2] << 8) |
-                      (unsigned char)String[Pos - 1];
-        Bits.push_back(V);
-      }
-    } else {  // Little-endian host
-      for (Pos += 4; Pos <= Size; Pos += 4) {
-        unsigned V = ((unsigned char)String[Pos - 1] << 24) |
-                     ((unsigned char)String[Pos - 2] << 16) |
-                     ((unsigned char)String[Pos - 3] << 8) |
-                      (unsigned char)String[Pos - 4];
-        Bits.push_back(V);
-      }
-    }
-  }
-  
-  // With the leftover bits.
-  unsigned V = 0;
-  // Pos will have overshot size by 4 - #bytes left over.
-  // No need to take endianness into account here - this is always executed.
-  switch (Pos - Size) {
-  case 1: V = (V << 8) | (unsigned char)String[Size - 3]; LLVM_FALLTHROUGH;
-  case 2: V = (V << 8) | (unsigned char)String[Size - 2]; LLVM_FALLTHROUGH;
-  case 3: V = (V << 8) | (unsigned char)String[Size - 1]; break;
-  default: return; // Nothing left.
-  }
-
-  Bits.push_back(V);
-}
-
-// AddNodeID - Adds the Bit data of another ID to *this.
-void FoldingSetNodeID::AddNodeID(const FoldingSetNodeID &ID) {
-  Bits.append(ID.Bits.begin(), ID.Bits.end());
-}
-
-/// ComputeHash - Compute a strong hash value for this FoldingSetNodeID, used to 
-/// lookup the node in the FoldingSetImpl.
-unsigned FoldingSetNodeID::ComputeHash() const {
-  return FoldingSetNodeIDRef(Bits.data(), Bits.size()).ComputeHash();
-}
-
-/// operator== - Used to compare two nodes to each other.
-///
-bool FoldingSetNodeID::operator==(const FoldingSetNodeID &RHS) const {
-  return *this == FoldingSetNodeIDRef(RHS.Bits.data(), RHS.Bits.size());
-}
-
-/// operator== - Used to compare two nodes to each other.
-///
-bool FoldingSetNodeID::operator==(FoldingSetNodeIDRef RHS) const {
-  return FoldingSetNodeIDRef(Bits.data(), Bits.size()) == RHS;
-}
-
-/// Used to compare the "ordering" of two nodes as defined by the
-/// profiled bits and their ordering defined by memcmp().
-bool FoldingSetNodeID::operator<(const FoldingSetNodeID &RHS) const {
-  return *this < FoldingSetNodeIDRef(RHS.Bits.data(), RHS.Bits.size());
-}
-
-bool FoldingSetNodeID::operator<(FoldingSetNodeIDRef RHS) const {
-  return FoldingSetNodeIDRef(Bits.data(), Bits.size()) < RHS;
-}
-
-/// Intern - Copy this node's data to a memory region allocated from the
-/// given allocator and return a FoldingSetNodeIDRef describing the
-/// interned data.
-FoldingSetNodeIDRef
-FoldingSetNodeID::Intern(BumpPtrAllocator &Allocator) const {
-  unsigned *New = Allocator.Allocate<unsigned>(Bits.size());
-  std::uninitialized_copy(Bits.begin(), Bits.end(), New);
-  return FoldingSetNodeIDRef(New, Bits.size());
-}
-
-//===----------------------------------------------------------------------===//
-/// Helper functions for FoldingSetImpl.
-
-/// GetNextPtr - In order to save space, each bucket is a
-/// singly-linked-list. In order to make deletion more efficient, we make
-/// the list circular, so we can delete a node without computing its hash.
-/// The problem with this is that the start of the hash buckets are not
-/// Nodes.  If NextInBucketPtr is a bucket pointer, this method returns null:
-/// use GetBucketPtr when this happens.
-static FoldingSetImpl::Node *GetNextPtr(void *NextInBucketPtr) {
-  // The low bit is set if this is the pointer back to the bucket.
-  if (reinterpret_cast<intptr_t>(NextInBucketPtr) & 1)
-    return nullptr;
-  
-  return static_cast<FoldingSetImpl::Node*>(NextInBucketPtr);
-}
-
-
-/// testing.
-static void **GetBucketPtr(void *NextInBucketPtr) {
-  intptr_t Ptr = reinterpret_cast<intptr_t>(NextInBucketPtr);
-  assert((Ptr & 1) && "Not a bucket pointer");
-  return reinterpret_cast<void**>(Ptr & ~intptr_t(1));
-}
-
-/// GetBucketFor - Hash the specified node ID and return the hash bucket for
-/// the specified ID.
-static void **GetBucketFor(unsigned Hash, void **Buckets, unsigned NumBuckets) {
-  // NumBuckets is always a power of 2.
-  unsigned BucketNum = Hash & (NumBuckets-1);
-  return Buckets + BucketNum;
-}
-
-/// AllocateBuckets - Allocated initialized bucket memory.
-static void **AllocateBuckets(unsigned NumBuckets) {
-  void **Buckets = static_cast<void**>(calloc(NumBuckets+1, sizeof(void*)));
-  // Set the very last bucket to be a non-null "pointer".
-  Buckets[NumBuckets] = reinterpret_cast<void*>(-1);
-  return Buckets;
-}
-
-//===----------------------------------------------------------------------===//
-// FoldingSetImpl Implementation
-
-void FoldingSetImpl::anchor() {}
-
-FoldingSetImpl::FoldingSetImpl(unsigned Log2InitSize) {
-  assert(5 < Log2InitSize && Log2InitSize < 32 &&
-         "Initial hash table size out of range");
-  NumBuckets = 1 << Log2InitSize;
-  Buckets = AllocateBuckets(NumBuckets);
-  NumNodes = 0;
-}
-
-FoldingSetImpl::FoldingSetImpl(FoldingSetImpl &&Arg)
-    : Buckets(Arg.Buckets), NumBuckets(Arg.NumBuckets), NumNodes(Arg.NumNodes) {
-  Arg.Buckets = nullptr;
-  Arg.NumBuckets = 0;
-  Arg.NumNodes = 0;
-}
-
-FoldingSetImpl &FoldingSetImpl::operator=(FoldingSetImpl &&RHS) {
-  free(Buckets); // This may be null if the set is in a moved-from state.
-  Buckets = RHS.Buckets;
-  NumBuckets = RHS.NumBuckets;
-  NumNodes = RHS.NumNodes;
-  RHS.Buckets = nullptr;
-  RHS.NumBuckets = 0;
-  RHS.NumNodes = 0;
-  return *this;
-}
-
-FoldingSetImpl::~FoldingSetImpl() {
-  free(Buckets);
-}
-
-void FoldingSetImpl::clear() {
-  // Set all but the last bucket to null pointers.
-  memset(Buckets, 0, NumBuckets*sizeof(void*));
-
-  // Set the very last bucket to be a non-null "pointer".
-  Buckets[NumBuckets] = reinterpret_cast<void*>(-1);
-
-  // Reset the node count to zero.
-  NumNodes = 0;
-}
-
-void FoldingSetImpl::GrowBucketCount(unsigned NewBucketCount) {
-  assert((NewBucketCount > NumBuckets) && "Can't shrink a folding set with GrowBucketCount");
-  assert(isPowerOf2_32(NewBucketCount) && "Bad bucket count!");
-  void **OldBuckets = Buckets;
-  unsigned OldNumBuckets = NumBuckets;
-  NumBuckets = NewBucketCount;
-  
-  // Clear out new buckets.
-  Buckets = AllocateBuckets(NumBuckets);
-  NumNodes = 0;
-
-  // Walk the old buckets, rehashing nodes into their new place.
-  FoldingSetNodeID TempID;
-  for (unsigned i = 0; i != OldNumBuckets; ++i) {
-    void *Probe = OldBuckets[i];
-    if (!Probe) continue;
-    while (Node *NodeInBucket = GetNextPtr(Probe)) {
-      // Figure out the next link, remove NodeInBucket from the old link.
-      Probe = NodeInBucket->getNextInBucket();
-      NodeInBucket->SetNextInBucket(nullptr);
-
-      // Insert the node into the new bucket, after recomputing the hash.
-      InsertNode(NodeInBucket,
-                 GetBucketFor(ComputeNodeHash(NodeInBucket, TempID),
-                              Buckets, NumBuckets));
-      TempID.clear();
-    }
-  }
-  
-  free(OldBuckets);
-}
-
-/// GrowHashTable - Double the size of the hash table and rehash everything.
-///
-void FoldingSetImpl::GrowHashTable() {
-  GrowBucketCount(NumBuckets * 2);
-}
-
-void FoldingSetImpl::reserve(unsigned EltCount) {
-  // This will give us somewhere between EltCount / 2 and
-  // EltCount buckets.  This puts us in the load factor
-  // range of 1.0 - 2.0.
-  if(EltCount < capacity())
-    return;
-  GrowBucketCount(PowerOf2Floor(EltCount));
-}
-
-/// FindNodeOrInsertPos - Look up the node specified by ID.  If it exists,
-/// return it.  If not, return the insertion token that will make insertion
-/// faster.
-FoldingSetImpl::Node
-*FoldingSetImpl::FindNodeOrInsertPos(const FoldingSetNodeID &ID,
-                                     void *&InsertPos) {
-  unsigned IDHash = ID.ComputeHash();
-  void **Bucket = GetBucketFor(IDHash, Buckets, NumBuckets);
-  void *Probe = *Bucket;
-  
-  InsertPos = nullptr;
-  
-  FoldingSetNodeID TempID;
-  while (Node *NodeInBucket = GetNextPtr(Probe)) {
-    if (NodeEquals(NodeInBucket, ID, IDHash, TempID))
-      return NodeInBucket;
-    TempID.clear();
-
-    Probe = NodeInBucket->getNextInBucket();
-  }
-  
-  // Didn't find the node, return null with the bucket as the InsertPos.
-  InsertPos = Bucket;
-  return nullptr;
-}
-
-/// InsertNode - Insert the specified node into the folding set, knowing that it
-/// is not already in the map.  InsertPos must be obtained from 
-/// FindNodeOrInsertPos.
-void FoldingSetImpl::InsertNode(Node *N, void *InsertPos) {
-  assert(!N->getNextInBucket());
-  // Do we need to grow the hashtable?
-  if (NumNodes+1 > capacity()) {
-    GrowHashTable();
-    FoldingSetNodeID TempID;
-    InsertPos = GetBucketFor(ComputeNodeHash(N, TempID), Buckets, NumBuckets);
-  }
-
-  ++NumNodes;
-  
-  /// The insert position is actually a bucket pointer.
-  void **Bucket = static_cast<void**>(InsertPos);
-  
-  void *Next = *Bucket;
-  
-  // If this is the first insertion into this bucket, its next pointer will be
-  // null.  Pretend as if it pointed to itself, setting the low bit to indicate
-  // that it is a pointer to the bucket.
-  if (!Next)
-    Next = reinterpret_cast<void*>(reinterpret_cast<intptr_t>(Bucket)|1);
-
-  // Set the node's next pointer, and make the bucket point to the node.
-  N->SetNextInBucket(Next);
-  *Bucket = N;
-}
-
-/// RemoveNode - Remove a node from the folding set, returning true if one was
-/// removed or false if the node was not in the folding set.
-bool FoldingSetImpl::RemoveNode(Node *N) {
-  // Because each bucket is a circular list, we don't need to compute N's hash
-  // to remove it.
-  void *Ptr = N->getNextInBucket();
-  if (!Ptr) return false;  // Not in folding set.
-
-  --NumNodes;
-  N->SetNextInBucket(nullptr);
-
-  // Remember what N originally pointed to, either a bucket or another node.
-  void *NodeNextPtr = Ptr;
-  
-  // Chase around the list until we find the node (or bucket) which points to N.
-  while (true) {
-    if (Node *NodeInBucket = GetNextPtr(Ptr)) {
-      // Advance pointer.
-      Ptr = NodeInBucket->getNextInBucket();
-      
-      // We found a node that points to N, change it to point to N's next node,
-      // removing N from the list.
-      if (Ptr == N) {
-        NodeInBucket->SetNextInBucket(NodeNextPtr);
-        return true;
-      }
-    } else {
-      void **Bucket = GetBucketPtr(Ptr);
-      Ptr = *Bucket;
-      
-      // If we found that the bucket points to N, update the bucket to point to
-      // whatever is next.
-      if (Ptr == N) {
-        *Bucket = NodeNextPtr;
-        return true;
-      }
-    }
-  }
-}
-
-/// GetOrInsertNode - If there is an existing simple Node exactly
-/// equal to the specified node, return it.  Otherwise, insert 'N' and it
-/// instead.
-FoldingSetImpl::Node *FoldingSetImpl::GetOrInsertNode(FoldingSetImpl::Node *N) {
-  FoldingSetNodeID ID;
-  GetNodeProfile(N, ID);
-  void *IP;
-  if (Node *E = FindNodeOrInsertPos(ID, IP))
-    return E;
-  InsertNode(N, IP);
-  return N;
-}
-
-//===----------------------------------------------------------------------===//
-// FoldingSetIteratorImpl Implementation
-
-FoldingSetIteratorImpl::FoldingSetIteratorImpl(void **Bucket) {
-  // Skip to the first non-null non-self-cycle bucket.
-  while (*Bucket != reinterpret_cast<void*>(-1) &&
-         (!*Bucket || !GetNextPtr(*Bucket)))
-    ++Bucket;
-  
-  NodePtr = static_cast<FoldingSetNode*>(*Bucket);
-}
-
-void FoldingSetIteratorImpl::advance() {
-  // If there is another link within this bucket, go to it.
-  void *Probe = NodePtr->getNextInBucket();
-
-  if (FoldingSetNode *NextNodeInBucket = GetNextPtr(Probe))
-    NodePtr = NextNodeInBucket;
-  else {
-    // Otherwise, this is the last link in this bucket.  
-    void **Bucket = GetBucketPtr(Probe);
-
-    // Skip to the next non-null non-self-cycle bucket.
-    do {
-      ++Bucket;
-    } while (*Bucket != reinterpret_cast<void*>(-1) &&
-             (!*Bucket || !GetNextPtr(*Bucket)));
-    
-    NodePtr = static_cast<FoldingSetNode*>(*Bucket);
-  }
-}
-
-//===----------------------------------------------------------------------===//
-// FoldingSetBucketIteratorImpl Implementation
-
-FoldingSetBucketIteratorImpl::FoldingSetBucketIteratorImpl(void **Bucket) {
-  Ptr = (!*Bucket || !GetNextPtr(*Bucket)) ? (void*) Bucket : *Bucket;
-}