[libcxx-commits] [libcxx] [libc++] Add remaining benchmarks from [alg.modifying.operations] (PR #127354)

Louis Dionne via libcxx-commits libcxx-commits at lists.llvm.org
Tue Feb 25 08:29:59 PST 2025


https://github.com/ldionne updated https://github.com/llvm/llvm-project/pull/127354

>From 232a73aec14b81590453ddcc97fd108938251f75 Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Sat, 15 Feb 2025 21:36:38 +0100
Subject: [PATCH 01/15] [libc++] Add remaining benchmarks from
 [alg.modifying.operations]

This patch adds benchmarks for all the remaining algorithms in
[alg.modifying.operations] that we didn't already have a benchmark
for.
---
 libcxx/include/module.modulemap               |   3 +-
 .../test/benchmarks/algorithms/fill.bench.cpp |  51 -------
 .../algorithms/modifying/fill.bench.cpp       |  86 +++++++++++
 .../algorithms/modifying/fill_n.bench.cpp     |  86 +++++++++++
 .../algorithms/modifying/generate.bench.cpp   |  59 +++++++
 .../algorithms/modifying/generate_n.bench.cpp |  59 +++++++
 .../algorithms/modifying/remove.bench.cpp     | 133 ++++++++++++++++
 .../modifying/remove_copy.bench.cpp           | 109 +++++++++++++
 .../modifying/remove_copy_if.bench.cpp        | 119 +++++++++++++++
 .../algorithms/modifying/remove_if.bench.cpp  | 143 +++++++++++++++++
 .../algorithms/modifying/replace.bench.cpp    | 107 +++++++++++++
 .../algorithms/modifying/replace_if.bench.cpp | 117 ++++++++++++++
 .../algorithms/modifying/reverse.bench.cpp    |  57 +++++++
 .../modifying/reverse_copy.bench.cpp          |  61 ++++++++
 .../algorithms/modifying/rotate.bench.cpp     |  59 +++++++
 .../modifying/rotate_copy.bench.cpp           |  65 ++++++++
 .../algorithms/modifying/sample.bench.cpp     |  68 +++++++++
 .../algorithms/modifying/shift_left.bench.cpp |  56 +++++++
 .../modifying/shift_right.bench.cpp           |  56 +++++++
 .../algorithms/modifying/shuffle.bench.cpp    |  56 +++++++
 .../modifying/swap_ranges.bench.cpp           |  64 ++++++++
 .../modifying/transform.binary.bench.cpp      |  73 +++++++++
 .../modifying/transform.unary.bench.cpp       |  68 +++++++++
 .../algorithms/modifying/unique.bench.cpp     | 132 ++++++++++++++++
 .../modifying/unique_copy.bench.cpp           | 105 +++++++++++++
 .../modifying/unique_copy_pred.bench.cpp      | 121 +++++++++++++++
 .../modifying/unique_pred.bench.cpp           | 144 ++++++++++++++++++
 .../benchmarks/algorithms/reverse.bench.cpp   |  48 ------
 28 files changed, 2205 insertions(+), 100 deletions(-)
 delete mode 100644 libcxx/test/benchmarks/algorithms/fill.bench.cpp
 create mode 100644 libcxx/test/benchmarks/algorithms/modifying/fill.bench.cpp
 create mode 100644 libcxx/test/benchmarks/algorithms/modifying/fill_n.bench.cpp
 create mode 100644 libcxx/test/benchmarks/algorithms/modifying/generate.bench.cpp
 create mode 100644 libcxx/test/benchmarks/algorithms/modifying/generate_n.bench.cpp
 create mode 100644 libcxx/test/benchmarks/algorithms/modifying/remove.bench.cpp
 create mode 100644 libcxx/test/benchmarks/algorithms/modifying/remove_copy.bench.cpp
 create mode 100644 libcxx/test/benchmarks/algorithms/modifying/remove_copy_if.bench.cpp
 create mode 100644 libcxx/test/benchmarks/algorithms/modifying/remove_if.bench.cpp
 create mode 100644 libcxx/test/benchmarks/algorithms/modifying/replace.bench.cpp
 create mode 100644 libcxx/test/benchmarks/algorithms/modifying/replace_if.bench.cpp
 create mode 100644 libcxx/test/benchmarks/algorithms/modifying/reverse.bench.cpp
 create mode 100644 libcxx/test/benchmarks/algorithms/modifying/reverse_copy.bench.cpp
 create mode 100644 libcxx/test/benchmarks/algorithms/modifying/rotate.bench.cpp
 create mode 100644 libcxx/test/benchmarks/algorithms/modifying/rotate_copy.bench.cpp
 create mode 100644 libcxx/test/benchmarks/algorithms/modifying/sample.bench.cpp
 create mode 100644 libcxx/test/benchmarks/algorithms/modifying/shift_left.bench.cpp
 create mode 100644 libcxx/test/benchmarks/algorithms/modifying/shift_right.bench.cpp
 create mode 100644 libcxx/test/benchmarks/algorithms/modifying/shuffle.bench.cpp
 create mode 100644 libcxx/test/benchmarks/algorithms/modifying/swap_ranges.bench.cpp
 create mode 100644 libcxx/test/benchmarks/algorithms/modifying/transform.binary.bench.cpp
 create mode 100644 libcxx/test/benchmarks/algorithms/modifying/transform.unary.bench.cpp
 create mode 100644 libcxx/test/benchmarks/algorithms/modifying/unique.bench.cpp
 create mode 100644 libcxx/test/benchmarks/algorithms/modifying/unique_copy.bench.cpp
 create mode 100644 libcxx/test/benchmarks/algorithms/modifying/unique_copy_pred.bench.cpp
 create mode 100644 libcxx/test/benchmarks/algorithms/modifying/unique_pred.bench.cpp
 delete mode 100644 libcxx/test/benchmarks/algorithms/reverse.bench.cpp

diff --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap
index b0720703bd0de..6af6e96af7d75 100644
--- a/libcxx/include/module.modulemap
+++ b/libcxx/include/module.modulemap
@@ -700,6 +700,7 @@ module std [system] {
     }
     module ranges_remove {
       header "__algorithm/ranges_remove.h"
+      export std.ranges.subrange // return type
     }
     module ranges_replace_copy_if {
       header "__algorithm/ranges_replace_copy_if.h"
@@ -724,7 +725,7 @@ module std [system] {
     }
     module ranges_rotate_copy {
       header "__algorithm/ranges_rotate_copy.h"
-      export std.algorithm.in_out_result
+      export std.ranges.subrange // return type
     }
     module ranges_rotate                          { header "__algorithm/ranges_rotate.h" }
     module ranges_sample                          { header "__algorithm/ranges_sample.h" }
diff --git a/libcxx/test/benchmarks/algorithms/fill.bench.cpp b/libcxx/test/benchmarks/algorithms/fill.bench.cpp
deleted file mode 100644
index 6a48b25b7eb63..0000000000000
--- a/libcxx/test/benchmarks/algorithms/fill.bench.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
-
-#include <algorithm>
-#include <benchmark/benchmark.h>
-#include <vector>
-
-static void bm_fill_n_vector_bool(benchmark::State& state) {
-  std::vector<bool> vec1(state.range());
-  for (auto _ : state) {
-    benchmark::DoNotOptimize(vec1);
-    benchmark::DoNotOptimize(std::fill_n(vec1.begin(), vec1.size(), false));
-  }
-}
-BENCHMARK(bm_fill_n_vector_bool)->DenseRange(1, 8)->Range(16, 1 << 20);
-
-static void bm_ranges_fill_n_vector_bool(benchmark::State& state) {
-  std::vector<bool> vec1(state.range());
-  for (auto _ : state) {
-    benchmark::DoNotOptimize(vec1);
-    benchmark::DoNotOptimize(std::ranges::fill_n(vec1.begin(), vec1.size(), false));
-  }
-}
-BENCHMARK(bm_ranges_fill_n_vector_bool)->DenseRange(1, 8)->Range(16, 1 << 20);
-
-static void bm_fill_vector_bool(benchmark::State& state) {
-  std::vector<bool> vec1(state.range());
-  for (auto _ : state) {
-    benchmark::DoNotOptimize(vec1);
-    std::fill(vec1.begin(), vec1.end(), false);
-  }
-}
-BENCHMARK(bm_fill_vector_bool)->DenseRange(1, 8)->Range(16, 1 << 20);
-
-static void bm_ranges_fill_vector_bool(benchmark::State& state) {
-  std::vector<bool> vec1(state.range());
-  for (auto _ : state) {
-    benchmark::DoNotOptimize(vec1);
-    benchmark::DoNotOptimize(std::ranges::fill(vec1, false));
-  }
-}
-BENCHMARK(bm_ranges_fill_vector_bool)->DenseRange(1, 8)->Range(16, 1 << 20);
-
-BENCHMARK_MAIN();
diff --git a/libcxx/test/benchmarks/algorithms/modifying/fill.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/fill.bench.cpp
new file mode 100644
index 0000000000000..64c7364be6549
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/modifying/fill.bench.cpp
@@ -0,0 +1,86 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+#include <algorithm>
+#include <cstddef>
+#include <deque>
+#include <iterator>
+#include <list>
+#include <string>
+#include <vector>
+
+#include "benchmark/benchmark.h"
+#include "../../GenerateInput.h"
+#include "test_macros.h"
+
+template <class Container, class Operation>
+void bm(std::string operation_name, Operation fill) {
+  auto bench = [fill](auto& st) {
+    std::size_t const size = st.range(0);
+    using ValueType        = typename Container::value_type;
+    ValueType x            = Generate<ValueType>::random();
+    ValueType y            = Generate<ValueType>::random();
+    Container c(size, y);
+
+    for ([[maybe_unused]] auto _ : st) {
+      fill(c.begin(), c.end(), x);
+      std::swap(x, y);
+      benchmark::DoNotOptimize(c);
+      benchmark::DoNotOptimize(x);
+      benchmark::DoNotOptimize(y);
+      benchmark::ClobberMemory();
+    }
+  };
+  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+template <class Operation>
+void bm_vector_bool(std::string operation_name, Operation fill) {
+  auto bench = [fill](auto& st) {
+    std::size_t const size = st.range(0);
+    bool x                 = true;
+    bool y                 = false;
+    std::vector<bool> c(size, y);
+
+    for ([[maybe_unused]] auto _ : st) {
+      fill(c.begin(), c.end(), x);
+      std::swap(x, y);
+      benchmark::DoNotOptimize(c);
+      benchmark::DoNotOptimize(x);
+      benchmark::DoNotOptimize(y);
+      benchmark::ClobberMemory();
+    }
+  };
+  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+int main(int argc, char** argv) {
+  auto std_fill    = [](auto first, auto last, auto const& value) { return std::fill(first, last, value); };
+  auto ranges_fill = [](auto first, auto last, auto const& value) { return std::ranges::fill(first, last, value); };
+
+  // std::fill
+  bm<std::vector<int>>("std::fill(vector<int>)", std_fill);
+  bm<std::deque<int>>("std::fill(deque<int>)", std_fill);
+  bm<std::list<int>>("std::fill(list<int>)", std_fill);
+  bm_vector_bool("std::fill(vector<bool>)", std_fill);
+
+  // ranges::fill
+  bm<std::vector<int>>("ranges::fill(vector<int>)", ranges_fill);
+  bm<std::deque<int>>("ranges::fill(deque<int>)", ranges_fill);
+  bm<std::list<int>>("ranges::fill(list<int>)", ranges_fill);
+#if TEST_STD_VER >= 23 // vector<bool>::iterator is not an output_iterator before C++23
+  bm_vector_bool("ranges::fill(vector<bool>)", ranges_fill);
+#endif
+
+  benchmark::Initialize(&argc, argv);
+  benchmark::RunSpecifiedBenchmarks();
+  benchmark::Shutdown();
+  return 0;
+}
diff --git a/libcxx/test/benchmarks/algorithms/modifying/fill_n.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/fill_n.bench.cpp
new file mode 100644
index 0000000000000..aaeb0982956f9
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/modifying/fill_n.bench.cpp
@@ -0,0 +1,86 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+#include <algorithm>
+#include <cstddef>
+#include <deque>
+#include <iterator>
+#include <list>
+#include <string>
+#include <vector>
+
+#include "benchmark/benchmark.h"
+#include "../../GenerateInput.h"
+#include "test_macros.h"
+
+template <class Container, class Operation>
+void bm(std::string operation_name, Operation fill_n) {
+  auto bench = [fill_n](auto& st) {
+    std::size_t const size = st.range(0);
+    using ValueType        = typename Container::value_type;
+    ValueType x            = Generate<ValueType>::random();
+    ValueType y            = Generate<ValueType>::random();
+    Container c(size, y);
+
+    for ([[maybe_unused]] auto _ : st) {
+      fill_n(c.begin(), size, x);
+      std::swap(x, y);
+      benchmark::DoNotOptimize(c);
+      benchmark::DoNotOptimize(x);
+      benchmark::DoNotOptimize(y);
+      benchmark::ClobberMemory();
+    }
+  };
+  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+template <class Operation>
+void bm_vector_bool(std::string operation_name, Operation fill_n) {
+  auto bench = [fill_n](auto& st) {
+    std::size_t const size = st.range(0);
+    bool x                 = true;
+    bool y                 = false;
+    std::vector<bool> c(size, y);
+
+    for ([[maybe_unused]] auto _ : st) {
+      fill_n(c.begin(), size, x);
+      std::swap(x, y);
+      benchmark::DoNotOptimize(c);
+      benchmark::DoNotOptimize(x);
+      benchmark::DoNotOptimize(y);
+      benchmark::ClobberMemory();
+    }
+  };
+  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+int main(int argc, char** argv) {
+  auto std_fill_n    = [](auto out, auto n, auto const& value) { return std::fill_n(out, n, value); };
+  auto ranges_fill_n = [](auto out, auto n, auto const& value) { return std::ranges::fill_n(out, n, value); };
+
+  // std::fill_n
+  bm<std::vector<int>>("std::fill_n(vector<int>)", std_fill_n);
+  bm<std::deque<int>>("std::fill_n(deque<int>)", std_fill_n);
+  bm<std::list<int>>("std::fill_n(list<int>)", std_fill_n);
+  bm_vector_bool("std::fill_n(vector<bool>)", std_fill_n);
+
+  // ranges::fill_n
+  bm<std::vector<int>>("ranges::fill_n(vector<int>)", ranges_fill_n);
+  bm<std::deque<int>>("ranges::fill_n(deque<int>)", ranges_fill_n);
+  bm<std::list<int>>("ranges::fill_n(list<int>)", ranges_fill_n);
+#if TEST_STD_VER >= 23 // vector<bool>::iterator is not an output_iterator before C++23
+  bm_vector_bool("ranges::fill_n(vector<bool>)", ranges_fill_n);
+#endif
+
+  benchmark::Initialize(&argc, argv);
+  benchmark::RunSpecifiedBenchmarks();
+  benchmark::Shutdown();
+  return 0;
+}
diff --git a/libcxx/test/benchmarks/algorithms/modifying/generate.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/generate.bench.cpp
new file mode 100644
index 0000000000000..15b039a4d3009
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/modifying/generate.bench.cpp
@@ -0,0 +1,59 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+#include <algorithm>
+#include <cstddef>
+#include <deque>
+#include <iterator>
+#include <list>
+#include <string>
+#include <vector>
+
+#include "benchmark/benchmark.h"
+#include "../../GenerateInput.h"
+
+template <class Container, class Operation>
+void bm(std::string operation_name, Operation generate) {
+  auto bench = [generate](auto& st) {
+    std::size_t const size = st.range(0);
+    Container c(size);
+    using ValueType = typename Container::value_type;
+    ValueType x     = Generate<ValueType>::random();
+
+    for ([[maybe_unused]] auto _ : st) {
+      auto f = [&x] { return x; };
+      generate(c.begin(), c.end(), f);
+      benchmark::DoNotOptimize(c);
+      benchmark::DoNotOptimize(x);
+      benchmark::ClobberMemory();
+    }
+  };
+  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+int main(int argc, char** argv) {
+  auto std_generate    = [](auto first, auto last, auto f) { return std::generate(first, last, f); };
+  auto ranges_generate = [](auto first, auto last, auto f) { return std::ranges::generate(first, last, f); };
+
+  // std::generate
+  bm<std::vector<int>>("std::generate(vector<int>)", std_generate);
+  bm<std::deque<int>>("std::generate(deque<int>)", std_generate);
+  bm<std::list<int>>("std::generate(list<int>)", std_generate);
+
+  // ranges::generate
+  bm<std::vector<int>>("ranges::generate(vector<int>)", ranges_generate);
+  bm<std::deque<int>>("ranges::generate(deque<int>)", ranges_generate);
+  bm<std::list<int>>("ranges::generate(list<int>)", ranges_generate);
+
+  benchmark::Initialize(&argc, argv);
+  benchmark::RunSpecifiedBenchmarks();
+  benchmark::Shutdown();
+  return 0;
+}
diff --git a/libcxx/test/benchmarks/algorithms/modifying/generate_n.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/generate_n.bench.cpp
new file mode 100644
index 0000000000000..75b088411810f
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/modifying/generate_n.bench.cpp
@@ -0,0 +1,59 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+#include <algorithm>
+#include <cstddef>
+#include <deque>
+#include <iterator>
+#include <list>
+#include <string>
+#include <vector>
+
+#include "benchmark/benchmark.h"
+#include "../../GenerateInput.h"
+
+template <class Container, class Operation>
+void bm(std::string operation_name, Operation generate_n) {
+  auto bench = [generate_n](auto& st) {
+    std::size_t const size = st.range(0);
+    Container c(size);
+    using ValueType = typename Container::value_type;
+    ValueType x     = Generate<ValueType>::random();
+
+    for ([[maybe_unused]] auto _ : st) {
+      auto f = [&x] { return x; };
+      generate_n(c.begin(), size, f);
+      benchmark::DoNotOptimize(c);
+      benchmark::DoNotOptimize(x);
+      benchmark::ClobberMemory();
+    }
+  };
+  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+int main(int argc, char** argv) {
+  auto std_generate_n    = [](auto out, auto n, auto f) { return std::generate_n(out, n, f); };
+  auto ranges_generate_n = [](auto out, auto n, auto f) { return std::ranges::generate_n(out, n, f); };
+
+  // std::generate_n
+  bm<std::vector<int>>("std::generate_n(vector<int>)", std_generate_n);
+  bm<std::deque<int>>("std::generate_n(deque<int>)", std_generate_n);
+  bm<std::list<int>>("std::generate_n(list<int>)", std_generate_n);
+
+  // ranges::generate_n
+  bm<std::vector<int>>("ranges::generate_n(vector<int>)", ranges_generate_n);
+  bm<std::deque<int>>("ranges::generate_n(deque<int>)", ranges_generate_n);
+  bm<std::list<int>>("ranges::generate_n(list<int>)", ranges_generate_n);
+
+  benchmark::Initialize(&argc, argv);
+  benchmark::RunSpecifiedBenchmarks();
+  benchmark::Shutdown();
+  return 0;
+}
diff --git a/libcxx/test/benchmarks/algorithms/modifying/remove.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/remove.bench.cpp
new file mode 100644
index 0000000000000..764dfe73ab70c
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/modifying/remove.bench.cpp
@@ -0,0 +1,133 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+#include <algorithm>
+#include <cstddef>
+#include <deque>
+#include <iterator>
+#include <list>
+#include <string>
+#include <vector>
+
+#include "benchmark/benchmark.h"
+#include "../../GenerateInput.h"
+
+// Create a sequence of the form xxxxxxxxxxyyyyyyyyyy and remove
+// the prefix of x's from it.
+//
+// We perform this benchmark in a batch because we need to restore the
+// state of the container after the operation.
+template <class Container, class Operation>
+void bm_prefix(std::string operation_name, Operation remove) {
+  auto bench = [remove](auto& st) {
+    std::size_t const size          = st.range(0);
+    constexpr std::size_t BatchSize = 10;
+    using ValueType                 = typename Container::value_type;
+    Container c[BatchSize];
+    ValueType x = Generate<ValueType>::random();
+    ValueType y = Generate<ValueType>::random();
+    for (std::size_t i = 0; i != BatchSize; ++i) {
+      c[i]      = Container(size);
+      auto half = size / 2;
+      std::fill_n(std::fill_n(c[i].begin(), half, x), half, y);
+    }
+
+    while (st.KeepRunningBatch(BatchSize)) {
+      for (std::size_t i = 0; i != BatchSize; ++i) {
+        auto result = remove(c[i].begin(), c[i].end(), x);
+        benchmark::DoNotOptimize(result);
+        benchmark::DoNotOptimize(c[i]);
+        benchmark::DoNotOptimize(x);
+        benchmark::ClobberMemory();
+      }
+
+      st.PauseTiming();
+      for (std::size_t i = 0; i != BatchSize; ++i) {
+        auto half = size / 2;
+        std::fill_n(std::fill_n(c[i].begin(), half, x), half, y);
+      }
+      st.ResumeTiming();
+    }
+  };
+  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+// Create a sequence of the form xyxyxyxyxyxyxyxyxyxy and remove
+// the x's from it.
+//
+// We perform this benchmark in a batch because we need to restore the
+// state of the container after the operation.
+template <class Container, class Operation>
+void bm_sprinkled(std::string operation_name, Operation remove) {
+  auto bench = [remove](auto& st) {
+    std::size_t const size          = st.range(0);
+    constexpr std::size_t BatchSize = 10;
+    using ValueType                 = typename Container::value_type;
+    Container c[BatchSize];
+    ValueType x    = Generate<ValueType>::random();
+    ValueType y    = Generate<ValueType>::random();
+    auto alternate = [&](auto out, auto n) {
+      for (std::size_t i = 0; i != n; ++i) {
+        *out++ = (i % 2 == 0 ? x : y);
+      }
+    };
+    for (std::size_t i = 0; i != BatchSize; ++i) {
+      c[i] = Container(size);
+      alternate(c[i].begin(), size);
+    }
+
+    while (st.KeepRunningBatch(BatchSize)) {
+      for (std::size_t i = 0; i != BatchSize; ++i) {
+        auto result = remove(c[i].begin(), c[i].end(), x);
+        benchmark::DoNotOptimize(result);
+        benchmark::DoNotOptimize(c[i]);
+        benchmark::DoNotOptimize(x);
+        benchmark::ClobberMemory();
+      }
+
+      st.PauseTiming();
+      for (std::size_t i = 0; i != BatchSize; ++i) {
+        alternate(c[i].begin(), size);
+      }
+      st.ResumeTiming();
+    }
+  };
+  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+int main(int argc, char** argv) {
+  auto std_remove    = [](auto first, auto last, auto const& value) { return std::remove(first, last, value); };
+  auto ranges_remove = [](auto first, auto last, auto const& value) { return std::ranges::remove(first, last, value); };
+
+  // std::remove
+  bm_prefix<std::vector<int>>("std::remove(vector<int>) (prefix)", std_remove);
+  bm_sprinkled<std::vector<int>>("std::remove(vector<int>) (sprinkled)", std_remove);
+
+  bm_prefix<std::deque<int>>("std::remove(deque<int>) (prefix)", std_remove);
+  bm_sprinkled<std::deque<int>>("std::remove(deque<int>) (sprinkled)", std_remove);
+
+  bm_prefix<std::list<int>>("std::remove(list<int>) (prefix)", std_remove);
+  bm_sprinkled<std::list<int>>("std::remove(list<int>) (sprinkled)", std_remove);
+
+  // ranges::remove
+  bm_prefix<std::vector<int>>("ranges::remove(vector<int>) (prefix)", ranges_remove);
+  bm_sprinkled<std::vector<int>>("ranges::remove(vector<int>) (sprinkled)", ranges_remove);
+
+  bm_prefix<std::deque<int>>("ranges::remove(deque<int>) (prefix)", ranges_remove);
+  bm_sprinkled<std::deque<int>>("ranges::remove(deque<int>) (sprinkled)", ranges_remove);
+
+  bm_prefix<std::list<int>>("ranges::remove(list<int>) (prefix)", ranges_remove);
+  bm_sprinkled<std::list<int>>("ranges::remove(list<int>) (sprinkled)", ranges_remove);
+
+  benchmark::Initialize(&argc, argv);
+  benchmark::RunSpecifiedBenchmarks();
+  benchmark::Shutdown();
+  return 0;
+}
diff --git a/libcxx/test/benchmarks/algorithms/modifying/remove_copy.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/remove_copy.bench.cpp
new file mode 100644
index 0000000000000..88c05384eb7bd
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/modifying/remove_copy.bench.cpp
@@ -0,0 +1,109 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+#include <algorithm>
+#include <cstddef>
+#include <deque>
+#include <iterator>
+#include <list>
+#include <string>
+#include <vector>
+
+#include "benchmark/benchmark.h"
+#include "../../GenerateInput.h"
+
+// Create a sequence of the form xxxxxxxxxxyyyyyyyyyy and remove
+// the prefix of x's from it.
+template <class Container, class Operation>
+void bm_prefix(std::string operation_name, Operation remove_copy) {
+  auto bench = [remove_copy](auto& st) {
+    std::size_t const size = st.range(0);
+    using ValueType        = typename Container::value_type;
+    Container c;
+    ValueType x = Generate<ValueType>::random();
+    ValueType y = Generate<ValueType>::random();
+    std::fill_n(std::back_inserter(c), size / 2, x);
+    std::fill_n(std::back_inserter(c), size / 2, y);
+
+    std::vector<ValueType> out(size);
+
+    for ([[maybe_unused]] auto _ : st) {
+      auto result = remove_copy(c.begin(), c.end(), out.begin(), x);
+      benchmark::DoNotOptimize(result);
+      benchmark::DoNotOptimize(c);
+      benchmark::DoNotOptimize(out);
+      benchmark::DoNotOptimize(x);
+      benchmark::ClobberMemory();
+    }
+  };
+  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+// Create a sequence of the form xyxyxyxyxyxyxyxyxyxy and remove
+// the x's from it.
+template <class Container, class Operation>
+void bm_sprinkled(std::string operation_name, Operation remove_copy) {
+  auto bench = [remove_copy](auto& st) {
+    std::size_t const size = st.range(0);
+    using ValueType        = typename Container::value_type;
+    Container c;
+    ValueType x = Generate<ValueType>::random();
+    ValueType y = Generate<ValueType>::random();
+    for (std::size_t i = 0; i != size; ++i) {
+      c.push_back(i % 2 == 0 ? x : y);
+    }
+
+    std::vector<ValueType> out(size);
+
+    for ([[maybe_unused]] auto _ : st) {
+      auto result = remove_copy(c.begin(), c.end(), out.begin(), x);
+      benchmark::DoNotOptimize(result);
+      benchmark::DoNotOptimize(c);
+      benchmark::DoNotOptimize(out);
+      benchmark::DoNotOptimize(x);
+      benchmark::ClobberMemory();
+    }
+  };
+  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+int main(int argc, char** argv) {
+  auto std_remove_copy = [](auto first, auto last, auto out, auto const& value) {
+    return std::remove_copy(first, last, out, value);
+  };
+  auto ranges_remove_copy = [](auto first, auto last, auto out, auto const& value) {
+    return std::ranges::remove_copy(first, last, out, value);
+  };
+
+  // std::remove_copy
+  bm_prefix<std::vector<int>>("std::remove_copy(vector<int>) (prefix)", std_remove_copy);
+  bm_sprinkled<std::vector<int>>("std::remove_copy(vector<int>) (sprinkled)", std_remove_copy);
+
+  bm_prefix<std::deque<int>>("std::remove_copy(deque<int>) (prefix)", std_remove_copy);
+  bm_sprinkled<std::deque<int>>("std::remove_copy(deque<int>) (sprinkled)", std_remove_copy);
+
+  bm_prefix<std::list<int>>("std::remove_copy(list<int>) (prefix)", std_remove_copy);
+  bm_sprinkled<std::list<int>>("std::remove_copy(list<int>) (sprinkled)", std_remove_copy);
+
+  // ranges::remove_copy
+  bm_prefix<std::vector<int>>("ranges::remove_copy(vector<int>) (prefix)", ranges_remove_copy);
+  bm_sprinkled<std::vector<int>>("ranges::remove_copy(vector<int>) (sprinkled)", ranges_remove_copy);
+
+  bm_prefix<std::deque<int>>("ranges::remove_copy(deque<int>) (prefix)", ranges_remove_copy);
+  bm_sprinkled<std::deque<int>>("ranges::remove_copy(deque<int>) (sprinkled)", ranges_remove_copy);
+
+  bm_prefix<std::list<int>>("ranges::remove_copy(list<int>) (prefix)", ranges_remove_copy);
+  bm_sprinkled<std::list<int>>("ranges::remove_copy(list<int>) (sprinkled)", ranges_remove_copy);
+
+  benchmark::Initialize(&argc, argv);
+  benchmark::RunSpecifiedBenchmarks();
+  benchmark::Shutdown();
+  return 0;
+}
diff --git a/libcxx/test/benchmarks/algorithms/modifying/remove_copy_if.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/remove_copy_if.bench.cpp
new file mode 100644
index 0000000000000..95b0e93362bab
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/modifying/remove_copy_if.bench.cpp
@@ -0,0 +1,119 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+#include <algorithm>
+#include <cstddef>
+#include <deque>
+#include <iterator>
+#include <list>
+#include <string>
+#include <vector>
+
+#include "benchmark/benchmark.h"
+#include "../../GenerateInput.h"
+
+// Create a sequence of the form xxxxxxxxxxyyyyyyyyyy and remove
+// the prefix of x's from it.
+template <class Container, class Operation>
+void bm_prefix(std::string operation_name, Operation remove_copy_if) {
+  auto bench = [remove_copy_if](auto& st) {
+    std::size_t const size = st.range(0);
+    using ValueType        = typename Container::value_type;
+    Container c;
+    ValueType x = Generate<ValueType>::random();
+    ValueType y = Generate<ValueType>::random();
+    std::fill_n(std::back_inserter(c), size / 2, x);
+    std::fill_n(std::back_inserter(c), size / 2, y);
+
+    auto pred = [&](auto& element) {
+      benchmark::DoNotOptimize(element);
+      return element == x;
+    };
+
+    std::vector<ValueType> out(size);
+
+    for ([[maybe_unused]] auto _ : st) {
+      auto result = remove_copy_if(c.begin(), c.end(), out.begin(), pred);
+      benchmark::DoNotOptimize(result);
+      benchmark::DoNotOptimize(c);
+      benchmark::DoNotOptimize(out);
+      benchmark::DoNotOptimize(x);
+      benchmark::ClobberMemory();
+    }
+  };
+  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+// Create a sequence of the form xyxyxyxyxyxyxyxyxyxy and remove
+// the x's from it.
+template <class Container, class Operation>
+void bm_sprinkled(std::string operation_name, Operation remove_copy_if) {
+  auto bench = [remove_copy_if](auto& st) {
+    std::size_t const size = st.range(0);
+    using ValueType        = typename Container::value_type;
+    Container c;
+    ValueType x = Generate<ValueType>::random();
+    ValueType y = Generate<ValueType>::random();
+    for (std::size_t i = 0; i != size; ++i) {
+      c.push_back(i % 2 == 0 ? x : y);
+    }
+
+    auto pred = [&](auto& element) {
+      benchmark::DoNotOptimize(element);
+      return element == x;
+    };
+
+    std::vector<ValueType> out(size);
+
+    for ([[maybe_unused]] auto _ : st) {
+      auto result = remove_copy_if(c.begin(), c.end(), out.begin(), pred);
+      benchmark::DoNotOptimize(result);
+      benchmark::DoNotOptimize(c);
+      benchmark::DoNotOptimize(out);
+      benchmark::DoNotOptimize(x);
+      benchmark::ClobberMemory();
+    }
+  };
+  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+int main(int argc, char** argv) {
+  auto std_remove_copy_if = [](auto first, auto last, auto out, auto pred) {
+    return std::remove_copy_if(first, last, out, pred);
+  };
+  auto ranges_remove_copy_if = [](auto first, auto last, auto out, auto pred) {
+    return std::ranges::remove_copy_if(first, last, out, pred);
+  };
+
+  // std::remove_copy_if
+  bm_prefix<std::vector<int>>("std::remove_copy_if(vector<int>) (prefix)", std_remove_copy_if);
+  bm_sprinkled<std::vector<int>>("std::remove_copy_if(vector<int>) (sprinkled)", std_remove_copy_if);
+
+  bm_prefix<std::deque<int>>("std::remove_copy_if(deque<int>) (prefix)", std_remove_copy_if);
+  bm_sprinkled<std::deque<int>>("std::remove_copy_if(deque<int>) (sprinkled)", std_remove_copy_if);
+
+  bm_prefix<std::list<int>>("std::remove_copy_if(list<int>) (prefix)", std_remove_copy_if);
+  bm_sprinkled<std::list<int>>("std::remove_copy_if(list<int>) (sprinkled)", std_remove_copy_if);
+
+  // ranges::remove_copy_if
+  bm_prefix<std::vector<int>>("ranges::remove_copy_if(vector<int>) (prefix)", ranges_remove_copy_if);
+  bm_sprinkled<std::vector<int>>("ranges::remove_copy_if(vector<int>) (sprinkled)", ranges_remove_copy_if);
+
+  bm_prefix<std::deque<int>>("ranges::remove_copy_if(deque<int>) (prefix)", ranges_remove_copy_if);
+  bm_sprinkled<std::deque<int>>("ranges::remove_copy_if(deque<int>) (sprinkled)", ranges_remove_copy_if);
+
+  bm_prefix<std::list<int>>("ranges::remove_copy_if(list<int>) (prefix)", ranges_remove_copy_if);
+  bm_sprinkled<std::list<int>>("ranges::remove_copy_if(list<int>) (sprinkled)", ranges_remove_copy_if);
+
+  benchmark::Initialize(&argc, argv);
+  benchmark::RunSpecifiedBenchmarks();
+  benchmark::Shutdown();
+  return 0;
+}
diff --git a/libcxx/test/benchmarks/algorithms/modifying/remove_if.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/remove_if.bench.cpp
new file mode 100644
index 0000000000000..db0dabfbaa2c3
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/modifying/remove_if.bench.cpp
@@ -0,0 +1,143 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+#include <algorithm>
+#include <cstddef>
+#include <deque>
+#include <iterator>
+#include <list>
+#include <string>
+#include <vector>
+
+#include "benchmark/benchmark.h"
+#include "../../GenerateInput.h"
+
+// Create a sequence of the form xxxxxxxxxxyyyyyyyyyy and remove
+// the prefix of x's from it.
+//
+// We perform this benchmark in a batch because we need to restore the
+// state of the container after the operation.
+template <class Container, class Operation>
+void bm_prefix(std::string operation_name, Operation remove_if) {
+  auto bench = [remove_if](auto& st) {
+    std::size_t const size          = st.range(0);
+    constexpr std::size_t BatchSize = 10;
+    using ValueType                 = typename Container::value_type;
+    Container c[BatchSize];
+    ValueType x = Generate<ValueType>::random();
+    ValueType y = Generate<ValueType>::random();
+    for (std::size_t i = 0; i != BatchSize; ++i) {
+      c[i]      = Container(size);
+      auto half = size / 2;
+      std::fill_n(std::fill_n(c[i].begin(), half, x), half, y);
+    }
+
+    auto pred = [&](auto& element) {
+      benchmark::DoNotOptimize(element);
+      return element == x;
+    };
+
+    while (st.KeepRunningBatch(BatchSize)) {
+      for (std::size_t i = 0; i != BatchSize; ++i) {
+        auto result = remove_if(c[i].begin(), c[i].end(), pred);
+        benchmark::DoNotOptimize(result);
+        benchmark::DoNotOptimize(c[i]);
+        benchmark::DoNotOptimize(x);
+        benchmark::ClobberMemory();
+      }
+
+      st.PauseTiming();
+      for (std::size_t i = 0; i != BatchSize; ++i) {
+        auto half = size / 2;
+        std::fill_n(std::fill_n(c[i].begin(), half, x), half, y);
+      }
+      st.ResumeTiming();
+    }
+  };
+  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+// Create a sequence of the form xyxyxyxyxyxyxyxyxyxy and remove
+// the x's from it.
+//
+// We perform this benchmark in a batch because we need to restore the
+// state of the container after the operation.
+template <class Container, class Operation>
+void bm_sprinkled(std::string operation_name, Operation remove_if) {
+  auto bench = [remove_if](auto& st) {
+    std::size_t const size          = st.range(0);
+    constexpr std::size_t BatchSize = 10;
+    using ValueType                 = typename Container::value_type;
+    Container c[BatchSize];
+    ValueType x    = Generate<ValueType>::random();
+    ValueType y    = Generate<ValueType>::random();
+    auto alternate = [&](auto out, auto n) {
+      for (std::size_t i = 0; i != n; ++i) {
+        *out++ = (i % 2 == 0 ? x : y);
+      }
+    };
+    for (std::size_t i = 0; i != BatchSize; ++i) {
+      c[i] = Container(size);
+      alternate(c[i].begin(), size);
+    }
+
+    auto pred = [&](auto& element) {
+      benchmark::DoNotOptimize(element);
+      return element == x;
+    };
+
+    while (st.KeepRunningBatch(BatchSize)) {
+      for (std::size_t i = 0; i != BatchSize; ++i) {
+        auto result = remove_if(c[i].begin(), c[i].end(), pred);
+        benchmark::DoNotOptimize(result);
+        benchmark::DoNotOptimize(c[i]);
+        benchmark::DoNotOptimize(x);
+        benchmark::ClobberMemory();
+      }
+
+      st.PauseTiming();
+      for (std::size_t i = 0; i != BatchSize; ++i) {
+        alternate(c[i].begin(), size);
+      }
+      st.ResumeTiming();
+    }
+  };
+  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+int main(int argc, char** argv) {
+  auto std_remove_if    = [](auto first, auto last, auto pred) { return std::remove_if(first, last, pred); };
+  auto ranges_remove_if = [](auto first, auto last, auto pred) { return std::ranges::remove_if(first, last, pred); };
+
+  // std::remove_if
+  bm_prefix<std::vector<int>>("std::remove_if(vector<int>) (prefix)", std_remove_if);
+  bm_sprinkled<std::vector<int>>("std::remove_if(vector<int>) (sprinkled)", std_remove_if);
+
+  bm_prefix<std::deque<int>>("std::remove_if(deque<int>) (prefix)", std_remove_if);
+  bm_sprinkled<std::deque<int>>("std::remove_if(deque<int>) (sprinkled)", std_remove_if);
+
+  bm_prefix<std::list<int>>("std::remove_if(list<int>) (prefix)", std_remove_if);
+  bm_sprinkled<std::list<int>>("std::remove_if(list<int>) (sprinkled)", std_remove_if);
+
+  // ranges::remove_if
+  bm_prefix<std::vector<int>>("ranges::remove_if(vector<int>) (prefix)", ranges_remove_if);
+  bm_sprinkled<std::vector<int>>("ranges::remove_if(vector<int>) (sprinkled)", ranges_remove_if);
+
+  bm_prefix<std::deque<int>>("ranges::remove_if(deque<int>) (prefix)", ranges_remove_if);
+  bm_sprinkled<std::deque<int>>("ranges::remove_if(deque<int>) (sprinkled)", ranges_remove_if);
+
+  bm_prefix<std::list<int>>("ranges::remove_if(list<int>) (prefix)", ranges_remove_if);
+  bm_sprinkled<std::list<int>>("ranges::remove_if(list<int>) (sprinkled)", ranges_remove_if);
+
+  benchmark::Initialize(&argc, argv);
+  benchmark::RunSpecifiedBenchmarks();
+  benchmark::Shutdown();
+  return 0;
+}
diff --git a/libcxx/test/benchmarks/algorithms/modifying/replace.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/replace.bench.cpp
new file mode 100644
index 0000000000000..b55790d4db017
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/modifying/replace.bench.cpp
@@ -0,0 +1,107 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+#include <algorithm>
+#include <cstddef>
+#include <deque>
+#include <iterator>
+#include <list>
+#include <string>
+#include <vector>
+
+#include "benchmark/benchmark.h"
+#include "../../GenerateInput.h"
+
+// Create a sequence of the form xxxxxxxxxxyyyyyyyyyy, replace
+// into zzzzzzzzzzzyyyyyyyyyy and then back.
+//
+// This measures the performance of replace() when replacing a large
+// contiguous sequence of equal values.
+template <class Container, class Operation>
+void bm_prefix(std::string operation_name, Operation replace) {
+  auto bench = [replace](auto& st) {
+    std::size_t const size = st.range(0);
+    using ValueType        = typename Container::value_type;
+    Container c;
+    ValueType x = Generate<ValueType>::random();
+    ValueType y = Generate<ValueType>::random();
+    ValueType z = Generate<ValueType>::random();
+    std::fill_n(std::back_inserter(c), size / 2, x);
+    std::fill_n(std::back_inserter(c), size / 2, y);
+
+    for ([[maybe_unused]] auto _ : st) {
+      replace(c.begin(), c.end(), x, z);
+      std::swap(x, z);
+      benchmark::DoNotOptimize(c);
+      benchmark::DoNotOptimize(x);
+      benchmark::DoNotOptimize(z);
+      benchmark::ClobberMemory();
+    }
+  };
+  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+// Sprinkle elements to replace inside the range, like xyxyxyxyxyxyxyxyxyxy.
+template <class Container, class Operation>
+void bm_sprinkled(std::string operation_name, Operation replace) {
+  auto bench = [replace](auto& st) {
+    std::size_t const size = st.range(0);
+    using ValueType        = typename Container::value_type;
+    Container c;
+    ValueType x = Generate<ValueType>::random();
+    ValueType y = Generate<ValueType>::random();
+    ValueType z = Generate<ValueType>::random();
+    for (std::size_t i = 0; i != size; ++i) {
+      c.push_back(i % 2 == 0 ? x : y);
+    }
+
+    for ([[maybe_unused]] auto _ : st) {
+      replace(c.begin(), c.end(), x, z);
+      std::swap(x, z);
+      benchmark::DoNotOptimize(c);
+      benchmark::DoNotOptimize(x);
+      benchmark::DoNotOptimize(z);
+      benchmark::ClobberMemory();
+    }
+  };
+  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+int main(int argc, char** argv) {
+  auto std_replace    = [](auto first, auto last, auto old, auto new_) { return std::replace(first, last, old, new_); };
+  auto ranges_replace = [](auto first, auto last, auto old, auto new_) {
+    return std::ranges::replace(first, last, old, new_);
+  };
+
+  // std::replace
+  bm_prefix<std::vector<int>>("std::replace(vector<int>) (prefix)", std_replace);
+  bm_sprinkled<std::vector<int>>("std::replace(vector<int>) (sprinkled)", std_replace);
+
+  bm_prefix<std::deque<int>>("std::replace(deque<int>) (prefix)", std_replace);
+  bm_sprinkled<std::deque<int>>("std::replace(deque<int>) (sprinkled)", std_replace);
+
+  bm_prefix<std::list<int>>("std::replace(list<int>) (prefix)", std_replace);
+  bm_sprinkled<std::list<int>>("std::replace(list<int>) (sprinkled)", std_replace);
+
+  // ranges::replace
+  bm_prefix<std::vector<int>>("ranges::replace(vector<int>) (prefix)", ranges_replace);
+  bm_sprinkled<std::vector<int>>("ranges::replace(vector<int>) (sprinkled)", ranges_replace);
+
+  bm_prefix<std::deque<int>>("ranges::replace(deque<int>) (prefix)", ranges_replace);
+  bm_sprinkled<std::deque<int>>("ranges::replace(deque<int>) (sprinkled)", ranges_replace);
+
+  bm_prefix<std::list<int>>("ranges::replace(list<int>) (prefix)", ranges_replace);
+  bm_sprinkled<std::list<int>>("ranges::replace(list<int>) (sprinkled)", ranges_replace);
+
+  benchmark::Initialize(&argc, argv);
+  benchmark::RunSpecifiedBenchmarks();
+  benchmark::Shutdown();
+  return 0;
+}
diff --git a/libcxx/test/benchmarks/algorithms/modifying/replace_if.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/replace_if.bench.cpp
new file mode 100644
index 0000000000000..820cf08e5a901
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/modifying/replace_if.bench.cpp
@@ -0,0 +1,117 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+#include <algorithm>
+#include <cstddef>
+#include <deque>
+#include <iterator>
+#include <list>
+#include <string>
+#include <vector>
+
+#include "benchmark/benchmark.h"
+#include "../../GenerateInput.h"
+
+// Create a sequence of the form xxxxxxxxxxyyyyyyyyyy, replace
+// into zzzzzzzzzzzyyyyyyyyyy and then back.
+//
+// This measures the performance of replace_if() when replacing a large
+// contiguous sequence of equal values.
+template <class Container, class Operation>
+void bm_prefix(std::string operation_name, Operation replace_if) {
+  auto bench = [replace_if](auto& st) {
+    std::size_t const size = st.range(0);
+    using ValueType        = typename Container::value_type;
+    Container c;
+    ValueType x = Generate<ValueType>::random();
+    ValueType y = Generate<ValueType>::random();
+    ValueType z = Generate<ValueType>::random();
+    std::fill_n(std::back_inserter(c), size / 2, x);
+    std::fill_n(std::back_inserter(c), size / 2, y);
+
+    for ([[maybe_unused]] auto _ : st) {
+      auto pred = [&x](auto& element) {
+        benchmark::DoNotOptimize(element);
+        return element == x;
+      };
+      replace_if(c.begin(), c.end(), pred, z);
+      std::swap(x, z);
+      benchmark::DoNotOptimize(c);
+      benchmark::DoNotOptimize(x);
+      benchmark::DoNotOptimize(z);
+      benchmark::ClobberMemory();
+    }
+  };
+  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+// Sprinkle elements to replace inside the range, like xyxyxyxyxyxyxyxyxyxy.
+template <class Container, class Operation>
+void bm_sprinkled(std::string operation_name, Operation replace_if) {
+  auto bench = [replace_if](auto& st) {
+    std::size_t const size = st.range(0);
+    using ValueType        = typename Container::value_type;
+    Container c;
+    ValueType x = Generate<ValueType>::random();
+    ValueType y = Generate<ValueType>::random();
+    ValueType z = Generate<ValueType>::random();
+    for (std::size_t i = 0; i != size; ++i) {
+      c.push_back(i % 2 == 0 ? x : y);
+    }
+
+    for ([[maybe_unused]] auto _ : st) {
+      auto pred = [&x](auto& element) {
+        benchmark::DoNotOptimize(element);
+        return element == x;
+      };
+      replace_if(c.begin(), c.end(), pred, z);
+      std::swap(x, z);
+      benchmark::DoNotOptimize(c);
+      benchmark::DoNotOptimize(x);
+      benchmark::DoNotOptimize(z);
+      benchmark::ClobberMemory();
+    }
+  };
+  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+int main(int argc, char** argv) {
+  auto std_replace_if = [](auto first, auto last, auto pred, auto new_) {
+    return std::replace_if(first, last, pred, new_);
+  };
+  auto ranges_replace_if = [](auto first, auto last, auto pred, auto new_) {
+    return std::ranges::replace_if(first, last, pred, new_);
+  };
+
+  // std::replace_if
+  bm_prefix<std::vector<int>>("std::replace_if(vector<int>) (prefix)", std_replace_if);
+  bm_sprinkled<std::vector<int>>("std::replace_if(vector<int>) (sprinkled)", std_replace_if);
+
+  bm_prefix<std::deque<int>>("std::replace_if(deque<int>) (prefix)", std_replace_if);
+  bm_sprinkled<std::deque<int>>("std::replace_if(deque<int>) (sprinkled)", std_replace_if);
+
+  bm_prefix<std::list<int>>("std::replace_if(list<int>) (prefix)", std_replace_if);
+  bm_sprinkled<std::list<int>>("std::replace_if(list<int>) (sprinkled)", std_replace_if);
+
+  // ranges::replace_if
+  bm_prefix<std::vector<int>>("ranges::replace_if(vector<int>) (prefix)", ranges_replace_if);
+  bm_sprinkled<std::vector<int>>("ranges::replace_if(vector<int>) (sprinkled)", ranges_replace_if);
+
+  bm_prefix<std::deque<int>>("ranges::replace_if(deque<int>) (prefix)", ranges_replace_if);
+  bm_sprinkled<std::deque<int>>("ranges::replace_if(deque<int>) (sprinkled)", ranges_replace_if);
+
+  bm_prefix<std::list<int>>("ranges::replace_if(list<int>) (prefix)", ranges_replace_if);
+  bm_sprinkled<std::list<int>>("ranges::replace_if(list<int>) (sprinkled)", ranges_replace_if);
+
+  benchmark::Initialize(&argc, argv);
+  benchmark::RunSpecifiedBenchmarks();
+  benchmark::Shutdown();
+  return 0;
+}
diff --git a/libcxx/test/benchmarks/algorithms/modifying/reverse.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/reverse.bench.cpp
new file mode 100644
index 0000000000000..dbb0d43d091c3
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/modifying/reverse.bench.cpp
@@ -0,0 +1,57 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+#include <algorithm>
+#include <cstddef>
+#include <deque>
+#include <iterator>
+#include <list>
+#include <string>
+#include <vector>
+
+#include "benchmark/benchmark.h"
+#include "../../GenerateInput.h"
+
+template <class Container, class Operation>
+void bm(std::string operation_name, Operation reverse) {
+  auto bench = [reverse](auto& st) {
+    std::size_t const size = st.range(0);
+    using ValueType        = typename Container::value_type;
+    Container c;
+    std::generate_n(std::back_inserter(c), size, [] { return Generate<ValueType>::random(); });
+
+    for ([[maybe_unused]] auto _ : st) {
+      reverse(c.begin(), c.end());
+      benchmark::DoNotOptimize(c);
+      benchmark::ClobberMemory();
+    }
+  };
+  benchmark::RegisterBenchmark(operation_name, bench)->Range(8, 1 << 15);
+}
+
+int main(int argc, char** argv) {
+  auto std_reverse    = [](auto first, auto last) { return std::reverse(first, last); };
+  auto ranges_reverse = [](auto first, auto last) { return std::ranges::reverse(first, last); };
+
+  // std::reverse
+  bm<std::vector<int>>("std::reverse(vector<int>)", std_reverse);
+  bm<std::deque<int>>("std::reverse(deque<int>)", std_reverse);
+  bm<std::list<int>>("std::reverse(list<int>)", std_reverse);
+
+  // ranges::reverse
+  bm<std::vector<int>>("ranges::reverse(vector<int>)", ranges_reverse);
+  bm<std::deque<int>>("ranges::reverse(deque<int>)", ranges_reverse);
+  bm<std::list<int>>("ranges::reverse(list<int>)", ranges_reverse);
+
+  benchmark::Initialize(&argc, argv);
+  benchmark::RunSpecifiedBenchmarks();
+  benchmark::Shutdown();
+  return 0;
+}
diff --git a/libcxx/test/benchmarks/algorithms/modifying/reverse_copy.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/reverse_copy.bench.cpp
new file mode 100644
index 0000000000000..84322fbfff40c
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/modifying/reverse_copy.bench.cpp
@@ -0,0 +1,61 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+#include <algorithm>
+#include <cstddef>
+#include <deque>
+#include <iterator>
+#include <list>
+#include <string>
+#include <vector>
+
+#include "benchmark/benchmark.h"
+#include "../../GenerateInput.h"
+
+template <class Container, class Operation>
+void bm(std::string operation_name, Operation reverse_copy) {
+  auto bench = [reverse_copy](auto& st) {
+    std::size_t const size = st.range(0);
+    using ValueType        = typename Container::value_type;
+    Container c;
+    std::generate_n(std::back_inserter(c), size, [] { return Generate<ValueType>::random(); });
+
+    std::vector<ValueType> out(size);
+
+    for ([[maybe_unused]] auto _ : st) {
+      reverse_copy(c.begin(), c.end(), out.begin());
+      benchmark::DoNotOptimize(c);
+      benchmark::ClobberMemory();
+    }
+  };
+  benchmark::RegisterBenchmark(operation_name, bench)->Range(8, 1 << 15);
+}
+
+int main(int argc, char** argv) {
+  auto std_reverse_copy    = [](auto first, auto last, auto out) { return std::reverse_copy(first, last, out); };
+  auto ranges_reverse_copy = [](auto first, auto last, auto out) {
+    return std::ranges::reverse_copy(first, last, out);
+  };
+
+  // std::reverse_copy
+  bm<std::vector<int>>("std::reverse_copy(vector<int>)", std_reverse_copy);
+  bm<std::deque<int>>("std::reverse_copy(deque<int>)", std_reverse_copy);
+  bm<std::list<int>>("std::reverse_copy(list<int>)", std_reverse_copy);
+
+  // ranges::reverse_copy
+  bm<std::vector<int>>("ranges::reverse_copy(vector<int>)", ranges_reverse_copy);
+  bm<std::deque<int>>("ranges::reverse_copy(deque<int>)", ranges_reverse_copy);
+  bm<std::list<int>>("ranges::reverse_copy(list<int>)", ranges_reverse_copy);
+
+  benchmark::Initialize(&argc, argv);
+  benchmark::RunSpecifiedBenchmarks();
+  benchmark::Shutdown();
+  return 0;
+}
diff --git a/libcxx/test/benchmarks/algorithms/modifying/rotate.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/rotate.bench.cpp
new file mode 100644
index 0000000000000..eb91a011d863a
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/modifying/rotate.bench.cpp
@@ -0,0 +1,59 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+#include <algorithm>
+#include <cstddef>
+#include <deque>
+#include <iterator>
+#include <list>
+#include <string>
+#include <vector>
+
+#include "benchmark/benchmark.h"
+#include "../../GenerateInput.h"
+
+template <class Container, class Operation>
+void bm(std::string operation_name, Operation rotate) {
+  auto bench = [rotate](auto& st) {
+    std::size_t const size = st.range(0);
+    using ValueType        = typename Container::value_type;
+    Container c;
+    std::generate_n(std::back_inserter(c), size, [] { return Generate<ValueType>::random(); });
+
+    auto middle = std::next(c.begin(), size / 2);
+    for ([[maybe_unused]] auto _ : st) {
+      auto result = rotate(c.begin(), middle, c.end());
+      benchmark::DoNotOptimize(result);
+      benchmark::DoNotOptimize(c);
+      benchmark::ClobberMemory();
+    }
+  };
+  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+int main(int argc, char** argv) {
+  auto std_rotate    = [](auto first, auto middle, auto last) { return std::rotate(first, middle, last); };
+  auto ranges_rotate = [](auto first, auto middle, auto last) { return std::ranges::rotate(first, middle, last); };
+
+  // std::rotate
+  bm<std::vector<int>>("std::rotate(vector<int>)", std_rotate);
+  bm<std::deque<int>>("std::rotate(deque<int>)", std_rotate);
+  bm<std::list<int>>("std::rotate(list<int>)", std_rotate);
+
+  // ranges::rotate
+  bm<std::vector<int>>("ranges::rotate(vector<int>)", ranges_rotate);
+  bm<std::deque<int>>("ranges::rotate(deque<int>)", ranges_rotate);
+  bm<std::list<int>>("ranges::rotate(list<int>)", ranges_rotate);
+
+  benchmark::Initialize(&argc, argv);
+  benchmark::RunSpecifiedBenchmarks();
+  benchmark::Shutdown();
+  return 0;
+}
diff --git a/libcxx/test/benchmarks/algorithms/modifying/rotate_copy.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/rotate_copy.bench.cpp
new file mode 100644
index 0000000000000..f5c14640fa87d
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/modifying/rotate_copy.bench.cpp
@@ -0,0 +1,65 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+#include <algorithm>
+#include <cstddef>
+#include <deque>
+#include <iterator>
+#include <list>
+#include <string>
+#include <vector>
+
+#include "benchmark/benchmark.h"
+#include "../../GenerateInput.h"
+
+template <class Container, class Operation>
+void bm(std::string operation_name, Operation rotate_copy) {
+  auto bench = [rotate_copy](auto& st) {
+    std::size_t const size = st.range(0);
+    using ValueType        = typename Container::value_type;
+    Container c;
+    std::generate_n(std::back_inserter(c), size, [] { return Generate<ValueType>::random(); });
+
+    std::vector<ValueType> out(size);
+
+    auto middle = std::next(c.begin(), size / 2);
+    for ([[maybe_unused]] auto _ : st) {
+      auto result = rotate_copy(c.begin(), middle, c.end(), out.begin());
+      benchmark::DoNotOptimize(result);
+      benchmark::DoNotOptimize(c);
+      benchmark::ClobberMemory();
+    }
+  };
+  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+int main(int argc, char** argv) {
+  auto std_rotate_copy = [](auto first, auto middle, auto last, auto out) {
+    return std::rotate_copy(first, middle, last, out);
+  };
+  auto ranges_rotate_copy = [](auto first, auto middle, auto last, auto out) {
+    return std::ranges::rotate_copy(first, middle, last, out);
+  };
+
+  // std::rotate_copy
+  bm<std::vector<int>>("std::rotate_copy(vector<int>)", std_rotate_copy);
+  bm<std::deque<int>>("std::rotate_copy(deque<int>)", std_rotate_copy);
+  bm<std::list<int>>("std::rotate_copy(list<int>)", std_rotate_copy);
+
+  // ranges::rotate_copy
+  bm<std::vector<int>>("ranges::rotate_copy(vector<int>)", ranges_rotate_copy);
+  bm<std::deque<int>>("ranges::rotate_copy(deque<int>)", ranges_rotate_copy);
+  bm<std::list<int>>("ranges::rotate_copy(list<int>)", ranges_rotate_copy);
+
+  benchmark::Initialize(&argc, argv);
+  benchmark::RunSpecifiedBenchmarks();
+  benchmark::Shutdown();
+  return 0;
+}
diff --git a/libcxx/test/benchmarks/algorithms/modifying/sample.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/sample.bench.cpp
new file mode 100644
index 0000000000000..5f783efe8f627
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/modifying/sample.bench.cpp
@@ -0,0 +1,68 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+#include <algorithm>
+#include <cstddef>
+#include <deque>
+#include <iterator>
+#include <list>
+#include <random>
+#include <string>
+#include <vector>
+
+#include "benchmark/benchmark.h"
+#include "../../GenerateInput.h"
+
+template <class Container, class Operation>
+void bm(std::string operation_name, Operation sample) {
+  auto bench = [sample](auto& st) {
+    std::size_t const size = st.range(0);
+    using ValueType        = typename Container::value_type;
+    Container c;
+    std::generate_n(std::back_inserter(c), size, [] { return Generate<ValueType>::random(); });
+
+    std::vector<ValueType> out(size);
+    auto const n = size / 4; // sample 1/4 of the range
+    std::mt19937 rng;
+
+    for ([[maybe_unused]] auto _ : st) {
+      auto result = sample(c.begin(), c.end(), out.begin(), n, rng);
+      benchmark::DoNotOptimize(result);
+      benchmark::DoNotOptimize(c);
+      benchmark::DoNotOptimize(out);
+      benchmark::ClobberMemory();
+    }
+  };
+  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+int main(int argc, char** argv) {
+  auto std_sample = [](auto first, auto last, auto out, auto n, auto& rng) {
+    return std::sample(first, last, out, n, rng);
+  };
+  auto ranges_sample = [](auto first, auto last, auto out, auto n, auto& rng) {
+    return std::ranges::sample(first, last, out, n, rng);
+  };
+
+  // std::sample
+  bm<std::vector<int>>("std::sample(vector<int>)", std_sample);
+  bm<std::deque<int>>("std::sample(deque<int>)", std_sample);
+  bm<std::list<int>>("std::sample(list<int>)", std_sample);
+
+  // ranges::sample
+  bm<std::vector<int>>("ranges::sample(vector<int>)", ranges_sample);
+  bm<std::deque<int>>("ranges::sample(deque<int>)", ranges_sample);
+  bm<std::list<int>>("ranges::sample(list<int>)", ranges_sample);
+
+  benchmark::Initialize(&argc, argv);
+  benchmark::RunSpecifiedBenchmarks();
+  benchmark::Shutdown();
+  return 0;
+}
diff --git a/libcxx/test/benchmarks/algorithms/modifying/shift_left.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/shift_left.bench.cpp
new file mode 100644
index 0000000000000..9cf428f67e03e
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/modifying/shift_left.bench.cpp
@@ -0,0 +1,56 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+#include <algorithm>
+#include <cstddef>
+#include <deque>
+#include <iterator>
+#include <list>
+#include <string>
+#include <vector>
+
+#include "benchmark/benchmark.h"
+#include "../../GenerateInput.h"
+
+template <class Container, class Operation>
+void bm(std::string operation_name, Operation shift_left) {
+  auto bench = [shift_left](auto& st) {
+    std::size_t const size = st.range(0);
+    using ValueType        = typename Container::value_type;
+    Container c;
+    std::generate_n(std::back_inserter(c), size, [] { return Generate<ValueType>::random(); });
+
+    auto const n = 9 * (size / 10); // shift all but 10% of the range
+
+    for ([[maybe_unused]] auto _ : st) {
+      auto result = shift_left(c.begin(), c.end(), n);
+      benchmark::DoNotOptimize(result);
+      benchmark::DoNotOptimize(c);
+      benchmark::ClobberMemory();
+    }
+  };
+  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+int main(int argc, char** argv) {
+  auto std_shift_left = [](auto first, auto last, auto n) { return std::shift_left(first, last, n); };
+
+  // std::shift_left
+  bm<std::vector<int>>("std::shift_left(vector<int>)", std_shift_left);
+  bm<std::deque<int>>("std::shift_left(deque<int>)", std_shift_left);
+  bm<std::list<int>>("std::shift_left(list<int>)", std_shift_left);
+
+  // ranges::shift_left not implemented yet
+
+  benchmark::Initialize(&argc, argv);
+  benchmark::RunSpecifiedBenchmarks();
+  benchmark::Shutdown();
+  return 0;
+}
diff --git a/libcxx/test/benchmarks/algorithms/modifying/shift_right.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/shift_right.bench.cpp
new file mode 100644
index 0000000000000..31a980ebdc5c1
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/modifying/shift_right.bench.cpp
@@ -0,0 +1,56 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+#include <algorithm>
+#include <cstddef>
+#include <deque>
+#include <iterator>
+#include <list>
+#include <string>
+#include <vector>
+
+#include "benchmark/benchmark.h"
+#include "../../GenerateInput.h"
+
+template <class Container, class Operation>
+void bm(std::string operation_name, Operation shift_right) {
+  auto bench = [shift_right](auto& st) {
+    std::size_t const size = st.range(0);
+    using ValueType        = typename Container::value_type;
+    Container c;
+    std::generate_n(std::back_inserter(c), size, [] { return Generate<ValueType>::random(); });
+
+    auto const n = 9 * (size / 10); // shift all but 10% of the range
+
+    for ([[maybe_unused]] auto _ : st) {
+      auto result = shift_right(c.begin(), c.end(), n);
+      benchmark::DoNotOptimize(result);
+      benchmark::DoNotOptimize(c);
+      benchmark::ClobberMemory();
+    }
+  };
+  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+int main(int argc, char** argv) {
+  auto std_shift_right = [](auto first, auto last, auto n) { return std::shift_right(first, last, n); };
+
+  // std::shift_right
+  bm<std::vector<int>>("std::shift_right(vector<int>)", std_shift_right);
+  bm<std::deque<int>>("std::shift_right(deque<int>)", std_shift_right);
+  bm<std::list<int>>("std::shift_right(list<int>)", std_shift_right);
+
+  // ranges::shift_right not implemented yet
+
+  benchmark::Initialize(&argc, argv);
+  benchmark::RunSpecifiedBenchmarks();
+  benchmark::Shutdown();
+  return 0;
+}
diff --git a/libcxx/test/benchmarks/algorithms/modifying/shuffle.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/shuffle.bench.cpp
new file mode 100644
index 0000000000000..cc483b631c2a4
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/modifying/shuffle.bench.cpp
@@ -0,0 +1,56 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+#include <algorithm>
+#include <cstddef>
+#include <deque>
+#include <iterator>
+#include <random>
+#include <string>
+#include <vector>
+
+#include "benchmark/benchmark.h"
+#include "../../GenerateInput.h"
+
+template <class Container, class Operation>
+void bm(std::string operation_name, Operation shuffle) {
+  auto bench = [shuffle](auto& st) {
+    std::size_t const size = st.range(0);
+    using ValueType        = typename Container::value_type;
+    Container c;
+    std::generate_n(std::back_inserter(c), size, [] { return Generate<ValueType>::random(); });
+    std::mt19937 rng;
+
+    for ([[maybe_unused]] auto _ : st) {
+      shuffle(c.begin(), c.end(), rng);
+      benchmark::DoNotOptimize(c);
+      benchmark::ClobberMemory();
+    }
+  };
+  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+int main(int argc, char** argv) {
+  auto std_shuffle    = [](auto first, auto last, auto& rng) { return std::shuffle(first, last, rng); };
+  auto ranges_shuffle = [](auto first, auto last, auto& rng) { return std::ranges::shuffle(first, last, rng); };
+
+  // std::shuffle
+  bm<std::vector<int>>("std::shuffle(vector<int>)", std_shuffle);
+  bm<std::deque<int>>("std::shuffle(deque<int>)", std_shuffle);
+
+  // ranges::shuffle
+  bm<std::vector<int>>("ranges::shuffle(vector<int>)", ranges_shuffle);
+  bm<std::deque<int>>("ranges::shuffle(deque<int>)", ranges_shuffle);
+
+  benchmark::Initialize(&argc, argv);
+  benchmark::RunSpecifiedBenchmarks();
+  benchmark::Shutdown();
+  return 0;
+}
diff --git a/libcxx/test/benchmarks/algorithms/modifying/swap_ranges.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/swap_ranges.bench.cpp
new file mode 100644
index 0000000000000..05b733fecc70d
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/modifying/swap_ranges.bench.cpp
@@ -0,0 +1,64 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+#include <algorithm>
+#include <cstddef>
+#include <deque>
+#include <iterator>
+#include <list>
+#include <string>
+#include <vector>
+
+#include "benchmark/benchmark.h"
+#include "../../GenerateInput.h"
+
+template <class Container, class Operation>
+void bm(std::string operation_name, Operation swap_ranges) {
+  auto bench = [swap_ranges](auto& st) {
+    std::size_t const size = st.range(0);
+    using ValueType        = typename Container::value_type;
+    Container c1, c2;
+    std::generate_n(std::back_inserter(c1), size, [] { return Generate<ValueType>::random(); });
+    std::generate_n(std::back_inserter(c2), size, [] { return Generate<ValueType>::random(); });
+
+    for ([[maybe_unused]] auto _ : st) {
+      auto result = swap_ranges(c1.begin(), c1.end(), c2.begin(), c2.end());
+      benchmark::DoNotOptimize(result);
+      benchmark::DoNotOptimize(c1);
+      benchmark::DoNotOptimize(c2);
+      benchmark::ClobberMemory();
+    }
+  };
+  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+int main(int argc, char** argv) {
+  auto std_swap_ranges = [](auto first1, auto last1, auto first2, auto) {
+    return std::swap_ranges(first1, last1, first2);
+  };
+  auto ranges_swap_ranges = [](auto first1, auto last1, auto first2, auto last2) {
+    return std::ranges::swap_ranges(first1, last1, first2, last2);
+  };
+
+  // std::swap_ranges
+  bm<std::vector<int>>("std::swap_ranges(vector<int>)", std_swap_ranges);
+  bm<std::deque<int>>("std::swap_ranges(deque<int>)", std_swap_ranges);
+  bm<std::list<int>>("std::swap_ranges(list<int>)", std_swap_ranges);
+
+  // ranges::swap_ranges
+  bm<std::vector<int>>("ranges::swap_ranges(vector<int>)", ranges_swap_ranges);
+  bm<std::deque<int>>("ranges::swap_ranges(deque<int>)", ranges_swap_ranges);
+  bm<std::list<int>>("ranges::swap_ranges(list<int>)", ranges_swap_ranges);
+
+  benchmark::Initialize(&argc, argv);
+  benchmark::RunSpecifiedBenchmarks();
+  benchmark::Shutdown();
+  return 0;
+}
diff --git a/libcxx/test/benchmarks/algorithms/modifying/transform.binary.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/transform.binary.bench.cpp
new file mode 100644
index 0000000000000..bdc913356d3c9
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/modifying/transform.binary.bench.cpp
@@ -0,0 +1,73 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+#include <algorithm>
+#include <cstddef>
+#include <deque>
+#include <iterator>
+#include <list>
+#include <string>
+#include <vector>
+
+#include "benchmark/benchmark.h"
+#include "../../GenerateInput.h"
+
+template <class Container, class Operation>
+void bm(std::string operation_name, Operation transform) {
+  auto bench = [transform](auto& st) {
+    std::size_t const size = st.range(0);
+    using ValueType        = typename Container::value_type;
+    Container c1, c2;
+    std::generate_n(std::back_inserter(c1), size, [] { return Generate<ValueType>::random(); });
+    std::generate_n(std::back_inserter(c2), size, [] { return Generate<ValueType>::random(); });
+
+    std::vector<ValueType> out(size);
+
+    auto f = [](auto& x, auto& y) {
+      benchmark::DoNotOptimize(x);
+      benchmark::DoNotOptimize(y);
+      return x + y;
+    };
+
+    for ([[maybe_unused]] auto _ : st) {
+      auto result = transform(c1.begin(), c1.end(), c2.begin(), c2.end(), out.begin(), f);
+      benchmark::DoNotOptimize(result);
+      benchmark::DoNotOptimize(out);
+      benchmark::DoNotOptimize(c1);
+      benchmark::DoNotOptimize(c2);
+      benchmark::ClobberMemory();
+    }
+  };
+  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+int main(int argc, char** argv) {
+  auto std_transform = [](auto first1, auto last1, auto first2, auto, auto out, auto f) {
+    return std::transform(first1, last1, first2, out, f);
+  };
+  auto ranges_transform = [](auto first1, auto last1, auto first2, auto last2, auto out, auto f) {
+    return std::ranges::transform(first1, last1, first2, last2, out, f);
+  };
+
+  // std::transform
+  bm<std::vector<int>>("std::transform(vector<int>, vector<int>)", std_transform);
+  bm<std::deque<int>>("std::transform(deque<int>, deque<int>)", std_transform);
+  bm<std::list<int>>("std::transform(list<int>, list<int>)", std_transform);
+
+  // ranges::transform
+  bm<std::vector<int>>("ranges::transform(vector<int>, vector<int>)", ranges_transform);
+  bm<std::deque<int>>("ranges::transform(deque<int>, deque<int>)", ranges_transform);
+  bm<std::list<int>>("ranges::transform(list<int>, list<int>)", ranges_transform);
+
+  benchmark::Initialize(&argc, argv);
+  benchmark::RunSpecifiedBenchmarks();
+  benchmark::Shutdown();
+  return 0;
+}
diff --git a/libcxx/test/benchmarks/algorithms/modifying/transform.unary.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/transform.unary.bench.cpp
new file mode 100644
index 0000000000000..6cf56368f63f3
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/modifying/transform.unary.bench.cpp
@@ -0,0 +1,68 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+#include <algorithm>
+#include <cstddef>
+#include <deque>
+#include <iterator>
+#include <list>
+#include <string>
+#include <vector>
+
+#include "benchmark/benchmark.h"
+#include "../../GenerateInput.h"
+
+template <class Container, class Operation>
+void bm(std::string operation_name, Operation transform) {
+  auto bench = [transform](auto& st) {
+    std::size_t const size = st.range(0);
+    using ValueType        = typename Container::value_type;
+    Container c;
+    std::generate_n(std::back_inserter(c), size, [] { return Generate<ValueType>::random(); });
+
+    std::vector<ValueType> out(size);
+
+    auto f = [](auto& element) {
+      benchmark::DoNotOptimize(element);
+      return element;
+    };
+
+    for ([[maybe_unused]] auto _ : st) {
+      auto result = transform(c.begin(), c.end(), out.begin(), f);
+      benchmark::DoNotOptimize(result);
+      benchmark::DoNotOptimize(out);
+      benchmark::DoNotOptimize(c);
+      benchmark::ClobberMemory();
+    }
+  };
+  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+int main(int argc, char** argv) {
+  auto std_transform    = [](auto first, auto last, auto out, auto f) { return std::transform(first, last, out, f); };
+  auto ranges_transform = [](auto first, auto last, auto out, auto f) {
+    return std::ranges::transform(first, last, out, f);
+  };
+
+  // std::transform
+  bm<std::vector<int>>("std::transform(vector<int>) (identity transform)", std_transform);
+  bm<std::deque<int>>("std::transform(deque<int>) (identity transform)", std_transform);
+  bm<std::list<int>>("std::transform(list<int>) (identity transform)", std_transform);
+
+  // ranges::transform
+  bm<std::vector<int>>("ranges::transform(vector<int>) (identity transform)", ranges_transform);
+  bm<std::deque<int>>("ranges::transform(deque<int>) (identity transform)", ranges_transform);
+  bm<std::list<int>>("ranges::transform(list<int>) (identity transform)", ranges_transform);
+
+  benchmark::Initialize(&argc, argv);
+  benchmark::RunSpecifiedBenchmarks();
+  benchmark::Shutdown();
+  return 0;
+}
diff --git a/libcxx/test/benchmarks/algorithms/modifying/unique.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/unique.bench.cpp
new file mode 100644
index 0000000000000..1d9cca2f60688
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/modifying/unique.bench.cpp
@@ -0,0 +1,132 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+#include <algorithm>
+#include <cstddef>
+#include <deque>
+#include <iterator>
+#include <list>
+#include <string>
+#include <vector>
+
+#include "benchmark/benchmark.h"
+#include "../../GenerateInput.h"
+
+// Create a sequence of the form xxxxxxxxxxyyyyyyyyyy and unique the
+// adjacent equal elements.
+//
+// We perform this benchmark in a batch because we need to restore the
+// state of the container after the operation.
+template <class Container, class Operation>
+void bm_contiguous(std::string operation_name, Operation unique) {
+  auto bench = [unique](auto& st) {
+    std::size_t const size          = st.range(0);
+    constexpr std::size_t BatchSize = 10;
+    using ValueType                 = typename Container::value_type;
+    Container c[BatchSize];
+    ValueType x = Generate<ValueType>::random();
+    ValueType y = Generate<ValueType>::random();
+    for (std::size_t i = 0; i != BatchSize; ++i) {
+      c[i]      = Container(size);
+      auto half = size / 2;
+      std::fill_n(std::fill_n(c[i].begin(), half, x), half, y);
+    }
+
+    while (st.KeepRunningBatch(BatchSize)) {
+      for (std::size_t i = 0; i != BatchSize; ++i) {
+        auto result = unique(c[i].begin(), c[i].end());
+        benchmark::DoNotOptimize(result);
+        benchmark::DoNotOptimize(c[i]);
+        benchmark::ClobberMemory();
+      }
+
+      st.PauseTiming();
+      for (std::size_t i = 0; i != BatchSize; ++i) {
+        auto half = size / 2;
+        std::fill_n(std::fill_n(c[i].begin(), half, x), half, y);
+      }
+      st.ResumeTiming();
+    }
+  };
+  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+// Create a sequence of the form xxyyxxyyxxyyxxyyxxyy and unique
+// adjacent equal elements.
+//
+// We perform this benchmark in a batch because we need to restore the
+// state of the container after the operation.
+template <class Container, class Operation>
+void bm_sprinkled(std::string operation_name, Operation unique) {
+  auto bench = [unique](auto& st) {
+    std::size_t const size          = st.range(0);
+    constexpr std::size_t BatchSize = 10;
+    using ValueType                 = typename Container::value_type;
+    Container c[BatchSize];
+    ValueType x    = Generate<ValueType>::random();
+    ValueType y    = Generate<ValueType>::random();
+    auto alternate = [&](auto out, auto n) {
+      for (std::size_t i = 0; i != n; i += 2) {
+        *out++ = (i % 4 == 0 ? x : y);
+        *out++ = (i % 4 == 0 ? x : y);
+      }
+    };
+    for (std::size_t i = 0; i != BatchSize; ++i) {
+      c[i] = Container(size);
+      alternate(c[i].begin(), size);
+    }
+
+    while (st.KeepRunningBatch(BatchSize)) {
+      for (std::size_t i = 0; i != BatchSize; ++i) {
+        auto result = unique(c[i].begin(), c[i].end());
+        benchmark::DoNotOptimize(result);
+        benchmark::DoNotOptimize(c[i]);
+        benchmark::ClobberMemory();
+      }
+
+      st.PauseTiming();
+      for (std::size_t i = 0; i != BatchSize; ++i) {
+        alternate(c[i].begin(), size);
+      }
+      st.ResumeTiming();
+    }
+  };
+  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+int main(int argc, char** argv) {
+  auto std_unique    = [](auto first, auto last) { return std::unique(first, last); };
+  auto ranges_unique = [](auto first, auto last) { return std::ranges::unique(first, last); };
+
+  // std::unique
+  bm_contiguous<std::vector<int>>("std::unique(vector<int>) (contiguous)", std_unique);
+  bm_sprinkled<std::vector<int>>("std::unique(vector<int>) (sprinkled)", std_unique);
+
+  bm_contiguous<std::deque<int>>("std::unique(deque<int>) (contiguous)", std_unique);
+  bm_sprinkled<std::deque<int>>("std::unique(deque<int>) (sprinkled)", std_unique);
+
+  bm_contiguous<std::list<int>>("std::unique(list<int>) (contiguous)", std_unique);
+  bm_sprinkled<std::list<int>>("std::unique(list<int>) (sprinkled)", std_unique);
+
+  // ranges::unique
+  bm_contiguous<std::vector<int>>("ranges::unique(vector<int>) (contiguous)", ranges_unique);
+  bm_sprinkled<std::vector<int>>("ranges::unique(vector<int>) (sprinkled)", ranges_unique);
+
+  bm_contiguous<std::deque<int>>("ranges::unique(deque<int>) (contiguous)", ranges_unique);
+  bm_sprinkled<std::deque<int>>("ranges::unique(deque<int>) (sprinkled)", ranges_unique);
+
+  bm_contiguous<std::list<int>>("ranges::unique(list<int>) (contiguous)", ranges_unique);
+  bm_sprinkled<std::list<int>>("ranges::unique(list<int>) (sprinkled)", ranges_unique);
+
+  benchmark::Initialize(&argc, argv);
+  benchmark::RunSpecifiedBenchmarks();
+  benchmark::Shutdown();
+  return 0;
+}
diff --git a/libcxx/test/benchmarks/algorithms/modifying/unique_copy.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/unique_copy.bench.cpp
new file mode 100644
index 0000000000000..c7b217ffd960d
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/modifying/unique_copy.bench.cpp
@@ -0,0 +1,105 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+#include <algorithm>
+#include <cstddef>
+#include <deque>
+#include <iterator>
+#include <list>
+#include <string>
+#include <vector>
+
+#include "benchmark/benchmark.h"
+#include "../../GenerateInput.h"
+
+// Create a sequence of the form xxxxxxxxxxyyyyyyyyyy and unique the
+// adjacent equal elements.
+template <class Container, class Operation>
+void bm_contiguous(std::string operation_name, Operation unique_copy) {
+  auto bench = [unique_copy](auto& st) {
+    std::size_t const size = st.range(0);
+    using ValueType        = typename Container::value_type;
+    Container c(size);
+    ValueType x = Generate<ValueType>::random();
+    ValueType y = Generate<ValueType>::random();
+    auto half   = size / 2;
+    std::fill_n(std::fill_n(c.begin(), half, x), half, y);
+
+    std::vector<ValueType> out(size);
+
+    for ([[maybe_unused]] auto _ : st) {
+      auto result = unique_copy(c.begin(), c.end(), out.begin());
+      benchmark::DoNotOptimize(result);
+      benchmark::DoNotOptimize(c);
+      benchmark::ClobberMemory();
+    }
+  };
+  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+// Create a sequence of the form xxyyxxyyxxyyxxyyxxyy and unique
+// adjacent equal elements.
+template <class Container, class Operation>
+void bm_sprinkled(std::string operation_name, Operation unique_copy) {
+  auto bench = [unique_copy](auto& st) {
+    std::size_t const size = st.range(0);
+    using ValueType        = typename Container::value_type;
+    Container c(size);
+    ValueType x    = Generate<ValueType>::random();
+    ValueType y    = Generate<ValueType>::random();
+    auto alternate = [&](auto out, auto n) {
+      for (std::size_t i = 0; i != n; i += 2) {
+        *out++ = (i % 4 == 0 ? x : y);
+        *out++ = (i % 4 == 0 ? x : y);
+      }
+    };
+    alternate(c.begin(), size);
+
+    std::vector<ValueType> out(size);
+
+    for ([[maybe_unused]] auto _ : st) {
+      auto result = unique_copy(c.begin(), c.end(), out.begin());
+      benchmark::DoNotOptimize(result);
+      benchmark::DoNotOptimize(c);
+      benchmark::ClobberMemory();
+    }
+  };
+  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+int main(int argc, char** argv) {
+  auto std_unique_copy    = [](auto first, auto last, auto out) { return std::unique_copy(first, last, out); };
+  auto ranges_unique_copy = [](auto first, auto last, auto out) { return std::ranges::unique_copy(first, last, out); };
+
+  // std::unique_copy
+  bm_contiguous<std::vector<int>>("std::unique_copy(vector<int>) (contiguous)", std_unique_copy);
+  bm_sprinkled<std::vector<int>>("std::unique_copy(vector<int>) (sprinkled)", std_unique_copy);
+
+  bm_contiguous<std::deque<int>>("std::unique_copy(deque<int>) (contiguous)", std_unique_copy);
+  bm_sprinkled<std::deque<int>>("std::unique_copy(deque<int>) (sprinkled)", std_unique_copy);
+
+  bm_contiguous<std::list<int>>("std::unique_copy(list<int>) (contiguous)", std_unique_copy);
+  bm_sprinkled<std::list<int>>("std::unique_copy(list<int>) (sprinkled)", std_unique_copy);
+
+  // ranges::unique_copy
+  bm_contiguous<std::vector<int>>("ranges::unique_copy(vector<int>) (contiguous)", ranges_unique_copy);
+  bm_sprinkled<std::vector<int>>("ranges::unique_copy(vector<int>) (sprinkled)", ranges_unique_copy);
+
+  bm_contiguous<std::deque<int>>("ranges::unique_copy(deque<int>) (contiguous)", ranges_unique_copy);
+  bm_sprinkled<std::deque<int>>("ranges::unique_copy(deque<int>) (sprinkled)", ranges_unique_copy);
+
+  bm_contiguous<std::list<int>>("ranges::unique_copy(list<int>) (contiguous)", ranges_unique_copy);
+  bm_sprinkled<std::list<int>>("ranges::unique_copy(list<int>) (sprinkled)", ranges_unique_copy);
+
+  benchmark::Initialize(&argc, argv);
+  benchmark::RunSpecifiedBenchmarks();
+  benchmark::Shutdown();
+  return 0;
+}
diff --git a/libcxx/test/benchmarks/algorithms/modifying/unique_copy_pred.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/unique_copy_pred.bench.cpp
new file mode 100644
index 0000000000000..24ca442fb3de4
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/modifying/unique_copy_pred.bench.cpp
@@ -0,0 +1,121 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+#include <algorithm>
+#include <cstddef>
+#include <deque>
+#include <iterator>
+#include <list>
+#include <string>
+#include <vector>
+
+#include "benchmark/benchmark.h"
+#include "../../GenerateInput.h"
+
+// Create a sequence of the form xxxxxxxxxxyyyyyyyyyy and unique the
+// adjacent equal elements.
+template <class Container, class Operation>
+void bm_contiguous(std::string operation_name, Operation unique_copy) {
+  auto bench = [unique_copy](auto& st) {
+    std::size_t const size = st.range(0);
+    using ValueType        = typename Container::value_type;
+    Container c(size);
+    ValueType x = Generate<ValueType>::random();
+    ValueType y = Generate<ValueType>::random();
+    auto half   = size / 2;
+    std::fill_n(std::fill_n(c.begin(), half, x), half, y);
+
+    std::vector<ValueType> out(size);
+
+    auto pred = [](auto& a, auto& b) {
+      benchmark::DoNotOptimize(a);
+      benchmark::DoNotOptimize(b);
+      return a == b;
+    };
+
+    for ([[maybe_unused]] auto _ : st) {
+      auto result = unique_copy(c.begin(), c.end(), out.begin(), pred);
+      benchmark::DoNotOptimize(result);
+      benchmark::DoNotOptimize(c);
+      benchmark::ClobberMemory();
+    }
+  };
+  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+// Create a sequence of the form xxyyxxyyxxyyxxyyxxyy and unique
+// adjacent equal elements.
+template <class Container, class Operation>
+void bm_sprinkled(std::string operation_name, Operation unique_copy) {
+  auto bench = [unique_copy](auto& st) {
+    std::size_t const size = st.range(0);
+    using ValueType        = typename Container::value_type;
+    Container c(size);
+    ValueType x    = Generate<ValueType>::random();
+    ValueType y    = Generate<ValueType>::random();
+    auto alternate = [&](auto out, auto n) {
+      for (std::size_t i = 0; i != n; i += 2) {
+        *out++ = (i % 4 == 0 ? x : y);
+        *out++ = (i % 4 == 0 ? x : y);
+      }
+    };
+    alternate(c.begin(), size);
+
+    std::vector<ValueType> out(size);
+
+    auto pred = [](auto& a, auto& b) {
+      benchmark::DoNotOptimize(a);
+      benchmark::DoNotOptimize(b);
+      return a == b;
+    };
+
+    for ([[maybe_unused]] auto _ : st) {
+      auto result = unique_copy(c.begin(), c.end(), out.begin(), pred);
+      benchmark::DoNotOptimize(result);
+      benchmark::DoNotOptimize(c);
+      benchmark::ClobberMemory();
+    }
+  };
+  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+int main(int argc, char** argv) {
+  auto std_unique_copy = [](auto first, auto last, auto out, auto pred) {
+    return std::unique_copy(first, last, out, pred);
+  };
+  auto ranges_unique_copy = [](auto first, auto last, auto out, auto pred) {
+    return std::ranges::unique_copy(first, last, out, pred);
+  };
+
+  // std::unique_copy
+  bm_contiguous<std::vector<int>>("std::unique_copy(vector<int>, pred) (contiguous)", std_unique_copy);
+  bm_sprinkled<std::vector<int>>("std::unique_copy(vector<int>, pred) (sprinkled)", std_unique_copy);
+
+  bm_contiguous<std::deque<int>>("std::unique_copy(deque<int>, pred) (contiguous)", std_unique_copy);
+  bm_sprinkled<std::deque<int>>("std::unique_copy(deque<int>, pred) (sprinkled)", std_unique_copy);
+
+  bm_contiguous<std::list<int>>("std::unique_copy(list<int>, pred) (contiguous)", std_unique_copy);
+  bm_sprinkled<std::list<int>>("std::unique_copy(list<int>, pred) (sprinkled)", std_unique_copy);
+
+  // ranges::unique_copy
+  bm_contiguous<std::vector<int>>("ranges::unique_copy(vector<int>, pred) (contiguous)", ranges_unique_copy);
+  bm_sprinkled<std::vector<int>>("ranges::unique_copy(vector<int>, pred) (sprinkled)", ranges_unique_copy);
+
+  bm_contiguous<std::deque<int>>("ranges::unique_copy(deque<int>, pred) (contiguous)", ranges_unique_copy);
+  bm_sprinkled<std::deque<int>>("ranges::unique_copy(deque<int>, pred) (sprinkled)", ranges_unique_copy);
+
+  bm_contiguous<std::list<int>>("ranges::unique_copy(list<int>, pred) (contiguous)", ranges_unique_copy);
+  bm_sprinkled<std::list<int>>("ranges::unique_copy(list<int>, pred) (sprinkled)", ranges_unique_copy);
+
+  benchmark::Initialize(&argc, argv);
+  benchmark::RunSpecifiedBenchmarks();
+  benchmark::Shutdown();
+  return 0;
+}
diff --git a/libcxx/test/benchmarks/algorithms/modifying/unique_pred.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/unique_pred.bench.cpp
new file mode 100644
index 0000000000000..0b258ea5cbecc
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/modifying/unique_pred.bench.cpp
@@ -0,0 +1,144 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+#include <algorithm>
+#include <cstddef>
+#include <deque>
+#include <iterator>
+#include <list>
+#include <string>
+#include <vector>
+
+#include "benchmark/benchmark.h"
+#include "../../GenerateInput.h"
+
+// Create a sequence of the form xxxxxxxxxxyyyyyyyyyy and unique the
+// adjacent equal elements.
+//
+// We perform this benchmark in a batch because we need to restore the
+// state of the container after the operation.
+template <class Container, class Operation>
+void bm_contiguous(std::string operation_name, Operation unique) {
+  auto bench = [unique](auto& st) {
+    std::size_t const size          = st.range(0);
+    constexpr std::size_t BatchSize = 10;
+    using ValueType                 = typename Container::value_type;
+    Container c[BatchSize];
+    ValueType x = Generate<ValueType>::random();
+    ValueType y = Generate<ValueType>::random();
+    for (std::size_t i = 0; i != BatchSize; ++i) {
+      c[i]      = Container(size);
+      auto half = size / 2;
+      std::fill_n(std::fill_n(c[i].begin(), half, x), half, y);
+    }
+
+    auto pred = [](auto& a, auto& b) {
+      benchmark::DoNotOptimize(a);
+      benchmark::DoNotOptimize(b);
+      return a == b;
+    };
+
+    while (st.KeepRunningBatch(BatchSize)) {
+      for (std::size_t i = 0; i != BatchSize; ++i) {
+        auto result = unique(c[i].begin(), c[i].end(), pred);
+        benchmark::DoNotOptimize(result);
+        benchmark::DoNotOptimize(c[i]);
+        benchmark::ClobberMemory();
+      }
+
+      st.PauseTiming();
+      for (std::size_t i = 0; i != BatchSize; ++i) {
+        auto half = size / 2;
+        std::fill_n(std::fill_n(c[i].begin(), half, x), half, y);
+      }
+      st.ResumeTiming();
+    }
+  };
+  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+// Create a sequence of the form xxyyxxyyxxyyxxyyxxyy and unique
+// adjacent equal elements.
+//
+// We perform this benchmark in a batch because we need to restore the
+// state of the container after the operation.
+template <class Container, class Operation>
+void bm_sprinkled(std::string operation_name, Operation unique) {
+  auto bench = [unique](auto& st) {
+    std::size_t const size          = st.range(0);
+    constexpr std::size_t BatchSize = 10;
+    using ValueType                 = typename Container::value_type;
+    Container c[BatchSize];
+    ValueType x    = Generate<ValueType>::random();
+    ValueType y    = Generate<ValueType>::random();
+    auto alternate = [&](auto out, auto n) {
+      for (std::size_t i = 0; i != n; i += 2) {
+        *out++ = (i % 4 == 0 ? x : y);
+        *out++ = (i % 4 == 0 ? x : y);
+      }
+    };
+    for (std::size_t i = 0; i != BatchSize; ++i) {
+      c[i] = Container(size);
+      alternate(c[i].begin(), size);
+    }
+
+    auto pred = [](auto& a, auto& b) {
+      benchmark::DoNotOptimize(a);
+      benchmark::DoNotOptimize(b);
+      return a == b;
+    };
+
+    while (st.KeepRunningBatch(BatchSize)) {
+      for (std::size_t i = 0; i != BatchSize; ++i) {
+        auto result = unique(c[i].begin(), c[i].end(), pred);
+        benchmark::DoNotOptimize(result);
+        benchmark::DoNotOptimize(c[i]);
+        benchmark::ClobberMemory();
+      }
+
+      st.PauseTiming();
+      for (std::size_t i = 0; i != BatchSize; ++i) {
+        alternate(c[i].begin(), size);
+      }
+      st.ResumeTiming();
+    }
+  };
+  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
+}
+
+int main(int argc, char** argv) {
+  auto std_unique    = [](auto first, auto last, auto pred) { return std::unique(first, last, pred); };
+  auto ranges_unique = [](auto first, auto last, auto pred) { return std::ranges::unique(first, last, pred); };
+
+  // std::unique
+  bm_contiguous<std::vector<int>>("std::unique(vector<int>, pred) (contiguous)", std_unique);
+  bm_sprinkled<std::vector<int>>("std::unique(vector<int>, pred) (sprinkled)", std_unique);
+
+  bm_contiguous<std::deque<int>>("std::unique(deque<int>, pred) (contiguous)", std_unique);
+  bm_sprinkled<std::deque<int>>("std::unique(deque<int>, pred) (sprinkled)", std_unique);
+
+  bm_contiguous<std::list<int>>("std::unique(list<int>, pred) (contiguous)", std_unique);
+  bm_sprinkled<std::list<int>>("std::unique(list<int>, pred) (sprinkled)", std_unique);
+
+  // ranges::unique
+  bm_contiguous<std::vector<int>>("ranges::unique(vector<int>, pred) (contiguous)", ranges_unique);
+  bm_sprinkled<std::vector<int>>("ranges::unique(vector<int>, pred) (sprinkled)", ranges_unique);
+
+  bm_contiguous<std::deque<int>>("ranges::unique(deque<int>, pred) (contiguous)", ranges_unique);
+  bm_sprinkled<std::deque<int>>("ranges::unique(deque<int>, pred) (sprinkled)", ranges_unique);
+
+  bm_contiguous<std::list<int>>("ranges::unique(list<int>, pred) (contiguous)", ranges_unique);
+  bm_sprinkled<std::list<int>>("ranges::unique(list<int>, pred) (sprinkled)", ranges_unique);
+
+  benchmark::Initialize(&argc, argv);
+  benchmark::RunSpecifiedBenchmarks();
+  benchmark::Shutdown();
+  return 0;
+}
diff --git a/libcxx/test/benchmarks/algorithms/reverse.bench.cpp b/libcxx/test/benchmarks/algorithms/reverse.bench.cpp
deleted file mode 100644
index 2d8dd819ac24c..0000000000000
--- a/libcxx/test/benchmarks/algorithms/reverse.bench.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
-
-#include <algorithm>
-#include <iterator>
-#include <string>
-#include <vector>
-
-#include <benchmark/benchmark.h>
-#include "../GenerateInput.h"
-
-template <class T>
-static void bm_reverse(benchmark::State& state) {
-  std::size_t const n = state.range();
-  std::vector<T> vec;
-  std::generate_n(std::back_inserter(vec), n, [] { return Generate<T>::cheap(); });
-  for (auto _ : state) {
-    std::reverse(vec.begin(), vec.end());
-    benchmark::DoNotOptimize(vec);
-  }
-}
-BENCHMARK(bm_reverse<int>)->Name("std::reverse(vector<int>)")->DenseRange(1, 8)->Range(16, 1 << 20);
-BENCHMARK(bm_reverse<std::string>)->Name("std::reverse(vector<string>)")->DenseRange(1, 8)->Range(16, 1 << 20);
-
-template <class T>
-static void bm_ranges_reverse(benchmark::State& state) {
-  std::size_t const n = state.range();
-  std::vector<T> vec;
-  std::generate_n(std::back_inserter(vec), n, [] { return Generate<T>::cheap(); });
-  for (auto _ : state) {
-    std::ranges::reverse(vec.begin(), vec.end());
-    benchmark::DoNotOptimize(vec);
-  }
-}
-BENCHMARK(bm_ranges_reverse<int>)->Name("ranges::reverse(vector<int>)")->DenseRange(1, 8)->Range(16, 1 << 20);
-BENCHMARK(bm_ranges_reverse<std::string>)
-    ->Name("ranges::reverse(vector<string>)")
-    ->DenseRange(1, 8)
-    ->Range(16, 1 << 20);
-
-BENCHMARK_MAIN();

>From b86aa95e1d7daa3ddf78c3de5dfa29bc434f1cfc Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Wed, 19 Feb 2025 15:10:48 -0500
Subject: [PATCH 02/15] Add move_backward

---
 .../algorithms/modifying/move.bench.cpp       | 91 +++++++++++++++++++
 .../modifying/move_backward.bench.cpp         | 91 +++++++++++++++++++
 .../test/benchmarks/algorithms/move.bench.cpp | 71 ---------------
 .../algorithms/move_backward.bench.cpp        | 71 ---------------
 4 files changed, 182 insertions(+), 142 deletions(-)
 create mode 100644 libcxx/test/benchmarks/algorithms/modifying/move.bench.cpp
 create mode 100644 libcxx/test/benchmarks/algorithms/modifying/move_backward.bench.cpp
 delete mode 100644 libcxx/test/benchmarks/algorithms/move.bench.cpp
 delete mode 100644 libcxx/test/benchmarks/algorithms/move_backward.bench.cpp

diff --git a/libcxx/test/benchmarks/algorithms/modifying/move.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/move.bench.cpp
new file mode 100644
index 0000000000000..f009850dac215
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/modifying/move.bench.cpp
@@ -0,0 +1,91 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+#include <algorithm>
+#include <cstddef>
+#include <deque>
+#include <iterator>
+#include <list>
+#include <string>
+#include <vector>
+
+#include "benchmark/benchmark.h"
+#include "../../GenerateInput.h"
+#include "test_macros.h"
+
+int main(int argc, char** argv) {
+  auto std_move = [](auto first, auto last, auto out) { return std::move(first, last, out); };
+
+  // {std,ranges}::move(normal container)
+  {
+    auto bm = []<class Container>(std::string name, auto move) {
+      benchmark::RegisterBenchmark(name, [move](auto& st) {
+        std::size_t const n = st.range(0);
+        using ValueType     = typename Container::value_type;
+        Container c1(n), c2(n);
+        std::generate_n(c1.begin(), n, [] { return Generate<ValueType>::random(); });
+
+        Container* in  = &c1;
+        Container* out = &c2;
+        for ([[maybe_unused]] auto _ : st) {
+          benchmark::DoNotOptimize(c1);
+          benchmark::DoNotOptimize(c2);
+          auto result = move(in->begin(), in->end(), out->begin());
+          benchmark::DoNotOptimize(result);
+          std::swap(in, out);
+        }
+      })->Range(8, 1 << 20);
+    };
+    bm.operator()<std::vector<int>>("std::move(vector<int>)", std_move);
+    bm.operator()<std::deque<int>>("std::move(deque<int>)", std_move);
+    bm.operator()<std::list<int>>("std::move(list<int>)", std_move);
+    bm.operator()<std::vector<int>>("rng::move(vector<int>)", std::ranges::move);
+    bm.operator()<std::deque<int>>("rng::move(deque<int>)", std::ranges::move);
+    bm.operator()<std::list<int>>("rng::move(list<int>)", std::ranges::move);
+  }
+
+  // {std,ranges}::move(vector<bool>)
+  {
+    auto bm = []<bool Aligned>(std::string name, auto move) {
+      benchmark::RegisterBenchmark(name, [move](auto& st) {
+        std::size_t const n = st.range(0);
+        std::vector<bool> c1(n, true);
+        std::vector<bool> c2(n, false);
+
+        std::vector<bool>* in  = &c1;
+        std::vector<bool>* out = &c2;
+        for (auto _ : st) {
+          auto first1 = in->begin();
+          auto last1  = in->end();
+          auto first2 = out->begin();
+          if constexpr (Aligned) {
+            benchmark::DoNotOptimize(move(first1, last1, first2));
+          } else {
+            benchmark::DoNotOptimize(move(first1 + 4, last1, first2));
+          }
+          std::swap(in, out);
+          benchmark::DoNotOptimize(in);
+          benchmark::DoNotOptimize(out);
+        }
+      })->Range(64, 1 << 20);
+    };
+    bm.operator()<true>("std::move(vector<bool>) (aligned)", std_move);
+    bm.operator()<false>("std::move(vector<bool>) (unaligned)", std_move);
+#if TEST_STD_VER >= 23 // vector<bool>::iterator is not an output_iterator before C++23
+    bm.operator()<true>("rng::move(vector<bool>) (aligned)", std::ranges::move);
+    bm.operator()<false>("rng::move(vector<bool>) (unaligned)", std::ranges::move);
+#endif
+  }
+
+  benchmark::Initialize(&argc, argv);
+  benchmark::RunSpecifiedBenchmarks();
+  benchmark::Shutdown();
+  return 0;
+}
diff --git a/libcxx/test/benchmarks/algorithms/modifying/move_backward.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/move_backward.bench.cpp
new file mode 100644
index 0000000000000..ef9373cbcdd72
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/modifying/move_backward.bench.cpp
@@ -0,0 +1,91 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+#include <algorithm>
+#include <cstddef>
+#include <deque>
+#include <iterator>
+#include <list>
+#include <string>
+#include <vector>
+
+#include "benchmark/benchmark.h"
+#include "../../GenerateInput.h"
+#include "test_macros.h"
+
+int main(int argc, char** argv) {
+  auto std_move_backward = [](auto first, auto last, auto out) { return std::move_backward(first, last, out); };
+
+  // {std,ranges}::move_backward(normal container)
+  {
+    auto bm = []<class Container>(std::string name, auto move_backward) {
+      benchmark::RegisterBenchmark(name, [move_backward](auto& st) {
+        std::size_t const n = st.range(0);
+        using ValueType     = typename Container::value_type;
+        Container c1(n), c2(n);
+        std::generate_n(c1.begin(), n, [] { return Generate<ValueType>::random(); });
+
+        Container* in  = &c1;
+        Container* out = &c2;
+        for ([[maybe_unused]] auto _ : st) {
+          benchmark::DoNotOptimize(c1);
+          benchmark::DoNotOptimize(c2);
+          auto result = move_backward(in->begin(), in->end(), out->end());
+          benchmark::DoNotOptimize(result);
+          std::swap(in, out);
+        }
+      })->Range(8, 1 << 20);
+    };
+    bm.operator()<std::vector<int>>("std::move_backward(vector<int>)", std_move_backward);
+    bm.operator()<std::deque<int>>("std::move_backward(deque<int>)", std_move_backward);
+    bm.operator()<std::list<int>>("std::move_backward(list<int>)", std_move_backward);
+    bm.operator()<std::vector<int>>("rng::move_backward(vector<int>)", std::ranges::move_backward);
+    bm.operator()<std::deque<int>>("rng::move_backward(deque<int>)", std::ranges::move_backward);
+    bm.operator()<std::list<int>>("rng::move_backward(list<int>)", std::ranges::move_backward);
+  }
+
+  // {std,ranges}::move_backward(vector<bool>)
+  {
+    auto bm = []<bool Aligned>(std::string name, auto move_backward) {
+      benchmark::RegisterBenchmark(name, [move_backward](auto& st) {
+        std::size_t const n = st.range(0);
+        std::vector<bool> c1(n, true);
+        std::vector<bool> c2(n, false);
+
+        std::vector<bool>* in  = &c1;
+        std::vector<bool>* out = &c2;
+        for (auto _ : st) {
+          auto first1 = in->begin();
+          auto last1  = in->end();
+          auto last2  = out->end();
+          if constexpr (Aligned) {
+            benchmark::DoNotOptimize(move_backward(first1, last1, last2));
+          } else {
+            benchmark::DoNotOptimize(move_backward(first1, last1 - 4, last2));
+          }
+          std::swap(in, out);
+          benchmark::DoNotOptimize(in);
+          benchmark::DoNotOptimize(out);
+        }
+      })->Range(64, 1 << 20);
+    };
+    bm.operator()<true>("std::move_backward(vector<bool>) (aligned)", std_move_backward);
+    bm.operator()<false>("std::move_backward(vector<bool>) (unaligned)", std_move_backward);
+#if TEST_STD_VER >= 23 // vector<bool>::iterator is not an output_iterator before C++23
+    bm.operator()<true>("rng::move_backward(vector<bool>) (aligned)", std::ranges::move_backward);
+    bm.operator()<false>("rng::move_backward(vector<bool>) (unaligned)", std::ranges::move_backward);
+#endif
+  }
+
+  benchmark::Initialize(&argc, argv);
+  benchmark::RunSpecifiedBenchmarks();
+  benchmark::Shutdown();
+  return 0;
+}
diff --git a/libcxx/test/benchmarks/algorithms/move.bench.cpp b/libcxx/test/benchmarks/algorithms/move.bench.cpp
deleted file mode 100644
index 73f36f0c129de..0000000000000
--- a/libcxx/test/benchmarks/algorithms/move.bench.cpp
+++ /dev/null
@@ -1,71 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
-
-#include <algorithm>
-#include <benchmark/benchmark.h>
-#include <ranges>
-#include <vector>
-
-template <bool aligned>
-void bm_ranges_move_vb(benchmark::State& state) {
-  auto n = state.range();
-  std::vector<bool> v1(n, true);
-  std::vector<bool> v2(n, false);
-  benchmark::DoNotOptimize(v1);
-  benchmark::DoNotOptimize(v2);
-  std::vector<bool>* in  = &v1;
-  std::vector<bool>* out = &v2;
-  for (auto _ : state) {
-    if constexpr (aligned) {
-      benchmark::DoNotOptimize(std::ranges::move(*in, std::ranges::begin(*out)));
-    } else {
-      benchmark::DoNotOptimize(
-          std::ranges::move(std::views::counted(in->begin() + 4, n - 4), std::ranges::begin(*out)));
-    }
-    std::swap(in, out);
-    benchmark::DoNotOptimize(in);
-    benchmark::DoNotOptimize(out);
-  }
-}
-
-template <bool aligned>
-void bm_move_vb(benchmark::State& state) {
-  auto n = state.range();
-  std::vector<bool> v1(n, true);
-  std::vector<bool> v2(n, false);
-  benchmark::DoNotOptimize(v1);
-  benchmark::DoNotOptimize(v2);
-  std::vector<bool>* in  = &v1;
-  std::vector<bool>* out = &v2;
-  for (auto _ : state) {
-    auto first1 = in->begin();
-    auto last1  = in->end();
-    auto first2 = out->begin();
-    if constexpr (aligned) {
-      benchmark::DoNotOptimize(std::move(first1, last1, first2));
-    } else {
-      benchmark::DoNotOptimize(std::move(first1 + 4, last1, first2));
-    }
-    std::swap(in, out);
-    benchmark::DoNotOptimize(in);
-    benchmark::DoNotOptimize(out);
-  }
-}
-
-BENCHMARK(bm_ranges_move_vb<true>)
-    ->Name("bm_ranges_move_vb_aligned")
-    ->Range(8, 1 << 16)
-    ->DenseRange(102400, 204800, 4096);
-BENCHMARK(bm_ranges_move_vb<false>)->Name("bm_ranges_move_vb_unaligned")->Range(8, 1 << 20);
-
-BENCHMARK(bm_move_vb<true>)->Name("bm_move_vb_aligned")->Range(8, 1 << 20);
-BENCHMARK(bm_move_vb<false>)->Name("bm_move_vb_unaligned")->Range(8, 1 << 20);
-
-BENCHMARK_MAIN();
diff --git a/libcxx/test/benchmarks/algorithms/move_backward.bench.cpp b/libcxx/test/benchmarks/algorithms/move_backward.bench.cpp
deleted file mode 100644
index 23d7395198419..0000000000000
--- a/libcxx/test/benchmarks/algorithms/move_backward.bench.cpp
+++ /dev/null
@@ -1,71 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
-
-#include <algorithm>
-#include <benchmark/benchmark.h>
-#include <ranges>
-#include <vector>
-
-template <bool aligned>
-void bm_ranges_move_backward_vb(benchmark::State& state) {
-  auto n = state.range();
-  std::vector<bool> v1(n, true);
-  std::vector<bool> v2(n, false);
-  benchmark::DoNotOptimize(v1);
-  benchmark::DoNotOptimize(v2);
-  std::vector<bool>* in  = &v1;
-  std::vector<bool>* out = &v2;
-  for (auto _ : state) {
-    if constexpr (aligned) {
-      benchmark::DoNotOptimize(std::ranges::move_backward(*in, std::ranges::end(*out)));
-    } else {
-      benchmark::DoNotOptimize(
-          std::ranges::move_backward(std::views::counted(in->begin(), n - 4), std::ranges::end(*out)));
-    }
-    std::swap(in, out);
-    benchmark::DoNotOptimize(in);
-    benchmark::DoNotOptimize(out);
-  }
-}
-
-template <bool aligned>
-void bm_move_backward_vb(benchmark::State& state) {
-  auto n = state.range();
-  std::vector<bool> v1(n, true);
-  std::vector<bool> v2(n, false);
-  benchmark::DoNotOptimize(v1);
-  benchmark::DoNotOptimize(v2);
-  std::vector<bool>* in  = &v1;
-  std::vector<bool>* out = &v2;
-  for (auto _ : state) {
-    auto first1 = in->begin();
-    auto last1  = in->end();
-    auto last2  = out->end();
-    if constexpr (aligned) {
-      benchmark::DoNotOptimize(std::move_backward(first1, last1, last2));
-    } else {
-      benchmark::DoNotOptimize(std::move_backward(first1, last1 - 4, last2));
-    }
-    std::swap(in, out);
-    benchmark::DoNotOptimize(in);
-    benchmark::DoNotOptimize(out);
-  }
-}
-
-BENCHMARK(bm_ranges_move_backward_vb<true>)
-    ->Name("bm_ranges_move_backward_vb_aligned")
-    ->Range(8, 1 << 16)
-    ->DenseRange(102400, 204800, 4096);
-BENCHMARK(bm_ranges_move_backward_vb<false>)->Name("bm_ranges_move_backward_vb_unaligned")->Range(8, 1 << 20);
-
-BENCHMARK(bm_move_backward_vb<true>)->Name("bm_move_backward_vb_aligned")->Range(8, 1 << 20);
-BENCHMARK(bm_move_backward_vb<false>)->Name("bm_move_backward_vb_unaligned")->Range(8, 1 << 20);
-
-BENCHMARK_MAIN();

>From 9fede1f1cda28145ecf0d8f086e9dbdee42f0336 Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Wed, 19 Feb 2025 16:12:19 -0500
Subject: [PATCH 03/15] Implement review comments from the std::copy code
 review

---
 .../algorithms/modifying/fill.bench.cpp       | 106 ++++----
 .../algorithms/modifying/fill_n.bench.cpp     | 106 ++++----
 .../algorithms/modifying/generate.bench.cpp   |  63 ++---
 .../algorithms/modifying/generate_n.bench.cpp |  63 ++---
 .../algorithms/modifying/remove.bench.cpp     | 211 ++++++++--------
 .../modifying/remove_copy.bench.cpp           | 153 ++++++------
 .../modifying/remove_copy_if.bench.cpp        | 173 +++++++------
 .../algorithms/modifying/remove_if.bench.cpp  | 229 ++++++++---------
 .../algorithms/modifying/replace.bench.cpp    | 149 ++++++-----
 .../algorithms/modifying/replace_if.bench.cpp | 163 ++++++------
 .../algorithms/modifying/reverse.bench.cpp    |  54 ++--
 .../modifying/reverse_copy.bench.cpp          |  60 ++---
 .../algorithms/modifying/rotate.bench.cpp     |  63 ++---
 .../modifying/rotate_copy.bench.cpp           |  63 +++--
 .../algorithms/modifying/sample.bench.cpp     |  67 +++--
 .../algorithms/modifying/shift_left.bench.cpp |  55 +++--
 .../modifying/shift_right.bench.cpp           |  55 +++--
 .../algorithms/modifying/shuffle.bench.cpp    |  57 ++---
 .../modifying/swap_ranges.bench.cpp           |  63 +++--
 .../modifying/transform.binary.bench.cpp      |  79 +++---
 .../modifying/transform.unary.bench.cpp       |  73 +++---
 .../algorithms/modifying/unique.bench.cpp     | 209 ++++++++--------
 .../modifying/unique_copy.bench.cpp           | 155 ++++++------
 .../modifying/unique_copy_pred.bench.cpp      | 177 +++++++-------
 .../modifying/unique_pred.bench.cpp           | 231 +++++++++---------
 25 files changed, 1438 insertions(+), 1439 deletions(-)

diff --git a/libcxx/test/benchmarks/algorithms/modifying/fill.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/fill.bench.cpp
index 64c7364be6549..fb0fa8ffc5c69 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/fill.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/fill.bench.cpp
@@ -20,64 +20,66 @@
 #include "../../GenerateInput.h"
 #include "test_macros.h"
 
-template <class Container, class Operation>
-void bm(std::string operation_name, Operation fill) {
-  auto bench = [fill](auto& st) {
-    std::size_t const size = st.range(0);
-    using ValueType        = typename Container::value_type;
-    ValueType x            = Generate<ValueType>::random();
-    ValueType y            = Generate<ValueType>::random();
-    Container c(size, y);
-
-    for ([[maybe_unused]] auto _ : st) {
-      fill(c.begin(), c.end(), x);
-      std::swap(x, y);
-      benchmark::DoNotOptimize(c);
-      benchmark::DoNotOptimize(x);
-      benchmark::DoNotOptimize(y);
-      benchmark::ClobberMemory();
-    }
-  };
-  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
-
-template <class Operation>
-void bm_vector_bool(std::string operation_name, Operation fill) {
-  auto bench = [fill](auto& st) {
-    std::size_t const size = st.range(0);
-    bool x                 = true;
-    bool y                 = false;
-    std::vector<bool> c(size, y);
+int main(int argc, char** argv) {
+  auto std_fill = [](auto first, auto last, auto const& value) { return std::fill(first, last, value); };
 
-    for ([[maybe_unused]] auto _ : st) {
-      fill(c.begin(), c.end(), x);
-      std::swap(x, y);
-      benchmark::DoNotOptimize(c);
-      benchmark::DoNotOptimize(x);
-      benchmark::DoNotOptimize(y);
-      benchmark::ClobberMemory();
-    }
-  };
-  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
+  // {std,ranges}::fill(normal container)
+  {
+    auto bm = []<class Container>(std::string name, auto fill) {
+      benchmark::RegisterBenchmark(
+          name,
+          [fill](auto& st) {
+            std::size_t const size = st.range(0);
+            using ValueType        = typename Container::value_type;
+            ValueType x            = Generate<ValueType>::random();
+            ValueType y            = Generate<ValueType>::random();
+            Container c(size, y);
 
-int main(int argc, char** argv) {
-  auto std_fill    = [](auto first, auto last, auto const& value) { return std::fill(first, last, value); };
-  auto ranges_fill = [](auto first, auto last, auto const& value) { return std::ranges::fill(first, last, value); };
+            for ([[maybe_unused]] auto _ : st) {
+              fill(c.begin(), c.end(), x);
+              std::swap(x, y);
+              benchmark::DoNotOptimize(c);
+              benchmark::DoNotOptimize(x);
+              benchmark::DoNotOptimize(y);
+              benchmark::ClobberMemory();
+            }
+          })
+          ->Arg(32)
+          ->Arg(1024)
+          ->Arg(8192);
+    };
+    bm.operator()<std::vector<int>>("std::fill(vector<int>)", std_fill);
+    bm.operator()<std::deque<int>>("std::fill(deque<int>)", std_fill);
+    bm.operator()<std::list<int>>("std::fill(list<int>)", std_fill);
+    bm.operator()<std::vector<int>>("rng::fill(vector<int>)", std::ranges::fill);
+    bm.operator()<std::deque<int>>("rng::fill(deque<int>)", std::ranges::fill);
+    bm.operator()<std::list<int>>("rng::fill(list<int>)", std::ranges::fill);
+  }
 
-  // std::fill
-  bm<std::vector<int>>("std::fill(vector<int>)", std_fill);
-  bm<std::deque<int>>("std::fill(deque<int>)", std_fill);
-  bm<std::list<int>>("std::fill(list<int>)", std_fill);
-  bm_vector_bool("std::fill(vector<bool>)", std_fill);
+  // {std,ranges}::fill(vector<bool>)
+  {
+    auto bm = [](std::string name, auto fill) {
+      benchmark::RegisterBenchmark(name, [fill](auto& st) {
+        std::size_t const size = st.range(0);
+        bool x                 = true;
+        bool y                 = false;
+        std::vector<bool> c(size, y);
 
-  // ranges::fill
-  bm<std::vector<int>>("ranges::fill(vector<int>)", ranges_fill);
-  bm<std::deque<int>>("ranges::fill(deque<int>)", ranges_fill);
-  bm<std::list<int>>("ranges::fill(list<int>)", ranges_fill);
+        for ([[maybe_unused]] auto _ : st) {
+          fill(c.begin(), c.end(), x);
+          std::swap(x, y);
+          benchmark::DoNotOptimize(c);
+          benchmark::DoNotOptimize(x);
+          benchmark::DoNotOptimize(y);
+          benchmark::ClobberMemory();
+        }
+      })->Range(64, 1 << 20);
+    };
+    bm("std::fill(vector<bool>)", std_fill);
 #if TEST_STD_VER >= 23 // vector<bool>::iterator is not an output_iterator before C++23
-  bm_vector_bool("ranges::fill(vector<bool>)", ranges_fill);
+    bm("rng::fill(vector<bool>)", std::ranges::fill);
 #endif
+  }
 
   benchmark::Initialize(&argc, argv);
   benchmark::RunSpecifiedBenchmarks();
diff --git a/libcxx/test/benchmarks/algorithms/modifying/fill_n.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/fill_n.bench.cpp
index aaeb0982956f9..d4ca98e623871 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/fill_n.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/fill_n.bench.cpp
@@ -20,64 +20,66 @@
 #include "../../GenerateInput.h"
 #include "test_macros.h"
 
-template <class Container, class Operation>
-void bm(std::string operation_name, Operation fill_n) {
-  auto bench = [fill_n](auto& st) {
-    std::size_t const size = st.range(0);
-    using ValueType        = typename Container::value_type;
-    ValueType x            = Generate<ValueType>::random();
-    ValueType y            = Generate<ValueType>::random();
-    Container c(size, y);
-
-    for ([[maybe_unused]] auto _ : st) {
-      fill_n(c.begin(), size, x);
-      std::swap(x, y);
-      benchmark::DoNotOptimize(c);
-      benchmark::DoNotOptimize(x);
-      benchmark::DoNotOptimize(y);
-      benchmark::ClobberMemory();
-    }
-  };
-  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
-
-template <class Operation>
-void bm_vector_bool(std::string operation_name, Operation fill_n) {
-  auto bench = [fill_n](auto& st) {
-    std::size_t const size = st.range(0);
-    bool x                 = true;
-    bool y                 = false;
-    std::vector<bool> c(size, y);
+int main(int argc, char** argv) {
+  auto std_fill_n = [](auto out, auto n, auto const& value) { return std::fill_n(out, n, value); };
 
-    for ([[maybe_unused]] auto _ : st) {
-      fill_n(c.begin(), size, x);
-      std::swap(x, y);
-      benchmark::DoNotOptimize(c);
-      benchmark::DoNotOptimize(x);
-      benchmark::DoNotOptimize(y);
-      benchmark::ClobberMemory();
-    }
-  };
-  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
+  // {std,ranges}::fill_n(normal container)
+  {
+    auto bm = []<class Container>(std::string name, auto fill_n) {
+      benchmark::RegisterBenchmark(
+          name,
+          [fill_n](auto& st) {
+            std::size_t const size = st.range(0);
+            using ValueType        = typename Container::value_type;
+            ValueType x            = Generate<ValueType>::random();
+            ValueType y            = Generate<ValueType>::random();
+            Container c(size, y);
 
-int main(int argc, char** argv) {
-  auto std_fill_n    = [](auto out, auto n, auto const& value) { return std::fill_n(out, n, value); };
-  auto ranges_fill_n = [](auto out, auto n, auto const& value) { return std::ranges::fill_n(out, n, value); };
+            for ([[maybe_unused]] auto _ : st) {
+              fill_n(c.begin(), size, x);
+              std::swap(x, y);
+              benchmark::DoNotOptimize(c);
+              benchmark::DoNotOptimize(x);
+              benchmark::DoNotOptimize(y);
+              benchmark::ClobberMemory();
+            }
+          })
+          ->Arg(32)
+          ->Arg(1024)
+          ->Arg(8192);
+    };
+    bm.operator()<std::vector<int>>("std::fill_n(vector<int>)", std_fill_n);
+    bm.operator()<std::deque<int>>("std::fill_n(deque<int>)", std_fill_n);
+    bm.operator()<std::list<int>>("std::fill_n(list<int>)", std_fill_n);
+    bm.operator()<std::vector<int>>("rng::fill_n(vector<int>)", std::ranges::fill_n);
+    bm.operator()<std::deque<int>>("rng::fill_n(deque<int>)", std::ranges::fill_n);
+    bm.operator()<std::list<int>>("rng::fill_n(list<int>)", std::ranges::fill_n);
+  }
 
-  // std::fill_n
-  bm<std::vector<int>>("std::fill_n(vector<int>)", std_fill_n);
-  bm<std::deque<int>>("std::fill_n(deque<int>)", std_fill_n);
-  bm<std::list<int>>("std::fill_n(list<int>)", std_fill_n);
-  bm_vector_bool("std::fill_n(vector<bool>)", std_fill_n);
+  // {std,ranges}::fill_n(vector<bool>)
+  {
+    auto bm = [](std::string name, auto fill_n) {
+      benchmark::RegisterBenchmark(name, [fill_n](auto& st) {
+        std::size_t const size = st.range(0);
+        bool x                 = true;
+        bool y                 = false;
+        std::vector<bool> c(size, y);
 
-  // ranges::fill_n
-  bm<std::vector<int>>("ranges::fill_n(vector<int>)", ranges_fill_n);
-  bm<std::deque<int>>("ranges::fill_n(deque<int>)", ranges_fill_n);
-  bm<std::list<int>>("ranges::fill_n(list<int>)", ranges_fill_n);
+        for ([[maybe_unused]] auto _ : st) {
+          fill_n(c.begin(), size, x);
+          std::swap(x, y);
+          benchmark::DoNotOptimize(c);
+          benchmark::DoNotOptimize(x);
+          benchmark::DoNotOptimize(y);
+          benchmark::ClobberMemory();
+        }
+      })->Range(64, 1 << 20);
+    };
+    bm("std::fill_n(vector<bool>)", std_fill_n);
 #if TEST_STD_VER >= 23 // vector<bool>::iterator is not an output_iterator before C++23
-  bm_vector_bool("ranges::fill_n(vector<bool>)", ranges_fill_n);
+    bm("rng::fill_n(vector<bool>)", std::ranges::fill_n);
 #endif
+  }
 
   benchmark::Initialize(&argc, argv);
   benchmark::RunSpecifiedBenchmarks();
diff --git a/libcxx/test/benchmarks/algorithms/modifying/generate.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/generate.bench.cpp
index 15b039a4d3009..9056d598d5d38 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/generate.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/generate.bench.cpp
@@ -19,38 +19,39 @@
 #include "benchmark/benchmark.h"
 #include "../../GenerateInput.h"
 
-template <class Container, class Operation>
-void bm(std::string operation_name, Operation generate) {
-  auto bench = [generate](auto& st) {
-    std::size_t const size = st.range(0);
-    Container c(size);
-    using ValueType = typename Container::value_type;
-    ValueType x     = Generate<ValueType>::random();
-
-    for ([[maybe_unused]] auto _ : st) {
-      auto f = [&x] { return x; };
-      generate(c.begin(), c.end(), f);
-      benchmark::DoNotOptimize(c);
-      benchmark::DoNotOptimize(x);
-      benchmark::ClobberMemory();
-    }
-  };
-  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
-
 int main(int argc, char** argv) {
-  auto std_generate    = [](auto first, auto last, auto f) { return std::generate(first, last, f); };
-  auto ranges_generate = [](auto first, auto last, auto f) { return std::ranges::generate(first, last, f); };
-
-  // std::generate
-  bm<std::vector<int>>("std::generate(vector<int>)", std_generate);
-  bm<std::deque<int>>("std::generate(deque<int>)", std_generate);
-  bm<std::list<int>>("std::generate(list<int>)", std_generate);
-
-  // ranges::generate
-  bm<std::vector<int>>("ranges::generate(vector<int>)", ranges_generate);
-  bm<std::deque<int>>("ranges::generate(deque<int>)", ranges_generate);
-  bm<std::list<int>>("ranges::generate(list<int>)", ranges_generate);
+  auto std_generate = [](auto first, auto last, auto f) { return std::generate(first, last, f); };
+
+  // {std,ranges}::generate
+  {
+    auto bm = []<class Container>(std::string name, auto generate) {
+      benchmark::RegisterBenchmark(
+          name,
+          [generate](auto& st) {
+            std::size_t const size = st.range(0);
+            Container c(size);
+            using ValueType = typename Container::value_type;
+            ValueType x     = Generate<ValueType>::random();
+
+            for ([[maybe_unused]] auto _ : st) {
+              auto f = [&x] { return x; };
+              generate(c.begin(), c.end(), f);
+              benchmark::DoNotOptimize(c);
+              benchmark::DoNotOptimize(x);
+              benchmark::ClobberMemory();
+            }
+          })
+          ->Arg(32)
+          ->Arg(1024)
+          ->Arg(8192);
+    };
+    bm.operator()<std::vector<int>>("std::generate(vector<int>)", std_generate);
+    bm.operator()<std::deque<int>>("std::generate(deque<int>)", std_generate);
+    bm.operator()<std::list<int>>("std::generate(list<int>)", std_generate);
+    bm.operator()<std::vector<int>>("rng::generate(vector<int>)", std::ranges::generate);
+    bm.operator()<std::deque<int>>("rng::generate(deque<int>)", std::ranges::generate);
+    bm.operator()<std::list<int>>("rng::generate(list<int>)", std::ranges::generate);
+  }
 
   benchmark::Initialize(&argc, argv);
   benchmark::RunSpecifiedBenchmarks();
diff --git a/libcxx/test/benchmarks/algorithms/modifying/generate_n.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/generate_n.bench.cpp
index 75b088411810f..d33d9183dcb42 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/generate_n.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/generate_n.bench.cpp
@@ -19,38 +19,39 @@
 #include "benchmark/benchmark.h"
 #include "../../GenerateInput.h"
 
-template <class Container, class Operation>
-void bm(std::string operation_name, Operation generate_n) {
-  auto bench = [generate_n](auto& st) {
-    std::size_t const size = st.range(0);
-    Container c(size);
-    using ValueType = typename Container::value_type;
-    ValueType x     = Generate<ValueType>::random();
-
-    for ([[maybe_unused]] auto _ : st) {
-      auto f = [&x] { return x; };
-      generate_n(c.begin(), size, f);
-      benchmark::DoNotOptimize(c);
-      benchmark::DoNotOptimize(x);
-      benchmark::ClobberMemory();
-    }
-  };
-  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
-
 int main(int argc, char** argv) {
-  auto std_generate_n    = [](auto out, auto n, auto f) { return std::generate_n(out, n, f); };
-  auto ranges_generate_n = [](auto out, auto n, auto f) { return std::ranges::generate_n(out, n, f); };
-
-  // std::generate_n
-  bm<std::vector<int>>("std::generate_n(vector<int>)", std_generate_n);
-  bm<std::deque<int>>("std::generate_n(deque<int>)", std_generate_n);
-  bm<std::list<int>>("std::generate_n(list<int>)", std_generate_n);
-
-  // ranges::generate_n
-  bm<std::vector<int>>("ranges::generate_n(vector<int>)", ranges_generate_n);
-  bm<std::deque<int>>("ranges::generate_n(deque<int>)", ranges_generate_n);
-  bm<std::list<int>>("ranges::generate_n(list<int>)", ranges_generate_n);
+  auto std_generate_n = [](auto out, auto n, auto f) { return std::generate_n(out, n, f); };
+
+  // {std,ranges}::generate_n
+  {
+    auto bm = []<class Container>(std::string name, auto generate_n) {
+      benchmark::RegisterBenchmark(
+          name,
+          [generate_n](auto& st) {
+            std::size_t const size = st.range(0);
+            Container c(size);
+            using ValueType = typename Container::value_type;
+            ValueType x     = Generate<ValueType>::random();
+
+            for ([[maybe_unused]] auto _ : st) {
+              auto f = [&x] { return x; };
+              generate_n(c.begin(), size, f);
+              benchmark::DoNotOptimize(c);
+              benchmark::DoNotOptimize(x);
+              benchmark::ClobberMemory();
+            }
+          })
+          ->Arg(32)
+          ->Arg(1024)
+          ->Arg(8192);
+    };
+    bm.operator()<std::vector<int>>("std::generate_n(vector<int>)", std_generate_n);
+    bm.operator()<std::deque<int>>("std::generate_n(deque<int>)", std_generate_n);
+    bm.operator()<std::list<int>>("std::generate_n(list<int>)", std_generate_n);
+    bm.operator()<std::vector<int>>("rng::generate_n(vector<int>)", std::ranges::generate_n);
+    bm.operator()<std::deque<int>>("rng::generate_n(deque<int>)", std::ranges::generate_n);
+    bm.operator()<std::list<int>>("rng::generate_n(list<int>)", std::ranges::generate_n);
+  }
 
   benchmark::Initialize(&argc, argv);
   benchmark::RunSpecifiedBenchmarks();
diff --git a/libcxx/test/benchmarks/algorithms/modifying/remove.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/remove.bench.cpp
index 764dfe73ab70c..956753de13edc 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/remove.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/remove.bench.cpp
@@ -19,112 +19,113 @@
 #include "benchmark/benchmark.h"
 #include "../../GenerateInput.h"
 
-// Create a sequence of the form xxxxxxxxxxyyyyyyyyyy and remove
-// the prefix of x's from it.
-//
-// We perform this benchmark in a batch because we need to restore the
-// state of the container after the operation.
-template <class Container, class Operation>
-void bm_prefix(std::string operation_name, Operation remove) {
-  auto bench = [remove](auto& st) {
-    std::size_t const size          = st.range(0);
-    constexpr std::size_t BatchSize = 10;
-    using ValueType                 = typename Container::value_type;
-    Container c[BatchSize];
-    ValueType x = Generate<ValueType>::random();
-    ValueType y = Generate<ValueType>::random();
-    for (std::size_t i = 0; i != BatchSize; ++i) {
-      c[i]      = Container(size);
-      auto half = size / 2;
-      std::fill_n(std::fill_n(c[i].begin(), half, x), half, y);
-    }
-
-    while (st.KeepRunningBatch(BatchSize)) {
-      for (std::size_t i = 0; i != BatchSize; ++i) {
-        auto result = remove(c[i].begin(), c[i].end(), x);
-        benchmark::DoNotOptimize(result);
-        benchmark::DoNotOptimize(c[i]);
-        benchmark::DoNotOptimize(x);
-        benchmark::ClobberMemory();
-      }
-
-      st.PauseTiming();
-      for (std::size_t i = 0; i != BatchSize; ++i) {
-        auto half = size / 2;
-        std::fill_n(std::fill_n(c[i].begin(), half, x), half, y);
-      }
-      st.ResumeTiming();
-    }
-  };
-  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
-
-// Create a sequence of the form xyxyxyxyxyxyxyxyxyxy and remove
-// the x's from it.
-//
-// We perform this benchmark in a batch because we need to restore the
-// state of the container after the operation.
-template <class Container, class Operation>
-void bm_sprinkled(std::string operation_name, Operation remove) {
-  auto bench = [remove](auto& st) {
-    std::size_t const size          = st.range(0);
-    constexpr std::size_t BatchSize = 10;
-    using ValueType                 = typename Container::value_type;
-    Container c[BatchSize];
-    ValueType x    = Generate<ValueType>::random();
-    ValueType y    = Generate<ValueType>::random();
-    auto alternate = [&](auto out, auto n) {
-      for (std::size_t i = 0; i != n; ++i) {
-        *out++ = (i % 2 == 0 ? x : y);
-      }
-    };
-    for (std::size_t i = 0; i != BatchSize; ++i) {
-      c[i] = Container(size);
-      alternate(c[i].begin(), size);
-    }
-
-    while (st.KeepRunningBatch(BatchSize)) {
-      for (std::size_t i = 0; i != BatchSize; ++i) {
-        auto result = remove(c[i].begin(), c[i].end(), x);
-        benchmark::DoNotOptimize(result);
-        benchmark::DoNotOptimize(c[i]);
-        benchmark::DoNotOptimize(x);
-        benchmark::ClobberMemory();
-      }
-
-      st.PauseTiming();
-      for (std::size_t i = 0; i != BatchSize; ++i) {
-        alternate(c[i].begin(), size);
-      }
-      st.ResumeTiming();
-    }
-  };
-  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
-
 int main(int argc, char** argv) {
-  auto std_remove    = [](auto first, auto last, auto const& value) { return std::remove(first, last, value); };
-  auto ranges_remove = [](auto first, auto last, auto const& value) { return std::ranges::remove(first, last, value); };
-
-  // std::remove
-  bm_prefix<std::vector<int>>("std::remove(vector<int>) (prefix)", std_remove);
-  bm_sprinkled<std::vector<int>>("std::remove(vector<int>) (sprinkled)", std_remove);
-
-  bm_prefix<std::deque<int>>("std::remove(deque<int>) (prefix)", std_remove);
-  bm_sprinkled<std::deque<int>>("std::remove(deque<int>) (sprinkled)", std_remove);
-
-  bm_prefix<std::list<int>>("std::remove(list<int>) (prefix)", std_remove);
-  bm_sprinkled<std::list<int>>("std::remove(list<int>) (sprinkled)", std_remove);
-
-  // ranges::remove
-  bm_prefix<std::vector<int>>("ranges::remove(vector<int>) (prefix)", ranges_remove);
-  bm_sprinkled<std::vector<int>>("ranges::remove(vector<int>) (sprinkled)", ranges_remove);
-
-  bm_prefix<std::deque<int>>("ranges::remove(deque<int>) (prefix)", ranges_remove);
-  bm_sprinkled<std::deque<int>>("ranges::remove(deque<int>) (sprinkled)", ranges_remove);
-
-  bm_prefix<std::list<int>>("ranges::remove(list<int>) (prefix)", ranges_remove);
-  bm_sprinkled<std::list<int>>("ranges::remove(list<int>) (sprinkled)", ranges_remove);
+  auto std_remove = [](auto first, auto last, auto const& value) { return std::remove(first, last, value); };
+
+  // Benchmark {std,ranges}::remove on a sequence of the form xxxxxxxxxxyyyyyyyyyy
+  // where we remove the prefix of x's from the sequence.
+  //
+  // We perform this benchmark in a batch because we need to restore the
+  // state of the container after the operation.
+  {
+    auto bm = []<class Container>(std::string name, auto remove) {
+      benchmark::RegisterBenchmark(
+          name,
+          [remove](auto& st) {
+            std::size_t const size          = st.range(0);
+            constexpr std::size_t BatchSize = 10;
+            using ValueType                 = typename Container::value_type;
+            Container c[BatchSize];
+            ValueType x = Generate<ValueType>::random();
+            ValueType y = Generate<ValueType>::random();
+            for (std::size_t i = 0; i != BatchSize; ++i) {
+              c[i]      = Container(size);
+              auto half = size / 2;
+              std::fill_n(std::fill_n(c[i].begin(), half, x), half, y);
+            }
+
+            while (st.KeepRunningBatch(BatchSize)) {
+              for (std::size_t i = 0; i != BatchSize; ++i) {
+                auto result = remove(c[i].begin(), c[i].end(), x);
+                benchmark::DoNotOptimize(result);
+                benchmark::DoNotOptimize(c[i]);
+                benchmark::DoNotOptimize(x);
+                benchmark::ClobberMemory();
+              }
+
+              st.PauseTiming();
+              for (std::size_t i = 0; i != BatchSize; ++i) {
+                auto half = size / 2;
+                std::fill_n(std::fill_n(c[i].begin(), half, x), half, y);
+              }
+              st.ResumeTiming();
+            }
+          })
+          ->Arg(32)
+          ->Arg(1024)
+          ->Arg(8192);
+    };
+    bm.operator()<std::vector<int>>("std::remove(vector<int>) (prefix)", std_remove);
+    bm.operator()<std::deque<int>>("std::remove(deque<int>) (prefix)", std_remove);
+    bm.operator()<std::list<int>>("std::remove(list<int>) (prefix)", std_remove);
+    bm.operator()<std::vector<int>>("rng::remove(vector<int>) (prefix)", std::ranges::remove);
+    bm.operator()<std::deque<int>>("rng::remove(deque<int>) (prefix)", std::ranges::remove);
+    bm.operator()<std::list<int>>("rng::remove(list<int>) (prefix)", std::ranges::remove);
+  }
+
+  // Benchmark {std,ranges}::remove on a sequence of the form xyxyxyxyxyxyxyxyxyxy
+  // where we remove the x's from the sequence.
+  //
+  // We perform this benchmark in a batch because we need to restore the
+  // state of the container after the operation.
+  {
+    auto bm = []<class Container>(std::string name, auto remove) {
+      benchmark::RegisterBenchmark(
+          name,
+          [remove](auto& st) {
+            std::size_t const size          = st.range(0);
+            constexpr std::size_t BatchSize = 10;
+            using ValueType                 = typename Container::value_type;
+            Container c[BatchSize];
+            ValueType x    = Generate<ValueType>::random();
+            ValueType y    = Generate<ValueType>::random();
+            auto alternate = [&](auto out, auto n) {
+              for (std::size_t i = 0; i != n; ++i) {
+                *out++ = (i % 2 == 0 ? x : y);
+              }
+            };
+            for (std::size_t i = 0; i != BatchSize; ++i) {
+              c[i] = Container(size);
+              alternate(c[i].begin(), size);
+            }
+
+            while (st.KeepRunningBatch(BatchSize)) {
+              for (std::size_t i = 0; i != BatchSize; ++i) {
+                auto result = remove(c[i].begin(), c[i].end(), x);
+                benchmark::DoNotOptimize(result);
+                benchmark::DoNotOptimize(c[i]);
+                benchmark::DoNotOptimize(x);
+                benchmark::ClobberMemory();
+              }
+
+              st.PauseTiming();
+              for (std::size_t i = 0; i != BatchSize; ++i) {
+                alternate(c[i].begin(), size);
+              }
+              st.ResumeTiming();
+            }
+          })
+          ->Arg(32)
+          ->Arg(1024)
+          ->Arg(8192);
+    };
+    bm.operator()<std::vector<int>>("std::remove(vector<int>) (sprinkled)", std_remove);
+    bm.operator()<std::deque<int>>("std::remove(deque<int>) (sprinkled)", std_remove);
+    bm.operator()<std::list<int>>("std::remove(list<int>) (sprinkled)", std_remove);
+    bm.operator()<std::vector<int>>("rng::remove(vector<int>) (sprinkled)", std::ranges::remove);
+    bm.operator()<std::deque<int>>("rng::remove(deque<int>) (sprinkled)", std::ranges::remove);
+    bm.operator()<std::list<int>>("rng::remove(list<int>) (sprinkled)", std::ranges::remove);
+  }
 
   benchmark::Initialize(&argc, argv);
   benchmark::RunSpecifiedBenchmarks();
diff --git a/libcxx/test/benchmarks/algorithms/modifying/remove_copy.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/remove_copy.bench.cpp
index 88c05384eb7bd..b5e876fc9ba15 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/remove_copy.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/remove_copy.bench.cpp
@@ -19,88 +19,87 @@
 #include "benchmark/benchmark.h"
 #include "../../GenerateInput.h"
 
-// Create a sequence of the form xxxxxxxxxxyyyyyyyyyy and remove
-// the prefix of x's from it.
-template <class Container, class Operation>
-void bm_prefix(std::string operation_name, Operation remove_copy) {
-  auto bench = [remove_copy](auto& st) {
-    std::size_t const size = st.range(0);
-    using ValueType        = typename Container::value_type;
-    Container c;
-    ValueType x = Generate<ValueType>::random();
-    ValueType y = Generate<ValueType>::random();
-    std::fill_n(std::back_inserter(c), size / 2, x);
-    std::fill_n(std::back_inserter(c), size / 2, y);
-
-    std::vector<ValueType> out(size);
-
-    for ([[maybe_unused]] auto _ : st) {
-      auto result = remove_copy(c.begin(), c.end(), out.begin(), x);
-      benchmark::DoNotOptimize(result);
-      benchmark::DoNotOptimize(c);
-      benchmark::DoNotOptimize(out);
-      benchmark::DoNotOptimize(x);
-      benchmark::ClobberMemory();
-    }
-  };
-  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
-
-// Create a sequence of the form xyxyxyxyxyxyxyxyxyxy and remove
-// the x's from it.
-template <class Container, class Operation>
-void bm_sprinkled(std::string operation_name, Operation remove_copy) {
-  auto bench = [remove_copy](auto& st) {
-    std::size_t const size = st.range(0);
-    using ValueType        = typename Container::value_type;
-    Container c;
-    ValueType x = Generate<ValueType>::random();
-    ValueType y = Generate<ValueType>::random();
-    for (std::size_t i = 0; i != size; ++i) {
-      c.push_back(i % 2 == 0 ? x : y);
-    }
-
-    std::vector<ValueType> out(size);
-
-    for ([[maybe_unused]] auto _ : st) {
-      auto result = remove_copy(c.begin(), c.end(), out.begin(), x);
-      benchmark::DoNotOptimize(result);
-      benchmark::DoNotOptimize(c);
-      benchmark::DoNotOptimize(out);
-      benchmark::DoNotOptimize(x);
-      benchmark::ClobberMemory();
-    }
-  };
-  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
-
 int main(int argc, char** argv) {
   auto std_remove_copy = [](auto first, auto last, auto out, auto const& value) {
     return std::remove_copy(first, last, out, value);
   };
-  auto ranges_remove_copy = [](auto first, auto last, auto out, auto const& value) {
-    return std::ranges::remove_copy(first, last, out, value);
-  };
-
-  // std::remove_copy
-  bm_prefix<std::vector<int>>("std::remove_copy(vector<int>) (prefix)", std_remove_copy);
-  bm_sprinkled<std::vector<int>>("std::remove_copy(vector<int>) (sprinkled)", std_remove_copy);
-
-  bm_prefix<std::deque<int>>("std::remove_copy(deque<int>) (prefix)", std_remove_copy);
-  bm_sprinkled<std::deque<int>>("std::remove_copy(deque<int>) (sprinkled)", std_remove_copy);
-
-  bm_prefix<std::list<int>>("std::remove_copy(list<int>) (prefix)", std_remove_copy);
-  bm_sprinkled<std::list<int>>("std::remove_copy(list<int>) (sprinkled)", std_remove_copy);
-
-  // ranges::remove_copy
-  bm_prefix<std::vector<int>>("ranges::remove_copy(vector<int>) (prefix)", ranges_remove_copy);
-  bm_sprinkled<std::vector<int>>("ranges::remove_copy(vector<int>) (sprinkled)", ranges_remove_copy);
-
-  bm_prefix<std::deque<int>>("ranges::remove_copy(deque<int>) (prefix)", ranges_remove_copy);
-  bm_sprinkled<std::deque<int>>("ranges::remove_copy(deque<int>) (sprinkled)", ranges_remove_copy);
 
-  bm_prefix<std::list<int>>("ranges::remove_copy(list<int>) (prefix)", ranges_remove_copy);
-  bm_sprinkled<std::list<int>>("ranges::remove_copy(list<int>) (sprinkled)", ranges_remove_copy);
+  // Benchmark {std,ranges}::remove_copy on a sequence of the form xxxxxxxxxxyyyyyyyyyy
+  // where we remove the prefix of x's from the sequence.
+  {
+    auto bm = []<class Container>(std::string name, auto remove_copy) {
+      benchmark::RegisterBenchmark(
+          name,
+          [remove_copy](auto& st) {
+            std::size_t const size = st.range(0);
+            using ValueType        = typename Container::value_type;
+            Container c;
+            ValueType x = Generate<ValueType>::random();
+            ValueType y = Generate<ValueType>::random();
+            std::fill_n(std::back_inserter(c), size / 2, x);
+            std::fill_n(std::back_inserter(c), size / 2, y);
+
+            std::vector<ValueType> out(size);
+
+            for ([[maybe_unused]] auto _ : st) {
+              auto result = remove_copy(c.begin(), c.end(), out.begin(), x);
+              benchmark::DoNotOptimize(result);
+              benchmark::DoNotOptimize(c);
+              benchmark::DoNotOptimize(out);
+              benchmark::DoNotOptimize(x);
+              benchmark::ClobberMemory();
+            }
+          })
+          ->Arg(32)
+          ->Arg(1024)
+          ->Arg(8192);
+    };
+    bm.operator()<std::vector<int>>("std::remove_copy(vector<int>) (prefix)", std_remove_copy);
+    bm.operator()<std::deque<int>>("std::remove_copy(deque<int>) (prefix)", std_remove_copy);
+    bm.operator()<std::list<int>>("std::remove_copy(list<int>) (prefix)", std_remove_copy);
+    bm.operator()<std::vector<int>>("rng::remove_copy(vector<int>) (prefix)", std::ranges::remove_copy);
+    bm.operator()<std::deque<int>>("rng::remove_copy(deque<int>) (prefix)", std::ranges::remove_copy);
+    bm.operator()<std::list<int>>("rng::remove_copy(list<int>) (prefix)", std::ranges::remove_copy);
+  }
+
+  // Benchmark {std,ranges}::remove_copy on a sequence of the form xyxyxyxyxyxyxyxyxyxy
+  // where we remove the x's from the sequence.
+  {
+    auto bm = []<class Container>(std::string name, auto remove_copy) {
+      benchmark::RegisterBenchmark(
+          name,
+          [remove_copy](auto& st) {
+            std::size_t const size = st.range(0);
+            using ValueType        = typename Container::value_type;
+            Container c;
+            ValueType x = Generate<ValueType>::random();
+            ValueType y = Generate<ValueType>::random();
+            for (std::size_t i = 0; i != size; ++i) {
+              c.push_back(i % 2 == 0 ? x : y);
+            }
+
+            std::vector<ValueType> out(size);
+
+            for ([[maybe_unused]] auto _ : st) {
+              auto result = remove_copy(c.begin(), c.end(), out.begin(), x);
+              benchmark::DoNotOptimize(result);
+              benchmark::DoNotOptimize(c);
+              benchmark::DoNotOptimize(out);
+              benchmark::DoNotOptimize(x);
+              benchmark::ClobberMemory();
+            }
+          })
+          ->Arg(32)
+          ->Arg(1024)
+          ->Arg(8192);
+    };
+    bm.operator()<std::vector<int>>("std::remove_copy(vector<int>) (sprinkled)", std_remove_copy);
+    bm.operator()<std::deque<int>>("std::remove_copy(deque<int>) (sprinkled)", std_remove_copy);
+    bm.operator()<std::list<int>>("std::remove_copy(list<int>) (sprinkled)", std_remove_copy);
+    bm.operator()<std::vector<int>>("rng::remove_copy(vector<int>) (sprinkled)", std::ranges::remove_copy);
+    bm.operator()<std::deque<int>>("rng::remove_copy(deque<int>) (sprinkled)", std::ranges::remove_copy);
+    bm.operator()<std::list<int>>("rng::remove_copy(list<int>) (sprinkled)", std::ranges::remove_copy);
+  }
 
   benchmark::Initialize(&argc, argv);
   benchmark::RunSpecifiedBenchmarks();
diff --git a/libcxx/test/benchmarks/algorithms/modifying/remove_copy_if.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/remove_copy_if.bench.cpp
index 95b0e93362bab..13464b65e8158 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/remove_copy_if.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/remove_copy_if.bench.cpp
@@ -19,98 +19,97 @@
 #include "benchmark/benchmark.h"
 #include "../../GenerateInput.h"
 
-// Create a sequence of the form xxxxxxxxxxyyyyyyyyyy and remove
-// the prefix of x's from it.
-template <class Container, class Operation>
-void bm_prefix(std::string operation_name, Operation remove_copy_if) {
-  auto bench = [remove_copy_if](auto& st) {
-    std::size_t const size = st.range(0);
-    using ValueType        = typename Container::value_type;
-    Container c;
-    ValueType x = Generate<ValueType>::random();
-    ValueType y = Generate<ValueType>::random();
-    std::fill_n(std::back_inserter(c), size / 2, x);
-    std::fill_n(std::back_inserter(c), size / 2, y);
-
-    auto pred = [&](auto& element) {
-      benchmark::DoNotOptimize(element);
-      return element == x;
-    };
-
-    std::vector<ValueType> out(size);
-
-    for ([[maybe_unused]] auto _ : st) {
-      auto result = remove_copy_if(c.begin(), c.end(), out.begin(), pred);
-      benchmark::DoNotOptimize(result);
-      benchmark::DoNotOptimize(c);
-      benchmark::DoNotOptimize(out);
-      benchmark::DoNotOptimize(x);
-      benchmark::ClobberMemory();
-    }
-  };
-  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
-
-// Create a sequence of the form xyxyxyxyxyxyxyxyxyxy and remove
-// the x's from it.
-template <class Container, class Operation>
-void bm_sprinkled(std::string operation_name, Operation remove_copy_if) {
-  auto bench = [remove_copy_if](auto& st) {
-    std::size_t const size = st.range(0);
-    using ValueType        = typename Container::value_type;
-    Container c;
-    ValueType x = Generate<ValueType>::random();
-    ValueType y = Generate<ValueType>::random();
-    for (std::size_t i = 0; i != size; ++i) {
-      c.push_back(i % 2 == 0 ? x : y);
-    }
-
-    auto pred = [&](auto& element) {
-      benchmark::DoNotOptimize(element);
-      return element == x;
-    };
-
-    std::vector<ValueType> out(size);
-
-    for ([[maybe_unused]] auto _ : st) {
-      auto result = remove_copy_if(c.begin(), c.end(), out.begin(), pred);
-      benchmark::DoNotOptimize(result);
-      benchmark::DoNotOptimize(c);
-      benchmark::DoNotOptimize(out);
-      benchmark::DoNotOptimize(x);
-      benchmark::ClobberMemory();
-    }
-  };
-  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
-
 int main(int argc, char** argv) {
   auto std_remove_copy_if = [](auto first, auto last, auto out, auto pred) {
     return std::remove_copy_if(first, last, out, pred);
   };
-  auto ranges_remove_copy_if = [](auto first, auto last, auto out, auto pred) {
-    return std::ranges::remove_copy_if(first, last, out, pred);
-  };
-
-  // std::remove_copy_if
-  bm_prefix<std::vector<int>>("std::remove_copy_if(vector<int>) (prefix)", std_remove_copy_if);
-  bm_sprinkled<std::vector<int>>("std::remove_copy_if(vector<int>) (sprinkled)", std_remove_copy_if);
-
-  bm_prefix<std::deque<int>>("std::remove_copy_if(deque<int>) (prefix)", std_remove_copy_if);
-  bm_sprinkled<std::deque<int>>("std::remove_copy_if(deque<int>) (sprinkled)", std_remove_copy_if);
 
-  bm_prefix<std::list<int>>("std::remove_copy_if(list<int>) (prefix)", std_remove_copy_if);
-  bm_sprinkled<std::list<int>>("std::remove_copy_if(list<int>) (sprinkled)", std_remove_copy_if);
-
-  // ranges::remove_copy_if
-  bm_prefix<std::vector<int>>("ranges::remove_copy_if(vector<int>) (prefix)", ranges_remove_copy_if);
-  bm_sprinkled<std::vector<int>>("ranges::remove_copy_if(vector<int>) (sprinkled)", ranges_remove_copy_if);
-
-  bm_prefix<std::deque<int>>("ranges::remove_copy_if(deque<int>) (prefix)", ranges_remove_copy_if);
-  bm_sprinkled<std::deque<int>>("ranges::remove_copy_if(deque<int>) (sprinkled)", ranges_remove_copy_if);
-
-  bm_prefix<std::list<int>>("ranges::remove_copy_if(list<int>) (prefix)", ranges_remove_copy_if);
-  bm_sprinkled<std::list<int>>("ranges::remove_copy_if(list<int>) (sprinkled)", ranges_remove_copy_if);
+  // Benchmark {std,ranges}::remove_copy_if on a sequence of the form xxxxxxxxxxyyyyyyyyyy
+  // where we remove the prefix of x's from the sequence.
+  {
+    auto bm = []<class Container>(std::string name, auto remove_copy_if) {
+      benchmark::RegisterBenchmark(
+          name,
+          [remove_copy_if](auto& st) {
+            std::size_t const size = st.range(0);
+            using ValueType        = typename Container::value_type;
+            Container c;
+            ValueType x = Generate<ValueType>::random();
+            ValueType y = Generate<ValueType>::random();
+            std::fill_n(std::back_inserter(c), size / 2, x);
+            std::fill_n(std::back_inserter(c), size / 2, y);
+
+            auto pred = [&](auto& element) {
+              benchmark::DoNotOptimize(element);
+              return element == x;
+            };
+
+            std::vector<ValueType> out(size);
+
+            for ([[maybe_unused]] auto _ : st) {
+              auto result = remove_copy_if(c.begin(), c.end(), out.begin(), pred);
+              benchmark::DoNotOptimize(result);
+              benchmark::DoNotOptimize(c);
+              benchmark::DoNotOptimize(out);
+              benchmark::DoNotOptimize(x);
+              benchmark::ClobberMemory();
+            }
+          })
+          ->Arg(32)
+          ->Arg(1024)
+          ->Arg(8192);
+    };
+    bm.operator()<std::vector<int>>("std::remove_copy_if(vector<int>) (prefix)", std_remove_copy_if);
+    bm.operator()<std::deque<int>>("std::remove_copy_if(deque<int>) (prefix)", std_remove_copy_if);
+    bm.operator()<std::list<int>>("std::remove_copy_if(list<int>) (prefix)", std_remove_copy_if);
+    bm.operator()<std::vector<int>>("rng::remove_copy_if(vector<int>) (prefix)", std::ranges::remove_copy_if);
+    bm.operator()<std::deque<int>>("rng::remove_copy_if(deque<int>) (prefix)", std::ranges::remove_copy_if);
+    bm.operator()<std::list<int>>("rng::remove_copy_if(list<int>) (prefix)", std::ranges::remove_copy_if);
+  }
+
+  // Benchmark {std,ranges}::remove_copy_if on a sequence of the form xyxyxyxyxyxyxyxyxyxy
+  // where we remove the x's from the sequence.
+  {
+    auto bm = []<class Container>(std::string name, auto remove_copy_if) {
+      benchmark::RegisterBenchmark(
+          name,
+          [remove_copy_if](auto& st) {
+            std::size_t const size = st.range(0);
+            using ValueType        = typename Container::value_type;
+            Container c;
+            ValueType x = Generate<ValueType>::random();
+            ValueType y = Generate<ValueType>::random();
+            for (std::size_t i = 0; i != size; ++i) {
+              c.push_back(i % 2 == 0 ? x : y);
+            }
+
+            auto pred = [&](auto& element) {
+              benchmark::DoNotOptimize(element);
+              return element == x;
+            };
+
+            std::vector<ValueType> out(size);
+
+            for ([[maybe_unused]] auto _ : st) {
+              auto result = remove_copy_if(c.begin(), c.end(), out.begin(), pred);
+              benchmark::DoNotOptimize(result);
+              benchmark::DoNotOptimize(c);
+              benchmark::DoNotOptimize(out);
+              benchmark::DoNotOptimize(x);
+              benchmark::ClobberMemory();
+            }
+          })
+          ->Arg(32)
+          ->Arg(1024)
+          ->Arg(8192);
+    };
+    bm.operator()<std::vector<int>>("std::remove_copy_if(vector<int>) (sprinkled)", std_remove_copy_if);
+    bm.operator()<std::deque<int>>("std::remove_copy_if(deque<int>) (sprinkled)", std_remove_copy_if);
+    bm.operator()<std::list<int>>("std::remove_copy_if(list<int>) (sprinkled)", std_remove_copy_if);
+    bm.operator()<std::vector<int>>("rng::remove_copy_if(vector<int>) (sprinkled)", std::ranges::remove_copy_if);
+    bm.operator()<std::deque<int>>("rng::remove_copy_if(deque<int>) (sprinkled)", std::ranges::remove_copy_if);
+    bm.operator()<std::list<int>>("rng::remove_copy_if(list<int>) (sprinkled)", std::ranges::remove_copy_if);
+  }
 
   benchmark::Initialize(&argc, argv);
   benchmark::RunSpecifiedBenchmarks();
diff --git a/libcxx/test/benchmarks/algorithms/modifying/remove_if.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/remove_if.bench.cpp
index db0dabfbaa2c3..9ccc436ba47cb 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/remove_if.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/remove_if.bench.cpp
@@ -19,122 +19,123 @@
 #include "benchmark/benchmark.h"
 #include "../../GenerateInput.h"
 
-// Create a sequence of the form xxxxxxxxxxyyyyyyyyyy and remove
-// the prefix of x's from it.
-//
-// We perform this benchmark in a batch because we need to restore the
-// state of the container after the operation.
-template <class Container, class Operation>
-void bm_prefix(std::string operation_name, Operation remove_if) {
-  auto bench = [remove_if](auto& st) {
-    std::size_t const size          = st.range(0);
-    constexpr std::size_t BatchSize = 10;
-    using ValueType                 = typename Container::value_type;
-    Container c[BatchSize];
-    ValueType x = Generate<ValueType>::random();
-    ValueType y = Generate<ValueType>::random();
-    for (std::size_t i = 0; i != BatchSize; ++i) {
-      c[i]      = Container(size);
-      auto half = size / 2;
-      std::fill_n(std::fill_n(c[i].begin(), half, x), half, y);
-    }
-
-    auto pred = [&](auto& element) {
-      benchmark::DoNotOptimize(element);
-      return element == x;
-    };
-
-    while (st.KeepRunningBatch(BatchSize)) {
-      for (std::size_t i = 0; i != BatchSize; ++i) {
-        auto result = remove_if(c[i].begin(), c[i].end(), pred);
-        benchmark::DoNotOptimize(result);
-        benchmark::DoNotOptimize(c[i]);
-        benchmark::DoNotOptimize(x);
-        benchmark::ClobberMemory();
-      }
-
-      st.PauseTiming();
-      for (std::size_t i = 0; i != BatchSize; ++i) {
-        auto half = size / 2;
-        std::fill_n(std::fill_n(c[i].begin(), half, x), half, y);
-      }
-      st.ResumeTiming();
-    }
-  };
-  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
-
-// Create a sequence of the form xyxyxyxyxyxyxyxyxyxy and remove
-// the x's from it.
-//
-// We perform this benchmark in a batch because we need to restore the
-// state of the container after the operation.
-template <class Container, class Operation>
-void bm_sprinkled(std::string operation_name, Operation remove_if) {
-  auto bench = [remove_if](auto& st) {
-    std::size_t const size          = st.range(0);
-    constexpr std::size_t BatchSize = 10;
-    using ValueType                 = typename Container::value_type;
-    Container c[BatchSize];
-    ValueType x    = Generate<ValueType>::random();
-    ValueType y    = Generate<ValueType>::random();
-    auto alternate = [&](auto out, auto n) {
-      for (std::size_t i = 0; i != n; ++i) {
-        *out++ = (i % 2 == 0 ? x : y);
-      }
+int main(int argc, char** argv) {
+  auto std_remove_if = [](auto first, auto last, auto pred) { return std::remove_if(first, last, pred); };
+
+  // Benchmark {std,ranges}::remove_if on a sequence of the form xxxxxxxxxxyyyyyyyyyy
+  // where we remove the prefix of x's from the sequence.
+  //
+  // We perform this benchmark in a batch because we need to restore the
+  // state of the container after the operation.
+  {
+    auto bm = []<class Container>(std::string name, auto remove_if) {
+      benchmark::RegisterBenchmark(
+          name,
+          [remove_if](auto& st) {
+            std::size_t const size          = st.range(0);
+            constexpr std::size_t BatchSize = 10;
+            using ValueType                 = typename Container::value_type;
+            Container c[BatchSize];
+            ValueType x = Generate<ValueType>::random();
+            ValueType y = Generate<ValueType>::random();
+            for (std::size_t i = 0; i != BatchSize; ++i) {
+              c[i]      = Container(size);
+              auto half = size / 2;
+              std::fill_n(std::fill_n(c[i].begin(), half, x), half, y);
+            }
+
+            auto pred = [&](auto& element) {
+              benchmark::DoNotOptimize(element);
+              return element == x;
+            };
+
+            while (st.KeepRunningBatch(BatchSize)) {
+              for (std::size_t i = 0; i != BatchSize; ++i) {
+                auto result = remove_if(c[i].begin(), c[i].end(), pred);
+                benchmark::DoNotOptimize(result);
+                benchmark::DoNotOptimize(c[i]);
+                benchmark::DoNotOptimize(x);
+                benchmark::ClobberMemory();
+              }
+
+              st.PauseTiming();
+              for (std::size_t i = 0; i != BatchSize; ++i) {
+                auto half = size / 2;
+                std::fill_n(std::fill_n(c[i].begin(), half, x), half, y);
+              }
+              st.ResumeTiming();
+            }
+          })
+          ->Arg(32)
+          ->Arg(1024)
+          ->Arg(8192);
     };
-    for (std::size_t i = 0; i != BatchSize; ++i) {
-      c[i] = Container(size);
-      alternate(c[i].begin(), size);
-    }
-
-    auto pred = [&](auto& element) {
-      benchmark::DoNotOptimize(element);
-      return element == x;
+    bm.operator()<std::vector<int>>("std::remove_if(vector<int>) (prefix)", std_remove_if);
+    bm.operator()<std::deque<int>>("std::remove_if(deque<int>) (prefix)", std_remove_if);
+    bm.operator()<std::list<int>>("std::remove_if(list<int>) (prefix)", std_remove_if);
+    bm.operator()<std::vector<int>>("rng::remove_if(vector<int>) (prefix)", std::ranges::remove_if);
+    bm.operator()<std::deque<int>>("rng::remove_if(deque<int>) (prefix)", std::ranges::remove_if);
+    bm.operator()<std::list<int>>("rng::remove_if(list<int>) (prefix)", std::ranges::remove_if);
+  }
+
+  // Benchmark {std,ranges}::remove_if on a sequence of the form xyxyxyxyxyxyxyxyxyxy
+  // where we remove the x's from the sequence.
+  //
+  // We perform this benchmark in a batch because we need to restore the
+  // state of the container after the operation.
+  {
+    auto bm = []<class Container>(std::string name, auto remove_if) {
+      benchmark::RegisterBenchmark(
+          name,
+          [remove_if](auto& st) {
+            std::size_t const size          = st.range(0);
+            constexpr std::size_t BatchSize = 10;
+            using ValueType                 = typename Container::value_type;
+            Container c[BatchSize];
+            ValueType x    = Generate<ValueType>::random();
+            ValueType y    = Generate<ValueType>::random();
+            auto alternate = [&](auto out, auto n) {
+              for (std::size_t i = 0; i != n; ++i) {
+                *out++ = (i % 2 == 0 ? x : y);
+              }
+            };
+            for (std::size_t i = 0; i != BatchSize; ++i) {
+              c[i] = Container(size);
+              alternate(c[i].begin(), size);
+            }
+
+            auto pred = [&](auto& element) {
+              benchmark::DoNotOptimize(element);
+              return element == x;
+            };
+
+            while (st.KeepRunningBatch(BatchSize)) {
+              for (std::size_t i = 0; i != BatchSize; ++i) {
+                auto result = remove_if(c[i].begin(), c[i].end(), pred);
+                benchmark::DoNotOptimize(result);
+                benchmark::DoNotOptimize(c[i]);
+                benchmark::DoNotOptimize(x);
+                benchmark::ClobberMemory();
+              }
+
+              st.PauseTiming();
+              for (std::size_t i = 0; i != BatchSize; ++i) {
+                alternate(c[i].begin(), size);
+              }
+              st.ResumeTiming();
+            }
+          })
+          ->Arg(32)
+          ->Arg(1024)
+          ->Arg(8192);
     };
-
-    while (st.KeepRunningBatch(BatchSize)) {
-      for (std::size_t i = 0; i != BatchSize; ++i) {
-        auto result = remove_if(c[i].begin(), c[i].end(), pred);
-        benchmark::DoNotOptimize(result);
-        benchmark::DoNotOptimize(c[i]);
-        benchmark::DoNotOptimize(x);
-        benchmark::ClobberMemory();
-      }
-
-      st.PauseTiming();
-      for (std::size_t i = 0; i != BatchSize; ++i) {
-        alternate(c[i].begin(), size);
-      }
-      st.ResumeTiming();
-    }
-  };
-  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
-
-int main(int argc, char** argv) {
-  auto std_remove_if    = [](auto first, auto last, auto pred) { return std::remove_if(first, last, pred); };
-  auto ranges_remove_if = [](auto first, auto last, auto pred) { return std::ranges::remove_if(first, last, pred); };
-
-  // std::remove_if
-  bm_prefix<std::vector<int>>("std::remove_if(vector<int>) (prefix)", std_remove_if);
-  bm_sprinkled<std::vector<int>>("std::remove_if(vector<int>) (sprinkled)", std_remove_if);
-
-  bm_prefix<std::deque<int>>("std::remove_if(deque<int>) (prefix)", std_remove_if);
-  bm_sprinkled<std::deque<int>>("std::remove_if(deque<int>) (sprinkled)", std_remove_if);
-
-  bm_prefix<std::list<int>>("std::remove_if(list<int>) (prefix)", std_remove_if);
-  bm_sprinkled<std::list<int>>("std::remove_if(list<int>) (sprinkled)", std_remove_if);
-
-  // ranges::remove_if
-  bm_prefix<std::vector<int>>("ranges::remove_if(vector<int>) (prefix)", ranges_remove_if);
-  bm_sprinkled<std::vector<int>>("ranges::remove_if(vector<int>) (sprinkled)", ranges_remove_if);
-
-  bm_prefix<std::deque<int>>("ranges::remove_if(deque<int>) (prefix)", ranges_remove_if);
-  bm_sprinkled<std::deque<int>>("ranges::remove_if(deque<int>) (sprinkled)", ranges_remove_if);
-
-  bm_prefix<std::list<int>>("ranges::remove_if(list<int>) (prefix)", ranges_remove_if);
-  bm_sprinkled<std::list<int>>("ranges::remove_if(list<int>) (sprinkled)", ranges_remove_if);
+    bm.operator()<std::vector<int>>("std::remove_if(vector<int>) (sprinkled)", std_remove_if);
+    bm.operator()<std::deque<int>>("std::remove_if(deque<int>) (sprinkled)", std_remove_if);
+    bm.operator()<std::list<int>>("std::remove_if(list<int>) (sprinkled)", std_remove_if);
+    bm.operator()<std::vector<int>>("rng::remove_if(vector<int>) (sprinkled)", std::ranges::remove_if);
+    bm.operator()<std::deque<int>>("rng::remove_if(deque<int>) (sprinkled)", std::ranges::remove_if);
+    bm.operator()<std::list<int>>("rng::remove_if(list<int>) (sprinkled)", std::ranges::remove_if);
+  }
 
   benchmark::Initialize(&argc, argv);
   benchmark::RunSpecifiedBenchmarks();
diff --git a/libcxx/test/benchmarks/algorithms/modifying/replace.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/replace.bench.cpp
index b55790d4db017..48ab1063a9954 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/replace.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/replace.bench.cpp
@@ -19,86 +19,85 @@
 #include "benchmark/benchmark.h"
 #include "../../GenerateInput.h"
 
-// Create a sequence of the form xxxxxxxxxxyyyyyyyyyy, replace
-// into zzzzzzzzzzzyyyyyyyyyy and then back.
-//
-// This measures the performance of replace() when replacing a large
-// contiguous sequence of equal values.
-template <class Container, class Operation>
-void bm_prefix(std::string operation_name, Operation replace) {
-  auto bench = [replace](auto& st) {
-    std::size_t const size = st.range(0);
-    using ValueType        = typename Container::value_type;
-    Container c;
-    ValueType x = Generate<ValueType>::random();
-    ValueType y = Generate<ValueType>::random();
-    ValueType z = Generate<ValueType>::random();
-    std::fill_n(std::back_inserter(c), size / 2, x);
-    std::fill_n(std::back_inserter(c), size / 2, y);
-
-    for ([[maybe_unused]] auto _ : st) {
-      replace(c.begin(), c.end(), x, z);
-      std::swap(x, z);
-      benchmark::DoNotOptimize(c);
-      benchmark::DoNotOptimize(x);
-      benchmark::DoNotOptimize(z);
-      benchmark::ClobberMemory();
-    }
-  };
-  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
-
-// Sprinkle elements to replace inside the range, like xyxyxyxyxyxyxyxyxyxy.
-template <class Container, class Operation>
-void bm_sprinkled(std::string operation_name, Operation replace) {
-  auto bench = [replace](auto& st) {
-    std::size_t const size = st.range(0);
-    using ValueType        = typename Container::value_type;
-    Container c;
-    ValueType x = Generate<ValueType>::random();
-    ValueType y = Generate<ValueType>::random();
-    ValueType z = Generate<ValueType>::random();
-    for (std::size_t i = 0; i != size; ++i) {
-      c.push_back(i % 2 == 0 ? x : y);
-    }
-
-    for ([[maybe_unused]] auto _ : st) {
-      replace(c.begin(), c.end(), x, z);
-      std::swap(x, z);
-      benchmark::DoNotOptimize(c);
-      benchmark::DoNotOptimize(x);
-      benchmark::DoNotOptimize(z);
-      benchmark::ClobberMemory();
-    }
-  };
-  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
-
 int main(int argc, char** argv) {
-  auto std_replace    = [](auto first, auto last, auto old, auto new_) { return std::replace(first, last, old, new_); };
-  auto ranges_replace = [](auto first, auto last, auto old, auto new_) {
-    return std::ranges::replace(first, last, old, new_);
-  };
-
-  // std::replace
-  bm_prefix<std::vector<int>>("std::replace(vector<int>) (prefix)", std_replace);
-  bm_sprinkled<std::vector<int>>("std::replace(vector<int>) (sprinkled)", std_replace);
-
-  bm_prefix<std::deque<int>>("std::replace(deque<int>) (prefix)", std_replace);
-  bm_sprinkled<std::deque<int>>("std::replace(deque<int>) (sprinkled)", std_replace);
+  auto std_replace = [](auto first, auto last, auto old, auto new_) { return std::replace(first, last, old, new_); };
 
-  bm_prefix<std::list<int>>("std::replace(list<int>) (prefix)", std_replace);
-  bm_sprinkled<std::list<int>>("std::replace(list<int>) (sprinkled)", std_replace);
+  // Create a sequence of the form xxxxxxxxxxyyyyyyyyyy, replace
+  // into zzzzzzzzzzzyyyyyyyyyy and then back.
+  //
+  // This measures the performance of replace() when replacing a large
+  // contiguous sequence of equal values.
+  {
+    auto bm = []<class Container>(std::string name, auto replace) {
+      benchmark::RegisterBenchmark(
+          name,
+          [replace](auto& st) {
+            std::size_t const size = st.range(0);
+            using ValueType        = typename Container::value_type;
+            Container c;
+            ValueType x = Generate<ValueType>::random();
+            ValueType y = Generate<ValueType>::random();
+            ValueType z = Generate<ValueType>::random();
+            std::fill_n(std::back_inserter(c), size / 2, x);
+            std::fill_n(std::back_inserter(c), size / 2, y);
 
-  // ranges::replace
-  bm_prefix<std::vector<int>>("ranges::replace(vector<int>) (prefix)", ranges_replace);
-  bm_sprinkled<std::vector<int>>("ranges::replace(vector<int>) (sprinkled)", ranges_replace);
+            for ([[maybe_unused]] auto _ : st) {
+              replace(c.begin(), c.end(), x, z);
+              std::swap(x, z);
+              benchmark::DoNotOptimize(c);
+              benchmark::DoNotOptimize(x);
+              benchmark::DoNotOptimize(z);
+              benchmark::ClobberMemory();
+            }
+          })
+          ->Arg(32)
+          ->Arg(1024)
+          ->Arg(8192);
+    };
+    bm.operator()<std::vector<int>>("std::replace(vector<int>) (prefix)", std_replace);
+    bm.operator()<std::deque<int>>("std::replace(deque<int>) (prefix)", std_replace);
+    bm.operator()<std::list<int>>("std::replace(list<int>) (prefix)", std_replace);
+    bm.operator()<std::vector<int>>("rng::replace(vector<int>) (prefix)", std::ranges::replace);
+    bm.operator()<std::deque<int>>("rng::replace(deque<int>) (prefix)", std::ranges::replace);
+    bm.operator()<std::list<int>>("rng::replace(list<int>) (prefix)", std::ranges::replace);
+  }
 
-  bm_prefix<std::deque<int>>("ranges::replace(deque<int>) (prefix)", ranges_replace);
-  bm_sprinkled<std::deque<int>>("ranges::replace(deque<int>) (sprinkled)", ranges_replace);
+  // Sprinkle elements to replace inside the range, like xyxyxyxyxyxyxyxyxyxy.
+  {
+    auto bm = []<class Container>(std::string name, auto replace) {
+      benchmark::RegisterBenchmark(
+          name,
+          [replace](auto& st) {
+            std::size_t const size = st.range(0);
+            using ValueType        = typename Container::value_type;
+            Container c;
+            ValueType x = Generate<ValueType>::random();
+            ValueType y = Generate<ValueType>::random();
+            ValueType z = Generate<ValueType>::random();
+            for (std::size_t i = 0; i != size; ++i) {
+              c.push_back(i % 2 == 0 ? x : y);
+            }
 
-  bm_prefix<std::list<int>>("ranges::replace(list<int>) (prefix)", ranges_replace);
-  bm_sprinkled<std::list<int>>("ranges::replace(list<int>) (sprinkled)", ranges_replace);
+            for ([[maybe_unused]] auto _ : st) {
+              replace(c.begin(), c.end(), x, z);
+              std::swap(x, z);
+              benchmark::DoNotOptimize(c);
+              benchmark::DoNotOptimize(x);
+              benchmark::DoNotOptimize(z);
+              benchmark::ClobberMemory();
+            }
+          })
+          ->Arg(32)
+          ->Arg(1024)
+          ->Arg(8192);
+    };
+    bm.operator()<std::vector<int>>("std::replace(vector<int>) (sprinkled)", std_replace);
+    bm.operator()<std::deque<int>>("std::replace(deque<int>) (sprinkled)", std_replace);
+    bm.operator()<std::list<int>>("std::replace(list<int>) (sprinkled)", std_replace);
+    bm.operator()<std::vector<int>>("rng::replace(vector<int>) (sprinkled)", std::ranges::replace);
+    bm.operator()<std::deque<int>>("rng::replace(deque<int>) (sprinkled)", std::ranges::replace);
+    bm.operator()<std::list<int>>("rng::replace(list<int>) (sprinkled)", std::ranges::replace);
+  }
 
   benchmark::Initialize(&argc, argv);
   benchmark::RunSpecifiedBenchmarks();
diff --git a/libcxx/test/benchmarks/algorithms/modifying/replace_if.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/replace_if.bench.cpp
index 820cf08e5a901..3b139c54eeb12 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/replace_if.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/replace_if.bench.cpp
@@ -19,96 +19,95 @@
 #include "benchmark/benchmark.h"
 #include "../../GenerateInput.h"
 
-// Create a sequence of the form xxxxxxxxxxyyyyyyyyyy, replace
-// into zzzzzzzzzzzyyyyyyyyyy and then back.
-//
-// This measures the performance of replace_if() when replacing a large
-// contiguous sequence of equal values.
-template <class Container, class Operation>
-void bm_prefix(std::string operation_name, Operation replace_if) {
-  auto bench = [replace_if](auto& st) {
-    std::size_t const size = st.range(0);
-    using ValueType        = typename Container::value_type;
-    Container c;
-    ValueType x = Generate<ValueType>::random();
-    ValueType y = Generate<ValueType>::random();
-    ValueType z = Generate<ValueType>::random();
-    std::fill_n(std::back_inserter(c), size / 2, x);
-    std::fill_n(std::back_inserter(c), size / 2, y);
-
-    for ([[maybe_unused]] auto _ : st) {
-      auto pred = [&x](auto& element) {
-        benchmark::DoNotOptimize(element);
-        return element == x;
-      };
-      replace_if(c.begin(), c.end(), pred, z);
-      std::swap(x, z);
-      benchmark::DoNotOptimize(c);
-      benchmark::DoNotOptimize(x);
-      benchmark::DoNotOptimize(z);
-      benchmark::ClobberMemory();
-    }
-  };
-  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
-
-// Sprinkle elements to replace inside the range, like xyxyxyxyxyxyxyxyxyxy.
-template <class Container, class Operation>
-void bm_sprinkled(std::string operation_name, Operation replace_if) {
-  auto bench = [replace_if](auto& st) {
-    std::size_t const size = st.range(0);
-    using ValueType        = typename Container::value_type;
-    Container c;
-    ValueType x = Generate<ValueType>::random();
-    ValueType y = Generate<ValueType>::random();
-    ValueType z = Generate<ValueType>::random();
-    for (std::size_t i = 0; i != size; ++i) {
-      c.push_back(i % 2 == 0 ? x : y);
-    }
-
-    for ([[maybe_unused]] auto _ : st) {
-      auto pred = [&x](auto& element) {
-        benchmark::DoNotOptimize(element);
-        return element == x;
-      };
-      replace_if(c.begin(), c.end(), pred, z);
-      std::swap(x, z);
-      benchmark::DoNotOptimize(c);
-      benchmark::DoNotOptimize(x);
-      benchmark::DoNotOptimize(z);
-      benchmark::ClobberMemory();
-    }
-  };
-  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
-
 int main(int argc, char** argv) {
   auto std_replace_if = [](auto first, auto last, auto pred, auto new_) {
     return std::replace_if(first, last, pred, new_);
   };
-  auto ranges_replace_if = [](auto first, auto last, auto pred, auto new_) {
-    return std::ranges::replace_if(first, last, pred, new_);
-  };
-
-  // std::replace_if
-  bm_prefix<std::vector<int>>("std::replace_if(vector<int>) (prefix)", std_replace_if);
-  bm_sprinkled<std::vector<int>>("std::replace_if(vector<int>) (sprinkled)", std_replace_if);
-
-  bm_prefix<std::deque<int>>("std::replace_if(deque<int>) (prefix)", std_replace_if);
-  bm_sprinkled<std::deque<int>>("std::replace_if(deque<int>) (sprinkled)", std_replace_if);
 
-  bm_prefix<std::list<int>>("std::replace_if(list<int>) (prefix)", std_replace_if);
-  bm_sprinkled<std::list<int>>("std::replace_if(list<int>) (sprinkled)", std_replace_if);
+  // Benchmark {std,ranges}::replace_if on a sequence of the form xxxxxxxxxxyyyyyyyyyy
+  // where we replace into zzzzzzzzzzzyyyyyyyyyy and then back.
+  //
+  // This measures the performance of replace_if() when replacing a large
+  // contiguous sequence of equal values.
+  {
+    auto bm = []<class Container>(std::string name, auto replace_if) {
+      benchmark::RegisterBenchmark(
+          name,
+          [replace_if](auto& st) {
+            std::size_t const size = st.range(0);
+            using ValueType        = typename Container::value_type;
+            Container c;
+            ValueType x = Generate<ValueType>::random();
+            ValueType y = Generate<ValueType>::random();
+            ValueType z = Generate<ValueType>::random();
+            std::fill_n(std::back_inserter(c), size / 2, x);
+            std::fill_n(std::back_inserter(c), size / 2, y);
 
-  // ranges::replace_if
-  bm_prefix<std::vector<int>>("ranges::replace_if(vector<int>) (prefix)", ranges_replace_if);
-  bm_sprinkled<std::vector<int>>("ranges::replace_if(vector<int>) (sprinkled)", ranges_replace_if);
+            for ([[maybe_unused]] auto _ : st) {
+              auto pred = [&x](auto& element) {
+                benchmark::DoNotOptimize(element);
+                return element == x;
+              };
+              replace_if(c.begin(), c.end(), pred, z);
+              std::swap(x, z);
+              benchmark::DoNotOptimize(c);
+              benchmark::DoNotOptimize(x);
+              benchmark::DoNotOptimize(z);
+              benchmark::ClobberMemory();
+            }
+          })
+          ->Arg(32)
+          ->Arg(1024)
+          ->Arg(8192);
+    };
+    bm.operator()<std::vector<int>>("std::replace_if(vector<int>) (prefix)", std_replace_if);
+    bm.operator()<std::deque<int>>("std::replace_if(deque<int>) (prefix)", std_replace_if);
+    bm.operator()<std::list<int>>("std::replace_if(list<int>) (prefix)", std_replace_if);
+    bm.operator()<std::vector<int>>("rng::replace_if(vector<int>) (prefix)", std::ranges::replace_if);
+    bm.operator()<std::deque<int>>("rng::replace_if(deque<int>) (prefix)", std::ranges::replace_if);
+    bm.operator()<std::list<int>>("rng::replace_if(list<int>) (prefix)", std::ranges::replace_if);
+  }
 
-  bm_prefix<std::deque<int>>("ranges::replace_if(deque<int>) (prefix)", ranges_replace_if);
-  bm_sprinkled<std::deque<int>>("ranges::replace_if(deque<int>) (sprinkled)", ranges_replace_if);
+  // Sprinkle elements to replace inside the range, like xyxyxyxyxyxyxyxyxyxy.
+  {
+    auto bm = []<class Container>(std::string name, auto replace_if) {
+      benchmark::RegisterBenchmark(
+          name,
+          [replace_if](auto& st) {
+            std::size_t const size = st.range(0);
+            using ValueType        = typename Container::value_type;
+            Container c;
+            ValueType x = Generate<ValueType>::random();
+            ValueType y = Generate<ValueType>::random();
+            ValueType z = Generate<ValueType>::random();
+            for (std::size_t i = 0; i != size; ++i) {
+              c.push_back(i % 2 == 0 ? x : y);
+            }
 
-  bm_prefix<std::list<int>>("ranges::replace_if(list<int>) (prefix)", ranges_replace_if);
-  bm_sprinkled<std::list<int>>("ranges::replace_if(list<int>) (sprinkled)", ranges_replace_if);
+            for ([[maybe_unused]] auto _ : st) {
+              auto pred = [&x](auto& element) {
+                benchmark::DoNotOptimize(element);
+                return element == x;
+              };
+              replace_if(c.begin(), c.end(), pred, z);
+              std::swap(x, z);
+              benchmark::DoNotOptimize(c);
+              benchmark::DoNotOptimize(x);
+              benchmark::DoNotOptimize(z);
+              benchmark::ClobberMemory();
+            }
+          })
+          ->Arg(32)
+          ->Arg(1024)
+          ->Arg(8192);
+    };
+    bm.operator()<std::vector<int>>("std::replace_if(vector<int>) (sprinkled)", std_replace_if);
+    bm.operator()<std::deque<int>>("std::replace_if(deque<int>) (sprinkled)", std_replace_if);
+    bm.operator()<std::list<int>>("std::replace_if(list<int>) (sprinkled)", std_replace_if);
+    bm.operator()<std::vector<int>>("rng::replace_if(vector<int>) (sprinkled)", std::ranges::replace_if);
+    bm.operator()<std::deque<int>>("rng::replace_if(deque<int>) (sprinkled)", std::ranges::replace_if);
+    bm.operator()<std::list<int>>("rng::replace_if(list<int>) (sprinkled)", std::ranges::replace_if);
+  }
 
   benchmark::Initialize(&argc, argv);
   benchmark::RunSpecifiedBenchmarks();
diff --git a/libcxx/test/benchmarks/algorithms/modifying/reverse.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/reverse.bench.cpp
index dbb0d43d091c3..4ce2133c9a557 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/reverse.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/reverse.bench.cpp
@@ -19,36 +19,32 @@
 #include "benchmark/benchmark.h"
 #include "../../GenerateInput.h"
 
-template <class Container, class Operation>
-void bm(std::string operation_name, Operation reverse) {
-  auto bench = [reverse](auto& st) {
-    std::size_t const size = st.range(0);
-    using ValueType        = typename Container::value_type;
-    Container c;
-    std::generate_n(std::back_inserter(c), size, [] { return Generate<ValueType>::random(); });
-
-    for ([[maybe_unused]] auto _ : st) {
-      reverse(c.begin(), c.end());
-      benchmark::DoNotOptimize(c);
-      benchmark::ClobberMemory();
-    }
-  };
-  benchmark::RegisterBenchmark(operation_name, bench)->Range(8, 1 << 15);
-}
-
 int main(int argc, char** argv) {
-  auto std_reverse    = [](auto first, auto last) { return std::reverse(first, last); };
-  auto ranges_reverse = [](auto first, auto last) { return std::ranges::reverse(first, last); };
-
-  // std::reverse
-  bm<std::vector<int>>("std::reverse(vector<int>)", std_reverse);
-  bm<std::deque<int>>("std::reverse(deque<int>)", std_reverse);
-  bm<std::list<int>>("std::reverse(list<int>)", std_reverse);
-
-  // ranges::reverse
-  bm<std::vector<int>>("ranges::reverse(vector<int>)", ranges_reverse);
-  bm<std::deque<int>>("ranges::reverse(deque<int>)", ranges_reverse);
-  bm<std::list<int>>("ranges::reverse(list<int>)", ranges_reverse);
+  auto std_reverse = [](auto first, auto last) { return std::reverse(first, last); };
+
+  // {std,ranges}::reverse(normal container)
+  {
+    auto bm = []<class Container>(std::string name, auto reverse) {
+      benchmark::RegisterBenchmark(name, [reverse](auto& st) {
+        std::size_t const size = st.range(0);
+        using ValueType        = typename Container::value_type;
+        Container c;
+        std::generate_n(std::back_inserter(c), size, [] { return Generate<ValueType>::random(); });
+
+        for ([[maybe_unused]] auto _ : st) {
+          reverse(c.begin(), c.end());
+          benchmark::DoNotOptimize(c);
+          benchmark::ClobberMemory();
+        }
+      })->Range(8, 1 << 15);
+    };
+    bm.operator()<std::vector<int>>("std::reverse(vector<int>)", std_reverse);
+    bm.operator()<std::deque<int>>("std::reverse(deque<int>)", std_reverse);
+    bm.operator()<std::list<int>>("std::reverse(list<int>)", std_reverse);
+    bm.operator()<std::vector<int>>("rng::reverse(vector<int>)", std::ranges::reverse);
+    bm.operator()<std::deque<int>>("rng::reverse(deque<int>)", std::ranges::reverse);
+    bm.operator()<std::list<int>>("rng::reverse(list<int>)", std::ranges::reverse);
+  }
 
   benchmark::Initialize(&argc, argv);
   benchmark::RunSpecifiedBenchmarks();
diff --git a/libcxx/test/benchmarks/algorithms/modifying/reverse_copy.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/reverse_copy.bench.cpp
index 84322fbfff40c..c77cb9a560494 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/reverse_copy.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/reverse_copy.bench.cpp
@@ -19,40 +19,34 @@
 #include "benchmark/benchmark.h"
 #include "../../GenerateInput.h"
 
-template <class Container, class Operation>
-void bm(std::string operation_name, Operation reverse_copy) {
-  auto bench = [reverse_copy](auto& st) {
-    std::size_t const size = st.range(0);
-    using ValueType        = typename Container::value_type;
-    Container c;
-    std::generate_n(std::back_inserter(c), size, [] { return Generate<ValueType>::random(); });
-
-    std::vector<ValueType> out(size);
-
-    for ([[maybe_unused]] auto _ : st) {
-      reverse_copy(c.begin(), c.end(), out.begin());
-      benchmark::DoNotOptimize(c);
-      benchmark::ClobberMemory();
-    }
-  };
-  benchmark::RegisterBenchmark(operation_name, bench)->Range(8, 1 << 15);
-}
-
 int main(int argc, char** argv) {
-  auto std_reverse_copy    = [](auto first, auto last, auto out) { return std::reverse_copy(first, last, out); };
-  auto ranges_reverse_copy = [](auto first, auto last, auto out) {
-    return std::ranges::reverse_copy(first, last, out);
-  };
-
-  // std::reverse_copy
-  bm<std::vector<int>>("std::reverse_copy(vector<int>)", std_reverse_copy);
-  bm<std::deque<int>>("std::reverse_copy(deque<int>)", std_reverse_copy);
-  bm<std::list<int>>("std::reverse_copy(list<int>)", std_reverse_copy);
-
-  // ranges::reverse_copy
-  bm<std::vector<int>>("ranges::reverse_copy(vector<int>)", ranges_reverse_copy);
-  bm<std::deque<int>>("ranges::reverse_copy(deque<int>)", ranges_reverse_copy);
-  bm<std::list<int>>("ranges::reverse_copy(list<int>)", ranges_reverse_copy);
+  auto std_reverse_copy = [](auto first, auto last, auto out) { return std::reverse_copy(first, last, out); };
+
+  // {std,ranges}::reverse_copy(normal container)
+  {
+    auto bm = []<class Container>(std::string name, auto reverse_copy) {
+      benchmark::RegisterBenchmark(name, [reverse_copy](auto& st) {
+        std::size_t const size = st.range(0);
+        using ValueType        = typename Container::value_type;
+        Container c;
+        std::generate_n(std::back_inserter(c), size, [] { return Generate<ValueType>::random(); });
+
+        std::vector<ValueType> out(size);
+
+        for ([[maybe_unused]] auto _ : st) {
+          reverse_copy(c.begin(), c.end(), out.begin());
+          benchmark::DoNotOptimize(c);
+          benchmark::ClobberMemory();
+        }
+      })->Range(8, 1 << 15);
+    };
+    bm.operator()<std::vector<int>>("std::reverse_copy(vector<int>)", std_reverse_copy);
+    bm.operator()<std::deque<int>>("std::reverse_copy(deque<int>)", std_reverse_copy);
+    bm.operator()<std::list<int>>("std::reverse_copy(list<int>)", std_reverse_copy);
+    bm.operator()<std::vector<int>>("rng::reverse_copy(vector<int>)", std::ranges::reverse_copy);
+    bm.operator()<std::deque<int>>("rng::reverse_copy(deque<int>)", std::ranges::reverse_copy);
+    bm.operator()<std::list<int>>("rng::reverse_copy(list<int>)", std::ranges::reverse_copy);
+  }
 
   benchmark::Initialize(&argc, argv);
   benchmark::RunSpecifiedBenchmarks();
diff --git a/libcxx/test/benchmarks/algorithms/modifying/rotate.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/rotate.bench.cpp
index eb91a011d863a..e32afbc87c9a0 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/rotate.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/rotate.bench.cpp
@@ -19,38 +19,39 @@
 #include "benchmark/benchmark.h"
 #include "../../GenerateInput.h"
 
-template <class Container, class Operation>
-void bm(std::string operation_name, Operation rotate) {
-  auto bench = [rotate](auto& st) {
-    std::size_t const size = st.range(0);
-    using ValueType        = typename Container::value_type;
-    Container c;
-    std::generate_n(std::back_inserter(c), size, [] { return Generate<ValueType>::random(); });
-
-    auto middle = std::next(c.begin(), size / 2);
-    for ([[maybe_unused]] auto _ : st) {
-      auto result = rotate(c.begin(), middle, c.end());
-      benchmark::DoNotOptimize(result);
-      benchmark::DoNotOptimize(c);
-      benchmark::ClobberMemory();
-    }
-  };
-  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
-
 int main(int argc, char** argv) {
-  auto std_rotate    = [](auto first, auto middle, auto last) { return std::rotate(first, middle, last); };
-  auto ranges_rotate = [](auto first, auto middle, auto last) { return std::ranges::rotate(first, middle, last); };
-
-  // std::rotate
-  bm<std::vector<int>>("std::rotate(vector<int>)", std_rotate);
-  bm<std::deque<int>>("std::rotate(deque<int>)", std_rotate);
-  bm<std::list<int>>("std::rotate(list<int>)", std_rotate);
-
-  // ranges::rotate
-  bm<std::vector<int>>("ranges::rotate(vector<int>)", ranges_rotate);
-  bm<std::deque<int>>("ranges::rotate(deque<int>)", ranges_rotate);
-  bm<std::list<int>>("ranges::rotate(list<int>)", ranges_rotate);
+  auto std_rotate = [](auto first, auto middle, auto last) { return std::rotate(first, middle, last); };
+
+  // {std,ranges}::rotate(normal container)
+  {
+    auto bm = []<class Container>(std::string name, auto rotate) {
+      benchmark::RegisterBenchmark(
+          name,
+          [rotate](auto& st) {
+            std::size_t const size = st.range(0);
+            using ValueType        = typename Container::value_type;
+            Container c;
+            std::generate_n(std::back_inserter(c), size, [] { return Generate<ValueType>::random(); });
+
+            auto middle = std::next(c.begin(), size / 2);
+            for ([[maybe_unused]] auto _ : st) {
+              auto result = rotate(c.begin(), middle, c.end());
+              benchmark::DoNotOptimize(result);
+              benchmark::DoNotOptimize(c);
+              benchmark::ClobberMemory();
+            }
+          })
+          ->Arg(32)
+          ->Arg(1024)
+          ->Arg(8192);
+    };
+    bm.operator()<std::vector<int>>("std::rotate(vector<int>)", std_rotate);
+    bm.operator()<std::deque<int>>("std::rotate(deque<int>)", std_rotate);
+    bm.operator()<std::list<int>>("std::rotate(list<int>)", std_rotate);
+    bm.operator()<std::vector<int>>("rng::rotate(vector<int>)", std::ranges::rotate);
+    bm.operator()<std::deque<int>>("rng::rotate(deque<int>)", std::ranges::rotate);
+    bm.operator()<std::list<int>>("rng::rotate(list<int>)", std::ranges::rotate);
+  }
 
   benchmark::Initialize(&argc, argv);
   benchmark::RunSpecifiedBenchmarks();
diff --git a/libcxx/test/benchmarks/algorithms/modifying/rotate_copy.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/rotate_copy.bench.cpp
index f5c14640fa87d..7972f1aba096e 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/rotate_copy.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/rotate_copy.bench.cpp
@@ -19,44 +19,43 @@
 #include "benchmark/benchmark.h"
 #include "../../GenerateInput.h"
 
-template <class Container, class Operation>
-void bm(std::string operation_name, Operation rotate_copy) {
-  auto bench = [rotate_copy](auto& st) {
-    std::size_t const size = st.range(0);
-    using ValueType        = typename Container::value_type;
-    Container c;
-    std::generate_n(std::back_inserter(c), size, [] { return Generate<ValueType>::random(); });
-
-    std::vector<ValueType> out(size);
-
-    auto middle = std::next(c.begin(), size / 2);
-    for ([[maybe_unused]] auto _ : st) {
-      auto result = rotate_copy(c.begin(), middle, c.end(), out.begin());
-      benchmark::DoNotOptimize(result);
-      benchmark::DoNotOptimize(c);
-      benchmark::ClobberMemory();
-    }
-  };
-  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
-
 int main(int argc, char** argv) {
   auto std_rotate_copy = [](auto first, auto middle, auto last, auto out) {
     return std::rotate_copy(first, middle, last, out);
   };
-  auto ranges_rotate_copy = [](auto first, auto middle, auto last, auto out) {
-    return std::ranges::rotate_copy(first, middle, last, out);
-  };
 
-  // std::rotate_copy
-  bm<std::vector<int>>("std::rotate_copy(vector<int>)", std_rotate_copy);
-  bm<std::deque<int>>("std::rotate_copy(deque<int>)", std_rotate_copy);
-  bm<std::list<int>>("std::rotate_copy(list<int>)", std_rotate_copy);
+  // {std,ranges}::rotate_copy(normal container)
+  {
+    auto bm = []<class Container>(std::string name, auto rotate_copy) {
+      benchmark::RegisterBenchmark(
+          name,
+          [rotate_copy](auto& st) {
+            std::size_t const size = st.range(0);
+            using ValueType        = typename Container::value_type;
+            Container c;
+            std::generate_n(std::back_inserter(c), size, [] { return Generate<ValueType>::random(); });
+
+            std::vector<ValueType> out(size);
 
-  // ranges::rotate_copy
-  bm<std::vector<int>>("ranges::rotate_copy(vector<int>)", ranges_rotate_copy);
-  bm<std::deque<int>>("ranges::rotate_copy(deque<int>)", ranges_rotate_copy);
-  bm<std::list<int>>("ranges::rotate_copy(list<int>)", ranges_rotate_copy);
+            auto middle = std::next(c.begin(), size / 2);
+            for ([[maybe_unused]] auto _ : st) {
+              auto result = rotate_copy(c.begin(), middle, c.end(), out.begin());
+              benchmark::DoNotOptimize(result);
+              benchmark::DoNotOptimize(c);
+              benchmark::ClobberMemory();
+            }
+          })
+          ->Arg(32)
+          ->Arg(1024)
+          ->Arg(8192);
+    };
+    bm.operator()<std::vector<int>>("std::rotate_copy(vector<int>)", std_rotate_copy);
+    bm.operator()<std::deque<int>>("std::rotate_copy(deque<int>)", std_rotate_copy);
+    bm.operator()<std::list<int>>("std::rotate_copy(list<int>)", std_rotate_copy);
+    bm.operator()<std::vector<int>>("rng::rotate_copy(vector<int>)", std::ranges::rotate_copy);
+    bm.operator()<std::deque<int>>("rng::rotate_copy(deque<int>)", std::ranges::rotate_copy);
+    bm.operator()<std::list<int>>("rng::rotate_copy(list<int>)", std::ranges::rotate_copy);
+  }
 
   benchmark::Initialize(&argc, argv);
   benchmark::RunSpecifiedBenchmarks();
diff --git a/libcxx/test/benchmarks/algorithms/modifying/sample.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/sample.bench.cpp
index 5f783efe8f627..87ab7517cb723 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/sample.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/sample.bench.cpp
@@ -20,46 +20,45 @@
 #include "benchmark/benchmark.h"
 #include "../../GenerateInput.h"
 
-template <class Container, class Operation>
-void bm(std::string operation_name, Operation sample) {
-  auto bench = [sample](auto& st) {
-    std::size_t const size = st.range(0);
-    using ValueType        = typename Container::value_type;
-    Container c;
-    std::generate_n(std::back_inserter(c), size, [] { return Generate<ValueType>::random(); });
-
-    std::vector<ValueType> out(size);
-    auto const n = size / 4; // sample 1/4 of the range
-    std::mt19937 rng;
-
-    for ([[maybe_unused]] auto _ : st) {
-      auto result = sample(c.begin(), c.end(), out.begin(), n, rng);
-      benchmark::DoNotOptimize(result);
-      benchmark::DoNotOptimize(c);
-      benchmark::DoNotOptimize(out);
-      benchmark::ClobberMemory();
-    }
-  };
-  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
-
 int main(int argc, char** argv) {
   auto std_sample = [](auto first, auto last, auto out, auto n, auto& rng) {
     return std::sample(first, last, out, n, rng);
   };
-  auto ranges_sample = [](auto first, auto last, auto out, auto n, auto& rng) {
-    return std::ranges::sample(first, last, out, n, rng);
-  };
 
-  // std::sample
-  bm<std::vector<int>>("std::sample(vector<int>)", std_sample);
-  bm<std::deque<int>>("std::sample(deque<int>)", std_sample);
-  bm<std::list<int>>("std::sample(list<int>)", std_sample);
+  // {std,ranges}::sample(normal container)
+  {
+    auto bm = []<class Container>(std::string name, auto sample) {
+      benchmark::RegisterBenchmark(
+          name,
+          [sample](auto& st) {
+            std::size_t const size = st.range(0);
+            using ValueType        = typename Container::value_type;
+            Container c;
+            std::generate_n(std::back_inserter(c), size, [] { return Generate<ValueType>::random(); });
+
+            std::vector<ValueType> out(size);
+            auto const n = size / 4; // sample 1/4 of the range
+            std::mt19937 rng;
 
-  // ranges::sample
-  bm<std::vector<int>>("ranges::sample(vector<int>)", ranges_sample);
-  bm<std::deque<int>>("ranges::sample(deque<int>)", ranges_sample);
-  bm<std::list<int>>("ranges::sample(list<int>)", ranges_sample);
+            for ([[maybe_unused]] auto _ : st) {
+              auto result = sample(c.begin(), c.end(), out.begin(), n, rng);
+              benchmark::DoNotOptimize(result);
+              benchmark::DoNotOptimize(c);
+              benchmark::DoNotOptimize(out);
+              benchmark::ClobberMemory();
+            }
+          })
+          ->Arg(32)
+          ->Arg(1024)
+          ->Arg(8192);
+    };
+    bm.operator()<std::vector<int>>("std::sample(vector<int>)", std_sample);
+    bm.operator()<std::deque<int>>("std::sample(deque<int>)", std_sample);
+    bm.operator()<std::list<int>>("std::sample(list<int>)", std_sample);
+    bm.operator()<std::vector<int>>("rng::sample(vector<int>)", std::ranges::sample);
+    bm.operator()<std::deque<int>>("rng::sample(deque<int>)", std::ranges::sample);
+    bm.operator()<std::list<int>>("rng::sample(list<int>)", std::ranges::sample);
+  }
 
   benchmark::Initialize(&argc, argv);
   benchmark::RunSpecifiedBenchmarks();
diff --git a/libcxx/test/benchmarks/algorithms/modifying/shift_left.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/shift_left.bench.cpp
index 9cf428f67e03e..24a3d34c65f09 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/shift_left.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/shift_left.bench.cpp
@@ -19,35 +19,38 @@
 #include "benchmark/benchmark.h"
 #include "../../GenerateInput.h"
 
-template <class Container, class Operation>
-void bm(std::string operation_name, Operation shift_left) {
-  auto bench = [shift_left](auto& st) {
-    std::size_t const size = st.range(0);
-    using ValueType        = typename Container::value_type;
-    Container c;
-    std::generate_n(std::back_inserter(c), size, [] { return Generate<ValueType>::random(); });
-
-    auto const n = 9 * (size / 10); // shift all but 10% of the range
-
-    for ([[maybe_unused]] auto _ : st) {
-      auto result = shift_left(c.begin(), c.end(), n);
-      benchmark::DoNotOptimize(result);
-      benchmark::DoNotOptimize(c);
-      benchmark::ClobberMemory();
-    }
-  };
-  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
-
 int main(int argc, char** argv) {
   auto std_shift_left = [](auto first, auto last, auto n) { return std::shift_left(first, last, n); };
 
-  // std::shift_left
-  bm<std::vector<int>>("std::shift_left(vector<int>)", std_shift_left);
-  bm<std::deque<int>>("std::shift_left(deque<int>)", std_shift_left);
-  bm<std::list<int>>("std::shift_left(list<int>)", std_shift_left);
-
-  // ranges::shift_left not implemented yet
+  // std::shift_left(normal container)
+  {
+    auto bm = []<class Container>(std::string name, auto shift_left) {
+      benchmark::RegisterBenchmark(
+          name,
+          [shift_left](auto& st) {
+            std::size_t const size = st.range(0);
+            using ValueType        = typename Container::value_type;
+            Container c;
+            std::generate_n(std::back_inserter(c), size, [] { return Generate<ValueType>::random(); });
+
+            auto const n = 9 * (size / 10); // shift all but 10% of the range
+
+            for ([[maybe_unused]] auto _ : st) {
+              auto result = shift_left(c.begin(), c.end(), n);
+              benchmark::DoNotOptimize(result);
+              benchmark::DoNotOptimize(c);
+              benchmark::ClobberMemory();
+            }
+          })
+          ->Arg(32)
+          ->Arg(1024)
+          ->Arg(8192);
+    };
+    bm.operator()<std::vector<int>>("std::shift_left(vector<int>)", std_shift_left);
+    bm.operator()<std::deque<int>>("std::shift_left(deque<int>)", std_shift_left);
+    bm.operator()<std::list<int>>("std::shift_left(list<int>)", std_shift_left);
+    // ranges::shift_left not implemented yet
+  }
 
   benchmark::Initialize(&argc, argv);
   benchmark::RunSpecifiedBenchmarks();
diff --git a/libcxx/test/benchmarks/algorithms/modifying/shift_right.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/shift_right.bench.cpp
index 31a980ebdc5c1..90fb507643149 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/shift_right.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/shift_right.bench.cpp
@@ -19,35 +19,38 @@
 #include "benchmark/benchmark.h"
 #include "../../GenerateInput.h"
 
-template <class Container, class Operation>
-void bm(std::string operation_name, Operation shift_right) {
-  auto bench = [shift_right](auto& st) {
-    std::size_t const size = st.range(0);
-    using ValueType        = typename Container::value_type;
-    Container c;
-    std::generate_n(std::back_inserter(c), size, [] { return Generate<ValueType>::random(); });
-
-    auto const n = 9 * (size / 10); // shift all but 10% of the range
-
-    for ([[maybe_unused]] auto _ : st) {
-      auto result = shift_right(c.begin(), c.end(), n);
-      benchmark::DoNotOptimize(result);
-      benchmark::DoNotOptimize(c);
-      benchmark::ClobberMemory();
-    }
-  };
-  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
-
 int main(int argc, char** argv) {
   auto std_shift_right = [](auto first, auto last, auto n) { return std::shift_right(first, last, n); };
 
-  // std::shift_right
-  bm<std::vector<int>>("std::shift_right(vector<int>)", std_shift_right);
-  bm<std::deque<int>>("std::shift_right(deque<int>)", std_shift_right);
-  bm<std::list<int>>("std::shift_right(list<int>)", std_shift_right);
-
-  // ranges::shift_right not implemented yet
+  // std::shift_right(normal container)
+  {
+    auto bm = []<class Container>(std::string name, auto shift_right) {
+      benchmark::RegisterBenchmark(
+          name,
+          [shift_right](auto& st) {
+            std::size_t const size = st.range(0);
+            using ValueType        = typename Container::value_type;
+            Container c;
+            std::generate_n(std::back_inserter(c), size, [] { return Generate<ValueType>::random(); });
+
+            auto const n = 9 * (size / 10); // shift all but 10% of the range
+
+            for ([[maybe_unused]] auto _ : st) {
+              auto result = shift_right(c.begin(), c.end(), n);
+              benchmark::DoNotOptimize(result);
+              benchmark::DoNotOptimize(c);
+              benchmark::ClobberMemory();
+            }
+          })
+          ->Arg(32)
+          ->Arg(1024)
+          ->Arg(8192);
+    };
+    bm.operator()<std::vector<int>>("std::shift_right(vector<int>)", std_shift_right);
+    bm.operator()<std::deque<int>>("std::shift_right(deque<int>)", std_shift_right);
+    bm.operator()<std::list<int>>("std::shift_right(list<int>)", std_shift_right);
+    // ranges::shift_right not implemented yet
+  }
 
   benchmark::Initialize(&argc, argv);
   benchmark::RunSpecifiedBenchmarks();
diff --git a/libcxx/test/benchmarks/algorithms/modifying/shuffle.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/shuffle.bench.cpp
index cc483b631c2a4..f50dff7635703 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/shuffle.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/shuffle.bench.cpp
@@ -19,35 +19,36 @@
 #include "benchmark/benchmark.h"
 #include "../../GenerateInput.h"
 
-template <class Container, class Operation>
-void bm(std::string operation_name, Operation shuffle) {
-  auto bench = [shuffle](auto& st) {
-    std::size_t const size = st.range(0);
-    using ValueType        = typename Container::value_type;
-    Container c;
-    std::generate_n(std::back_inserter(c), size, [] { return Generate<ValueType>::random(); });
-    std::mt19937 rng;
-
-    for ([[maybe_unused]] auto _ : st) {
-      shuffle(c.begin(), c.end(), rng);
-      benchmark::DoNotOptimize(c);
-      benchmark::ClobberMemory();
-    }
-  };
-  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
-
 int main(int argc, char** argv) {
-  auto std_shuffle    = [](auto first, auto last, auto& rng) { return std::shuffle(first, last, rng); };
-  auto ranges_shuffle = [](auto first, auto last, auto& rng) { return std::ranges::shuffle(first, last, rng); };
-
-  // std::shuffle
-  bm<std::vector<int>>("std::shuffle(vector<int>)", std_shuffle);
-  bm<std::deque<int>>("std::shuffle(deque<int>)", std_shuffle);
-
-  // ranges::shuffle
-  bm<std::vector<int>>("ranges::shuffle(vector<int>)", ranges_shuffle);
-  bm<std::deque<int>>("ranges::shuffle(deque<int>)", ranges_shuffle);
+  auto std_shuffle = [](auto first, auto last, auto& rng) { return std::shuffle(first, last, rng); };
+
+  // {std,ranges}::shuffle(normal container)
+  {
+    auto bm = []<class Container>(std::string name, auto shuffle) {
+      benchmark::RegisterBenchmark(
+          name,
+          [shuffle](auto& st) {
+            std::size_t const size = st.range(0);
+            using ValueType        = typename Container::value_type;
+            Container c;
+            std::generate_n(std::back_inserter(c), size, [] { return Generate<ValueType>::random(); });
+            std::mt19937 rng;
+
+            for ([[maybe_unused]] auto _ : st) {
+              shuffle(c.begin(), c.end(), rng);
+              benchmark::DoNotOptimize(c);
+              benchmark::ClobberMemory();
+            }
+          })
+          ->Arg(32)
+          ->Arg(1024)
+          ->Arg(8192);
+    };
+    bm.operator()<std::vector<int>>("std::shuffle(vector<int>)", std_shuffle);
+    bm.operator()<std::deque<int>>("std::shuffle(deque<int>)", std_shuffle);
+    bm.operator()<std::vector<int>>("rng::shuffle(vector<int>)", std::ranges::shuffle);
+    bm.operator()<std::deque<int>>("rng::shuffle(deque<int>)", std::ranges::shuffle);
+  }
 
   benchmark::Initialize(&argc, argv);
   benchmark::RunSpecifiedBenchmarks();
diff --git a/libcxx/test/benchmarks/algorithms/modifying/swap_ranges.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/swap_ranges.bench.cpp
index 05b733fecc70d..f7c2ff1252b09 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/swap_ranges.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/swap_ranges.bench.cpp
@@ -19,43 +19,42 @@
 #include "benchmark/benchmark.h"
 #include "../../GenerateInput.h"
 
-template <class Container, class Operation>
-void bm(std::string operation_name, Operation swap_ranges) {
-  auto bench = [swap_ranges](auto& st) {
-    std::size_t const size = st.range(0);
-    using ValueType        = typename Container::value_type;
-    Container c1, c2;
-    std::generate_n(std::back_inserter(c1), size, [] { return Generate<ValueType>::random(); });
-    std::generate_n(std::back_inserter(c2), size, [] { return Generate<ValueType>::random(); });
-
-    for ([[maybe_unused]] auto _ : st) {
-      auto result = swap_ranges(c1.begin(), c1.end(), c2.begin(), c2.end());
-      benchmark::DoNotOptimize(result);
-      benchmark::DoNotOptimize(c1);
-      benchmark::DoNotOptimize(c2);
-      benchmark::ClobberMemory();
-    }
-  };
-  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
-
 int main(int argc, char** argv) {
   auto std_swap_ranges = [](auto first1, auto last1, auto first2, auto) {
     return std::swap_ranges(first1, last1, first2);
   };
-  auto ranges_swap_ranges = [](auto first1, auto last1, auto first2, auto last2) {
-    return std::ranges::swap_ranges(first1, last1, first2, last2);
-  };
-
-  // std::swap_ranges
-  bm<std::vector<int>>("std::swap_ranges(vector<int>)", std_swap_ranges);
-  bm<std::deque<int>>("std::swap_ranges(deque<int>)", std_swap_ranges);
-  bm<std::list<int>>("std::swap_ranges(list<int>)", std_swap_ranges);
 
-  // ranges::swap_ranges
-  bm<std::vector<int>>("ranges::swap_ranges(vector<int>)", ranges_swap_ranges);
-  bm<std::deque<int>>("ranges::swap_ranges(deque<int>)", ranges_swap_ranges);
-  bm<std::list<int>>("ranges::swap_ranges(list<int>)", ranges_swap_ranges);
+  // {std,ranges}::swap_ranges(normal container)
+  {
+    auto bm = []<class Container>(std::string name, auto swap_ranges) {
+      benchmark::RegisterBenchmark(
+          name,
+          [swap_ranges](auto& st) {
+            std::size_t const size = st.range(0);
+            using ValueType        = typename Container::value_type;
+            Container c1, c2;
+            std::generate_n(std::back_inserter(c1), size, [] { return Generate<ValueType>::random(); });
+            std::generate_n(std::back_inserter(c2), size, [] { return Generate<ValueType>::random(); });
+
+            for ([[maybe_unused]] auto _ : st) {
+              auto result = swap_ranges(c1.begin(), c1.end(), c2.begin(), c2.end());
+              benchmark::DoNotOptimize(result);
+              benchmark::DoNotOptimize(c1);
+              benchmark::DoNotOptimize(c2);
+              benchmark::ClobberMemory();
+            }
+          })
+          ->Arg(32)
+          ->Arg(1024)
+          ->Arg(8192);
+    };
+    bm.operator()<std::vector<int>>("std::swap_ranges(vector<int>)", std_swap_ranges);
+    bm.operator()<std::deque<int>>("std::swap_ranges(deque<int>)", std_swap_ranges);
+    bm.operator()<std::list<int>>("std::swap_ranges(list<int>)", std_swap_ranges);
+    bm.operator()<std::vector<int>>("rng::swap_ranges(vector<int>)", std::ranges::swap_ranges);
+    bm.operator()<std::deque<int>>("rng::swap_ranges(deque<int>)", std::ranges::swap_ranges);
+    bm.operator()<std::list<int>>("rng::swap_ranges(list<int>)", std::ranges::swap_ranges);
+  }
 
   benchmark::Initialize(&argc, argv);
   benchmark::RunSpecifiedBenchmarks();
diff --git a/libcxx/test/benchmarks/algorithms/modifying/transform.binary.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/transform.binary.bench.cpp
index bdc913356d3c9..b3e1195bcecb8 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/transform.binary.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/transform.binary.bench.cpp
@@ -19,52 +19,51 @@
 #include "benchmark/benchmark.h"
 #include "../../GenerateInput.h"
 
-template <class Container, class Operation>
-void bm(std::string operation_name, Operation transform) {
-  auto bench = [transform](auto& st) {
-    std::size_t const size = st.range(0);
-    using ValueType        = typename Container::value_type;
-    Container c1, c2;
-    std::generate_n(std::back_inserter(c1), size, [] { return Generate<ValueType>::random(); });
-    std::generate_n(std::back_inserter(c2), size, [] { return Generate<ValueType>::random(); });
-
-    std::vector<ValueType> out(size);
-
-    auto f = [](auto& x, auto& y) {
-      benchmark::DoNotOptimize(x);
-      benchmark::DoNotOptimize(y);
-      return x + y;
-    };
-
-    for ([[maybe_unused]] auto _ : st) {
-      auto result = transform(c1.begin(), c1.end(), c2.begin(), c2.end(), out.begin(), f);
-      benchmark::DoNotOptimize(result);
-      benchmark::DoNotOptimize(out);
-      benchmark::DoNotOptimize(c1);
-      benchmark::DoNotOptimize(c2);
-      benchmark::ClobberMemory();
-    }
-  };
-  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
-
 int main(int argc, char** argv) {
   auto std_transform = [](auto first1, auto last1, auto first2, auto, auto out, auto f) {
     return std::transform(first1, last1, first2, out, f);
   };
-  auto ranges_transform = [](auto first1, auto last1, auto first2, auto last2, auto out, auto f) {
-    return std::ranges::transform(first1, last1, first2, last2, out, f);
-  };
 
-  // std::transform
-  bm<std::vector<int>>("std::transform(vector<int>, vector<int>)", std_transform);
-  bm<std::deque<int>>("std::transform(deque<int>, deque<int>)", std_transform);
-  bm<std::list<int>>("std::transform(list<int>, list<int>)", std_transform);
+  // {std,ranges}::transform(normal container, normal container)
+  {
+    auto bm = []<class Container>(std::string name, auto transform) {
+      benchmark::RegisterBenchmark(
+          name,
+          [transform](auto& st) {
+            std::size_t const size = st.range(0);
+            using ValueType        = typename Container::value_type;
+            Container c1, c2;
+            std::generate_n(std::back_inserter(c1), size, [] { return Generate<ValueType>::random(); });
+            std::generate_n(std::back_inserter(c2), size, [] { return Generate<ValueType>::random(); });
+
+            std::vector<ValueType> out(size);
 
-  // ranges::transform
-  bm<std::vector<int>>("ranges::transform(vector<int>, vector<int>)", ranges_transform);
-  bm<std::deque<int>>("ranges::transform(deque<int>, deque<int>)", ranges_transform);
-  bm<std::list<int>>("ranges::transform(list<int>, list<int>)", ranges_transform);
+            auto f = [](auto& x, auto& y) {
+              benchmark::DoNotOptimize(x);
+              benchmark::DoNotOptimize(y);
+              return x + y;
+            };
+
+            for ([[maybe_unused]] auto _ : st) {
+              auto result = transform(c1.begin(), c1.end(), c2.begin(), c2.end(), out.begin(), f);
+              benchmark::DoNotOptimize(result);
+              benchmark::DoNotOptimize(out);
+              benchmark::DoNotOptimize(c1);
+              benchmark::DoNotOptimize(c2);
+              benchmark::ClobberMemory();
+            }
+          })
+          ->Arg(32)
+          ->Arg(1024)
+          ->Arg(8192);
+    };
+    bm.operator()<std::vector<int>>("std::transform(vector<int>, vector<int>)", std_transform);
+    bm.operator()<std::deque<int>>("std::transform(deque<int>, deque<int>)", std_transform);
+    bm.operator()<std::list<int>>("std::transform(list<int>, list<int>)", std_transform);
+    bm.operator()<std::vector<int>>("rng::transform(vector<int>, vector<int>)", std::ranges::transform);
+    bm.operator()<std::deque<int>>("rng::transform(deque<int>, deque<int>)", std::ranges::transform);
+    bm.operator()<std::list<int>>("rng::transform(list<int>, list<int>)", std::ranges::transform);
+  }
 
   benchmark::Initialize(&argc, argv);
   benchmark::RunSpecifiedBenchmarks();
diff --git a/libcxx/test/benchmarks/algorithms/modifying/transform.unary.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/transform.unary.bench.cpp
index 6cf56368f63f3..837be87ada70b 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/transform.unary.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/transform.unary.bench.cpp
@@ -19,47 +19,46 @@
 #include "benchmark/benchmark.h"
 #include "../../GenerateInput.h"
 
-template <class Container, class Operation>
-void bm(std::string operation_name, Operation transform) {
-  auto bench = [transform](auto& st) {
-    std::size_t const size = st.range(0);
-    using ValueType        = typename Container::value_type;
-    Container c;
-    std::generate_n(std::back_inserter(c), size, [] { return Generate<ValueType>::random(); });
+int main(int argc, char** argv) {
+  auto std_transform = [](auto first, auto last, auto out, auto f) { return std::transform(first, last, out, f); };
 
-    std::vector<ValueType> out(size);
+  // {std,ranges}::transform(normal container)
+  {
+    auto bm = []<class Container>(std::string name, auto transform) {
+      benchmark::RegisterBenchmark(
+          name,
+          [transform](auto& st) {
+            std::size_t const size = st.range(0);
+            using ValueType        = typename Container::value_type;
+            Container c;
+            std::generate_n(std::back_inserter(c), size, [] { return Generate<ValueType>::random(); });
 
-    auto f = [](auto& element) {
-      benchmark::DoNotOptimize(element);
-      return element;
-    };
+            std::vector<ValueType> out(size);
 
-    for ([[maybe_unused]] auto _ : st) {
-      auto result = transform(c.begin(), c.end(), out.begin(), f);
-      benchmark::DoNotOptimize(result);
-      benchmark::DoNotOptimize(out);
-      benchmark::DoNotOptimize(c);
-      benchmark::ClobberMemory();
-    }
-  };
-  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
+            auto f = [](auto& element) {
+              benchmark::DoNotOptimize(element);
+              return element;
+            };
 
-int main(int argc, char** argv) {
-  auto std_transform    = [](auto first, auto last, auto out, auto f) { return std::transform(first, last, out, f); };
-  auto ranges_transform = [](auto first, auto last, auto out, auto f) {
-    return std::ranges::transform(first, last, out, f);
-  };
-
-  // std::transform
-  bm<std::vector<int>>("std::transform(vector<int>) (identity transform)", std_transform);
-  bm<std::deque<int>>("std::transform(deque<int>) (identity transform)", std_transform);
-  bm<std::list<int>>("std::transform(list<int>) (identity transform)", std_transform);
-
-  // ranges::transform
-  bm<std::vector<int>>("ranges::transform(vector<int>) (identity transform)", ranges_transform);
-  bm<std::deque<int>>("ranges::transform(deque<int>) (identity transform)", ranges_transform);
-  bm<std::list<int>>("ranges::transform(list<int>) (identity transform)", ranges_transform);
+            for ([[maybe_unused]] auto _ : st) {
+              auto result = transform(c.begin(), c.end(), out.begin(), f);
+              benchmark::DoNotOptimize(result);
+              benchmark::DoNotOptimize(out);
+              benchmark::DoNotOptimize(c);
+              benchmark::ClobberMemory();
+            }
+          })
+          ->Arg(32)
+          ->Arg(1024)
+          ->Arg(8192);
+    };
+    bm.operator()<std::vector<int>>("std::transform(vector<int>) (identity transform)", std_transform);
+    bm.operator()<std::deque<int>>("std::transform(deque<int>) (identity transform)", std_transform);
+    bm.operator()<std::list<int>>("std::transform(list<int>) (identity transform)", std_transform);
+    bm.operator()<std::vector<int>>("rng::transform(vector<int>) (identity transform)", std::ranges::transform);
+    bm.operator()<std::deque<int>>("rng::transform(deque<int>) (identity transform)", std::ranges::transform);
+    bm.operator()<std::list<int>>("rng::transform(list<int>) (identity transform)", std::ranges::transform);
+  }
 
   benchmark::Initialize(&argc, argv);
   benchmark::RunSpecifiedBenchmarks();
diff --git a/libcxx/test/benchmarks/algorithms/modifying/unique.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/unique.bench.cpp
index 1d9cca2f60688..8cc80982de70b 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/unique.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/unique.bench.cpp
@@ -19,111 +19,112 @@
 #include "benchmark/benchmark.h"
 #include "../../GenerateInput.h"
 
-// Create a sequence of the form xxxxxxxxxxyyyyyyyyyy and unique the
-// adjacent equal elements.
-//
-// We perform this benchmark in a batch because we need to restore the
-// state of the container after the operation.
-template <class Container, class Operation>
-void bm_contiguous(std::string operation_name, Operation unique) {
-  auto bench = [unique](auto& st) {
-    std::size_t const size          = st.range(0);
-    constexpr std::size_t BatchSize = 10;
-    using ValueType                 = typename Container::value_type;
-    Container c[BatchSize];
-    ValueType x = Generate<ValueType>::random();
-    ValueType y = Generate<ValueType>::random();
-    for (std::size_t i = 0; i != BatchSize; ++i) {
-      c[i]      = Container(size);
-      auto half = size / 2;
-      std::fill_n(std::fill_n(c[i].begin(), half, x), half, y);
-    }
-
-    while (st.KeepRunningBatch(BatchSize)) {
-      for (std::size_t i = 0; i != BatchSize; ++i) {
-        auto result = unique(c[i].begin(), c[i].end());
-        benchmark::DoNotOptimize(result);
-        benchmark::DoNotOptimize(c[i]);
-        benchmark::ClobberMemory();
-      }
-
-      st.PauseTiming();
-      for (std::size_t i = 0; i != BatchSize; ++i) {
-        auto half = size / 2;
-        std::fill_n(std::fill_n(c[i].begin(), half, x), half, y);
-      }
-      st.ResumeTiming();
-    }
-  };
-  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
-
-// Create a sequence of the form xxyyxxyyxxyyxxyyxxyy and unique
-// adjacent equal elements.
-//
-// We perform this benchmark in a batch because we need to restore the
-// state of the container after the operation.
-template <class Container, class Operation>
-void bm_sprinkled(std::string operation_name, Operation unique) {
-  auto bench = [unique](auto& st) {
-    std::size_t const size          = st.range(0);
-    constexpr std::size_t BatchSize = 10;
-    using ValueType                 = typename Container::value_type;
-    Container c[BatchSize];
-    ValueType x    = Generate<ValueType>::random();
-    ValueType y    = Generate<ValueType>::random();
-    auto alternate = [&](auto out, auto n) {
-      for (std::size_t i = 0; i != n; i += 2) {
-        *out++ = (i % 4 == 0 ? x : y);
-        *out++ = (i % 4 == 0 ? x : y);
-      }
-    };
-    for (std::size_t i = 0; i != BatchSize; ++i) {
-      c[i] = Container(size);
-      alternate(c[i].begin(), size);
-    }
-
-    while (st.KeepRunningBatch(BatchSize)) {
-      for (std::size_t i = 0; i != BatchSize; ++i) {
-        auto result = unique(c[i].begin(), c[i].end());
-        benchmark::DoNotOptimize(result);
-        benchmark::DoNotOptimize(c[i]);
-        benchmark::ClobberMemory();
-      }
-
-      st.PauseTiming();
-      for (std::size_t i = 0; i != BatchSize; ++i) {
-        alternate(c[i].begin(), size);
-      }
-      st.ResumeTiming();
-    }
-  };
-  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
-
 int main(int argc, char** argv) {
-  auto std_unique    = [](auto first, auto last) { return std::unique(first, last); };
-  auto ranges_unique = [](auto first, auto last) { return std::ranges::unique(first, last); };
-
-  // std::unique
-  bm_contiguous<std::vector<int>>("std::unique(vector<int>) (contiguous)", std_unique);
-  bm_sprinkled<std::vector<int>>("std::unique(vector<int>) (sprinkled)", std_unique);
-
-  bm_contiguous<std::deque<int>>("std::unique(deque<int>) (contiguous)", std_unique);
-  bm_sprinkled<std::deque<int>>("std::unique(deque<int>) (sprinkled)", std_unique);
-
-  bm_contiguous<std::list<int>>("std::unique(list<int>) (contiguous)", std_unique);
-  bm_sprinkled<std::list<int>>("std::unique(list<int>) (sprinkled)", std_unique);
-
-  // ranges::unique
-  bm_contiguous<std::vector<int>>("ranges::unique(vector<int>) (contiguous)", ranges_unique);
-  bm_sprinkled<std::vector<int>>("ranges::unique(vector<int>) (sprinkled)", ranges_unique);
-
-  bm_contiguous<std::deque<int>>("ranges::unique(deque<int>) (contiguous)", ranges_unique);
-  bm_sprinkled<std::deque<int>>("ranges::unique(deque<int>) (sprinkled)", ranges_unique);
-
-  bm_contiguous<std::list<int>>("ranges::unique(list<int>) (contiguous)", ranges_unique);
-  bm_sprinkled<std::list<int>>("ranges::unique(list<int>) (sprinkled)", ranges_unique);
+  auto std_unique = [](auto first, auto last) { return std::unique(first, last); };
+
+  // Create a sequence of the form xxxxxxxxxxyyyyyyyyyy and unique the
+  // adjacent equal elements.
+  //
+  // We perform this benchmark in a batch because we need to restore the
+  // state of the container after the operation.
+  {
+    auto bm = []<class Container>(std::string name, auto unique) {
+      benchmark::RegisterBenchmark(
+          name,
+          [unique](auto& st) {
+            std::size_t const size          = st.range(0);
+            constexpr std::size_t BatchSize = 10;
+            using ValueType                 = typename Container::value_type;
+            Container c[BatchSize];
+            ValueType x = Generate<ValueType>::random();
+            ValueType y = Generate<ValueType>::random();
+            for (std::size_t i = 0; i != BatchSize; ++i) {
+              c[i]      = Container(size);
+              auto half = size / 2;
+              std::fill_n(std::fill_n(c[i].begin(), half, x), half, y);
+            }
+
+            while (st.KeepRunningBatch(BatchSize)) {
+              for (std::size_t i = 0; i != BatchSize; ++i) {
+                auto result = unique(c[i].begin(), c[i].end());
+                benchmark::DoNotOptimize(result);
+                benchmark::DoNotOptimize(c[i]);
+                benchmark::ClobberMemory();
+              }
+
+              st.PauseTiming();
+              for (std::size_t i = 0; i != BatchSize; ++i) {
+                auto half = size / 2;
+                std::fill_n(std::fill_n(c[i].begin(), half, x), half, y);
+              }
+              st.ResumeTiming();
+            }
+          })
+          ->Arg(32)
+          ->Arg(1024)
+          ->Arg(8192);
+    };
+    bm.operator()<std::vector<int>>("std::unique(vector<int>) (contiguous)", std_unique);
+    bm.operator()<std::deque<int>>("std::unique(deque<int>) (contiguous)", std_unique);
+    bm.operator()<std::list<int>>("std::unique(list<int>) (contiguous)", std_unique);
+    bm.operator()<std::vector<int>>("rng::unique(vector<int>) (contiguous)", std::ranges::unique);
+    bm.operator()<std::deque<int>>("rng::unique(deque<int>) (contiguous)", std::ranges::unique);
+    bm.operator()<std::list<int>>("rng::unique(list<int>) (contiguous)", std::ranges::unique);
+  }
+
+  // Create a sequence of the form xxyyxxyyxxyyxxyyxxyy and unique
+  // adjacent equal elements.
+  //
+  // We perform this benchmark in a batch because we need to restore the
+  // state of the container after the operation.
+  {
+    auto bm = []<class Container>(std::string name, auto unique) {
+      benchmark::RegisterBenchmark(
+          name,
+          [unique](auto& st) {
+            std::size_t const size          = st.range(0);
+            constexpr std::size_t BatchSize = 10;
+            using ValueType                 = typename Container::value_type;
+            Container c[BatchSize];
+            ValueType x    = Generate<ValueType>::random();
+            ValueType y    = Generate<ValueType>::random();
+            auto alternate = [&](auto out, auto n) {
+              for (std::size_t i = 0; i != n; i += 2) {
+                *out++ = (i % 4 == 0 ? x : y);
+                *out++ = (i % 4 == 0 ? x : y);
+              }
+            };
+            for (std::size_t i = 0; i != BatchSize; ++i) {
+              c[i] = Container(size);
+              alternate(c[i].begin(), size);
+            }
+
+            while (st.KeepRunningBatch(BatchSize)) {
+              for (std::size_t i = 0; i != BatchSize; ++i) {
+                auto result = unique(c[i].begin(), c[i].end());
+                benchmark::DoNotOptimize(result);
+                benchmark::DoNotOptimize(c[i]);
+                benchmark::ClobberMemory();
+              }
+
+              st.PauseTiming();
+              for (std::size_t i = 0; i != BatchSize; ++i) {
+                alternate(c[i].begin(), size);
+              }
+              st.ResumeTiming();
+            }
+          })
+          ->Arg(32)
+          ->Arg(1024)
+          ->Arg(8192);
+    };
+    bm.operator()<std::vector<int>>("std::unique(vector<int>) (sprinkled)", std_unique);
+    bm.operator()<std::deque<int>>("std::unique(deque<int>) (sprinkled)", std_unique);
+    bm.operator()<std::list<int>>("std::unique(list<int>) (sprinkled)", std_unique);
+    bm.operator()<std::vector<int>>("rng::unique(vector<int>) (sprinkled)", std::ranges::unique);
+    bm.operator()<std::deque<int>>("rng::unique(deque<int>) (sprinkled)", std::ranges::unique);
+    bm.operator()<std::list<int>>("rng::unique(list<int>) (sprinkled)", std::ranges::unique);
+  }
 
   benchmark::Initialize(&argc, argv);
   benchmark::RunSpecifiedBenchmarks();
diff --git a/libcxx/test/benchmarks/algorithms/modifying/unique_copy.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/unique_copy.bench.cpp
index c7b217ffd960d..3027953513958 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/unique_copy.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/unique_copy.bench.cpp
@@ -19,84 +19,85 @@
 #include "benchmark/benchmark.h"
 #include "../../GenerateInput.h"
 
-// Create a sequence of the form xxxxxxxxxxyyyyyyyyyy and unique the
-// adjacent equal elements.
-template <class Container, class Operation>
-void bm_contiguous(std::string operation_name, Operation unique_copy) {
-  auto bench = [unique_copy](auto& st) {
-    std::size_t const size = st.range(0);
-    using ValueType        = typename Container::value_type;
-    Container c(size);
-    ValueType x = Generate<ValueType>::random();
-    ValueType y = Generate<ValueType>::random();
-    auto half   = size / 2;
-    std::fill_n(std::fill_n(c.begin(), half, x), half, y);
-
-    std::vector<ValueType> out(size);
-
-    for ([[maybe_unused]] auto _ : st) {
-      auto result = unique_copy(c.begin(), c.end(), out.begin());
-      benchmark::DoNotOptimize(result);
-      benchmark::DoNotOptimize(c);
-      benchmark::ClobberMemory();
-    }
-  };
-  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
-
-// Create a sequence of the form xxyyxxyyxxyyxxyyxxyy and unique
-// adjacent equal elements.
-template <class Container, class Operation>
-void bm_sprinkled(std::string operation_name, Operation unique_copy) {
-  auto bench = [unique_copy](auto& st) {
-    std::size_t const size = st.range(0);
-    using ValueType        = typename Container::value_type;
-    Container c(size);
-    ValueType x    = Generate<ValueType>::random();
-    ValueType y    = Generate<ValueType>::random();
-    auto alternate = [&](auto out, auto n) {
-      for (std::size_t i = 0; i != n; i += 2) {
-        *out++ = (i % 4 == 0 ? x : y);
-        *out++ = (i % 4 == 0 ? x : y);
-      }
-    };
-    alternate(c.begin(), size);
-
-    std::vector<ValueType> out(size);
-
-    for ([[maybe_unused]] auto _ : st) {
-      auto result = unique_copy(c.begin(), c.end(), out.begin());
-      benchmark::DoNotOptimize(result);
-      benchmark::DoNotOptimize(c);
-      benchmark::ClobberMemory();
-    }
-  };
-  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
-
 int main(int argc, char** argv) {
-  auto std_unique_copy    = [](auto first, auto last, auto out) { return std::unique_copy(first, last, out); };
-  auto ranges_unique_copy = [](auto first, auto last, auto out) { return std::ranges::unique_copy(first, last, out); };
-
-  // std::unique_copy
-  bm_contiguous<std::vector<int>>("std::unique_copy(vector<int>) (contiguous)", std_unique_copy);
-  bm_sprinkled<std::vector<int>>("std::unique_copy(vector<int>) (sprinkled)", std_unique_copy);
-
-  bm_contiguous<std::deque<int>>("std::unique_copy(deque<int>) (contiguous)", std_unique_copy);
-  bm_sprinkled<std::deque<int>>("std::unique_copy(deque<int>) (sprinkled)", std_unique_copy);
-
-  bm_contiguous<std::list<int>>("std::unique_copy(list<int>) (contiguous)", std_unique_copy);
-  bm_sprinkled<std::list<int>>("std::unique_copy(list<int>) (sprinkled)", std_unique_copy);
-
-  // ranges::unique_copy
-  bm_contiguous<std::vector<int>>("ranges::unique_copy(vector<int>) (contiguous)", ranges_unique_copy);
-  bm_sprinkled<std::vector<int>>("ranges::unique_copy(vector<int>) (sprinkled)", ranges_unique_copy);
-
-  bm_contiguous<std::deque<int>>("ranges::unique_copy(deque<int>) (contiguous)", ranges_unique_copy);
-  bm_sprinkled<std::deque<int>>("ranges::unique_copy(deque<int>) (sprinkled)", ranges_unique_copy);
-
-  bm_contiguous<std::list<int>>("ranges::unique_copy(list<int>) (contiguous)", ranges_unique_copy);
-  bm_sprinkled<std::list<int>>("ranges::unique_copy(list<int>) (sprinkled)", ranges_unique_copy);
+  auto std_unique_copy = [](auto first, auto last, auto out) { return std::unique_copy(first, last, out); };
+
+  // Create a sequence of the form xxxxxxxxxxyyyyyyyyyy and unique the
+  // adjacent equal elements.
+  {
+    auto bm = []<class Container>(std::string name, auto unique_copy) {
+      benchmark::RegisterBenchmark(
+          name,
+          [unique_copy](auto& st) {
+            std::size_t const size = st.range(0);
+            using ValueType        = typename Container::value_type;
+            Container c(size);
+            ValueType x = Generate<ValueType>::random();
+            ValueType y = Generate<ValueType>::random();
+            auto half   = size / 2;
+            std::fill_n(std::fill_n(c.begin(), half, x), half, y);
+
+            std::vector<ValueType> out(size);
+
+            for ([[maybe_unused]] auto _ : st) {
+              auto result = unique_copy(c.begin(), c.end(), out.begin());
+              benchmark::DoNotOptimize(result);
+              benchmark::DoNotOptimize(c);
+              benchmark::ClobberMemory();
+            }
+          })
+          ->Arg(32)
+          ->Arg(1024)
+          ->Arg(8192);
+    };
+    bm.operator()<std::vector<int>>("std::unique_copy(vector<int>) (contiguous)", std_unique_copy);
+    bm.operator()<std::deque<int>>("std::unique_copy(deque<int>) (contiguous)", std_unique_copy);
+    bm.operator()<std::list<int>>("std::unique_copy(list<int>) (contiguous)", std_unique_copy);
+    bm.operator()<std::vector<int>>("rng::unique_copy(vector<int>) (contiguous)", std::ranges::unique_copy);
+    bm.operator()<std::deque<int>>("rng::unique_copy(deque<int>) (contiguous)", std::ranges::unique_copy);
+    bm.operator()<std::list<int>>("rng::unique_copy(list<int>) (contiguous)", std::ranges::unique_copy);
+  }
+
+  // Create a sequence of the form xxyyxxyyxxyyxxyyxxyy and unique
+  // adjacent equal elements.
+  {
+    auto bm = []<class Container>(std::string name, auto unique_copy) {
+      benchmark::RegisterBenchmark(
+          name,
+          [unique_copy](auto& st) {
+            std::size_t const size = st.range(0);
+            using ValueType        = typename Container::value_type;
+            Container c(size);
+            ValueType x    = Generate<ValueType>::random();
+            ValueType y    = Generate<ValueType>::random();
+            auto alternate = [&](auto out, auto n) {
+              for (std::size_t i = 0; i != n; i += 2) {
+                *out++ = (i % 4 == 0 ? x : y);
+                *out++ = (i % 4 == 0 ? x : y);
+              }
+            };
+            alternate(c.begin(), size);
+
+            std::vector<ValueType> out(size);
+
+            for ([[maybe_unused]] auto _ : st) {
+              auto result = unique_copy(c.begin(), c.end(), out.begin());
+              benchmark::DoNotOptimize(result);
+              benchmark::DoNotOptimize(c);
+              benchmark::ClobberMemory();
+            }
+          })
+          ->Arg(32)
+          ->Arg(1024)
+          ->Arg(8192);
+    };
+    bm.operator()<std::vector<int>>("std::unique_copy(vector<int>) (sprinkled)", std_unique_copy);
+    bm.operator()<std::deque<int>>("std::unique_copy(deque<int>) (sprinkled)", std_unique_copy);
+    bm.operator()<std::list<int>>("std::unique_copy(list<int>) (sprinkled)", std_unique_copy);
+    bm.operator()<std::vector<int>>("rng::unique_copy(vector<int>) (sprinkled)", std::ranges::unique_copy);
+    bm.operator()<std::deque<int>>("rng::unique_copy(deque<int>) (sprinkled)", std::ranges::unique_copy);
+    bm.operator()<std::list<int>>("rng::unique_copy(list<int>) (sprinkled)", std::ranges::unique_copy);
+  }
 
   benchmark::Initialize(&argc, argv);
   benchmark::RunSpecifiedBenchmarks();
diff --git a/libcxx/test/benchmarks/algorithms/modifying/unique_copy_pred.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/unique_copy_pred.bench.cpp
index 24ca442fb3de4..742feb873b25e 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/unique_copy_pred.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/unique_copy_pred.bench.cpp
@@ -19,100 +19,99 @@
 #include "benchmark/benchmark.h"
 #include "../../GenerateInput.h"
 
-// Create a sequence of the form xxxxxxxxxxyyyyyyyyyy and unique the
-// adjacent equal elements.
-template <class Container, class Operation>
-void bm_contiguous(std::string operation_name, Operation unique_copy) {
-  auto bench = [unique_copy](auto& st) {
-    std::size_t const size = st.range(0);
-    using ValueType        = typename Container::value_type;
-    Container c(size);
-    ValueType x = Generate<ValueType>::random();
-    ValueType y = Generate<ValueType>::random();
-    auto half   = size / 2;
-    std::fill_n(std::fill_n(c.begin(), half, x), half, y);
-
-    std::vector<ValueType> out(size);
-
-    auto pred = [](auto& a, auto& b) {
-      benchmark::DoNotOptimize(a);
-      benchmark::DoNotOptimize(b);
-      return a == b;
-    };
-
-    for ([[maybe_unused]] auto _ : st) {
-      auto result = unique_copy(c.begin(), c.end(), out.begin(), pred);
-      benchmark::DoNotOptimize(result);
-      benchmark::DoNotOptimize(c);
-      benchmark::ClobberMemory();
-    }
-  };
-  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
-
-// Create a sequence of the form xxyyxxyyxxyyxxyyxxyy and unique
-// adjacent equal elements.
-template <class Container, class Operation>
-void bm_sprinkled(std::string operation_name, Operation unique_copy) {
-  auto bench = [unique_copy](auto& st) {
-    std::size_t const size = st.range(0);
-    using ValueType        = typename Container::value_type;
-    Container c(size);
-    ValueType x    = Generate<ValueType>::random();
-    ValueType y    = Generate<ValueType>::random();
-    auto alternate = [&](auto out, auto n) {
-      for (std::size_t i = 0; i != n; i += 2) {
-        *out++ = (i % 4 == 0 ? x : y);
-        *out++ = (i % 4 == 0 ? x : y);
-      }
-    };
-    alternate(c.begin(), size);
-
-    std::vector<ValueType> out(size);
-
-    auto pred = [](auto& a, auto& b) {
-      benchmark::DoNotOptimize(a);
-      benchmark::DoNotOptimize(b);
-      return a == b;
-    };
-
-    for ([[maybe_unused]] auto _ : st) {
-      auto result = unique_copy(c.begin(), c.end(), out.begin(), pred);
-      benchmark::DoNotOptimize(result);
-      benchmark::DoNotOptimize(c);
-      benchmark::ClobberMemory();
-    }
-  };
-  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
-
 int main(int argc, char** argv) {
   auto std_unique_copy = [](auto first, auto last, auto out, auto pred) {
     return std::unique_copy(first, last, out, pred);
   };
-  auto ranges_unique_copy = [](auto first, auto last, auto out, auto pred) {
-    return std::ranges::unique_copy(first, last, out, pred);
-  };
-
-  // std::unique_copy
-  bm_contiguous<std::vector<int>>("std::unique_copy(vector<int>, pred) (contiguous)", std_unique_copy);
-  bm_sprinkled<std::vector<int>>("std::unique_copy(vector<int>, pred) (sprinkled)", std_unique_copy);
-
-  bm_contiguous<std::deque<int>>("std::unique_copy(deque<int>, pred) (contiguous)", std_unique_copy);
-  bm_sprinkled<std::deque<int>>("std::unique_copy(deque<int>, pred) (sprinkled)", std_unique_copy);
 
-  bm_contiguous<std::list<int>>("std::unique_copy(list<int>, pred) (contiguous)", std_unique_copy);
-  bm_sprinkled<std::list<int>>("std::unique_copy(list<int>, pred) (sprinkled)", std_unique_copy);
-
-  // ranges::unique_copy
-  bm_contiguous<std::vector<int>>("ranges::unique_copy(vector<int>, pred) (contiguous)", ranges_unique_copy);
-  bm_sprinkled<std::vector<int>>("ranges::unique_copy(vector<int>, pred) (sprinkled)", ranges_unique_copy);
-
-  bm_contiguous<std::deque<int>>("ranges::unique_copy(deque<int>, pred) (contiguous)", ranges_unique_copy);
-  bm_sprinkled<std::deque<int>>("ranges::unique_copy(deque<int>, pred) (sprinkled)", ranges_unique_copy);
-
-  bm_contiguous<std::list<int>>("ranges::unique_copy(list<int>, pred) (contiguous)", ranges_unique_copy);
-  bm_sprinkled<std::list<int>>("ranges::unique_copy(list<int>, pred) (sprinkled)", ranges_unique_copy);
+  // Create a sequence of the form xxxxxxxxxxyyyyyyyyyy and unique the
+  // adjacent equal elements.
+  {
+    auto bm = []<class Container>(std::string name, auto unique_copy) {
+      benchmark::RegisterBenchmark(
+          name,
+          [unique_copy](auto& st) {
+            std::size_t const size = st.range(0);
+            using ValueType        = typename Container::value_type;
+            Container c(size);
+            ValueType x = Generate<ValueType>::random();
+            ValueType y = Generate<ValueType>::random();
+            auto half   = size / 2;
+            std::fill_n(std::fill_n(c.begin(), half, x), half, y);
+
+            std::vector<ValueType> out(size);
+
+            auto pred = [](auto& a, auto& b) {
+              benchmark::DoNotOptimize(a);
+              benchmark::DoNotOptimize(b);
+              return a == b;
+            };
+
+            for ([[maybe_unused]] auto _ : st) {
+              auto result = unique_copy(c.begin(), c.end(), out.begin(), pred);
+              benchmark::DoNotOptimize(result);
+              benchmark::DoNotOptimize(c);
+              benchmark::ClobberMemory();
+            }
+          })
+          ->Arg(32)
+          ->Arg(1024)
+          ->Arg(8192);
+    };
+    bm.operator()<std::vector<int>>("std::unique_copy(vector<int>, pred) (contiguous)", std_unique_copy);
+    bm.operator()<std::deque<int>>("std::unique_copy(deque<int>, pred) (contiguous)", std_unique_copy);
+    bm.operator()<std::list<int>>("std::unique_copy(list<int>, pred) (contiguous)", std_unique_copy);
+    bm.operator()<std::vector<int>>("rng::unique_copy(vector<int>, pred) (contiguous)", std::ranges::unique_copy);
+    bm.operator()<std::deque<int>>("rng::unique_copy(deque<int>, pred) (contiguous)", std::ranges::unique_copy);
+    bm.operator()<std::list<int>>("rng::unique_copy(list<int>, pred) (contiguous)", std::ranges::unique_copy);
+  }
+
+  // Create a sequence of the form xxyyxxyyxxyyxxyyxxyy and unique
+  // adjacent equal elements.
+  {
+    auto bm = []<class Container>(std::string name, auto unique_copy) {
+      benchmark::RegisterBenchmark(
+          name,
+          [unique_copy](auto& st) {
+            std::size_t const size = st.range(0);
+            using ValueType        = typename Container::value_type;
+            Container c(size);
+            ValueType x    = Generate<ValueType>::random();
+            ValueType y    = Generate<ValueType>::random();
+            auto alternate = [&](auto out, auto n) {
+              for (std::size_t i = 0; i != n; i += 2) {
+                *out++ = (i % 4 == 0 ? x : y);
+                *out++ = (i % 4 == 0 ? x : y);
+              }
+            };
+            alternate(c.begin(), size);
+
+            std::vector<ValueType> out(size);
+
+            auto pred = [](auto& a, auto& b) {
+              benchmark::DoNotOptimize(a);
+              benchmark::DoNotOptimize(b);
+              return a == b;
+            };
+
+            for ([[maybe_unused]] auto _ : st) {
+              auto result = unique_copy(c.begin(), c.end(), out.begin(), pred);
+              benchmark::DoNotOptimize(result);
+              benchmark::DoNotOptimize(c);
+              benchmark::ClobberMemory();
+            }
+          })
+          ->Arg(32)
+          ->Arg(1024)
+          ->Arg(8192);
+    };
+    bm.operator()<std::vector<int>>("std::unique_copy(vector<int>, pred) (sprinkled)", std_unique_copy);
+    bm.operator()<std::deque<int>>("std::unique_copy(deque<int>, pred) (sprinkled)", std_unique_copy);
+    bm.operator()<std::list<int>>("std::unique_copy(list<int>, pred) (sprinkled)", std_unique_copy);
+    bm.operator()<std::vector<int>>("rng::unique_copy(vector<int>, pred) (sprinkled)", std::ranges::unique_copy);
+    bm.operator()<std::deque<int>>("rng::unique_copy(deque<int>, pred) (sprinkled)", std::ranges::unique_copy);
+    bm.operator()<std::list<int>>("rng::unique_copy(list<int>, pred) (sprinkled)", std::ranges::unique_copy);
+  }
 
   benchmark::Initialize(&argc, argv);
   benchmark::RunSpecifiedBenchmarks();
diff --git a/libcxx/test/benchmarks/algorithms/modifying/unique_pred.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/unique_pred.bench.cpp
index 0b258ea5cbecc..fb11f2e1adb9d 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/unique_pred.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/unique_pred.bench.cpp
@@ -19,123 +19,124 @@
 #include "benchmark/benchmark.h"
 #include "../../GenerateInput.h"
 
-// Create a sequence of the form xxxxxxxxxxyyyyyyyyyy and unique the
-// adjacent equal elements.
-//
-// We perform this benchmark in a batch because we need to restore the
-// state of the container after the operation.
-template <class Container, class Operation>
-void bm_contiguous(std::string operation_name, Operation unique) {
-  auto bench = [unique](auto& st) {
-    std::size_t const size          = st.range(0);
-    constexpr std::size_t BatchSize = 10;
-    using ValueType                 = typename Container::value_type;
-    Container c[BatchSize];
-    ValueType x = Generate<ValueType>::random();
-    ValueType y = Generate<ValueType>::random();
-    for (std::size_t i = 0; i != BatchSize; ++i) {
-      c[i]      = Container(size);
-      auto half = size / 2;
-      std::fill_n(std::fill_n(c[i].begin(), half, x), half, y);
-    }
-
-    auto pred = [](auto& a, auto& b) {
-      benchmark::DoNotOptimize(a);
-      benchmark::DoNotOptimize(b);
-      return a == b;
-    };
-
-    while (st.KeepRunningBatch(BatchSize)) {
-      for (std::size_t i = 0; i != BatchSize; ++i) {
-        auto result = unique(c[i].begin(), c[i].end(), pred);
-        benchmark::DoNotOptimize(result);
-        benchmark::DoNotOptimize(c[i]);
-        benchmark::ClobberMemory();
-      }
-
-      st.PauseTiming();
-      for (std::size_t i = 0; i != BatchSize; ++i) {
-        auto half = size / 2;
-        std::fill_n(std::fill_n(c[i].begin(), half, x), half, y);
-      }
-      st.ResumeTiming();
-    }
-  };
-  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
-
-// Create a sequence of the form xxyyxxyyxxyyxxyyxxyy and unique
-// adjacent equal elements.
-//
-// We perform this benchmark in a batch because we need to restore the
-// state of the container after the operation.
-template <class Container, class Operation>
-void bm_sprinkled(std::string operation_name, Operation unique) {
-  auto bench = [unique](auto& st) {
-    std::size_t const size          = st.range(0);
-    constexpr std::size_t BatchSize = 10;
-    using ValueType                 = typename Container::value_type;
-    Container c[BatchSize];
-    ValueType x    = Generate<ValueType>::random();
-    ValueType y    = Generate<ValueType>::random();
-    auto alternate = [&](auto out, auto n) {
-      for (std::size_t i = 0; i != n; i += 2) {
-        *out++ = (i % 4 == 0 ? x : y);
-        *out++ = (i % 4 == 0 ? x : y);
-      }
+int main(int argc, char** argv) {
+  auto std_unique = [](auto first, auto last, auto pred) { return std::unique(first, last, pred); };
+
+  // Create a sequence of the form xxxxxxxxxxyyyyyyyyyy and unique the
+  // adjacent equal elements.
+  //
+  // We perform this benchmark in a batch because we need to restore the
+  // state of the container after the operation.
+  {
+    auto bm = []<class Container>(std::string name, auto unique) {
+      benchmark::RegisterBenchmark(
+          name,
+          [unique](auto& st) {
+            std::size_t const size          = st.range(0);
+            constexpr std::size_t BatchSize = 10;
+            using ValueType                 = typename Container::value_type;
+            Container c[BatchSize];
+            ValueType x = Generate<ValueType>::random();
+            ValueType y = Generate<ValueType>::random();
+            for (std::size_t i = 0; i != BatchSize; ++i) {
+              c[i]      = Container(size);
+              auto half = size / 2;
+              std::fill_n(std::fill_n(c[i].begin(), half, x), half, y);
+            }
+
+            auto pred = [](auto& a, auto& b) {
+              benchmark::DoNotOptimize(a);
+              benchmark::DoNotOptimize(b);
+              return a == b;
+            };
+
+            while (st.KeepRunningBatch(BatchSize)) {
+              for (std::size_t i = 0; i != BatchSize; ++i) {
+                auto result = unique(c[i].begin(), c[i].end(), pred);
+                benchmark::DoNotOptimize(result);
+                benchmark::DoNotOptimize(c[i]);
+                benchmark::ClobberMemory();
+              }
+
+              st.PauseTiming();
+              for (std::size_t i = 0; i != BatchSize; ++i) {
+                auto half = size / 2;
+                std::fill_n(std::fill_n(c[i].begin(), half, x), half, y);
+              }
+              st.ResumeTiming();
+            }
+          })
+          ->Arg(32)
+          ->Arg(1024)
+          ->Arg(8192);
     };
-    for (std::size_t i = 0; i != BatchSize; ++i) {
-      c[i] = Container(size);
-      alternate(c[i].begin(), size);
-    }
-
-    auto pred = [](auto& a, auto& b) {
-      benchmark::DoNotOptimize(a);
-      benchmark::DoNotOptimize(b);
-      return a == b;
+    bm.operator()<std::vector<int>>("std::unique(vector<int>, pred) (contiguous)", std_unique);
+    bm.operator()<std::deque<int>>("std::unique(deque<int>, pred) (contiguous)", std_unique);
+    bm.operator()<std::list<int>>("std::unique(list<int>, pred) (contiguous)", std_unique);
+    bm.operator()<std::vector<int>>("rng::unique(vector<int>, pred) (contiguous)", std::ranges::unique);
+    bm.operator()<std::deque<int>>("rng::unique(deque<int>, pred) (contiguous)", std::ranges::unique);
+    bm.operator()<std::list<int>>("rng::unique(list<int>, pred) (contiguous)", std::ranges::unique);
+  }
+
+  // Create a sequence of the form xxyyxxyyxxyyxxyyxxyy and unique
+  // adjacent equal elements.
+  //
+  // We perform this benchmark in a batch because we need to restore the
+  // state of the container after the operation.
+  {
+    auto bm = []<class Container>(std::string name, auto unique) {
+      benchmark::RegisterBenchmark(
+          name,
+          [unique](auto& st) {
+            std::size_t const size          = st.range(0);
+            constexpr std::size_t BatchSize = 10;
+            using ValueType                 = typename Container::value_type;
+            Container c[BatchSize];
+            ValueType x    = Generate<ValueType>::random();
+            ValueType y    = Generate<ValueType>::random();
+            auto alternate = [&](auto out, auto n) {
+              for (std::size_t i = 0; i != n; i += 2) {
+                *out++ = (i % 4 == 0 ? x : y);
+                *out++ = (i % 4 == 0 ? x : y);
+              }
+            };
+            for (std::size_t i = 0; i != BatchSize; ++i) {
+              c[i] = Container(size);
+              alternate(c[i].begin(), size);
+            }
+
+            auto pred = [](auto& a, auto& b) {
+              benchmark::DoNotOptimize(a);
+              benchmark::DoNotOptimize(b);
+              return a == b;
+            };
+
+            while (st.KeepRunningBatch(BatchSize)) {
+              for (std::size_t i = 0; i != BatchSize; ++i) {
+                auto result = unique(c[i].begin(), c[i].end(), pred);
+                benchmark::DoNotOptimize(result);
+                benchmark::DoNotOptimize(c[i]);
+                benchmark::ClobberMemory();
+              }
+
+              st.PauseTiming();
+              for (std::size_t i = 0; i != BatchSize; ++i) {
+                alternate(c[i].begin(), size);
+              }
+              st.ResumeTiming();
+            }
+          })
+          ->Arg(32)
+          ->Arg(1024)
+          ->Arg(8192);
     };
-
-    while (st.KeepRunningBatch(BatchSize)) {
-      for (std::size_t i = 0; i != BatchSize; ++i) {
-        auto result = unique(c[i].begin(), c[i].end(), pred);
-        benchmark::DoNotOptimize(result);
-        benchmark::DoNotOptimize(c[i]);
-        benchmark::ClobberMemory();
-      }
-
-      st.PauseTiming();
-      for (std::size_t i = 0; i != BatchSize; ++i) {
-        alternate(c[i].begin(), size);
-      }
-      st.ResumeTiming();
-    }
-  };
-  benchmark::RegisterBenchmark(operation_name, bench)->Arg(32)->Arg(1024)->Arg(8192);
-}
-
-int main(int argc, char** argv) {
-  auto std_unique    = [](auto first, auto last, auto pred) { return std::unique(first, last, pred); };
-  auto ranges_unique = [](auto first, auto last, auto pred) { return std::ranges::unique(first, last, pred); };
-
-  // std::unique
-  bm_contiguous<std::vector<int>>("std::unique(vector<int>, pred) (contiguous)", std_unique);
-  bm_sprinkled<std::vector<int>>("std::unique(vector<int>, pred) (sprinkled)", std_unique);
-
-  bm_contiguous<std::deque<int>>("std::unique(deque<int>, pred) (contiguous)", std_unique);
-  bm_sprinkled<std::deque<int>>("std::unique(deque<int>, pred) (sprinkled)", std_unique);
-
-  bm_contiguous<std::list<int>>("std::unique(list<int>, pred) (contiguous)", std_unique);
-  bm_sprinkled<std::list<int>>("std::unique(list<int>, pred) (sprinkled)", std_unique);
-
-  // ranges::unique
-  bm_contiguous<std::vector<int>>("ranges::unique(vector<int>, pred) (contiguous)", ranges_unique);
-  bm_sprinkled<std::vector<int>>("ranges::unique(vector<int>, pred) (sprinkled)", ranges_unique);
-
-  bm_contiguous<std::deque<int>>("ranges::unique(deque<int>, pred) (contiguous)", ranges_unique);
-  bm_sprinkled<std::deque<int>>("ranges::unique(deque<int>, pred) (sprinkled)", ranges_unique);
-
-  bm_contiguous<std::list<int>>("ranges::unique(list<int>, pred) (contiguous)", ranges_unique);
-  bm_sprinkled<std::list<int>>("ranges::unique(list<int>, pred) (sprinkled)", ranges_unique);
+    bm.operator()<std::vector<int>>("std::unique(vector<int>, pred) (sprinkled)", std_unique);
+    bm.operator()<std::deque<int>>("std::unique(deque<int>, pred) (sprinkled)", std_unique);
+    bm.operator()<std::list<int>>("std::unique(list<int>, pred) (sprinkled)", std_unique);
+    bm.operator()<std::vector<int>>("rng::unique(vector<int>, pred) (sprinkled)", std::ranges::unique);
+    bm.operator()<std::deque<int>>("rng::unique(deque<int>, pred) (sprinkled)", std::ranges::unique);
+    bm.operator()<std::list<int>>("rng::unique(list<int>, pred) (sprinkled)", std::ranges::unique);
+  }
 
   benchmark::Initialize(&argc, argv);
   benchmark::RunSpecifiedBenchmarks();

>From 55c1ebe59fa435b33dac84a11a735c77e443bcc3 Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Wed, 19 Feb 2025 16:36:59 -0500
Subject: [PATCH 04/15] Fix DoNotOptimize

---
 .../algorithms/modifying/fill.bench.cpp       | 14 ++++-----
 .../algorithms/modifying/fill_n.bench.cpp     | 14 ++++-----
 .../algorithms/modifying/generate.bench.cpp   |  9 +++---
 .../algorithms/modifying/generate_n.bench.cpp |  9 +++---
 .../algorithms/modifying/move.bench.cpp       | 31 ++++++++-----------
 .../modifying/move_backward.bench.cpp         | 31 ++++++++-----------
 .../algorithms/modifying/remove.bench.cpp     | 10 +++---
 .../modifying/remove_copy.bench.cpp           | 10 +++---
 .../modifying/remove_copy_if.bench.cpp        | 30 +++++++-----------
 .../algorithms/modifying/remove_if.bench.cpp  |  8 ++---
 .../algorithms/modifying/replace.bench.cpp    | 12 +++----
 .../algorithms/modifying/replace_if.bench.cpp | 14 ++++-----
 .../algorithms/modifying/reverse.bench.cpp    |  2 +-
 .../modifying/reverse_copy.bench.cpp          |  5 +--
 .../algorithms/modifying/rotate.bench.cpp     |  3 +-
 .../modifying/rotate_copy.bench.cpp           |  4 +--
 .../algorithms/modifying/sample.bench.cpp     |  5 ++-
 .../algorithms/modifying/shift_left.bench.cpp |  3 +-
 .../modifying/shift_right.bench.cpp           |  3 +-
 .../algorithms/modifying/shuffle.bench.cpp    |  2 +-
 .../modifying/swap_ranges.bench.cpp           |  3 +-
 .../modifying/transform.binary.bench.cpp      |  7 ++---
 .../modifying/transform.unary.bench.cpp       |  5 ++-
 .../algorithms/modifying/unique.bench.cpp     |  6 ++--
 .../modifying/unique_copy.bench.cpp           |  8 ++---
 .../modifying/unique_copy_pred.bench.cpp      |  8 ++---
 .../modifying/unique_pred.bench.cpp           |  6 ++--
 27 files changed, 113 insertions(+), 149 deletions(-)

diff --git a/libcxx/test/benchmarks/algorithms/modifying/fill.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/fill.bench.cpp
index fb0fa8ffc5c69..79f6619e2977f 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/fill.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/fill.bench.cpp
@@ -36,12 +36,11 @@ int main(int argc, char** argv) {
             Container c(size, y);
 
             for ([[maybe_unused]] auto _ : st) {
-              fill(c.begin(), c.end(), x);
-              std::swap(x, y);
               benchmark::DoNotOptimize(c);
               benchmark::DoNotOptimize(x);
-              benchmark::DoNotOptimize(y);
-              benchmark::ClobberMemory();
+              fill(c.begin(), c.end(), x);
+              benchmark::DoNotOptimize(c);
+              std::swap(x, y);
             }
           })
           ->Arg(32)
@@ -66,12 +65,11 @@ int main(int argc, char** argv) {
         std::vector<bool> c(size, y);
 
         for ([[maybe_unused]] auto _ : st) {
-          fill(c.begin(), c.end(), x);
-          std::swap(x, y);
           benchmark::DoNotOptimize(c);
           benchmark::DoNotOptimize(x);
-          benchmark::DoNotOptimize(y);
-          benchmark::ClobberMemory();
+          fill(c.begin(), c.end(), x);
+          benchmark::DoNotOptimize(c);
+          std::swap(x, y);
         }
       })->Range(64, 1 << 20);
     };
diff --git a/libcxx/test/benchmarks/algorithms/modifying/fill_n.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/fill_n.bench.cpp
index d4ca98e623871..505fbcbb2f442 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/fill_n.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/fill_n.bench.cpp
@@ -36,12 +36,11 @@ int main(int argc, char** argv) {
             Container c(size, y);
 
             for ([[maybe_unused]] auto _ : st) {
-              fill_n(c.begin(), size, x);
-              std::swap(x, y);
               benchmark::DoNotOptimize(c);
               benchmark::DoNotOptimize(x);
-              benchmark::DoNotOptimize(y);
-              benchmark::ClobberMemory();
+              fill_n(c.begin(), size, x);
+              benchmark::DoNotOptimize(c);
+              std::swap(x, y);
             }
           })
           ->Arg(32)
@@ -66,12 +65,11 @@ int main(int argc, char** argv) {
         std::vector<bool> c(size, y);
 
         for ([[maybe_unused]] auto _ : st) {
-          fill_n(c.begin(), size, x);
-          std::swap(x, y);
           benchmark::DoNotOptimize(c);
           benchmark::DoNotOptimize(x);
-          benchmark::DoNotOptimize(y);
-          benchmark::ClobberMemory();
+          fill_n(c.begin(), size, x);
+          benchmark::DoNotOptimize(c);
+          std::swap(x, y);
         }
       })->Range(64, 1 << 20);
     };
diff --git a/libcxx/test/benchmarks/algorithms/modifying/generate.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/generate.bench.cpp
index 9056d598d5d38..e3a8d650b5159 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/generate.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/generate.bench.cpp
@@ -34,11 +34,12 @@ int main(int argc, char** argv) {
             ValueType x     = Generate<ValueType>::random();
 
             for ([[maybe_unused]] auto _ : st) {
-              auto f = [&x] { return x; };
-              generate(c.begin(), c.end(), f);
               benchmark::DoNotOptimize(c);
-              benchmark::DoNotOptimize(x);
-              benchmark::ClobberMemory();
+              generate(c.begin(), c.end(), [&x] {
+                benchmark::DoNotOptimize(x);
+                return x;
+              });
+              benchmark::DoNotOptimize(c);
             }
           })
           ->Arg(32)
diff --git a/libcxx/test/benchmarks/algorithms/modifying/generate_n.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/generate_n.bench.cpp
index d33d9183dcb42..3671b66b21a85 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/generate_n.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/generate_n.bench.cpp
@@ -34,11 +34,12 @@ int main(int argc, char** argv) {
             ValueType x     = Generate<ValueType>::random();
 
             for ([[maybe_unused]] auto _ : st) {
-              auto f = [&x] { return x; };
-              generate_n(c.begin(), size, f);
               benchmark::DoNotOptimize(c);
-              benchmark::DoNotOptimize(x);
-              benchmark::ClobberMemory();
+              generate_n(c.begin(), size, [&x] {
+                benchmark::DoNotOptimize(x);
+                return x;
+              });
+              benchmark::DoNotOptimize(c);
             }
           })
           ->Arg(32)
diff --git a/libcxx/test/benchmarks/algorithms/modifying/move.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/move.bench.cpp
index f009850dac215..73e1a3881515f 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/move.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/move.bench.cpp
@@ -27,16 +27,16 @@ int main(int argc, char** argv) {
   {
     auto bm = []<class Container>(std::string name, auto move) {
       benchmark::RegisterBenchmark(name, [move](auto& st) {
-        std::size_t const n = st.range(0);
-        using ValueType     = typename Container::value_type;
-        Container c1(n), c2(n);
-        std::generate_n(c1.begin(), n, [] { return Generate<ValueType>::random(); });
+        std::size_t const size = st.range(0);
+        using ValueType        = typename Container::value_type;
+        Container c1(size), c2(size);
+        std::generate_n(c1.begin(), size, [] { return Generate<ValueType>::random(); });
 
         Container* in  = &c1;
         Container* out = &c2;
         for ([[maybe_unused]] auto _ : st) {
-          benchmark::DoNotOptimize(c1);
-          benchmark::DoNotOptimize(c2);
+          benchmark::DoNotOptimize(in);
+          benchmark::DoNotOptimize(out);
           auto result = move(in->begin(), in->end(), out->begin());
           benchmark::DoNotOptimize(result);
           std::swap(in, out);
@@ -55,24 +55,19 @@ int main(int argc, char** argv) {
   {
     auto bm = []<bool Aligned>(std::string name, auto move) {
       benchmark::RegisterBenchmark(name, [move](auto& st) {
-        std::size_t const n = st.range(0);
-        std::vector<bool> c1(n, true);
-        std::vector<bool> c2(n, false);
+        std::size_t const size = st.range(0);
+        std::vector<bool> c1(size, true);
+        std::vector<bool> c2(size, false);
 
         std::vector<bool>* in  = &c1;
         std::vector<bool>* out = &c2;
         for (auto _ : st) {
-          auto first1 = in->begin();
-          auto last1  = in->end();
-          auto first2 = out->begin();
-          if constexpr (Aligned) {
-            benchmark::DoNotOptimize(move(first1, last1, first2));
-          } else {
-            benchmark::DoNotOptimize(move(first1 + 4, last1, first2));
-          }
-          std::swap(in, out);
           benchmark::DoNotOptimize(in);
           benchmark::DoNotOptimize(out);
+          auto first  = Aligned ? in->begin() : in->begin() + 4;
+          auto result = move(first, in->end(), out->begin());
+          benchmark::DoNotOptimize(result);
+          std::swap(in, out);
         }
       })->Range(64, 1 << 20);
     };
diff --git a/libcxx/test/benchmarks/algorithms/modifying/move_backward.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/move_backward.bench.cpp
index ef9373cbcdd72..0e6eea1b4d873 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/move_backward.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/move_backward.bench.cpp
@@ -27,16 +27,16 @@ int main(int argc, char** argv) {
   {
     auto bm = []<class Container>(std::string name, auto move_backward) {
       benchmark::RegisterBenchmark(name, [move_backward](auto& st) {
-        std::size_t const n = st.range(0);
-        using ValueType     = typename Container::value_type;
-        Container c1(n), c2(n);
-        std::generate_n(c1.begin(), n, [] { return Generate<ValueType>::random(); });
+        std::size_t const size = st.range(0);
+        using ValueType        = typename Container::value_type;
+        Container c1(size), c2(size);
+        std::generate_n(c1.begin(), size, [] { return Generate<ValueType>::random(); });
 
         Container* in  = &c1;
         Container* out = &c2;
         for ([[maybe_unused]] auto _ : st) {
-          benchmark::DoNotOptimize(c1);
-          benchmark::DoNotOptimize(c2);
+          benchmark::DoNotOptimize(in);
+          benchmark::DoNotOptimize(out);
           auto result = move_backward(in->begin(), in->end(), out->end());
           benchmark::DoNotOptimize(result);
           std::swap(in, out);
@@ -55,24 +55,19 @@ int main(int argc, char** argv) {
   {
     auto bm = []<bool Aligned>(std::string name, auto move_backward) {
       benchmark::RegisterBenchmark(name, [move_backward](auto& st) {
-        std::size_t const n = st.range(0);
-        std::vector<bool> c1(n, true);
-        std::vector<bool> c2(n, false);
+        std::size_t const size = st.range(0);
+        std::vector<bool> c1(size, true);
+        std::vector<bool> c2(size, false);
 
         std::vector<bool>* in  = &c1;
         std::vector<bool>* out = &c2;
         for (auto _ : st) {
-          auto first1 = in->begin();
-          auto last1  = in->end();
-          auto last2  = out->end();
-          if constexpr (Aligned) {
-            benchmark::DoNotOptimize(move_backward(first1, last1, last2));
-          } else {
-            benchmark::DoNotOptimize(move_backward(first1, last1 - 4, last2));
-          }
-          std::swap(in, out);
           benchmark::DoNotOptimize(in);
           benchmark::DoNotOptimize(out);
+          auto last   = Aligned ? in->end() : in->end() - 4;
+          auto result = move_backward(in->begin(), last, out->end());
+          benchmark::DoNotOptimize(result);
+          std::swap(in, out);
         }
       })->Range(64, 1 << 20);
     };
diff --git a/libcxx/test/benchmarks/algorithms/modifying/remove.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/remove.bench.cpp
index 956753de13edc..adec1d2292bcf 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/remove.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/remove.bench.cpp
@@ -46,11 +46,10 @@ int main(int argc, char** argv) {
 
             while (st.KeepRunningBatch(BatchSize)) {
               for (std::size_t i = 0; i != BatchSize; ++i) {
-                auto result = remove(c[i].begin(), c[i].end(), x);
-                benchmark::DoNotOptimize(result);
                 benchmark::DoNotOptimize(c[i]);
                 benchmark::DoNotOptimize(x);
-                benchmark::ClobberMemory();
+                auto result = remove(c[i].begin(), c[i].end(), x);
+                benchmark::DoNotOptimize(result);
               }
 
               st.PauseTiming();
@@ -101,11 +100,10 @@ int main(int argc, char** argv) {
 
             while (st.KeepRunningBatch(BatchSize)) {
               for (std::size_t i = 0; i != BatchSize; ++i) {
-                auto result = remove(c[i].begin(), c[i].end(), x);
-                benchmark::DoNotOptimize(result);
                 benchmark::DoNotOptimize(c[i]);
                 benchmark::DoNotOptimize(x);
-                benchmark::ClobberMemory();
+                auto result = remove(c[i].begin(), c[i].end(), x);
+                benchmark::DoNotOptimize(result);
               }
 
               st.PauseTiming();
diff --git a/libcxx/test/benchmarks/algorithms/modifying/remove_copy.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/remove_copy.bench.cpp
index b5e876fc9ba15..af9994c07cc22 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/remove_copy.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/remove_copy.bench.cpp
@@ -42,12 +42,11 @@ int main(int argc, char** argv) {
             std::vector<ValueType> out(size);
 
             for ([[maybe_unused]] auto _ : st) {
-              auto result = remove_copy(c.begin(), c.end(), out.begin(), x);
-              benchmark::DoNotOptimize(result);
               benchmark::DoNotOptimize(c);
               benchmark::DoNotOptimize(out);
               benchmark::DoNotOptimize(x);
-              benchmark::ClobberMemory();
+              auto result = remove_copy(c.begin(), c.end(), out.begin(), x);
+              benchmark::DoNotOptimize(result);
             }
           })
           ->Arg(32)
@@ -81,12 +80,11 @@ int main(int argc, char** argv) {
             std::vector<ValueType> out(size);
 
             for ([[maybe_unused]] auto _ : st) {
-              auto result = remove_copy(c.begin(), c.end(), out.begin(), x);
-              benchmark::DoNotOptimize(result);
               benchmark::DoNotOptimize(c);
               benchmark::DoNotOptimize(out);
               benchmark::DoNotOptimize(x);
-              benchmark::ClobberMemory();
+              auto result = remove_copy(c.begin(), c.end(), out.begin(), x);
+              benchmark::DoNotOptimize(result);
             }
           })
           ->Arg(32)
diff --git a/libcxx/test/benchmarks/algorithms/modifying/remove_copy_if.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/remove_copy_if.bench.cpp
index 13464b65e8158..e6fa7a0c1ea79 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/remove_copy_if.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/remove_copy_if.bench.cpp
@@ -39,20 +39,17 @@ int main(int argc, char** argv) {
             std::fill_n(std::back_inserter(c), size / 2, x);
             std::fill_n(std::back_inserter(c), size / 2, y);
 
-            auto pred = [&](auto& element) {
-              benchmark::DoNotOptimize(element);
-              return element == x;
-            };
-
             std::vector<ValueType> out(size);
 
             for ([[maybe_unused]] auto _ : st) {
-              auto result = remove_copy_if(c.begin(), c.end(), out.begin(), pred);
-              benchmark::DoNotOptimize(result);
               benchmark::DoNotOptimize(c);
               benchmark::DoNotOptimize(out);
-              benchmark::DoNotOptimize(x);
-              benchmark::ClobberMemory();
+              auto pred = [&x](auto& element) {
+                benchmark::DoNotOptimize(element);
+                return element == x;
+              };
+              auto result = remove_copy_if(c.begin(), c.end(), out.begin(), pred);
+              benchmark::DoNotOptimize(result);
             }
           })
           ->Arg(32)
@@ -83,20 +80,17 @@ int main(int argc, char** argv) {
               c.push_back(i % 2 == 0 ? x : y);
             }
 
-            auto pred = [&](auto& element) {
-              benchmark::DoNotOptimize(element);
-              return element == x;
-            };
-
             std::vector<ValueType> out(size);
 
             for ([[maybe_unused]] auto _ : st) {
-              auto result = remove_copy_if(c.begin(), c.end(), out.begin(), pred);
-              benchmark::DoNotOptimize(result);
               benchmark::DoNotOptimize(c);
               benchmark::DoNotOptimize(out);
-              benchmark::DoNotOptimize(x);
-              benchmark::ClobberMemory();
+              auto pred = [&](auto& element) {
+                benchmark::DoNotOptimize(element);
+                return element == x;
+              };
+              auto result = remove_copy_if(c.begin(), c.end(), out.begin(), pred);
+              benchmark::DoNotOptimize(result);
             }
           })
           ->Arg(32)
diff --git a/libcxx/test/benchmarks/algorithms/modifying/remove_if.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/remove_if.bench.cpp
index 9ccc436ba47cb..d5e185ef3ba9c 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/remove_if.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/remove_if.bench.cpp
@@ -51,11 +51,9 @@ int main(int argc, char** argv) {
 
             while (st.KeepRunningBatch(BatchSize)) {
               for (std::size_t i = 0; i != BatchSize; ++i) {
+                benchmark::DoNotOptimize(c[i]);
                 auto result = remove_if(c[i].begin(), c[i].end(), pred);
                 benchmark::DoNotOptimize(result);
-                benchmark::DoNotOptimize(c[i]);
-                benchmark::DoNotOptimize(x);
-                benchmark::ClobberMemory();
               }
 
               st.PauseTiming();
@@ -111,11 +109,9 @@ int main(int argc, char** argv) {
 
             while (st.KeepRunningBatch(BatchSize)) {
               for (std::size_t i = 0; i != BatchSize; ++i) {
+                benchmark::DoNotOptimize(c[i]);
                 auto result = remove_if(c[i].begin(), c[i].end(), pred);
                 benchmark::DoNotOptimize(result);
-                benchmark::DoNotOptimize(c[i]);
-                benchmark::DoNotOptimize(x);
-                benchmark::ClobberMemory();
               }
 
               st.PauseTiming();
diff --git a/libcxx/test/benchmarks/algorithms/modifying/replace.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/replace.bench.cpp
index 48ab1063a9954..e34f1e28c1459 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/replace.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/replace.bench.cpp
@@ -42,12 +42,12 @@ int main(int argc, char** argv) {
             std::fill_n(std::back_inserter(c), size / 2, y);
 
             for ([[maybe_unused]] auto _ : st) {
-              replace(c.begin(), c.end(), x, z);
-              std::swap(x, z);
               benchmark::DoNotOptimize(c);
               benchmark::DoNotOptimize(x);
               benchmark::DoNotOptimize(z);
-              benchmark::ClobberMemory();
+              replace(c.begin(), c.end(), x, z);
+              benchmark::DoNotOptimize(c);
+              std::swap(x, z);
             }
           })
           ->Arg(32)
@@ -79,12 +79,12 @@ int main(int argc, char** argv) {
             }
 
             for ([[maybe_unused]] auto _ : st) {
-              replace(c.begin(), c.end(), x, z);
-              std::swap(x, z);
               benchmark::DoNotOptimize(c);
               benchmark::DoNotOptimize(x);
               benchmark::DoNotOptimize(z);
-              benchmark::ClobberMemory();
+              replace(c.begin(), c.end(), x, z);
+              benchmark::DoNotOptimize(c);
+              std::swap(x, z);
             }
           })
           ->Arg(32)
diff --git a/libcxx/test/benchmarks/algorithms/modifying/replace_if.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/replace_if.bench.cpp
index 3b139c54eeb12..1a51d3da4fc89 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/replace_if.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/replace_if.bench.cpp
@@ -44,16 +44,15 @@ int main(int argc, char** argv) {
             std::fill_n(std::back_inserter(c), size / 2, y);
 
             for ([[maybe_unused]] auto _ : st) {
+              benchmark::DoNotOptimize(c);
+              benchmark::DoNotOptimize(z);
               auto pred = [&x](auto& element) {
                 benchmark::DoNotOptimize(element);
                 return element == x;
               };
               replace_if(c.begin(), c.end(), pred, z);
-              std::swap(x, z);
               benchmark::DoNotOptimize(c);
-              benchmark::DoNotOptimize(x);
-              benchmark::DoNotOptimize(z);
-              benchmark::ClobberMemory();
+              std::swap(x, z);
             }
           })
           ->Arg(32)
@@ -85,16 +84,15 @@ int main(int argc, char** argv) {
             }
 
             for ([[maybe_unused]] auto _ : st) {
+              benchmark::DoNotOptimize(c);
+              benchmark::DoNotOptimize(z);
               auto pred = [&x](auto& element) {
                 benchmark::DoNotOptimize(element);
                 return element == x;
               };
               replace_if(c.begin(), c.end(), pred, z);
-              std::swap(x, z);
               benchmark::DoNotOptimize(c);
-              benchmark::DoNotOptimize(x);
-              benchmark::DoNotOptimize(z);
-              benchmark::ClobberMemory();
+              std::swap(x, z);
             }
           })
           ->Arg(32)
diff --git a/libcxx/test/benchmarks/algorithms/modifying/reverse.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/reverse.bench.cpp
index 4ce2133c9a557..ded7d5018cdbe 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/reverse.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/reverse.bench.cpp
@@ -32,9 +32,9 @@ int main(int argc, char** argv) {
         std::generate_n(std::back_inserter(c), size, [] { return Generate<ValueType>::random(); });
 
         for ([[maybe_unused]] auto _ : st) {
+          benchmark::DoNotOptimize(c);
           reverse(c.begin(), c.end());
           benchmark::DoNotOptimize(c);
-          benchmark::ClobberMemory();
         }
       })->Range(8, 1 << 15);
     };
diff --git a/libcxx/test/benchmarks/algorithms/modifying/reverse_copy.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/reverse_copy.bench.cpp
index c77cb9a560494..7e19eb71f059a 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/reverse_copy.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/reverse_copy.bench.cpp
@@ -34,9 +34,10 @@ int main(int argc, char** argv) {
         std::vector<ValueType> out(size);
 
         for ([[maybe_unused]] auto _ : st) {
-          reverse_copy(c.begin(), c.end(), out.begin());
           benchmark::DoNotOptimize(c);
-          benchmark::ClobberMemory();
+          benchmark::DoNotOptimize(out);
+          auto result = reverse_copy(c.begin(), c.end(), out.begin());
+          benchmark::DoNotOptimize(result);
         }
       })->Range(8, 1 << 15);
     };
diff --git a/libcxx/test/benchmarks/algorithms/modifying/rotate.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/rotate.bench.cpp
index e32afbc87c9a0..8345f0941c62e 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/rotate.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/rotate.bench.cpp
@@ -35,10 +35,9 @@ int main(int argc, char** argv) {
 
             auto middle = std::next(c.begin(), size / 2);
             for ([[maybe_unused]] auto _ : st) {
+              benchmark::DoNotOptimize(c);
               auto result = rotate(c.begin(), middle, c.end());
               benchmark::DoNotOptimize(result);
-              benchmark::DoNotOptimize(c);
-              benchmark::ClobberMemory();
             }
           })
           ->Arg(32)
diff --git a/libcxx/test/benchmarks/algorithms/modifying/rotate_copy.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/rotate_copy.bench.cpp
index 7972f1aba096e..4f685ba9a8c7e 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/rotate_copy.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/rotate_copy.bench.cpp
@@ -39,10 +39,10 @@ int main(int argc, char** argv) {
 
             auto middle = std::next(c.begin(), size / 2);
             for ([[maybe_unused]] auto _ : st) {
+              benchmark::DoNotOptimize(c);
+              benchmark::DoNotOptimize(out);
               auto result = rotate_copy(c.begin(), middle, c.end(), out.begin());
               benchmark::DoNotOptimize(result);
-              benchmark::DoNotOptimize(c);
-              benchmark::ClobberMemory();
             }
           })
           ->Arg(32)
diff --git a/libcxx/test/benchmarks/algorithms/modifying/sample.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/sample.bench.cpp
index 87ab7517cb723..6cc789f460700 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/sample.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/sample.bench.cpp
@@ -41,11 +41,10 @@ int main(int argc, char** argv) {
             std::mt19937 rng;
 
             for ([[maybe_unused]] auto _ : st) {
-              auto result = sample(c.begin(), c.end(), out.begin(), n, rng);
-              benchmark::DoNotOptimize(result);
               benchmark::DoNotOptimize(c);
               benchmark::DoNotOptimize(out);
-              benchmark::ClobberMemory();
+              auto result = sample(c.begin(), c.end(), out.begin(), n, rng);
+              benchmark::DoNotOptimize(result);
             }
           })
           ->Arg(32)
diff --git a/libcxx/test/benchmarks/algorithms/modifying/shift_left.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/shift_left.bench.cpp
index 24a3d34c65f09..906e825992b9d 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/shift_left.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/shift_left.bench.cpp
@@ -36,10 +36,9 @@ int main(int argc, char** argv) {
             auto const n = 9 * (size / 10); // shift all but 10% of the range
 
             for ([[maybe_unused]] auto _ : st) {
+              benchmark::DoNotOptimize(c);
               auto result = shift_left(c.begin(), c.end(), n);
               benchmark::DoNotOptimize(result);
-              benchmark::DoNotOptimize(c);
-              benchmark::ClobberMemory();
             }
           })
           ->Arg(32)
diff --git a/libcxx/test/benchmarks/algorithms/modifying/shift_right.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/shift_right.bench.cpp
index 90fb507643149..ef55e55f3ca10 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/shift_right.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/shift_right.bench.cpp
@@ -36,10 +36,9 @@ int main(int argc, char** argv) {
             auto const n = 9 * (size / 10); // shift all but 10% of the range
 
             for ([[maybe_unused]] auto _ : st) {
+              benchmark::DoNotOptimize(c);
               auto result = shift_right(c.begin(), c.end(), n);
               benchmark::DoNotOptimize(result);
-              benchmark::DoNotOptimize(c);
-              benchmark::ClobberMemory();
             }
           })
           ->Arg(32)
diff --git a/libcxx/test/benchmarks/algorithms/modifying/shuffle.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/shuffle.bench.cpp
index f50dff7635703..24f7fb6828977 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/shuffle.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/shuffle.bench.cpp
@@ -35,9 +35,9 @@ int main(int argc, char** argv) {
             std::mt19937 rng;
 
             for ([[maybe_unused]] auto _ : st) {
+              benchmark::DoNotOptimize(c);
               shuffle(c.begin(), c.end(), rng);
               benchmark::DoNotOptimize(c);
-              benchmark::ClobberMemory();
             }
           })
           ->Arg(32)
diff --git a/libcxx/test/benchmarks/algorithms/modifying/swap_ranges.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/swap_ranges.bench.cpp
index f7c2ff1252b09..541f4ae17cc7a 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/swap_ranges.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/swap_ranges.bench.cpp
@@ -37,11 +37,12 @@ int main(int argc, char** argv) {
             std::generate_n(std::back_inserter(c2), size, [] { return Generate<ValueType>::random(); });
 
             for ([[maybe_unused]] auto _ : st) {
+              benchmark::DoNotOptimize(c1);
+              benchmark::DoNotOptimize(c2);
               auto result = swap_ranges(c1.begin(), c1.end(), c2.begin(), c2.end());
               benchmark::DoNotOptimize(result);
               benchmark::DoNotOptimize(c1);
               benchmark::DoNotOptimize(c2);
-              benchmark::ClobberMemory();
             }
           })
           ->Arg(32)
diff --git a/libcxx/test/benchmarks/algorithms/modifying/transform.binary.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/transform.binary.bench.cpp
index b3e1195bcecb8..dd5e3783e6f13 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/transform.binary.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/transform.binary.bench.cpp
@@ -45,12 +45,11 @@ int main(int argc, char** argv) {
             };
 
             for ([[maybe_unused]] auto _ : st) {
-              auto result = transform(c1.begin(), c1.end(), c2.begin(), c2.end(), out.begin(), f);
-              benchmark::DoNotOptimize(result);
-              benchmark::DoNotOptimize(out);
               benchmark::DoNotOptimize(c1);
               benchmark::DoNotOptimize(c2);
-              benchmark::ClobberMemory();
+              benchmark::DoNotOptimize(out);
+              auto result = transform(c1.begin(), c1.end(), c2.begin(), c2.end(), out.begin(), f);
+              benchmark::DoNotOptimize(result);
             }
           })
           ->Arg(32)
diff --git a/libcxx/test/benchmarks/algorithms/modifying/transform.unary.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/transform.unary.bench.cpp
index 837be87ada70b..e36a5f96c4e6f 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/transform.unary.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/transform.unary.bench.cpp
@@ -41,11 +41,10 @@ int main(int argc, char** argv) {
             };
 
             for ([[maybe_unused]] auto _ : st) {
+              benchmark::DoNotOptimize(c);
+              benchmark::DoNotOptimize(out);
               auto result = transform(c.begin(), c.end(), out.begin(), f);
               benchmark::DoNotOptimize(result);
-              benchmark::DoNotOptimize(out);
-              benchmark::DoNotOptimize(c);
-              benchmark::ClobberMemory();
             }
           })
           ->Arg(32)
diff --git a/libcxx/test/benchmarks/algorithms/modifying/unique.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/unique.bench.cpp
index 8cc80982de70b..2a334447f953b 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/unique.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/unique.bench.cpp
@@ -46,10 +46,9 @@ int main(int argc, char** argv) {
 
             while (st.KeepRunningBatch(BatchSize)) {
               for (std::size_t i = 0; i != BatchSize; ++i) {
+                benchmark::DoNotOptimize(c[i]);
                 auto result = unique(c[i].begin(), c[i].end());
                 benchmark::DoNotOptimize(result);
-                benchmark::DoNotOptimize(c[i]);
-                benchmark::ClobberMemory();
               }
 
               st.PauseTiming();
@@ -101,10 +100,9 @@ int main(int argc, char** argv) {
 
             while (st.KeepRunningBatch(BatchSize)) {
               for (std::size_t i = 0; i != BatchSize; ++i) {
+                benchmark::DoNotOptimize(c[i]);
                 auto result = unique(c[i].begin(), c[i].end());
                 benchmark::DoNotOptimize(result);
-                benchmark::DoNotOptimize(c[i]);
-                benchmark::ClobberMemory();
               }
 
               st.PauseTiming();
diff --git a/libcxx/test/benchmarks/algorithms/modifying/unique_copy.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/unique_copy.bench.cpp
index 3027953513958..a8bd2ed327c2b 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/unique_copy.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/unique_copy.bench.cpp
@@ -40,10 +40,10 @@ int main(int argc, char** argv) {
             std::vector<ValueType> out(size);
 
             for ([[maybe_unused]] auto _ : st) {
+              benchmark::DoNotOptimize(c);
+              benchmark::DoNotOptimize(out);
               auto result = unique_copy(c.begin(), c.end(), out.begin());
               benchmark::DoNotOptimize(result);
-              benchmark::DoNotOptimize(c);
-              benchmark::ClobberMemory();
             }
           })
           ->Arg(32)
@@ -81,10 +81,10 @@ int main(int argc, char** argv) {
             std::vector<ValueType> out(size);
 
             for ([[maybe_unused]] auto _ : st) {
+              benchmark::DoNotOptimize(c);
+              benchmark::DoNotOptimize(out);
               auto result = unique_copy(c.begin(), c.end(), out.begin());
               benchmark::DoNotOptimize(result);
-              benchmark::DoNotOptimize(c);
-              benchmark::ClobberMemory();
             }
           })
           ->Arg(32)
diff --git a/libcxx/test/benchmarks/algorithms/modifying/unique_copy_pred.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/unique_copy_pred.bench.cpp
index 742feb873b25e..4d29e16ce9e1e 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/unique_copy_pred.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/unique_copy_pred.bench.cpp
@@ -48,10 +48,10 @@ int main(int argc, char** argv) {
             };
 
             for ([[maybe_unused]] auto _ : st) {
+              benchmark::DoNotOptimize(c);
+              benchmark::DoNotOptimize(out);
               auto result = unique_copy(c.begin(), c.end(), out.begin(), pred);
               benchmark::DoNotOptimize(result);
-              benchmark::DoNotOptimize(c);
-              benchmark::ClobberMemory();
             }
           })
           ->Arg(32)
@@ -95,10 +95,10 @@ int main(int argc, char** argv) {
             };
 
             for ([[maybe_unused]] auto _ : st) {
+              benchmark::DoNotOptimize(c);
+              benchmark::DoNotOptimize(out);
               auto result = unique_copy(c.begin(), c.end(), out.begin(), pred);
               benchmark::DoNotOptimize(result);
-              benchmark::DoNotOptimize(c);
-              benchmark::ClobberMemory();
             }
           })
           ->Arg(32)
diff --git a/libcxx/test/benchmarks/algorithms/modifying/unique_pred.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/unique_pred.bench.cpp
index fb11f2e1adb9d..25f87e022023b 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/unique_pred.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/unique_pred.bench.cpp
@@ -52,10 +52,9 @@ int main(int argc, char** argv) {
 
             while (st.KeepRunningBatch(BatchSize)) {
               for (std::size_t i = 0; i != BatchSize; ++i) {
+                benchmark::DoNotOptimize(c[i]);
                 auto result = unique(c[i].begin(), c[i].end(), pred);
                 benchmark::DoNotOptimize(result);
-                benchmark::DoNotOptimize(c[i]);
-                benchmark::ClobberMemory();
               }
 
               st.PauseTiming();
@@ -113,10 +112,9 @@ int main(int argc, char** argv) {
 
             while (st.KeepRunningBatch(BatchSize)) {
               for (std::size_t i = 0; i != BatchSize; ++i) {
+                benchmark::DoNotOptimize(c[i]);
                 auto result = unique(c[i].begin(), c[i].end(), pred);
                 benchmark::DoNotOptimize(result);
-                benchmark::DoNotOptimize(c[i]);
-                benchmark::ClobberMemory();
               }
 
               st.PauseTiming();

>From 8cca6555ab0b20802f1a7f4651354fc367ffad2c Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Thu, 20 Feb 2025 08:27:34 -0500
Subject: [PATCH 05/15] maybe_unused

---
 libcxx/test/benchmarks/algorithms/modifying/move.bench.cpp      | 2 +-
 .../benchmarks/algorithms/modifying/move_backward.bench.cpp     | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/libcxx/test/benchmarks/algorithms/modifying/move.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/move.bench.cpp
index 73e1a3881515f..8213c16b78e6b 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/move.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/move.bench.cpp
@@ -61,7 +61,7 @@ int main(int argc, char** argv) {
 
         std::vector<bool>* in  = &c1;
         std::vector<bool>* out = &c2;
-        for (auto _ : st) {
+        for ([[maybe_unused]] auto _ : st) {
           benchmark::DoNotOptimize(in);
           benchmark::DoNotOptimize(out);
           auto first  = Aligned ? in->begin() : in->begin() + 4;
diff --git a/libcxx/test/benchmarks/algorithms/modifying/move_backward.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/move_backward.bench.cpp
index 0e6eea1b4d873..a5bfc75ec94e8 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/move_backward.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/move_backward.bench.cpp
@@ -61,7 +61,7 @@ int main(int argc, char** argv) {
 
         std::vector<bool>* in  = &c1;
         std::vector<bool>* out = &c2;
-        for (auto _ : st) {
+        for ([[maybe_unused]] auto _ : st) {
           benchmark::DoNotOptimize(in);
           benchmark::DoNotOptimize(out);
           auto last   = Aligned ? in->end() : in->end() - 4;

>From cbf29945a7ed7e9358b610e2fe01072360bcd92a Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Fri, 21 Feb 2025 12:27:48 -0500
Subject: [PATCH 06/15] Ensure uniqueness of elements when needed

---
 libcxx/test/benchmarks/GenerateInput.h                   | 9 +++++++++
 .../benchmarks/algorithms/modifying/remove.bench.cpp     | 4 ++--
 .../algorithms/modifying/remove_copy.bench.cpp           | 4 ++--
 .../algorithms/modifying/remove_copy_if.bench.cpp        | 4 ++--
 .../benchmarks/algorithms/modifying/remove_if.bench.cpp  | 4 ++--
 .../benchmarks/algorithms/modifying/replace.bench.cpp    | 8 ++++----
 .../benchmarks/algorithms/modifying/replace_if.bench.cpp | 8 ++++----
 .../benchmarks/algorithms/modifying/unique.bench.cpp     | 4 ++--
 .../algorithms/modifying/unique_copy.bench.cpp           | 4 ++--
 .../algorithms/modifying/unique_copy_pred.bench.cpp      | 4 ++--
 .../algorithms/modifying/unique_pred.bench.cpp           | 4 ++--
 11 files changed, 33 insertions(+), 24 deletions(-)

diff --git a/libcxx/test/benchmarks/GenerateInput.h b/libcxx/test/benchmarks/GenerateInput.h
index c87fd69162e9d..9f741a5d6c24c 100644
--- a/libcxx/test/benchmarks/GenerateInput.h
+++ b/libcxx/test/benchmarks/GenerateInput.h
@@ -204,4 +204,13 @@ struct Generate<std::string> {
   }
 };
 
+template <class T>
+T random_different_from(std::initializer_list<T> others) {
+  T value;
+  do {
+    value = Generate<T>::random();
+  } while (std::ranges::contains(others, value));
+  return value;
+}
+
 #endif // BENCHMARK_GENERATE_INPUT_H
diff --git a/libcxx/test/benchmarks/algorithms/modifying/remove.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/remove.bench.cpp
index adec1d2292bcf..1067ecd9e8795 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/remove.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/remove.bench.cpp
@@ -37,7 +37,7 @@ int main(int argc, char** argv) {
             using ValueType                 = typename Container::value_type;
             Container c[BatchSize];
             ValueType x = Generate<ValueType>::random();
-            ValueType y = Generate<ValueType>::random();
+            ValueType y = random_different_from({x});
             for (std::size_t i = 0; i != BatchSize; ++i) {
               c[i]      = Container(size);
               auto half = size / 2;
@@ -87,7 +87,7 @@ int main(int argc, char** argv) {
             using ValueType                 = typename Container::value_type;
             Container c[BatchSize];
             ValueType x    = Generate<ValueType>::random();
-            ValueType y    = Generate<ValueType>::random();
+            ValueType y    = random_different_from({x});
             auto alternate = [&](auto out, auto n) {
               for (std::size_t i = 0; i != n; ++i) {
                 *out++ = (i % 2 == 0 ? x : y);
diff --git a/libcxx/test/benchmarks/algorithms/modifying/remove_copy.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/remove_copy.bench.cpp
index af9994c07cc22..ba290e4765219 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/remove_copy.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/remove_copy.bench.cpp
@@ -35,7 +35,7 @@ int main(int argc, char** argv) {
             using ValueType        = typename Container::value_type;
             Container c;
             ValueType x = Generate<ValueType>::random();
-            ValueType y = Generate<ValueType>::random();
+            ValueType y = random_different_from({x});
             std::fill_n(std::back_inserter(c), size / 2, x);
             std::fill_n(std::back_inserter(c), size / 2, y);
 
@@ -72,7 +72,7 @@ int main(int argc, char** argv) {
             using ValueType        = typename Container::value_type;
             Container c;
             ValueType x = Generate<ValueType>::random();
-            ValueType y = Generate<ValueType>::random();
+            ValueType y = random_different_from({x});
             for (std::size_t i = 0; i != size; ++i) {
               c.push_back(i % 2 == 0 ? x : y);
             }
diff --git a/libcxx/test/benchmarks/algorithms/modifying/remove_copy_if.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/remove_copy_if.bench.cpp
index e6fa7a0c1ea79..942a79f939138 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/remove_copy_if.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/remove_copy_if.bench.cpp
@@ -35,7 +35,7 @@ int main(int argc, char** argv) {
             using ValueType        = typename Container::value_type;
             Container c;
             ValueType x = Generate<ValueType>::random();
-            ValueType y = Generate<ValueType>::random();
+            ValueType y = random_different_from({x});
             std::fill_n(std::back_inserter(c), size / 2, x);
             std::fill_n(std::back_inserter(c), size / 2, y);
 
@@ -75,7 +75,7 @@ int main(int argc, char** argv) {
             using ValueType        = typename Container::value_type;
             Container c;
             ValueType x = Generate<ValueType>::random();
-            ValueType y = Generate<ValueType>::random();
+            ValueType y = random_different_from({x});
             for (std::size_t i = 0; i != size; ++i) {
               c.push_back(i % 2 == 0 ? x : y);
             }
diff --git a/libcxx/test/benchmarks/algorithms/modifying/remove_if.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/remove_if.bench.cpp
index d5e185ef3ba9c..09f4b1495c897 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/remove_if.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/remove_if.bench.cpp
@@ -37,7 +37,7 @@ int main(int argc, char** argv) {
             using ValueType                 = typename Container::value_type;
             Container c[BatchSize];
             ValueType x = Generate<ValueType>::random();
-            ValueType y = Generate<ValueType>::random();
+            ValueType y = random_different_from({x});
             for (std::size_t i = 0; i != BatchSize; ++i) {
               c[i]      = Container(size);
               auto half = size / 2;
@@ -91,7 +91,7 @@ int main(int argc, char** argv) {
             using ValueType                 = typename Container::value_type;
             Container c[BatchSize];
             ValueType x    = Generate<ValueType>::random();
-            ValueType y    = Generate<ValueType>::random();
+            ValueType y    = random_different_from({x});
             auto alternate = [&](auto out, auto n) {
               for (std::size_t i = 0; i != n; ++i) {
                 *out++ = (i % 2 == 0 ? x : y);
diff --git a/libcxx/test/benchmarks/algorithms/modifying/replace.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/replace.bench.cpp
index e34f1e28c1459..e1bf5e20e99ea 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/replace.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/replace.bench.cpp
@@ -36,8 +36,8 @@ int main(int argc, char** argv) {
             using ValueType        = typename Container::value_type;
             Container c;
             ValueType x = Generate<ValueType>::random();
-            ValueType y = Generate<ValueType>::random();
-            ValueType z = Generate<ValueType>::random();
+            ValueType y = random_different_from({x});
+            ValueType z = random_different_from({x, y});
             std::fill_n(std::back_inserter(c), size / 2, x);
             std::fill_n(std::back_inserter(c), size / 2, y);
 
@@ -72,8 +72,8 @@ int main(int argc, char** argv) {
             using ValueType        = typename Container::value_type;
             Container c;
             ValueType x = Generate<ValueType>::random();
-            ValueType y = Generate<ValueType>::random();
-            ValueType z = Generate<ValueType>::random();
+            ValueType y = random_different_from({x});
+            ValueType z = random_different_from({x, y});
             for (std::size_t i = 0; i != size; ++i) {
               c.push_back(i % 2 == 0 ? x : y);
             }
diff --git a/libcxx/test/benchmarks/algorithms/modifying/replace_if.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/replace_if.bench.cpp
index 1a51d3da4fc89..d7eab24b6d411 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/replace_if.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/replace_if.bench.cpp
@@ -38,8 +38,8 @@ int main(int argc, char** argv) {
             using ValueType        = typename Container::value_type;
             Container c;
             ValueType x = Generate<ValueType>::random();
-            ValueType y = Generate<ValueType>::random();
-            ValueType z = Generate<ValueType>::random();
+            ValueType y = random_different_from({x});
+            ValueType z = random_different_from({x, y});
             std::fill_n(std::back_inserter(c), size / 2, x);
             std::fill_n(std::back_inserter(c), size / 2, y);
 
@@ -77,8 +77,8 @@ int main(int argc, char** argv) {
             using ValueType        = typename Container::value_type;
             Container c;
             ValueType x = Generate<ValueType>::random();
-            ValueType y = Generate<ValueType>::random();
-            ValueType z = Generate<ValueType>::random();
+            ValueType y = random_different_from({x});
+            ValueType z = random_different_from({x, y});
             for (std::size_t i = 0; i != size; ++i) {
               c.push_back(i % 2 == 0 ? x : y);
             }
diff --git a/libcxx/test/benchmarks/algorithms/modifying/unique.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/unique.bench.cpp
index 2a334447f953b..477f1b5622c3e 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/unique.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/unique.bench.cpp
@@ -37,7 +37,7 @@ int main(int argc, char** argv) {
             using ValueType                 = typename Container::value_type;
             Container c[BatchSize];
             ValueType x = Generate<ValueType>::random();
-            ValueType y = Generate<ValueType>::random();
+            ValueType y = random_different_from({x});
             for (std::size_t i = 0; i != BatchSize; ++i) {
               c[i]      = Container(size);
               auto half = size / 2;
@@ -86,7 +86,7 @@ int main(int argc, char** argv) {
             using ValueType                 = typename Container::value_type;
             Container c[BatchSize];
             ValueType x    = Generate<ValueType>::random();
-            ValueType y    = Generate<ValueType>::random();
+            ValueType y    = random_different_from({x});
             auto alternate = [&](auto out, auto n) {
               for (std::size_t i = 0; i != n; i += 2) {
                 *out++ = (i % 4 == 0 ? x : y);
diff --git a/libcxx/test/benchmarks/algorithms/modifying/unique_copy.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/unique_copy.bench.cpp
index a8bd2ed327c2b..247e7d9c6e497 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/unique_copy.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/unique_copy.bench.cpp
@@ -33,7 +33,7 @@ int main(int argc, char** argv) {
             using ValueType        = typename Container::value_type;
             Container c(size);
             ValueType x = Generate<ValueType>::random();
-            ValueType y = Generate<ValueType>::random();
+            ValueType y = random_different_from({x});
             auto half   = size / 2;
             std::fill_n(std::fill_n(c.begin(), half, x), half, y);
 
@@ -69,7 +69,7 @@ int main(int argc, char** argv) {
             using ValueType        = typename Container::value_type;
             Container c(size);
             ValueType x    = Generate<ValueType>::random();
-            ValueType y    = Generate<ValueType>::random();
+            ValueType y    = random_different_from({x});
             auto alternate = [&](auto out, auto n) {
               for (std::size_t i = 0; i != n; i += 2) {
                 *out++ = (i % 4 == 0 ? x : y);
diff --git a/libcxx/test/benchmarks/algorithms/modifying/unique_copy_pred.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/unique_copy_pred.bench.cpp
index 4d29e16ce9e1e..72f94c196360e 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/unique_copy_pred.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/unique_copy_pred.bench.cpp
@@ -35,7 +35,7 @@ int main(int argc, char** argv) {
             using ValueType        = typename Container::value_type;
             Container c(size);
             ValueType x = Generate<ValueType>::random();
-            ValueType y = Generate<ValueType>::random();
+            ValueType y = random_different_from({x});
             auto half   = size / 2;
             std::fill_n(std::fill_n(c.begin(), half, x), half, y);
 
@@ -77,7 +77,7 @@ int main(int argc, char** argv) {
             using ValueType        = typename Container::value_type;
             Container c(size);
             ValueType x    = Generate<ValueType>::random();
-            ValueType y    = Generate<ValueType>::random();
+            ValueType y    = random_different_from({x});
             auto alternate = [&](auto out, auto n) {
               for (std::size_t i = 0; i != n; i += 2) {
                 *out++ = (i % 4 == 0 ? x : y);
diff --git a/libcxx/test/benchmarks/algorithms/modifying/unique_pred.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/unique_pred.bench.cpp
index 25f87e022023b..a333c965cee8f 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/unique_pred.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/unique_pred.bench.cpp
@@ -37,7 +37,7 @@ int main(int argc, char** argv) {
             using ValueType                 = typename Container::value_type;
             Container c[BatchSize];
             ValueType x = Generate<ValueType>::random();
-            ValueType y = Generate<ValueType>::random();
+            ValueType y = random_different_from({x});
             for (std::size_t i = 0; i != BatchSize; ++i) {
               c[i]      = Container(size);
               auto half = size / 2;
@@ -92,7 +92,7 @@ int main(int argc, char** argv) {
             using ValueType                 = typename Container::value_type;
             Container c[BatchSize];
             ValueType x    = Generate<ValueType>::random();
-            ValueType y    = Generate<ValueType>::random();
+            ValueType y    = random_different_from({x});
             auto alternate = [&](auto out, auto n) {
               for (std::size_t i = 0; i != n; i += 2) {
                 *out++ = (i % 4 == 0 ? x : y);

>From 321e38d74df78d7e42c53e1584e3d1cc8e373bec Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Fri, 21 Feb 2025 16:38:03 -0500
Subject: [PATCH 07/15] C++20 friendly

---
 libcxx/test/benchmarks/GenerateInput.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libcxx/test/benchmarks/GenerateInput.h b/libcxx/test/benchmarks/GenerateInput.h
index 9f741a5d6c24c..9be76f55c2774 100644
--- a/libcxx/test/benchmarks/GenerateInput.h
+++ b/libcxx/test/benchmarks/GenerateInput.h
@@ -209,7 +209,7 @@ T random_different_from(std::initializer_list<T> others) {
   T value;
   do {
     value = Generate<T>::random();
-  } while (std::ranges::contains(others, value));
+  } while (std::find(others.begin(), others.end(), value) != others.end());
   return value;
 }
 

>From c850286e330abddf7abecdec63ba473ff3f591bb Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Tue, 25 Feb 2025 10:06:05 -0500
Subject: [PATCH 08/15] Always fill with the same value

---
 .../test/benchmarks/algorithms/modifying/fill.bench.cpp   | 8 ++------
 .../test/benchmarks/algorithms/modifying/fill_n.bench.cpp | 8 ++------
 2 files changed, 4 insertions(+), 12 deletions(-)

diff --git a/libcxx/test/benchmarks/algorithms/modifying/fill.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/fill.bench.cpp
index 79f6619e2977f..7b3534969b247 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/fill.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/fill.bench.cpp
@@ -32,15 +32,13 @@ int main(int argc, char** argv) {
             std::size_t const size = st.range(0);
             using ValueType        = typename Container::value_type;
             ValueType x            = Generate<ValueType>::random();
-            ValueType y            = Generate<ValueType>::random();
-            Container c(size, y);
+            Container c(size, x);
 
             for ([[maybe_unused]] auto _ : st) {
               benchmark::DoNotOptimize(c);
               benchmark::DoNotOptimize(x);
               fill(c.begin(), c.end(), x);
               benchmark::DoNotOptimize(c);
-              std::swap(x, y);
             }
           })
           ->Arg(32)
@@ -61,15 +59,13 @@ int main(int argc, char** argv) {
       benchmark::RegisterBenchmark(name, [fill](auto& st) {
         std::size_t const size = st.range(0);
         bool x                 = true;
-        bool y                 = false;
-        std::vector<bool> c(size, y);
+        std::vector<bool> c(size, x);
 
         for ([[maybe_unused]] auto _ : st) {
           benchmark::DoNotOptimize(c);
           benchmark::DoNotOptimize(x);
           fill(c.begin(), c.end(), x);
           benchmark::DoNotOptimize(c);
-          std::swap(x, y);
         }
       })->Range(64, 1 << 20);
     };
diff --git a/libcxx/test/benchmarks/algorithms/modifying/fill_n.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/fill_n.bench.cpp
index 505fbcbb2f442..700d109fdbc61 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/fill_n.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/fill_n.bench.cpp
@@ -32,15 +32,13 @@ int main(int argc, char** argv) {
             std::size_t const size = st.range(0);
             using ValueType        = typename Container::value_type;
             ValueType x            = Generate<ValueType>::random();
-            ValueType y            = Generate<ValueType>::random();
-            Container c(size, y);
+            Container c(size, x);
 
             for ([[maybe_unused]] auto _ : st) {
               benchmark::DoNotOptimize(c);
               benchmark::DoNotOptimize(x);
               fill_n(c.begin(), size, x);
               benchmark::DoNotOptimize(c);
-              std::swap(x, y);
             }
           })
           ->Arg(32)
@@ -61,15 +59,13 @@ int main(int argc, char** argv) {
       benchmark::RegisterBenchmark(name, [fill_n](auto& st) {
         std::size_t const size = st.range(0);
         bool x                 = true;
-        bool y                 = false;
-        std::vector<bool> c(size, y);
+        std::vector<bool> c(size, x);
 
         for ([[maybe_unused]] auto _ : st) {
           benchmark::DoNotOptimize(c);
           benchmark::DoNotOptimize(x);
           fill_n(c.begin(), size, x);
           benchmark::DoNotOptimize(c);
-          std::swap(x, y);
         }
       })->Range(64, 1 << 20);
     };

>From ffc5a7a668e60ca051ab516e978fcf21d19ce3cb Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Tue, 25 Feb 2025 10:08:40 -0500
Subject: [PATCH 09/15] Don't take references in predicates

---
 .../benchmarks/algorithms/modifying/remove_copy_if.bench.cpp  | 4 ++--
 .../test/benchmarks/algorithms/modifying/remove_if.bench.cpp  | 4 ++--
 .../test/benchmarks/algorithms/modifying/replace_if.bench.cpp | 4 ++--
 .../algorithms/modifying/transform.binary.bench.cpp           | 2 +-
 .../benchmarks/algorithms/modifying/transform.unary.bench.cpp | 2 +-
 .../algorithms/modifying/unique_copy_pred.bench.cpp           | 4 ++--
 .../benchmarks/algorithms/modifying/unique_pred.bench.cpp     | 4 ++--
 7 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/libcxx/test/benchmarks/algorithms/modifying/remove_copy_if.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/remove_copy_if.bench.cpp
index 942a79f939138..ca59f0fdb0338 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/remove_copy_if.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/remove_copy_if.bench.cpp
@@ -44,7 +44,7 @@ int main(int argc, char** argv) {
             for ([[maybe_unused]] auto _ : st) {
               benchmark::DoNotOptimize(c);
               benchmark::DoNotOptimize(out);
-              auto pred = [&x](auto& element) {
+              auto pred = [&x](auto element) {
                 benchmark::DoNotOptimize(element);
                 return element == x;
               };
@@ -85,7 +85,7 @@ int main(int argc, char** argv) {
             for ([[maybe_unused]] auto _ : st) {
               benchmark::DoNotOptimize(c);
               benchmark::DoNotOptimize(out);
-              auto pred = [&](auto& element) {
+              auto pred = [&](auto element) {
                 benchmark::DoNotOptimize(element);
                 return element == x;
               };
diff --git a/libcxx/test/benchmarks/algorithms/modifying/remove_if.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/remove_if.bench.cpp
index 09f4b1495c897..23ea0a4824242 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/remove_if.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/remove_if.bench.cpp
@@ -44,7 +44,7 @@ int main(int argc, char** argv) {
               std::fill_n(std::fill_n(c[i].begin(), half, x), half, y);
             }
 
-            auto pred = [&](auto& element) {
+            auto pred = [&](auto element) {
               benchmark::DoNotOptimize(element);
               return element == x;
             };
@@ -102,7 +102,7 @@ int main(int argc, char** argv) {
               alternate(c[i].begin(), size);
             }
 
-            auto pred = [&](auto& element) {
+            auto pred = [&](auto element) {
               benchmark::DoNotOptimize(element);
               return element == x;
             };
diff --git a/libcxx/test/benchmarks/algorithms/modifying/replace_if.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/replace_if.bench.cpp
index d7eab24b6d411..ecd46dae01089 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/replace_if.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/replace_if.bench.cpp
@@ -46,7 +46,7 @@ int main(int argc, char** argv) {
             for ([[maybe_unused]] auto _ : st) {
               benchmark::DoNotOptimize(c);
               benchmark::DoNotOptimize(z);
-              auto pred = [&x](auto& element) {
+              auto pred = [&x](auto element) {
                 benchmark::DoNotOptimize(element);
                 return element == x;
               };
@@ -86,7 +86,7 @@ int main(int argc, char** argv) {
             for ([[maybe_unused]] auto _ : st) {
               benchmark::DoNotOptimize(c);
               benchmark::DoNotOptimize(z);
-              auto pred = [&x](auto& element) {
+              auto pred = [&x](auto element) {
                 benchmark::DoNotOptimize(element);
                 return element == x;
               };
diff --git a/libcxx/test/benchmarks/algorithms/modifying/transform.binary.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/transform.binary.bench.cpp
index dd5e3783e6f13..cb6cfceee5bc4 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/transform.binary.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/transform.binary.bench.cpp
@@ -38,7 +38,7 @@ int main(int argc, char** argv) {
 
             std::vector<ValueType> out(size);
 
-            auto f = [](auto& x, auto& y) {
+            auto f = [](auto x, auto y) {
               benchmark::DoNotOptimize(x);
               benchmark::DoNotOptimize(y);
               return x + y;
diff --git a/libcxx/test/benchmarks/algorithms/modifying/transform.unary.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/transform.unary.bench.cpp
index e36a5f96c4e6f..db02fb67556b9 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/transform.unary.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/transform.unary.bench.cpp
@@ -35,7 +35,7 @@ int main(int argc, char** argv) {
 
             std::vector<ValueType> out(size);
 
-            auto f = [](auto& element) {
+            auto f = [](auto element) {
               benchmark::DoNotOptimize(element);
               return element;
             };
diff --git a/libcxx/test/benchmarks/algorithms/modifying/unique_copy_pred.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/unique_copy_pred.bench.cpp
index 72f94c196360e..91031ef884611 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/unique_copy_pred.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/unique_copy_pred.bench.cpp
@@ -41,7 +41,7 @@ int main(int argc, char** argv) {
 
             std::vector<ValueType> out(size);
 
-            auto pred = [](auto& a, auto& b) {
+            auto pred = [](auto a, auto b) {
               benchmark::DoNotOptimize(a);
               benchmark::DoNotOptimize(b);
               return a == b;
@@ -88,7 +88,7 @@ int main(int argc, char** argv) {
 
             std::vector<ValueType> out(size);
 
-            auto pred = [](auto& a, auto& b) {
+            auto pred = [](auto a, auto b) {
               benchmark::DoNotOptimize(a);
               benchmark::DoNotOptimize(b);
               return a == b;
diff --git a/libcxx/test/benchmarks/algorithms/modifying/unique_pred.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/unique_pred.bench.cpp
index a333c965cee8f..1b0ea26c6b7f5 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/unique_pred.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/unique_pred.bench.cpp
@@ -44,7 +44,7 @@ int main(int argc, char** argv) {
               std::fill_n(std::fill_n(c[i].begin(), half, x), half, y);
             }
 
-            auto pred = [](auto& a, auto& b) {
+            auto pred = [](auto a, auto b) {
               benchmark::DoNotOptimize(a);
               benchmark::DoNotOptimize(b);
               return a == b;
@@ -104,7 +104,7 @@ int main(int argc, char** argv) {
               alternate(c[i].begin(), size);
             }
 
-            auto pred = [](auto& a, auto& b) {
+            auto pred = [](auto a, auto b) {
               benchmark::DoNotOptimize(a);
               benchmark::DoNotOptimize(b);
               return a == b;

>From 91bf6bde167b6d1fa714e8eadc88a4b6681a7b06 Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Tue, 25 Feb 2025 10:28:26 -0500
Subject: [PATCH 10/15] Merge predicated version of the algorithms

---
 .../algorithms/modifying/remove.bench.cpp     |  34 ++++-
 .../modifying/remove_copy.bench.cpp           |  34 ++++-
 .../modifying/remove_copy_if.bench.cpp        | 112 --------------
 .../algorithms/modifying/remove_if.bench.cpp  | 140 -----------------
 .../algorithms/modifying/replace.bench.cpp    |  34 ++++-
 .../algorithms/modifying/replace_if.bench.cpp | 114 --------------
 .../algorithms/modifying/unique.bench.cpp     |  34 ++++-
 .../modifying/unique_copy.bench.cpp           |  34 ++++-
 .../modifying/unique_copy_pred.bench.cpp      | 120 ---------------
 .../modifying/unique_pred.bench.cpp           | 143 ------------------
 10 files changed, 163 insertions(+), 636 deletions(-)
 delete mode 100644 libcxx/test/benchmarks/algorithms/modifying/remove_copy_if.bench.cpp
 delete mode 100644 libcxx/test/benchmarks/algorithms/modifying/remove_if.bench.cpp
 delete mode 100644 libcxx/test/benchmarks/algorithms/modifying/replace_if.bench.cpp
 delete mode 100644 libcxx/test/benchmarks/algorithms/modifying/unique_copy_pred.bench.cpp
 delete mode 100644 libcxx/test/benchmarks/algorithms/modifying/unique_pred.bench.cpp

diff --git a/libcxx/test/benchmarks/algorithms/modifying/remove.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/remove.bench.cpp
index 1067ecd9e8795..07e8f834a8639 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/remove.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/remove.bench.cpp
@@ -20,9 +20,21 @@
 #include "../../GenerateInput.h"
 
 int main(int argc, char** argv) {
-  auto std_remove = [](auto first, auto last, auto const& value) { return std::remove(first, last, value); };
+  auto std_remove    = [](auto first, auto last, auto const& value) { return std::remove(first, last, value); };
+  auto std_remove_if = [](auto first, auto last, auto const& value) {
+    return std::remove_if(first, last, [&](auto element) {
+      benchmark::DoNotOptimize(element);
+      return element == value;
+    });
+  };
+  auto ranges_remove_if = [](auto first, auto last, auto const& value) {
+    return std::ranges::remove_if(first, last, [&](auto element) {
+      benchmark::DoNotOptimize(element);
+      return element == value;
+    });
+  };
 
-  // Benchmark {std,ranges}::remove on a sequence of the form xxxxxxxxxxyyyyyyyyyy
+  // Benchmark {std,ranges}::{remove,remove_if} on a sequence of the form xxxxxxxxxxyyyyyyyyyy
   // where we remove the prefix of x's from the sequence.
   //
   // We perform this benchmark in a batch because we need to restore the
@@ -64,12 +76,21 @@ int main(int argc, char** argv) {
           ->Arg(1024)
           ->Arg(8192);
     };
+    // {std,ranges}::remove
     bm.operator()<std::vector<int>>("std::remove(vector<int>) (prefix)", std_remove);
     bm.operator()<std::deque<int>>("std::remove(deque<int>) (prefix)", std_remove);
     bm.operator()<std::list<int>>("std::remove(list<int>) (prefix)", std_remove);
     bm.operator()<std::vector<int>>("rng::remove(vector<int>) (prefix)", std::ranges::remove);
     bm.operator()<std::deque<int>>("rng::remove(deque<int>) (prefix)", std::ranges::remove);
     bm.operator()<std::list<int>>("rng::remove(list<int>) (prefix)", std::ranges::remove);
+
+    // {std,ranges}::remove_if
+    bm.operator()<std::vector<int>>("std::remove_if(vector<int>) (prefix)", std_remove_if);
+    bm.operator()<std::deque<int>>("std::remove_if(deque<int>) (prefix)", std_remove_if);
+    bm.operator()<std::list<int>>("std::remove_if(list<int>) (prefix)", std_remove_if);
+    bm.operator()<std::vector<int>>("rng::remove_if(vector<int>) (prefix)", ranges_remove_if);
+    bm.operator()<std::deque<int>>("rng::remove_if(deque<int>) (prefix)", ranges_remove_if);
+    bm.operator()<std::list<int>>("rng::remove_if(list<int>) (prefix)", ranges_remove_if);
   }
 
   // Benchmark {std,ranges}::remove on a sequence of the form xyxyxyxyxyxyxyxyxyxy
@@ -117,12 +138,21 @@ int main(int argc, char** argv) {
           ->Arg(1024)
           ->Arg(8192);
     };
+    // {std,ranges}::remove
     bm.operator()<std::vector<int>>("std::remove(vector<int>) (sprinkled)", std_remove);
     bm.operator()<std::deque<int>>("std::remove(deque<int>) (sprinkled)", std_remove);
     bm.operator()<std::list<int>>("std::remove(list<int>) (sprinkled)", std_remove);
     bm.operator()<std::vector<int>>("rng::remove(vector<int>) (sprinkled)", std::ranges::remove);
     bm.operator()<std::deque<int>>("rng::remove(deque<int>) (sprinkled)", std::ranges::remove);
     bm.operator()<std::list<int>>("rng::remove(list<int>) (sprinkled)", std::ranges::remove);
+
+    // {std,ranges}::remove_if
+    bm.operator()<std::vector<int>>("std::remove_if(vector<int>) (sprinkled)", std_remove_if);
+    bm.operator()<std::deque<int>>("std::remove_if(deque<int>) (sprinkled)", std_remove_if);
+    bm.operator()<std::list<int>>("std::remove_if(list<int>) (sprinkled)", std_remove_if);
+    bm.operator()<std::vector<int>>("rng::remove_if(vector<int>) (sprinkled)", ranges_remove_if);
+    bm.operator()<std::deque<int>>("rng::remove_if(deque<int>) (sprinkled)", ranges_remove_if);
+    bm.operator()<std::list<int>>("rng::remove_if(list<int>) (sprinkled)", ranges_remove_if);
   }
 
   benchmark::Initialize(&argc, argv);
diff --git a/libcxx/test/benchmarks/algorithms/modifying/remove_copy.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/remove_copy.bench.cpp
index ba290e4765219..b0bc58e8a7a2f 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/remove_copy.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/remove_copy.bench.cpp
@@ -23,8 +23,20 @@ int main(int argc, char** argv) {
   auto std_remove_copy = [](auto first, auto last, auto out, auto const& value) {
     return std::remove_copy(first, last, out, value);
   };
+  auto std_remove_copy_if = [](auto first, auto last, auto out, auto const& value) {
+    return std::remove_copy_if(first, last, out, [&](auto element) {
+      benchmark::DoNotOptimize(element);
+      return element == value;
+    });
+  };
+  auto ranges_remove_copy_if = [](auto first, auto last, auto out, auto const& value) {
+    return std::ranges::remove_copy_if(first, last, out, [&](auto element) {
+      benchmark::DoNotOptimize(element);
+      return element == value;
+    });
+  };
 
-  // Benchmark {std,ranges}::remove_copy on a sequence of the form xxxxxxxxxxyyyyyyyyyy
+  // Benchmark {std,ranges}::{remove_copy,remove_copy_if} on a sequence of the form xxxxxxxxxxyyyyyyyyyy
   // where we remove the prefix of x's from the sequence.
   {
     auto bm = []<class Container>(std::string name, auto remove_copy) {
@@ -53,15 +65,24 @@ int main(int argc, char** argv) {
           ->Arg(1024)
           ->Arg(8192);
     };
+    // {std,ranges}::remove_copy
     bm.operator()<std::vector<int>>("std::remove_copy(vector<int>) (prefix)", std_remove_copy);
     bm.operator()<std::deque<int>>("std::remove_copy(deque<int>) (prefix)", std_remove_copy);
     bm.operator()<std::list<int>>("std::remove_copy(list<int>) (prefix)", std_remove_copy);
     bm.operator()<std::vector<int>>("rng::remove_copy(vector<int>) (prefix)", std::ranges::remove_copy);
     bm.operator()<std::deque<int>>("rng::remove_copy(deque<int>) (prefix)", std::ranges::remove_copy);
     bm.operator()<std::list<int>>("rng::remove_copy(list<int>) (prefix)", std::ranges::remove_copy);
+
+    // {std,ranges}::remove_copy_if
+    bm.operator()<std::vector<int>>("std::remove_copy_if(vector<int>) (prefix)", std_remove_copy_if);
+    bm.operator()<std::deque<int>>("std::remove_copy_if(deque<int>) (prefix)", std_remove_copy_if);
+    bm.operator()<std::list<int>>("std::remove_copy_if(list<int>) (prefix)", std_remove_copy_if);
+    bm.operator()<std::vector<int>>("rng::remove_copy_if(vector<int>) (prefix)", ranges_remove_copy_if);
+    bm.operator()<std::deque<int>>("rng::remove_copy_if(deque<int>) (prefix)", ranges_remove_copy_if);
+    bm.operator()<std::list<int>>("rng::remove_copy_if(list<int>) (prefix)", ranges_remove_copy_if);
   }
 
-  // Benchmark {std,ranges}::remove_copy on a sequence of the form xyxyxyxyxyxyxyxyxyxy
+  // Benchmark {std,ranges}::{remove_copy,remove_copy_if} on a sequence of the form xyxyxyxyxyxyxyxyxyxy
   // where we remove the x's from the sequence.
   {
     auto bm = []<class Container>(std::string name, auto remove_copy) {
@@ -91,12 +112,21 @@ int main(int argc, char** argv) {
           ->Arg(1024)
           ->Arg(8192);
     };
+    // {std,ranges}::remove_copy
     bm.operator()<std::vector<int>>("std::remove_copy(vector<int>) (sprinkled)", std_remove_copy);
     bm.operator()<std::deque<int>>("std::remove_copy(deque<int>) (sprinkled)", std_remove_copy);
     bm.operator()<std::list<int>>("std::remove_copy(list<int>) (sprinkled)", std_remove_copy);
     bm.operator()<std::vector<int>>("rng::remove_copy(vector<int>) (sprinkled)", std::ranges::remove_copy);
     bm.operator()<std::deque<int>>("rng::remove_copy(deque<int>) (sprinkled)", std::ranges::remove_copy);
     bm.operator()<std::list<int>>("rng::remove_copy(list<int>) (sprinkled)", std::ranges::remove_copy);
+
+    // {std,ranges}::remove_copy_if
+    bm.operator()<std::vector<int>>("std::remove_copy_if(vector<int>) (sprinkled)", std_remove_copy_if);
+    bm.operator()<std::deque<int>>("std::remove_copy_if(deque<int>) (sprinkled)", std_remove_copy_if);
+    bm.operator()<std::list<int>>("std::remove_copy_if(list<int>) (sprinkled)", std_remove_copy_if);
+    bm.operator()<std::vector<int>>("rng::remove_copy_if(vector<int>) (sprinkled)", ranges_remove_copy_if);
+    bm.operator()<std::deque<int>>("rng::remove_copy_if(deque<int>) (sprinkled)", ranges_remove_copy_if);
+    bm.operator()<std::list<int>>("rng::remove_copy_if(list<int>) (sprinkled)", ranges_remove_copy_if);
   }
 
   benchmark::Initialize(&argc, argv);
diff --git a/libcxx/test/benchmarks/algorithms/modifying/remove_copy_if.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/remove_copy_if.bench.cpp
deleted file mode 100644
index ca59f0fdb0338..0000000000000
--- a/libcxx/test/benchmarks/algorithms/modifying/remove_copy_if.bench.cpp
+++ /dev/null
@@ -1,112 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++03, c++11, c++14, c++17
-
-#include <algorithm>
-#include <cstddef>
-#include <deque>
-#include <iterator>
-#include <list>
-#include <string>
-#include <vector>
-
-#include "benchmark/benchmark.h"
-#include "../../GenerateInput.h"
-
-int main(int argc, char** argv) {
-  auto std_remove_copy_if = [](auto first, auto last, auto out, auto pred) {
-    return std::remove_copy_if(first, last, out, pred);
-  };
-
-  // Benchmark {std,ranges}::remove_copy_if on a sequence of the form xxxxxxxxxxyyyyyyyyyy
-  // where we remove the prefix of x's from the sequence.
-  {
-    auto bm = []<class Container>(std::string name, auto remove_copy_if) {
-      benchmark::RegisterBenchmark(
-          name,
-          [remove_copy_if](auto& st) {
-            std::size_t const size = st.range(0);
-            using ValueType        = typename Container::value_type;
-            Container c;
-            ValueType x = Generate<ValueType>::random();
-            ValueType y = random_different_from({x});
-            std::fill_n(std::back_inserter(c), size / 2, x);
-            std::fill_n(std::back_inserter(c), size / 2, y);
-
-            std::vector<ValueType> out(size);
-
-            for ([[maybe_unused]] auto _ : st) {
-              benchmark::DoNotOptimize(c);
-              benchmark::DoNotOptimize(out);
-              auto pred = [&x](auto element) {
-                benchmark::DoNotOptimize(element);
-                return element == x;
-              };
-              auto result = remove_copy_if(c.begin(), c.end(), out.begin(), pred);
-              benchmark::DoNotOptimize(result);
-            }
-          })
-          ->Arg(32)
-          ->Arg(1024)
-          ->Arg(8192);
-    };
-    bm.operator()<std::vector<int>>("std::remove_copy_if(vector<int>) (prefix)", std_remove_copy_if);
-    bm.operator()<std::deque<int>>("std::remove_copy_if(deque<int>) (prefix)", std_remove_copy_if);
-    bm.operator()<std::list<int>>("std::remove_copy_if(list<int>) (prefix)", std_remove_copy_if);
-    bm.operator()<std::vector<int>>("rng::remove_copy_if(vector<int>) (prefix)", std::ranges::remove_copy_if);
-    bm.operator()<std::deque<int>>("rng::remove_copy_if(deque<int>) (prefix)", std::ranges::remove_copy_if);
-    bm.operator()<std::list<int>>("rng::remove_copy_if(list<int>) (prefix)", std::ranges::remove_copy_if);
-  }
-
-  // Benchmark {std,ranges}::remove_copy_if on a sequence of the form xyxyxyxyxyxyxyxyxyxy
-  // where we remove the x's from the sequence.
-  {
-    auto bm = []<class Container>(std::string name, auto remove_copy_if) {
-      benchmark::RegisterBenchmark(
-          name,
-          [remove_copy_if](auto& st) {
-            std::size_t const size = st.range(0);
-            using ValueType        = typename Container::value_type;
-            Container c;
-            ValueType x = Generate<ValueType>::random();
-            ValueType y = random_different_from({x});
-            for (std::size_t i = 0; i != size; ++i) {
-              c.push_back(i % 2 == 0 ? x : y);
-            }
-
-            std::vector<ValueType> out(size);
-
-            for ([[maybe_unused]] auto _ : st) {
-              benchmark::DoNotOptimize(c);
-              benchmark::DoNotOptimize(out);
-              auto pred = [&](auto element) {
-                benchmark::DoNotOptimize(element);
-                return element == x;
-              };
-              auto result = remove_copy_if(c.begin(), c.end(), out.begin(), pred);
-              benchmark::DoNotOptimize(result);
-            }
-          })
-          ->Arg(32)
-          ->Arg(1024)
-          ->Arg(8192);
-    };
-    bm.operator()<std::vector<int>>("std::remove_copy_if(vector<int>) (sprinkled)", std_remove_copy_if);
-    bm.operator()<std::deque<int>>("std::remove_copy_if(deque<int>) (sprinkled)", std_remove_copy_if);
-    bm.operator()<std::list<int>>("std::remove_copy_if(list<int>) (sprinkled)", std_remove_copy_if);
-    bm.operator()<std::vector<int>>("rng::remove_copy_if(vector<int>) (sprinkled)", std::ranges::remove_copy_if);
-    bm.operator()<std::deque<int>>("rng::remove_copy_if(deque<int>) (sprinkled)", std::ranges::remove_copy_if);
-    bm.operator()<std::list<int>>("rng::remove_copy_if(list<int>) (sprinkled)", std::ranges::remove_copy_if);
-  }
-
-  benchmark::Initialize(&argc, argv);
-  benchmark::RunSpecifiedBenchmarks();
-  benchmark::Shutdown();
-  return 0;
-}
diff --git a/libcxx/test/benchmarks/algorithms/modifying/remove_if.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/remove_if.bench.cpp
deleted file mode 100644
index 23ea0a4824242..0000000000000
--- a/libcxx/test/benchmarks/algorithms/modifying/remove_if.bench.cpp
+++ /dev/null
@@ -1,140 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++03, c++11, c++14, c++17
-
-#include <algorithm>
-#include <cstddef>
-#include <deque>
-#include <iterator>
-#include <list>
-#include <string>
-#include <vector>
-
-#include "benchmark/benchmark.h"
-#include "../../GenerateInput.h"
-
-int main(int argc, char** argv) {
-  auto std_remove_if = [](auto first, auto last, auto pred) { return std::remove_if(first, last, pred); };
-
-  // Benchmark {std,ranges}::remove_if on a sequence of the form xxxxxxxxxxyyyyyyyyyy
-  // where we remove the prefix of x's from the sequence.
-  //
-  // We perform this benchmark in a batch because we need to restore the
-  // state of the container after the operation.
-  {
-    auto bm = []<class Container>(std::string name, auto remove_if) {
-      benchmark::RegisterBenchmark(
-          name,
-          [remove_if](auto& st) {
-            std::size_t const size          = st.range(0);
-            constexpr std::size_t BatchSize = 10;
-            using ValueType                 = typename Container::value_type;
-            Container c[BatchSize];
-            ValueType x = Generate<ValueType>::random();
-            ValueType y = random_different_from({x});
-            for (std::size_t i = 0; i != BatchSize; ++i) {
-              c[i]      = Container(size);
-              auto half = size / 2;
-              std::fill_n(std::fill_n(c[i].begin(), half, x), half, y);
-            }
-
-            auto pred = [&](auto element) {
-              benchmark::DoNotOptimize(element);
-              return element == x;
-            };
-
-            while (st.KeepRunningBatch(BatchSize)) {
-              for (std::size_t i = 0; i != BatchSize; ++i) {
-                benchmark::DoNotOptimize(c[i]);
-                auto result = remove_if(c[i].begin(), c[i].end(), pred);
-                benchmark::DoNotOptimize(result);
-              }
-
-              st.PauseTiming();
-              for (std::size_t i = 0; i != BatchSize; ++i) {
-                auto half = size / 2;
-                std::fill_n(std::fill_n(c[i].begin(), half, x), half, y);
-              }
-              st.ResumeTiming();
-            }
-          })
-          ->Arg(32)
-          ->Arg(1024)
-          ->Arg(8192);
-    };
-    bm.operator()<std::vector<int>>("std::remove_if(vector<int>) (prefix)", std_remove_if);
-    bm.operator()<std::deque<int>>("std::remove_if(deque<int>) (prefix)", std_remove_if);
-    bm.operator()<std::list<int>>("std::remove_if(list<int>) (prefix)", std_remove_if);
-    bm.operator()<std::vector<int>>("rng::remove_if(vector<int>) (prefix)", std::ranges::remove_if);
-    bm.operator()<std::deque<int>>("rng::remove_if(deque<int>) (prefix)", std::ranges::remove_if);
-    bm.operator()<std::list<int>>("rng::remove_if(list<int>) (prefix)", std::ranges::remove_if);
-  }
-
-  // Benchmark {std,ranges}::remove_if on a sequence of the form xyxyxyxyxyxyxyxyxyxy
-  // where we remove the x's from the sequence.
-  //
-  // We perform this benchmark in a batch because we need to restore the
-  // state of the container after the operation.
-  {
-    auto bm = []<class Container>(std::string name, auto remove_if) {
-      benchmark::RegisterBenchmark(
-          name,
-          [remove_if](auto& st) {
-            std::size_t const size          = st.range(0);
-            constexpr std::size_t BatchSize = 10;
-            using ValueType                 = typename Container::value_type;
-            Container c[BatchSize];
-            ValueType x    = Generate<ValueType>::random();
-            ValueType y    = random_different_from({x});
-            auto alternate = [&](auto out, auto n) {
-              for (std::size_t i = 0; i != n; ++i) {
-                *out++ = (i % 2 == 0 ? x : y);
-              }
-            };
-            for (std::size_t i = 0; i != BatchSize; ++i) {
-              c[i] = Container(size);
-              alternate(c[i].begin(), size);
-            }
-
-            auto pred = [&](auto element) {
-              benchmark::DoNotOptimize(element);
-              return element == x;
-            };
-
-            while (st.KeepRunningBatch(BatchSize)) {
-              for (std::size_t i = 0; i != BatchSize; ++i) {
-                benchmark::DoNotOptimize(c[i]);
-                auto result = remove_if(c[i].begin(), c[i].end(), pred);
-                benchmark::DoNotOptimize(result);
-              }
-
-              st.PauseTiming();
-              for (std::size_t i = 0; i != BatchSize; ++i) {
-                alternate(c[i].begin(), size);
-              }
-              st.ResumeTiming();
-            }
-          })
-          ->Arg(32)
-          ->Arg(1024)
-          ->Arg(8192);
-    };
-    bm.operator()<std::vector<int>>("std::remove_if(vector<int>) (sprinkled)", std_remove_if);
-    bm.operator()<std::deque<int>>("std::remove_if(deque<int>) (sprinkled)", std_remove_if);
-    bm.operator()<std::list<int>>("std::remove_if(list<int>) (sprinkled)", std_remove_if);
-    bm.operator()<std::vector<int>>("rng::remove_if(vector<int>) (sprinkled)", std::ranges::remove_if);
-    bm.operator()<std::deque<int>>("rng::remove_if(deque<int>) (sprinkled)", std::ranges::remove_if);
-    bm.operator()<std::list<int>>("rng::remove_if(list<int>) (sprinkled)", std::ranges::remove_if);
-  }
-
-  benchmark::Initialize(&argc, argv);
-  benchmark::RunSpecifiedBenchmarks();
-  benchmark::Shutdown();
-  return 0;
-}
diff --git a/libcxx/test/benchmarks/algorithms/modifying/replace.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/replace.bench.cpp
index e1bf5e20e99ea..5df7aa1fbbc04 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/replace.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/replace.bench.cpp
@@ -20,7 +20,21 @@
 #include "../../GenerateInput.h"
 
 int main(int argc, char** argv) {
-  auto std_replace = [](auto first, auto last, auto old, auto new_) { return std::replace(first, last, old, new_); };
+  auto std_replace    = [](auto first, auto last, auto old, auto new_) { return std::replace(first, last, old, new_); };
+  auto std_replace_if = [](auto first, auto last, auto old, auto new_) {
+    auto pred = [&](auto element) {
+      benchmark::DoNotOptimize(element);
+      return element == old;
+    };
+    return std::replace_if(first, last, pred, new_);
+  };
+  auto ranges_replace_if = [](auto first, auto last, auto old, auto new_) {
+    auto pred = [&](auto element) {
+      benchmark::DoNotOptimize(element);
+      return element == old;
+    };
+    return std::ranges::replace_if(first, last, pred, new_);
+  };
 
   // Create a sequence of the form xxxxxxxxxxyyyyyyyyyy, replace
   // into zzzzzzzzzzzyyyyyyyyyy and then back.
@@ -54,12 +68,21 @@ int main(int argc, char** argv) {
           ->Arg(1024)
           ->Arg(8192);
     };
+    // {std,ranges}::replace
     bm.operator()<std::vector<int>>("std::replace(vector<int>) (prefix)", std_replace);
     bm.operator()<std::deque<int>>("std::replace(deque<int>) (prefix)", std_replace);
     bm.operator()<std::list<int>>("std::replace(list<int>) (prefix)", std_replace);
     bm.operator()<std::vector<int>>("rng::replace(vector<int>) (prefix)", std::ranges::replace);
     bm.operator()<std::deque<int>>("rng::replace(deque<int>) (prefix)", std::ranges::replace);
     bm.operator()<std::list<int>>("rng::replace(list<int>) (prefix)", std::ranges::replace);
+
+    // {std,ranges}::replace_if
+    bm.operator()<std::vector<int>>("std::replace_if(vector<int>) (prefix)", std_replace_if);
+    bm.operator()<std::deque<int>>("std::replace_if(deque<int>) (prefix)", std_replace_if);
+    bm.operator()<std::list<int>>("std::replace_if(list<int>) (prefix)", std_replace_if);
+    bm.operator()<std::vector<int>>("rng::replace_if(vector<int>) (prefix)", ranges_replace_if);
+    bm.operator()<std::deque<int>>("rng::replace_if(deque<int>) (prefix)", ranges_replace_if);
+    bm.operator()<std::list<int>>("rng::replace_if(list<int>) (prefix)", ranges_replace_if);
   }
 
   // Sprinkle elements to replace inside the range, like xyxyxyxyxyxyxyxyxyxy.
@@ -91,12 +114,21 @@ int main(int argc, char** argv) {
           ->Arg(1024)
           ->Arg(8192);
     };
+    // {std,ranges}::replace
     bm.operator()<std::vector<int>>("std::replace(vector<int>) (sprinkled)", std_replace);
     bm.operator()<std::deque<int>>("std::replace(deque<int>) (sprinkled)", std_replace);
     bm.operator()<std::list<int>>("std::replace(list<int>) (sprinkled)", std_replace);
     bm.operator()<std::vector<int>>("rng::replace(vector<int>) (sprinkled)", std::ranges::replace);
     bm.operator()<std::deque<int>>("rng::replace(deque<int>) (sprinkled)", std::ranges::replace);
     bm.operator()<std::list<int>>("rng::replace(list<int>) (sprinkled)", std::ranges::replace);
+
+    // {std,ranges}::replace_if
+    bm.operator()<std::vector<int>>("std::replace_if(vector<int>) (sprinkled)", std_replace_if);
+    bm.operator()<std::deque<int>>("std::replace_if(deque<int>) (sprinkled)", std_replace_if);
+    bm.operator()<std::list<int>>("std::replace_if(list<int>) (sprinkled)", std_replace_if);
+    bm.operator()<std::vector<int>>("rng::replace_if(vector<int>) (sprinkled)", ranges_replace_if);
+    bm.operator()<std::deque<int>>("rng::replace_if(deque<int>) (sprinkled)", ranges_replace_if);
+    bm.operator()<std::list<int>>("rng::replace_if(list<int>) (sprinkled)", ranges_replace_if);
   }
 
   benchmark::Initialize(&argc, argv);
diff --git a/libcxx/test/benchmarks/algorithms/modifying/replace_if.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/replace_if.bench.cpp
deleted file mode 100644
index ecd46dae01089..0000000000000
--- a/libcxx/test/benchmarks/algorithms/modifying/replace_if.bench.cpp
+++ /dev/null
@@ -1,114 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++03, c++11, c++14, c++17
-
-#include <algorithm>
-#include <cstddef>
-#include <deque>
-#include <iterator>
-#include <list>
-#include <string>
-#include <vector>
-
-#include "benchmark/benchmark.h"
-#include "../../GenerateInput.h"
-
-int main(int argc, char** argv) {
-  auto std_replace_if = [](auto first, auto last, auto pred, auto new_) {
-    return std::replace_if(first, last, pred, new_);
-  };
-
-  // Benchmark {std,ranges}::replace_if on a sequence of the form xxxxxxxxxxyyyyyyyyyy
-  // where we replace into zzzzzzzzzzzyyyyyyyyyy and then back.
-  //
-  // This measures the performance of replace_if() when replacing a large
-  // contiguous sequence of equal values.
-  {
-    auto bm = []<class Container>(std::string name, auto replace_if) {
-      benchmark::RegisterBenchmark(
-          name,
-          [replace_if](auto& st) {
-            std::size_t const size = st.range(0);
-            using ValueType        = typename Container::value_type;
-            Container c;
-            ValueType x = Generate<ValueType>::random();
-            ValueType y = random_different_from({x});
-            ValueType z = random_different_from({x, y});
-            std::fill_n(std::back_inserter(c), size / 2, x);
-            std::fill_n(std::back_inserter(c), size / 2, y);
-
-            for ([[maybe_unused]] auto _ : st) {
-              benchmark::DoNotOptimize(c);
-              benchmark::DoNotOptimize(z);
-              auto pred = [&x](auto element) {
-                benchmark::DoNotOptimize(element);
-                return element == x;
-              };
-              replace_if(c.begin(), c.end(), pred, z);
-              benchmark::DoNotOptimize(c);
-              std::swap(x, z);
-            }
-          })
-          ->Arg(32)
-          ->Arg(1024)
-          ->Arg(8192);
-    };
-    bm.operator()<std::vector<int>>("std::replace_if(vector<int>) (prefix)", std_replace_if);
-    bm.operator()<std::deque<int>>("std::replace_if(deque<int>) (prefix)", std_replace_if);
-    bm.operator()<std::list<int>>("std::replace_if(list<int>) (prefix)", std_replace_if);
-    bm.operator()<std::vector<int>>("rng::replace_if(vector<int>) (prefix)", std::ranges::replace_if);
-    bm.operator()<std::deque<int>>("rng::replace_if(deque<int>) (prefix)", std::ranges::replace_if);
-    bm.operator()<std::list<int>>("rng::replace_if(list<int>) (prefix)", std::ranges::replace_if);
-  }
-
-  // Sprinkle elements to replace inside the range, like xyxyxyxyxyxyxyxyxyxy.
-  {
-    auto bm = []<class Container>(std::string name, auto replace_if) {
-      benchmark::RegisterBenchmark(
-          name,
-          [replace_if](auto& st) {
-            std::size_t const size = st.range(0);
-            using ValueType        = typename Container::value_type;
-            Container c;
-            ValueType x = Generate<ValueType>::random();
-            ValueType y = random_different_from({x});
-            ValueType z = random_different_from({x, y});
-            for (std::size_t i = 0; i != size; ++i) {
-              c.push_back(i % 2 == 0 ? x : y);
-            }
-
-            for ([[maybe_unused]] auto _ : st) {
-              benchmark::DoNotOptimize(c);
-              benchmark::DoNotOptimize(z);
-              auto pred = [&x](auto element) {
-                benchmark::DoNotOptimize(element);
-                return element == x;
-              };
-              replace_if(c.begin(), c.end(), pred, z);
-              benchmark::DoNotOptimize(c);
-              std::swap(x, z);
-            }
-          })
-          ->Arg(32)
-          ->Arg(1024)
-          ->Arg(8192);
-    };
-    bm.operator()<std::vector<int>>("std::replace_if(vector<int>) (sprinkled)", std_replace_if);
-    bm.operator()<std::deque<int>>("std::replace_if(deque<int>) (sprinkled)", std_replace_if);
-    bm.operator()<std::list<int>>("std::replace_if(list<int>) (sprinkled)", std_replace_if);
-    bm.operator()<std::vector<int>>("rng::replace_if(vector<int>) (sprinkled)", std::ranges::replace_if);
-    bm.operator()<std::deque<int>>("rng::replace_if(deque<int>) (sprinkled)", std::ranges::replace_if);
-    bm.operator()<std::list<int>>("rng::replace_if(list<int>) (sprinkled)", std::ranges::replace_if);
-  }
-
-  benchmark::Initialize(&argc, argv);
-  benchmark::RunSpecifiedBenchmarks();
-  benchmark::Shutdown();
-  return 0;
-}
diff --git a/libcxx/test/benchmarks/algorithms/modifying/unique.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/unique.bench.cpp
index 477f1b5622c3e..4ba4106f35cc9 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/unique.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/unique.bench.cpp
@@ -20,7 +20,21 @@
 #include "../../GenerateInput.h"
 
 int main(int argc, char** argv) {
-  auto std_unique = [](auto first, auto last) { return std::unique(first, last); };
+  auto std_unique      = [](auto first, auto last) { return std::unique(first, last); };
+  auto std_unique_pred = [](auto first, auto last) {
+    return std::unique(first, last, [](auto a, auto b) {
+      benchmark::DoNotOptimize(a);
+      benchmark::DoNotOptimize(b);
+      return a == b;
+    });
+  };
+  auto ranges_unique_pred = [](auto first, auto last) {
+    return std::ranges::unique(first, last, [](auto a, auto b) {
+      benchmark::DoNotOptimize(a);
+      benchmark::DoNotOptimize(b);
+      return a == b;
+    });
+  };
 
   // Create a sequence of the form xxxxxxxxxxyyyyyyyyyy and unique the
   // adjacent equal elements.
@@ -63,12 +77,21 @@ int main(int argc, char** argv) {
           ->Arg(1024)
           ->Arg(8192);
     };
+    // {std,ranges}::unique(it, it)
     bm.operator()<std::vector<int>>("std::unique(vector<int>) (contiguous)", std_unique);
     bm.operator()<std::deque<int>>("std::unique(deque<int>) (contiguous)", std_unique);
     bm.operator()<std::list<int>>("std::unique(list<int>) (contiguous)", std_unique);
     bm.operator()<std::vector<int>>("rng::unique(vector<int>) (contiguous)", std::ranges::unique);
     bm.operator()<std::deque<int>>("rng::unique(deque<int>) (contiguous)", std::ranges::unique);
     bm.operator()<std::list<int>>("rng::unique(list<int>) (contiguous)", std::ranges::unique);
+
+    // {std,ranges}::unique(it, it, pred)
+    bm.operator()<std::vector<int>>("std::unique(vector<int>, pred) (contiguous)", std_unique_pred);
+    bm.operator()<std::deque<int>>("std::unique(deque<int>, pred) (contiguous)", std_unique_pred);
+    bm.operator()<std::list<int>>("std::unique(list<int>, pred) (contiguous)", std_unique_pred);
+    bm.operator()<std::vector<int>>("rng::unique(vector<int>, pred) (contiguous)", ranges_unique_pred);
+    bm.operator()<std::deque<int>>("rng::unique(deque<int>, pred) (contiguous)", ranges_unique_pred);
+    bm.operator()<std::list<int>>("rng::unique(list<int>, pred) (contiguous)", ranges_unique_pred);
   }
 
   // Create a sequence of the form xxyyxxyyxxyyxxyyxxyy and unique
@@ -116,12 +139,21 @@ int main(int argc, char** argv) {
           ->Arg(1024)
           ->Arg(8192);
     };
+    // {std,ranges}::unique(it, it)
     bm.operator()<std::vector<int>>("std::unique(vector<int>) (sprinkled)", std_unique);
     bm.operator()<std::deque<int>>("std::unique(deque<int>) (sprinkled)", std_unique);
     bm.operator()<std::list<int>>("std::unique(list<int>) (sprinkled)", std_unique);
     bm.operator()<std::vector<int>>("rng::unique(vector<int>) (sprinkled)", std::ranges::unique);
     bm.operator()<std::deque<int>>("rng::unique(deque<int>) (sprinkled)", std::ranges::unique);
     bm.operator()<std::list<int>>("rng::unique(list<int>) (sprinkled)", std::ranges::unique);
+
+    // {std,ranges}::unique(it, it, pred)
+    bm.operator()<std::vector<int>>("std::unique(vector<int>, pred) (sprinkled)", std_unique_pred);
+    bm.operator()<std::deque<int>>("std::unique(deque<int>, pred) (sprinkled)", std_unique_pred);
+    bm.operator()<std::list<int>>("std::unique(list<int>, pred) (sprinkled)", std_unique_pred);
+    bm.operator()<std::vector<int>>("rng::unique(vector<int>, pred) (sprinkled)", ranges_unique_pred);
+    bm.operator()<std::deque<int>>("rng::unique(deque<int>, pred) (sprinkled)", ranges_unique_pred);
+    bm.operator()<std::list<int>>("rng::unique(list<int>, pred) (sprinkled)", ranges_unique_pred);
   }
 
   benchmark::Initialize(&argc, argv);
diff --git a/libcxx/test/benchmarks/algorithms/modifying/unique_copy.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/unique_copy.bench.cpp
index 247e7d9c6e497..9aa96316d6e33 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/unique_copy.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/unique_copy.bench.cpp
@@ -20,7 +20,21 @@
 #include "../../GenerateInput.h"
 
 int main(int argc, char** argv) {
-  auto std_unique_copy = [](auto first, auto last, auto out) { return std::unique_copy(first, last, out); };
+  auto std_unique_copy      = [](auto first, auto last, auto out) { return std::unique_copy(first, last, out); };
+  auto std_unique_copy_pred = [](auto first, auto last, auto out) {
+    return std::unique_copy(first, last, out, [](auto a, auto b) {
+      benchmark::DoNotOptimize(a);
+      benchmark::DoNotOptimize(b);
+      return a == b;
+    });
+  };
+  auto ranges_unique_copy_pred = [](auto first, auto last, auto out) {
+    return std::ranges::unique_copy(first, last, out, [](auto a, auto b) {
+      benchmark::DoNotOptimize(a);
+      benchmark::DoNotOptimize(b);
+      return a == b;
+    });
+  };
 
   // Create a sequence of the form xxxxxxxxxxyyyyyyyyyy and unique the
   // adjacent equal elements.
@@ -50,12 +64,21 @@ int main(int argc, char** argv) {
           ->Arg(1024)
           ->Arg(8192);
     };
+    // {std,ranges}::unique_copy(it, it, out)
     bm.operator()<std::vector<int>>("std::unique_copy(vector<int>) (contiguous)", std_unique_copy);
     bm.operator()<std::deque<int>>("std::unique_copy(deque<int>) (contiguous)", std_unique_copy);
     bm.operator()<std::list<int>>("std::unique_copy(list<int>) (contiguous)", std_unique_copy);
     bm.operator()<std::vector<int>>("rng::unique_copy(vector<int>) (contiguous)", std::ranges::unique_copy);
     bm.operator()<std::deque<int>>("rng::unique_copy(deque<int>) (contiguous)", std::ranges::unique_copy);
     bm.operator()<std::list<int>>("rng::unique_copy(list<int>) (contiguous)", std::ranges::unique_copy);
+
+    // {std,ranges}::unique_copy(it, it, out, pred)
+    bm.operator()<std::vector<int>>("std::unique_copy(vector<int>, pred) (contiguous)", std_unique_copy_pred);
+    bm.operator()<std::deque<int>>("std::unique_copy(deque<int>, pred) (contiguous)", std_unique_copy_pred);
+    bm.operator()<std::list<int>>("std::unique_copy(list<int>, pred) (contiguous)", std_unique_copy_pred);
+    bm.operator()<std::vector<int>>("rng::unique_copy(vector<int>, pred) (contiguous)", ranges_unique_copy_pred);
+    bm.operator()<std::deque<int>>("rng::unique_copy(deque<int>, pred) (contiguous)", ranges_unique_copy_pred);
+    bm.operator()<std::list<int>>("rng::unique_copy(list<int>, pred) (contiguous)", ranges_unique_copy_pred);
   }
 
   // Create a sequence of the form xxyyxxyyxxyyxxyyxxyy and unique
@@ -91,12 +114,21 @@ int main(int argc, char** argv) {
           ->Arg(1024)
           ->Arg(8192);
     };
+    // {std,ranges}::unique_copy(it, it, out)
     bm.operator()<std::vector<int>>("std::unique_copy(vector<int>) (sprinkled)", std_unique_copy);
     bm.operator()<std::deque<int>>("std::unique_copy(deque<int>) (sprinkled)", std_unique_copy);
     bm.operator()<std::list<int>>("std::unique_copy(list<int>) (sprinkled)", std_unique_copy);
     bm.operator()<std::vector<int>>("rng::unique_copy(vector<int>) (sprinkled)", std::ranges::unique_copy);
     bm.operator()<std::deque<int>>("rng::unique_copy(deque<int>) (sprinkled)", std::ranges::unique_copy);
     bm.operator()<std::list<int>>("rng::unique_copy(list<int>) (sprinkled)", std::ranges::unique_copy);
+
+    // {std,ranges}::unique_copy(it, it, out, pred)
+    bm.operator()<std::vector<int>>("std::unique_copy(vector<int>, pred) (sprinkled)", std_unique_copy_pred);
+    bm.operator()<std::deque<int>>("std::unique_copy(deque<int>, pred) (sprinkled)", std_unique_copy_pred);
+    bm.operator()<std::list<int>>("std::unique_copy(list<int>, pred) (sprinkled)", std_unique_copy_pred);
+    bm.operator()<std::vector<int>>("rng::unique_copy(vector<int>, pred) (sprinkled)", ranges_unique_copy_pred);
+    bm.operator()<std::deque<int>>("rng::unique_copy(deque<int>, pred) (sprinkled)", ranges_unique_copy_pred);
+    bm.operator()<std::list<int>>("rng::unique_copy(list<int>, pred) (sprinkled)", ranges_unique_copy_pred);
   }
 
   benchmark::Initialize(&argc, argv);
diff --git a/libcxx/test/benchmarks/algorithms/modifying/unique_copy_pred.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/unique_copy_pred.bench.cpp
deleted file mode 100644
index 91031ef884611..0000000000000
--- a/libcxx/test/benchmarks/algorithms/modifying/unique_copy_pred.bench.cpp
+++ /dev/null
@@ -1,120 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++03, c++11, c++14, c++17
-
-#include <algorithm>
-#include <cstddef>
-#include <deque>
-#include <iterator>
-#include <list>
-#include <string>
-#include <vector>
-
-#include "benchmark/benchmark.h"
-#include "../../GenerateInput.h"
-
-int main(int argc, char** argv) {
-  auto std_unique_copy = [](auto first, auto last, auto out, auto pred) {
-    return std::unique_copy(first, last, out, pred);
-  };
-
-  // Create a sequence of the form xxxxxxxxxxyyyyyyyyyy and unique the
-  // adjacent equal elements.
-  {
-    auto bm = []<class Container>(std::string name, auto unique_copy) {
-      benchmark::RegisterBenchmark(
-          name,
-          [unique_copy](auto& st) {
-            std::size_t const size = st.range(0);
-            using ValueType        = typename Container::value_type;
-            Container c(size);
-            ValueType x = Generate<ValueType>::random();
-            ValueType y = random_different_from({x});
-            auto half   = size / 2;
-            std::fill_n(std::fill_n(c.begin(), half, x), half, y);
-
-            std::vector<ValueType> out(size);
-
-            auto pred = [](auto a, auto b) {
-              benchmark::DoNotOptimize(a);
-              benchmark::DoNotOptimize(b);
-              return a == b;
-            };
-
-            for ([[maybe_unused]] auto _ : st) {
-              benchmark::DoNotOptimize(c);
-              benchmark::DoNotOptimize(out);
-              auto result = unique_copy(c.begin(), c.end(), out.begin(), pred);
-              benchmark::DoNotOptimize(result);
-            }
-          })
-          ->Arg(32)
-          ->Arg(1024)
-          ->Arg(8192);
-    };
-    bm.operator()<std::vector<int>>("std::unique_copy(vector<int>, pred) (contiguous)", std_unique_copy);
-    bm.operator()<std::deque<int>>("std::unique_copy(deque<int>, pred) (contiguous)", std_unique_copy);
-    bm.operator()<std::list<int>>("std::unique_copy(list<int>, pred) (contiguous)", std_unique_copy);
-    bm.operator()<std::vector<int>>("rng::unique_copy(vector<int>, pred) (contiguous)", std::ranges::unique_copy);
-    bm.operator()<std::deque<int>>("rng::unique_copy(deque<int>, pred) (contiguous)", std::ranges::unique_copy);
-    bm.operator()<std::list<int>>("rng::unique_copy(list<int>, pred) (contiguous)", std::ranges::unique_copy);
-  }
-
-  // Create a sequence of the form xxyyxxyyxxyyxxyyxxyy and unique
-  // adjacent equal elements.
-  {
-    auto bm = []<class Container>(std::string name, auto unique_copy) {
-      benchmark::RegisterBenchmark(
-          name,
-          [unique_copy](auto& st) {
-            std::size_t const size = st.range(0);
-            using ValueType        = typename Container::value_type;
-            Container c(size);
-            ValueType x    = Generate<ValueType>::random();
-            ValueType y    = random_different_from({x});
-            auto alternate = [&](auto out, auto n) {
-              for (std::size_t i = 0; i != n; i += 2) {
-                *out++ = (i % 4 == 0 ? x : y);
-                *out++ = (i % 4 == 0 ? x : y);
-              }
-            };
-            alternate(c.begin(), size);
-
-            std::vector<ValueType> out(size);
-
-            auto pred = [](auto a, auto b) {
-              benchmark::DoNotOptimize(a);
-              benchmark::DoNotOptimize(b);
-              return a == b;
-            };
-
-            for ([[maybe_unused]] auto _ : st) {
-              benchmark::DoNotOptimize(c);
-              benchmark::DoNotOptimize(out);
-              auto result = unique_copy(c.begin(), c.end(), out.begin(), pred);
-              benchmark::DoNotOptimize(result);
-            }
-          })
-          ->Arg(32)
-          ->Arg(1024)
-          ->Arg(8192);
-    };
-    bm.operator()<std::vector<int>>("std::unique_copy(vector<int>, pred) (sprinkled)", std_unique_copy);
-    bm.operator()<std::deque<int>>("std::unique_copy(deque<int>, pred) (sprinkled)", std_unique_copy);
-    bm.operator()<std::list<int>>("std::unique_copy(list<int>, pred) (sprinkled)", std_unique_copy);
-    bm.operator()<std::vector<int>>("rng::unique_copy(vector<int>, pred) (sprinkled)", std::ranges::unique_copy);
-    bm.operator()<std::deque<int>>("rng::unique_copy(deque<int>, pred) (sprinkled)", std::ranges::unique_copy);
-    bm.operator()<std::list<int>>("rng::unique_copy(list<int>, pred) (sprinkled)", std::ranges::unique_copy);
-  }
-
-  benchmark::Initialize(&argc, argv);
-  benchmark::RunSpecifiedBenchmarks();
-  benchmark::Shutdown();
-  return 0;
-}
diff --git a/libcxx/test/benchmarks/algorithms/modifying/unique_pred.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/unique_pred.bench.cpp
deleted file mode 100644
index 1b0ea26c6b7f5..0000000000000
--- a/libcxx/test/benchmarks/algorithms/modifying/unique_pred.bench.cpp
+++ /dev/null
@@ -1,143 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++03, c++11, c++14, c++17
-
-#include <algorithm>
-#include <cstddef>
-#include <deque>
-#include <iterator>
-#include <list>
-#include <string>
-#include <vector>
-
-#include "benchmark/benchmark.h"
-#include "../../GenerateInput.h"
-
-int main(int argc, char** argv) {
-  auto std_unique = [](auto first, auto last, auto pred) { return std::unique(first, last, pred); };
-
-  // Create a sequence of the form xxxxxxxxxxyyyyyyyyyy and unique the
-  // adjacent equal elements.
-  //
-  // We perform this benchmark in a batch because we need to restore the
-  // state of the container after the operation.
-  {
-    auto bm = []<class Container>(std::string name, auto unique) {
-      benchmark::RegisterBenchmark(
-          name,
-          [unique](auto& st) {
-            std::size_t const size          = st.range(0);
-            constexpr std::size_t BatchSize = 10;
-            using ValueType                 = typename Container::value_type;
-            Container c[BatchSize];
-            ValueType x = Generate<ValueType>::random();
-            ValueType y = random_different_from({x});
-            for (std::size_t i = 0; i != BatchSize; ++i) {
-              c[i]      = Container(size);
-              auto half = size / 2;
-              std::fill_n(std::fill_n(c[i].begin(), half, x), half, y);
-            }
-
-            auto pred = [](auto a, auto b) {
-              benchmark::DoNotOptimize(a);
-              benchmark::DoNotOptimize(b);
-              return a == b;
-            };
-
-            while (st.KeepRunningBatch(BatchSize)) {
-              for (std::size_t i = 0; i != BatchSize; ++i) {
-                benchmark::DoNotOptimize(c[i]);
-                auto result = unique(c[i].begin(), c[i].end(), pred);
-                benchmark::DoNotOptimize(result);
-              }
-
-              st.PauseTiming();
-              for (std::size_t i = 0; i != BatchSize; ++i) {
-                auto half = size / 2;
-                std::fill_n(std::fill_n(c[i].begin(), half, x), half, y);
-              }
-              st.ResumeTiming();
-            }
-          })
-          ->Arg(32)
-          ->Arg(1024)
-          ->Arg(8192);
-    };
-    bm.operator()<std::vector<int>>("std::unique(vector<int>, pred) (contiguous)", std_unique);
-    bm.operator()<std::deque<int>>("std::unique(deque<int>, pred) (contiguous)", std_unique);
-    bm.operator()<std::list<int>>("std::unique(list<int>, pred) (contiguous)", std_unique);
-    bm.operator()<std::vector<int>>("rng::unique(vector<int>, pred) (contiguous)", std::ranges::unique);
-    bm.operator()<std::deque<int>>("rng::unique(deque<int>, pred) (contiguous)", std::ranges::unique);
-    bm.operator()<std::list<int>>("rng::unique(list<int>, pred) (contiguous)", std::ranges::unique);
-  }
-
-  // Create a sequence of the form xxyyxxyyxxyyxxyyxxyy and unique
-  // adjacent equal elements.
-  //
-  // We perform this benchmark in a batch because we need to restore the
-  // state of the container after the operation.
-  {
-    auto bm = []<class Container>(std::string name, auto unique) {
-      benchmark::RegisterBenchmark(
-          name,
-          [unique](auto& st) {
-            std::size_t const size          = st.range(0);
-            constexpr std::size_t BatchSize = 10;
-            using ValueType                 = typename Container::value_type;
-            Container c[BatchSize];
-            ValueType x    = Generate<ValueType>::random();
-            ValueType y    = random_different_from({x});
-            auto alternate = [&](auto out, auto n) {
-              for (std::size_t i = 0; i != n; i += 2) {
-                *out++ = (i % 4 == 0 ? x : y);
-                *out++ = (i % 4 == 0 ? x : y);
-              }
-            };
-            for (std::size_t i = 0; i != BatchSize; ++i) {
-              c[i] = Container(size);
-              alternate(c[i].begin(), size);
-            }
-
-            auto pred = [](auto a, auto b) {
-              benchmark::DoNotOptimize(a);
-              benchmark::DoNotOptimize(b);
-              return a == b;
-            };
-
-            while (st.KeepRunningBatch(BatchSize)) {
-              for (std::size_t i = 0; i != BatchSize; ++i) {
-                benchmark::DoNotOptimize(c[i]);
-                auto result = unique(c[i].begin(), c[i].end(), pred);
-                benchmark::DoNotOptimize(result);
-              }
-
-              st.PauseTiming();
-              for (std::size_t i = 0; i != BatchSize; ++i) {
-                alternate(c[i].begin(), size);
-              }
-              st.ResumeTiming();
-            }
-          })
-          ->Arg(32)
-          ->Arg(1024)
-          ->Arg(8192);
-    };
-    bm.operator()<std::vector<int>>("std::unique(vector<int>, pred) (sprinkled)", std_unique);
-    bm.operator()<std::deque<int>>("std::unique(deque<int>, pred) (sprinkled)", std_unique);
-    bm.operator()<std::list<int>>("std::unique(list<int>, pred) (sprinkled)", std_unique);
-    bm.operator()<std::vector<int>>("rng::unique(vector<int>, pred) (sprinkled)", std::ranges::unique);
-    bm.operator()<std::deque<int>>("rng::unique(deque<int>, pred) (sprinkled)", std::ranges::unique);
-    bm.operator()<std::list<int>>("rng::unique(list<int>, pred) (sprinkled)", std::ranges::unique);
-  }
-
-  benchmark::Initialize(&argc, argv);
-  benchmark::RunSpecifiedBenchmarks();
-  benchmark::Shutdown();
-  return 0;
-}

>From c50f43fb11519e5565c9c71d07e28f0d42e11340 Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Tue, 25 Feb 2025 10:38:19 -0500
Subject: [PATCH 11/15] Simplify how we generate alternating sequences

---
 .../algorithms/modifying/remove.bench.cpp     | 29 ++++++++-------
 .../algorithms/modifying/unique.bench.cpp     | 36 +++++++++++--------
 .../modifying/unique_copy.bench.cpp           | 18 ++++++----
 3 files changed, 48 insertions(+), 35 deletions(-)

diff --git a/libcxx/test/benchmarks/algorithms/modifying/remove.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/remove.bench.cpp
index 07e8f834a8639..f0713dc7f9720 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/remove.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/remove.bench.cpp
@@ -48,12 +48,15 @@ int main(int argc, char** argv) {
             constexpr std::size_t BatchSize = 10;
             using ValueType                 = typename Container::value_type;
             Container c[BatchSize];
-            ValueType x = Generate<ValueType>::random();
-            ValueType y = random_different_from({x});
+            ValueType x   = Generate<ValueType>::random();
+            ValueType y   = random_different_from({x});
+            auto populate = [&](Container& cont) {
+              auto half = cont.size() / 2;
+              std::fill_n(std::fill_n(cont.begin(), half, x), half, y);
+            };
             for (std::size_t i = 0; i != BatchSize; ++i) {
-              c[i]      = Container(size);
-              auto half = size / 2;
-              std::fill_n(std::fill_n(c[i].begin(), half, x), half, y);
+              c[i] = Container(size);
+              populate(c[i]);
             }
 
             while (st.KeepRunningBatch(BatchSize)) {
@@ -66,8 +69,7 @@ int main(int argc, char** argv) {
 
               st.PauseTiming();
               for (std::size_t i = 0; i != BatchSize; ++i) {
-                auto half = size / 2;
-                std::fill_n(std::fill_n(c[i].begin(), half, x), half, y);
+                populate(c[i]);
               }
               st.ResumeTiming();
             }
@@ -107,16 +109,17 @@ int main(int argc, char** argv) {
             constexpr std::size_t BatchSize = 10;
             using ValueType                 = typename Container::value_type;
             Container c[BatchSize];
-            ValueType x    = Generate<ValueType>::random();
-            ValueType y    = random_different_from({x});
-            auto alternate = [&](auto out, auto n) {
-              for (std::size_t i = 0; i != n; ++i) {
+            ValueType x   = Generate<ValueType>::random();
+            ValueType y   = random_different_from({x});
+            auto populate = [&](Container& cont) {
+              auto out = cont.begin();
+              for (std::size_t i = 0; i != cont.size(); ++i) {
                 *out++ = (i % 2 == 0 ? x : y);
               }
             };
             for (std::size_t i = 0; i != BatchSize; ++i) {
               c[i] = Container(size);
-              alternate(c[i].begin(), size);
+              populate(c[i]);
             }
 
             while (st.KeepRunningBatch(BatchSize)) {
@@ -129,7 +132,7 @@ int main(int argc, char** argv) {
 
               st.PauseTiming();
               for (std::size_t i = 0; i != BatchSize; ++i) {
-                alternate(c[i].begin(), size);
+                populate(c[i]);
               }
               st.ResumeTiming();
             }
diff --git a/libcxx/test/benchmarks/algorithms/modifying/unique.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/unique.bench.cpp
index 4ba4106f35cc9..baec1fc8187d9 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/unique.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/unique.bench.cpp
@@ -50,12 +50,15 @@ int main(int argc, char** argv) {
             constexpr std::size_t BatchSize = 10;
             using ValueType                 = typename Container::value_type;
             Container c[BatchSize];
-            ValueType x = Generate<ValueType>::random();
-            ValueType y = random_different_from({x});
+            ValueType x   = Generate<ValueType>::random();
+            ValueType y   = random_different_from({x});
+            auto populate = [&](Container& cont) {
+              auto half = cont.size() / 2;
+              std::fill_n(std::fill_n(cont.begin(), half, x), half, y);
+            };
             for (std::size_t i = 0; i != BatchSize; ++i) {
-              c[i]      = Container(size);
-              auto half = size / 2;
-              std::fill_n(std::fill_n(c[i].begin(), half, x), half, y);
+              c[i] = Container(size);
+              populate(c[i]);
             }
 
             while (st.KeepRunningBatch(BatchSize)) {
@@ -67,8 +70,7 @@ int main(int argc, char** argv) {
 
               st.PauseTiming();
               for (std::size_t i = 0; i != BatchSize; ++i) {
-                auto half = size / 2;
-                std::fill_n(std::fill_n(c[i].begin(), half, x), half, y);
+                populate(c[i]);
               }
               st.ResumeTiming();
             }
@@ -108,17 +110,21 @@ int main(int argc, char** argv) {
             constexpr std::size_t BatchSize = 10;
             using ValueType                 = typename Container::value_type;
             Container c[BatchSize];
-            ValueType x    = Generate<ValueType>::random();
-            ValueType y    = random_different_from({x});
-            auto alternate = [&](auto out, auto n) {
-              for (std::size_t i = 0; i != n; i += 2) {
-                *out++ = (i % 4 == 0 ? x : y);
-                *out++ = (i % 4 == 0 ? x : y);
+            ValueType x   = Generate<ValueType>::random();
+            ValueType y   = random_different_from({x});
+            auto populate = [&](Container& cont) {
+              assert(cont.size() % 4 == 0);
+              auto out = cont.begin();
+              for (std::size_t i = 0; i != cont.size(); i += 4) {
+                *out++ = x;
+                *out++ = x;
+                *out++ = y;
+                *out++ = y;
               }
             };
             for (std::size_t i = 0; i != BatchSize; ++i) {
               c[i] = Container(size);
-              alternate(c[i].begin(), size);
+              populate(c[i]);
             }
 
             while (st.KeepRunningBatch(BatchSize)) {
@@ -130,7 +136,7 @@ int main(int argc, char** argv) {
 
               st.PauseTiming();
               for (std::size_t i = 0; i != BatchSize; ++i) {
-                alternate(c[i].begin(), size);
+                populate(c[i]);
               }
               st.ResumeTiming();
             }
diff --git a/libcxx/test/benchmarks/algorithms/modifying/unique_copy.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/unique_copy.bench.cpp
index 9aa96316d6e33..c5b5439e88e71 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/unique_copy.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/unique_copy.bench.cpp
@@ -91,15 +91,19 @@ int main(int argc, char** argv) {
             std::size_t const size = st.range(0);
             using ValueType        = typename Container::value_type;
             Container c(size);
-            ValueType x    = Generate<ValueType>::random();
-            ValueType y    = random_different_from({x});
-            auto alternate = [&](auto out, auto n) {
-              for (std::size_t i = 0; i != n; i += 2) {
-                *out++ = (i % 4 == 0 ? x : y);
-                *out++ = (i % 4 == 0 ? x : y);
+            ValueType x   = Generate<ValueType>::random();
+            ValueType y   = random_different_from({x});
+            auto populate = [&](Container& cont) {
+              assert(cont.size() % 4 == 0);
+              auto out = cont.begin();
+              for (std::size_t i = 0; i != cont.size(); i += 4) {
+                *out++ = x;
+                *out++ = x;
+                *out++ = y;
+                *out++ = y;
               }
             };
-            alternate(c.begin(), size);
+            populate(c);
 
             std::vector<ValueType> out(size);
 

>From ef203af6d18ca8cb83767f1429d0104604ffde21 Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Tue, 25 Feb 2025 10:55:20 -0500
Subject: [PATCH 12/15] Improve coverage for rotate

---
 .../algorithms/modifying/rotate.bench.cpp     | 93 +++++++++++++++++--
 1 file changed, 84 insertions(+), 9 deletions(-)

diff --git a/libcxx/test/benchmarks/algorithms/modifying/rotate.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/rotate.bench.cpp
index 8345f0941c62e..49165f74561b9 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/rotate.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/rotate.bench.cpp
@@ -22,7 +22,82 @@
 int main(int argc, char** argv) {
   auto std_rotate = [](auto first, auto middle, auto last) { return std::rotate(first, middle, last); };
 
-  // {std,ranges}::rotate(normal container)
+  // Benchmark {std,ranges}::rotate where we rotate various fractions of the range. It is possible to
+  // special-case some of these fractions to cleverly perform swap_ranges.
+  {
+    auto bm = []<class Container>(std::string name, auto rotate, double fraction) {
+      benchmark::RegisterBenchmark(
+          name,
+          [=](auto& st) {
+            std::size_t const size = st.range(0);
+            using ValueType        = typename Container::value_type;
+            Container c;
+            std::generate_n(std::back_inserter(c), size, [] { return Generate<ValueType>::random(); });
+
+            auto nth = std::next(c.begin(), static_cast<std::size_t>(size * fraction));
+            for ([[maybe_unused]] auto _ : st) {
+              benchmark::DoNotOptimize(c);
+              auto result = rotate(c.begin(), nth, c.end());
+              benchmark::DoNotOptimize(result);
+            }
+          })
+          ->Arg(32)
+          ->Arg(1024)
+          ->Arg(8192);
+    };
+    bm.operator()<std::vector<int>>("std::rotate(vector<int>) (by 1/4)", std_rotate, 0.25);
+    bm.operator()<std::deque<int>>("std::rotate(deque<int>) (by 1/4)", std_rotate, 0.25);
+    bm.operator()<std::list<int>>("std::rotate(list<int>) (by 1/4)", std_rotate, 0.25);
+    bm.operator()<std::vector<int>>("rng::rotate(vector<int>) (by 1/4)", std::ranges::rotate, 0.25);
+    bm.operator()<std::deque<int>>("rng::rotate(deque<int>) (by 1/4)", std::ranges::rotate, 0.25);
+    bm.operator()<std::list<int>>("rng::rotate(list<int>) (by 1/4)", std::ranges::rotate, 0.25);
+
+    bm.operator()<std::vector<int>>("std::rotate(vector<int>) (by 1/3)", std_rotate, 0.33);
+    bm.operator()<std::deque<int>>("std::rotate(deque<int>) (by 1/3)", std_rotate, 0.33);
+    bm.operator()<std::list<int>>("std::rotate(list<int>) (by 1/3)", std_rotate, 0.33);
+    bm.operator()<std::vector<int>>("rng::rotate(vector<int>) (by 1/3)", std::ranges::rotate, 0.33);
+    bm.operator()<std::deque<int>>("rng::rotate(deque<int>) (by 1/3)", std::ranges::rotate, 0.33);
+    bm.operator()<std::list<int>>("rng::rotate(list<int>) (by 1/3)", std::ranges::rotate, 0.33);
+
+    bm.operator()<std::vector<int>>("std::rotate(vector<int>) (by 1/2)", std_rotate, 0.50);
+    bm.operator()<std::deque<int>>("std::rotate(deque<int>) (by 1/2)", std_rotate, 0.50);
+    bm.operator()<std::list<int>>("std::rotate(list<int>) (by 1/2)", std_rotate, 0.50);
+    bm.operator()<std::vector<int>>("rng::rotate(vector<int>) (by 1/2)", std::ranges::rotate, 0.50);
+    bm.operator()<std::deque<int>>("rng::rotate(deque<int>) (by 1/2)", std::ranges::rotate, 0.50);
+    bm.operator()<std::list<int>>("rng::rotate(list<int>) (by 1/2)", std::ranges::rotate, 0.50);
+  }
+
+  // Benchmark {std,ranges}::rotate where we rotate a single element from the beginning to the end of the range.
+  {
+    auto bm = []<class Container>(std::string name, auto rotate) {
+      benchmark::RegisterBenchmark(
+          name,
+          [rotate](auto& st) {
+            std::size_t const size = st.range(0);
+            using ValueType        = typename Container::value_type;
+            Container c;
+            std::generate_n(std::back_inserter(c), size, [] { return Generate<ValueType>::random(); });
+
+            auto pivot = std::next(c.begin());
+            for ([[maybe_unused]] auto _ : st) {
+              benchmark::DoNotOptimize(c);
+              auto result = rotate(c.begin(), pivot, c.end());
+              benchmark::DoNotOptimize(result);
+            }
+          })
+          ->Arg(32)
+          ->Arg(1024)
+          ->Arg(8192);
+    };
+    bm.operator()<std::vector<int>>("std::rotate(vector<int>) (1 element forward)", std_rotate);
+    bm.operator()<std::deque<int>>("std::rotate(deque<int>) (1 element forward)", std_rotate);
+    bm.operator()<std::list<int>>("std::rotate(list<int>) (1 element forward)", std_rotate);
+    bm.operator()<std::vector<int>>("rng::rotate(vector<int>) (1 element forward)", std::ranges::rotate);
+    bm.operator()<std::deque<int>>("rng::rotate(deque<int>) (1 element forward)", std::ranges::rotate);
+    bm.operator()<std::list<int>>("rng::rotate(list<int>) (1 element forward)", std::ranges::rotate);
+  }
+
+  // Benchmark {std,ranges}::rotate where we rotate a single element from the end to the beginning of the range.
   {
     auto bm = []<class Container>(std::string name, auto rotate) {
       benchmark::RegisterBenchmark(
@@ -33,10 +108,10 @@ int main(int argc, char** argv) {
             Container c;
             std::generate_n(std::back_inserter(c), size, [] { return Generate<ValueType>::random(); });
 
-            auto middle = std::next(c.begin(), size / 2);
+            auto pivot = std::next(c.begin(), size - 1);
             for ([[maybe_unused]] auto _ : st) {
               benchmark::DoNotOptimize(c);
-              auto result = rotate(c.begin(), middle, c.end());
+              auto result = rotate(c.begin(), pivot, c.end());
               benchmark::DoNotOptimize(result);
             }
           })
@@ -44,12 +119,12 @@ int main(int argc, char** argv) {
           ->Arg(1024)
           ->Arg(8192);
     };
-    bm.operator()<std::vector<int>>("std::rotate(vector<int>)", std_rotate);
-    bm.operator()<std::deque<int>>("std::rotate(deque<int>)", std_rotate);
-    bm.operator()<std::list<int>>("std::rotate(list<int>)", std_rotate);
-    bm.operator()<std::vector<int>>("rng::rotate(vector<int>)", std::ranges::rotate);
-    bm.operator()<std::deque<int>>("rng::rotate(deque<int>)", std::ranges::rotate);
-    bm.operator()<std::list<int>>("rng::rotate(list<int>)", std::ranges::rotate);
+    bm.operator()<std::vector<int>>("std::rotate(vector<int>) (1 element backward)", std_rotate);
+    bm.operator()<std::deque<int>>("std::rotate(deque<int>) (1 element backward)", std_rotate);
+    bm.operator()<std::list<int>>("std::rotate(list<int>) (1 element backward)", std_rotate);
+    bm.operator()<std::vector<int>>("rng::rotate(vector<int>) (1 element backward)", std::ranges::rotate);
+    bm.operator()<std::deque<int>>("rng::rotate(deque<int>) (1 element backward)", std::ranges::rotate);
+    bm.operator()<std::list<int>>("rng::rotate(list<int>) (1 element backward)", std::ranges::rotate);
   }
 
   benchmark::Initialize(&argc, argv);

>From 13789b4ebc1b991e9f65cbe644740221f60962cd Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Tue, 25 Feb 2025 11:13:37 -0500
Subject: [PATCH 13/15] Address comments on shift_{left,right} benchmarks

---
 .../algorithms/modifying/shift_left.bench.cpp      | 14 +++++++++++---
 .../algorithms/modifying/shift_right.bench.cpp     | 14 +++++++++++---
 2 files changed, 22 insertions(+), 6 deletions(-)

diff --git a/libcxx/test/benchmarks/algorithms/modifying/shift_left.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/shift_left.bench.cpp
index 906e825992b9d..8c3b410bf2ec6 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/shift_left.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/shift_left.bench.cpp
@@ -14,6 +14,7 @@
 #include <iterator>
 #include <list>
 #include <string>
+#include <utility>
 #include <vector>
 
 #include "benchmark/benchmark.h"
@@ -22,7 +23,7 @@
 int main(int argc, char** argv) {
   auto std_shift_left = [](auto first, auto last, auto n) { return std::shift_left(first, last, n); };
 
-  // std::shift_left(normal container)
+  // Benchmark std::shift_left where we shift exactly one element, which is the worst case.
   {
     auto bm = []<class Container>(std::string name, auto shift_left) {
       benchmark::RegisterBenchmark(
@@ -32,12 +33,19 @@ int main(int argc, char** argv) {
             using ValueType        = typename Container::value_type;
             Container c;
             std::generate_n(std::back_inserter(c), size, [] { return Generate<ValueType>::random(); });
+            std::size_t n = 1;
 
-            auto const n = 9 * (size / 10); // shift all but 10% of the range
+            // To avoid ending up with a fully moved-from range, restore the element that gets
+            // overwritten by the shift after performing the shift.
+            auto first_element = c.begin();
+            auto last_element  = std::next(c.begin(), size - 1);
 
             for ([[maybe_unused]] auto _ : st) {
               benchmark::DoNotOptimize(c);
-              auto result = shift_left(c.begin(), c.end(), n);
+              benchmark::DoNotOptimize(n);
+              ValueType tmp = *first_element;
+              auto result   = shift_left(c.begin(), c.end(), n);
+              *last_element = std::move(tmp);
               benchmark::DoNotOptimize(result);
             }
           })
diff --git a/libcxx/test/benchmarks/algorithms/modifying/shift_right.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/shift_right.bench.cpp
index ef55e55f3ca10..7e55c390b1951 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/shift_right.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/shift_right.bench.cpp
@@ -14,6 +14,7 @@
 #include <iterator>
 #include <list>
 #include <string>
+#include <utility>
 #include <vector>
 
 #include "benchmark/benchmark.h"
@@ -22,7 +23,7 @@
 int main(int argc, char** argv) {
   auto std_shift_right = [](auto first, auto last, auto n) { return std::shift_right(first, last, n); };
 
-  // std::shift_right(normal container)
+  // Benchmark std::shift_right where we shift exactly one element, which is the worst case.
   {
     auto bm = []<class Container>(std::string name, auto shift_right) {
       benchmark::RegisterBenchmark(
@@ -32,12 +33,19 @@ int main(int argc, char** argv) {
             using ValueType        = typename Container::value_type;
             Container c;
             std::generate_n(std::back_inserter(c), size, [] { return Generate<ValueType>::random(); });
+            std::size_t n = 1;
 
-            auto const n = 9 * (size / 10); // shift all but 10% of the range
+            // To avoid ending up with a fully moved-from range, restore the element that gets
+            // overwritten by the shift after performing the shift.
+            auto first_element = c.begin();
+            auto last_element  = std::next(c.begin(), size - 1);
 
             for ([[maybe_unused]] auto _ : st) {
               benchmark::DoNotOptimize(c);
-              auto result = shift_right(c.begin(), c.end(), n);
+              benchmark::DoNotOptimize(n);
+              ValueType tmp  = *last_element;
+              auto result    = shift_right(c.begin(), c.end(), n);
+              *first_element = std::move(tmp);
               benchmark::DoNotOptimize(result);
             }
           })

>From 073d849d612998eb3a57454875e36e95babbf636 Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Tue, 25 Feb 2025 11:17:13 -0500
Subject: [PATCH 14/15] Avoid two decls on a line

---
 libcxx/test/benchmarks/algorithms/modifying/move.bench.cpp     | 3 ++-
 .../benchmarks/algorithms/modifying/move_backward.bench.cpp    | 3 ++-
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/libcxx/test/benchmarks/algorithms/modifying/move.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/move.bench.cpp
index 8213c16b78e6b..7473dffc123ce 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/move.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/move.bench.cpp
@@ -29,7 +29,8 @@ int main(int argc, char** argv) {
       benchmark::RegisterBenchmark(name, [move](auto& st) {
         std::size_t const size = st.range(0);
         using ValueType        = typename Container::value_type;
-        Container c1(size), c2(size);
+        Container c1(size);
+        Container c2(size);
         std::generate_n(c1.begin(), size, [] { return Generate<ValueType>::random(); });
 
         Container* in  = &c1;
diff --git a/libcxx/test/benchmarks/algorithms/modifying/move_backward.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/move_backward.bench.cpp
index a5bfc75ec94e8..1cdc880910686 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/move_backward.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/move_backward.bench.cpp
@@ -29,7 +29,8 @@ int main(int argc, char** argv) {
       benchmark::RegisterBenchmark(name, [move_backward](auto& st) {
         std::size_t const size = st.range(0);
         using ValueType        = typename Container::value_type;
-        Container c1(size), c2(size);
+        Container c1(size);
+        Container c2(size);
         std::generate_n(c1.begin(), size, [] { return Generate<ValueType>::random(); });
 
         Container* in  = &c1;

>From 5c563b52c44238b65aaa1c1f93d83894991b9cac Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Tue, 25 Feb 2025 11:20:22 -0500
Subject: [PATCH 15/15] Add non-powers-of-two

---
 libcxx/test/benchmarks/algorithms/modifying/fill.bench.cpp     | 1 +
 libcxx/test/benchmarks/algorithms/modifying/fill_n.bench.cpp   | 1 +
 libcxx/test/benchmarks/algorithms/modifying/generate.bench.cpp | 1 +
 .../test/benchmarks/algorithms/modifying/generate_n.bench.cpp  | 1 +
 libcxx/test/benchmarks/algorithms/modifying/remove.bench.cpp   | 2 ++
 .../test/benchmarks/algorithms/modifying/remove_copy.bench.cpp | 2 ++
 libcxx/test/benchmarks/algorithms/modifying/replace.bench.cpp  | 2 ++
 libcxx/test/benchmarks/algorithms/modifying/rotate.bench.cpp   | 3 +++
 .../test/benchmarks/algorithms/modifying/rotate_copy.bench.cpp | 1 +
 .../test/benchmarks/algorithms/modifying/shift_left.bench.cpp  | 1 +
 .../test/benchmarks/algorithms/modifying/shift_right.bench.cpp | 1 +
 .../test/benchmarks/algorithms/modifying/swap_ranges.bench.cpp | 1 +
 .../benchmarks/algorithms/modifying/transform.binary.bench.cpp | 1 +
 .../benchmarks/algorithms/modifying/transform.unary.bench.cpp  | 1 +
 libcxx/test/benchmarks/algorithms/modifying/unique.bench.cpp   | 2 ++
 .../test/benchmarks/algorithms/modifying/unique_copy.bench.cpp | 1 +
 16 files changed, 22 insertions(+)

diff --git a/libcxx/test/benchmarks/algorithms/modifying/fill.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/fill.bench.cpp
index 7b3534969b247..9060752259eb9 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/fill.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/fill.bench.cpp
@@ -42,6 +42,7 @@ int main(int argc, char** argv) {
             }
           })
           ->Arg(32)
+          ->Arg(50) // non power-of-two
           ->Arg(1024)
           ->Arg(8192);
     };
diff --git a/libcxx/test/benchmarks/algorithms/modifying/fill_n.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/fill_n.bench.cpp
index 700d109fdbc61..8ad3e7534b1ef 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/fill_n.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/fill_n.bench.cpp
@@ -42,6 +42,7 @@ int main(int argc, char** argv) {
             }
           })
           ->Arg(32)
+          ->Arg(50) // non power-of-two
           ->Arg(1024)
           ->Arg(8192);
     };
diff --git a/libcxx/test/benchmarks/algorithms/modifying/generate.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/generate.bench.cpp
index e3a8d650b5159..34354e5af0efb 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/generate.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/generate.bench.cpp
@@ -43,6 +43,7 @@ int main(int argc, char** argv) {
             }
           })
           ->Arg(32)
+          ->Arg(50) // non power-of-two
           ->Arg(1024)
           ->Arg(8192);
     };
diff --git a/libcxx/test/benchmarks/algorithms/modifying/generate_n.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/generate_n.bench.cpp
index 3671b66b21a85..9f8fb1e07524d 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/generate_n.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/generate_n.bench.cpp
@@ -43,6 +43,7 @@ int main(int argc, char** argv) {
             }
           })
           ->Arg(32)
+          ->Arg(50) // non power-of-two
           ->Arg(1024)
           ->Arg(8192);
     };
diff --git a/libcxx/test/benchmarks/algorithms/modifying/remove.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/remove.bench.cpp
index f0713dc7f9720..19cd49641e173 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/remove.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/remove.bench.cpp
@@ -75,6 +75,7 @@ int main(int argc, char** argv) {
             }
           })
           ->Arg(32)
+          ->Arg(50) // non power-of-two
           ->Arg(1024)
           ->Arg(8192);
     };
@@ -138,6 +139,7 @@ int main(int argc, char** argv) {
             }
           })
           ->Arg(32)
+          ->Arg(50) // non power-of-two
           ->Arg(1024)
           ->Arg(8192);
     };
diff --git a/libcxx/test/benchmarks/algorithms/modifying/remove_copy.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/remove_copy.bench.cpp
index b0bc58e8a7a2f..582175b8a32cc 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/remove_copy.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/remove_copy.bench.cpp
@@ -62,6 +62,7 @@ int main(int argc, char** argv) {
             }
           })
           ->Arg(32)
+          ->Arg(50) // non power-of-two
           ->Arg(1024)
           ->Arg(8192);
     };
@@ -109,6 +110,7 @@ int main(int argc, char** argv) {
             }
           })
           ->Arg(32)
+          ->Arg(50) // non power-of-two
           ->Arg(1024)
           ->Arg(8192);
     };
diff --git a/libcxx/test/benchmarks/algorithms/modifying/replace.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/replace.bench.cpp
index 5df7aa1fbbc04..bdf26acb8d07f 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/replace.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/replace.bench.cpp
@@ -65,6 +65,7 @@ int main(int argc, char** argv) {
             }
           })
           ->Arg(32)
+          ->Arg(50) // non power-of-two
           ->Arg(1024)
           ->Arg(8192);
     };
@@ -111,6 +112,7 @@ int main(int argc, char** argv) {
             }
           })
           ->Arg(32)
+          ->Arg(50) // non power-of-two
           ->Arg(1024)
           ->Arg(8192);
     };
diff --git a/libcxx/test/benchmarks/algorithms/modifying/rotate.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/rotate.bench.cpp
index 49165f74561b9..64fb9b18c07b9 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/rotate.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/rotate.bench.cpp
@@ -42,6 +42,7 @@ int main(int argc, char** argv) {
             }
           })
           ->Arg(32)
+          ->Arg(50) // non power-of-two
           ->Arg(1024)
           ->Arg(8192);
     };
@@ -86,6 +87,7 @@ int main(int argc, char** argv) {
             }
           })
           ->Arg(32)
+          ->Arg(50) // non power-of-two
           ->Arg(1024)
           ->Arg(8192);
     };
@@ -116,6 +118,7 @@ int main(int argc, char** argv) {
             }
           })
           ->Arg(32)
+          ->Arg(50) // non power-of-two
           ->Arg(1024)
           ->Arg(8192);
     };
diff --git a/libcxx/test/benchmarks/algorithms/modifying/rotate_copy.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/rotate_copy.bench.cpp
index 4f685ba9a8c7e..4ba9110552807 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/rotate_copy.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/rotate_copy.bench.cpp
@@ -46,6 +46,7 @@ int main(int argc, char** argv) {
             }
           })
           ->Arg(32)
+          ->Arg(50) // non power-of-two
           ->Arg(1024)
           ->Arg(8192);
     };
diff --git a/libcxx/test/benchmarks/algorithms/modifying/shift_left.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/shift_left.bench.cpp
index 8c3b410bf2ec6..b26526484c66a 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/shift_left.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/shift_left.bench.cpp
@@ -50,6 +50,7 @@ int main(int argc, char** argv) {
             }
           })
           ->Arg(32)
+          ->Arg(50) // non power-of-two
           ->Arg(1024)
           ->Arg(8192);
     };
diff --git a/libcxx/test/benchmarks/algorithms/modifying/shift_right.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/shift_right.bench.cpp
index 7e55c390b1951..42946760fc8a3 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/shift_right.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/shift_right.bench.cpp
@@ -50,6 +50,7 @@ int main(int argc, char** argv) {
             }
           })
           ->Arg(32)
+          ->Arg(50) // non power-of-two
           ->Arg(1024)
           ->Arg(8192);
     };
diff --git a/libcxx/test/benchmarks/algorithms/modifying/swap_ranges.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/swap_ranges.bench.cpp
index 541f4ae17cc7a..e9fb201a57d34 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/swap_ranges.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/swap_ranges.bench.cpp
@@ -46,6 +46,7 @@ int main(int argc, char** argv) {
             }
           })
           ->Arg(32)
+          ->Arg(50) // non power-of-two
           ->Arg(1024)
           ->Arg(8192);
     };
diff --git a/libcxx/test/benchmarks/algorithms/modifying/transform.binary.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/transform.binary.bench.cpp
index cb6cfceee5bc4..c4ea7535aefef 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/transform.binary.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/transform.binary.bench.cpp
@@ -53,6 +53,7 @@ int main(int argc, char** argv) {
             }
           })
           ->Arg(32)
+          ->Arg(50) // non power-of-two
           ->Arg(1024)
           ->Arg(8192);
     };
diff --git a/libcxx/test/benchmarks/algorithms/modifying/transform.unary.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/transform.unary.bench.cpp
index db02fb67556b9..9ae40cb488085 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/transform.unary.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/transform.unary.bench.cpp
@@ -48,6 +48,7 @@ int main(int argc, char** argv) {
             }
           })
           ->Arg(32)
+          ->Arg(50) // non power-of-two
           ->Arg(1024)
           ->Arg(8192);
     };
diff --git a/libcxx/test/benchmarks/algorithms/modifying/unique.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/unique.bench.cpp
index baec1fc8187d9..c0aee942eef64 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/unique.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/unique.bench.cpp
@@ -76,6 +76,7 @@ int main(int argc, char** argv) {
             }
           })
           ->Arg(32)
+          ->Arg(50) // non power-of-two
           ->Arg(1024)
           ->Arg(8192);
     };
@@ -142,6 +143,7 @@ int main(int argc, char** argv) {
             }
           })
           ->Arg(32)
+          ->Arg(50) // non power-of-two
           ->Arg(1024)
           ->Arg(8192);
     };
diff --git a/libcxx/test/benchmarks/algorithms/modifying/unique_copy.bench.cpp b/libcxx/test/benchmarks/algorithms/modifying/unique_copy.bench.cpp
index c5b5439e88e71..45b52dd23b695 100644
--- a/libcxx/test/benchmarks/algorithms/modifying/unique_copy.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/modifying/unique_copy.bench.cpp
@@ -115,6 +115,7 @@ int main(int argc, char** argv) {
             }
           })
           ->Arg(32)
+          ->Arg(50) // non power-of-two
           ->Arg(1024)
           ->Arg(8192);
     };



More information about the libcxx-commits mailing list