While preparing the initial commit for the std::list ABI transition I noticed the move constructor does unnecessary work, initializing the object to an empty state, then calling _List_node_base::swap which checks whether it's empty (but we already know it is) and then initializes it again. The _List_node_base::swap function is a call into libstdc++.so so can't be inlined or otherwise optimized.
This patch changes the move constructor to avoid unnecessary checking and redundant initializations. The code size increases for -Os, but on my laptop the following silly test goes from 8s to 4.5s with -O3, and from 10.5s to 8.5s with -Os, so I think it's worthwhile: #include <list> int main() { std::list<int> l1; for (long i = 0; i < 1000000000; ++i) { std::list<int> l2 = std::move(l1); l1 = std::move(l2); } } I intend to commit this to trunk later today.
commit f71c29dc7e025e8065f759cfc89bdeab5f3964f9 Author: Jonathan Wakely <jwak...@redhat.com> Date: Thu Aug 7 10:59:47 2014 +0100 * include/bits/stl_list.h (_List_base::_List_base(_List_base&&)): Optimize. * testsuite/23_containers/list/requirements/dr438/assign_neg.cc: Adjust dg-error line number. * testsuite/23_containers/list/requirements/dr438/constructor_1_neg.cc: Likewise. * testsuite/23_containers/list/requirements/dr438/constructor_2_neg.cc: Likewise. * testsuite/23_containers/list/requirements/dr438/insert_neg.cc: Likewise. diff --git a/libstdc++-v3/include/bits/stl_list.h b/libstdc++-v3/include/bits/stl_list.h index e014fbc..dd9bba7 100644 --- a/libstdc++-v3/include/bits/stl_list.h +++ b/libstdc++-v3/include/bits/stl_list.h @@ -377,8 +377,17 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _List_base(_List_base&& __x) noexcept : _M_impl(std::move(__x._M_get_Node_allocator())) { - _M_init(); - __detail::_List_node_base::swap(_M_impl._M_node, __x._M_impl._M_node); + auto* const __xnode = std::__addressof(__x._M_impl._M_node); + if (__xnode->_M_next == __xnode) + _M_init(); + else + { + auto* const __node = std::__addressof(_M_impl._M_node); + __node->_M_next = __xnode->_M_next; + __node->_M_prev = __xnode->_M_prev; + __node->_M_next->_M_prev = __node->_M_prev->_M_next = __node; + __xnode->_M_next = __xnode->_M_prev = __xnode; + } } #endif diff --git a/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/assign_neg.cc b/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/assign_neg.cc index 7c29a2d..885e753 100644 --- a/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/assign_neg.cc +++ b/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/assign_neg.cc @@ -18,7 +18,7 @@ // <http://www.gnu.org/licenses/>. // { dg-do compile } -// { dg-error "no matching" "" { target *-*-* } 1656 } +// { dg-error "no matching" "" { target *-*-* } 1665 } #include <list> diff --git a/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/constructor_1_neg.cc b/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/constructor_1_neg.cc index 382d985..ccd9d17 100644 --- a/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/constructor_1_neg.cc +++ b/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/constructor_1_neg.cc @@ -18,7 +18,7 @@ // <http://www.gnu.org/licenses/>. // { dg-do compile } -// { dg-error "no matching" "" { target *-*-* } 1608 } +// { dg-error "no matching" "" { target *-*-* } 1617 } #include <list> diff --git a/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/constructor_2_neg.cc b/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/constructor_2_neg.cc index 14585af..04966dc 100644 --- a/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/constructor_2_neg.cc +++ b/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/constructor_2_neg.cc @@ -18,7 +18,7 @@ // <http://www.gnu.org/licenses/>. // { dg-do compile } -// { dg-error "no matching" "" { target *-*-* } 1608 } +// { dg-error "no matching" "" { target *-*-* } 1617 } #include <list> #include <utility> diff --git a/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/insert_neg.cc b/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/insert_neg.cc index a9f9f30..759dad6 100644 --- a/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/insert_neg.cc +++ b/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/insert_neg.cc @@ -18,7 +18,7 @@ // <http://www.gnu.org/licenses/>. // { dg-do compile } -// { dg-error "no matching" "" { target *-*-* } 1608 } +// { dg-error "no matching" "" { target *-*-* } 1617 } #include <list>