Replace the hashing functions on APInt and APFloat with overloads of the

new hash_value infrastructure, and replace their implementations using
hash_combine. This removes a complete copy of Jenkin's lookup3 hash
function (which is both significantly slower and lower quality than the
one implemented in hash_combine) along with a somewhat scary xor-only
hash function.

Now that APInt and APFloat can be passed directly to hash_combine,
simplify the rest of the LLVMContextImpl hashing to use the new
infrastructure.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@152004 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chandler Carruth
2012-03-04 12:02:57 +00:00
parent 528f0bbe19
commit ed7692a136
5 changed files with 44 additions and 114 deletions

View File

@ -14,9 +14,10 @@
#define DEBUG_TYPE "apint"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
@ -675,93 +676,11 @@ unsigned APInt::getBitsNeeded(StringRef str, uint8_t radix) {
}
}
// From http://www.burtleburtle.net, byBob Jenkins.
// When targeting x86, both GCC and LLVM seem to recognize this as a
// rotate instruction.
#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k))))
hash_code llvm::hash_value(const APInt &Arg) {
if (Arg.isSingleWord())
return hash_combine(Arg.VAL);
// From http://www.burtleburtle.net, by Bob Jenkins.
#define mix(a,b,c) \
{ \
a -= c; a ^= rot(c, 4); c += b; \
b -= a; b ^= rot(a, 6); a += c; \
c -= b; c ^= rot(b, 8); b += a; \
a -= c; a ^= rot(c,16); c += b; \
b -= a; b ^= rot(a,19); a += c; \
c -= b; c ^= rot(b, 4); b += a; \
}
// From http://www.burtleburtle.net, by Bob Jenkins.
#define final(a,b,c) \
{ \
c ^= b; c -= rot(b,14); \
a ^= c; a -= rot(c,11); \
b ^= a; b -= rot(a,25); \
c ^= b; c -= rot(b,16); \
a ^= c; a -= rot(c,4); \
b ^= a; b -= rot(a,14); \
c ^= b; c -= rot(b,24); \
}
// hashword() was adapted from http://www.burtleburtle.net, by Bob
// Jenkins. k is a pointer to an array of uint32_t values; length is
// the length of the key, in 32-bit chunks. This version only handles
// keys that are a multiple of 32 bits in size.
static inline uint32_t hashword(const uint64_t *k64, size_t length)
{
const uint32_t *k = reinterpret_cast<const uint32_t *>(k64);
uint32_t a,b,c;
/* Set up the internal state */
a = b = c = 0xdeadbeef + (((uint32_t)length)<<2);
/*------------------------------------------------- handle most of the key */
while (length > 3) {
a += k[0];
b += k[1];
c += k[2];
mix(a,b,c);
length -= 3;
k += 3;
}
/*------------------------------------------- handle the last 3 uint32_t's */
switch (length) { /* all the case statements fall through */
case 3 : c+=k[2];
case 2 : b+=k[1];
case 1 : a+=k[0];
final(a,b,c);
case 0: /* case 0: nothing left to add */
break;
}
/*------------------------------------------------------ report the result */
return c;
}
// hashword8() was adapted from http://www.burtleburtle.net, by Bob
// Jenkins. This computes a 32-bit hash from one 64-bit word. When
// targeting x86 (32 or 64 bit), both LLVM and GCC compile this
// function into about 35 instructions when inlined.
static inline uint32_t hashword8(const uint64_t k64)
{
uint32_t a,b,c;
a = b = c = 0xdeadbeef + 4;
b += k64 >> 32;
a += k64 & 0xffffffff;
final(a,b,c);
return c;
}
#undef final
#undef mix
#undef rot
uint64_t APInt::getHashValue() const {
uint64_t hash;
if (isSingleWord())
hash = hashword8(VAL);
else
hash = hashword(pVal, getNumWords()*2);
return hash;
return hash_combine_range(Arg.pVal, Arg.pVal + Arg.getNumWords());
}
/// HiBits - This function returns the high "numBits" bits of this APInt.