This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[patch] optimize std::list move constructor
- From: Jonathan Wakely <jwakely at redhat dot com>
- To: libstdc++ at gcc dot gnu dot org, gcc-patches at gcc dot gnu dot org
- Date: Thu, 7 Aug 2014 12:01:04 +0100
- Subject: [patch] optimize std::list move constructor
- Authentication-results: sourceware.org; auth=none
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 <jwakely@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>