[llvm] [WIP][ADT] Avoid slow size queries on append (PR #136365)
Kazu Hirata via llvm-commits
llvm-commits at lists.llvm.org
Fri Apr 18 13:38:00 PDT 2025
================
@@ -679,13 +687,37 @@ class SmallVectorImpl : public SmallVectorTemplateBase<T> {
void swap(SmallVectorImpl &RHS);
/// Add the specified range to the end of the SmallVector.
- template <typename ItTy, typename = EnableIfConvertibleToInputIterator<ItTy>>
+ template <typename ItTy,
+ typename = detail::EnableIfConvertibleToInputIterator<ItTy>>
void append(ItTy in_start, ItTy in_end) {
this->assertSafeToAddRange(in_start, in_end);
- size_type NumInputs = std::distance(in_start, in_end);
- this->reserve(this->size() + NumInputs);
- this->uninitialized_copy(in_start, in_end, this->end());
- this->set_size(this->size() + NumInputs);
+ if constexpr (detail::IsOfIteratorCategory<
+ ItTy, std::random_access_iterator_tag>) {
+ // Only reserve the required extra size upfront when the size calculation
+ // is guaranteed to be O(1).
+ size_type NumInputs = std::distance(in_start, in_end);
+ this->reserve(this->size() + NumInputs);
+ this->uninitialized_copy(in_start, in_end, this->end());
+ this->set_size(this->size() + NumInputs);
+ } else {
+ // Otherwise, append using `in_end` as the sentinel and reserve more space
+ // as necessary.
+ for (ItTy It = in_start; It != in_end;) {
+ iterator Dest = this->end();
+ size_type InitialSize = this->size();
+ size_type ExtraCap = this->capacity() - InitialSize;
+ size_type NumCopied = 0;
+ for (; NumCopied != ExtraCap && It != in_end; ++It, ++NumCopied) {
+ ::new ((void *)(Dest + NumCopied)) T(*It);
+ }
+ size_type NewSize = InitialSize + NumCopied;
+ this->set_size(NewSize);
+
+ if (It != in_end) {
+ this->reserve(NewSize + 1);
+ }
----------------
kazutakahirata wrote:
nit: Drop curly braces.
https://github.com/llvm/llvm-project/pull/136365
More information about the llvm-commits
mailing list