[libcxx-commits] [libcxx] [libc++] Opzimize bitset shift operations (PR #106225)

Nikolas Klauser via libcxx-commits libcxx-commits at lists.llvm.org
Tue Aug 27 06:53:22 PDT 2024


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

--------------------------------------
Benchmark               old        new
--------------------------------------
bm_left_shift<32>   6.19 ns   0.210 ns
bm_left_shift<64>   6.16 ns    6.20 ns
bm_right_shift<32>  6.23 ns   0.421 ns
bm_right_shift<64>  6.26 ns    6.31 ns



>From 827aa35fb1074ab64b5a13511d1aee8f5dc90c46 Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Tue, 27 Aug 2024 15:51:12 +0200
Subject: [PATCH] [libc++] Opzimize bitset shift operations

---
 libcxx/include/__bit_reference          | 18 ++++++++++++
 libcxx/test/benchmarks/CMakeLists.txt   |  1 +
 libcxx/test/benchmarks/bitset.bench.cpp | 37 +++++++++++++++++++++++++
 3 files changed, 56 insertions(+)
 create mode 100644 libcxx/test/benchmarks/bitset.bench.cpp

diff --git a/libcxx/include/__bit_reference b/libcxx/include/__bit_reference
index 22637d43974123..599e87d3e6fc3e 100644
--- a/libcxx/include/__bit_reference
+++ b/libcxx/include/__bit_reference
@@ -290,6 +290,15 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, false> _
 template <class _Cp, bool _IsConst>
 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator<_Cp, false>
 copy(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) {
+  if (__builtin_constant_p(
+          __result.__ctz_ == 0 && __first.__seg_ == __last.__seg_ && __last.__seg_ == __result.__seg_) &&
+      __result.__ctz_ == 0 && __first.__seg_ == __last.__seg_ && __last.__seg_ == __result.__seg_) {
+    if (__first == __last)
+      return __result;
+    *__result.__seg_ >>= __first.__ctz_;
+    return __result + (__last - __first);
+  }
+
   if (__first.__ctz_ == __result.__ctz_)
     return std::__copy_aligned(__first, __last, __result);
   return std::__copy_unaligned(__first, __last, __result);
@@ -418,6 +427,15 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, false> _
 template <class _Cp, bool _IsConst>
 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator<_Cp, false> copy_backward(
     __bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) {
+  if (__builtin_constant_p(
+          __first.__ctz_ == 0 && __first.__seg_ == __last.__seg_ && __last.__seg_ == __result.__seg_) &&
+      __first.__ctz_ == 0 && __first.__seg_ == __last.__seg_ && __last.__seg_ == __result.__seg_) {
+    if (__first == __last)
+      return __result;
+    *__result.__seg_ <<= __result.__ctz_ - __last.__ctz_;
+    return __result - (__last - __first);
+  }
+
   if (__last.__ctz_ == __result.__ctz_)
     return std::__copy_backward_aligned(__first, __last, __result);
   return std::__copy_backward_unaligned(__first, __last, __result);
diff --git a/libcxx/test/benchmarks/CMakeLists.txt b/libcxx/test/benchmarks/CMakeLists.txt
index 616cf0ff8d2374..d88ca038bc39f6 100644
--- a/libcxx/test/benchmarks/CMakeLists.txt
+++ b/libcxx/test/benchmarks/CMakeLists.txt
@@ -140,6 +140,7 @@ set(BENCHMARK_TESTS
     algorithms/stable_sort.bench.cpp
     atomic_wait.bench.cpp
     atomic_wait_vs_mutex_lock.bench.cpp
+    bitset.bench.cpp
     libcxxabi/dynamic_cast.bench.cpp
     libcxxabi/dynamic_cast_old_stress.bench.cpp
     allocation.bench.cpp
diff --git a/libcxx/test/benchmarks/bitset.bench.cpp b/libcxx/test/benchmarks/bitset.bench.cpp
new file mode 100644
index 00000000000000..fbe3dee5089e7e
--- /dev/null
+++ b/libcxx/test/benchmarks/bitset.bench.cpp
@@ -0,0 +1,37 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include <bitset>
+
+#include "benchmark/benchmark.h"
+
+template <std::size_t N>
+static void bm_left_shift(benchmark::State& state) {
+  std::bitset<N> b;
+
+  for (auto _ : state) {
+    b <<= 4;
+    benchmark::DoNotOptimize(b);
+  }
+}
+BENCHMARK(bm_left_shift<32>);
+BENCHMARK(bm_left_shift<64>);
+
+template <std::size_t N>
+static void bm_right_shift(benchmark::State& state) {
+  std::bitset<N> b;
+
+  for (auto _ : state) {
+    b >>= 4;
+    benchmark::DoNotOptimize(b);
+  }
+}
+BENCHMARK(bm_right_shift<32>);
+BENCHMARK(bm_right_shift<64>);
+
+BENCHMARK_MAIN();



More information about the libcxx-commits mailing list