| 1 | //===- llvm/ADT/SetVector.h - Set with insert order iteration ---*- C++ -*-===// | 
| 2 | // | 
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | 
| 4 | // See https://llvm.org/LICENSE.txt for license information. | 
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | 
| 6 | // | 
| 7 | //===----------------------------------------------------------------------===// | 
| 8 | /// | 
| 9 | /// \file | 
| 10 | /// This file implements a set that has insertion order iteration | 
| 11 | /// characteristics. This is useful for keeping a set of things that need to be | 
| 12 | /// visited later but in a deterministic order (insertion order). The interface | 
| 13 | /// is purposefully minimal. | 
| 14 | /// | 
| 15 | /// This file defines SetVector and SmallSetVector, which performs no | 
| 16 | /// allocations if the SetVector has less than a certain number of elements. | 
| 17 | /// | 
| 18 | //===----------------------------------------------------------------------===// | 
| 19 |  | 
| 20 | #ifndef LLVM_ADT_SETVECTOR_H | 
| 21 | #define LLVM_ADT_SETVECTOR_H | 
| 22 |  | 
| 23 | #include "llvm/ADT/ArrayRef.h" | 
| 24 | #include "llvm/ADT/DenseSet.h" | 
| 25 | #include "llvm/ADT/STLExtras.h" | 
| 26 | #include "llvm/Support/Compiler.h" | 
| 27 | #include <cassert> | 
| 28 | #include <iterator> | 
| 29 | #include <vector> | 
| 30 |  | 
| 31 | namespace llvm { | 
| 32 |  | 
| 33 | /// A vector that has set insertion semantics. | 
| 34 | /// | 
| 35 | /// This adapter class provides a way to keep a set of things that also has the | 
| 36 | /// property of a deterministic iteration order. The order of iteration is the | 
| 37 | /// order of insertion. | 
| 38 | /// | 
| 39 | /// The key and value types are derived from the Set and Vector types | 
| 40 | /// respectively. This allows the vector-type operations and set-type operations | 
| 41 | /// to have different types. In particular, this is useful when storing pointers | 
| 42 | /// as "Foo *" values but looking them up as "const Foo *" keys. | 
| 43 | /// | 
| 44 | /// No constraint is placed on the key and value types, although it is assumed | 
| 45 | /// that value_type can be converted into key_type for insertion. Users must be | 
| 46 | /// aware of any loss of information in this conversion. For example, setting | 
| 47 | /// value_type to float and key_type to int can produce very surprising results, | 
| 48 | /// but it is not explicitly disallowed. | 
| 49 | /// | 
| 50 | /// The parameter N specifies the "small" size of the container, which is the | 
| 51 | /// number of elements upto which a linear scan over the Vector will be used | 
| 52 | /// when searching for elements instead of checking Set, due to it being better | 
| 53 | /// for performance. A value of 0 means that this mode of operation is not used, | 
| 54 | /// and is the default value. | 
| 55 | template <typename T, typename Vector = std::vector<T>, | 
| 56 |           typename Set = DenseSet<T>, unsigned N = 0> | 
| 57 | class SetVector { | 
| 58 |   // Much like in SmallPtrSet, this value should not be too high to prevent | 
| 59 |   // excessively long linear scans from occuring. | 
| 60 |   static_assert(N <= 32, "Small size should be less than or equal to 32!" ); | 
| 61 |  | 
| 62 | public: | 
| 63 |   using value_type = typename Vector::value_type; | 
| 64 |   using key_type = typename Set::key_type; | 
| 65 |   using reference = value_type &; | 
| 66 |   using const_reference = const value_type &; | 
| 67 |   using set_type = Set; | 
| 68 |   using vector_type = Vector; | 
| 69 |   using iterator = typename vector_type::const_iterator; | 
| 70 |   using const_iterator = typename vector_type::const_iterator; | 
| 71 |   using reverse_iterator = typename vector_type::const_reverse_iterator; | 
| 72 |   using const_reverse_iterator = typename vector_type::const_reverse_iterator; | 
| 73 |   using size_type = typename vector_type::size_type; | 
| 74 |  | 
| 75 |   /// Construct an empty SetVector | 
| 76 |   SetVector() = default; | 
| 77 |  | 
| 78 |   /// Initialize a SetVector with a range of elements | 
| 79 |   template<typename It> | 
| 80 |   SetVector(It Start, It End) { | 
| 81 |     insert(Start, End); | 
| 82 |   } | 
| 83 |  | 
| 84 |   ArrayRef<value_type> getArrayRef() const { return vector_; } | 
| 85 |  | 
| 86 |   /// Clear the SetVector and return the underlying vector. | 
| 87 |   Vector takeVector() { | 
| 88 |     set_.clear(); | 
| 89 |     return std::move(vector_); | 
| 90 |   } | 
| 91 |  | 
| 92 |   /// Determine if the SetVector is empty or not. | 
| 93 |   bool empty() const { | 
| 94 |     return vector_.empty(); | 
| 95 |   } | 
| 96 |  | 
| 97 |   /// Determine the number of elements in the SetVector. | 
| 98 |   size_type size() const { | 
| 99 |     return vector_.size(); | 
| 100 |   } | 
| 101 |  | 
| 102 |   /// Get an iterator to the beginning of the SetVector. | 
| 103 |   iterator begin() { | 
| 104 |     return vector_.begin(); | 
| 105 |   } | 
| 106 |  | 
| 107 |   /// Get a const_iterator to the beginning of the SetVector. | 
| 108 |   const_iterator begin() const { | 
| 109 |     return vector_.begin(); | 
| 110 |   } | 
| 111 |  | 
| 112 |   /// Get an iterator to the end of the SetVector. | 
| 113 |   iterator end() { | 
| 114 |     return vector_.end(); | 
| 115 |   } | 
| 116 |  | 
| 117 |   /// Get a const_iterator to the end of the SetVector. | 
| 118 |   const_iterator end() const { | 
| 119 |     return vector_.end(); | 
| 120 |   } | 
| 121 |  | 
| 122 |   /// Get an reverse_iterator to the end of the SetVector. | 
| 123 |   reverse_iterator rbegin() { | 
| 124 |     return vector_.rbegin(); | 
| 125 |   } | 
| 126 |  | 
| 127 |   /// Get a const_reverse_iterator to the end of the SetVector. | 
| 128 |   const_reverse_iterator rbegin() const { | 
| 129 |     return vector_.rbegin(); | 
| 130 |   } | 
| 131 |  | 
| 132 |   /// Get a reverse_iterator to the beginning of the SetVector. | 
| 133 |   reverse_iterator rend() { | 
| 134 |     return vector_.rend(); | 
| 135 |   } | 
| 136 |  | 
| 137 |   /// Get a const_reverse_iterator to the beginning of the SetVector. | 
| 138 |   const_reverse_iterator rend() const { | 
| 139 |     return vector_.rend(); | 
| 140 |   } | 
| 141 |  | 
| 142 |   /// Return the first element of the SetVector. | 
| 143 |   const value_type &front() const { | 
| 144 |     assert(!empty() && "Cannot call front() on empty SetVector!" ); | 
| 145 |     return vector_.front(); | 
| 146 |   } | 
| 147 |  | 
| 148 |   /// Return the last element of the SetVector. | 
| 149 |   const value_type &back() const { | 
| 150 |     assert(!empty() && "Cannot call back() on empty SetVector!" ); | 
| 151 |     return vector_.back(); | 
| 152 |   } | 
| 153 |  | 
| 154 |   /// Index into the SetVector. | 
| 155 |   const_reference operator[](size_type n) const { | 
| 156 |     assert(n < vector_.size() && "SetVector access out of range!" ); | 
| 157 |     return vector_[n]; | 
| 158 |   } | 
| 159 |  | 
| 160 |   /// Insert a new element into the SetVector. | 
| 161 |   /// \returns true if the element was inserted into the SetVector. | 
| 162 |   bool insert(const value_type &X) { | 
| 163 |     if constexpr (canBeSmall()) | 
| 164 |       if (isSmall()) { | 
| 165 |         if (llvm::find(vector_, X) == vector_.end()) { | 
| 166 |           vector_.push_back(X); | 
| 167 |           if (vector_.size() > N) | 
| 168 |             makeBig(); | 
| 169 |           return true; | 
| 170 |         } | 
| 171 |         return false; | 
| 172 |       } | 
| 173 |  | 
| 174 |     bool result = set_.insert(X).second; | 
| 175 |     if (result) | 
| 176 |       vector_.push_back(X); | 
| 177 |     return result; | 
| 178 |   } | 
| 179 |  | 
| 180 |   /// Insert a range of elements into the SetVector. | 
| 181 |   template<typename It> | 
| 182 |   void insert(It Start, It End) { | 
| 183 |     for (; Start != End; ++Start) | 
| 184 |       insert(*Start); | 
| 185 |   } | 
| 186 |  | 
| 187 |   /// Remove an item from the set vector. | 
| 188 |   bool remove(const value_type& X) { | 
| 189 |     if constexpr (canBeSmall()) | 
| 190 |       if (isSmall()) { | 
| 191 |         typename vector_type::iterator I = find(vector_, X); | 
| 192 |         if (I != vector_.end()) { | 
| 193 |           vector_.erase(I); | 
| 194 |           return true; | 
| 195 |         } | 
| 196 |         return false; | 
| 197 |       } | 
| 198 |  | 
| 199 |     if (set_.erase(X)) { | 
| 200 |       typename vector_type::iterator I = find(vector_, X); | 
| 201 |       assert(I != vector_.end() && "Corrupted SetVector instances!" ); | 
| 202 |       vector_.erase(I); | 
| 203 |       return true; | 
| 204 |     } | 
| 205 |     return false; | 
| 206 |   } | 
| 207 |  | 
| 208 |   /// Erase a single element from the set vector. | 
| 209 |   /// \returns an iterator pointing to the next element that followed the | 
| 210 |   /// element erased. This is the end of the SetVector if the last element is | 
| 211 |   /// erased. | 
| 212 |   iterator erase(const_iterator I) { | 
| 213 |     if constexpr (canBeSmall()) | 
| 214 |       if (isSmall()) | 
| 215 |         return vector_.erase(I); | 
| 216 |  | 
| 217 |     const key_type &V = *I; | 
| 218 |     assert(set_.count(V) && "Corrupted SetVector instances!" ); | 
| 219 |     set_.erase(V); | 
| 220 |     return vector_.erase(I); | 
| 221 |   } | 
| 222 |  | 
| 223 |   /// Remove items from the set vector based on a predicate function. | 
| 224 |   /// | 
| 225 |   /// This is intended to be equivalent to the following code, if we could | 
| 226 |   /// write it: | 
| 227 |   /// | 
| 228 |   /// \code | 
| 229 |   ///   V.erase(remove_if(V, P), V.end()); | 
| 230 |   /// \endcode | 
| 231 |   /// | 
| 232 |   /// However, SetVector doesn't expose non-const iterators, making any | 
| 233 |   /// algorithm like remove_if impossible to use. | 
| 234 |   /// | 
| 235 |   /// \returns true if any element is removed. | 
| 236 |   template <typename UnaryPredicate> | 
| 237 |   bool remove_if(UnaryPredicate P) { | 
| 238 |     typename vector_type::iterator I = [this, P] { | 
| 239 |       if constexpr (canBeSmall()) | 
| 240 |         if (isSmall()) | 
| 241 |           return llvm::remove_if(vector_, P); | 
| 242 |  | 
| 243 |       return llvm::remove_if(vector_, | 
| 244 |                              TestAndEraseFromSet<UnaryPredicate>(P, set_)); | 
| 245 |     }(); | 
| 246 |  | 
| 247 |     if (I == vector_.end()) | 
| 248 |       return false; | 
| 249 |     vector_.erase(I, vector_.end()); | 
| 250 |     return true; | 
| 251 |   } | 
| 252 |  | 
| 253 |   /// Check if the SetVector contains the given key. | 
| 254 |   bool contains(const key_type &key) const { | 
| 255 |     if constexpr (canBeSmall()) | 
| 256 |       if (isSmall()) | 
| 257 |         return is_contained(vector_, key); | 
| 258 |  | 
| 259 |     return set_.find(key) != set_.end(); | 
| 260 |   } | 
| 261 |  | 
| 262 |   /// Count the number of elements of a given key in the SetVector. | 
| 263 |   /// \returns 0 if the element is not in the SetVector, 1 if it is. | 
| 264 |   size_type count(const key_type &key) const { | 
| 265 |     if constexpr (canBeSmall()) | 
| 266 |       if (isSmall()) | 
| 267 |         return is_contained(vector_, key); | 
| 268 |  | 
| 269 |     return set_.count(key); | 
| 270 |   } | 
| 271 |  | 
| 272 |   /// Completely clear the SetVector | 
| 273 |   void clear() { | 
| 274 |     set_.clear(); | 
| 275 |     vector_.clear(); | 
| 276 |   } | 
| 277 |  | 
| 278 |   /// Remove the last element of the SetVector. | 
| 279 |   void pop_back() { | 
| 280 |     assert(!empty() && "Cannot remove an element from an empty SetVector!" ); | 
| 281 |     set_.erase(back()); | 
| 282 |     vector_.pop_back(); | 
| 283 |   } | 
| 284 |  | 
| 285 |   [[nodiscard]] value_type pop_back_val() { | 
| 286 |     value_type Ret = back(); | 
| 287 |     pop_back(); | 
| 288 |     return Ret; | 
| 289 |   } | 
| 290 |  | 
| 291 |   bool operator==(const SetVector &that) const { | 
| 292 |     return vector_ == that.vector_; | 
| 293 |   } | 
| 294 |  | 
| 295 |   bool operator!=(const SetVector &that) const { | 
| 296 |     return vector_ != that.vector_; | 
| 297 |   } | 
| 298 |  | 
| 299 |   /// Compute This := This u S, return whether 'This' changed. | 
| 300 |   /// TODO: We should be able to use set_union from SetOperations.h, but | 
| 301 |   ///       SetVector interface is inconsistent with DenseSet. | 
| 302 |   template <class STy> | 
| 303 |   bool set_union(const STy &S) { | 
| 304 |     bool Changed = false; | 
| 305 |  | 
| 306 |     for (typename STy::const_iterator SI = S.begin(), SE = S.end(); SI != SE; | 
| 307 |          ++SI) | 
| 308 |       if (insert(*SI)) | 
| 309 |         Changed = true; | 
| 310 |  | 
| 311 |     return Changed; | 
| 312 |   } | 
| 313 |  | 
| 314 |   /// Compute This := This - B | 
| 315 |   /// TODO: We should be able to use set_subtract from SetOperations.h, but | 
| 316 |   ///       SetVector interface is inconsistent with DenseSet. | 
| 317 |   template <class STy> | 
| 318 |   void set_subtract(const STy &S) { | 
| 319 |     for (typename STy::const_iterator SI = S.begin(), SE = S.end(); SI != SE; | 
| 320 |          ++SI) | 
| 321 |       remove(X: *SI); | 
| 322 |   } | 
| 323 |  | 
| 324 |   void swap(SetVector<T, Vector, Set, N> &RHS) { | 
| 325 |     set_.swap(RHS.set_); | 
| 326 |     vector_.swap(RHS.vector_); | 
| 327 |   } | 
| 328 |  | 
| 329 | private: | 
| 330 |   /// A wrapper predicate designed for use with std::remove_if. | 
| 331 |   /// | 
| 332 |   /// This predicate wraps a predicate suitable for use with std::remove_if to | 
| 333 |   /// call set_.erase(x) on each element which is slated for removal. | 
| 334 |   template <typename UnaryPredicate> | 
| 335 |   class TestAndEraseFromSet { | 
| 336 |     UnaryPredicate P; | 
| 337 |     set_type &set_; | 
| 338 |  | 
| 339 |   public: | 
| 340 |     TestAndEraseFromSet(UnaryPredicate P, set_type &set_) | 
| 341 |         : P(std::move(P)), set_(set_) {} | 
| 342 |  | 
| 343 |     template <typename ArgumentT> | 
| 344 |     bool operator()(const ArgumentT &Arg) { | 
| 345 |       if (P(Arg)) { | 
| 346 |         set_.erase(Arg); | 
| 347 |         return true; | 
| 348 |       } | 
| 349 |       return false; | 
| 350 |     } | 
| 351 |   }; | 
| 352 |  | 
| 353 |   [[nodiscard]] static constexpr bool canBeSmall() { return N != 0; } | 
| 354 |  | 
| 355 |   [[nodiscard]] bool isSmall() const { return set_.empty(); } | 
| 356 |  | 
| 357 |   void makeBig() { | 
| 358 |     if constexpr (canBeSmall()) | 
| 359 |       for (const auto &entry : vector_) | 
| 360 |         set_.insert(entry); | 
| 361 |   } | 
| 362 |  | 
| 363 |   set_type set_;         ///< The set. | 
| 364 |   vector_type vector_;   ///< The vector. | 
| 365 | }; | 
| 366 |  | 
| 367 | /// A SetVector that performs no allocations if smaller than | 
| 368 | /// a certain size. | 
| 369 | template <typename T, unsigned N> | 
| 370 | class SmallSetVector : public SetVector<T, SmallVector<T, N>, DenseSet<T>, N> { | 
| 371 | public: | 
| 372 |   SmallSetVector() = default; | 
| 373 |  | 
| 374 |   /// Initialize a SmallSetVector with a range of elements | 
| 375 |   template<typename It> | 
| 376 |   SmallSetVector(It Start, It End) { | 
| 377 |     this->insert(Start, End); | 
| 378 |   } | 
| 379 | }; | 
| 380 |  | 
| 381 | } // end namespace llvm | 
| 382 |  | 
| 383 | namespace std { | 
| 384 |  | 
| 385 | /// Implement std::swap in terms of SetVector swap. | 
| 386 | template <typename T, typename V, typename S, unsigned N> | 
| 387 | inline void swap(llvm::SetVector<T, V, S, N> &LHS, | 
| 388 |                  llvm::SetVector<T, V, S, N> &RHS) { | 
| 389 |   LHS.swap(RHS); | 
| 390 | } | 
| 391 |  | 
| 392 | /// Implement std::swap in terms of SmallSetVector swap. | 
| 393 | template<typename T, unsigned N> | 
| 394 | inline void | 
| 395 | swap(llvm::SmallSetVector<T, N> &LHS, llvm::SmallSetVector<T, N> &RHS) { | 
| 396 |   LHS.swap(RHS); | 
| 397 | } | 
| 398 |  | 
| 399 | } // end namespace std | 
| 400 |  | 
| 401 | #endif // LLVM_ADT_SETVECTOR_H | 
| 402 |  |