14#ifndef LLVM_ADT_SMALLVECTOR_H
15#define LLVM_ADT_SMALLVECTOR_H
25#include <initializer_list>
39template <
class Iterator>
41 typename std::iterator_traits<Iterator>::iterator_category,
42 std::input_iterator_tag>
::value>;
59 return std::numeric_limits<Size_T>::max();
69 void *
mallocForGrow(
void *FirstEl,
size_t MinSize,
size_t TSize,
75 void grow_pod(
void *FirstEl,
size_t MinSize,
size_t TSize);
103 Size =
static_cast<Size_T
>(
N);
119 std::conditional_t<
sizeof(
T) < 4 &&
sizeof(
void *) >= 8,
uint64_t,
132template <
typename T,
typename =
void>
142 return const_cast<void *
>(
reinterpret_cast<const void *
>(
143 reinterpret_cast<const char *
>(
this) +
167 std::less<> LessThan;
168 return !LessThan(V,
First) && LessThan(V,
Last);
180 std::less<> LessThan;
182 !LessThan(this->
end(), Last);
193 if (NewSize <= this->
size())
194 return Elt < this->
begin() + NewSize;
203 "Attempting to reference an element of the vector in an operation "
204 "that invalidates it");
222 std::enable_if_t<!std::is_same<std::remove_const_t<ItTy>,
T *>
::value,
235 std::enable_if_t<!std::is_same<std::remove_const_t<ItTy>,
T *>
::value,
244 size_t NewSize = This->size() +
N;
248 bool ReferencesStorage =
false;
250 if (!U::TakesParamByValue) {
252 ReferencesStorage =
true;
253 Index = &Elt - This->begin();
257 return ReferencesStorage ? This->begin() +
Index : &Elt;
339template <
typename T,
bool = (std::is_trivially_copy_constructible<T>::value) &&
340 (std::is_trivially_move_constructible<T>::value) &&
341 std::is_trivially_destructible<T>::value>
360 template<
typename It1,
typename It2>
362 std::uninitialized_move(
I,
E, Dest);
367 template<
typename It1,
typename It2>
369 std::uninitialized_copy(
I,
E, Dest);
397 return const_cast<T *
>(
408 std::uninitialized_fill_n(NewElts, NumElts, Elt);
418 ::new ((
void *)(NewElts + this->
size()))
T(std::forward<ArgTypes>(Args)...);
428 ::new ((
void *)this->
end())
T(*EltPtr);
434 ::new ((
void *)this->
end())
T(::std::move(*EltPtr));
445template <
typename T,
bool TriviallyCopyable>
448 T *NewElts = mallocForGrow(MinSize, NewCapacity);
449 moveElementsForGrow(NewElts);
450 takeAllocationForGrow(NewElts, NewCapacity);
453template <
typename T,
bool TriviallyCopyable>
455 size_t MinSize,
size_t &NewCapacity) {
456 return static_cast<T *
>(
458 this->getFirstEl(), MinSize,
sizeof(
T), NewCapacity));
462template <
typename T,
bool TriviallyCopyable>
466 this->uninitialized_move(this->begin(), this->end(), NewElts);
469 destroy_range(this->begin(), this->end());
473template <
typename T,
bool TriviallyCopyable>
475 T *NewElts,
size_t NewCapacity) {
477 if (!this->isSmall())
480 this->set_allocation_range(NewElts, NewCapacity);
498 using ValueParamT = std::conditional_t<TakesParamByValue, T, const T &>;
507 template<
typename It1,
typename It2>
515 template<
typename It1,
typename It2>
518 std::uninitialized_copy(
I,
E, Dest);
523 template <
typename T1,
typename T2>
526 std::enable_if_t<std::is_same<std::remove_const_t<T1>, T2>
::value> * =
533 memcpy(
reinterpret_cast<void *
>(Dest),
I, (
E -
I) *
sizeof(
T));
549 return const_cast<T *
>(
561 std::uninitialized_fill_n(this->
begin(), NumElts, Elt);
569 push_back(
T(std::forward<ArgTypes>(Args)...));
576 memcpy(
reinterpret_cast<void *
>(this->
end()), EltPtr,
sizeof(
T));
632 template <
bool ForOverwrite>
void resizeImpl(
size_type N) {
633 if (
N == this->size())
636 if (N < this->size()) {
642 for (
auto I = this->
end(),
E = this->
begin() + N;
I !=
E; ++
I)
658 assert(this->
size() >=
N &&
"Cannot increase size with truncate");
664 if (
N == this->
size())
667 if (N < this->
size()) {
687 T Result = ::std::move(this->
back());
695 template <
typename ItTy,
typename = EnableIfConvertibleToInputIterator<ItTy>>
698 size_type NumInputs = std::distance(in_start, in_end);
707 std::uninitialized_fill_n(this->
end(), NumInputs, *EltPtr);
711 void append(std::initializer_list<T> IL) {
712 append(IL.begin(), IL.end());
725 std::fill_n(this->
begin(), std::min(NumElts, this->
size()), Elt);
726 if (NumElts > this->
size())
727 std::uninitialized_fill_n(this->
end(), NumElts - this->
size(), Elt);
728 else if (NumElts < this->
size())
736 template <
typename ItTy,
typename = EnableIfConvertibleToInputIterator<ItTy>>
743 void assign(std::initializer_list<T> IL) {
758 std::move(
I+1, this->
end(), I);
784 std::is_same<std::remove_const_t<std::remove_reference_t<ArgType>>,
786 "ArgType must be derived from T!");
788 if (
I == this->
end()) {
789 this->
push_back(::std::forward<ArgType>(Elt));
790 return this->
end()-1;
797 std::remove_reference_t<ArgType> *EltPtr =
803 std::move_backward(
I, this->
end()-1, this->
end());
809 "ArgType must be '
T' when taking by
value!");
813 *
I = ::
std::forward<ArgType>(*EltPtr);
828 size_t InsertElt =
I - this->
begin();
830 if (I == this->
end()) {
832 return this->
begin()+InsertElt;
842 I = this->
begin()+InsertElt;
848 if (
size_t(this->
end()-I) >= NumToInsert) {
849 T *OldEnd = this->
end();
850 append(std::move_iterator<iterator>(this->
end() - NumToInsert),
851 std::move_iterator<iterator>(this->
end()));
854 std::move_backward(
I, OldEnd-NumToInsert, OldEnd);
859 EltPtr += NumToInsert;
861 std::fill_n(
I, NumToInsert, *EltPtr);
869 T *OldEnd = this->
end();
871 size_t NumOverwritten = OldEnd-
I;
877 EltPtr += NumToInsert;
880 std::fill_n(
I, NumOverwritten, *EltPtr);
883 std::uninitialized_fill_n(OldEnd, NumToInsert - NumOverwritten, *EltPtr);
887 template <
typename ItTy,
typename = EnableIfConvertibleToInputIterator<ItTy>>
890 size_t InsertElt =
I - this->
begin();
892 if (I == this->
end()) {
894 return this->
begin()+InsertElt;
902 size_t NumToInsert = std::distance(
From, To);
908 I = this->
begin()+InsertElt;
914 if (
size_t(this->
end()-I) >= NumToInsert) {
915 T *OldEnd = this->
end();
916 append(std::move_iterator<iterator>(this->
end() - NumToInsert),
917 std::move_iterator<iterator>(this->
end()));
920 std::move_backward(
I, OldEnd-NumToInsert, OldEnd);
922 std::copy(
From, To,
I);
930 T *OldEnd = this->
end();
932 size_t NumOverwritten = OldEnd-
I;
936 for (
T *J =
I; NumOverwritten > 0; --NumOverwritten) {
947 insert(
I, IL.begin(), IL.end());
954 ::new ((
void *)this->
end())
T(std::forward<ArgTypes>(Args)...);
964 if (this->
size() !=
RHS.size())
return false;
968 return !(*
this ==
RHS);
972 return std::lexicographical_compare(this->
begin(), this->
end(),
982 if (
this == &
RHS)
return;
995 size_t NumShared = this->
size();
996 if (NumShared >
RHS.size()) NumShared =
RHS.size();
997 for (
size_type i = 0; i != NumShared; ++i)
1001 if (this->
size() >
RHS.size()) {
1002 size_t EltDiff = this->
size() -
RHS.size();
1004 RHS.set_size(
RHS.size() + EltDiff);
1007 }
else if (
RHS.size() > this->size()) {
1008 size_t EltDiff =
RHS.size() - this->
size();
1012 RHS.set_size(NumShared);
1016template <
typename T>
1020 if (
this == &
RHS)
return *
this;
1024 size_t RHSSize =
RHS.size();
1025 size_t CurSize = this->
size();
1026 if (CurSize >= RHSSize) {
1030 NewEnd = std::copy(
RHS.begin(),
RHS.begin()+RHSSize, this->begin());
1032 NewEnd = this->
begin();
1049 this->
grow(RHSSize);
1050 }
else if (CurSize) {
1052 std::copy(
RHS.begin(),
RHS.begin()+CurSize, this->begin());
1057 this->begin()+CurSize);
1064template <
typename T>
1067 if (
this == &
RHS)
return *
this;
1070 if (!
RHS.isSmall()) {
1077 size_t RHSSize =
RHS.size();
1078 size_t CurSize = this->
size();
1079 if (CurSize >= RHSSize) {
1083 NewEnd = std::move(
RHS.begin(),
RHS.end(), NewEnd);
1103 this->
grow(RHSSize);
1104 }
else if (CurSize) {
1106 std::move(
RHS.begin(),
RHS.begin()+CurSize, this->begin());
1111 this->begin()+CurSize);
1122template <
typename T,
unsigned N>
1124 alignas(
T)
char InlineElts[
N *
sizeof(
T)];
1150 static constexpr size_t kPreferredSmallVectorSizeof = 64;
1176 "You are trying to use a default number of inlined elements for "
1177 "`SmallVector<T>` but `sizeof(T)` is really big! Please use an "
1178 "explicit number of inlined elements with `SmallVector<T, N>` to make "
1179 "sure you really want that much inline storage.");
1183 static constexpr size_t PreferredInlineBytes =
1185 static constexpr size_t NumElementsThatFit = PreferredInlineBytes /
sizeof(
T);
1187 NumElementsThatFit == 0 ? 1 : NumElementsThatFit;
1206template <
typename T,
1215 this->destroy_range(this->begin(), this->end());
1228 template <
typename ItTy,
typename = EnableIfConvertibleToInputIterator<ItTy>>
1233 template <
typename RangeTy>
1236 this->append(R.begin(), R.end());
1243 template <
typename U,
1244 typename = std::enable_if_t<std::is_convertible<U, T>::value>>
1246 this->append(
A.begin(),
A.end());
1279 this->destroy_range(this->begin(), this->end());
1282 this->assignRemote(std::move(
RHS));
1298template <
typename T,
unsigned N>
1300 return X.capacity_in_bytes();
1303template <
typename RangeType>
1305 std::remove_const_t<std::remove_reference_t<
decltype(*std::begin(
1306 std::declval<RangeType &>()))>>;
1311template <
unsigned Size,
typename R>
1315template <
typename R>
1320template <
typename Out,
unsigned Size,
typename R>
1331#if SIZE_MAX > UINT32_MAX
1340 template<
typename T>
1347 template<
typename T,
unsigned N>
#define offsetof(TYPE, MEMBER)
BlockVerifier::State From
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define LLVM_UNLIKELY(EXPR)
#define LLVM_GSL_OWNER
LLVM_GSL_OWNER - Apply this to owning classes like SmallVector to enable lifetime warnings.
#define LLVM_LIKELY(EXPR)
Given that RA is a live value
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
This is all the stuff common to all SmallVectors.
void grow_pod(void *FirstEl, size_t MinSize, size_t TSize)
This is an implementation of the grow() method which only works on POD-like data types and is out of ...
void * mallocForGrow(void *FirstEl, size_t MinSize, size_t TSize, size_t &NewCapacity)
This is a helper for grow() that's out of line to reduce code duplication.
void set_allocation_range(void *Begin, size_t N)
Set the array data pointer to Begin and capacity to N.
SmallVectorBase(void *FirstEl, size_t TotalCapacity)
void set_size(size_t N)
Set the array size to N, which the current array must have enough capacity for.
void * replaceAllocation(void *NewElts, size_t TSize, size_t NewCapacity, size_t VSize=0)
If vector was first created with capacity 0, getFirstEl() points to the memory right after,...
static constexpr size_t SizeTypeMax()
The maximum value of the Size_T used.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void resize_for_overwrite(size_type N)
Like resize, but T is POD, the new values won't be initialized.
void append(const SmallVectorImpl &RHS)
void pop_back_n(size_type NumItems)
void assign(const SmallVectorImpl &RHS)
SmallVectorImpl(const SmallVectorImpl &)=delete
void assign(size_type NumElts, ValueParamT Elt)
reference emplace_back(ArgTypes &&... Args)
bool operator==(const SmallVectorImpl &RHS) const
void reserve(size_type N)
typename SuperClass::reference reference
iterator insert(iterator I, size_type NumToInsert, ValueParamT Elt)
iterator erase(const_iterator CI)
iterator insert(iterator I, ItTy From, ItTy To)
typename SuperClass::const_iterator const_iterator
void assignRemote(SmallVectorImpl &&RHS)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void resize(size_type N, ValueParamT NV)
iterator insert(iterator I, T &&Elt)
bool operator>(const SmallVectorImpl &RHS) const
bool operator<(const SmallVectorImpl &RHS) const
iterator erase(const_iterator CS, const_iterator CE)
bool operator!=(const SmallVectorImpl &RHS) const
void truncate(size_type N)
Like resize, but requires that N is less than size().
void assign(ItTy in_start, ItTy in_end)
void assign(std::initializer_list< T > IL)
SmallVectorImpl(unsigned N)
void swap(SmallVectorImpl &RHS)
typename SuperClass::iterator iterator
bool operator<=(const SmallVectorImpl &RHS) const
typename SuperClass::size_type size_type
void append(std::initializer_list< T > IL)
void append(size_type NumInputs, ValueParamT Elt)
Append NumInputs copies of Elt to the end.
SmallVectorImpl & operator=(const SmallVectorImpl &RHS)
void insert(iterator I, std::initializer_list< T > IL)
SmallVectorImpl & operator=(SmallVectorImpl &&RHS)
typename SuperClass::ValueParamT ValueParamT
bool operator>=(const SmallVectorImpl &RHS) const
iterator insert(iterator I, const T &Elt)
static void uninitialized_copy(It1 I, It1 E, It2 Dest)
Copy the range [I, E) onto the uninitialized memory starting with "Dest", constructing elements into ...
static void uninitialized_move(It1 I, It1 E, It2 Dest)
Move the range [I, E) onto the uninitialized memory starting with "Dest", constructing elements into ...
std::conditional_t< TakesParamByValue, T, const T & > ValueParamT
Either const T& or T, depending on whether it's cheap enough to take parameters by value.
SmallVectorTemplateBase(size_t Size)
const T * reserveForParamAndGetAddress(const T &Elt, size_t N=1)
Reserve enough space to add one element, and return the updated element pointer in case it was a refe...
void push_back(ValueParamT Elt)
static void destroy_range(T *, T *)
T * reserveForParamAndGetAddress(T &Elt, size_t N=1)
Reserve enough space to add one element, and return the updated element pointer in case it was a refe...
static ValueParamT forward_value_param(ValueParamT V)
Copy V or return a reference, depending on ValueParamT.
T & growAndEmplaceBack(ArgTypes &&... Args)
static void uninitialized_copy(T1 *I, T1 *E, T2 *Dest, std::enable_if_t< std::is_same< std::remove_const_t< T1 >, T2 >::value > *=nullptr)
Copy the range [I, E) onto the uninitialized memory starting with "Dest", constructing elements into ...
void growAndAssign(size_t NumElts, T Elt)
void grow(size_t MinSize=0)
Double the size of the allocated memory, guaranteeing space for at least one more element or MinSize ...
SmallVectorTemplateBase<TriviallyCopyable = false> - This is where we put method implementations that...
void moveElementsForGrow(T *NewElts)
Move existing elements over to the new allocation NewElts, the middle section of grow().
static void uninitialized_copy(It1 I, It1 E, It2 Dest)
Copy the range [I, E) onto the uninitialized memory starting with "Dest", constructing elements as ne...
static T && forward_value_param(T &&V)
static void destroy_range(T *S, T *E)
T * mallocForGrow(size_t MinSize, size_t &NewCapacity)
Create a new allocation big enough for MinSize and pass back its size in NewCapacity.
static constexpr bool TakesParamByValue
SmallVectorTemplateBase(size_t Size)
T * reserveForParamAndGetAddress(T &Elt, size_t N=1)
Reserve enough space to add one element, and return the updated element pointer in case it was a refe...
void takeAllocationForGrow(T *NewElts, size_t NewCapacity)
Transfer ownership of the allocation, finishing up grow().
void growAndAssign(size_t NumElts, const T &Elt)
static const T & forward_value_param(const T &V)
static void uninitialized_move(It1 I, It1 E, It2 Dest)
Move the range [I, E) into the uninitialized memory starting with "Dest", constructing elements as ne...
void grow(size_t MinSize=0)
Grow the allocated memory (without initializing new elements), doubling the size of the allocated mem...
const T * reserveForParamAndGetAddress(const T &Elt, size_t N=1)
Reserve enough space to add one element, and return the updated element pointer in case it was a refe...
T & growAndEmplaceBack(ArgTypes &&... Args)
void push_back(const T &Elt)
This is the part of SmallVectorTemplateBase which does not depend on whether the type T is a POD.
void assertSafeToAddRange(ItTy, ItTy)
bool isSmall() const
Return true if this is a smallvector which has not had dynamic memory allocated for it.
const_iterator end() const
reverse_iterator rbegin()
static const T * reserveForParamAndGetAddressImpl(U *This, const T &Elt, size_t N)
Reserve enough space to add one element, and return the updated element pointer in case it was a refe...
SmallVectorTemplateCommon(size_t Size)
void assertSafeToAddRange(const T *From, const T *To)
Check whether any part of the range will be invalidated by growing.
const_reference operator[](size_type idx) const
void resetToSmall()
Put this vector in a state of being small.
bool isSafeToReferenceAfterResize(const void *Elt, size_t NewSize)
Return true unless Elt will be invalidated by resizing the vector to NewSize.
void assertSafeToReferenceAfterClear(const T *From, const T *To)
Check whether any part of the range will be invalidated by clearing.
std::reverse_iterator< const_iterator > const_reverse_iterator
pointer data()
Return a pointer to the vector's buffer, even if empty().
bool isReferenceToRange(const void *V, const void *First, const void *Last) const
Return true if V is an internal reference to the given range.
void grow_pod(size_t MinSize, size_t TSize)
const_reverse_iterator rbegin() const
const_iterator begin() const
reference operator[](size_type idx)
size_t capacity_in_bytes() const
size_type size_in_bytes() const
size_type max_size() const
bool isReferenceToStorage(const void *V) const
Return true if V is an internal reference to this vector.
const_reference back() const
bool isRangeInStorage(const void *First, const void *Last) const
Return true if First and Last form a valid (possibly empty) range in this vector's storage.
const_reference front() const
void assertSafeToAdd(const void *Elt, size_t N=1)
Check whether Elt will be invalidated by increasing the size of the vector by N.
void assertSafeToReferenceAfterResize(const void *Elt, size_t NewSize)
Check whether Elt will be invalidated by resizing the vector to NewSize.
std::reverse_iterator< iterator > reverse_iterator
void assertSafeToReferenceAfterClear(ItTy, ItTy)
const_reverse_iterator rend() const
const_pointer data() const
Return a pointer to the vector's buffer, even if empty().
void * getFirstEl() const
Find the address of the first element.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
SmallVector(std::initializer_list< T > IL)
SmallVector(SmallVectorImpl< T > &&RHS)
SmallVector(ArrayRef< U > A)
SmallVector(size_t Size, const T &Value)
SmallVector & operator=(const SmallVector &RHS)
SmallVector(const iterator_range< RangeTy > &R)
SmallVector & operator=(std::initializer_list< T > IL)
SmallVector(ItTy S, ItTy E)
SmallVector(SmallVector &&RHS)
SmallVector & operator=(SmallVector &&RHS)
SmallVector(const SmallVector &RHS)
SmallVector & operator=(SmallVectorImpl< T > &&RHS)
LLVM Value Representation.
A range adaptor for a pair of iterators.
This is an optimization pass for GlobalISel generic memory operations.
std::conditional_t< sizeof(T)< 4 &&sizeof(void *) >=8, uint64_t, uint32_t > SmallVectorSizeType
BitVector::size_type capacity_in_bytes(const BitVector &X)
std::enable_if_t< std::is_convertible< typename std::iterator_traits< Iterator >::iterator_category, std::input_iterator_tag >::value > EnableIfConvertibleToInputIterator
SmallVector< ValueTypeFromRangeType< R >, Size > to_vector(R &&Range)
Given a range of type R, iterate the entire range and return a SmallVector with elements of the vecto...
std::remove_const_t< std::remove_reference_t< decltype(*std::begin(std::declval< RangeType & >()))> > ValueTypeFromRangeType
iterator_range(Container &&) -> iterator_range< llvm::detail::IterOfRange< Container > >
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
ArrayRef(const T &OneElt) -> ArrayRef< T >
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
SmallVector< Out, Size > to_vector_of(R &&Range)
Implement std::hash so that hash_code can be used in STL containers.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Helper class for calculating the default number of inline elements for SmallVector<T>.
Figure out the offset of the first element.
char Base[sizeof(SmallVectorBase< SmallVectorSizeType< T > >)]
Storage for the SmallVector elements.