Skip to content

Commit

Permalink
folly::simd::contains, all types. (#2306)
Browse files Browse the repository at this point in the history
Summary:
Pull Request resolved: #2306

extended the SimdCharPlatform => SimdPlatform to support all unsigned types.

Reviewed By: Gownta

Differential Revision: D63548781

fbshipit-source-id: 6599a7bd8686955e28df4f83aeb45f43a31b855e
  • Loading branch information
DenisYaroshevskiy authored and facebook-github-bot committed Oct 7, 2024
1 parent 56d76a3 commit 46d56b8
Show file tree
Hide file tree
Showing 18 changed files with 574 additions and 362 deletions.
47 changes: 27 additions & 20 deletions folly/algorithm/simd/Movemask.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,22 +91,7 @@ struct movemask_fn {
auto operator()(Reg reg) const;

template <typename Reg, typename Ignore>
FOLLY_ERASE auto operator()(Reg reg, Ignore ignore) const {
auto [bits, bitsPerElement] = operator()(reg);

if constexpr (std::is_same_v<Ignore, ignore_none>) {
return std::pair{bits, bitsPerElement};
} else {
static constexpr int kCardinal = sizeof(Reg) / sizeof(Scalar);

int bitsToKeep = (kCardinal - ignore.last) * bitsPerElement;

bits =
clear_n_least_significant_bits(bits, ignore.first * bitsPerElement);
bits = clear_n_most_significant_bits(bits, sizeof(bits) * 8 - bitsToKeep);
return std::pair{bits, bitsPerElement};
}
}
auto operator()(Reg reg, Ignore ignore) const;
};

template <typename Scalar>
Expand All @@ -116,7 +101,7 @@ inline constexpr movemask_fn<Scalar> movemask;

template <typename Scalar>
template <typename Reg>
auto movemask_fn<Scalar>::operator()(Reg reg) const {
FOLLY_ERASE auto movemask_fn<Scalar>::operator()(Reg reg) const {
std::integral_constant<std::uint32_t, sizeof(Scalar) == 2 ? 2 : 1>
bitsPerElement;

Expand Down Expand Up @@ -154,7 +139,7 @@ auto movemask_fn<Scalar>::operator()(Reg reg) const {

namespace detail {

inline auto movemaskChars16Aarch64(uint8x16_t reg) {
FOLLY_ERASE auto movemaskChars16Aarch64(uint8x16_t reg) {
uint16x8_t u16s = vreinterpretq_u16_u8(reg);
u16s = vshrq_n_u16(u16s, 4);
uint8x8_t packed = vmovn_u16(u16s);
Expand All @@ -163,7 +148,7 @@ inline auto movemaskChars16Aarch64(uint8x16_t reg) {
}

template <typename Reg>
uint64x1_t asUint64x1Aarch64(Reg reg) {
FOLLY_ERASE uint64x1_t asUint64x1Aarch64(Reg reg) {
if constexpr (std::is_same_v<Reg, uint32x2_t>) {
return vreinterpret_u64_u32(reg);
} else if constexpr (std::is_same_v<Reg, uint16x4_t>) {
Expand All @@ -177,7 +162,7 @@ uint64x1_t asUint64x1Aarch64(Reg reg) {

template <typename Scalar>
template <typename Reg>
auto movemask_fn<Scalar>::operator()(Reg reg) const {
FOLLY_ERASE auto movemask_fn<Scalar>::operator()(Reg reg) const {
if constexpr (std::is_same_v<Reg, uint64x2_t>) {
return movemask<std::uint32_t>(vmovn_u64(reg));
} else if constexpr (std::is_same_v<Reg, uint32x4_t>) {
Expand All @@ -195,6 +180,28 @@ auto movemask_fn<Scalar>::operator()(Reg reg) const {

#endif

#if FOLLY_X64 || FOLLY_AARCH64

template <typename Scalar>
template <typename Reg, typename Ignore>
FOLLY_ERASE auto movemask_fn<Scalar>::operator()(Reg reg, Ignore ignore) const {
auto [bits, bitsPerElement] = operator()(reg);

if constexpr (std::is_same_v<Ignore, ignore_none>) {
return std::pair{bits, bitsPerElement};
} else {
static constexpr int kCardinal = sizeof(Reg) / sizeof(Scalar);

int bitsToKeep = (kCardinal - ignore.last) * bitsPerElement;

bits = clear_n_least_significant_bits(bits, ignore.first * bitsPerElement);
bits = clear_n_most_significant_bits(bits, sizeof(bits) * 8 - bitsToKeep);
return std::pair{bits, bitsPerElement};
}
}

#endif

} // namespace folly::simd

FOLLY_POP_WARNING
7 changes: 4 additions & 3 deletions folly/algorithm/simd/detail/BUCK
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ cpp_library(
)

cpp_library(
name = "simd_char_platform",
headers = ["SimdCharPlatform.h"],
name = "simd_platform",
headers = ["SimdPlatform.h"],
exported_deps = [
"//folly:portability",
"//folly/algorithm/simd:ignore",
Expand All @@ -31,7 +31,7 @@ cpp_library(
headers = ["ContainsImpl.h"],
exported_deps = [
":simd_any_of",
":simd_char_platform",
":simd_platform",
"//folly:c_portability",
"//folly/container:span",
],
Expand All @@ -45,6 +45,7 @@ cpp_library(
"//folly:c_portability",
"//folly:traits",
"//folly/algorithm/simd:ignore",
"//folly/lang:align",
],
)

Expand Down
22 changes: 11 additions & 11 deletions folly/algorithm/simd/detail/ContainsImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

#include <folly/CPortability.h>
#include <folly/algorithm/simd/detail/SimdAnyOf.h>
#include <folly/algorithm/simd/detail/SimdCharPlatform.h>
#include <folly/algorithm/simd/detail/SimdPlatform.h>
#include <folly/container/span.h>

namespace folly::simd::detail {
Expand Down Expand Up @@ -62,20 +62,20 @@ FOLLY_ERASE bool containsImplStd(folly::span<const T> haystack, T needle) {

template <typename T>
constexpr bool hasHandwrittenContains() {
return std::is_same_v<T, std::uint8_t> &&
!std::is_same_v<SimdCharPlatform, void>;
return !std::is_same_v<SimdPlatform<T>, void> &&
(std::is_same_v<std::uint8_t, T> || std::is_same_v<std::uint16_t, T> ||
std::is_same_v<std::uint32_t, T> || std::is_same_v<std::uint64_t, T>);
}

template <typename T>
template <typename T, typename Platform = SimdPlatform<T>>
FOLLY_ERASE bool containsImplHandwritten(
folly::span<const T> haystack, T needle) {
static_assert(std::is_same_v<T, std::uint8_t>, "");
auto as_chars = folly::reinterpret_span_cast<const char>(haystack);
return simdAnyOf<SimdCharPlatform, 4>(
as_chars.data(),
as_chars.data() + as_chars.size(),
[&](SimdCharPlatform::reg_t x) {
return SimdCharPlatform::equal(x, static_cast<char>(needle));
static_assert(!std::is_same_v<Platform, void>, "");
return simdAnyOf<Platform, 4>(
haystack.data(),
haystack.data() + haystack.size(),
[&](typename Platform::reg_t x) {
return Platform::equal(x, static_cast<T>(needle));
});
}

Expand Down
Loading

0 comments on commit 46d56b8

Please sign in to comment.