diff options
author | Jonathan Wakely <jwakely@redhat.com> | 2023-05-25 09:57:46 +0100 |
---|---|---|
committer | Jonathan Wakely <jwakely@redhat.com> | 2023-05-31 21:01:15 +0100 |
commit | fb409a15d9babc78fe1d9957afcbaf1102cce58f (patch) | |
tree | b597fb9c7e3211c9099661a94a765f54b4cb9f9c /libstdc++-v3/include | |
parent | a239a35075ffd8b34f1db72c22998a625ff962b5 (diff) | |
download | gcc-fb409a15d9babc78fe1d9957afcbaf1102cce58f.zip gcc-fb409a15d9babc78fe1d9957afcbaf1102cce58f.tar.gz gcc-fb409a15d9babc78fe1d9957afcbaf1102cce58f.tar.bz2 |
libstdc++: Express std::vector's size() <= capacity() invariant in code
This adds optimizer hints so that GCC knows that size() <= capacity() is
always true. This allows the compiler to optimize away re-allocating
paths when assigning new values to the vector without resizing it, e.g.,
vec.assign(vec.size(), new_val).
libstdc++-v3/ChangeLog:
* include/bits/stl_vector.h (_Vector_base::_M_invariant()): New
function.
(vector::size(), vector::capacity()): Call _M_invariant().
* testsuite/23_containers/vector/capacity/invariant.cc: New test.
* testsuite/23_containers/vector/types/1.cc: Add suppression for
false positive warning (PR110060).
Diffstat (limited to 'libstdc++-v3/include')
-rw-r--r-- | libstdc++-v3/include/bits/stl_vector.h | 30 |
1 files changed, 27 insertions, 3 deletions
diff --git a/libstdc++-v3/include/bits/stl_vector.h b/libstdc++-v3/include/bits/stl_vector.h index acb2939..e593be4 100644 --- a/libstdc++-v3/include/bits/stl_vector.h +++ b/libstdc++-v3/include/bits/stl_vector.h @@ -388,6 +388,24 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER } protected: + + __attribute__((__always_inline__)) + _GLIBCXX20_CONSTEXPR void + _M_invariant() const + { +#if __OPTIMIZE__ + if (this->_M_impl._M_finish < this->_M_impl._M_start) + __builtin_unreachable(); + if (this->_M_impl._M_finish > this->_M_impl._M_end_of_storage) + __builtin_unreachable(); + + size_t __sz = this->_M_impl._M_finish - this->_M_impl._M_start; + size_t __cap = this->_M_impl._M_end_of_storage - this->_M_impl._M_start; + if (__sz > __cap) + __builtin_unreachable(); +#endif + } + _GLIBCXX20_CONSTEXPR void _M_create_storage(size_t __n) @@ -987,7 +1005,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR size_type size() const _GLIBCXX_NOEXCEPT - { return size_type(this->_M_impl._M_finish - this->_M_impl._M_start); } + { + _Base::_M_invariant(); + return size_type(this->_M_impl._M_finish - this->_M_impl._M_start); + } /** Returns the size() of the largest possible %vector. */ _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR @@ -1073,8 +1094,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR size_type capacity() const _GLIBCXX_NOEXCEPT - { return size_type(this->_M_impl._M_end_of_storage - - this->_M_impl._M_start); } + { + _Base::_M_invariant(); + return size_type(this->_M_impl._M_end_of_storage + - this->_M_impl._M_start); + } /** * Returns true if the %vector is empty. (Thus begin() would |