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