public inbox for libstdc++-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r12-4233] libstdc++: Avoid debug checks in uniform container erasure functions
@ 2021-10-07 16:52 Jonathan Wakely
0 siblings, 0 replies; only message in thread
From: Jonathan Wakely @ 2021-10-07 16:52 UTC (permalink / raw)
To: gcc-cvs, libstdc++-cvs
https://gcc.gnu.org/g:561078480ffb5adb68577276c6b23e4ee7b39272
commit r12-4233-g561078480ffb5adb68577276c6b23e4ee7b39272
Author: Jonathan Wakely <jwakely@redhat.com>
Date: Thu Oct 7 14:40:26 2021 +0100
libstdc++: Avoid debug checks in uniform container erasure functions
In commit r12-4083 I tried to make the std::erase and std::erase_if
function avoid the unnecessary overhead of safe iterators. It didn't
work, for two reasons. Firstly, for the RB tree containers the
__niter_base function is a no-op (because the iterators aren't
random access) so the safe iterators were still used. Secondly, for the
cases where __niter_base did remove the safe iterator layer, there was
still unnecessary overhead to create a new safe iterator and link it to
the container.
This solves the problem by simply binding a reference to the non-debug
version of the conainer. For normal mode this is a no-op, and for debug
mode it binds a reference to the debug container's base class. That
means the rest of the function operates directly on the non-debug
container, and avoids all checking.
For std::basic_string there's no need to unwrap anything, because we use
std::basic_string directly in debug mode anyway.
libstdc++-v3/ChangeLog:
* include/bits/erase_if.h (__erase_nodes_if): Remove redundant
__niter_base calls.
* include/std/string (erase, erase_if): Likewise.
* include/std/deque (erase, erase_if): Access non-debug
container directly.
* include/std/map (erase, erase_if): Likewise.
* include/std/set (erase, erase_if): Likewise.
* include/std/unordered_map (erase, erase_if): Likewise.
* include/std/unordered_set (erase, erase_if): Likewise.
* include/std/vector (erase, erase_if): Likewise.
* include/experimental/deque (erase, erase_if): Likewise.
* include/experimental/map (erase, erase_if): Likewise.
* include/experimental/set (erase, erase_if): Likewise.
* include/experimental/unordered_map (erase, erase_if):
Likewise.
* include/experimental/unordered_set (erase, erase_if):
Likewise.
* include/experimental/vector (erase, erase_if): Likewise.
Diff:
---
libstdc++-v3/include/bits/erase_if.h | 3 +--
libstdc++-v3/include/experimental/deque | 8 +++----
libstdc++-v3/include/experimental/map | 10 +++++++--
libstdc++-v3/include/experimental/set | 10 +++++++--
libstdc++-v3/include/experimental/unordered_map | 12 +++++++++--
libstdc++-v3/include/experimental/unordered_set | 11 ++++++++--
libstdc++-v3/include/experimental/vector | 8 +++----
libstdc++-v3/include/std/deque | 28 ++++++++++++-------------
libstdc++-v3/include/std/map | 10 +++++++--
libstdc++-v3/include/std/set | 10 +++++++--
libstdc++-v3/include/std/string | 18 +++++++---------
libstdc++-v3/include/std/unordered_map | 12 +++++++++--
libstdc++-v3/include/std/unordered_set | 11 ++++++++--
libstdc++-v3/include/std/vector | 26 +++++++++++------------
14 files changed, 114 insertions(+), 63 deletions(-)
diff --git a/libstdc++-v3/include/bits/erase_if.h b/libstdc++-v3/include/bits/erase_if.h
index 7716e1a953c..8d1d23168fa 100644
--- a/libstdc++-v3/include/bits/erase_if.h
+++ b/libstdc++-v3/include/bits/erase_if.h
@@ -51,8 +51,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__erase_nodes_if(_Container& __cont, _Predicate __pred)
{
typename _Container::size_type __num = 0;
- for (auto __iter = std::__niter_base(__cont.begin()),
- __last = std::__niter_base(__cont.end());
+ for (auto __iter = __cont.begin(), __last = __cont.end();
__iter != __last;)
{
if (__pred(*__iter))
diff --git a/libstdc++-v3/include/experimental/deque b/libstdc++-v3/include/experimental/deque
index a76fb659bbf..710833ebcad 100644
--- a/libstdc++-v3/include/experimental/deque
+++ b/libstdc++-v3/include/experimental/deque
@@ -50,16 +50,16 @@ inline namespace fundamentals_v2
inline void
erase_if(deque<_Tp, _Alloc>& __cont, _Predicate __pred)
{
- __cont.erase(std::remove_if(__cont.begin(), __cont.end(), __pred),
- __cont.end());
+ _GLIBCXX_STD_C::deque<_Tp, _Alloc>& __c = __cont;
+ __c.erase(std::remove_if(__c.begin(), __c.end(), __pred), __c.end());
}
template<typename _Tp, typename _Alloc, typename _Up>
inline void
erase(deque<_Tp, _Alloc>& __cont, const _Up& __value)
{
- __cont.erase(std::remove(__cont.begin(), __cont.end(), __value),
- __cont.end());
+ _GLIBCXX_STD_C::deque<_Tp, _Alloc>& __c = __cont;
+ __c.erase(std::remove(__c.begin(), __c.end(), __value), __c.end());
}
namespace pmr {
diff --git a/libstdc++-v3/include/experimental/map b/libstdc++-v3/include/experimental/map
index 0c0f42222f5..ef69fadf944 100644
--- a/libstdc++-v3/include/experimental/map
+++ b/libstdc++-v3/include/experimental/map
@@ -50,13 +50,19 @@ inline namespace fundamentals_v2
typename _Predicate>
inline void
erase_if(map<_Key, _Tp, _Compare, _Alloc>& __cont, _Predicate __pred)
- { std::__detail::__erase_nodes_if(__cont, __pred); }
+ {
+ _GLIBCXX_STD_C::map<_Key, _Tp, _Compare, _Alloc>& __c = __cont;
+ std::__detail::__erase_nodes_if(__c, __pred);
+ }
template<typename _Key, typename _Tp, typename _Compare, typename _Alloc,
typename _Predicate>
inline void
erase_if(multimap<_Key, _Tp, _Compare, _Alloc>& __cont, _Predicate __pred)
- { std::__detail::__erase_nodes_if(__cont, __pred); }
+ {
+ _GLIBCXX_STD_C::multimap<_Key, _Tp, _Compare, _Alloc>& __c = __cont;
+ std::__detail::__erase_nodes_if(__c, __pred);
+ }
namespace pmr {
template<typename _Key, typename _Tp, typename _Compare = less<_Key>>
diff --git a/libstdc++-v3/include/experimental/set b/libstdc++-v3/include/experimental/set
index c3f5433e995..7a5986aec0e 100644
--- a/libstdc++-v3/include/experimental/set
+++ b/libstdc++-v3/include/experimental/set
@@ -50,13 +50,19 @@ inline namespace fundamentals_v2
typename _Predicate>
inline void
erase_if(set<_Key, _Compare, _Alloc>& __cont, _Predicate __pred)
- { std::__detail::__erase_nodes_if(__cont, __pred); }
+ {
+ _GLIBCXX_STD_C::set<_Key, _Compare, _Alloc>& __c = __cont;
+ std::__detail::__erase_nodes_if(__c, __pred);
+ }
template<typename _Key, typename _Compare, typename _Alloc,
typename _Predicate>
inline void
erase_if(multiset<_Key, _Compare, _Alloc>& __cont, _Predicate __pred)
- { std::__detail::__erase_nodes_if(__cont, __pred); }
+ {
+ _GLIBCXX_STD_C::multiset<_Key, _Compare, _Alloc>& __c = __cont;
+ std::__detail::__erase_nodes_if(__c, __pred);
+ }
namespace pmr {
template<typename _Key, typename _Compare = less<_Key>>
diff --git a/libstdc++-v3/include/experimental/unordered_map b/libstdc++-v3/include/experimental/unordered_map
index 0b915ab13e5..eba989713fa 100644
--- a/libstdc++-v3/include/experimental/unordered_map
+++ b/libstdc++-v3/include/experimental/unordered_map
@@ -51,14 +51,22 @@ inline namespace fundamentals_v2
inline void
erase_if(unordered_map<_Key, _Tp, _Hash, _CPred, _Alloc>& __cont,
_Predicate __pred)
- { std::__detail::__erase_nodes_if(__cont, __pred); }
+ {
+ _GLIBCXX_STD_C::unordered_map<_Key, _Tp, _Hash, _CPred, _Alloc>& __c
+ = __cont;
+ std::__detail::__erase_nodes_if(__c, __pred);
+ }
template<typename _Key, typename _Tp, typename _Hash, typename _CPred,
typename _Alloc, typename _Predicate>
inline void
erase_if(unordered_multimap<_Key, _Tp, _Hash, _CPred, _Alloc>& __cont,
_Predicate __pred)
- { std::__detail::__erase_nodes_if(__cont, __pred); }
+ {
+ _GLIBCXX_STD_C::unordered_multimap<_Key, _Tp, _Hash, _CPred, _Alloc>& __c
+ = __cont;
+ std::__detail::__erase_nodes_if(__c, __pred);
+ }
namespace pmr {
template<typename _Key, typename _Tp, typename _Hash = hash<_Key>,
diff --git a/libstdc++-v3/include/experimental/unordered_set b/libstdc++-v3/include/experimental/unordered_set
index 87db4464401..bc5cc11419e 100644
--- a/libstdc++-v3/include/experimental/unordered_set
+++ b/libstdc++-v3/include/experimental/unordered_set
@@ -51,14 +51,21 @@ inline namespace fundamentals_v2
inline void
erase_if(unordered_set<_Key, _Hash, _CPred, _Alloc>& __cont,
_Predicate __pred)
- { std::__detail::__erase_nodes_if(__cont, __pred); }
+ {
+ _GLIBCXX_STD_C::unordered_set<_Key, _Hash, _CPred, _Alloc>& __c = __cont;
+ std::__detail::__erase_nodes_if(__c, __pred);
+ }
template<typename _Key, typename _Hash, typename _CPred, typename _Alloc,
typename _Predicate>
inline void
erase_if(unordered_multiset<_Key, _Hash, _CPred, _Alloc>& __cont,
_Predicate __pred)
- { std::__detail::__erase_nodes_if(__cont, __pred); }
+ {
+ _GLIBCXX_STD_C::unordered_multiset<_Key, _Hash, _CPred, _Alloc>& __c
+ = __cont;
+ std::__detail::__erase_nodes_if(__c, __pred);
+ }
namespace pmr {
template<typename _Key, typename _Hash = hash<_Key>,
diff --git a/libstdc++-v3/include/experimental/vector b/libstdc++-v3/include/experimental/vector
index a14aedf3364..c45a500ef5e 100644
--- a/libstdc++-v3/include/experimental/vector
+++ b/libstdc++-v3/include/experimental/vector
@@ -52,16 +52,16 @@ inline namespace fundamentals_v2
inline void
erase_if(vector<_Tp, _Alloc>& __cont, _Predicate __pred)
{
- __cont.erase(std::remove_if(__cont.begin(), __cont.end(), __pred),
- __cont.end());
+ _GLIBCXX_STD_C::vector<_Tp, _Alloc>& __c = __cont;
+ __c.erase(std::remove_if(__c.begin(), __c.end(), __pred), __c.end());
}
template<typename _Tp, typename _Alloc, typename _Up>
inline void
erase(vector<_Tp, _Alloc>& __cont, const _Up& __value)
{
- __cont.erase(std::remove(__cont.begin(), __cont.end(), __value),
- __cont.end());
+ _GLIBCXX_STD_C::vector<_Tp, _Alloc>& __c = __cont;
+ __c.erase(std::remove(__c.begin(), __c.end(), __value), __c.end());
}
namespace pmr {
diff --git a/libstdc++-v3/include/std/deque b/libstdc++-v3/include/std/deque
index b2a7cee483a..71993e757a5 100644
--- a/libstdc++-v3/include/std/deque
+++ b/libstdc++-v3/include/std/deque
@@ -95,28 +95,28 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
inline typename deque<_Tp, _Alloc>::size_type
erase_if(deque<_Tp, _Alloc>& __cont, _Predicate __pred)
{
+ _GLIBCXX_STD_C::deque<_Tp, _Alloc>& __c = __cont;
using namespace __gnu_cxx;
- const auto __osz = __cont.size();
- const auto __end = __cont.end();
- auto __removed(std::__remove_if(std::__niter_base(__cont.begin()),
- std::__niter_base(__end),
- __ops::__pred_iter(std::ref(__pred))));
- __cont.erase(std::__niter_wrap(__end, __removed), __end);
- return __osz - __cont.size();
+ const auto __osz = __c.size();
+ const auto __end = __c.end();
+ auto __removed = std::__remove_if(__c.begin(), __end,
+ __ops::__pred_iter(std::ref(__pred)));
+ __c.erase(__removed, __end);
+ return __osz - __c.size();
}
template<typename _Tp, typename _Alloc, typename _Up>
inline typename deque<_Tp, _Alloc>::size_type
erase(deque<_Tp, _Alloc>& __cont, const _Up& __value)
{
+ _GLIBCXX_STD_C::deque<_Tp, _Alloc>& __c = __cont;
using namespace __gnu_cxx;
- const auto __osz = __cont.size();
- const auto __end = __cont.end();
- auto __removed(std::__remove_if(std::__niter_base(__cont.begin()),
- std::__niter_base(__end),
- __ops::__iter_equals_val(__value)));
- __cont.erase(std::__niter_wrap(__end, __removed), __end);
- return __osz - __cont.size();
+ const auto __osz = __c.size();
+ const auto __end = __c.end();
+ auto __removed = std::__remove_if(__c.begin(), __end,
+ __ops::__iter_equals_val(__value));
+ __c.erase(__removed, __end);
+ return __osz - __c.size();
}
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
diff --git a/libstdc++-v3/include/std/map b/libstdc++-v3/include/std/map
index 44bd44b5922..29265580995 100644
--- a/libstdc++-v3/include/std/map
+++ b/libstdc++-v3/include/std/map
@@ -95,13 +95,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typename _Predicate>
inline typename map<_Key, _Tp, _Compare, _Alloc>::size_type
erase_if(map<_Key, _Tp, _Compare, _Alloc>& __cont, _Predicate __pred)
- { return __detail::__erase_nodes_if(__cont, __pred); }
+ {
+ _GLIBCXX_STD_C::map<_Key, _Tp, _Compare, _Alloc>& __c = __cont;
+ return __detail::__erase_nodes_if(__c, __pred);
+ }
template<typename _Key, typename _Tp, typename _Compare, typename _Alloc,
typename _Predicate>
inline typename multimap<_Key, _Tp, _Compare, _Alloc>::size_type
erase_if(multimap<_Key, _Tp, _Compare, _Alloc>& __cont, _Predicate __pred)
- { return __detail::__erase_nodes_if(__cont, __pred); }
+ {
+ _GLIBCXX_STD_C::multimap<_Key, _Tp, _Compare, _Alloc>& __c = __cont;
+ return __detail::__erase_nodes_if(__c, __pred);
+ }
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // C++20
diff --git a/libstdc++-v3/include/std/set b/libstdc++-v3/include/std/set
index f1e1864937a..24e6e633624 100644
--- a/libstdc++-v3/include/std/set
+++ b/libstdc++-v3/include/std/set
@@ -91,13 +91,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typename _Predicate>
inline typename set<_Key, _Compare, _Alloc>::size_type
erase_if(set<_Key, _Compare, _Alloc>& __cont, _Predicate __pred)
- { return __detail::__erase_nodes_if(__cont, __pred); }
+ {
+ _GLIBCXX_STD_C::set<_Key, _Compare, _Alloc>& __c = __cont;
+ return __detail::__erase_nodes_if(__c, __pred);
+ }
template<typename _Key, typename _Compare, typename _Alloc,
typename _Predicate>
inline typename multiset<_Key, _Compare, _Alloc>::size_type
erase_if(multiset<_Key, _Compare, _Alloc>& __cont, _Predicate __pred)
- { return __detail::__erase_nodes_if(__cont, __pred); }
+ {
+ _GLIBCXX_STD_C::multiset<_Key, _Compare, _Alloc>& __c = __cont;
+ return __detail::__erase_nodes_if(__c, __pred);
+ }
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // C++20
diff --git a/libstdc++-v3/include/std/string b/libstdc++-v3/include/std/string
index 7f994147a33..95412b6f7a3 100644
--- a/libstdc++-v3/include/std/string
+++ b/libstdc++-v3/include/std/string
@@ -124,12 +124,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
erase_if(basic_string<_CharT, _Traits, _Alloc>& __cont, _Predicate __pred)
{
using namespace __gnu_cxx;
- using _It = typename basic_string<_CharT, _Traits, _Alloc>::iterator;
const auto __osz = __cont.size();
- _It __removed(std::__remove_if(std::__niter_base(__cont.begin()),
- std::__niter_base(__cont.end()),
- __ops::__pred_iter(std::ref(__pred))));
- __cont.erase(__removed, __cont.end());
+ const auto __end = __cont.end();
+ auto __removed = std::__remove_if(__cont.begin(), __end,
+ __ops::__pred_iter(std::ref(__pred)));
+ __cont.erase(__removed, __end);
return __osz - __cont.size();
}
@@ -138,12 +137,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
erase(basic_string<_CharT, _Traits, _Alloc>& __cont, const _Up& __value)
{
using namespace __gnu_cxx;
- using _It = typename basic_string<_CharT, _Traits, _Alloc>::iterator;
const auto __osz = __cont.size();
- _It __removed(std::__remove_if(std::__niter_base(__cont.begin()),
- std::__niter_base(__cont.end()),
- __ops::__iter_equals_val(__value)));
- __cont.erase(__removed, __cont.end());
+ const auto __end = __cont.end();
+ auto __removed = std::__remove_if(__cont.begin(), __end,
+ __ops::__iter_equals_val(__value));
+ __cont.erase(__removed, __end);
return __osz - __cont.size();
}
_GLIBCXX_END_NAMESPACE_VERSION
diff --git a/libstdc++-v3/include/std/unordered_map b/libstdc++-v3/include/std/unordered_map
index e6715069362..774c21fc28b 100644
--- a/libstdc++-v3/include/std/unordered_map
+++ b/libstdc++-v3/include/std/unordered_map
@@ -83,7 +83,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
inline typename unordered_map<_Key, _Tp, _Hash, _CPred, _Alloc>::size_type
erase_if(unordered_map<_Key, _Tp, _Hash, _CPred, _Alloc>& __cont,
_Predicate __pred)
- { return __detail::__erase_nodes_if(__cont, __pred); }
+ {
+ _GLIBCXX_STD_C::unordered_map<_Key, _Tp, _Hash, _CPred, _Alloc>& __c
+ = __cont;
+ return __detail::__erase_nodes_if(__c, __pred);
+ }
template<typename _Key, typename _Tp, typename _Hash, typename _CPred,
typename _Alloc, typename _Predicate>
@@ -91,7 +95,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
size_type
erase_if(unordered_multimap<_Key, _Tp, _Hash, _CPred, _Alloc>& __cont,
_Predicate __pred)
- { return __detail::__erase_nodes_if(__cont, __pred); }
+ {
+ _GLIBCXX_STD_C::unordered_multimap<_Key, _Tp, _Hash, _CPred, _Alloc>& __c
+ = __cont;
+ return __detail::__erase_nodes_if(__c, __pred);
+ }
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // C++20
diff --git a/libstdc++-v3/include/std/unordered_set b/libstdc++-v3/include/std/unordered_set
index 1ad93d0031b..3859eeaebd0 100644
--- a/libstdc++-v3/include/std/unordered_set
+++ b/libstdc++-v3/include/std/unordered_set
@@ -83,14 +83,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
inline typename unordered_set<_Key, _Hash, _CPred, _Alloc>::size_type
erase_if(unordered_set<_Key, _Hash, _CPred, _Alloc>& __cont,
_Predicate __pred)
- { return __detail::__erase_nodes_if(__cont, __pred); }
+ {
+ _GLIBCXX_STD_C::unordered_set<_Key, _Hash, _CPred, _Alloc>& __c = __cont;
+ return __detail::__erase_nodes_if(__c, __pred);
+ }
template<typename _Key, typename _Hash, typename _CPred, typename _Alloc,
typename _Predicate>
inline typename unordered_multiset<_Key, _Hash, _CPred, _Alloc>::size_type
erase_if(unordered_multiset<_Key, _Hash, _CPred, _Alloc>& __cont,
_Predicate __pred)
- { return __detail::__erase_nodes_if(__cont, __pred); }
+ {
+ _GLIBCXX_STD_C::unordered_multiset<_Key, _Hash, _CPred, _Alloc>& __c
+ = __cont;
+ return __detail::__erase_nodes_if(__c, __pred);
+ }
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // C++20
diff --git a/libstdc++-v3/include/std/vector b/libstdc++-v3/include/std/vector
index 3b275e249fc..835fa8aeb69 100644
--- a/libstdc++-v3/include/std/vector
+++ b/libstdc++-v3/include/std/vector
@@ -105,28 +105,28 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
inline typename vector<_Tp, _Alloc>::size_type
erase_if(vector<_Tp, _Alloc>& __cont, _Predicate __pred)
{
+ _GLIBCXX_STD_C::vector<_Tp, _Alloc>& __c = __cont;
using namespace __gnu_cxx;
- const auto __osz = __cont.size();
- const auto __end = __cont.end();
- auto __removed(std::__remove_if(std::__niter_base(__cont.begin()),
- std::__niter_base(__end),
+ const auto __osz = __c.size();
+ const auto __end = __c.end();
+ auto __removed(std::__remove_if(__c.begin(), __end,
__ops::__pred_iter(std::ref(__pred))));
- __cont.erase(std::__niter_wrap(__end, __removed), __end);
- return __osz - __cont.size();
+ __c.erase(__removed, __end);
+ return __osz - __c.size();
}
template<typename _Tp, typename _Alloc, typename _Up>
inline typename vector<_Tp, _Alloc>::size_type
erase(vector<_Tp, _Alloc>& __cont, const _Up& __value)
{
+ _GLIBCXX_STD_C::vector<_Tp, _Alloc>& __c = __cont;
using namespace __gnu_cxx;
- const auto __osz = __cont.size();
- const auto __end = __cont.end();
- auto __removed(std::__remove_if(std::__niter_base(__cont.begin()),
- std::__niter_base(__end),
- __ops::__iter_equals_val(__value)));
- __cont.erase(std::__niter_wrap(__end, __removed), __end);
- return __osz - __cont.size();
+ const auto __osz = __c.size();
+ const auto __end = __c.end();
+ auto __removed = std::__remove_if(__c.begin(), __end,
+ __ops::__iter_equals_val(__value));
+ __c.erase(__removed, __end);
+ return __osz - __c.size();
}
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2021-10-07 16:52 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-10-07 16:52 [gcc r12-4233] libstdc++: Avoid debug checks in uniform container erasure functions Jonathan Wakely
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).