summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/IR/LLVMContextImpl.cpp34
-rw-r--r--llvm/lib/IR/LLVMContextImpl.h71
-rw-r--r--llvm/lib/IR/Metadata.cpp29
3 files changed, 84 insertions, 50 deletions
diff --git a/llvm/lib/IR/LLVMContextImpl.cpp b/llvm/lib/IR/LLVMContextImpl.cpp
index 01a786dbfda..2fa6780e569 100644
--- a/llvm/lib/IR/LLVMContextImpl.cpp
+++ b/llvm/lib/IR/LLVMContextImpl.cpp
@@ -163,6 +163,40 @@ LLVMContextImpl::~LLVMContextImpl() {
MDStringCache.clear();
}
+namespace llvm {
+/// \brief Make MDOperand transparent for hashing.
+///
+/// This overload of an implementation detail of the hashing library makes
+/// MDOperand hash to the same value as a \a Metadata pointer.
+///
+/// Note that overloading \a hash_value() as follows:
+///
+/// \code
+/// size_t hash_value(const MDOperand &X) { return hash_value(X.get()); }
+/// \endcode
+///
+/// does not cause MDOperand to be transparent. In particular, a bare pointer
+/// doesn't get hashed before it's combined, whereas \a MDOperand would.
+static const Metadata *get_hashable_data(const MDOperand &X) { return X.get(); }
+}
+
+unsigned MDNodeOpsKey::calculateHash(MDNode *N) {
+ unsigned Hash = hash_combine_range(N->op_begin(), N->op_end());
+#ifndef NDEBUG
+ {
+ SmallVector<Metadata *, 8> MDs(N->op_begin(), N->op_end());
+ unsigned RawHash = calculateHash(MDs);
+ assert(Hash == RawHash &&
+ "Expected hash of MDOperand to equal hash of Metadata*");
+ }
+#endif
+ return Hash;
+}
+
+unsigned MDNodeOpsKey::calculateHash(ArrayRef<Metadata *> Ops) {
+ return hash_combine_range(Ops.begin(), Ops.end());
+}
+
// ConstantsContext anchors
void UnaryConstantExpr::anchor() { }
diff --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h
index 45f86093f52..729e48be083 100644
--- a/llvm/lib/IR/LLVMContextImpl.h
+++ b/llvm/lib/IR/LLVMContextImpl.h
@@ -167,35 +167,62 @@ struct FunctionTypeKeyInfo {
}
};
+/// \brief Structure for hashing arbitrary MDNode operands.
+class MDNodeOpsKey {
+ ArrayRef<Metadata *> RawOps;
+ ArrayRef<MDOperand> Ops;
+
+ unsigned Hash;
+
+protected:
+ MDNodeOpsKey(ArrayRef<Metadata *> Ops)
+ : RawOps(Ops), Hash(calculateHash(Ops)) {}
+
+ template <class NodeTy>
+ MDNodeOpsKey(NodeTy *N)
+ : Ops(N->op_begin(), N->op_end()), Hash(N->getHash()) {}
+
+ template <class NodeTy> bool compareOps(const NodeTy *RHS) const {
+ if (getHash() != RHS->getHash())
+ return false;
+
+ assert((RawOps.empty() || Ops.empty()) && "Two sets of operands?");
+ return RawOps.empty() ? compareOps(Ops, RHS) : compareOps(RawOps, RHS);
+ }
+
+ static unsigned calculateHash(MDNode *N);
+
+private:
+ template <class T>
+ static bool compareOps(ArrayRef<T> Ops, const MDNode *RHS) {
+ if (Ops.size() != RHS->getNumOperands())
+ return false;
+ return std::equal(Ops.begin(), Ops.end(), RHS->op_begin());
+ }
+
+ static unsigned calculateHash(ArrayRef<Metadata *> Ops);
+
+public:
+ unsigned getHash() const { return Hash; }
+};
+
/// \brief DenseMapInfo for MDTuple.
///
/// Note that we don't need the is-function-local bit, since that's implicit in
/// the operands.
struct MDTupleInfo {
- struct KeyTy {
- ArrayRef<Metadata *> RawOps;
- ArrayRef<MDOperand> Ops;
- unsigned Hash;
-
- KeyTy(ArrayRef<Metadata *> Ops)
- : RawOps(Ops), Hash(hash_combine_range(Ops.begin(), Ops.end())) {}
-
- KeyTy(MDTuple *N)
- : Ops(N->op_begin(), N->op_end()), Hash(N->getHash()) {}
+ struct KeyTy : MDNodeOpsKey {
+ KeyTy(ArrayRef<Metadata *> Ops) : MDNodeOpsKey(Ops) {}
+ KeyTy(MDTuple *N) : MDNodeOpsKey(N) {}
bool operator==(const MDTuple *RHS) const {
if (RHS == getEmptyKey() || RHS == getTombstoneKey())
return false;
- if (Hash != RHS->getHash())
- return false;
- assert((RawOps.empty() || Ops.empty()) && "Two sets of operands?");
- return RawOps.empty() ? compareOps(Ops, RHS) : compareOps(RawOps, RHS);
+ return compareOps(RHS);
}
- template <class T>
- static bool compareOps(ArrayRef<T> Ops, const MDTuple *RHS) {
- if (Ops.size() != RHS->getNumOperands())
- return false;
- return std::equal(Ops.begin(), Ops.end(), RHS->op_begin());
+
+ static unsigned calculateHash(MDTuple *N) {
+ return MDNodeOpsKey::calculateHash(N);
}
};
static inline MDTuple *getEmptyKey() {
@@ -204,10 +231,8 @@ struct MDTupleInfo {
static inline MDTuple *getTombstoneKey() {
return DenseMapInfo<MDTuple *>::getTombstoneKey();
}
- static unsigned getHashValue(const KeyTy &Key) { return Key.Hash; }
- static unsigned getHashValue(const MDTuple *U) {
- return U->getHash();
- }
+ static unsigned getHashValue(const KeyTy &Key) { return Key.getHash(); }
+ static unsigned getHashValue(const MDTuple *U) { return U->getHash(); }
static bool isEqual(const KeyTy &LHS, const MDTuple *RHS) {
return LHS == RHS;
}
diff --git a/llvm/lib/IR/Metadata.cpp b/llvm/lib/IR/Metadata.cpp
index e9265eb96ad..8253a4e6a96 100644
--- a/llvm/lib/IR/Metadata.cpp
+++ b/llvm/lib/IR/Metadata.cpp
@@ -515,15 +515,7 @@ void UniquableMDNode::resolveCycles() {
}
void MDTuple::recalculateHash() {
- setHash(hash_combine_range(op_begin(), op_end()));
-#ifndef NDEBUG
- {
- SmallVector<Metadata *, 8> MDs(op_begin(), op_end());
- unsigned RawHash = hash_combine_range(MDs.begin(), MDs.end());
- assert(getHash() == RawHash &&
- "Expected hash of MDOperand to equal hash of Metadata*");
- }
-#endif
+ setHash(MDTupleInfo::KeyTy::calculateHash(this));
}
void MDNode::dropAllReferences() {
@@ -536,23 +528,6 @@ void MDNode::dropAllReferences() {
}
}
-namespace llvm {
-/// \brief Make MDOperand transparent for hashing.
-///
-/// This overload of an implementation detail of the hashing library makes
-/// MDOperand hash to the same value as a \a Metadata pointer.
-///
-/// Note that overloading \a hash_value() as follows:
-///
-/// \code
-/// size_t hash_value(const MDOperand &X) { return hash_value(X.get()); }
-/// \endcode
-///
-/// does not cause MDOperand to be transparent. In particular, a bare pointer
-/// doesn't get hashed before it's combined, whereas \a MDOperand would.
-static const Metadata *get_hashable_data(const MDOperand &X) { return X.get(); }
-}
-
void UniquableMDNode::handleChangedOperand(void *Ref, Metadata *New) {
unsigned Op = static_cast<MDOperand *>(Ref) - op_begin();
assert(Op < getNumOperands() && "Expected valid operand");
@@ -687,7 +662,7 @@ MDTuple *MDTuple::getImpl(LLVMContext &Context, ArrayRef<Metadata *> MDs,
return N;
if (!ShouldCreate)
return nullptr;
- Hash = Key.Hash;
+ Hash = Key.getHash();
} else {
assert(ShouldCreate && "Expected non-uniqued nodes to always be created");
}
OpenPOWER on IntegriCloud