diff --git a/third-party/folly/src/CMakeLists.txt b/third-party/folly/src/CMakeLists.txt index 885990ecc7c22f..c30fc9938ed16f 100644 --- a/third-party/folly/src/CMakeLists.txt +++ b/third-party/folly/src/CMakeLists.txt @@ -648,8 +648,10 @@ if (BUILD_TESTS OR BUILD_BENCHMARKS) folly_define_tests( DIRECTORY algorithm/simd/detail/test/ TEST algorithm_simd_detail_simd_any_of_test SOURCES SimdAnyOfTest.cpp - TEST algorithm_simd_detail_unroll_utils_test SOURCES UnrollUtilsTest.cpp TEST algorithm_simd_detail_simd_for_each_test SOURCES SimdForEachTest.cpp + TEST algorithm_simd_detail_unroll_utils_test SOURCES UnrollUtilsTest.cpp + # disabled until C++20 + # TEST algorithm_simd_detail_simd_traits_test SOURCES TraitsTest.cpp DIRECTORY algorithm/simd/test/ TEST algorithm_simd_find_fixed_test SOURCES FindFixedTest.cpp diff --git a/third-party/folly/src/folly/algorithm/simd/FindFixed.h b/third-party/folly/src/folly/algorithm/simd/FindFixed.h index c76c8022341fe9..547b02a6b3ae28 100644 --- a/third-party/folly/src/folly/algorithm/simd/FindFixed.h +++ b/third-party/folly/src/folly/algorithm/simd/FindFixed.h @@ -28,6 +28,7 @@ #include #include +#include #if FOLLY_X64 #include @@ -82,11 +83,6 @@ constexpr std::optional findFixed(std::span where, U x) // implementation --------------------------------------------------------- namespace find_fixed_detail { -template -std::optional findFixedCast(std::span& where, T x) { - std::span whereU{reinterpret_cast(where.data()), N}; - return findFixed(whereU, static_cast(x)); -} template constexpr std::optional findFixedConstexpr( @@ -295,13 +291,9 @@ constexpr std::optional findFixed(std::span where, U x) return findFixed(where, static_cast(x)); } else if (std::is_constant_evaluated()) { return find_fixed_detail::findFixedConstexpr(std::span(where), x); - } else if constexpr (std::is_enum_v) { - return find_fixed_detail::findFixedCast>( - where, x); - } else if constexpr (std::is_signed_v) { - return find_fixed_detail::findFixedCast>(where, x); } else { - return find_fixed_detail::findFixedDispatch(where, x); + return find_fixed_detail::findFixedDispatch( + detail::asSimdFriendlyUint(where), detail::asSimdFriendlyUint(x)); } } diff --git a/third-party/folly/src/folly/algorithm/simd/detail/Traits.h b/third-party/folly/src/folly/algorithm/simd/detail/Traits.h new file mode 100644 index 00000000000000..ee2ef3d5105b6c --- /dev/null +++ b/third-party/folly/src/folly/algorithm/simd/detail/Traits.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include +#include + +#include +#include + +namespace folly::detail { + +template +auto findSimdFriendlyEquivalent() { + if constexpr (std::is_enum_v) { + return findSimdFriendlyEquivalent>(); + } else if constexpr (std::is_floating_point_v) { + if constexpr (sizeof(T) == 4) { + return float{}; + } else { + return double{}; + } + } else if constexpr (std::is_signed_v) { + if constexpr (sizeof(T) == 1) { + return std::int8_t{}; + } else if constexpr (sizeof(T) == 2) { + return std::int16_t{}; + } else if constexpr (sizeof(T) == 4) { + return std::int32_t{}; + } else if constexpr (sizeof(T) == 8) { + return std::int64_t{}; + } + } else if constexpr (std::is_unsigned_v) { + if constexpr (sizeof(T) == 1) { + return std::uint8_t{}; + } else if constexpr (sizeof(T) == 2) { + return std::uint16_t{}; + } else if constexpr (sizeof(T) == 4) { + return std::uint32_t{}; + } else if constexpr (sizeof(T) == 8) { + return std::uint64_t{}; + } + } +} + +template +concept has_simd_friendly_equivalent = + !std::is_same_v())>; + +template +using simd_friendly_equivalent_t = folly::like_t< // + T, + decltype(findSimdFriendlyEquivalent>())>; + +template +concept has_integral_simd_friendly_equivalent = + has_simd_friendly_equivalent && // have to explicitly specify this for + // subsumption to work + std::integral>; + +template +using integral_simd_friendly_equivalent = simd_friendly_equivalent_t; + +template +auto asSimdFriendly(folly::span s) { + return folly::reinterpret_span_cast>(s); +} + +template +constexpr auto asSimdFriendly(T x) { + return static_cast>(x); +} + +template +auto asSimdFriendlyUint(folly::span s) { + return folly::reinterpret_span_cast< + folly::like_t>>(s); +} + +template +constexpr auto asSimdFriendlyUint(T x) { + return static_cast>(x); +} + +} // namespace folly::detail diff --git a/third-party/folly/src/folly/algorithm/simd/detail/test/TraitsTest.cpp b/third-party/folly/src/folly/algorithm/simd/detail/test/TraitsTest.cpp new file mode 100644 index 00000000000000..5d01d9630dfc65 --- /dev/null +++ b/third-party/folly/src/folly/algorithm/simd/detail/test/TraitsTest.cpp @@ -0,0 +1,139 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include + +namespace folly::detail { + +struct FollySimdTraitsTest : testing::Test {}; + +namespace simd_friendly_equivalent_test { + +// ints +static_assert( + std::is_same_v>); +static_assert( + std::is_same_v>); + +static_assert(std::is_same_v>); +static_assert( + std::is_same_v>); + +static_assert(std::is_same_v>); +static_assert( + std::is_same_v>); + +static_assert( + std::is_same_v>); +static_assert( + std::is_same_v>); + +// floats +static_assert(std::is_same_v>); +static_assert(std::is_same_v>); + +// enum +enum SomeInt {}; +enum class SomeIntClass : std::int32_t {}; + +static_assert( + std::is_same_v>); +static_assert( + std::is_same_v>); + +// const + +static_assert( + std::is_same_v>); + +// sfinae +constexpr auto sfinae_call = + [](T) -> simd_friendly_equivalent_t { return {}; }; + +static_assert(std::invocable); + +struct NotSimdFriendly {}; +static_assert(!std::invocable); + +} // namespace simd_friendly_equivalent_test + +namespace integral_simd_friendly_equivalent_test { + +static_assert(std::is_same_v< // + std::int8_t, + integral_simd_friendly_equivalent>); + +struct Overloading { + constexpr int operator()(auto) { return 0; } + constexpr int operator()(has_simd_friendly_equivalent auto) { return 1; } + constexpr int operator()(has_integral_simd_friendly_equivalent auto) { + return 2; + } +}; + +// Subsumption tests +struct NotSimdFriendly {}; +enum class SomeInt {}; + +static_assert(Overloading{}(NotSimdFriendly{}) == 0); +static_assert(Overloading{}(float{}) == 1); +static_assert(Overloading{}(int{}) == 2); +static_assert(Overloading{}(SomeInt{}) == 2); + +} // namespace integral_simd_friendly_equivalent_test + +TEST_F(FollySimdTraitsTest, AsSimdFriendly) { + enum SomeEnum : int { Foo = 1, Bar, Baz }; + + static_assert(asSimdFriendly(SomeEnum::Foo) == 1); + + std::array arr{SomeEnum::Foo, SomeEnum::Bar, SomeEnum::Baz}; + folly::span castSpan = asSimdFriendly(folly::span(arr)); + ASSERT_THAT(castSpan, testing::ElementsAre(1, 2, 3)); +} + +template +void isSameTest(const T&, const U&) = delete; + +template +void isSameTest(const T&, const T&) {} + +template +void asSimdFriendlyUintTypeTest() { + isSameTest(asSimdFriendlyUint(From{}), To{}); + isSameTest(asSimdFriendlyUint(std::span{}), std::span{}); + isSameTest( + asSimdFriendlyUint(std::span{}), std::span{}); +} + +TEST_F(FollySimdTraitsTest, AsSimdFriendlyUint) { + enum SomeEnum : int { Foo = 1, Bar, Baz }; + + static_assert(asSimdFriendlyUint(SomeEnum::Foo) == 1U); + + asSimdFriendlyUintTypeTest(); + asSimdFriendlyUintTypeTest(); + asSimdFriendlyUintTypeTest(); + asSimdFriendlyUintTypeTest(); + asSimdFriendlyUintTypeTest(); + asSimdFriendlyUintTypeTest(); + asSimdFriendlyUintTypeTest(); +} + +} // namespace folly::detail