DenseMapInfo.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397
  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. // This file defines DenseMapInfo traits for DenseMap.
  10. //
  11. //===----------------------------------------------------------------------===//
  12. #ifndef LLVM_ADT_DENSEMAPINFO_H
  13. #define LLVM_ADT_DENSEMAPINFO_H
  14. #include "llvm/ADT/APInt.h"
  15. #include "llvm/ADT/APSInt.h"
  16. #include "llvm/ADT/ArrayRef.h"
  17. #include "llvm/ADT/Hashing.h"
  18. #include "llvm/ADT/StringRef.h"
  19. #include <cassert>
  20. #include <cstddef>
  21. #include <cstdint>
  22. #include <utility>
  23. namespace llvm {
  24. namespace detail {
  25. /// Simplistic combination of 32-bit hash values into 32-bit hash values.
  26. static inline unsigned combineHashValue(unsigned a, unsigned b) {
  27. uint64_t key = (uint64_t)a << 32 | (uint64_t)b;
  28. key += ~(key << 32);
  29. key ^= (key >> 22);
  30. key += ~(key << 13);
  31. key ^= (key >> 8);
  32. key += (key << 3);
  33. key ^= (key >> 15);
  34. key += ~(key << 27);
  35. key ^= (key >> 31);
  36. return (unsigned)key;
  37. }
  38. } // end namespace detail
  39. template<typename T>
  40. struct DenseMapInfo {
  41. //static inline T getEmptyKey();
  42. //static inline T getTombstoneKey();
  43. //static unsigned getHashValue(const T &Val);
  44. //static bool isEqual(const T &LHS, const T &RHS);
  45. };
  46. // Provide DenseMapInfo for all pointers. Come up with sentinel pointer values
  47. // that are aligned to alignof(T) bytes, but try to avoid requiring T to be
  48. // complete. This allows clients to instantiate DenseMap<T*, ...> with forward
  49. // declared key types. Assume that no pointer key type requires more than 4096
  50. // bytes of alignment.
  51. template<typename T>
  52. struct DenseMapInfo<T*> {
  53. // The following should hold, but it would require T to be complete:
  54. // static_assert(alignof(T) <= (1 << Log2MaxAlign),
  55. // "DenseMap does not support pointer keys requiring more than "
  56. // "Log2MaxAlign bits of alignment");
  57. static constexpr uintptr_t Log2MaxAlign = 12;
  58. static inline T* getEmptyKey() {
  59. uintptr_t Val = static_cast<uintptr_t>(-1);
  60. Val <<= Log2MaxAlign;
  61. return reinterpret_cast<T*>(Val);
  62. }
  63. static inline T* getTombstoneKey() {
  64. uintptr_t Val = static_cast<uintptr_t>(-2);
  65. Val <<= Log2MaxAlign;
  66. return reinterpret_cast<T*>(Val);
  67. }
  68. static unsigned getHashValue(const T *PtrVal) {
  69. return (unsigned((uintptr_t)PtrVal) >> 4) ^
  70. (unsigned((uintptr_t)PtrVal) >> 9);
  71. }
  72. static bool isEqual(const T *LHS, const T *RHS) { return LHS == RHS; }
  73. };
  74. // Provide DenseMapInfo for chars.
  75. template<> struct DenseMapInfo<char> {
  76. static inline char getEmptyKey() { return ~0; }
  77. static inline char getTombstoneKey() { return ~0 - 1; }
  78. static unsigned getHashValue(const char& Val) { return Val * 37U; }
  79. static bool isEqual(const char &LHS, const char &RHS) {
  80. return LHS == RHS;
  81. }
  82. };
  83. // Provide DenseMapInfo for unsigned chars.
  84. template <> struct DenseMapInfo<unsigned char> {
  85. static inline unsigned char getEmptyKey() { return ~0; }
  86. static inline unsigned char getTombstoneKey() { return ~0 - 1; }
  87. static unsigned getHashValue(const unsigned char &Val) { return Val * 37U; }
  88. static bool isEqual(const unsigned char &LHS, const unsigned char &RHS) {
  89. return LHS == RHS;
  90. }
  91. };
  92. // Provide DenseMapInfo for unsigned shorts.
  93. template <> struct DenseMapInfo<unsigned short> {
  94. static inline unsigned short getEmptyKey() { return 0xFFFF; }
  95. static inline unsigned short getTombstoneKey() { return 0xFFFF - 1; }
  96. static unsigned getHashValue(const unsigned short &Val) { return Val * 37U; }
  97. static bool isEqual(const unsigned short &LHS, const unsigned short &RHS) {
  98. return LHS == RHS;
  99. }
  100. };
  101. // Provide DenseMapInfo for unsigned ints.
  102. template<> struct DenseMapInfo<unsigned> {
  103. static inline unsigned getEmptyKey() { return ~0U; }
  104. static inline unsigned getTombstoneKey() { return ~0U - 1; }
  105. static unsigned getHashValue(const unsigned& Val) { return Val * 37U; }
  106. static bool isEqual(const unsigned& LHS, const unsigned& RHS) {
  107. return LHS == RHS;
  108. }
  109. };
  110. // Provide DenseMapInfo for unsigned longs.
  111. template<> struct DenseMapInfo<unsigned long> {
  112. static inline unsigned long getEmptyKey() { return ~0UL; }
  113. static inline unsigned long getTombstoneKey() { return ~0UL - 1L; }
  114. static unsigned getHashValue(const unsigned long& Val) {
  115. return (unsigned)(Val * 37UL);
  116. }
  117. static bool isEqual(const unsigned long& LHS, const unsigned long& RHS) {
  118. return LHS == RHS;
  119. }
  120. };
  121. // Provide DenseMapInfo for unsigned long longs.
  122. template<> struct DenseMapInfo<unsigned long long> {
  123. static inline unsigned long long getEmptyKey() { return ~0ULL; }
  124. static inline unsigned long long getTombstoneKey() { return ~0ULL - 1ULL; }
  125. static unsigned getHashValue(const unsigned long long& Val) {
  126. return (unsigned)(Val * 37ULL);
  127. }
  128. static bool isEqual(const unsigned long long& LHS,
  129. const unsigned long long& RHS) {
  130. return LHS == RHS;
  131. }
  132. };
  133. // Provide DenseMapInfo for shorts.
  134. template <> struct DenseMapInfo<short> {
  135. static inline short getEmptyKey() { return 0x7FFF; }
  136. static inline short getTombstoneKey() { return -0x7FFF - 1; }
  137. static unsigned getHashValue(const short &Val) { return Val * 37U; }
  138. static bool isEqual(const short &LHS, const short &RHS) { return LHS == RHS; }
  139. };
  140. // Provide DenseMapInfo for ints.
  141. template<> struct DenseMapInfo<int> {
  142. static inline int getEmptyKey() { return 0x7fffffff; }
  143. static inline int getTombstoneKey() { return -0x7fffffff - 1; }
  144. static unsigned getHashValue(const int& Val) { return (unsigned)(Val * 37U); }
  145. static bool isEqual(const int& LHS, const int& RHS) {
  146. return LHS == RHS;
  147. }
  148. };
  149. // Provide DenseMapInfo for longs.
  150. template<> struct DenseMapInfo<long> {
  151. static inline long getEmptyKey() {
  152. return (1UL << (sizeof(long) * 8 - 1)) - 1UL;
  153. }
  154. static inline long getTombstoneKey() { return getEmptyKey() - 1L; }
  155. static unsigned getHashValue(const long& Val) {
  156. return (unsigned)(Val * 37UL);
  157. }
  158. static bool isEqual(const long& LHS, const long& RHS) {
  159. return LHS == RHS;
  160. }
  161. };
  162. // Provide DenseMapInfo for long longs.
  163. template<> struct DenseMapInfo<long long> {
  164. static inline long long getEmptyKey() { return 0x7fffffffffffffffLL; }
  165. static inline long long getTombstoneKey() { return -0x7fffffffffffffffLL-1; }
  166. static unsigned getHashValue(const long long& Val) {
  167. return (unsigned)(Val * 37ULL);
  168. }
  169. static bool isEqual(const long long& LHS,
  170. const long long& RHS) {
  171. return LHS == RHS;
  172. }
  173. };
  174. // Provide DenseMapInfo for all pairs whose members have info.
  175. template<typename T, typename U>
  176. struct DenseMapInfo<std::pair<T, U>> {
  177. using Pair = std::pair<T, U>;
  178. using FirstInfo = DenseMapInfo<T>;
  179. using SecondInfo = DenseMapInfo<U>;
  180. static inline Pair getEmptyKey() {
  181. return std::make_pair(FirstInfo::getEmptyKey(),
  182. SecondInfo::getEmptyKey());
  183. }
  184. static inline Pair getTombstoneKey() {
  185. return std::make_pair(FirstInfo::getTombstoneKey(),
  186. SecondInfo::getTombstoneKey());
  187. }
  188. static unsigned getHashValue(const Pair& PairVal) {
  189. return detail::combineHashValue(FirstInfo::getHashValue(PairVal.first),
  190. SecondInfo::getHashValue(PairVal.second));
  191. }
  192. static bool isEqual(const Pair &LHS, const Pair &RHS) {
  193. return FirstInfo::isEqual(LHS.first, RHS.first) &&
  194. SecondInfo::isEqual(LHS.second, RHS.second);
  195. }
  196. };
  197. // Provide DenseMapInfo for all tuples whose members have info.
  198. template <typename... Ts> struct DenseMapInfo<std::tuple<Ts...>> {
  199. using Tuple = std::tuple<Ts...>;
  200. static inline Tuple getEmptyKey() {
  201. return Tuple(DenseMapInfo<Ts>::getEmptyKey()...);
  202. }
  203. static inline Tuple getTombstoneKey() {
  204. return Tuple(DenseMapInfo<Ts>::getTombstoneKey()...);
  205. }
  206. template <unsigned I>
  207. static unsigned getHashValueImpl(const Tuple &values, std::false_type) {
  208. using EltType = typename std::tuple_element<I, Tuple>::type;
  209. std::integral_constant<bool, I + 1 == sizeof...(Ts)> atEnd;
  210. return detail::combineHashValue(
  211. DenseMapInfo<EltType>::getHashValue(std::get<I>(values)),
  212. getHashValueImpl<I + 1>(values, atEnd));
  213. }
  214. template <unsigned I>
  215. static unsigned getHashValueImpl(const Tuple &, std::true_type) {
  216. return 0;
  217. }
  218. static unsigned getHashValue(const std::tuple<Ts...> &values) {
  219. std::integral_constant<bool, 0 == sizeof...(Ts)> atEnd;
  220. return getHashValueImpl<0>(values, atEnd);
  221. }
  222. template <unsigned I>
  223. static bool isEqualImpl(const Tuple &lhs, const Tuple &rhs, std::false_type) {
  224. using EltType = typename std::tuple_element<I, Tuple>::type;
  225. std::integral_constant<bool, I + 1 == sizeof...(Ts)> atEnd;
  226. return DenseMapInfo<EltType>::isEqual(std::get<I>(lhs), std::get<I>(rhs)) &&
  227. isEqualImpl<I + 1>(lhs, rhs, atEnd);
  228. }
  229. template <unsigned I>
  230. static bool isEqualImpl(const Tuple &, const Tuple &, std::true_type) {
  231. return true;
  232. }
  233. static bool isEqual(const Tuple &lhs, const Tuple &rhs) {
  234. std::integral_constant<bool, 0 == sizeof...(Ts)> atEnd;
  235. return isEqualImpl<0>(lhs, rhs, atEnd);
  236. }
  237. };
  238. // Provide DenseMapInfo for StringRefs.
  239. template <> struct DenseMapInfo<StringRef> {
  240. static inline StringRef getEmptyKey() {
  241. return StringRef(reinterpret_cast<const char *>(~static_cast<uintptr_t>(0)),
  242. 0);
  243. }
  244. static inline StringRef getTombstoneKey() {
  245. return StringRef(reinterpret_cast<const char *>(~static_cast<uintptr_t>(1)),
  246. 0);
  247. }
  248. static unsigned getHashValue(StringRef Val) {
  249. assert(Val.data() != getEmptyKey().data() && "Cannot hash the empty key!");
  250. assert(Val.data() != getTombstoneKey().data() &&
  251. "Cannot hash the tombstone key!");
  252. return (unsigned)(hash_value(Val));
  253. }
  254. static bool isEqual(StringRef LHS, StringRef RHS) {
  255. if (RHS.data() == getEmptyKey().data())
  256. return LHS.data() == getEmptyKey().data();
  257. if (RHS.data() == getTombstoneKey().data())
  258. return LHS.data() == getTombstoneKey().data();
  259. return LHS == RHS;
  260. }
  261. };
  262. // Provide DenseMapInfo for ArrayRefs.
  263. template <typename T> struct DenseMapInfo<ArrayRef<T>> {
  264. static inline ArrayRef<T> getEmptyKey() {
  265. return ArrayRef<T>(reinterpret_cast<const T *>(~static_cast<uintptr_t>(0)),
  266. size_t(0));
  267. }
  268. static inline ArrayRef<T> getTombstoneKey() {
  269. return ArrayRef<T>(reinterpret_cast<const T *>(~static_cast<uintptr_t>(1)),
  270. size_t(0));
  271. }
  272. static unsigned getHashValue(ArrayRef<T> Val) {
  273. assert(Val.data() != getEmptyKey().data() && "Cannot hash the empty key!");
  274. assert(Val.data() != getTombstoneKey().data() &&
  275. "Cannot hash the tombstone key!");
  276. return (unsigned)(hash_value(Val));
  277. }
  278. static bool isEqual(ArrayRef<T> LHS, ArrayRef<T> RHS) {
  279. if (RHS.data() == getEmptyKey().data())
  280. return LHS.data() == getEmptyKey().data();
  281. if (RHS.data() == getTombstoneKey().data())
  282. return LHS.data() == getTombstoneKey().data();
  283. return LHS == RHS;
  284. }
  285. };
  286. template <> struct DenseMapInfo<hash_code> {
  287. static inline hash_code getEmptyKey() { return hash_code(-1); }
  288. static inline hash_code getTombstoneKey() { return hash_code(-2); }
  289. static unsigned getHashValue(hash_code val) { return val; }
  290. static bool isEqual(hash_code LHS, hash_code RHS) { return LHS == RHS; }
  291. };
  292. /// Provide DenseMapInfo for APInt.
  293. template <> struct DenseMapInfo<APInt> {
  294. static inline APInt getEmptyKey() {
  295. APInt V(nullptr, 0);
  296. V.U.VAL = 0;
  297. return V;
  298. }
  299. static inline APInt getTombstoneKey() {
  300. APInt V(nullptr, 0);
  301. V.U.VAL = 1;
  302. return V;
  303. }
  304. static unsigned getHashValue(const APInt &Key) {
  305. return static_cast<unsigned>(hash_value(Key));
  306. }
  307. static bool isEqual(const APInt &LHS, const APInt &RHS) {
  308. return LHS.getBitWidth() == RHS.getBitWidth() && LHS == RHS;
  309. }
  310. };
  311. /// Provide DenseMapInfo for APSInt, using the DenseMapInfo for APInt.
  312. template <> struct DenseMapInfo<APSInt> {
  313. static inline APSInt getEmptyKey() {
  314. return APSInt(DenseMapInfo<APInt>::getEmptyKey());
  315. }
  316. static inline APSInt getTombstoneKey() {
  317. return APSInt(DenseMapInfo<APInt>::getTombstoneKey());
  318. }
  319. static unsigned getHashValue(const APSInt &Key) {
  320. return static_cast<unsigned>(hash_value(Key));
  321. }
  322. static bool isEqual(const APSInt &LHS, const APSInt &RHS) {
  323. return LHS.getBitWidth() == RHS.getBitWidth() &&
  324. LHS.isUnsigned() == RHS.isUnsigned() && LHS == RHS;
  325. }
  326. };
  327. } // end namespace llvm
  328. #endif // LLVM_ADT_DENSEMAPINFO_H