Skip to content

Commit 7b78262

Browse files
committed
vector optimizations and disabled false GCC warning
1 parent 97c7295 commit 7b78262

3 files changed

Lines changed: 37 additions & 9 deletions

File tree

bench/bench_vector.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@
1212
//
1313
//////////////////////////////////////////////////////////////////////////////
1414

15+
#ifndef LONG_BENCH
16+
//#define LONG_BENCH
17+
#endif
18+
1519
#include <vector>
1620
#include <memory> //std::allocator
1721
#include <boost/container/vector.hpp>
@@ -23,7 +27,9 @@ void run_containers(runner<IntType, Operation>& r)
2327
{
2428
//First registered container is the baseline (denominator).
2529
r.template add< std::vector<IntType, std::allocator<IntType> > >("std::vector");
26-
r.template add< bc::vector<IntType, std::allocator<IntType> > >("vector");
30+
r.template add< bc::vector<IntType, std::allocator<IntType> > >("vector(1.6x)");
31+
typedef typename bc::vector_options < bc::growth_factor<bc::growth_factor_100> >::type growth_100_t;
32+
r.template add< bc::vector<IntType, std::allocator<IntType>, growth_100_t> >("vector(2x)");
2733
}
2834

2935
int main()

include/boost/container/detail/copy_move_algo.hpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -535,11 +535,22 @@ inline typename dtl::disable_if_memtransfer_copy_constructible<I, F, F>::type
535535
{
536536
F back = r;
537537
BOOST_CONTAINER_TRY{
538+
//GCC's value-range analysis issues a spurious -Wmaybe-uninitialized here
539+
//when this copy-construct loop is inlined into a fixed-capacity container's
540+
//(e.g. static_vector) copy constructor after a near-end single-element
541+
//insert: it cannot prove the just-built trailing slot is initialized.
542+
#if defined(BOOST_GCC) && (BOOST_GCC >= 40600)
543+
#pragma GCC diagnostic push
544+
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
545+
#endif
538546
while (n) {
539547
--n;
540548
allocator_traits<Allocator>::construct(a, boost::movelib::iterator_to_raw_pointer(r), *f);
541549
++f; ++r;
542550
}
551+
#if defined(BOOST_GCC) && (BOOST_GCC >= 40600)
552+
#pragma GCC diagnostic pop
553+
#endif
543554
}
544555
BOOST_CONTAINER_CATCH(...){
545556
for (; back != r; ++back){

include/boost/container/vector.hpp

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1938,17 +1938,21 @@ class vector
19381938
template<class ...Args>
19391939
inline reference emplace_back(BOOST_FWD_REF(Args)...args)
19401940
{
1941-
T* const p = this->priv_raw_end();
19421941
if (BOOST_LIKELY(this->room_enough())){
1943-
//There is more memory, just construct a new object at the end
1942+
//There is more memory, just construct a new object at the end.
1943+
//Deriving the end pointer inside this branch (instead of before the
1944+
//room_enough() test, where the slow path would also use it) lets the
1945+
//optimizer fold 'start + size' into the store's addressing mode and
1946+
//keep size as the sole induction variable in append loops.
1947+
T* const p = this->priv_raw_end();
19441948
allocator_traits_type::construct(this->m_holder.alloc(), p, ::boost::forward<Args>(args)...);
19451949
++this->m_holder.m_size;
19461950
return *p;
19471951
}
19481952
else{
19491953
typedef dtl::insert_emplace_proxy<allocator_type, Args...> proxy_t;
19501954
return *this->priv_insert_forward_range_no_capacity
1951-
(p, 1, proxy_t(::boost::forward<Args>(args)...), alloc_version());
1955+
(this->priv_raw_end(), 1, proxy_t(::boost::forward<Args>(args)...), alloc_version());
19521956
}
19531957
}
19541958

@@ -2019,17 +2023,20 @@ class vector
20192023
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
20202024
inline reference emplace_back(BOOST_MOVE_UREF##N)\
20212025
{\
2022-
T* const p = this->priv_raw_end();\
20232026
if (BOOST_LIKELY(this->room_enough())){\
2027+
/*Derive the end pointer inside this branch so the optimizer can fold*/\
2028+
/*'start + size' into the store and keep size as the sole induction*/\
2029+
/*variable in append loops (the slow path recomputes it).*/\
2030+
T* const p = this->priv_raw_end();\
20242031
allocator_traits_type::construct (this->m_holder.alloc()\
2025-
, this->priv_raw_end() BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
2032+
, p BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
20262033
++this->m_holder.m_size;\
20272034
return *p;\
20282035
}\
20292036
else{\
20302037
typedef dtl::insert_emplace_proxy_arg##N<allocator_type BOOST_MOVE_I##N BOOST_MOVE_TARG##N> proxy_t;\
20312038
return *this->priv_insert_forward_range_no_capacity\
2032-
( p, 1, proxy_t(BOOST_MOVE_FWD##N), alloc_version());\
2039+
( this->priv_raw_end(), 1, proxy_t(BOOST_MOVE_FWD##N), alloc_version());\
20332040
}\
20342041
}\
20352042
\
@@ -3335,8 +3342,12 @@ class vector
33353342
//There is enough memory
33363343
T* const old_finish = this->priv_raw_end();
33373344
allocator_type & a = this->m_holder.alloc();
3345+
//Number of trailing elements [raw_pos, old_finish). Expressing the shift
3346+
//length against the end pointer (n_after - 1) lets the compiler bound and
3347+
//fold a near-end shift to inline moves instead of an out-of-line memmove.
3348+
const size_type n_after = size_type(old_finish - raw_pos);
33383349

3339-
if (old_finish == raw_pos){
3350+
if (!n_after){
33403351
insert_range_proxy.uninitialized_copy_n_and_update(a, old_finish, 1);
33413352
++this->m_holder.m_size;
33423353
}
@@ -3348,7 +3359,7 @@ class vector
33483359
allocator_traits_type::construct(a, old_finish, ::boost::move(*before_old_finish));
33493360
++this->m_holder.m_size;
33503361
//Copy previous to last objects to the initialized end
3351-
boost::container::move_backward(raw_pos, before_old_finish, old_finish);
3362+
boost::container::move_backward_n(before_old_finish, n_after - 1u, old_finish);
33523363
//Insert new objects in the raw_pos
33533364
insert_range_proxy.copy_n_and_update(a, raw_pos, 1);
33543365
}

0 commit comments

Comments
 (0)