diff options
author | Eric Fiselier <eric@efcs.ca> | 2019-08-12 07:51:05 +0000 |
---|---|---|
committer | Eric Fiselier <eric@efcs.ca> | 2019-08-12 07:51:05 +0000 |
commit | b0945e1bd2e2d7ac6dd8152e479a56db302d981e (patch) | |
tree | dc9395039df5dd3272da9cc49c1f4e7b244a0cc1 /libcxx/include/__split_buffer | |
parent | fd5ea1b0d904dc8f9793fcdf7699d10009f6a45f (diff) | |
download | bcm5719-llvm-b0945e1bd2e2d7ac6dd8152e479a56db302d981e.tar.gz bcm5719-llvm-b0945e1bd2e2d7ac6dd8152e479a56db302d981e.zip |
Improve codegen for deque.
This patch rewrites a few loops in deque and split_buffer to better
optimize the codegen. For constructors like
`deque<unsigned char> d(500000, 0);` this patch results in a 2x speedup.
The patch improves the codegen in roughly three ways:
1. Changes do { ... } while (...) loops into more typical for loops.
The optimizer can reason about normal looking loops better.
2. Split the iteration over a range into (A) iteration over the blocks,
then (B) iteration within the block. This nested structure helps LLVM
lower the inner loop to `memset`.
3. Do fewer things each iteration. Some of these loops were incrementing
or changing 4-5 variables every loop (in addition to the
construction). Previously most loops would increment the end pointer,
the size, and decrement the count of remaining items to construct.
Now we only increment a single pointer for most iterations.
llvm-svn: 368547
Diffstat (limited to 'libcxx/include/__split_buffer')
-rw-r--r-- | libcxx/include/__split_buffer | 45 |
1 files changed, 26 insertions, 19 deletions
diff --git a/libcxx/include/__split_buffer b/libcxx/include/__split_buffer index 1daa4e5ada3..095fe8928c6 100644 --- a/libcxx/include/__split_buffer +++ b/libcxx/include/__split_buffer @@ -161,6 +161,19 @@ private: _LIBCPP_INLINE_VISIBILITY void __move_assign_alloc(__split_buffer&, false_type) _NOEXCEPT {} + + struct _ConstructTransaction { + explicit _ConstructTransaction(pointer* __p, size_type __n) _NOEXCEPT + : __pos_(*__p), __end_(*__p + __n), __dest_(__p) { + } + ~_ConstructTransaction() { + *__dest_ = __pos_; + } + pointer __pos_; + const pointer __end_; + private: + pointer *__dest_; + }; }; template <class _Tp, class _Allocator> @@ -197,13 +210,10 @@ template <class _Tp, class _Allocator> void __split_buffer<_Tp, _Allocator>::__construct_at_end(size_type __n) { - __alloc_rr& __a = this->__alloc(); - do - { - __alloc_traits::construct(__a, _VSTD::__to_raw_pointer(this->__end_)); - ++this->__end_; - --__n; - } while (__n > 0); + _ConstructTransaction __tx(&this->__end_, __n); + for (; __tx.__pos_ != __tx.__end_; ++__tx.__pos_) { + __alloc_traits::construct(this->__alloc(), _VSTD::__to_raw_pointer(__tx.__pos_)); + } } // Copy constructs __n objects starting at __end_ from __x @@ -216,13 +226,11 @@ template <class _Tp, class _Allocator> void __split_buffer<_Tp, _Allocator>::__construct_at_end(size_type __n, const_reference __x) { - __alloc_rr& __a = this->__alloc(); - do - { - __alloc_traits::construct(__a, _VSTD::__to_raw_pointer(this->__end_), __x); - ++this->__end_; - --__n; - } while (__n > 0); + _ConstructTransaction __tx(&this->__end_, __n); + for (; __tx.__pos_ != __tx.__end_; ++__tx.__pos_) { + __alloc_traits::construct(this->__alloc(), + _VSTD::__to_raw_pointer(__tx.__pos_), __x); + } } template <class _Tp, class _Allocator> @@ -262,11 +270,10 @@ typename enable_if >::type __split_buffer<_Tp, _Allocator>::__construct_at_end(_ForwardIterator __first, _ForwardIterator __last) { - __alloc_rr& __a = this->__alloc(); - for (; __first != __last; ++__first) - { - __alloc_traits::construct(__a, _VSTD::__to_raw_pointer(this->__end_), *__first); - ++this->__end_; + _ConstructTransaction __tx(&this->__end_, std::distance(__first, __last)); + for (; __tx.__pos_ != __tx.__end_; ++__tx.__pos_, ++__first) { + __alloc_traits::construct(this->__alloc(), + _VSTD::__to_raw_pointer(__tx.__pos_), *__first); } } |