[libcxx-commits] [libcxx] b203d53 - [libc++] Optimize std::find if types are integral and have the same signedness (#70345)

via libcxx-commits libcxx-commits at lists.llvm.org
Sat Dec 23 02:21:31 PST 2023


Author: Nikolas Klauser
Date: 2023-12-23T11:21:27+01:00
New Revision: b203d5320df7754bf0ce019f01347a0ef743a207

URL: https://github.com/llvm/llvm-project/commit/b203d5320df7754bf0ce019f01347a0ef743a207
DIFF: https://github.com/llvm/llvm-project/commit/b203d5320df7754bf0ce019f01347a0ef743a207.diff

LOG: [libc++] Optimize std::find if types are integral and have the same signedness (#70345)

Fixes #70238

Added: 
    

Modified: 
    libcxx/include/__algorithm/find.h
    libcxx/test/std/algorithms/alg.nonmodifying/alg.find/find.pass.cpp

Removed: 
    


################################################################################
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 
diff erent 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..0676da13e90f76 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
@@ -6,6 +6,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+// ADDITIONAL_COMPILE_FLAGS(gcc): -Wno-bool-compare
 // ADDITIONAL_COMPILE_FLAGS(gcc-style-warnings): -Wno-sign-compare
 // MSVC warning C4389: '==': signed/unsigned mismatch
 // ADDITIONAL_COMPILE_FLAGS(cl-style-warnings): /wd4389
@@ -162,6 +163,45 @@ 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>(1, 1);
+    test<U>(0, -1);
+    test<U>(-1, -1);
+    test<U>(0, U(-127));
+    test<U>(T(-127), U(-127));
+    test<U>(T(-128), U(-128));
+    test<U>(T(-129), U(-129));
+    test<U>(T(255), U(255));
+    test<U>(T(256), U(256));
+    test<U>(T(257), U(257));
+    test<U>(0, std::numeric_limits<U>::min());
+    test<U>(T(std::numeric_limits<U>::min()), std::numeric_limits<U>::min());
+    test<U>(0, std::numeric_limits<U>::min() + 1);
+    test<U>(T(std::numeric_limits<U>::min() + 1), std::numeric_limits<U>::min() + 1);
+    test<U>(0, std::numeric_limits<U>::max());
+    test<U>(T(std::numeric_limits<U>::max()), std::numeric_limits<U>::max());
+    test<U>(T(std::numeric_limits<U>::max() - 1), 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 +221,8 @@ TEST_CONSTEXPR_CXX20 bool test() {
   }
 #endif
 
+  types::for_each(types::integral_types(), TestIntegerPromotions());
+
   return true;
 }
 


        


More information about the libcxx-commits mailing list