]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
optimize basic_string
authorJan Hubicka <hubicka@ucw.cz>
Wed, 27 Nov 2024 22:52:37 +0000 (23:52 +0100)
committerJan Hubicka <hubicka@ucw.cz>
Wed, 27 Nov 2024 22:52:37 +0000 (23:52 +0100)
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.

gcc/testsuite/g++.dg/tree-ssa/empty-loop.C
gcc/testsuite/g++.dg/tree-ssa/string-1.C [new file with mode: 0644]
libstdc++-v3/include/bits/basic_string.h

index ed4a603bf5b33472cef2548d44a681bf4b7b44e9..b7e7e27cc042cd79cfaf4208e138e034a37650de 100644 (file)
@@ -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 (file)
index 0000000..d38c23a
--- /dev/null
@@ -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" } } */
index f5b320099b171d59d5534c75ed2c1075ff21654c..17b973c8b45c5c56884649c4070af4380b2f4ca7 100644 (file)
@@ -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:
       /**