summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Transforms/Scalar/GVN.cpp
diff options
context:
space:
mode:
authorChandler Carruth <chandlerc@gmail.com>2012-03-05 11:29:54 +0000
committerChandler Carruth <chandlerc@gmail.com>2012-03-05 11:29:54 +0000
commite134d1a3367c33e015e7dfa57986963e55c4402d (patch)
tree37c84fd934fecd1322b40c8652a1e9c96e7e48a2 /llvm/lib/Transforms/Scalar/GVN.cpp
parent189fa748ec9e05820f7c5df8ff00aa3c7bc0546c (diff)
downloadbcm5719-llvm-e134d1a3367c33e015e7dfa57986963e55c4402d.tar.gz
bcm5719-llvm-e134d1a3367c33e015e7dfa57986963e55c4402d.zip
Replace the ad-hoc hashing in GVN with the new hashing infrastructure.
This implicitly fixes a nasty bug in the GVN hashing (that thankfully could only manifest as a performance bug): actually include the opcode in the hash. The old code started the hash off with the opcode, but then overwrote it with the type pointer. Since this is likely to be pretty hot (GVN being already pretty expensive) I've included a micro-optimization to just not bother with the varargs hashing if they aren't present. I can't measure any change in GVN performance due to this, even with a big test case like Duncan's sqlite one. Everything I see is in the noise floor. That said, this closes a loop hole for a potential scaling problem due to collisions if the opcode were the differentiating aspect of the expression. llvm-svn: 152025
Diffstat (limited to 'llvm/lib/Transforms/Scalar/GVN.cpp')
-rw-r--r--llvm/lib/Transforms/Scalar/GVN.cpp23
1 files changed, 13 insertions, 10 deletions
diff --git a/llvm/lib/Transforms/Scalar/GVN.cpp b/llvm/lib/Transforms/Scalar/GVN.cpp
index dc13edff255..bc32b7f4418 100644
--- a/llvm/lib/Transforms/Scalar/GVN.cpp
+++ b/llvm/lib/Transforms/Scalar/GVN.cpp
@@ -36,6 +36,7 @@
#include "llvm/Transforms/Utils/SSAUpdater.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DepthFirstIterator.h"
+#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/Allocator.h"
@@ -84,6 +85,16 @@ namespace {
return false;
return true;
}
+
+ friend hash_code hash_value(const Expression &Value) {
+ // Optimize for the common case.
+ if (Value.varargs.empty())
+ return hash_combine(Value.opcode, Value.type);
+
+ return hash_combine(Value.opcode, Value.type,
+ hash_combine_range(Value.varargs.begin(),
+ Value.varargs.end()));
+ }
};
class ValueTable {
@@ -130,16 +141,8 @@ template <> struct DenseMapInfo<Expression> {
}
static unsigned getHashValue(const Expression e) {
- unsigned hash = e.opcode;
-
- hash = ((unsigned)((uintptr_t)e.type >> 4) ^
- (unsigned)((uintptr_t)e.type >> 9));
-
- for (SmallVector<uint32_t, 4>::const_iterator I = e.varargs.begin(),
- E = e.varargs.end(); I != E; ++I)
- hash = *I + hash * 37;
-
- return hash;
+ using llvm::hash_value;
+ return static_cast<unsigned>(hash_value(e));
}
static bool isEqual(const Expression &LHS, const Expression &RHS) {
return LHS == RHS;
OpenPOWER on IntegriCloud