[libcxx-commits] [libcxx] [libc++] Optimize string::pop_back() (PR #223729)

Nikolas Klauser via libcxx-commits libcxx-commits at lists.llvm.org
Tue Sep 15 07:54:35 PDT 2026


https://github.com/philnik777 created https://github.com/llvm/llvm-project/pull/223729

None

>From 837629d7f64651ec1151a0da8c252eeaed5e58e9 Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Tue, 15 Sep 2026 16:54:06 +0200
Subject: [PATCH] [libc++] Optimize string::pop_back()

---
 libcxx/include/string                         |  8 ++++-
 .../benchmarks/containers/string.bench.cpp    | 29 +++++++++++++++++++
 2 files changed, 36 insertions(+), 1 deletion(-)

diff --git a/libcxx/include/string b/libcxx/include/string
index 8b0b648d2c655..1c9bf956a0291 100644
--- a/libcxx/include/string
+++ b/libcxx/include/string
@@ -3319,7 +3319,13 @@ basic_string<_CharT, _Traits, _Allocator>::erase(const_iterator __first, const_i
 template <class _CharT, class _Traits, class _Allocator>
 inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::pop_back() {
   _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "string::pop_back(): string is already empty");
-  __erase_to_end(size() - 1);
+  if (__is_long()) {
+    __rep_.__l.__size_ -= 1;
+    __rep_.__l.__data_[__rep_.__l.__size_] = '\0';
+  } else {
+    __rep_.__s.__size_ -= 1;
+    __rep_.__s.__data_[__rep_.__s.__size_] = '\0';
+  }
 }
 
 template <class _CharT, class _Traits, class _Allocator>
diff --git a/libcxx/test/benchmarks/containers/string.bench.cpp b/libcxx/test/benchmarks/containers/string.bench.cpp
index b795654e84281..1e1b75c3642da 100644
--- a/libcxx/test/benchmarks/containers/string.bench.cpp
+++ b/libcxx/test/benchmarks/containers/string.bench.cpp
@@ -263,6 +263,35 @@ int main(int argc, char** argv) {
           [](auto bm) { bm->Arg(small_size)->Arg(large_size); });
   }
 
+  {
+    static auto bench_impl =
+        []<bool opaque, class CharT>(std::bool_constant<opaque>, std::type_identity<CharT>, benchmark::State& state) {
+          std::basic_string<CharT> strings[4096];
+
+          size_t size = state.range();
+          size_t pos  = size / 2;
+          while (state.KeepRunningBatch(std::size(strings))) {
+            state.PauseTiming();
+            for (auto& string : strings)
+              string.resize(size, 'a');
+            state.ResumeTiming();
+            for (auto& string : strings) {
+              if constexpr (opaque) {
+                benchmark::DoNotOptimize(pos);
+                benchmark::DoNotOptimize(npos);
+              }
+              string.pop_back();
+            }
+          }
+        };
+    bench("std::basic_string::pop_back() (opaque)", std::bind_front(bench_impl, std::true_type{}), [](auto bm) {
+      bm->Arg(small_size)->Arg(large_size);
+    });
+    bench("std::basic_string::pop_back() (transparent)", std::bind_front(bench_impl, std::false_type{}), [](auto bm) {
+      bm->Arg(small_size)->Arg(large_size);
+    });
+  }
+
   // [string.ops]
   bench("std::basic_string::data()", []<class CharT>(std::type_identity<CharT>, benchmark::State& state) {
     std::basic_string<CharT> str;



More information about the libcxx-commits mailing list