[libcxx-commits] [libcxx] [libc++] Run vector instructions during constant evaluation when Clang supports it (PR #160057)

Nikolas Klauser via libcxx-commits libcxx-commits at lists.llvm.org
Mon Sep 22 02:58:29 PDT 2025


https://github.com/philnik777 updated https://github.com/llvm/llvm-project/pull/160057

>From 693b19685f772016a7f6baff8bffba222afc5439 Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Mon, 22 Sep 2025 11:54:40 +0200
Subject: [PATCH] [libc++] Run vector instructions during constant evaluation
 when Clang supports it

---
 libcxx/include/__algorithm/mismatch.h   |  2 +-
 libcxx/include/__algorithm/simd_utils.h | 34 ++++++++++++++++++++-----
 2 files changed, 28 insertions(+), 8 deletions(-)

diff --git a/libcxx/include/__algorithm/mismatch.h b/libcxx/include/__algorithm/mismatch.h
index a6836792c0581..b8a791bf976e2 100644
--- a/libcxx/include/__algorithm/mismatch.h
+++ b/libcxx/include/__algorithm/mismatch.h
@@ -65,7 +65,7 @@ __mismatch_vectorized(_Iter __first1, _Iter __last1, _Iter __first2) {
   constexpr size_t __vec_size     = __native_vector_size<__value_type>;
   using __vec                     = __simd_vector<__value_type, __vec_size>;
 
-  if (!__libcpp_is_constant_evaluated()) {
+  if (!__libcpp_is_constant_evaluated() || _LIBCPP_HAS_CONSTEXPR_VECTORS) {
     auto __orig_first1 = __first1;
     auto __last2       = __first2 + (__last1 - __first1);
     while (static_cast<size_t>(__last1 - __first1) >= __unroll_count * __vec_size) [[__unlikely__]] {
diff --git a/libcxx/include/__algorithm/simd_utils.h b/libcxx/include/__algorithm/simd_utils.h
index 96b074c063a5d..3c8d010e56cb6 100644
--- a/libcxx/include/__algorithm/simd_utils.h
+++ b/libcxx/include/__algorithm/simd_utils.h
@@ -40,6 +40,14 @@ _LIBCPP_PUSH_MACROS
 
 #if _LIBCPP_HAS_ALGORITHM_VECTOR_UTILS
 
+#  if defined(_LIBCPP_CLANG_VER) && _LIBCPP_CLANG_VER >= 2200
+#    define _LIBCPP_HAS_CONSTEXPR_VECTORS 1
+#    define _LIBCPP_VECTOR_CONSTEXPR _LIBCPP_CONSTEXPR
+#  else
+#    define _LIBCPP_HAS_CONSTEXPR_VECTORS 0
+#    define _LIBCPP_VECTOR_CONSTEXPR
+#  endif
+
 _LIBCPP_BEGIN_NAMESPACE_STD
 
 template <class _Tp>
@@ -108,30 +116,40 @@ using __simd_vector_underlying_type_t _LIBCPP_NODEBUG = decltype(std::__simd_vec
 
 // This isn't inlined without always_inline when loading chars.
 template <class _VecT, class _Iter>
-[[__nodiscard__]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _VecT __load_vector(_Iter __iter) noexcept {
+[[__nodiscard__]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_VECTOR_CONSTEXPR _VecT
+__load_vector(_Iter __iter) noexcept {
   return [=]<size_t... _Indices>(index_sequence<_Indices...>) _LIBCPP_ALWAYS_INLINE noexcept {
     return _VecT{__iter[_Indices]...};
   }(make_index_sequence<__simd_vector_size_v<_VecT>>{});
 }
 
 template <class _Tp, size_t _Np>
-[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool __all_of(__simd_vector<_Tp, _Np> __vec) noexcept {
+[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_VECTOR_CONSTEXPR bool __all_of(__simd_vector<_Tp, _Np> __vec) noexcept {
   return __builtin_reduce_and(__builtin_convertvector(__vec, __simd_vector<bool, _Np>));
 }
 
 template <class _Tp, size_t _Np>
-[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_t __find_first_set(__simd_vector<_Tp, _Np> __vec) noexcept {
+[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_VECTOR_CONSTEXPR size_t
+__find_first_set(__simd_vector<_Tp, _Np> __vec) noexcept {
   using __mask_vec = __simd_vector<bool, _Np>;
 
+#  if _LIBCPP_HAS_CONSTEXPR_VECTORS
+#    if defined(_LIBCPP_BIG_ENDIAN)
+  return __builtin_clzg(__builtin_convertvector(__vec, __mask_vec), static_cast<int>(_Np));
+#    else
+  return __builtin_ctzg(__builtin_convertvector(__vec, __mask_vec), static_cast<int>(_Np));
+#    endif
+#  else
+
   // This has MSan disabled du to https://llvm.org/PR85876
   auto __impl = [&]<class _MaskT>(_MaskT) _LIBCPP_NO_SANITIZE("memory") noexcept {
-#  if defined(_LIBCPP_BIG_ENDIAN)
+#    if defined(_LIBCPP_BIG_ENDIAN)
     return std::min<size_t>(
         _Np, std::__countl_zero(__builtin_bit_cast(_MaskT, __builtin_convertvector(__vec, __mask_vec))));
-#  else
+#    else
     return std::min<size_t>(
         _Np, std::__countr_zero(__builtin_bit_cast(_MaskT, __builtin_convertvector(__vec, __mask_vec))));
-#  endif
+#    endif
   };
 
   if constexpr (sizeof(__mask_vec) == sizeof(uint8_t)) {
@@ -146,10 +164,12 @@ template <class _Tp, size_t _Np>
     static_assert(sizeof(__mask_vec) == 0, "unexpected required size for mask integer type");
     return 0;
   }
+#  endif
 }
 
 template <class _Tp, size_t _Np>
-[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_t __find_first_not_set(__simd_vector<_Tp, _Np> __vec) noexcept {
+[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_VECTOR_CONSTEXPR size_t
+__find_first_not_set(__simd_vector<_Tp, _Np> __vec) noexcept {
   return std::__find_first_set(~__vec);
 }
 



More information about the libcxx-commits mailing list