LLVM 23.0.0git
DenseMapInfo.h
Go to the documentation of this file.
1//===- llvm/ADT/DenseMapInfo.h - Type traits for DenseMap -------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8///
9/// \file
10/// This file defines DenseMapInfo traits for DenseMap.
11///
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_ADT_DENSEMAPINFO_H
15#define LLVM_ADT_DENSEMAPINFO_H
16
17#include <cassert>
18#include <cstddef>
19#include <cstdint>
20#include <limits>
21#include <optional>
22#include <tuple>
23#include <type_traits>
24#include <utility>
25
26namespace llvm {
27
28namespace densemap::detail {
29// A bit mixer with very low latency using one multiplications and one
30// xor-shift. The constant is from splitmix64.
32 x *= 0xbf58476d1ce4e5b9u;
33 x ^= x >> 31;
34 return x;
35}
36} // namespace densemap::detail
37
38namespace detail {
39
40/// Simplistic combination of 32-bit hash values into 32-bit hash values.
41inline unsigned combineHashValue(unsigned a, unsigned b) {
42 uint64_t x = (uint64_t)a << 32 | (uint64_t)b;
43 return (unsigned)densemap::detail::mix(x);
44}
45
46} // end namespace detail
47
48/// An information struct used to provide DenseMap with the various necessary
49/// components for a given value type `T`. `Enable` is an optional additional
50/// parameter that is used to support SFINAE (generally using std::enable_if_t)
51/// in derived DenseMapInfo specializations; in non-SFINAE use cases this should
52/// just be `void`.
53template <typename T, typename Enable = void> struct DenseMapInfo {
54 // static unsigned getHashValue(const T &Val);
55 // static bool isEqual(const T &LHS, const T &RHS);
56};
57
58// Provide DenseMapInfo for all pointers. Avoid requiring T to be complete so
59// clients can instantiate DenseMap<T*, ...> with forward declared key types.
60template <typename T> struct DenseMapInfo<T *> {
61 static unsigned getHashValue(const T *PtrVal) {
62 return densemap::detail::mix(reinterpret_cast<uintptr_t>(PtrVal));
63 }
64
65 static bool isEqual(const T *LHS, const T *RHS) { return LHS == RHS; }
66};
67
68// Provide DenseMapInfo for all integral types.
69template <typename T>
70struct DenseMapInfo<T, std::enable_if_t<std::is_integral_v<T>>> {
71 static unsigned getHashValue(const T &Val) {
72 if constexpr (std::is_unsigned_v<T> && sizeof(T) > sizeof(unsigned))
73 return densemap::detail::mix(Val);
74 else
75 return static_cast<unsigned>(Val *
76 static_cast<std::make_unsigned_t<T>>(37U));
77 }
78
79 static bool isEqual(const T &LHS, const T &RHS) { return LHS == RHS; }
80};
81
82// Provide DenseMapInfo for all pairs whose members have info.
83template<typename T, typename U>
84struct DenseMapInfo<std::pair<T, U>> {
85 using Pair = std::pair<T, U>;
88
89 static unsigned getHashValue(const Pair& PairVal) {
90 return detail::combineHashValue(FirstInfo::getHashValue(PairVal.first),
91 SecondInfo::getHashValue(PairVal.second));
92 }
93
94 // Expose an additional function intended to be used by other
95 // specializations of DenseMapInfo without needing to know how
96 // to combine hash values manually
97 static unsigned getHashValuePiecewise(const T &First, const U &Second) {
98 return detail::combineHashValue(FirstInfo::getHashValue(First),
99 SecondInfo::getHashValue(Second));
100 }
101
102 static bool isEqual(const Pair &LHS, const Pair &RHS) {
103 return FirstInfo::isEqual(LHS.first, RHS.first) &&
104 SecondInfo::isEqual(LHS.second, RHS.second);
105 }
106};
107
108// Provide DenseMapInfo for all tuples whose members have info.
109template <typename... Ts> struct DenseMapInfo<std::tuple<Ts...>> {
110 using Tuple = std::tuple<Ts...>;
111
112 template <unsigned I> static unsigned getHashValueImpl(const Tuple &values) {
113 if constexpr (I == sizeof...(Ts)) {
114 return 0;
115 } else {
116 using EltType = std::tuple_element_t<I, Tuple>;
118 DenseMapInfo<EltType>::getHashValue(std::get<I>(values)),
120 }
121 }
122
123 static unsigned getHashValue(const std::tuple<Ts...> &values) {
124 return getHashValueImpl<0>(values);
125 }
126
127 template <std::size_t... Is>
128 static bool isEqualImpl(const Tuple &lhs, const Tuple &rhs,
129 std::index_sequence<Is...>) {
130 return (DenseMapInfo<std::tuple_element_t<Is, Tuple>>::isEqual(
131 std::get<Is>(lhs), std::get<Is>(rhs)) &&
132 ...);
133 }
134
135 static bool isEqual(const Tuple &lhs, const Tuple &rhs) {
136 return isEqualImpl(lhs, rhs, std::index_sequence_for<Ts...>{});
137 }
138};
139
140// Provide DenseMapInfo for enum classes.
141template <typename Enum>
142struct DenseMapInfo<Enum, std::enable_if_t<std::is_enum_v<Enum>>> {
143 using UnderlyingType = std::underlying_type_t<Enum>;
145
146 static unsigned getHashValue(const Enum &Val) {
147 return Info::getHashValue(static_cast<UnderlyingType>(Val));
148 }
149
150 static bool isEqual(const Enum &LHS, const Enum &RHS) { return LHS == RHS; }
151};
152
153template <typename T> struct DenseMapInfo<std::optional<T>> {
154 using Optional = std::optional<T>;
156
157 static unsigned getHashValue(const Optional &OptionalVal) {
158 if (OptionalVal)
159 return detail::combineHashValue(1, Info::getHashValue(*OptionalVal));
160 return 0;
161 }
162
163 static bool isEqual(const Optional &LHS, const Optional &RHS) {
164 if (LHS && RHS) {
165 return Info::isEqual(LHS.value(), RHS.value());
166 }
167 return !LHS && !RHS;
168 }
169};
170} // end namespace llvm
171
172#endif // LLVM_ADT_DENSEMAPINFO_H
static unsigned getHashValueImpl(SimpleValue Val)
Definition EarlyCSE.cpp:216
static bool isEqualImpl(SimpleValue LHS, SimpleValue RHS)
Definition EarlyCSE.cpp:337
#define I(x, y, z)
Definition MD5.cpp:57
#define T
Value * RHS
Value * LHS
uint64_t mix(uint64_t x)
unsigned combineHashValue(unsigned a, unsigned b)
Simplistic combination of 32-bit hash values into 32-bit hash values.
This is an optimization pass for GlobalISel generic memory operations.
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
Definition ModRef.h:74
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:860
static unsigned getHashValue(const T *PtrVal)
static bool isEqual(const T *LHS, const T *RHS)
static unsigned getHashValue(const Optional &OptionalVal)
static bool isEqual(const Optional &LHS, const Optional &RHS)
static unsigned getHashValuePiecewise(const T &First, const U &Second)
static unsigned getHashValue(const Pair &PairVal)
static bool isEqual(const Pair &LHS, const Pair &RHS)
static bool isEqualImpl(const Tuple &lhs, const Tuple &rhs, std::index_sequence< Is... >)
static unsigned getHashValue(const std::tuple< Ts... > &values)
static bool isEqual(const Tuple &lhs, const Tuple &rhs)
static unsigned getHashValueImpl(const Tuple &values)
An information struct used to provide DenseMap with the various necessary components for a given valu...