After some discussion with djg, teach SmallVector to grow from a zero

capacity and remove the workaround in SmallVector<T,0>.  There are some
theoretical benefits to a N->2N+1 growth policy anyway.

llvm-svn: 112870
This commit is contained in:
John McCall 2010-09-02 21:55:03 +00:00
parent 814a69c330
commit 7f55c258c6
2 changed files with 7 additions and 18 deletions

View File

@ -206,7 +206,7 @@ template <typename T, bool isPodLike>
void SmallVectorTemplateBase<T, isPodLike>::grow(size_t MinSize) { void SmallVectorTemplateBase<T, isPodLike>::grow(size_t MinSize) {
size_t CurCapacity = this->capacity(); size_t CurCapacity = this->capacity();
size_t CurSize = this->size(); size_t CurSize = this->size();
size_t NewCapacity = 2*CurCapacity; size_t NewCapacity = 2*CurCapacity + 1; // Always grow, even from zero.
if (NewCapacity < MinSize) if (NewCapacity < MinSize)
NewCapacity = MinSize; NewCapacity = MinSize;
T *NewElts = static_cast<T*>(malloc(NewCapacity*sizeof(T))); T *NewElts = static_cast<T*>(malloc(NewCapacity*sizeof(T)));
@ -712,38 +712,27 @@ public:
/// members are required. /// members are required.
template <typename T> template <typename T>
class SmallVector<T,0> : public SmallVectorImpl<T> { class SmallVector<T,0> : public SmallVectorImpl<T> {
// SmallVector doesn't like growing from zero capacity. As a
// temporary workaround, avoid changing the growth algorithm by
// forcing capacity to be at least 1 in the constructors.
public: public:
SmallVector() : SmallVectorImpl<T>(0) { SmallVector() : SmallVectorImpl<T>(0) {}
this->reserve(1); // workaround
}
explicit SmallVector(unsigned Size, const T &Value = T()) explicit SmallVector(unsigned Size, const T &Value = T())
: SmallVectorImpl<T>(0) { : SmallVectorImpl<T>(0) {
this->reserve(Size ? Size : 1); // workaround this->reserve(Size);
while (Size--) while (Size--)
this->push_back(Value); this->push_back(Value);
} }
template<typename ItTy> template<typename ItTy>
SmallVector(ItTy S, ItTy E) : SmallVectorImpl<T>(0) { SmallVector(ItTy S, ItTy E) : SmallVectorImpl<T>(0) {
if (S == E) this->reserve(1); // workaround
this->append(S, E); this->append(S, E);
} }
SmallVector(const SmallVector &RHS) : SmallVectorImpl<T>(0) { SmallVector(const SmallVector &RHS) : SmallVectorImpl<T>(0) {
if (!RHS.empty()) SmallVectorImpl<T>::operator=(RHS);
SmallVectorImpl<T>::operator=(RHS);
else
this->reserve(1); // workaround
} }
const SmallVector &operator=(const SmallVector &RHS) { SmallVector &operator=(const SmallVectorImpl<T> &RHS) {
SmallVectorImpl<T>::operator=(RHS); return SmallVectorImpl<T>::operator=(RHS);
return *this;
} }
}; };

View File

@ -18,7 +18,7 @@ using namespace llvm;
/// on POD-like datatypes and is out of line to reduce code duplication. /// on POD-like datatypes and is out of line to reduce code duplication.
void SmallVectorBase::grow_pod(size_t MinSizeInBytes, size_t TSize) { void SmallVectorBase::grow_pod(size_t MinSizeInBytes, size_t TSize) {
size_t CurSizeBytes = size_in_bytes(); size_t CurSizeBytes = size_in_bytes();
size_t NewCapacityInBytes = 2 * capacity_in_bytes(); size_t NewCapacityInBytes = 2 * capacity_in_bytes() + TSize; // Always grow.
if (NewCapacityInBytes < MinSizeInBytes) if (NewCapacityInBytes < MinSizeInBytes)
NewCapacityInBytes = MinSizeInBytes; NewCapacityInBytes = MinSizeInBytes;