diff options
Diffstat (limited to 'absl/hash/internal/low_level_hash.cc')
-rw-r--r-- | absl/hash/internal/low_level_hash.cc | 23 |
1 files changed, 9 insertions, 14 deletions
diff --git a/absl/hash/internal/low_level_hash.cc b/absl/hash/internal/low_level_hash.cc index 6f9cb9c7..b5db0b89 100644 --- a/absl/hash/internal/low_level_hash.cc +++ b/absl/hash/internal/low_level_hash.cc @@ -15,7 +15,7 @@ #include "absl/hash/internal/low_level_hash.h" #include "absl/base/internal/unaligned_access.h" -#include "absl/numeric/bits.h" +#include "absl/base/prefetch.h" #include "absl/numeric/int128.h" namespace absl { @@ -23,24 +23,15 @@ ABSL_NAMESPACE_BEGIN namespace hash_internal { static uint64_t Mix(uint64_t v0, uint64_t v1) { -#if !defined(__aarch64__) - // The default bit-mixer uses 64x64->128-bit multiplication. absl::uint128 p = v0; p *= v1; return absl::Uint128Low64(p) ^ absl::Uint128High64(p); -#else - // The default bit-mixer above would perform poorly on some ARM microarchs, - // where calculating a 128-bit product requires a sequence of two - // instructions with a high combined latency and poor throughput. - // Instead, we mix bits using only 64-bit arithmetic, which is faster. - uint64_t p = v0 ^ absl::rotl(v1, 40); - p *= v1 ^ absl::rotl(v0, 39); - return p ^ (p >> 11); -#endif } uint64_t LowLevelHash(const void* data, size_t len, uint64_t seed, - const uint64_t salt[]) { + const uint64_t salt[5]) { + // Prefetch the cacheline that data resides in. + PrefetchToLocalCache(data); const uint8_t* ptr = static_cast<const uint8_t*>(data); uint64_t starting_length = static_cast<uint64_t>(len); uint64_t current_state = seed ^ salt[0]; @@ -52,6 +43,9 @@ uint64_t LowLevelHash(const void* data, size_t len, uint64_t seed, uint64_t duplicated_state = current_state; do { + // Always prefetch the next cacheline. + PrefetchToLocalCache(ptr + ABSL_CACHELINE_SIZE); + uint64_t a = absl::base_internal::UnalignedLoad64(ptr); uint64_t b = absl::base_internal::UnalignedLoad64(ptr + 8); uint64_t c = absl::base_internal::UnalignedLoad64(ptr + 16); @@ -106,7 +100,8 @@ uint64_t LowLevelHash(const void* data, size_t len, uint64_t seed, } else if (len > 0) { // If we have at least 1 and at most 3 bytes, read all of the provided // bits into A, with some adjustments. - a = ((ptr[0] << 16) | (ptr[len >> 1] << 8) | ptr[len - 1]); + a = static_cast<uint64_t>((ptr[0] << 16) | (ptr[len >> 1] << 8) | + ptr[len - 1]); b = 0; } else { a = 0; |