Implement a few optimizations for vector push_back and insert.  Fixes r10828365.

git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@150542 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/memory b/include/memory
index 0e14275..e841b2c 100644
--- a/include/memory
+++ b/include/memory
@@ -597,6 +597,7 @@
 #include <__functional_base>
 #include <iosfwd>
 #include <tuple>
+#include <cstring>
 #if defined(_LIBCPP_NO_EXCEPTIONS)
     #include <cassert>
 #endif
@@ -1395,6 +1396,14 @@
 {
 };
 
+#else  // _LIBCPP_HAS_NO_VARIADICS
+
+template <class _Alloc, class _Pointer, class _Args>
+struct __has_construct
+    : false_type
+{
+};
+
 #endif  // _LIBCPP_HAS_NO_VARIADICS
 
 template <class _Alloc, class _Pointer>
@@ -1524,6 +1533,60 @@
                 __has_select_on_container_copy_construction<const allocator_type>(),
                 __a);}
 
+    template <class _Ptr>
+        _LIBCPP_INLINE_VISIBILITY
+        static
+        void
+        __construct_forward(allocator_type& __a, _Ptr __begin1, _Ptr __end1, _Ptr& __begin2)
+        {
+            for (; __begin1 != __end1; ++__begin1, ++__begin2)
+                construct(__a, _VSTD::__to_raw_pointer(__begin2), _VSTD::move_if_noexcept(*__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_forward(allocator_type& __a, _Tp* __begin1, _Tp* __end1, _Tp*& __begin2)
+        {
+            ptrdiff_t _Np = __end1 - __begin1;
+            _VSTD::memcpy(__begin2, __begin1, _Np * sizeof(_Tp));
+            __begin2 += _Np;
+        }
+
+    template <class _Ptr>
+        _LIBCPP_INLINE_VISIBILITY
+        static
+        void
+        __construct_backward(allocator_type& __a, _Ptr __begin1, _Ptr __end1, _Ptr& __end2)
+        {
+            while (__end1 != __begin1)
+                construct(__a, _VSTD::__to_raw_pointer(--__end2), _VSTD::move_if_noexcept(*--__end1));
+        }
+
+    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_backward(allocator_type& __a, _Tp* __begin1, _Tp* __end1, _Tp*& __end2)
+        {
+            ptrdiff_t _Np = __end1 - __begin1;
+            __end2 -= _Np;
+            _VSTD::memcpy(__end2, __begin1, _Np * sizeof(_Tp));
+        }
+
 private:
 
     _LIBCPP_INLINE_VISIBILITY