[base] allow inlining of hash_combine to improve performance
This improved Turboshaft value numbering performance significantly in local testing. Change-Id: I8b8c8e3a67da9b83b57efc34c08ca693e84d9076 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3852486 Reviewed-by: Clemens Backes <clemensb@chromium.org> Commit-Queue: Tobias Tebbi <tebbi@chromium.org> Auto-Submit: Tobias Tebbi <tebbi@chromium.org> Cr-Commit-Position: refs/heads/main@{#82708}
This commit is contained in:
parent
a084d3e594
commit
d75a0eed1c
@ -607,7 +607,6 @@ filegroup(
|
||||
"src/base/file-utils.h",
|
||||
"src/base/flags.h",
|
||||
"src/base/free_deleter.h",
|
||||
"src/base/functional.cc",
|
||||
"src/base/functional.h",
|
||||
"src/base/hashmap-entry.h",
|
||||
"src/base/hashmap.h",
|
||||
|
1
BUILD.gn
1
BUILD.gn
@ -5430,7 +5430,6 @@ v8_component("v8_libbase") {
|
||||
"src/base/file-utils.h",
|
||||
"src/base/flags.h",
|
||||
"src/base/free_deleter.h",
|
||||
"src/base/functional.cc",
|
||||
"src/base/functional.h",
|
||||
"src/base/hashmap-entry.h",
|
||||
"src/base/hashmap.h",
|
||||
|
@ -1,110 +0,0 @@
|
||||
// Copyright 2014 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
//
|
||||
// This also contains public domain code from MurmurHash. From the
|
||||
// MurmurHash header:
|
||||
//
|
||||
// MurmurHash3 was written by Austin Appleby, and is placed in the public
|
||||
// domain. The author hereby disclaims copyright to this source code.
|
||||
|
||||
#include "src/base/functional.h"
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include "src/base/bits.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace base {
|
||||
|
||||
namespace {
|
||||
|
||||
// Thomas Wang, Integer Hash Functions.
|
||||
// https://gist.github.com/badboy/6267743
|
||||
template <typename T>
|
||||
V8_INLINE size_t hash_value_unsigned(T v) {
|
||||
switch (sizeof(T)) {
|
||||
case 4: {
|
||||
// "32 bit Mix Functions"
|
||||
v = ~v + (v << 15); // v = (v << 15) - v - 1;
|
||||
v = v ^ (v >> 12);
|
||||
v = v + (v << 2);
|
||||
v = v ^ (v >> 4);
|
||||
v = v * 2057; // v = (v + (v << 3)) + (v << 11);
|
||||
v = v ^ (v >> 16);
|
||||
return static_cast<size_t>(v);
|
||||
}
|
||||
case 8: {
|
||||
switch (sizeof(size_t)) {
|
||||
case 4: {
|
||||
// "64 bit to 32 bit Hash Functions"
|
||||
v = ~v + (v << 18); // v = (v << 18) - v - 1;
|
||||
v = v ^ (v >> 31);
|
||||
v = v * 21; // v = (v + (v << 2)) + (v << 4);
|
||||
v = v ^ (v >> 11);
|
||||
v = v + (v << 6);
|
||||
v = v ^ (v >> 22);
|
||||
return static_cast<size_t>(v);
|
||||
}
|
||||
case 8: {
|
||||
// "64 bit Mix Functions"
|
||||
v = ~v + (v << 21); // v = (v << 21) - v - 1;
|
||||
v = v ^ (v >> 24);
|
||||
v = (v + (v << 3)) + (v << 8); // v * 265
|
||||
v = v ^ (v >> 14);
|
||||
v = (v + (v << 2)) + (v << 4); // v * 21
|
||||
v = v ^ (v >> 28);
|
||||
v = v + (v << 31);
|
||||
return static_cast<size_t>(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
// This code was taken from MurmurHash.
|
||||
size_t hash_combine(size_t seed, size_t value) {
|
||||
#if V8_HOST_ARCH_32_BIT
|
||||
const uint32_t c1 = 0xCC9E2D51;
|
||||
const uint32_t c2 = 0x1B873593;
|
||||
|
||||
value *= c1;
|
||||
value = bits::RotateRight32(value, 15);
|
||||
value *= c2;
|
||||
|
||||
seed ^= value;
|
||||
seed = bits::RotateRight32(seed, 13);
|
||||
seed = seed * 5 + 0xE6546B64;
|
||||
#else
|
||||
const uint64_t m = uint64_t{0xC6A4A7935BD1E995};
|
||||
const uint32_t r = 47;
|
||||
|
||||
value *= m;
|
||||
value ^= value >> r;
|
||||
value *= m;
|
||||
|
||||
seed ^= value;
|
||||
seed *= m;
|
||||
#endif // V8_HOST_ARCH_32_BIT
|
||||
return seed;
|
||||
}
|
||||
|
||||
|
||||
size_t hash_value(unsigned int v) { return hash_value_unsigned(v); }
|
||||
|
||||
|
||||
size_t hash_value(unsigned long v) { // NOLINT(runtime/int)
|
||||
return hash_value_unsigned(v);
|
||||
}
|
||||
|
||||
|
||||
size_t hash_value(unsigned long long v) { // NOLINT(runtime/int)
|
||||
return hash_value_unsigned(v);
|
||||
}
|
||||
|
||||
} // namespace base
|
||||
} // namespace v8
|
@ -15,6 +15,7 @@
|
||||
#include <utility>
|
||||
|
||||
#include "src/base/base-export.h"
|
||||
#include "src/base/bits.h"
|
||||
#include "src/base/macros.h"
|
||||
|
||||
namespace v8 {
|
||||
@ -66,10 +67,80 @@ namespace base {
|
||||
template <typename>
|
||||
struct hash;
|
||||
|
||||
// Thomas Wang, Integer Hash Functions.
|
||||
// https://gist.github.com/badboy/6267743
|
||||
template <typename T>
|
||||
V8_INLINE size_t hash_value_unsigned_impl(T v) {
|
||||
switch (sizeof(T)) {
|
||||
case 4: {
|
||||
// "32 bit Mix Functions"
|
||||
v = ~v + (v << 15); // v = (v << 15) - v - 1;
|
||||
v = v ^ (v >> 12);
|
||||
v = v + (v << 2);
|
||||
v = v ^ (v >> 4);
|
||||
v = v * 2057; // v = (v + (v << 3)) + (v << 11);
|
||||
v = v ^ (v >> 16);
|
||||
return static_cast<size_t>(v);
|
||||
}
|
||||
case 8: {
|
||||
switch (sizeof(size_t)) {
|
||||
case 4: {
|
||||
// "64 bit to 32 bit Hash Functions"
|
||||
v = ~v + (v << 18); // v = (v << 18) - v - 1;
|
||||
v = v ^ (v >> 31);
|
||||
v = v * 21; // v = (v + (v << 2)) + (v << 4);
|
||||
v = v ^ (v >> 11);
|
||||
v = v + (v << 6);
|
||||
v = v ^ (v >> 22);
|
||||
return static_cast<size_t>(v);
|
||||
}
|
||||
case 8: {
|
||||
// "64 bit Mix Functions"
|
||||
v = ~v + (v << 21); // v = (v << 21) - v - 1;
|
||||
v = v ^ (v >> 24);
|
||||
v = (v + (v << 3)) + (v << 8); // v * 265
|
||||
v = v ^ (v >> 14);
|
||||
v = (v + (v << 2)) + (v << 4); // v * 21
|
||||
v = v ^ (v >> 28);
|
||||
v = v + (v << 31);
|
||||
return static_cast<size_t>(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
V8_INLINE size_t hash_combine() { return 0u; }
|
||||
V8_INLINE size_t hash_combine(size_t seed) { return seed; }
|
||||
V8_BASE_EXPORT size_t hash_combine(size_t seed, size_t value);
|
||||
|
||||
// This code was taken from MurmurHash.
|
||||
V8_INLINE size_t hash_combine(size_t seed, size_t value) {
|
||||
#if V8_HOST_ARCH_32_BIT
|
||||
const uint32_t c1 = 0xCC9E2D51;
|
||||
const uint32_t c2 = 0x1B873593;
|
||||
|
||||
value *= c1;
|
||||
value = bits::RotateRight32(value, 15);
|
||||
value *= c2;
|
||||
|
||||
seed ^= value;
|
||||
seed = bits::RotateRight32(seed, 13);
|
||||
seed = seed * 5 + 0xE6546B64;
|
||||
#else
|
||||
const uint64_t m = uint64_t{0xC6A4A7935BD1E995};
|
||||
const uint32_t r = 47;
|
||||
|
||||
value *= m;
|
||||
value ^= value >> r;
|
||||
value *= m;
|
||||
|
||||
seed ^= value;
|
||||
seed *= m;
|
||||
#endif // V8_HOST_ARCH_32_BIT
|
||||
return seed;
|
||||
}
|
||||
|
||||
template <typename T, typename... Ts>
|
||||
V8_INLINE size_t hash_combine(T const& v, Ts const&... vs) {
|
||||
return hash_combine(hash_combine(vs...), hash<T>()(v));
|
||||
@ -93,9 +164,17 @@ V8_BASE_HASH_VALUE_TRIVIAL(unsigned char)
|
||||
V8_BASE_HASH_VALUE_TRIVIAL(unsigned short) // NOLINT(runtime/int)
|
||||
#undef V8_BASE_HASH_VALUE_TRIVIAL
|
||||
|
||||
V8_BASE_EXPORT size_t hash_value(unsigned int);
|
||||
V8_BASE_EXPORT size_t hash_value(unsigned long); // NOLINT(runtime/int)
|
||||
V8_BASE_EXPORT size_t hash_value(unsigned long long); // NOLINT(runtime/int)
|
||||
V8_INLINE size_t hash_value(unsigned int v) {
|
||||
return hash_value_unsigned_impl(v);
|
||||
}
|
||||
|
||||
V8_INLINE size_t hash_value(unsigned long v) { // NOLINT(runtime/int)
|
||||
return hash_value_unsigned_impl(v);
|
||||
}
|
||||
|
||||
V8_INLINE size_t hash_value(unsigned long long v) { // NOLINT(runtime/int)
|
||||
return hash_value_unsigned_impl(v);
|
||||
}
|
||||
|
||||
#define V8_BASE_HASH_VALUE_SIGNED(type) \
|
||||
V8_INLINE size_t hash_value(signed type v) { \
|
||||
|
Loading…
Reference in New Issue
Block a user