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);
90 Size =
static_cast<Size_T
>(
N);
106 std::conditional_t<
sizeof(
T) < 4 &&
sizeof(
void *) >= 8,
uint64_t,
119template <
typename T,
typename =
void>
129 return const_cast<void *
>(
reinterpret_cast<const void *
>(
130 reinterpret_cast<const char *
>(
this) +
154 std::less<> LessThan;
155 return !LessThan(V,
First) && LessThan(V,
Last);
167 std::less<> LessThan;
169 !LessThan(this->
end(), Last);
180 if (NewSize <= this->
size())
181 return Elt < this->
begin() + NewSize;
190 "Attempting to reference an element of the vector in an operation "
191 "that invalidates it");
209 std::enable_if_t<!std::is_same<std::remove_const_t<ItTy>,
T *>
::value,
222 std::enable_if_t<!std::is_same<std::remove_const_t<ItTy>,
T *>
::value,
231 size_t NewSize = This->size() +
N;
235 bool ReferencesStorage =
false;
237 if (!U::TakesParamByValue) {
239 ReferencesStorage =
true;
240 Index = &Elt - This->begin();
244 return ReferencesStorage ? This->begin() +
Index : &Elt;
326template <
typename T,
bool = (std::is_trivially_copy_constructible<T>::value) &&
327 (std::is_trivially_move_constructible<T>::value) &&
328 std::is_trivially_destructible<T>::value>
347 template<
typename It1,
typename It2>
349 std::uninitialized_move(
I,
E, Dest);
354 template<
typename It1,
typename It2>
356 std::uninitialized_copy(
I,
E, Dest);
384 return const_cast<T *
>(
395 std::uninitialized_fill_n(NewElts, NumElts, Elt);
405 ::new ((
void *)(NewElts + this->
size()))
T(std::forward<ArgTypes>(Args)...);
415 ::new ((
void *)this->
end())
T(*EltPtr);
421 ::new ((
void *)this->
end())
T(::std::move(*EltPtr));
432template <
typename T,
bool TriviallyCopyable>
435 T *NewElts = mallocForGrow(MinSize, NewCapacity);
436 moveElementsForGrow(NewElts);
437 takeAllocationForGrow(NewElts, NewCapacity);
440template <
typename T,
bool TriviallyCopyable>
442 size_t MinSize,
size_t &NewCapacity) {
443 return static_cast<T *
>(
445 this->getFirstEl(), MinSize,
sizeof(
T), NewCapacity));
449template <
typename T,
bool TriviallyCopyable>
453 this->uninitialized_move(this->begin(), this->end(), NewElts);
456 destroy_range(this->begin(), this->end());
460template <
typename T,
bool TriviallyCopyable>
462 T *NewElts,
size_t NewCapacity) {
464 if (!this->isSmall())
467 this->set_allocation_range(NewElts, NewCapacity);
485 using ValueParamT = std::conditional_t<TakesParamByValue, T, const T &>;
494 template<
typename It1,
typename It2>
502 template<
typename It1,
typename It2>
505 std::uninitialized_copy(
I,
E, Dest);
510 template <
typename T1,
typename T2>
513 std::enable_if_t<std::is_same<std::remove_const_t<T1>, T2>
::value> * =
520 memcpy(
reinterpret_cast<void *
>(Dest),
I, (
E -
I) *
sizeof(
T));
536 return const_cast<T *
>(
548 std::uninitialized_fill_n(this->
begin(), NumElts, Elt);
556 push_back(
T(std::forward<ArgTypes>(Args)...));
563 memcpy(
reinterpret_cast<void *
>(this->
end()), EltPtr,
sizeof(
T));
619 template <
bool ForOverwrite>
void resizeImpl(
size_type N) {
620 if (
N == this->size())
623 if (N < this->size()) {
629 for (
auto I = this->
end(),
E = this->
begin() + N;
I !=
E; ++
I)
645 assert(this->
size() >=
N &&
"Cannot increase size with truncate");
651 if (
N == this->
size())
654 if (N < this->
size()) {
674 T Result = ::std::move(this->
back());
682 template <
typename ItTy,
typename = EnableIfConvertibleToInputIterator<ItTy>>
685 size_type NumInputs = std::distance(in_start, in_end);
694 std::uninitialized_fill_n(this->
end(), NumInputs, *EltPtr);
698 void append(std::initializer_list<T> IL) {
699 append(IL.begin(), IL.end());
712 std::fill_n(this->
begin(), std::min(NumElts, this->
size()), Elt);
713 if (NumElts > this->
size())
714 std::uninitialized_fill_n(this->
end(), NumElts - this->
size(), Elt);
715 else if (NumElts < this->
size())
723 template <
typename ItTy,
typename = EnableIfConvertibleToInputIterator<ItTy>>
730 void assign(std::initializer_list<T> IL) {
745 std::move(
I+1, this->
end(), I);
771 std::is_same<std::remove_const_t<std::remove_reference_t<ArgType>>,
773 "ArgType must be derived from T!");
775 if (
I == this->
end()) {
776 this->
push_back(::std::forward<ArgType>(Elt));
777 return this->
end()-1;
784 std::remove_reference_t<ArgType> *EltPtr =
790 std::move_backward(
I, this->
end()-1, this->
end());
796 "ArgType must be '
T' when taking by
value!");
800 *
I = ::
std::forward<ArgType>(*EltPtr);
815 size_t InsertElt =
I - this->
begin();
817 if (I == this->
end()) {
819 return this->
begin()+InsertElt;
829 I = this->
begin()+InsertElt;
835 if (
size_t(this->
end()-I) >= NumToInsert) {
836 T *OldEnd = this->
end();
837 append(std::move_iterator<iterator>(this->
end() - NumToInsert),
838 std::move_iterator<iterator>(this->
end()));
841 std::move_backward(
I, OldEnd-NumToInsert, OldEnd);
846 EltPtr += NumToInsert;
848 std::fill_n(
I, NumToInsert, *EltPtr);
856 T *OldEnd = this->
end();
858 size_t NumOverwritten = OldEnd-
I;
864 EltPtr += NumToInsert;
867 std::fill_n(
I, NumOverwritten, *EltPtr);
870 std::uninitialized_fill_n(OldEnd, NumToInsert - NumOverwritten, *EltPtr);
874 template <
typename ItTy,
typename = EnableIfConvertibleToInputIterator<ItTy>>
877 size_t InsertElt =
I - this->
begin();
879 if (I == this->
end()) {
881 return this->
begin()+InsertElt;
889 size_t NumToInsert = std::distance(
From, To);
895 I = this->
begin()+InsertElt;
901 if (
size_t(this->
end()-I) >= NumToInsert) {
902 T *OldEnd = this->
end();
903 append(std::move_iterator<iterator>(this->
end() - NumToInsert),
904 std::move_iterator<iterator>(this->
end()));
907 std::move_backward(
I, OldEnd-NumToInsert, OldEnd);
909 std::copy(
From, To,
I);
917 T *OldEnd = this->
end();
919 size_t NumOverwritten = OldEnd-
I;
923 for (
T *J =
I; NumOverwritten > 0; --NumOverwritten) {
934 insert(
I, IL.begin(), IL.end());
941 ::new ((
void *)this->
end())
T(std::forward<ArgTypes>(Args)...);
951 if (this->
size() !=
RHS.size())
return false;
955 return !(*
this ==
RHS);
959 return std::lexicographical_compare(this->
begin(), this->
end(),
969 if (
this == &
RHS)
return;
982 size_t NumShared = this->
size();
983 if (NumShared >
RHS.size()) NumShared =
RHS.size();
984 for (
size_type i = 0; i != NumShared; ++i)
988 if (this->
size() >
RHS.size()) {
989 size_t EltDiff = this->
size() -
RHS.size();
991 RHS.set_size(
RHS.size() + EltDiff);
994 }
else if (
RHS.size() > this->size()) {
995 size_t EltDiff =
RHS.size() - this->
size();
999 RHS.set_size(NumShared);
1003template <
typename T>
1007 if (
this == &
RHS)
return *
this;
1011 size_t RHSSize =
RHS.size();
1012 size_t CurSize = this->
size();
1013 if (CurSize >= RHSSize) {
1017 NewEnd = std::copy(
RHS.begin(),
RHS.begin()+RHSSize, this->begin());
1019 NewEnd = this->
begin();
1036 this->
grow(RHSSize);
1037 }
else if (CurSize) {
1039 std::copy(
RHS.begin(),
RHS.begin()+CurSize, this->begin());
1044 this->begin()+CurSize);
1051template <
typename T>
1054 if (
this == &
RHS)
return *
this;
1057 if (!
RHS.isSmall()) {
1064 size_t RHSSize =
RHS.size();
1065 size_t CurSize = this->
size();
1066 if (CurSize >= RHSSize) {
1070 NewEnd = std::move(
RHS.begin(),
RHS.end(), NewEnd);
1090 this->
grow(RHSSize);
1091 }
else if (CurSize) {
1093 std::move(
RHS.begin(),
RHS.begin()+CurSize, this->begin());
1098 this->begin()+CurSize);
1109template <
typename T,
unsigned N>
1111 alignas(
T)
char InlineElts[
N *
sizeof(
T)];
1137 static constexpr size_t kPreferredSmallVectorSizeof = 64;
1163 "You are trying to use a default number of inlined elements for "
1164 "`SmallVector<T>` but `sizeof(T)` is really big! Please use an "
1165 "explicit number of inlined elements with `SmallVector<T, N>` to make "
1166 "sure you really want that much inline storage.");
1170 static constexpr size_t PreferredInlineBytes =
1172 static constexpr size_t NumElementsThatFit = PreferredInlineBytes /
sizeof(
T);
1174 NumElementsThatFit == 0 ? 1 : NumElementsThatFit;
1193template <
typename T,
1202 this->destroy_range(this->begin(), this->end());
1215 template <
typename ItTy,
typename = EnableIfConvertibleToInputIterator<ItTy>>
1220 template <
typename RangeTy>
1223 this->append(R.begin(), R.end());
1230 template <
typename U,
1231 typename = std::enable_if_t<std::is_convertible<U, T>::value>>
1233 this->append(
A.begin(),
A.end());
1266 this->destroy_range(this->begin(), this->end());
1269 this->assignRemote(std::move(
RHS));
1285template <
typename T,
unsigned N>
1287 return X.capacity_in_bytes();
1290template <
typename RangeType>
1292 std::remove_const_t<std::remove_reference_t<
decltype(*std::begin(
1293 std::declval<RangeType &>()))>>;
1298template <
unsigned Size,
typename R>
1302template <
typename R>
1307template <
typename Out,
unsigned Size,
typename R>
1318#if SIZE_MAX > UINT32_MAX
1327 template<
typename T>
1334 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.
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.