std::vector<bool> code cleanup fixes optimizations

Jonathan Wakely jwakely@redhat.com
Fri Jul 17 10:36:54 GMT 2020


On 16/12/19 08:18 +0100, François Dumont wrote:
>A small refresh on this patch now tested also for versioned namespace 
>which require printers.py to be updated.
>
>Note that this simplification works also for normal mode so I can 
>apply it independently from the stl_bvector.h part.
>
>
>    * include/bits/stl_bvector.h
>    [_GLIBCXX_INLINE_VERSION](_Bvector_impl_data::_M_start): Define as
>    _Bit_type*.
>    (_Bvector_impl_data(const _Bvector_impl_data&)): Default.
>    (_Bvector_impl_data(_Bvector_impl_data&&)): Delegate to latter.
>    (_Bvector_impl_data::operator=(const _Bvector_impl_data&)): Default.
>(_Bvector_impl_data::_M_move_data(_Bvector_impl_data&&)): Use latter.
>    (_Bvector_impl_data::_M_reset()): Likewise.
>    (_Bvector_impl_data::_M_swap_data): New.
>    (_Bvector_impl::_Bvector_impl(_Bvector_impl&&)): Implement explicitely.
>    (_Bvector_impl::_Bvector_impl(_Bit_alloc_type&&, 
>_Bvector_impl&&)): New.
>    (_Bvector_base::_Bvector_base(_Bvector_base&&, const allocator_type&)):
>    New, use latter.
>    (vector::vector(vector&&, const allocator_type&, true_type)): New, use
>    latter.
>    (vector::vector(vector&&, const allocator_type&, false_type)): New.
>    (vector::vector(vector&&, const allocator_type&)): Use latters.
>    (vector::vector(const vector&, const allocator_type&)): Adapt.
>    [__cplusplus >= 201103](vector::vector(_InputIt, _InputIt,
>    const allocator_type&)): Use _M_initialize_range.
>    (vector::operator[](size_type)): Use iterator operator[].
>    (vector::operator[](size_type) const): Use const_iterator operator[].
>    (vector::swap(vector&)): Add assertions on allocators. Use 
>_M_swap_data.
>    [__cplusplus >= 201103](vector::insert(const_iterator, _InputIt,
>    _InputIt)): Use _M_insert_range.
>    (vector::_M_initialize(size_type)): Adapt.
>    [__cplusplus >= 201103](vector::_M_initialize_dispatch): Remove.
>    [__cplusplus >= 201103](vector::_M_insert_dispatch): Remove.
>    * python/libstdcxx/v6/printers.py (StdVectorPrinter._iterator): Stop
>    using start _M_offset.
>    (StdVectorPrinter.to_string): Likewise.
>    * testsuite/23_containers/vector/bool/allocator/swap.cc: Adapt.
>    * testsuite/23_containers/vector/bool/cons/noexcept_move_construct.cc:
>    Add check.
>
>François
>
>
>On 6/24/19 9:31 PM, François Dumont wrote:
>>Hi
>>
>>    Any feedback regarding this patch ?
>>
>>Thanks
>>
>>On 5/14/19 7:46 AM, François Dumont wrote:
>>>Hi
>>>
>>>    This is the patch on vector<bool> to:
>>>
>>>- Optimize sizeof in Versioned namespace mode. We could go one 
>>>step further by removing _M_p from _M_finish and just transform it 
>>>into an offset but it is a little bit more impacting for the code.
>>>
>>>- Implement the swap optimization already done on main std::vector 
>>>template class.
>>>
>>>- Fix move constructor so that it is noexcept no matter allocator 
>>>move constructor noexcept qualification
>>>
>>>- Optimize move constructor with allocator when allocator type is 
>>>always equal.
>>>
>>>- Use shortcuts in C++11 by skipping the _M_XXX_dispatch methods. 
>>>Those are now defined only in pre-C++11 mode, I can't see any abi 
>>>issue in doing so.
>>>
>>>    * include/bits/stl_bvector.h
>>>    [_GLIBCXX_INLINE_VERSION](_Bvector_impl_data::_M_start): Define as
>>>    _Bit_type*.
>>>    (_Bvector_impl_data(const _Bvector_impl_data&)): Default.
>>>    (_Bvector_impl_data(_Bvector_impl_data&&)): Delegate to latter.
>>>    (_Bvector_impl_data::operator=(const _Bvector_impl_data&)): Default.
>>>(_Bvector_impl_data::_M_move_data(_Bvector_impl_data&&)): Use latter.
>>>    (_Bvector_impl_data::_M_reset()): Likewise.
>>>    (_Bvector_impl_data::_M_swap_data): New.
>>>    (_Bvector_impl::_Bvector_impl(_Bvector_impl&&)): Implement 
>>>explicitely.
>>>    (_Bvector_impl::_Bvector_impl(_Bit_alloc_type&&, 
>>>_Bvector_impl&&)): New.
>>>    (_Bvector_base::_Bvector_base(_Bvector_base&&, const 
>>>allocator_type&)):
>>>    New, use latter.
>>>    (vector::vector(vector&&, const allocator_type&, true_type)): 
>>>New, use
>>>    latter.
>>>    (vector::vector(vector&&, const allocator_type&, false_type)): New.
>>>    (vector::vector(vector&&, const allocator_type&)): Use latters.
>>>    (vector::vector(const vector&, const allocator_type&)): Adapt.
>>>    [__cplusplus >= 201103](vector::vector(_InputIt, _InputIt,
>>>    const allocator_type&)): Use _M_initialize_range.
>>>    (vector::operator[](size_type)): Use iterator operator[].
>>>    (vector::operator[](size_type) const): Use const_iterator 
>>>operator[].
>>>    (vector::swap(vector&)): Adapt.
>>>    (vector::_M_initialize(size_type)): Add assertions on allocators.
>>>    Use _M_swap_data.
>>>    [__cplusplus >= 201103](vector::insert(const_iterator, _InputIt,
>>>    _InputIt)): Use _M_insert_range.
>>>    [__cplusplus >= 201103](vector::_M_initialize_dispatch): Remove.
>>>    [__cplusplus >= 201103](vector::_M_insert_dispatch): Remove.
>>>    * testsuite/23_containers/vector/bool/allocator/swap.cc: Adapt.
>>>    * 
>>>testsuite/23_containers/vector/bool/cons/noexcept_move_construct.cc:
>>>    Add check.
>>>
>>>Tested under Linux x86_64, normal and debug modes.
>>>
>>>Ok to commit ?

