Skip to content

Commit f52ec5d

Browse files
committed
[llvm][DenseMapInfo] Add an info specialization for std::tuple
This revision adds a DenseMapInfo overload for std::tuples whose elements all have a DenseMapInfo. The implementation is similar to that of std::pair, and has been used within MLIR for over a year. Differential Revision: https://reviews.llvm.org/D78057
1 parent 483f278 commit f52ec5d

File tree

2 files changed

+70
-81
lines changed

2 files changed

+70
-81
lines changed

llvm/include/llvm/ADT/DenseMapInfo.h

+70-11
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,24 @@
2323

2424
namespace llvm {
2525

26+
namespace detail {
27+
28+
/// Simplistic combination of 32-bit hash values into 32-bit hash values.
29+
static inline unsigned combineHashValue(unsigned a, unsigned b) {
30+
uint64_t key = (uint64_t)a << 32 | (uint64_t)b;
31+
key += ~(key << 32);
32+
key ^= (key >> 22);
33+
key += ~(key << 13);
34+
key ^= (key >> 8);
35+
key += (key << 3);
36+
key ^= (key >> 15);
37+
key += ~(key << 27);
38+
key ^= (key >> 31);
39+
return (unsigned)key;
40+
}
41+
42+
} // end namespace detail
43+
2644
template<typename T>
2745
struct DenseMapInfo {
2846
//static inline T getEmptyKey();
@@ -206,17 +224,8 @@ struct DenseMapInfo<std::pair<T, U>> {
206224
}
207225

208226
static unsigned getHashValue(const Pair& PairVal) {
209-
uint64_t key = (uint64_t)FirstInfo::getHashValue(PairVal.first) << 32
210-
| (uint64_t)SecondInfo::getHashValue(PairVal.second);
211-
key += ~(key << 32);
212-
key ^= (key >> 22);
213-
key += ~(key << 13);
214-
key ^= (key >> 8);
215-
key += (key << 3);
216-
key ^= (key >> 15);
217-
key += ~(key << 27);
218-
key ^= (key >> 31);
219-
return (unsigned)key;
227+
return detail::combineHashValue(FirstInfo::getHashValue(PairVal.first),
228+
SecondInfo::getHashValue(PairVal.second));
220229
}
221230

222231
static bool isEqual(const Pair &LHS, const Pair &RHS) {
@@ -225,6 +234,56 @@ struct DenseMapInfo<std::pair<T, U>> {
225234
}
226235
};
227236

237+
// Provide DenseMapInfo for all tuples whose members have info.
238+
template <typename... Ts> struct DenseMapInfo<std::tuple<Ts...>> {
239+
using Tuple = std::tuple<Ts...>;
240+
241+
static inline Tuple getEmptyKey() {
242+
return Tuple(DenseMapInfo<Ts>::getEmptyKey()...);
243+
}
244+
245+
static inline Tuple getTombstoneKey() {
246+
return Tuple(DenseMapInfo<Ts>::getTombstoneKey()...);
247+
}
248+
249+
template <unsigned I>
250+
static unsigned getHashValueImpl(const Tuple &values, std::false_type) {
251+
using EltType = typename std::tuple_element<I, Tuple>::type;
252+
std::integral_constant<bool, I + 1 == sizeof...(Ts)> atEnd;
253+
return detail::combineHashValue(
254+
DenseMapInfo<EltType>::getHashValue(std::get<I>(values)),
255+
getHashValueImpl<I + 1>(values, atEnd));
256+
}
257+
258+
template <unsigned I>
259+
static unsigned getHashValueImpl(const Tuple &values, std::true_type) {
260+
return 0;
261+
}
262+
263+
static unsigned getHashValue(const std::tuple<Ts...> &values) {
264+
std::integral_constant<bool, 0 == sizeof...(Ts)> atEnd;
265+
return getHashValueImpl<0>(values, atEnd);
266+
}
267+
268+
template <unsigned I>
269+
static bool isEqualImpl(const Tuple &lhs, const Tuple &rhs, std::false_type) {
270+
using EltType = typename std::tuple_element<I, Tuple>::type;
271+
std::integral_constant<bool, I + 1 == sizeof...(Ts)> atEnd;
272+
return DenseMapInfo<EltType>::isEqual(std::get<I>(lhs), std::get<I>(rhs)) &&
273+
isEqualImpl<I + 1>(lhs, rhs, atEnd);
274+
}
275+
276+
template <unsigned I>
277+
static bool isEqualImpl(const Tuple &lhs, const Tuple &rhs, std::true_type) {
278+
return true;
279+
}
280+
281+
static bool isEqual(const Tuple &lhs, const Tuple &rhs) {
282+
std::integral_constant<bool, 0 == sizeof...(Ts)> atEnd;
283+
return isEqualImpl<0>(lhs, rhs, atEnd);
284+
}
285+
};
286+
228287
// Provide DenseMapInfo for StringRefs.
229288
template <> struct DenseMapInfo<StringRef> {
230289
static inline StringRef getEmptyKey() {

mlir/include/mlir/Support/STLExtras.h

-70
Original file line numberDiff line numberDiff line change
@@ -399,74 +399,4 @@ struct FunctionTraits<ReturnType (&)(Args...), false>
399399
: public FunctionTraits<ReturnType (*)(Args...)> {};
400400
} // end namespace mlir
401401

402-
// Allow tuples to be usable as DenseMap keys.
403-
// TODO: Move this to upstream LLVM.
404-
405-
/// Simplistic combination of 32-bit hash values into 32-bit hash values.
406-
/// This function is taken from llvm/ADT/DenseMapInfo.h.
407-
static inline unsigned llvm_combineHashValue(unsigned a, unsigned b) {
408-
uint64_t key = (uint64_t)a << 32 | (uint64_t)b;
409-
key += ~(key << 32);
410-
key ^= (key >> 22);
411-
key += ~(key << 13);
412-
key ^= (key >> 8);
413-
key += (key << 3);
414-
key ^= (key >> 15);
415-
key += ~(key << 27);
416-
key ^= (key >> 31);
417-
return (unsigned)key;
418-
}
419-
420-
namespace llvm {
421-
template <typename... Ts> struct DenseMapInfo<std::tuple<Ts...>> {
422-
using Tuple = std::tuple<Ts...>;
423-
424-
static inline Tuple getEmptyKey() {
425-
return Tuple(DenseMapInfo<Ts>::getEmptyKey()...);
426-
}
427-
428-
static inline Tuple getTombstoneKey() {
429-
return Tuple(DenseMapInfo<Ts>::getTombstoneKey()...);
430-
}
431-
432-
template <unsigned I>
433-
static unsigned getHashValueImpl(const Tuple &values, std::false_type) {
434-
using EltType = typename std::tuple_element<I, Tuple>::type;
435-
std::integral_constant<bool, I + 1 == sizeof...(Ts)> atEnd;
436-
return llvm_combineHashValue(
437-
DenseMapInfo<EltType>::getHashValue(std::get<I>(values)),
438-
getHashValueImpl<I + 1>(values, atEnd));
439-
}
440-
441-
template <unsigned I>
442-
static unsigned getHashValueImpl(const Tuple &values, std::true_type) {
443-
return 0;
444-
}
445-
446-
static unsigned getHashValue(const std::tuple<Ts...> &values) {
447-
std::integral_constant<bool, 0 == sizeof...(Ts)> atEnd;
448-
return getHashValueImpl<0>(values, atEnd);
449-
}
450-
451-
template <unsigned I>
452-
static bool isEqualImpl(const Tuple &lhs, const Tuple &rhs, std::false_type) {
453-
using EltType = typename std::tuple_element<I, Tuple>::type;
454-
std::integral_constant<bool, I + 1 == sizeof...(Ts)> atEnd;
455-
return DenseMapInfo<EltType>::isEqual(std::get<I>(lhs), std::get<I>(rhs)) &&
456-
isEqualImpl<I + 1>(lhs, rhs, atEnd);
457-
}
458-
459-
template <unsigned I>
460-
static bool isEqualImpl(const Tuple &lhs, const Tuple &rhs, std::true_type) {
461-
return true;
462-
}
463-
464-
static bool isEqual(const Tuple &lhs, const Tuple &rhs) {
465-
std::integral_constant<bool, 0 == sizeof...(Ts)> atEnd;
466-
return isEqualImpl<0>(lhs, rhs, atEnd);
467-
}
468-
};
469-
470-
} // end namespace llvm
471-
472402
#endif // MLIR_SUPPORT_STLEXTRAS_H

0 commit comments

Comments
 (0)