summaryrefslogtreecommitdiff
path: root/include/memory
diff options
context:
space:
mode:
authorEric Fiselier <eric@efcs.ca>2015-03-31 16:54:19 +0000
committerEric Fiselier <eric@efcs.ca>2015-03-31 16:54:19 +0000
commit088ed9fe946997f94682ee53d586b8c3d118e211 (patch)
tree6038b79fb1f25f58e5827930561e7d3b6ffc4f2b /include/memory
parentbf9653d85f05b945ed5e2a79f1c93b16e064e054 (diff)
[libcxx] Optimize vectors uninitialized construction of trivial types from an iterator range.
Summary: In certain cases vector can use memcpy to construct a range of elements at the back of the vector. We currently don't do this resulting in terrible code gen in non-optimized mode and a very large slowdown compared to libstdc++. This patch adds a `__construct_forward_range(Allocator, Iter, Iter, _Ptr&)` and `__construct_forward_range(Allocator, Tp*, Tp*, Tp*&)` functions to `allocator_traits` which act similarly to the existing `__construct_forward(...)` functions. This patch also changes vectors `__construct_at_end(Iter, Iter)` to be `__construct_at_end(Iter, Iter, SizeType)` where SizeType is the size of the range. `__construct_at_end(Iter, Iter, SizeType)` now calls `allocator_traits<Tp>::__construct_forward_range(...)`. This patch is based off the design of `__swap_out_circular_buffer(...)` which uses `allocator_traits<Tp>::__construct_forward(...)`. On my machine this code performs 4x better than the current implementation when tested against `std::vector<int>`. Reviewers: howard.hinnant, titus, kcc, mclow.lists Reviewed By: mclow.lists Subscribers: cfe-commits Differential Revision: http://reviews.llvm.org/D8109 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@233711 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include/memory')
-rw-r--r--include/memory28
1 files changed, 28 insertions, 0 deletions
diff --git a/include/memory b/include/memory
index 7085cedad..43f8dbada 100644
--- a/include/memory
+++ b/include/memory
@@ -1525,6 +1525,34 @@ struct _LIBCPP_TYPE_VIS_ONLY allocator_traits
__begin2 += _Np;
}
+ template <class _Iter, class _Ptr>
+ _LIBCPP_INLINE_VISIBILITY
+ static
+ void
+ __construct_range_forward(allocator_type& __a, _Iter __begin1, _Iter __end1, _Ptr& __begin2)
+ {
+ for (; __begin1 != __end1; ++__begin1, (void) ++__begin2)
+ construct(__a, _VSTD::__to_raw_pointer(__begin2), *__begin1);
+ }
+
+ template <class _Tp>
+ _LIBCPP_INLINE_VISIBILITY
+ static
+ typename enable_if
+ <
+ (is_same<allocator_type, allocator<_Tp> >::value
+ || !__has_construct<allocator_type, _Tp*, _Tp>::value) &&
+ is_trivially_move_constructible<_Tp>::value,
+ void
+ >::type
+ __construct_range_forward(allocator_type& __a, _Tp* __begin1, _Tp* __end1, _Tp*& __begin2)
+ {
+ typedef typename remove_const<_Tp>::type _Vp;
+ ptrdiff_t _Np = __end1 - __begin1;
+ _VSTD::memcpy(const_cast<_Vp*>(__begin2), __begin1, _Np * sizeof(_Tp));
+ __begin2 += _Np;
+ }
+
template <class _Ptr>
_LIBCPP_INLINE_VISIBILITY
static