LLVM 24.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 <cstddef>
18#include <cstdint>
19#include <optional>
20#include <tuple>
21#include <type_traits>
22#include <utility>
23
24namespace llvm {
25
26namespace densemap::detail {
27// A bit mixer with very low latency using one multiplications and one
28// xor-shift. The constant is from splitmix64.
30 x *= 0xbf58476d1ce4e5b9u;
31 x ^= x >> 31;
32 return x;
33}
34} // namespace densemap::detail
35
36namespace detail {
37
38/// Simplistic combination of 32-bit hash values into 32-bit hash values.
39inline unsigned combineHashValue(unsigned a, unsigned b) {
40 uint64_t x = (uint64_t)a << 32 | (uint64_t)b;
41 return (unsigned)densemap::detail::mix(x);
42}
43
44} // end namespace detail
45
46/// An information struct used to provide DenseMap with the various necessary
47/// components for a given value type `T`. `Enable` is an optional additional
48/// parameter that is used to support SFINAE (generally using std::enable_if_t)
49/// in derived DenseMapInfo specializations; in non-SFINAE use cases this should
50/// just be `void`.
51template <typename T, typename Enable = void> struct DenseMapInfo {
52 // static unsigned getHashValue(const T &Val);
53 // static bool isEqual(const T &LHS, const T &RHS);
54};
55
56// Provide DenseMapInfo for all pointers. Avoid requiring T to be complete so
57// clients can instantiate DenseMap<T*, ...> with forward declared key types.
58template <typename T> struct DenseMapInfo<T *> {
59 // Select InlinePtrHash in DenseMap.cpp.
61
62 static unsigned getHashValue(const T *PtrVal) {
63 return densemap::detail::mix(reinterpret_cast<uintptr_t>(PtrVal));
64 }
65
66 static bool isEqual(const T *LHS, const T *RHS) { return LHS == RHS; }
67};
68
69// Provide DenseMapInfo for all integral types.
70template <typename T>
71struct DenseMapInfo<T, std::enable_if_t<std::is_integral_v<T>>> {
72 static unsigned getHashValue(const T &Val) {
73 if constexpr (std::is_unsigned_v<T> && sizeof(T) > sizeof(unsigned))
74 return densemap::detail::mix(Val);
75 else
76 return static_cast<unsigned>(Val *
77 static_cast<std::make_unsigned_t<T>>(37U));
78 }
79
80 static bool isEqual(const T &LHS, const T &RHS) { return LHS == RHS; }
81};
82
83// Provide DenseMapInfo for all pairs whose members have info.
84template<typename T, typename U>
85struct DenseMapInfo<std::pair<T, U>> {
86 using Pair = std::pair<T, U>;
89
90 static unsigned getHashValue(const Pair& PairVal) {
91 return detail::combineHashValue(FirstInfo::getHashValue(PairVal.first),
92 SecondInfo::getHashValue(PairVal.second));
93 }
94
95 // Expose an additional function intended to be used by other
96 // specializations of DenseMapInfo without needing to know how
97 // to combine hash values manually
98 static unsigned getHashValuePiecewise(const T &First, const U &Second) {
99 return detail::combineHashValue(FirstInfo::getHashValue(First),
100 SecondInfo::getHashValue(Second));
101 }
102
103 static bool isEqual(const Pair &LHS, const Pair &RHS) {
104 return FirstInfo::isEqual(LHS.first, RHS.first) &&
105 SecondInfo::isEqual(LHS.second, RHS.second);
106 }
107};
108
109// Provide DenseMapInfo for all tuples whose members have info.
110template <typename... Ts> struct DenseMapInfo<std::tuple<Ts...>> {
111 using Tuple = std::tuple<Ts...>;
112
113 template <unsigned I> static unsigned getHashValueImpl(const Tuple &values) {
114 if constexpr (I == sizeof...(Ts)) {
115 return 0;
116 } else {
117 using EltType = std::tuple_element_t<I, Tuple>;
119 DenseMapInfo<EltType>::getHashValue(std::get<I>(values)),
121 }
122 }
123
124 static unsigned getHashValue(const std::tuple<Ts...> &values) {
125 return getHashValueImpl<0>(values);
126 }
127
128 template <std::size_t... Is>
129 static bool isEqualImpl(const Tuple &lhs, const Tuple &rhs,
130 std::index_sequence<Is...>) {
131 return (DenseMapInfo<std::tuple_element_t<Is, Tuple>>::isEqual(
132 std::get<Is>(lhs), std::get<Is>(rhs)) &&
133 ...);
134 }
135
136 static bool isEqual(const Tuple &lhs, const Tuple &rhs) {
137 return isEqualImpl(lhs, rhs, std::index_sequence_for<Ts...>{});
138 }
139};
140
141// Provide DenseMapInfo for enum classes.
142template <typename Enum>
143struct DenseMapInfo<Enum, std::enable_if_t<std::is_enum_v<Enum>>> {
144 using UnderlyingType = std::underlying_type_t<Enum>;
146
147 static unsigned getHashValue(const Enum &Val) {
148 return Info::getHashValue(static_cast<UnderlyingType>(Val));
149 }
150
151 static bool isEqual(const Enum &LHS, const Enum &RHS) { return LHS == RHS; }
152};
153
154template <typename T> struct DenseMapInfo<std::optional<T>> {
155 using Optional = std::optional<T>;
157
158 static unsigned getHashValue(const Optional &OptionalVal) {
159 if (OptionalVal)
160 return detail::combineHashValue(1, Info::getHashValue(*OptionalVal));
161 return 0;
162 }
163
164 static bool isEqual(const Optional &LHS, const Optional &RHS) {
165 if (LHS && RHS) {
166 return Info::isEqual(LHS.value(), RHS.value());
167 }
168 return !LHS && !RHS;
169 }
170};
171} // end namespace llvm
172
173#endif // LLVM_ADT_DENSEMAPINFO_H
unsigned uint64_t
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:878
DenseMapInfo PointerValueHash
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...