tint/writer: Replace use of strings for cache keys

Concatenating strings to use for cache keys is horribly inefficent and very error prone.

Add a UnorderedKeyWrapper helper to allow types to be used as a unordered_map and unordered_set key. Use this for the type_constructor_to_id_ map.

Produces SPIR-V with some duplicate SPIR-V instructions for constructors removed.

Change-Id: Ib072d485ca28bb07f03e979c133cdce1f69ee482
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/88300
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
Reviewed-by: Dan Sinclair <dsinclair@chromium.org>
This commit is contained in:
Ben Clayton
2022-04-28 13:08:22 +00:00
committed by Dawn LUCI CQ
parent 89fe801dff
commit 046abc08e8
8 changed files with 189 additions and 84 deletions

View File

@@ -18,6 +18,7 @@
#include <stdint.h>
#include <cstdio>
#include <functional>
#include <utility>
#include <vector>
namespace tint::utils {
@@ -76,6 +77,53 @@ size_t Hash(const ARGS&... args) {
return hash;
}
/// Wrapper for a hashable type enabling the wrapped value to be used as a key
/// for an unordered_map or unordered_set.
template <typename T>
struct UnorderedKeyWrapper {
/// The wrapped value
const T value;
/// The hash of value
const size_t hash;
/// Constructor
/// @param v the value to wrap
explicit UnorderedKeyWrapper(const T& v) : value(v), hash(Hash(v)) {}
/// Move constructor
/// @param v the value to wrap
explicit UnorderedKeyWrapper(T&& v)
: value(std::move(v)), hash(Hash(value)) {}
/// @returns true if this wrapper comes before other
/// @param other the RHS of the operator
bool operator<(const UnorderedKeyWrapper& other) const {
return hash < other.hash;
}
/// @returns true if this wrapped value is equal to the other wrapped value
/// @param other the RHS of the operator
bool operator==(const UnorderedKeyWrapper& other) const {
return value == other.value;
}
};
} // namespace tint::utils
namespace std {
/// Custom std::hash specialization for tint::utils::UnorderedKeyWrapper
template <typename T>
class hash<tint::utils::UnorderedKeyWrapper<T>> {
public:
/// @param w the UnorderedKeyWrapper
/// @return the hash value
inline std::size_t operator()(
const tint::utils::UnorderedKeyWrapper<T>& w) const {
return w.hash;
}
};
} // namespace std
#endif // SRC_TINT_UTILS_HASH_H_

View File

@@ -15,6 +15,7 @@
#include "src/tint/utils/hash.h"
#include <string>
#include <unordered_map>
#include "gtest/gtest.h"
@@ -43,5 +44,30 @@ TEST(HashTests, Vector) {
Hash(std::vector<int>({1, 2, 3, 4})));
}
TEST(HashTests, UnorderedKeyWrapper) {
using W = UnorderedKeyWrapper<std::vector<int>>;
std::unordered_map<W, int> m;
m.emplace(W{{1, 2}}, -1);
EXPECT_EQ(m.size(), 1u);
EXPECT_EQ(m[W({1, 2})], -1);
m.emplace(W{{3, 2}}, 1);
EXPECT_EQ(m.size(), 2u);
EXPECT_EQ(m[W({3, 2})], 1);
EXPECT_EQ(m[W({1, 2})], -1);
m.emplace(W{{100}}, 100);
EXPECT_EQ(m.size(), 3u);
EXPECT_EQ(m[W({100})], 100);
EXPECT_EQ(m[W({3, 2})], 1);
EXPECT_EQ(m[W({1, 2})], -1);
// Reversed vector element order
EXPECT_EQ(m[W({2, 3})], 0);
EXPECT_EQ(m[W({2, 1})], 0);
}
} // namespace
} // namespace tint::utils