Yes, OK for master, but I have one question below (and one minor
comment).

>diff --git a/libstdc++-v3/include/bits/stl_bvector.h b/libstdc++-v3/include/bits/stl_bvector.h
>index f2eea7799dc..15ecce62683 100644
>--- a/libstdc++-v3/include/bits/stl_bvector.h
>+++ b/libstdc++-v3/include/bits/stl_bvector.h
>@@ -449,7 +449,16 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
> 
>       struct _Bvector_impl_data
>       {
>+#if !_GLIBCXX_INLINE_VERSION
> 	_Bit_iterator	_M_start;
>+#else
>+	// We don't need the offset field for the start, it's always zero.
>+	struct {
>+	  _Bit_type* _M_p;
>+	  // Allow assignment from iterators (assume offset is zero):
>+	  void operator=(_Bit_iterator __it) { _M_p = __it._M_p; }
>+	} _M_start;
>+#endif
> 	_Bit_iterator	_M_finish;
> 	_Bit_pointer	_M_end_of_storage;
> 
>@@ -533,6 +555,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
> 
> #if __cplusplus >= 201103L
>       _Bvector_base(_Bvector_base&&) = default;
>+
>+      _Bvector_base(_Bvector_base&& __x, const allocator_type& __a)

I think you can add 'noexcept' here.

Constructing the _Bit_alloc_type can't throw, and the base constructor
is noexcept.

>+      : _M_impl(_Bit_alloc_type(__a), std::move(__x._M_impl))
>+      { }
> #endif
> 
>       ~_Bvector_base()


>diff --git a/libstdc++-v3/testsuite/23_containers/vector/bool/allocator/swap.cc b/libstdc++-v3/testsuite/23_containers/vector/bool/allocator/swap.cc
>index de441426532..745fdc85cf6 100644
>--- a/libstdc++-v3/testsuite/23_containers/vector/bool/allocator/swap.cc
>+++ b/libstdc++-v3/testsuite/23_containers/vector/bool/allocator/swap.cc
>@@ -28,19 +28,17 @@ namespace __gnu_test
>   // It is undefined behaviour to swap() containers with unequal allocators
>   // if the allocator doesn't propagate, so ensure the allocators compare
>   // equal, while still being able to test propagation via get_personality().
>+  template<typename Type>
>     bool
>-  operator==(const propagating_allocator<T, false>&,
>-	     const propagating_allocator<T, false>&)
>-  {
>-    return true;
>-  }
>+    operator==(const propagating_allocator<Type, false>&,
>+	       const propagating_allocator<Type, false>&)
>+    { return true; }
> 
>+  template<typename Type>
>     bool
>-  operator!=(const propagating_allocator<T, false>&,
>-	     const propagating_allocator<T, false>&)
>-  {
>-    return false;
>-  }
>+    operator!=(const propagating_allocator<Type, false>&,
>+	       const propagating_allocator<Type, false>&)
>+    { return false; }

Why does this test need to be adapted?



More information about the Libstdc++ mailing list