summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorChandler Carruth <chandlerc@gmail.com>2012-03-04 12:02:57 +0000
committerChandler Carruth <chandlerc@gmail.com>2012-03-04 12:02:57 +0000
commited7692a136a9bcf513b91b7b5eb33a1e2d83e7ee (patch)
tree699f358d3fdc8138b9aa7cadf8427eb2473c739e /lib
parent528f0bbe19553dfadedca040df13a389daa7593d (diff)
downloadllvm-ed7692a136a9bcf513b91b7b5eb33a1e2d83e7ee.tar.gz
llvm-ed7692a136a9bcf513b91b7b5eb33a1e2d83e7ee.tar.bz2
llvm-ed7692a136a9bcf513b91b7b5eb33a1e2d83e7ee.tar.xz
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
Diffstat (limited to 'lib')
-rw-r--r--lib/Support/APFloat.cpp31
-rw-r--r--lib/Support/APInt.cpp93
-rw-r--r--lib/VMCore/LLVMContextImpl.h11
3 files changed, 29 insertions, 106 deletions
diff --git a/lib/Support/APFloat.cpp b/lib/Support/APFloat.cpp
index 525aea28c6..409d4fbd0a 100644
--- a/lib/Support/APFloat.cpp
+++ b/lib/Support/APFloat.cpp
@@ -14,8 +14,9 @@
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/APSInt.h"
-#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/Hashing.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
#include <limits.h>
@@ -2681,21 +2682,19 @@ APFloat::convertNormalToHexString(char *dst, unsigned int hexDigits,
return writeSignedDecimal (dst, exponent);
}
-// For good performance it is desirable for different APFloats
-// to produce different integers.
-uint32_t
-APFloat::getHashValue() const
-{
- if (category==fcZero) return sign<<8 | semantics->precision ;
- else if (category==fcInfinity) return sign<<9 | semantics->precision;
- else if (category==fcNaN) return 1<<10 | semantics->precision;
- else {
- uint32_t hash = sign<<11 | semantics->precision | exponent<<12;
- const integerPart* p = significandParts();
- for (int i=partCount(); i>0; i--, p++)
- hash ^= ((uint32_t)*p) ^ (uint32_t)((*p)>>32);
- return hash;
- }
+hash_code llvm::hash_value(const APFloat &Arg) {
+ if (Arg.category != APFloat::fcNormal)
+ return hash_combine((uint8_t)Arg.category,
+ // NaN has no sign, fix it at zero.
+ Arg.isNaN() ? (uint8_t)0 : (uint8_t)Arg.sign,
+ Arg.semantics->precision);
+
+ // Normal floats need their exponent and significand hashed.
+ return hash_combine((uint8_t)Arg.category, (uint8_t)Arg.sign,
+ Arg.semantics->precision, Arg.exponent,
+ hash_combine_range(
+ Arg.significandParts(),
+ Arg.significandParts() + Arg.partCount()));
}
// Conversion from APFloat to/from host float/double. It may eventually be
diff --git a/lib/Support/APInt.cpp b/lib/Support/APInt.cpp
index 0d4e0f9f75..031bbb8882 100644
--- a/lib/Support/APInt.cpp
+++ b/lib/Support/APInt.cpp
@@ -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))))
-
-// 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;
-}
+hash_code llvm::hash_value(const APInt &Arg) {
+ if (Arg.isSingleWord())
+ return hash_combine(Arg.VAL);
-// 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.
diff --git a/lib/VMCore/LLVMContextImpl.h b/lib/VMCore/LLVMContextImpl.h
index a29bba2f3b..f98526de65 100644
--- a/lib/VMCore/LLVMContextImpl.h
+++ b/lib/VMCore/LLVMContextImpl.h
@@ -52,12 +52,14 @@ struct DenseMapAPIntKeyInfo {
bool operator!=(const KeyTy& that) const {
return !this->operator==(that);
}
+ friend hash_code hash_value(const KeyTy &Key) {
+ return hash_combine(Key.type, Key.val);
+ }
};
static inline KeyTy getEmptyKey() { return KeyTy(APInt(1,0), 0); }
static inline KeyTy getTombstoneKey() { return KeyTy(APInt(1,1), 0); }
static unsigned getHashValue(const KeyTy &Key) {
- return DenseMapInfo<void*>::getHashValue(Key.type) ^
- Key.val.getHashValue();
+ return static_cast<unsigned>(hash_value(Key));
}
static bool isEqual(const KeyTy &LHS, const KeyTy &RHS) {
return LHS == RHS;
@@ -75,6 +77,9 @@ struct DenseMapAPFloatKeyInfo {
bool operator!=(const KeyTy& that) const {
return !this->operator==(that);
}
+ friend hash_code hash_value(const KeyTy &Key) {
+ return hash_combine(Key.val);
+ }
};
static inline KeyTy getEmptyKey() {
return KeyTy(APFloat(APFloat::Bogus,1));
@@ -83,7 +88,7 @@ struct DenseMapAPFloatKeyInfo {
return KeyTy(APFloat(APFloat::Bogus,2));
}
static unsigned getHashValue(const KeyTy &Key) {
- return Key.val.getHashValue();
+ return static_cast<unsigned>(hash_value(Key));
}
static bool isEqual(const KeyTy &LHS, const KeyTy &RHS) {
return LHS == RHS;