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);
109 std::conditional_t<
sizeof(
T) < 4 &&
sizeof(
void *) >= 8,
uint64_t,
122template <
typename T,
typename =
void>
132 return const_cast<void *
>(
reinterpret_cast<const void *
>(
133 reinterpret_cast<const char *
>(
this) +
157 std::less<> LessThan;
158 return !LessThan(V,
First) && LessThan(V,
Last);
170 std::less<> LessThan;
172 !LessThan(this->
end(), Last);
183 if (NewSize <= this->
size())
184 return Elt < this->
begin() + NewSize;
193 "Attempting to reference an element of the vector in an operation "
194 "that invalidates it");
212 std::enable_if_t<!std::is_same<std::remove_const_t<ItTy>,
T *>
::value,
225 std::enable_if_t<!std::is_same<std::remove_const_t<ItTy>,
T *>
::value,
234 size_t NewSize = This->size() +
N;
238 bool ReferencesStorage =
false;
240 if (!U::TakesParamByValue) {
242 ReferencesStorage =
true;
243 Index = &Elt - This->begin();
247 return ReferencesStorage ? This->begin() +
Index : &Elt;
329template <
typename T,
bool = (std::is_trivially_copy_constructible<T>::value) &&
330 (std::is_trivially_move_constructible<T>::value) &&
331 std::is_trivially_destructible<T>::value>
350 template<
typename It1,
typename It2>
352 std::uninitialized_move(
I,
E, Dest);
357 template<
typename It1,
typename It2>
359 std::uninitialized_copy(
I,
E, Dest);
387 return const_cast<T *
>(
398 std::uninitialized_fill_n(NewElts, NumElts, Elt);
408 ::new ((
void *)(NewElts + this->
size()))
T(std::forward<ArgTypes>(Args)...);
418 ::new ((
void *)this->
end())
T(*EltPtr);
424 ::new ((
void *)this->
end())
T(::std::move(*EltPtr));
435template <
typename T,
bool TriviallyCopyable>
438 T *NewElts = mallocForGrow(MinSize, NewCapacity);
439 moveElementsForGrow(NewElts);
440 takeAllocationForGrow(NewElts, NewCapacity);
443template <
typename T,
bool TriviallyCopyable>
445 size_t MinSize,
size_t &NewCapacity) {
446 return static_cast<T *
>(
448 this->getFirstEl(), MinSize,
sizeof(
T), NewCapacity));
452template <
typename T,
bool TriviallyCopyable>
456 this->uninitialized_move(this->begin(), this->end(), NewElts);
459 destroy_range(this->begin(), this->end());
463template <
typename T,
bool TriviallyCopyable>
465 T *NewElts,
size_t NewCapacity) {
467 if (!this->isSmall())
470 this->BeginX = NewElts;
471 this->Capacity = NewCapacity;
489 using ValueParamT = std::conditional_t<TakesParamByValue, T, const T &>;
498 template<
typename It1,
typename It2>
506 template<
typename It1,
typename It2>
509 std::uninitialized_copy(
I,
E, Dest);
514 template <
typename T1,
typename T2>
517 std::enable_if_t<std::is_same<std::remove_const_t<T1>, T2>
::value> * =
524 memcpy(
reinterpret_cast<void *
>(Dest),
I, (
E -
I) *
sizeof(
T));
540 return const_cast<T *
>(
552 std::uninitialized_fill_n(this->
begin(), NumElts, Elt);
560 push_back(
T(std::forward<ArgTypes>(Args)...));
567 memcpy(
reinterpret_cast<void *
>(this->
end()), EltPtr,
sizeof(
T));
623 template <
bool ForOverwrite>
void resizeImpl(
size_type N) {
624 if (
N == this->size())
627 if (N < this->size()) {
633 for (
auto I = this->
end(),
E = this->
begin() + N;
I !=
E; ++
I)
649 assert(this->
size() >=
N &&
"Cannot increase size with truncate");
655 if (
N == this->
size())
658 if (N < this->
size()) {
678 T Result = ::std::move(this->
back());
686 template <
typename ItTy,
typename = EnableIfConvertibleToInputIterator<ItTy>>
689 size_type NumInputs = std::distance(in_start, in_end);
698 std::uninitialized_fill_n(this->
end(), NumInputs, *EltPtr);
702 void append(std::initializer_list<T> IL) {
703 append(IL.begin(), IL.end());
716 std::fill_n(this->
begin(), std::min(NumElts, this->
size()), Elt);
717 if (NumElts > this->
size())
718 std::uninitialized_fill_n(this->
end(), NumElts - this->
size(), Elt);
719 else if (NumElts < this->
size())
727 template <
typename ItTy,
typename = EnableIfConvertibleToInputIterator<ItTy>>
734 void assign(std::initializer_list<T> IL) {
749 std::move(
I+1, this->
end(), I);
775 std::is_same<std::remove_const_t<std::remove_reference_t<ArgType>>,
777 "ArgType must be derived from T!");
779 if (
I == this->
end()) {
780 this->
push_back(::std::forward<ArgType>(Elt));
781 return this->
end()-1;
788 std::remove_reference_t<ArgType> *EltPtr =
794 std::move_backward(
I, this->
end()-1, this->
end());
800 "ArgType must be '
T' when taking by
value!");
804 *
I = ::
std::forward<ArgType>(*EltPtr);
819 size_t InsertElt =
I - this->
begin();
821 if (I == this->
end()) {
823 return this->
begin()+InsertElt;
833 I = this->
begin()+InsertElt;
839 if (
size_t(this->
end()-I) >= NumToInsert) {
840 T *OldEnd = this->
end();
841 append(std::move_iterator<iterator>(this->
end() - NumToInsert),
842 std::move_iterator<iterator>(this->
end()));
845 std::move_backward(
I, OldEnd-NumToInsert, OldEnd);
850 EltPtr += NumToInsert;
852 std::fill_n(
I, NumToInsert, *EltPtr);
860 T *OldEnd = this->
end();
862 size_t NumOverwritten = OldEnd-
I;
868 EltPtr += NumToInsert;
871 std::fill_n(
I, NumOverwritten, *EltPtr);
874 std::uninitialized_fill_n(OldEnd, NumToInsert - NumOverwritten, *EltPtr);
878 template <
typename ItTy,
typename = EnableIfConvertibleToInputIterator<ItTy>>
881 size_t InsertElt =
I - this->
begin();
883 if (I == this->
end()) {
885 return this->
begin()+InsertElt;
893 size_t NumToInsert = std::distance(
From, To);
899 I = this->
begin()+InsertElt;
905 if (
size_t(this->
end()-I) >= NumToInsert) {
906 T *OldEnd = this->
end();
907 append(std::move_iterator<iterator>(this->
end() - NumToInsert),
908 std::move_iterator<iterator>(this->
end()));
911 std::move_backward(
I, OldEnd-NumToInsert, OldEnd);
913 std::copy(
From, To,
I);
921 T *OldEnd = this->
end();
923 size_t NumOverwritten = OldEnd-
I;
927 for (
T *J =
I; NumOverwritten > 0; --NumOverwritten) {
938 insert(
I, IL.begin(), IL.end());
945 ::new ((
void *)this->
end())
T(std::forward<ArgTypes>(Args)...);
955 if (this->
size() !=
RHS.size())
return false;
959 return !(*
this ==
RHS);
963 return std::lexicographical_compare(this->
begin(), this->
end(),
973 if (
this == &
RHS)
return;
986 size_t NumShared = this->
size();
987 if (NumShared >
RHS.size()) NumShared =
RHS.size();
988 for (
size_type i = 0; i != NumShared; ++i)
992 if (this->
size() >
RHS.size()) {
993 size_t EltDiff = this->
size() -
RHS.size();
995 RHS.set_size(
RHS.size() + EltDiff);
998 }
else if (
RHS.size() > this->size()) {
999 size_t EltDiff =
RHS.size() - this->
size();
1003 RHS.set_size(NumShared);
1007template <
typename T>
1011 if (
this == &
RHS)
return *
this;
1015 size_t RHSSize =
RHS.size();
1016 size_t CurSize = this->
size();
1017 if (CurSize >= RHSSize) {
1021 NewEnd = std::copy(
RHS.begin(),
RHS.begin()+RHSSize, this->begin());
1023 NewEnd = this->
begin();
1040 this->
grow(RHSSize);
1041 }
else if (CurSize) {
1043 std::copy(
RHS.begin(),
RHS.begin()+CurSize, this->begin());
1048 this->begin()+CurSize);
1055template <
typename T>
1058 if (
this == &
RHS)
return *
this;
1061 if (!
RHS.isSmall()) {
1068 size_t RHSSize =
RHS.size();
1069 size_t CurSize = this->
size();
1070 if (CurSize >= RHSSize) {
1074 NewEnd = std::move(
RHS.begin(),
RHS.end(), NewEnd);
1094 this->
grow(RHSSize);
1095 }
else if (CurSize) {
1097 std::move(
RHS.begin(),
RHS.begin()+CurSize, this->begin());
1102 this->begin()+CurSize);
1113template <
typename T,
unsigned N>
1115 alignas(
T)
char InlineElts[
N *
sizeof(
T)];
1141 static constexpr size_t kPreferredSmallVectorSizeof = 64;
1167 "You are trying to use a default number of inlined elements for "
1168 "`SmallVector<T>` but `sizeof(T)` is really big! Please use an "
1169 "explicit number of inlined elements with `SmallVector<T, N>` to make "
1170 "sure you really want that much inline storage.");
1174 static constexpr size_t PreferredInlineBytes =
1176 static constexpr size_t NumElementsThatFit = PreferredInlineBytes /
sizeof(
T);
1178 NumElementsThatFit == 0 ? 1 : NumElementsThatFit;
1197template <
typename T,
1206 this->destroy_range(this->begin(), this->end());
1219 template <
typename ItTy,
typename = EnableIfConvertibleToInputIterator<ItTy>>
1224 template <
typename RangeTy>
1227 this->append(R.begin(), R.end());
1234 template <
typename U,
1235 typename = std::enable_if_t<std::is_convertible<U, T>::value>>
1237 this->append(
A.begin(),
A.end());
1270 this->destroy_range(this->begin(), this->end());
1273 this->assignRemote(std::move(
RHS));
1289template <
typename T,
unsigned N>
1291 return X.capacity_in_bytes();
1294template <
typename RangeType>
1296 std::remove_const_t<std::remove_reference_t<
decltype(*std::begin(
1297 std::declval<RangeType &>()))>>;
1302template <
unsigned Size,
typename R>
1304 return {std::begin(Range), std::end(Range)};
1306template <
typename R>
1308 return {std::begin(Range), std::end(Range)};
1311template <
typename Out,
unsigned Size,
typename R>
1313 return {std::begin(Range), std::end(Range)};
1317 return {std::begin(Range), std::end(Range)};
1322#if SIZE_MAX > UINT32_MAX
1331 template<
typename T>
1338 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")
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.
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
iterator_range(Container &&) -> iterator_range< detail::IterOfRange< Container > >
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
@ 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.