[turboshaft] faster hash for GVN
Bug: v8:12783 Change-Id: I97f6a28bfef7c9aed679c84f33d60a71cf467718 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3859327 Reviewed-by: Darius Mercadier <dmercadier@chromium.org> Commit-Queue: Tobias Tebbi <tebbi@chromium.org> Cr-Commit-Position: refs/heads/main@{#82865}
This commit is contained in:
parent
f6a1f55c3b
commit
9bbc13bd40
@ -2863,6 +2863,7 @@ filegroup(
|
||||
"src/compiler/turboshaft/decompression-optimization.cc",
|
||||
"src/compiler/turboshaft/decompression-optimization.h",
|
||||
"src/compiler/turboshaft/deopt-data.h",
|
||||
"src/compiler/turboshaft/fast-hash.h",
|
||||
"src/compiler/turboshaft/graph-builder.cc",
|
||||
"src/compiler/turboshaft/graph-builder.h",
|
||||
"src/compiler/turboshaft/graph.cc",
|
||||
|
1
BUILD.gn
1
BUILD.gn
@ -2988,6 +2988,7 @@ v8_header_set("v8_internal_headers") {
|
||||
"src/compiler/turboshaft/assembler.h",
|
||||
"src/compiler/turboshaft/decompression-optimization.h",
|
||||
"src/compiler/turboshaft/deopt-data.h",
|
||||
"src/compiler/turboshaft/fast-hash.h",
|
||||
"src/compiler/turboshaft/graph-builder.h",
|
||||
"src/compiler/turboshaft/graph-visualizer.h",
|
||||
"src/compiler/turboshaft/graph.h",
|
||||
|
73
src/compiler/turboshaft/fast-hash.h
Normal file
73
src/compiler/turboshaft/fast-hash.h
Normal file
@ -0,0 +1,73 @@
|
||||
// Copyright 2022 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.
|
||||
|
||||
#ifndef V8_COMPILER_TURBOSHAFT_FAST_HASH_H_
|
||||
#define V8_COMPILER_TURBOSHAFT_FAST_HASH_H_
|
||||
|
||||
#include <tuple>
|
||||
|
||||
#include "src/base/functional.h"
|
||||
#include "src/base/vector.h"
|
||||
|
||||
namespace v8::internal::compiler::turboshaft {
|
||||
|
||||
// fast_hash_combine() / fast_hash_value() produce a bad but very fast to
|
||||
// compute hash, intended for hash-tables and only usable for data that is
|
||||
// sufficiently random already and has high variance in their low bits.
|
||||
|
||||
V8_INLINE size_t fast_hash_combine() { return 0u; }
|
||||
V8_INLINE size_t fast_hash_combine(size_t acc) { return acc; }
|
||||
V8_INLINE size_t fast_hash_combine(size_t acc, size_t value) {
|
||||
return 17 * acc + value;
|
||||
}
|
||||
template <typename T, typename... Ts>
|
||||
V8_INLINE size_t fast_hash_combine(T const& v, Ts const&... vs);
|
||||
|
||||
template <class T>
|
||||
struct fast_hash {
|
||||
size_t operator()(const T& v) {
|
||||
if constexpr (std::is_enum<T>::value) {
|
||||
return static_cast<size_t>(v);
|
||||
} else {
|
||||
return base::hash<T>()(v);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <class... Ts>
|
||||
struct fast_hash<std::tuple<Ts...>> {
|
||||
size_t operator()(const std::tuple<Ts...>& v) {
|
||||
return impl(v, std::make_index_sequence<sizeof...(Ts)>());
|
||||
}
|
||||
|
||||
template <size_t... I>
|
||||
V8_INLINE size_t impl(std::tuple<Ts...> const& v, std::index_sequence<I...>) {
|
||||
return fast_hash_combine(std::get<I>(v)...);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename... Ts>
|
||||
V8_INLINE size_t fast_hash_combine(T const& v, Ts const&... vs) {
|
||||
return fast_hash_combine(fast_hash_combine(vs...), fast_hash<T>()(v));
|
||||
}
|
||||
|
||||
template <typename Iterator>
|
||||
V8_INLINE size_t fast_hash_range(Iterator first, Iterator last) {
|
||||
size_t acc = 0;
|
||||
for (; first != last; ++first) {
|
||||
acc = fast_hash_combine(acc, *first);
|
||||
}
|
||||
return acc;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
struct fast_hash<base::Vector<T>> {
|
||||
V8_INLINE size_t operator()(base::Vector<T> v) {
|
||||
return fast_hash_range(v.begin(), v.end());
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace v8::internal::compiler::turboshaft
|
||||
|
||||
#endif // V8_COMPILER_TURBOSHAFT_FAST_HASH_H_
|
@ -24,6 +24,7 @@
|
||||
#include "src/codegen/machine-type.h"
|
||||
#include "src/common/globals.h"
|
||||
#include "src/compiler/globals.h"
|
||||
#include "src/compiler/turboshaft/fast-hash.h"
|
||||
#include "src/compiler/turboshaft/utils.h"
|
||||
#include "src/compiler/write-barrier-kind.h"
|
||||
#include "src/zone/zone.h"
|
||||
@ -177,7 +178,10 @@ class OpIndex {
|
||||
static constexpr uint32_t kTurbofanNodeIdFlag = 1;
|
||||
};
|
||||
|
||||
V8_INLINE size_t hash_value(OpIndex op) { return op.id(); }
|
||||
template <>
|
||||
struct fast_hash<OpIndex> {
|
||||
V8_INLINE size_t operator()(OpIndex op) { return op.id(); }
|
||||
};
|
||||
|
||||
// `BlockIndex` is the index of a bound block.
|
||||
// A dominating block always has a smaller index.
|
||||
@ -203,7 +207,10 @@ class BlockIndex {
|
||||
uint32_t id_;
|
||||
};
|
||||
|
||||
V8_INLINE size_t hash_value(BlockIndex b) { return b.id(); }
|
||||
template <>
|
||||
struct fast_hash<BlockIndex> {
|
||||
V8_INLINE size_t operator()(BlockIndex op) { return op.id(); }
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, BlockIndex b);
|
||||
std::ostream& operator<<(std::ostream& os, const Block* b);
|
||||
@ -419,7 +426,7 @@ struct OperationT : Operation {
|
||||
derived_this().options() == other.derived_this().options();
|
||||
}
|
||||
size_t hash_value() const {
|
||||
return base::hash_combine(opcode, derived_this().inputs(),
|
||||
return fast_hash_combine(opcode, derived_this().inputs(),
|
||||
derived_this().options());
|
||||
}
|
||||
|
||||
@ -1154,17 +1161,17 @@ struct ConstantOp : FixedArityOperationT<0, ConstantOp> {
|
||||
case Kind::kWord32:
|
||||
case Kind::kWord64:
|
||||
case Kind::kTaggedIndex:
|
||||
return base::hash_combine(kind, storage.integral);
|
||||
return fast_hash_combine(opcode, kind, storage.integral);
|
||||
case Kind::kFloat32:
|
||||
return base::hash_combine(kind, storage.float32);
|
||||
return fast_hash_combine(opcode, kind, storage.float32);
|
||||
case Kind::kFloat64:
|
||||
case Kind::kNumber:
|
||||
return base::hash_combine(kind, storage.float64);
|
||||
return fast_hash_combine(opcode, kind, storage.float64);
|
||||
case Kind::kExternal:
|
||||
return base::hash_combine(kind, storage.external.address());
|
||||
return fast_hash_combine(opcode, kind, storage.external.address());
|
||||
case Kind::kHeapObject:
|
||||
case Kind::kCompressedHeapObject:
|
||||
return base::hash_combine(kind, storage.handle.address());
|
||||
return fast_hash_combine(opcode, kind, storage.handle.address());
|
||||
}
|
||||
}
|
||||
bool operator==(const ConstantOp& other) const {
|
||||
@ -1563,9 +1570,7 @@ struct SwitchOp : FixedArityOperationT<1, SwitchOp> {
|
||||
|
||||
Case(int32_t value, Block* destination)
|
||||
: value(value), destination(destination) {}
|
||||
friend size_t hash_value(Case v) {
|
||||
return base::hash_combine(v.value, v.destination);
|
||||
}
|
||||
|
||||
bool operator==(const Case& other) const {
|
||||
return value == other.value && destination == other.destination;
|
||||
}
|
||||
@ -1583,6 +1588,13 @@ struct SwitchOp : FixedArityOperationT<1, SwitchOp> {
|
||||
auto options() const { return std::tuple{cases, default_case}; }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct fast_hash<SwitchOp::Case> {
|
||||
size_t operator()(SwitchOp::Case v) {
|
||||
return fast_hash_combine(v.value, v.destination);
|
||||
}
|
||||
};
|
||||
|
||||
// Tuples are only used to lower operations with multiple outputs.
|
||||
// `TupleOp` should be folded away by subsequent `ProjectionOp`s.
|
||||
struct TupleOp : OperationT<TupleOp> {
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "src/base/logging.h"
|
||||
#include "src/base/vector.h"
|
||||
#include "src/compiler/turboshaft/assembler.h"
|
||||
#include "src/compiler/turboshaft/fast-hash.h"
|
||||
#include "src/compiler/turboshaft/graph.h"
|
||||
#include "src/compiler/turboshaft/operations.h"
|
||||
#include "src/utils/utils.h"
|
||||
@ -239,7 +240,7 @@ class ValueNumberingAssembler : public Assembler {
|
||||
size_t ComputeHash(const Op& op) {
|
||||
size_t hash = op.hash_value();
|
||||
if (same_block_only) {
|
||||
hash = base::hash_combine(current_block()->index(), hash);
|
||||
hash = fast_hash_combine(current_block()->index(), hash);
|
||||
}
|
||||
if (V8_UNLIKELY(hash == 0)) return 1;
|
||||
return hash;
|
||||
|
Loading…
Reference in New Issue
Block a user