[libcxx-commits] [libcxx] [libc++] Optimize std::find if types are integral (PR #70345)
Nikolas Klauser via libcxx-commits
libcxx-commits at lists.llvm.org
Thu Dec 21 06:58:01 PST 2023
https://github.com/philnik777 updated https://github.com/llvm/llvm-project/pull/70345
>From fa7c221ddf79bc802b38a41b14e783be8be65826 Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Thu, 26 Oct 2023 11:54:29 +0200
Subject: [PATCH] [libc++] Optimize std::find if types are integral
---
libcxx/include/__algorithm/find.h | 19 ++++++++++
.../alg.nonmodifying/alg.find/find.pass.cpp | 35 +++++++++++++++++++
2 files changed, 54 insertions(+)
diff --git a/libcxx/include/__algorithm/find.h b/libcxx/include/__algorithm/find.h
index 754e597130c5b1..7d7631b6e98a96 100644
--- a/libcxx/include/__algorithm/find.h
+++ b/libcxx/include/__algorithm/find.h
@@ -21,8 +21,11 @@
#include <__fwd/bit_reference.h>
#include <__iterator/segmented_iterator.h>
#include <__string/constexpr_c_functions.h>
+#include <__type_traits/is_integral.h>
#include <__type_traits/is_same.h>
+#include <__type_traits/is_signed.h>
#include <__utility/move.h>
+#include <limits>
#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
# include <cwchar>
@@ -76,6 +79,22 @@ __find_impl(_Tp* __first, _Tp* __last, const _Up& __value, _Proj&) {
}
#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
+// TODO: This should also be possible to get right with different signedness
+// cast integral types to allow vectorization
+template <class _Tp,
+ class _Up,
+ class _Proj,
+ __enable_if_t<__is_identity<_Proj>::value && !__libcpp_is_trivially_equality_comparable<_Tp, _Up>::value &&
+ is_integral<_Tp>::value && is_integral<_Up>::value &&
+ is_signed<_Tp>::value == is_signed<_Up>::value,
+ int> = 0>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp*
+__find_impl(_Tp* __first, _Tp* __last, const _Up& __value, _Proj& __proj) {
+ if (__value < numeric_limits<_Tp>::min() || __value > numeric_limits<_Tp>::max())
+ return __last;
+ return std::__find_impl(__first, __last, _Tp(__value), __proj);
+}
+
// __bit_iterator implementation
template <bool _ToFind, class _Cp, bool _IsConst>
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, _IsConst>
diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/alg.find/find.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/alg.find/find.pass.cpp
index 0afc573aa17713..c47913e13b8d62 100644
--- a/libcxx/test/std/algorithms/alg.nonmodifying/alg.find/find.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.nonmodifying/alg.find/find.pass.cpp
@@ -162,6 +162,39 @@ void test_deque() {
}
}
+template <class T>
+struct TestIntegerPromotions1 {
+ template <class U>
+ TEST_CONSTEXPR_CXX20 void test(T val, U to_find) {
+ bool expect_match = val == to_find;
+ assert(std::find(&val, &val + 1, to_find) == (expect_match ? &val : &val + 1));
+ }
+
+ template <class U>
+ TEST_CONSTEXPR_CXX20 void operator()() {
+ test<U>(0, 0);
+ test<U>(0, 1);
+ test<U>(0, -1);
+ test<U>(0, U(-127));
+ test<U>(0, U(-128));
+ test<U>(0, U(-129));
+ test<U>(0, U(255));
+ test<U>(0, U(256));
+ test<U>(0, U(257));
+ test<U>(0, std::numeric_limits<U>::min());
+ test<U>(0, std::numeric_limits<U>::min() + 1);
+ test<U>(0, std::numeric_limits<U>::max());
+ test<U>(0, std::numeric_limits<U>::max() - 1);
+ }
+};
+
+struct TestIntegerPromotions {
+ template <class T>
+ TEST_CONSTEXPR_CXX20 void operator()() {
+ types::for_each(types::integral_types(), TestIntegerPromotions1<T>());
+ }
+};
+
TEST_CONSTEXPR_CXX20 bool test() {
types::for_each(types::integer_types(), TestTypes<char>());
types::for_each(types::integer_types(), TestTypes<int>());
@@ -181,6 +214,8 @@ TEST_CONSTEXPR_CXX20 bool test() {
}
#endif
+ types::for_each(types::integral_types(), TestIntegerPromotions());
+
return true;
}
More information about the libcxx-commits
mailing list