aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Hubicka <hubicka@ucw.cz>2024-11-27 23:52:37 +0100
committerJan Hubicka <hubicka@ucw.cz>2024-11-27 23:52:37 +0100
commit1046c32de4956c3d706a2ff8683582fd21b8f360 (patch)
tree52eb137dbd27e63d5b7798886323abbddd8b5e3c
parent87492fb3fd5e7510983e0275a38ba95769335018 (diff)
downloadgcc-1046c32de4956c3d706a2ff8683582fd21b8f360.zip
gcc-1046c32de4956c3d706a2ff8683582fd21b8f360.tar.gz
gcc-1046c32de4956c3d706a2ff8683582fd21b8f360.tar.bz2
optimize basic_string
Add __builtin_unreachable conditionls to declare value ranges of basic_string::length(). FIx max_size() to return actual max size using logic similar to std::vector. Aviod use of size() in empty() to save some compile time overhead. As disucced, max_size() change is technically ABI breaking, but hopefully this does not really matter in practice. Change of length() breaks empty-loop testcase where we now optimize the loop only after inlining, so template is updated to check cddce3 instead of cddce2. This is PR117764. With these chages we now optimize out unused strings as tested in string-1.C libstdc++-v3/ChangeLog: * include/bits/basic_string.h (basic_string::size(), basic_string::length(), basic_string::capacity()): Add __builtin_unreachable to declare value ranges. (basic_string::empty()): Implement directly (basic_string::max_size()): Account correctly the terminating 0 and limits implied by ptrdiff_t. gcc/testsuite/ChangeLog: * g++.dg/tree-ssa/empty-loop.C: xfail optimization at cddce2 and check it happens at cddce3. * g++.dg/tree-ssa/string-1.C: New test.
-rw-r--r--gcc/testsuite/g++.dg/tree-ssa/empty-loop.C5
-rw-r--r--gcc/testsuite/g++.dg/tree-ssa/string-1.C9
-rw-r--r--libstdc++-v3/include/bits/basic_string.h25
3 files changed, 32 insertions, 7 deletions
diff --git a/gcc/testsuite/g++.dg/tree-ssa/empty-loop.C b/gcc/testsuite/g++.dg/tree-ssa/empty-loop.C
index ed4a603..b7e7e27 100644
--- a/gcc/testsuite/g++.dg/tree-ssa/empty-loop.C
+++ b/gcc/testsuite/g++.dg/tree-ssa/empty-loop.C
@@ -30,5 +30,8 @@ int foo (vector<string> &v, list<string> &l, set<string> &s, map<int, string> &m
return 0;
}
-/* { dg-final { scan-tree-dump-not "if" "cddce2"} } */
+/* Adding __builtin_unreachable to std::string::size() prevents cddce2 from
+ eliminating the loop early, see PR117764. */
+/* { dg-final { scan-tree-dump-not "if" "cddce2" { xfail *-*-* } } } */
+/* { dg-final { scan-tree-dump-not "if" "cddce3"} } */
diff --git a/gcc/testsuite/g++.dg/tree-ssa/string-1.C b/gcc/testsuite/g++.dg/tree-ssa/string-1.C
new file mode 100644
index 0000000..d38c23a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/tree-ssa/string-1.C
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -std=c++20 -fdump-tree-optimized" } */
+#include <string>
+std::string
+test (std::string &a)
+{
+ return a;
+}
+/* { dg-final { scan-tree-dump-not "throw" "optimized" } } */
diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h
index f5b3200..17b973c 100644
--- a/libstdc++-v3/include/bits/basic_string.h
+++ b/libstdc++-v3/include/bits/basic_string.h
@@ -1079,20 +1079,30 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
size_type
size() const _GLIBCXX_NOEXCEPT
- { return _M_string_length; }
+ {
+ size_type __sz = _M_string_length;
+ if (__sz > max_size ())
+ __builtin_unreachable ();
+ return __sz;
+ }
/// Returns the number of characters in the string, not including any
/// null-termination.
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
size_type
length() const _GLIBCXX_NOEXCEPT
- { return _M_string_length; }
+ { return size(); }
/// Returns the size() of the largest possible %string.
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
size_type
max_size() const _GLIBCXX_NOEXCEPT
- { return (_Alloc_traits::max_size(_M_get_allocator()) - 1) / 2; }
+ {
+ const size_t __diffmax
+ = __gnu_cxx::__numeric_traits<ptrdiff_t>::__max / sizeof(_CharT);
+ const size_t __allocmax = _Alloc_traits::max_size(_M_get_allocator());
+ return (std::min)(__diffmax, __allocmax) - 1;
+ }
/**
* @brief Resizes the %string to the specified number of characters.
@@ -1184,8 +1194,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
size_type
capacity() const _GLIBCXX_NOEXCEPT
{
- return _M_is_local() ? size_type(_S_local_capacity)
- : _M_allocated_capacity;
+ size_t __sz = _M_is_local() ? size_type(_S_local_capacity)
+ : _M_allocated_capacity;
+ if (__sz < _S_local_capacity || __sz > max_size ())
+ __builtin_unreachable ();
+ return __sz;
}
/**
@@ -1234,7 +1247,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
bool
empty() const _GLIBCXX_NOEXCEPT
- { return this->size() == 0; }
+ { return _M_string_length == 0; }
// Element access:
/**