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() { }
}
};
+/// \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() {
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;
}
}
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() {
}
}
-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");
return N;
if (!ShouldCreate)
return nullptr;
- Hash = Key.Hash;
+ Hash = Key.getHash();
} else {
assert(ShouldCreate && "Expected non-uniqued nodes to always be created");
}