LLVM 22.0.0git
TinyPtrVector.h
Go to the documentation of this file.
1//===- llvm/ADT/TinyPtrVector.h - 'Normally tiny' vectors -------*- 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#ifndef LLVM_ADT_TINYPTRVECTOR_H
10#define LLVM_ADT_TINYPTRVECTOR_H
11
12#include "llvm/ADT/ArrayRef.h"
15#include <cassert>
16#include <cstddef>
17#include <iterator>
18
19namespace llvm {
20
21/// TinyPtrVector - This class is specialized for cases where there are
22/// normally 0 or 1 element in a vector, but is general enough to go beyond that
23/// when required.
24///
25/// NOTE: This container doesn't allow you to store a null pointer into it.
26///
27template <typename EltTy>
29public:
31 using value_type = typename VecTy::value_type;
32 // EltTy must be the first pointer type so that is<EltTy> is true for the
33 // default-constructed PtrUnion. This allows an empty TinyPtrVector to
34 // naturally vend a begin/end iterator of type EltTy* without an additional
35 // check for the empty state.
37
38private:
39 PtrUnion Val;
40
41public:
42 TinyPtrVector() = default;
43
46 delete V;
47 }
48
49 TinyPtrVector(const TinyPtrVector &RHS) : Val(RHS.Val) {
51 Val = new VecTy(*V);
52 }
53
55 if (this == &RHS)
56 return *this;
57 if (RHS.empty()) {
58 this->clear();
59 return *this;
60 }
61
62 // Try to squeeze into the single slot. If it won't fit, allocate a copied
63 // vector.
64 if (isa<EltTy>(Val)) {
65 if (RHS.size() == 1)
66 Val = RHS.front();
67 else
68 Val = new VecTy(*cast<VecTy *>(RHS.Val));
69 return *this;
70 }
71
72 // If we have a full vector allocated, try to re-use it.
73 if (isa<EltTy>(RHS.Val)) {
74 cast<VecTy *>(Val)->clear();
75 cast<VecTy *>(Val)->push_back(RHS.front());
76 } else {
77 *cast<VecTy *>(Val) = *cast<VecTy *>(RHS.Val);
78 }
79 return *this;
80 }
81
83 RHS.Val = (EltTy)nullptr;
84 }
85
87 if (this == &RHS)
88 return *this;
89 if (RHS.empty()) {
90 this->clear();
91 return *this;
92 }
93
94 // If this vector has been allocated on the heap, re-use it if cheap. If it
95 // would require more copying, just delete it and we'll steal the other
96 // side.
97 if (VecTy *V = dyn_cast_if_present<VecTy *>(Val)) {
98 if (isa<EltTy>(RHS.Val)) {
99 V->clear();
100 V->push_back(RHS.front());
101 RHS.Val = EltTy();
102 return *this;
103 }
104 delete V;
105 }
106
107 Val = RHS.Val;
108 RHS.Val = EltTy();
109 return *this;
110 }
111
112 TinyPtrVector(std::initializer_list<EltTy> IL)
113 : Val(IL.size() == 0
114 ? PtrUnion()
115 : IL.size() == 1 ? PtrUnion(*IL.begin())
116 : PtrUnion(new VecTy(IL.begin(), IL.end()))) {}
117
118 /// Constructor from an ArrayRef.
119 ///
120 /// This also is a constructor for individual array elements due to the single
121 /// element constructor for ArrayRef.
123 : Val(Elts.empty()
124 ? PtrUnion()
125 : Elts.size() == 1
126 ? PtrUnion(Elts[0])
127 : PtrUnion(new VecTy(Elts.begin(), Elts.end()))) {}
128
129 TinyPtrVector(size_t Count, EltTy Value)
130 : Val(Count == 0 ? PtrUnion()
131 : Count == 1 ? PtrUnion(Value)
132 : PtrUnion(new VecTy(Count, Value))) {}
133
134 bool empty() const {
135 // This vector can be empty if it contains no element, or if it
136 // contains a pointer to an empty vector.
137 if (isa<EltTy>(Val))
138 return Val.isNull();
139 return cast<VecTy *>(Val)->empty();
140 }
141
142 unsigned size() const {
143 if (isa<EltTy>(Val))
144 return Val.isNull() ? 0 : 1;
145 return cast<VecTy *>(Val)->size();
146 }
147
148 using iterator = EltTy *;
149 using const_iterator = const EltTy *;
150 using reverse_iterator = std::reverse_iterator<iterator>;
151 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
152
154 if (isa<EltTy>(Val))
155 return Val.getAddrOfPtr1();
156
157 return cast<VecTy *>(Val)->begin();
158 }
159
161 if (isa<EltTy>(Val))
162 return begin() + (Val.isNull() ? 0 : 1);
163
164 return cast<VecTy *>(Val)->end();
165 }
166
168 return (const_iterator)const_cast<TinyPtrVector*>(this)->begin();
169 }
170
172 return (const_iterator)const_cast<TinyPtrVector*>(this)->end();
173 }
174
177
181
185
186 EltTy *data() { return begin(); }
187 const EltTy *data() const { return begin(); }
188
189 EltTy operator[](unsigned i) const {
190 assert(!Val.isNull() && "can't index into an empty vector");
191 if (isa<EltTy>(Val)) {
192 assert(i == 0 && "tinyvector index out of range");
193 return cast<EltTy>(Val);
194 }
195
196 assert(i < cast<VecTy *>(Val)->size() && "tinyvector index out of range");
197 return (*cast<VecTy *>(Val))[i];
198 }
199
200 EltTy front() const {
201 assert(!empty() && "vector empty");
202 if (isa<EltTy>(Val))
203 return cast<EltTy>(Val);
204 return cast<VecTy *>(Val)->front();
205 }
206
207 EltTy back() const {
208 assert(!empty() && "vector empty");
209 if (isa<EltTy>(Val))
210 return cast<EltTy>(Val);
211 return cast<VecTy *>(Val)->back();
212 }
213
214 void push_back(EltTy NewVal) {
215 // If we have nothing, add something.
216 if (Val.isNull()) {
217 Val = NewVal;
218 assert(!Val.isNull() && "Can't add a null value");
219 return;
220 }
221
222 // If we have a single value, convert to a vector.
223 if (isa<EltTy>(Val)) {
224 EltTy V = cast<EltTy>(Val);
225 Val = new VecTy({V, NewVal});
226 return;
227 }
228
229 // Add the new value, we know we have a vector.
230 cast<VecTy *>(Val)->push_back(NewVal);
231 }
232
233 void pop_back() {
234 // If we have a single value, convert to empty.
235 if (isa<EltTy>(Val))
236 Val = EltTy();
237 else
238 cast<VecTy *>(Val)->pop_back();
239 }
240
241 void clear() {
242 // If we have a single value, convert to empty.
243 if (isa<EltTy>(Val)) {
244 Val = EltTy();
245 } else {
246 // If we have a vector form, just clear it.
247 cast<VecTy *>(Val)->clear();
248 }
249 }
250
252 assert(I >= begin() && "Iterator to erase is out of bounds.");
253 assert(I < end() && "Erasing at past-the-end iterator.");
254
255 // If we have a single value, convert to empty.
256 if (isa<EltTy>(Val)) {
257 if (I == begin())
258 Val = EltTy();
259 } else {
260 // multiple items in a vector; just do the erase, there is no
261 // benefit to collapsing back to a pointer
262 return cast<VecTy *>(Val)->erase(I);
263 }
264 return end();
265 }
266
268 assert(S >= begin() && "Range to erase is out of bounds.");
269 assert(S <= E && "Trying to erase invalid range.");
270 assert(E <= end() && "Trying to erase past the end.");
271
272 if (isa<EltTy>(Val)) {
273 if (S == begin() && S != E)
274 Val = EltTy();
275 } else {
276 return cast<VecTy *>(Val)->erase(S, E);
277 }
278 return end();
279 }
280
281 iterator insert(iterator I, const EltTy &Elt) {
282 assert(I >= this->begin() && "Insertion iterator is out of bounds.");
283 assert(I <= this->end() && "Inserting past the end of the vector.");
284 if (I == end()) {
285 push_back(Elt);
286 return std::prev(end());
287 }
288 assert(!Val.isNull() && "Null value with non-end insert iterator.");
289 if (isa<EltTy>(Val)) {
290 EltTy V = cast<EltTy>(Val);
291 assert(I == begin());
292 Val = Elt;
293 push_back(V);
294 return begin();
295 }
296
297 return cast<VecTy *>(Val)->insert(I, Elt);
298 }
299
300 template<typename ItTy>
302 assert(I >= this->begin() && "Insertion iterator is out of bounds.");
303 assert(I <= this->end() && "Inserting past the end of the vector.");
304 if (From == To)
305 return I;
306
307 // If we have a single value, convert to a vector.
308 ptrdiff_t Offset = I - begin();
309 if (Val.isNull()) {
310 if (std::next(From) == To) {
311 Val = *From;
312 return begin();
313 }
314
315 Val = new VecTy();
316 } else if (isa<EltTy>(Val)) {
317 EltTy V = cast<EltTy>(Val);
318 Val = new VecTy();
319 cast<VecTy *>(Val)->push_back(V);
320 }
321 return cast<VecTy *>(Val)->insert(begin() + Offset, From, To);
322 }
323};
324
325} // end namespace llvm
326
327#endif // LLVM_ADT_TINYPTRVECTOR_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define I(x, y, z)
Definition MD5.cpp:57
This file defines the PointerUnion class, which is a discriminated union of pointer types.
This file defines the SmallVector class.
Value * RHS
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
A discriminated union of two or more pointer types, with the discriminator in the low bit of the poin...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
reverse_iterator rbegin()
const EltTy * const_iterator
TinyPtrVector(std::initializer_list< EltTy > IL)
void push_back(EltTy NewVal)
TinyPtrVector & operator=(TinyPtrVector &&RHS)
reverse_iterator rend()
TinyPtrVector()=default
std::reverse_iterator< const_iterator > const_reverse_iterator
const_reverse_iterator rbegin() const
TinyPtrVector(ArrayRef< EltTy > Elts)
Constructor from an ArrayRef.
std::reverse_iterator< iterator > reverse_iterator
EltTy front() const
const_iterator begin() const
iterator erase(iterator I)
TinyPtrVector & operator=(const TinyPtrVector &RHS)
TinyPtrVector(const TinyPtrVector &RHS)
const_reverse_iterator rend() const
const EltTy * data() const
const_iterator end() const
PointerUnion< EltTy, VecTy * > PtrUnion
iterator insert(iterator I, const EltTy &Elt)
iterator erase(iterator S, iterator E)
SmallVector< EltTy, 4 > VecTy
typename VecTy::value_type value_type
TinyPtrVector(TinyPtrVector &&RHS)
iterator insert(iterator I, ItTy From, ItTy To)
EltTy operator[](unsigned i) const
TinyPtrVector(size_t Count, EltTy Value)
LLVM Value Representation.
Definition Value.h:75
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:532
auto dyn_cast_if_present(const Y &Val)
dyn_cast_if_present<X> - Functionally identical to dyn_cast, except that a null (or none in the case ...
Definition Casting.h:732
FunctionAddr VTableAddr Count
Definition InstrProf.h:139
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559