[libcxx-commits] [libcxx] [libc++] Add constant folding for optimized std::find variants (PR #96491)

Nikolas Klauser via libcxx-commits libcxx-commits at lists.llvm.org
Mon Jun 24 07:18:41 PDT 2024


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

Currently Clang isn't able to constant fold `memchr` and `wmemchr`. This adds some basic constant folding to `__constexpr_memchr` and `__constexpr_wmemchr`, mostly alleviating the problem.

While not necessarily representative of the real world, an optimized version of the `find.pass.cpp` test is reduced from ~13k to ~4.5k lines of assembly.



>From 0522ee34a76a91785ebcb96ddec9867eb9df34f8 Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Mon, 24 Jun 2024 16:09:04 +0200
Subject: [PATCH] [libc++] Add constant folding for optimized std::find
 variants

---
 libcxx/include/__string/constexpr_c_functions.h | 13 +++++++++++++
 libcxx/include/cwchar                           | 13 +++++++++++++
 2 files changed, 26 insertions(+)

diff --git a/libcxx/include/__string/constexpr_c_functions.h b/libcxx/include/__string/constexpr_c_functions.h
index a978f816f1897..cd5b63ae47d1e 100644
--- a/libcxx/include/__string/constexpr_c_functions.h
+++ b/libcxx/include/__string/constexpr_c_functions.h
@@ -132,6 +132,19 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp* __constexpr_memchr(_Tp*
   static_assert(sizeof(_Tp) == 1 && __libcpp_is_trivially_equality_comparable<_Tp, _Up>::value,
                 "Calling memchr on non-trivially equality comparable types is unsafe.");
 
+  if (__builtin_constant_p(__count) && __builtin_constant_p(__value)) {
+    for (; __count; --__count) {
+      if (!__builtin_constant_p(*__str))
+        break;
+      if (*__str == __value)
+        return __str;
+      ++__str;
+    }
+  }
+
+  if (__builtin_constant_p(__count) && __count == 0)
+    return nullptr;
+
   if (__libcpp_is_constant_evaluated()) {
 // use __builtin_char_memchr to optimize constexpr evaluation if we can
 #if _LIBCPP_STD_VER >= 17 && __has_builtin(__builtin_char_memchr)
diff --git a/libcxx/include/cwchar b/libcxx/include/cwchar
index 08cfac58c846a..76fdf08988dc5 100644
--- a/libcxx/include/cwchar
+++ b/libcxx/include/cwchar
@@ -231,6 +231,19 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp* __constexpr_wmemchr(_Tp
                     __libcpp_is_trivially_equality_comparable<_Tp, _Tp>::value,
                 "Calling wmemchr on non-trivially equality comparable types is unsafe.");
 
+  if (__builtin_constant_p(__count) && __builtin_constant_p(__value)) {
+    for (; __count; --__count) {
+      if (!__builtin_constant_p(*__str))
+        break;
+      if (*__str == __value)
+        return __str;
+      ++__str;
+    }
+  }
+
+  if (__builtin_constant_p(__count) && __count == 0)
+    return nullptr;
+
 #if __has_builtin(__builtin_wmemchr)
   if (!__libcpp_is_constant_evaluated()) {
     wchar_t __value_buffer = 0;



More information about the libcxx-commits mailing list