1//===- PriorityWorklist.h - Worklist with insertion priority ----*- C++ -*-===// 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 7//===----------------------------------------------------------------------===// 11/// This file provides a priority worklist. See the class comments for details. 13//===----------------------------------------------------------------------===// 15#ifndef LLVM_ADT_PRIORITYWORKLIST_H 16#define LLVM_ADT_PRIORITYWORKLIST_H 30/// A FILO worklist that prioritizes on re-insertion without duplication. 32/// This is very similar to a \c SetVector with the primary difference that 33/// while re-insertion does not create a duplicate, it does adjust the 34/// visitation order to respect the last insertion point. This can be useful 35/// when the visit order needs to be prioritized based on insertion point 36/// without actually having duplicate visits. 38/// Note that this doesn't prevent re-insertion of elements which have been 39/// visited -- if you need to break cycles, a set will still be necessary. 41/// The type \c T must be default constructable to a null value that will be 42/// ignored. It is an error to insert such a value, and popping elements will 43/// never produce such a value. It is expected to be used with common nullable 44/// types like pointers or optionals. 46/// Internally this uses a vector to store the worklist and a map to identify 47/// existing elements in the worklist. Both of these may be customized, but the 48/// map must support the basic DenseMap API for mapping from a T to an integer 49/// index into the vector. 51/// A partial specialization is provided to automatically select a SmallVector 52/// and a SmallDenseMap if custom data structures are not provided. 53template <
typename T,
typename VectorT = std::vector<T>,
54typename MapT = DenseMap<T, ptrdiff_t>>
63 /// Construct an empty PriorityWorklist 66 /// Determine if the PriorityWorklist is empty or not. 71 /// Returns the number of elements in the worklist. 76 /// Count the number of elements of a given key in the PriorityWorklist. 77 /// \returns 0 if the element is not in the PriorityWorklist, 1 if it is. 82 /// Return the last element of the PriorityWorklist. 84assert(!
empty() &&
"Cannot call back() on empty PriorityWorklist!");
88 /// Insert a new element into the PriorityWorklist. 89 /// \returns true if the element was inserted into the PriorityWorklist. 91assert(
X !=
T() &&
"Cannot insert a null (default constructed) value!");
92auto InsertResult = M.insert({
X, V.size()});
93if (InsertResult.second) {
94// Fresh value, just append it to the vector. 99auto &
Index = InsertResult.first->second;
100assert(V[
Index] ==
X &&
"Value not actually at index in map!");
102// If the element isn't at the back, null it out and append a fresh one. 110 /// Insert a sequence of new elements into the PriorityWorklist. 111template <
typename SequenceT>
112 std::enable_if_t<!std::is_convertible<SequenceT, T>::value>
114if (std::begin(Input) == std::end(Input))
115// Nothing to do for an empty input sequence. 118// First pull the input sequence into the vector as a bulk append 121 V.insert(V.end(), std::begin(Input), std::end(Input));
122// Now walk backwards fixing up the index map and deleting any duplicates. 123for (
ptrdiff_t i = V.size() - 1; i >= StartIndex; --i) {
124auto InsertResult = M.insert({V[i], i});
125if (InsertResult.second)
128// If the existing index is before this insert's start, nuke that one and 131if (
Index < StartIndex) {
137// Otherwise the existing one comes first so just clear out the value in 143 /// Remove the last element of the PriorityWorklist. 145assert(!
empty() &&
"Cannot remove an element when empty!");
146assert(
back() !=
T() &&
"Cannot have a null element at the back!");
150 }
while (!V.empty() && V.back() ==
T());
159 /// Erase an item from the worklist. 161 /// Note that this is constant time due to the nature of the worklist implementation. 167assert(V[
I->second] ==
X &&
"Value not actually at index in map!");
171 }
while (!V.empty() && V.back() ==
T());
179 /// Erase items from the set vector based on a predicate function. 181 /// This is intended to be equivalent to the following code, if we could 185 /// V.erase(remove_if(V, P), V.end()); 188 /// However, PriorityWorklist doesn't expose non-const iterators, making any 189 /// algorithm like remove_if impossible to use. 191 /// \returns true if any element is removed. 192template <
typename UnaryPredicate>
194typename VectorT::iterator
E =
195remove_if(V, TestAndEraseFromMap<UnaryPredicate>(
P, M));
198for (
autoI = V.begin();
I !=
E; ++
I)
200 M[*
I] =
I - V.begin();
205 /// Reverse the items in the PriorityWorklist. 207 /// This does an in-place reversal. Other kinds of reverse aren't easy to 208 /// support in the face of the worklist semantics. 210 /// Completely clear the PriorityWorklist 217 /// A wrapper predicate designed for use with std::remove_if. 219 /// This predicate wraps a predicate suitable for use with std::remove_if to 220 /// call M.erase(x) on each element which is slated for removal. This just 221 /// allows the predicate to be move only which we can't do with lambdas 223template <
typename UnaryPredicateT>
224classTestAndEraseFromMap {
229 TestAndEraseFromMap(UnaryPredicateT P,
MapT &M)
232bool operator()(
constT &Arg) {
234// Skip null values in the PriorityWorklist. 245 /// The map from value to index in the vector. 248 /// The vector of elements in insertion order. 252/// A version of \c PriorityWorklist that selects small size optimized data 253/// structures for the vector and map. 254template <
typename T,
unsigned N>
257 SmallDenseMap<T, ptrdiff_t>> {
262}
// end namespace llvm 264#endif// LLVM_ADT_PRIORITYWORKLIST_H static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file defines the DenseMap class.
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file contains some templates that are useful if you are working with the STL at all.
This file defines the SmallVector class.
A FILO worklist that prioritizes on re-insertion without duplication.
const T & back() const
Return the last element of the PriorityWorklist.
PriorityWorklist()=default
Construct an empty PriorityWorklist.
size_type count(const key_type &key) const
Count the number of elements of a given key in the PriorityWorklist.
void clear()
Reverse the items in the PriorityWorklist.
typename MapT::size_type size_type
size_type size() const
Returns the number of elements in the worklist.
bool erase_if(UnaryPredicate P)
Erase items from the set vector based on a predicate function.
bool erase(const T &X)
Erase an item from the worklist.
void pop_back()
Remove the last element of the PriorityWorklist.
bool empty() const
Determine if the PriorityWorklist is empty or not.
bool insert(const T &X)
Insert a new element into the PriorityWorklist.
std::enable_if_t<!std::is_convertible< SequenceT, T >::value > insert(SequenceT &&Input)
Insert a sequence of new elements into the PriorityWorklist.
A version of PriorityWorklist that selects small size optimized data structures for the vector and ma...
SmallPriorityWorklist()=default
This is an optimization pass for GlobalISel generic memory operations.
auto remove_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::remove_if which take ranges instead of having to pass begin/end explicitly.
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Implement std::hash so that hash_code can be used in STL containers.