Skip to content

Commit 333f501

Browse files
committed
[SmallVector] Optimize move assignment operator for N==0 case
Due to the SmallVector hierarchy, N==0 cannot be leveraged by functions defined in base classes. This patch special cases N==0 for SmallVector to save code size and be slightly more efficient. In a Release build of x86 only clang, .text is -3.34KiB smaller. In lld .text is 7.17KiB smaller. Reviewed By: lichray Differential Revision: https://reviews.llvm.org/D117976
1 parent 4a69c8e commit 333f501

File tree

1 file changed

+25
-7
lines changed

1 file changed

+25
-7
lines changed

llvm/include/llvm/ADT/SmallVector.h

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,16 @@ class SmallVectorImpl : public SmallVectorTemplateBase<T> {
568568
explicit SmallVectorImpl(unsigned N)
569569
: SmallVectorTemplateBase<T>(N) {}
570570

571+
void assignRemote(SmallVectorImpl &&RHS) {
572+
this->destroy_range(this->begin(), this->end());
573+
if (!this->isSmall())
574+
free(this->begin());
575+
this->BeginX = RHS.BeginX;
576+
this->Size = RHS.Size;
577+
this->Capacity = RHS.Capacity;
578+
RHS.resetToSmall();
579+
}
580+
571581
public:
572582
SmallVectorImpl(const SmallVectorImpl &) = delete;
573583

@@ -1032,12 +1042,7 @@ SmallVectorImpl<T> &SmallVectorImpl<T>::operator=(SmallVectorImpl<T> &&RHS) {
10321042

10331043
// If the RHS isn't small, clear this vector and then steal its buffer.
10341044
if (!RHS.isSmall()) {
1035-
this->destroy_range(this->begin(), this->end());
1036-
if (!this->isSmall()) free(this->begin());
1037-
this->BeginX = RHS.BeginX;
1038-
this->Size = RHS.Size;
1039-
this->Capacity = RHS.Capacity;
1040-
RHS.resetToSmall();
1045+
this->assignRemote(std::move(RHS));
10411046
return *this;
10421047
}
10431048

@@ -1228,7 +1233,20 @@ class LLVM_GSL_OWNER SmallVector : public SmallVectorImpl<T>,
12281233
}
12291234

12301235
SmallVector &operator=(SmallVector &&RHS) {
1231-
SmallVectorImpl<T>::operator=(::std::move(RHS));
1236+
if (N) {
1237+
SmallVectorImpl<T>::operator=(::std::move(RHS));
1238+
return *this;
1239+
}
1240+
// SmallVectorImpl<T>::operator= does not leverage N==0. Optimize the
1241+
// case.
1242+
if (this == &RHS)
1243+
return *this;
1244+
if (RHS.empty()) {
1245+
this->destroy_range(this->begin(), this->end());
1246+
this->Size = 0;
1247+
} else {
1248+
this->assignRemote(std::move(RHS));
1249+
}
12321250
return *this;
12331251
}
12341252

0 commit comments

Comments
 (0)