blob: a6a0034129fb70e2970006424ff858ba36d4586f [file] [log] [blame]
Talin1a4b19e2012-02-18 21:00:49 +00001//===- llvm/unittest/ADT/HashingTest.cpp ----------------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// Hashing.h unit tests.
11//
12//===----------------------------------------------------------------------===//
13
14#include "gtest/gtest.h"
15#include "llvm/ADT/Hashing.h"
Chandler Carruth0b66c6f2012-03-01 18:55:25 +000016#include "llvm/Support/DataTypes.h"
17#include <deque>
18#include <list>
19#include <map>
20#include <vector>
21
22namespace llvm {
23
24// Helper for test code to print hash codes.
25void PrintTo(const hash_code &code, std::ostream *os) {
26 *os << static_cast<size_t>(code);
27}
28
29// Fake an object that is recognized as hashable data to test super large
30// objects.
31struct LargeTestInteger { uint64_t arr[8]; };
32
33namespace hashing {
34namespace detail {
35template <> struct is_hashable_data<LargeTestInteger> : true_type {};
36} // namespace detail
37} // namespace hashing
38
39} // namespace llvm
Talin1a4b19e2012-02-18 21:00:49 +000040
41using namespace llvm;
42
43namespace {
44
Chandler Carruth0b66c6f2012-03-01 18:55:25 +000045TEST(HashingTest, HashValueBasicTest) {
46 int x = 42, y = 43, c = 'x';
47 void *p = 0;
48 uint64_t i = 71;
49 const unsigned ci = 71;
50 volatile int vi = 71;
51 const volatile int cvi = 71;
52 uintptr_t addr = reinterpret_cast<uintptr_t>(&y);
53 EXPECT_EQ(hash_value(42), hash_value(x));
54 EXPECT_NE(hash_value(42), hash_value(y));
55 EXPECT_NE(hash_value(42), hash_value(p));
Chandler Carruth0b66c6f2012-03-01 18:55:25 +000056 EXPECT_EQ(hash_value(71), hash_value(i));
57 EXPECT_EQ(hash_value(71), hash_value(ci));
58 EXPECT_EQ(hash_value(71), hash_value(vi));
59 EXPECT_EQ(hash_value(71), hash_value(cvi));
60 EXPECT_EQ(hash_value(c), hash_value('x'));
61 EXPECT_EQ(hash_value('4'), hash_value('0' + 4));
62 EXPECT_EQ(hash_value(addr), hash_value(&y));
Talin1a4b19e2012-02-18 21:00:49 +000063}
64
Chandler Carruth0b66c6f2012-03-01 18:55:25 +000065template <typename T, size_t N> T *begin(T (&arr)[N]) { return arr; }
66template <typename T, size_t N> T *end(T (&arr)[N]) { return arr + N; }
67
68// Provide a dummy, hashable type designed for easy verification: its hash is
69// the same as its value.
70struct HashableDummy { size_t value; };
71hash_code hash_value(HashableDummy dummy) { return dummy.value; }
72
73TEST(HashingTest, HashCombineRangeBasicTest) {
74 // Leave this uninitialized in the hope that valgrind will catch bad reads.
75 int dummy;
76 hash_code dummy_hash = hash_combine_range(&dummy, &dummy);
Chandler Carruth41669892012-03-02 00:48:38 +000077 EXPECT_NE(hash_code(0), dummy_hash);
Chandler Carruth0b66c6f2012-03-01 18:55:25 +000078
79 const int arr1[] = { 1, 2, 3 };
80 hash_code arr1_hash = hash_combine_range(begin(arr1), end(arr1));
Chandler Carruth0b66c6f2012-03-01 18:55:25 +000081 EXPECT_NE(dummy_hash, arr1_hash);
82 EXPECT_EQ(arr1_hash, hash_combine_range(begin(arr1), end(arr1)));
83
84 const std::vector<int> vec(begin(arr1), end(arr1));
85 EXPECT_EQ(arr1_hash, hash_combine_range(vec.begin(), vec.end()));
86
87 const std::list<int> list(begin(arr1), end(arr1));
88 EXPECT_EQ(arr1_hash, hash_combine_range(list.begin(), list.end()));
89
90 const std::deque<int> deque(begin(arr1), end(arr1));
91 EXPECT_EQ(arr1_hash, hash_combine_range(deque.begin(), deque.end()));
92
93 const int arr2[] = { 3, 2, 1 };
94 hash_code arr2_hash = hash_combine_range(begin(arr2), end(arr2));
Chandler Carruth0b66c6f2012-03-01 18:55:25 +000095 EXPECT_NE(dummy_hash, arr2_hash);
96 EXPECT_NE(arr1_hash, arr2_hash);
97
98 const int arr3[] = { 1, 1, 2, 3 };
99 hash_code arr3_hash = hash_combine_range(begin(arr3), end(arr3));
Chandler Carruth0b66c6f2012-03-01 18:55:25 +0000100 EXPECT_NE(dummy_hash, arr3_hash);
101 EXPECT_NE(arr1_hash, arr3_hash);
102
103 const int arr4[] = { 1, 2, 3, 3 };
104 hash_code arr4_hash = hash_combine_range(begin(arr4), end(arr4));
Chandler Carruth0b66c6f2012-03-01 18:55:25 +0000105 EXPECT_NE(dummy_hash, arr4_hash);
106 EXPECT_NE(arr1_hash, arr4_hash);
107
108 const size_t arr5[] = { 1, 2, 3 };
109 const HashableDummy d_arr5[] = { {1}, {2}, {3} };
110 hash_code arr5_hash = hash_combine_range(begin(arr5), end(arr5));
111 hash_code d_arr5_hash = hash_combine_range(begin(d_arr5), end(d_arr5));
112 EXPECT_EQ(arr5_hash, d_arr5_hash);
Talin1a4b19e2012-02-18 21:00:49 +0000113}
114
Chandler Carruth0b66c6f2012-03-01 18:55:25 +0000115TEST(HashingTest, HashCombineRangeLengthDiff) {
116 // Test that as only the length varies, we compute different hash codes for
117 // sequences.
118 std::map<size_t, size_t> code_to_size;
119 std::vector<char> all_one_c(256, '\xff');
120 for (unsigned Idx = 1, Size = all_one_c.size(); Idx < Size; ++Idx) {
121 hash_code code = hash_combine_range(&all_one_c[0], &all_one_c[0] + Idx);
122 std::map<size_t, size_t>::iterator
123 I = code_to_size.insert(std::make_pair(code, Idx)).first;
124 EXPECT_EQ(Idx, I->second);
125 }
126 code_to_size.clear();
127 std::vector<char> all_zero_c(256, '\0');
128 for (unsigned Idx = 1, Size = all_zero_c.size(); Idx < Size; ++Idx) {
129 hash_code code = hash_combine_range(&all_zero_c[0], &all_zero_c[0] + Idx);
130 std::map<size_t, size_t>::iterator
131 I = code_to_size.insert(std::make_pair(code, Idx)).first;
132 EXPECT_EQ(Idx, I->second);
133 }
134 code_to_size.clear();
135 std::vector<unsigned> all_one_int(512, -1);
136 for (unsigned Idx = 1, Size = all_one_int.size(); Idx < Size; ++Idx) {
137 hash_code code = hash_combine_range(&all_one_int[0], &all_one_int[0] + Idx);
138 std::map<size_t, size_t>::iterator
139 I = code_to_size.insert(std::make_pair(code, Idx)).first;
140 EXPECT_EQ(Idx, I->second);
141 }
142 code_to_size.clear();
143 std::vector<unsigned> all_zero_int(512, 0);
144 for (unsigned Idx = 1, Size = all_zero_int.size(); Idx < Size; ++Idx) {
145 hash_code code = hash_combine_range(&all_zero_int[0], &all_zero_int[0] + Idx);
146 std::map<size_t, size_t>::iterator
147 I = code_to_size.insert(std::make_pair(code, Idx)).first;
148 EXPECT_EQ(Idx, I->second);
149 }
Talin1a4b19e2012-02-18 21:00:49 +0000150}
151
Chandler Carruth0b66c6f2012-03-01 18:55:25 +0000152TEST(HashingTest, HashCombineRangeGoldenTest) {
153 struct { const char *s; uint64_t hash; } golden_data[] = {
Chandler Carruth97312942012-03-01 23:06:19 +0000154#if SIZE_MAX == UINT64_MAX
Chandler Carruth0b66c6f2012-03-01 18:55:25 +0000155 { "a", 0xaeb6f9d5517c61f8ULL },
156 { "ab", 0x7ab1edb96be496b4ULL },
157 { "abc", 0xe38e60bf19c71a3fULL },
158 { "abcde", 0xd24461a66de97f6eULL },
159 { "abcdefgh", 0x4ef872ec411dec9dULL },
160 { "abcdefghijklm", 0xe8a865539f4eadfeULL },
161 { "abcdefghijklmnopqrstu", 0x261cdf85faaf4e79ULL },
162 { "abcdefghijklmnopqrstuvwxyzabcdef", 0x43ba70e4198e3b2aULL },
163 { "abcdefghijklmnopqrstuvwxyzabcdef"
164 "abcdefghijklmnopqrstuvwxyzghijkl"
165 "abcdefghijklmnopqrstuvwxyzmnopqr"
166 "abcdefghijklmnopqrstuvwxyzstuvwx"
167 "abcdefghijklmnopqrstuvwxyzyzabcd", 0xdcd57fb2afdf72beULL },
168 { "a", 0xaeb6f9d5517c61f8ULL },
169 { "aa", 0xf2b3b69a9736a1ebULL },
170 { "aaa", 0xf752eb6f07b1cafeULL },
171 { "aaaaa", 0x812bd21e1236954cULL },
172 { "aaaaaaaa", 0xff07a2cff08ac587ULL },
173 { "aaaaaaaaaaaaa", 0x84ac949d54d704ecULL },
174 { "aaaaaaaaaaaaaaaaaaaaa", 0xcb2c8fb6be8f5648ULL },
175 { "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 0xcc40ab7f164091b6ULL },
176 { "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
177 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
178 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
179 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
180 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 0xc58e174c1e78ffe9ULL },
181 { "z", 0x1ba160d7e8f8785cULL },
182 { "zz", 0x2c5c03172f1285d7ULL },
183 { "zzz", 0x9d2c4f4b507a2ac3ULL },
184 { "zzzzz", 0x0f03b9031735693aULL },
185 { "zzzzzzzz", 0xe674147c8582c08eULL },
186 { "zzzzzzzzzzzzz", 0x3162d9fa6938db83ULL },
187 { "zzzzzzzzzzzzzzzzzzzzz", 0x37b9a549e013620cULL },
188 { "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz", 0x8921470aff885016ULL },
189 { "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"
190 "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"
191 "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"
192 "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"
193 "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz", 0xf60fdcd9beb08441ULL },
194 { "a", 0xaeb6f9d5517c61f8ULL },
195 { "ab", 0x7ab1edb96be496b4ULL },
196 { "aba", 0x3edb049950884d0aULL },
197 { "ababa", 0x8f2de9e73a97714bULL },
198 { "abababab", 0xee14a29ddf0ce54cULL },
199 { "ababababababa", 0x38b3ddaada2d52b4ULL },
200 { "ababababababababababa", 0xd3665364219f2b85ULL },
201 { "abababababababababababababababab"
202 "abababababababababababababababab"
203 "abababababababababababababababab"
204 "abababababababababababababababab"
205 "abababababababababababababababab", 0x840192d129f7a22bULL }
Chandler Carruth97312942012-03-01 23:06:19 +0000206#elif SIZE_MAX == UINT32_MAX
207 { "a", 0x000000004605f745ULL },
208 { "ab", 0x00000000d5f06301ULL },
209 { "abc", 0x00000000559fe1eeULL },
210 { "abcde", 0x00000000424028d7ULL },
211 { "abcdefgh", 0x000000007bb119f8ULL },
212 { "abcdefghijklm", 0x00000000edbca513ULL },
213 { "abcdefghijklmnopqrstu", 0x000000007c15712eULL },
214 { "abcdefghijklmnopqrstuvwxyzabcdef", 0x000000000b3aad66ULL },
215 { "abcdefghijklmnopqrstuvwxyzabcdef"
216 "abcdefghijklmnopqrstuvwxyzghijkl"
217 "abcdefghijklmnopqrstuvwxyzmnopqr"
218 "abcdefghijklmnopqrstuvwxyzstuvwx"
219 "abcdefghijklmnopqrstuvwxyzyzabcd", 0x000000008c758c8bULL },
220 { "a", 0x000000004605f745ULL },
221 { "aa", 0x00000000dc0a52daULL },
222 { "aaa", 0x00000000b309274fULL },
223 { "aaaaa", 0x00000000203b5ef6ULL },
224 { "aaaaaaaa", 0x00000000a429e18fULL },
225 { "aaaaaaaaaaaaa", 0x000000008662070bULL },
226 { "aaaaaaaaaaaaaaaaaaaaa", 0x000000003f11151cULL },
227 { "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 0x000000008600fe20ULL },
228 { "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
229 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
230 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
231 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
232 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 0x000000004e0e0804ULL },
233 { "z", 0x00000000c5e405e9ULL },
234 { "zz", 0x00000000a8d8a2c6ULL },
235 { "zzz", 0x00000000fc2af672ULL },
236 { "zzzzz", 0x0000000047d9efe6ULL },
237 { "zzzzzzzz", 0x0000000080d77794ULL },
238 { "zzzzzzzzzzzzz", 0x00000000405f93adULL },
239 { "zzzzzzzzzzzzzzzzzzzzz", 0x00000000fc72838dULL },
240 { "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz", 0x000000007ce160f1ULL },
241 { "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"
242 "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"
243 "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"
244 "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"
245 "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz", 0x00000000aed9ed1bULL },
246 { "a", 0x000000004605f745ULL },
247 { "ab", 0x00000000d5f06301ULL },
248 { "aba", 0x00000000a85cd91bULL },
249 { "ababa", 0x000000009e3bb52eULL },
250 { "abababab", 0x000000002709b3b9ULL },
251 { "ababababababa", 0x000000003a234174ULL },
252 { "ababababababababababa", 0x000000005c63e5ceULL },
253 { "abababababababababababababababab", 0x0000000013f74334ULL },
254 { "abababababababababababababababab"
255 "abababababababababababababababab"
256 "abababababababababababababababab"
257 "abababababababababababababababab"
258 "abababababababababababababababab", 0x00000000c1a6f135ULL },
259#else
260#error This test only supports 64-bit and 32-bit systems.
261#endif
Chandler Carruth0b66c6f2012-03-01 18:55:25 +0000262 };
263 for (unsigned i = 0; i < sizeof(golden_data)/sizeof(*golden_data); ++i) {
264 StringRef str = golden_data[i].s;
265 hash_code hash = hash_combine_range(str.begin(), str.end());
Chandler Carruth5a491ca2012-03-01 23:20:45 +0000266#if 0 // Enable this to generate paste-able text for the above structure.
Chandler Carruth0b66c6f2012-03-01 18:55:25 +0000267 std::string member_str = "\"" + str.str() + "\",";
Chandler Carruth97312942012-03-01 23:06:19 +0000268 fprintf(stderr, " { %-35s 0x%016llxULL },\n",
269 member_str.c_str(), static_cast<uint64_t>(hash));
Chandler Carruth0b66c6f2012-03-01 18:55:25 +0000270#endif
271 EXPECT_EQ(static_cast<size_t>(golden_data[i].hash),
272 static_cast<size_t>(hash));
273 }
Talin1a4b19e2012-02-18 21:00:49 +0000274}
275
Chandler Carruth0b66c6f2012-03-01 18:55:25 +0000276TEST(HashingTest, HashCombineBasicTest) {
277 // Hashing a sequence of homogenous types matches range hashing.
278 const int i1 = 42, i2 = 43, i3 = 123, i4 = 999, i5 = 0, i6 = 79;
279 const int arr1[] = { i1, i2, i3, i4, i5, i6 };
280 EXPECT_EQ(hash_combine_range(arr1, arr1 + 1), hash_combine(i1));
281 EXPECT_EQ(hash_combine_range(arr1, arr1 + 2), hash_combine(i1, i2));
282 EXPECT_EQ(hash_combine_range(arr1, arr1 + 3), hash_combine(i1, i2, i3));
283 EXPECT_EQ(hash_combine_range(arr1, arr1 + 4), hash_combine(i1, i2, i3, i4));
284 EXPECT_EQ(hash_combine_range(arr1, arr1 + 5),
285 hash_combine(i1, i2, i3, i4, i5));
286 EXPECT_EQ(hash_combine_range(arr1, arr1 + 6),
287 hash_combine(i1, i2, i3, i4, i5, i6));
Talin1a4b19e2012-02-18 21:00:49 +0000288
Chandler Carruth0b66c6f2012-03-01 18:55:25 +0000289 // Hashing a sequence of heterogenous types which *happen* to all produce the
290 // same data for hashing produces the same as a range-based hash of the
291 // fundamental values.
292 const size_t s1 = 1024, s2 = 8888, s3 = 9000000;
293 const HashableDummy d1 = { 1024 }, d2 = { 8888 }, d3 = { 9000000 };
294 const size_t arr2[] = { s1, s2, s3 };
295 EXPECT_EQ(hash_combine_range(begin(arr2), end(arr2)),
296 hash_combine(s1, s2, s3));
297 EXPECT_EQ(hash_combine(s1, s2, s3), hash_combine(s1, s2, d3));
298 EXPECT_EQ(hash_combine(s1, s2, s3), hash_combine(s1, d2, s3));
299 EXPECT_EQ(hash_combine(s1, s2, s3), hash_combine(d1, s2, s3));
300 EXPECT_EQ(hash_combine(s1, s2, s3), hash_combine(d1, d2, s3));
301 EXPECT_EQ(hash_combine(s1, s2, s3), hash_combine(d1, d2, d3));
302
303 // Permuting values causes hashes to change.
304 EXPECT_NE(hash_combine(i1, i1, i1), hash_combine(i1, i1, i2));
305 EXPECT_NE(hash_combine(i1, i1, i1), hash_combine(i1, i2, i1));
306 EXPECT_NE(hash_combine(i1, i1, i1), hash_combine(i2, i1, i1));
307 EXPECT_NE(hash_combine(i1, i1, i1), hash_combine(i2, i2, i1));
308 EXPECT_NE(hash_combine(i1, i1, i1), hash_combine(i2, i2, i2));
309 EXPECT_NE(hash_combine(i2, i1, i1), hash_combine(i1, i1, i2));
310 EXPECT_NE(hash_combine(i1, i1, i2), hash_combine(i1, i2, i1));
311 EXPECT_NE(hash_combine(i1, i2, i1), hash_combine(i2, i1, i1));
312
313 // Changing type w/o changing value causes hashes to change.
314 EXPECT_NE(hash_combine(i1, i2, i3), hash_combine((char)i1, i2, i3));
315 EXPECT_NE(hash_combine(i1, i2, i3), hash_combine(i1, (char)i2, i3));
316 EXPECT_NE(hash_combine(i1, i2, i3), hash_combine(i1, i2, (char)i3));
317
318 // This is array of uint64, but it should have the exact same byte pattern as
319 // an array of LargeTestIntegers.
320 const uint64_t bigarr[] = {
321 0xaaaaaaaaababababULL, 0xacacacacbcbcbcbcULL, 0xccddeeffeeddccbbULL,
322 0xdeadbeafdeadbeefULL, 0xfefefefededededeULL, 0xafafafafededededULL,
323 0xffffeeeeddddccccULL, 0xaaaacbcbffffababULL,
324 0xaaaaaaaaababababULL, 0xacacacacbcbcbcbcULL, 0xccddeeffeeddccbbULL,
325 0xdeadbeafdeadbeefULL, 0xfefefefededededeULL, 0xafafafafededededULL,
326 0xffffeeeeddddccccULL, 0xaaaacbcbffffababULL,
327 0xaaaaaaaaababababULL, 0xacacacacbcbcbcbcULL, 0xccddeeffeeddccbbULL,
328 0xdeadbeafdeadbeefULL, 0xfefefefededededeULL, 0xafafafafededededULL,
329 0xffffeeeeddddccccULL, 0xaaaacbcbffffababULL
330 };
331 // Hash a preposterously large integer, both aligned with the buffer and
332 // misaligned.
333 const LargeTestInteger li = { {
334 0xaaaaaaaaababababULL, 0xacacacacbcbcbcbcULL, 0xccddeeffeeddccbbULL,
335 0xdeadbeafdeadbeefULL, 0xfefefefededededeULL, 0xafafafafededededULL,
336 0xffffeeeeddddccccULL, 0xaaaacbcbffffababULL
337 } };
338 // Rotate the storage from 'li'.
339 const LargeTestInteger l2 = { {
340 0xacacacacbcbcbcbcULL, 0xccddeeffeeddccbbULL, 0xdeadbeafdeadbeefULL,
341 0xfefefefededededeULL, 0xafafafafededededULL, 0xffffeeeeddddccccULL,
342 0xaaaacbcbffffababULL, 0xaaaaaaaaababababULL
343 } };
344 const LargeTestInteger l3 = { {
345 0xccddeeffeeddccbbULL, 0xdeadbeafdeadbeefULL, 0xfefefefededededeULL,
346 0xafafafafededededULL, 0xffffeeeeddddccccULL, 0xaaaacbcbffffababULL,
347 0xaaaaaaaaababababULL, 0xacacacacbcbcbcbcULL
348 } };
349 EXPECT_EQ(hash_combine_range(begin(bigarr), end(bigarr)),
350 hash_combine(li, li, li));
351 EXPECT_EQ(hash_combine_range(bigarr, bigarr + 9),
352 hash_combine(bigarr[0], l2));
353 EXPECT_EQ(hash_combine_range(bigarr, bigarr + 10),
354 hash_combine(bigarr[0], bigarr[1], l3));
355 EXPECT_EQ(hash_combine_range(bigarr, bigarr + 17),
356 hash_combine(li, bigarr[0], l2));
357 EXPECT_EQ(hash_combine_range(bigarr, bigarr + 18),
358 hash_combine(li, bigarr[0], bigarr[1], l3));
359 EXPECT_EQ(hash_combine_range(bigarr, bigarr + 18),
360 hash_combine(bigarr[0], l2, bigarr[9], l3));
361 EXPECT_EQ(hash_combine_range(bigarr, bigarr + 20),
362 hash_combine(bigarr[0], l2, bigarr[9], l3, bigarr[18], bigarr[19]));
Talin1a4b19e2012-02-18 21:00:49 +0000363}
364
365}