diff --git a/libcxx/benchmarks/ContainerBenchmarks.h b/libcxx/benchmarks/ContainerBenchmarks.h --- a/libcxx/benchmarks/ContainerBenchmarks.h +++ b/libcxx/benchmarks/ContainerBenchmarks.h @@ -79,6 +79,19 @@ } } +template +void BM_Pushback(benchmark::State& state, Container c) { + int count = state.range(0); + c.reserve(count); + while (state.KeepRunningBatch(count)) { + c.clear(); + for (int i = 0; i != count; ++i) { + c.push_back(i); + } + benchmark::DoNotOptimize(c.data()); + } +} + template void BM_InsertValue(benchmark::State& st, Container c, GenInputs gen) { auto in = gen(st.range(0)); diff --git a/libcxx/benchmarks/vector_operations.bench.cpp b/libcxx/benchmarks/vector_operations.bench.cpp --- a/libcxx/benchmarks/vector_operations.bench.cpp +++ b/libcxx/benchmarks/vector_operations.bench.cpp @@ -39,4 +39,6 @@ BENCHMARK_CAPTURE(BM_ConstructFromRange, vector_string, std::vector{}, getRandomStringInputs) ->Arg(TestNumInputs); +BENCHMARK_CAPTURE(BM_Pushback, vector_int, std::vector{})->Arg(TestNumInputs); + BENCHMARK_MAIN(); diff --git a/libcxx/include/vector b/libcxx/include/vector --- a/libcxx/include/vector +++ b/libcxx/include/vector @@ -833,11 +833,11 @@ template _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI - inline void __push_back_slow_path(_Up&& __x); + inline pointer __push_back_slow_path(_Up&& __x); template _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI - inline void __emplace_back_slow_path(_Args&&... __args); + inline pointer __emplace_back_slow_path(_Args&&... __args); // The following functions are no-ops outside of AddressSanitizer mode. // We call annotations for every allocator, unless explicitly disabled. @@ -1609,7 +1609,7 @@ template template _LIBCPP_CONSTEXPR_SINCE_CXX20 -void +typename vector<_Tp, _Allocator>::pointer vector<_Tp, _Allocator>::__push_back_slow_path(_Up&& __x) { allocator_type& __a = this->__alloc(); @@ -1618,6 +1618,7 @@ __alloc_traits::construct(__a, std::__to_address(__v.__end_), std::forward<_Up>(__x)); __v.__end_++; __swap_out_circular_buffer(__v); + return this->__end_; } template @@ -1626,12 +1627,14 @@ void vector<_Tp, _Allocator>::push_back(const_reference __x) { - if (this->__end_ != this->__end_cap()) - { + pointer __end = this->__end_; + if (__end < this->__end_cap()) { __construct_one_at_end(__x); + ++__end; + } else { + __end = __push_back_slow_path(__x); } - else - __push_back_slow_path(__x); + this->__end_ = __end; } template @@ -1640,18 +1643,20 @@ void vector<_Tp, _Allocator>::push_back(value_type&& __x) { - if (this->__end_ < this->__end_cap()) - { + pointer __end = this->__end_; + if (__end < this->__end_cap()) { __construct_one_at_end(std::move(__x)); + ++__end; + } else { + __end = __push_back_slow_path(std::move(__x)); } - else - __push_back_slow_path(std::move(__x)); + this->__end_ = __end; } template template _LIBCPP_CONSTEXPR_SINCE_CXX20 -void +typename vector<_Tp, _Allocator>::pointer vector<_Tp, _Allocator>::__emplace_back_slow_path(_Args&&... __args) { allocator_type& __a = this->__alloc(); @@ -1660,6 +1665,7 @@ __alloc_traits::construct(__a, std::__to_address(__v.__end_), std::forward<_Args>(__args)...); __v.__end_++; __swap_out_circular_buffer(__v); + return this->__end_; } template @@ -1673,14 +1679,16 @@ #endif vector<_Tp, _Allocator>::emplace_back(_Args&&... __args) { - if (this->__end_ < this->__end_cap()) - { + pointer __end = this->__end_; + if (__end < this->__end_cap()) { __construct_one_at_end(std::forward<_Args>(__args)...); + ++__end; + } else { + __end = __emplace_back_slow_path(std::forward<_Args>(__args)...); } - else - __emplace_back_slow_path(std::forward<_Args>(__args)...); + this->__end_ = __end; #if _LIBCPP_STD_VER >= 17 - return this->back(); + return *(__end - 1); #endif }