mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-25 00:33:15 +00:00
IR: Extract MDNodeOpsKey, NFC
Make the MDTuple operand hashing logic reusable. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@226519 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
ce8f144e00
commit
fce53dd939
@ -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() { }
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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");
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user