IR: Split GenericMDNode into MDTuple and UniquableMDNode

Split `GenericMDNode` into two classes (with more descriptive names).

  - `UniquableMDNode` will be a common subclass for `MDNode`s that are
    sometimes uniqued like constants, and sometimes 'distinct'.

    This class gets the (short-lived) RAUW support and related API.

  - `MDTuple` is the basic tuple that has always been returned by
    `MDNode::get()`.  This is as opposed to more specific nodes to be
    added soon, which have additional fields, custom assembly syntax,
    and extra semantics.

    This class gets the hash-related logic, since other sublcasses of
    `UniquableMDNode` may need to hash based on other fields.

To keep this diff from getting too big, I've added casts to `MDTuple`
that won't really scale as new subclasses of `UniquableMDNode` are
added, but I'll clean those up incrementally.

(No functionality change intended.)

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@225682 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Duncan P. N. Exon Smith 2015-01-12 20:09:34 +00:00
parent 2d88dc293b
commit ae9e15f914
10 changed files with 128 additions and 98 deletions

View File

@ -37,7 +37,8 @@ HANDLE_METADATA_LEAF(ConstantAsMetadata)
HANDLE_METADATA_LEAF(LocalAsMetadata) HANDLE_METADATA_LEAF(LocalAsMetadata)
HANDLE_METADATA_BRANCH(MDNode) HANDLE_METADATA_BRANCH(MDNode)
HANDLE_METADATA_LEAF(MDNodeFwdDecl) HANDLE_METADATA_LEAF(MDNodeFwdDecl)
HANDLE_METADATA_LEAF(GenericMDNode) HANDLE_METADATA_BRANCH(UniquableMDNode)
HANDLE_METADATA_LEAF(MDTuple)
#undef HANDLE_METADATA #undef HANDLE_METADATA
#undef HANDLE_METADATA_LEAF #undef HANDLE_METADATA_LEAF

View File

@ -56,7 +56,7 @@ protected:
public: public:
enum MetadataKind { enum MetadataKind {
GenericMDNodeKind, MDTupleKind,
MDNodeFwdDeclKind, MDNodeFwdDeclKind,
ConstantAsMetadataKind, ConstantAsMetadataKind,
LocalAsMetadataKind, LocalAsMetadataKind,
@ -158,7 +158,7 @@ public:
/// \brief Resolve all uses of this. /// \brief Resolve all uses of this.
/// ///
/// Resolve all uses of this, turning off RAUW permanently. If \c /// Resolve all uses of this, turning off RAUW permanently. If \c
/// ResolveUsers, call \a GenericMDNode::resolve() on any users whose last /// ResolveUsers, call \a UniquableMDNode::resolve() on any users whose last
/// operand is resolved. /// operand is resolved.
void resolveAllUses(bool ResolveUsers = true); void resolveAllUses(bool ResolveUsers = true);
@ -682,7 +682,7 @@ public:
/// \brief Methods for support type inquiry through isa, cast, and dyn_cast: /// \brief Methods for support type inquiry through isa, cast, and dyn_cast:
static bool classof(const Metadata *MD) { static bool classof(const Metadata *MD) {
return MD->getMetadataID() == GenericMDNodeKind || return MD->getMetadataID() == MDTupleKind ||
MD->getMetadataID() == MDNodeFwdDeclKind; MD->getMetadataID() == MDNodeFwdDeclKind;
} }
@ -698,46 +698,46 @@ public:
static MDNode *getMostGenericRange(MDNode *A, MDNode *B); static MDNode *getMostGenericRange(MDNode *A, MDNode *B);
}; };
/// \brief Generic metadata node. /// \brief Uniquable metadata node.
/// ///
/// Generic metadata nodes, with opt-out support for uniquing. /// A uniquable metadata node. This contains the basic functionality
/// for implementing sub-types of \a MDNode that can be uniqued like
/// constants.
/// ///
/// Although nodes are uniqued by default, \a GenericMDNode has no support for /// There is limited support for RAUW at construction time. At
/// RAUW. If an operand change (due to RAUW or otherwise) causes a uniquing /// construction time, if any operands are an instance of \a
/// collision, the uniquing bit is dropped. /// MDNodeFwdDecl (or another unresolved \a UniquableMDNode, which
class GenericMDNode : public MDNode { /// indicates an \a MDNodeFwdDecl in its path), the node itself will be
friend class Metadata; /// unresolved. As soon as all operands become resolved, it will drop
/// RAUW support permanently.
///
/// If an unresolved node is part of a cycle, \a resolveCycles() needs
/// to be called on some member of the cycle when each \a MDNodeFwdDecl
/// has been removed.
class UniquableMDNode : public MDNode {
friend class ReplaceableMetadataImpl;
friend class MDNode; friend class MDNode;
friend class LLVMContextImpl; friend class LLVMContextImpl;
friend class ReplaceableMetadataImpl;
/// \brief Support RAUW as long as one of its arguments is replaceable. /// \brief Support RAUW as long as one of its arguments is replaceable.
/// ///
/// If an operand is an \a MDNodeFwdDecl (or a replaceable \a GenericMDNode),
/// support RAUW to support uniquing as forward declarations are resolved.
/// As soon as operands have been resolved, drop support.
///
/// FIXME: Save memory by storing this in a pointer union with the /// FIXME: Save memory by storing this in a pointer union with the
/// LLVMContext, and adding an LLVMContext reference to RMI. /// LLVMContext, and adding an LLVMContext reference to RMI.
std::unique_ptr<ReplaceableMetadataImpl> ReplaceableUses; std::unique_ptr<ReplaceableMetadataImpl> ReplaceableUses;
protected:
/// \brief Create a new node. /// \brief Create a new node.
/// ///
/// If \c AllowRAUW, then if any operands are unresolved support RAUW. RAUW /// If \c AllowRAUW, then if any operands are unresolved support RAUW. RAUW
/// will be dropped once all operands have been resolved (or if \a /// will be dropped once all operands have been resolved (or if \a
/// resolveCycles() is called). /// resolveCycles() is called).
GenericMDNode(LLVMContext &C, ArrayRef<Metadata *> Vals, bool AllowRAUW); UniquableMDNode(LLVMContext &C, unsigned ID, ArrayRef<Metadata *> Vals,
~GenericMDNode(); bool AllowRAUW);
~UniquableMDNode();
void setHash(unsigned Hash) { MDNodeSubclassData = Hash; }
void recalculateHash();
public: public:
/// \brief Get the hash, if any.
unsigned getHash() const { return MDNodeSubclassData; }
static bool classof(const Metadata *MD) { static bool classof(const Metadata *MD) {
return MD->getMetadataID() == GenericMDNodeKind; return MD->getMetadataID() == MDTupleKind;
} }
/// \brief Check whether any operands are forward declarations. /// \brief Check whether any operands are forward declarations.
@ -766,11 +766,36 @@ private:
void decrementUnresolvedOperandCount(); void decrementUnresolvedOperandCount();
}; };
/// \brief Tuple of metadata.
///
/// This is the simple \a MDNode arbitrary tuple. Nodes are uniqued by
/// default based on their operands.
class MDTuple : public UniquableMDNode {
friend class LLVMContextImpl;
friend class UniquableMDNode;
friend class MDNode;
MDTuple(LLVMContext &C, ArrayRef<Metadata *> Vals, bool AllowRAUW)
: UniquableMDNode(C, MDTupleKind, Vals, AllowRAUW) {}
~MDTuple();
void setHash(unsigned Hash) { MDNodeSubclassData = Hash; }
void recalculateHash();
public:
/// \brief Get the hash, if any.
unsigned getHash() const { return MDNodeSubclassData; }
static bool classof(const Metadata *MD) {
return MD->getMetadataID() == MDTupleKind;
}
};
/// \brief Forward declaration of metadata. /// \brief Forward declaration of metadata.
/// ///
/// Forward declaration of metadata, in the form of a metadata node. Unlike \a /// Forward declaration of metadata, in the form of a basic tuple. Unlike \a
/// GenericMDNode, this class has support for RAUW and is suitable for forward /// MDTuple, this class has full support for RAUW, is not owned, is not
/// references. /// uniqued, and is suitable for forward references.
class MDNodeFwdDecl : public MDNode, ReplaceableMetadataImpl { class MDNodeFwdDecl : public MDNode, ReplaceableMetadataImpl {
friend class Metadata; friend class Metadata;
friend class MDNode; friend class MDNode;

View File

@ -169,8 +169,8 @@ bool LLParser::ValidateEndOfModule() {
// Resolve metadata cycles. // Resolve metadata cycles.
for (auto &N : NumberedMetadata) for (auto &N : NumberedMetadata)
if (auto *G = cast_or_null<GenericMDNode>(N)) if (auto *U = cast_or_null<UniquableMDNode>(N))
G->resolveCycles(); U->resolveCycles();
// Look for intrinsic functions and CallInst that need to be upgraded // Look for intrinsic functions and CallInst that need to be upgraded
for (Module::iterator FI = M->begin(), FE = M->end(); FI != FE; ) for (Module::iterator FI = M->begin(), FE = M->end(); FI != FE; )

View File

@ -558,8 +558,8 @@ void BitcodeReaderMDValueList::tryToResolveCycles() {
// Resolve any cycles. // Resolve any cycles.
for (auto &MD : MDValuePtrs) { for (auto &MD : MDValuePtrs) {
assert(!(MD && isa<MDNodeFwdDecl>(MD)) && "Unexpected forward reference"); assert(!(MD && isa<MDNodeFwdDecl>(MD)) && "Unexpected forward reference");
if (auto *G = dyn_cast_or_null<GenericMDNode>(MD)) if (auto *N = dyn_cast_or_null<UniquableMDNode>(MD))
G->resolveCycles(); N->resolveCycles();
} }
} }

View File

@ -55,7 +55,8 @@ DIBuilder::DIBuilder(Module &m, bool AllowUnresolvedNodes)
AllowUnresolvedNodes(AllowUnresolvedNodes) {} AllowUnresolvedNodes(AllowUnresolvedNodes) {}
static bool isUnresolved(MDNode *N) { static bool isUnresolved(MDNode *N) {
return N && (isa<MDNodeFwdDecl>(N) || !cast<GenericMDNode>(N)->isResolved()); return N &&
(isa<MDNodeFwdDecl>(N) || !cast<UniquableMDNode>(N)->isResolved());
} }
void DIBuilder::trackIfUnresolved(MDNode *N) { void DIBuilder::trackIfUnresolved(MDNode *N) {
@ -110,7 +111,7 @@ void DIBuilder::finalize() {
// cycles. // cycles.
for (const auto &N : UnresolvedNodes) for (const auto &N : UnresolvedNodes)
if (N) if (N)
cast<GenericMDNode>(N)->resolveCycles(); cast<UniquableMDNode>(N)->resolveCycles();
UnresolvedNodes.clear(); UnresolvedNodes.clear();
// Can't handle unresolved nodes anymore. // Can't handle unresolved nodes anymore.

View File

@ -135,17 +135,17 @@ LLVMContextImpl::~LLVMContextImpl() {
for (auto &Pair : ValuesAsMetadata) for (auto &Pair : ValuesAsMetadata)
delete Pair.second; delete Pair.second;
// Destroy MDNodes. ~MDNode can move and remove nodes between the MDNodeSet // Destroy MDNodes. ~MDNode can move and remove nodes between the MDTuples
// and the NonUniquedMDNodes sets, so copy the values out first. // and the DistinctMDNodes sets, so copy the values out first.
SmallVector<GenericMDNode *, 8> MDNodes; SmallVector<UniquableMDNode *, 8> Uniquables;
MDNodes.reserve(MDNodeSet.size() + NonUniquedMDNodes.size()); Uniquables.reserve(MDTuples.size() + DistinctMDNodes.size());
MDNodes.append(MDNodeSet.begin(), MDNodeSet.end()); Uniquables.append(MDTuples.begin(), MDTuples.end());
MDNodes.append(NonUniquedMDNodes.begin(), NonUniquedMDNodes.end()); Uniquables.append(DistinctMDNodes.begin(), DistinctMDNodes.end());
for (GenericMDNode *I : MDNodes) for (UniquableMDNode *I : Uniquables)
I->dropAllReferences(); I->dropAllReferences();
for (GenericMDNode *I : MDNodes) for (UniquableMDNode *I : Uniquables)
delete I; delete cast<MDTuple>(I);
assert(MDNodeSet.empty() && NonUniquedMDNodes.empty() && assert(MDTuples.empty() && DistinctMDNodes.empty() &&
"Destroying all MDNodes didn't empty the Context's sets."); "Destroying all MDNodes didn't empty the Context's sets.");
// Destroy MDStrings. // Destroy MDStrings.

View File

@ -166,11 +166,11 @@ struct FunctionTypeKeyInfo {
} }
}; };
/// \brief DenseMapInfo for GenericMDNode. /// \brief DenseMapInfo for MDTuple.
/// ///
/// Note that we don't need the is-function-local bit, since that's implicit in /// Note that we don't need the is-function-local bit, since that's implicit in
/// the operands. /// the operands.
struct GenericMDNodeInfo { struct MDTupleInfo {
struct KeyTy { struct KeyTy {
ArrayRef<Metadata *> RawOps; ArrayRef<Metadata *> RawOps;
ArrayRef<MDOperand> Ops; ArrayRef<MDOperand> Ops;
@ -179,10 +179,10 @@ struct GenericMDNodeInfo {
KeyTy(ArrayRef<Metadata *> Ops) KeyTy(ArrayRef<Metadata *> Ops)
: RawOps(Ops), Hash(hash_combine_range(Ops.begin(), Ops.end())) {} : RawOps(Ops), Hash(hash_combine_range(Ops.begin(), Ops.end())) {}
KeyTy(GenericMDNode *N) KeyTy(MDTuple *N)
: Ops(N->op_begin(), N->op_end()), Hash(N->getHash()) {} : Ops(N->op_begin(), N->op_end()), Hash(N->getHash()) {}
bool operator==(const GenericMDNode *RHS) const { bool operator==(const MDTuple *RHS) const {
if (RHS == getEmptyKey() || RHS == getTombstoneKey()) if (RHS == getEmptyKey() || RHS == getTombstoneKey())
return false; return false;
if (Hash != RHS->getHash()) if (Hash != RHS->getHash())
@ -191,26 +191,26 @@ struct GenericMDNodeInfo {
return RawOps.empty() ? compareOps(Ops, RHS) : compareOps(RawOps, RHS); return RawOps.empty() ? compareOps(Ops, RHS) : compareOps(RawOps, RHS);
} }
template <class T> template <class T>
static bool compareOps(ArrayRef<T> Ops, const GenericMDNode *RHS) { static bool compareOps(ArrayRef<T> Ops, const MDTuple *RHS) {
if (Ops.size() != RHS->getNumOperands()) if (Ops.size() != RHS->getNumOperands())
return false; return false;
return std::equal(Ops.begin(), Ops.end(), RHS->op_begin()); return std::equal(Ops.begin(), Ops.end(), RHS->op_begin());
} }
}; };
static inline GenericMDNode *getEmptyKey() { static inline MDTuple *getEmptyKey() {
return DenseMapInfo<GenericMDNode *>::getEmptyKey(); return DenseMapInfo<MDTuple *>::getEmptyKey();
} }
static inline GenericMDNode *getTombstoneKey() { static inline MDTuple *getTombstoneKey() {
return DenseMapInfo<GenericMDNode *>::getTombstoneKey(); return DenseMapInfo<MDTuple *>::getTombstoneKey();
} }
static unsigned getHashValue(const KeyTy &Key) { return Key.Hash; } static unsigned getHashValue(const KeyTy &Key) { return Key.Hash; }
static unsigned getHashValue(const GenericMDNode *U) { static unsigned getHashValue(const MDTuple *U) {
return U->getHash(); return U->getHash();
} }
static bool isEqual(const KeyTy &LHS, const GenericMDNode *RHS) { static bool isEqual(const KeyTy &LHS, const MDTuple *RHS) {
return LHS == RHS; return LHS == RHS;
} }
static bool isEqual(const GenericMDNode *LHS, const GenericMDNode *RHS) { static bool isEqual(const MDTuple *LHS, const MDTuple *RHS) {
return LHS == RHS; return LHS == RHS;
} }
}; };
@ -245,13 +245,13 @@ public:
DenseMap<Value *, ValueAsMetadata *> ValuesAsMetadata; DenseMap<Value *, ValueAsMetadata *> ValuesAsMetadata;
DenseMap<Metadata *, MetadataAsValue *> MetadataAsValues; DenseMap<Metadata *, MetadataAsValue *> MetadataAsValues;
DenseSet<GenericMDNode *, GenericMDNodeInfo> MDNodeSet; DenseSet<MDTuple *, MDTupleInfo> MDTuples;
// MDNodes may be uniqued or not uniqued. When they're not uniqued, they // MDNodes may be uniqued or not uniqued. When they're not uniqued, they
// aren't in the MDNodeSet, but they're still shared between objects, so no // aren't in the MDNodeSet, but they're still shared between objects, so no
// one object can destroy them. This set allows us to at least destroy them // one object can destroy them. This set allows us to at least destroy them
// on Context destruction. // on Context destruction.
SmallPtrSet<GenericMDNode *, 1> NonUniquedMDNodes; SmallPtrSet<UniquableMDNode *, 1> DistinctMDNodes;
DenseMap<Type*, ConstantAggregateZero*> CAZConstants; DenseMap<Type*, ConstantAggregateZero*> CAZConstants;

View File

@ -222,8 +222,8 @@ void ReplaceableMetadataImpl::resolveAllUses(bool ResolveUsers) {
if (Owner.is<MetadataAsValue *>()) if (Owner.is<MetadataAsValue *>())
continue; continue;
// Resolve GenericMDNodes that point at this. // Resolve UniquableMDNodes that point at this.
auto *OwnerMD = dyn_cast<GenericMDNode>(Owner.get<Metadata *>()); auto *OwnerMD = dyn_cast<UniquableMDNode>(Owner.get<Metadata *>());
if (!OwnerMD) if (!OwnerMD)
continue; continue;
if (OwnerMD->isResolved()) if (OwnerMD->isResolved())
@ -400,7 +400,7 @@ MDNode::MDNode(LLVMContext &Context, unsigned ID, ArrayRef<Metadata *> MDs)
bool MDNode::isResolved() const { bool MDNode::isResolved() const {
if (isa<MDNodeFwdDecl>(this)) if (isa<MDNodeFwdDecl>(this))
return false; return false;
return cast<GenericMDNode>(this)->isResolved(); return cast<UniquableMDNode>(this)->isResolved();
} }
static bool isOperandUnresolved(Metadata *Op) { static bool isOperandUnresolved(Metadata *Op) {
@ -409,9 +409,9 @@ static bool isOperandUnresolved(Metadata *Op) {
return false; return false;
} }
GenericMDNode::GenericMDNode(LLVMContext &C, ArrayRef<Metadata *> Vals, UniquableMDNode::UniquableMDNode(LLVMContext &C, unsigned ID,
bool AllowRAUW) ArrayRef<Metadata *> Vals, bool AllowRAUW)
: MDNode(C, GenericMDNodeKind, Vals) { : MDNode(C, ID, Vals) {
if (!AllowRAUW) if (!AllowRAUW)
return; return;
@ -427,16 +427,14 @@ GenericMDNode::GenericMDNode(LLVMContext &C, ArrayRef<Metadata *> Vals,
SubclassData32 = NumUnresolved; SubclassData32 = NumUnresolved;
} }
GenericMDNode::~GenericMDNode() { UniquableMDNode::~UniquableMDNode() {
LLVMContextImpl *pImpl = getContext().pImpl;
if (isStoredDistinctInContext()) if (isStoredDistinctInContext())
pImpl->NonUniquedMDNodes.erase(this); getContext().pImpl->DistinctMDNodes.erase(this);
else
pImpl->MDNodeSet.erase(this);
dropAllReferences(); dropAllReferences();
} }
void GenericMDNode::resolve() { void UniquableMDNode::resolve() {
assert(!isResolved() && "Expected this to be unresolved"); assert(!isResolved() && "Expected this to be unresolved");
// Move the map, so that this immediately looks resolved. // Move the map, so that this immediately looks resolved.
@ -448,7 +446,7 @@ void GenericMDNode::resolve() {
Uses->resolveAllUses(); Uses->resolveAllUses();
} }
void GenericMDNode::resolveAfterOperandChange(Metadata *Old, Metadata *New) { void UniquableMDNode::resolveAfterOperandChange(Metadata *Old, Metadata *New) {
assert(SubclassData32 != 0 && "Expected unresolved operands"); assert(SubclassData32 != 0 && "Expected unresolved operands");
// Check if an operand was resolved. // Check if an operand was resolved.
@ -458,13 +456,13 @@ void GenericMDNode::resolveAfterOperandChange(Metadata *Old, Metadata *New) {
decrementUnresolvedOperandCount(); decrementUnresolvedOperandCount();
} }
void GenericMDNode::decrementUnresolvedOperandCount() { void UniquableMDNode::decrementUnresolvedOperandCount() {
if (!--SubclassData32) if (!--SubclassData32)
// Last unresolved operand has just been resolved. // Last unresolved operand has just been resolved.
resolve(); resolve();
} }
void GenericMDNode::resolveCycles() { void UniquableMDNode::resolveCycles() {
if (isResolved()) if (isResolved())
return; return;
@ -477,13 +475,18 @@ void GenericMDNode::resolveCycles() {
continue; continue;
assert(!isa<MDNodeFwdDecl>(Op) && assert(!isa<MDNodeFwdDecl>(Op) &&
"Expected all forward declarations to be resolved"); "Expected all forward declarations to be resolved");
if (auto *N = dyn_cast<GenericMDNode>(Op)) if (auto *N = dyn_cast<UniquableMDNode>(Op))
if (!N->isResolved()) if (!N->isResolved())
N->resolveCycles(); N->resolveCycles();
} }
} }
void GenericMDNode::recalculateHash() { MDTuple::~MDTuple() {
if (!isStoredDistinctInContext())
getContext().pImpl->MDTuples.erase(this);
}
void MDTuple::recalculateHash() {
setHash(hash_combine_range(op_begin(), op_end())); setHash(hash_combine_range(op_begin(), op_end()));
#ifndef NDEBUG #ifndef NDEBUG
{ {
@ -498,10 +501,10 @@ void GenericMDNode::recalculateHash() {
void MDNode::dropAllReferences() { void MDNode::dropAllReferences() {
for (unsigned I = 0, E = NumOperands; I != E; ++I) for (unsigned I = 0, E = NumOperands; I != E; ++I)
setOperand(I, nullptr); setOperand(I, nullptr);
if (auto *G = dyn_cast<GenericMDNode>(this)) if (auto *N = dyn_cast<UniquableMDNode>(this))
if (!G->isResolved()) { if (!N->isResolved()) {
G->ReplaceableUses->resolveAllUses(/* ResolveUsers */ false); N->ReplaceableUses->resolveAllUses(/* ResolveUsers */ false);
G->ReplaceableUses.reset(); N->ReplaceableUses.reset();
} }
} }
@ -522,7 +525,7 @@ namespace llvm {
static const Metadata *get_hashable_data(const MDOperand &X) { return X.get(); } static const Metadata *get_hashable_data(const MDOperand &X) { return X.get(); }
} }
void GenericMDNode::handleChangedOperand(void *Ref, Metadata *New) { void UniquableMDNode::handleChangedOperand(void *Ref, Metadata *New) {
unsigned Op = static_cast<MDOperand *>(Ref) - op_begin(); unsigned Op = static_cast<MDOperand *>(Ref) - op_begin();
assert(Op < getNumOperands() && "Expected valid operand"); assert(Op < getNumOperands() && "Expected valid operand");
@ -534,8 +537,8 @@ void GenericMDNode::handleChangedOperand(void *Ref, Metadata *New) {
return; return;
} }
auto &Store = getContext().pImpl->MDNodeSet; auto &Store = getContext().pImpl->MDTuples;
Store.erase(this); Store.erase(cast<MDTuple>(this));
Metadata *Old = getOperand(Op); Metadata *Old = getOperand(Op);
setOperand(Op, New); setOperand(Op, New);
@ -549,11 +552,11 @@ void GenericMDNode::handleChangedOperand(void *Ref, Metadata *New) {
} }
// Re-unique the node. // Re-unique the node.
recalculateHash(); cast<MDTuple>(this)->recalculateHash();
GenericMDNodeInfo::KeyTy Key(this); MDTupleInfo::KeyTy Key(cast<MDTuple>(this));
auto I = Store.find_as(Key); auto I = Store.find_as(Key);
if (I == Store.end()) { if (I == Store.end()) {
Store.insert(this); Store.insert(cast<MDTuple>(this));
if (!isResolved()) if (!isResolved())
resolveAfterOperandChange(Old, New); resolveAfterOperandChange(Old, New);
@ -570,7 +573,7 @@ void GenericMDNode::handleChangedOperand(void *Ref, Metadata *New) {
for (unsigned O = 0, E = getNumOperands(); O != E; ++O) for (unsigned O = 0, E = getNumOperands(); O != E; ++O)
setOperand(O, nullptr); setOperand(O, nullptr);
ReplaceableUses->replaceAllUsesWith(*I); ReplaceableUses->replaceAllUsesWith(*I);
delete this; delete cast<MDTuple>(this);
return; return;
} }
@ -580,9 +583,9 @@ void GenericMDNode::handleChangedOperand(void *Ref, Metadata *New) {
MDNode *MDNode::getMDNode(LLVMContext &Context, ArrayRef<Metadata *> MDs, MDNode *MDNode::getMDNode(LLVMContext &Context, ArrayRef<Metadata *> MDs,
bool Insert) { bool Insert) {
auto &Store = Context.pImpl->MDNodeSet; auto &Store = Context.pImpl->MDTuples;
GenericMDNodeInfo::KeyTy Key(MDs); MDTupleInfo::KeyTy Key(MDs);
auto I = Store.find_as(Key); auto I = Store.find_as(Key);
if (I != Store.end()) if (I != Store.end())
return *I; return *I;
@ -590,14 +593,14 @@ MDNode *MDNode::getMDNode(LLVMContext &Context, ArrayRef<Metadata *> MDs,
return nullptr; return nullptr;
// Coallocate space for the node and Operands together, then placement new. // Coallocate space for the node and Operands together, then placement new.
auto *N = new (MDs.size()) GenericMDNode(Context, MDs, /* AllowRAUW */ true); auto *N = new (MDs.size()) MDTuple(Context, MDs, /* AllowRAUW */ true);
N->setHash(Key.Hash); N->setHash(Key.Hash);
Store.insert(N); Store.insert(N);
return N; return N;
} }
MDNode *MDNode::getDistinct(LLVMContext &Context, ArrayRef<Metadata *> MDs) { MDNode *MDNode::getDistinct(LLVMContext &Context, ArrayRef<Metadata *> MDs) {
auto *N = new (MDs.size()) GenericMDNode(Context, MDs, /* AllowRAUW */ false); auto *N = new (MDs.size()) MDTuple(Context, MDs, /* AllowRAUW */ false);
N->storeDistinctInContext(); N->storeDistinctInContext();
return N; return N;
} }
@ -616,9 +619,9 @@ void MDNode::deleteTemporary(MDNode *N) {
void MDNode::storeDistinctInContext() { void MDNode::storeDistinctInContext() {
assert(!IsDistinctInContext && "Expected newly distinct metadata"); assert(!IsDistinctInContext && "Expected newly distinct metadata");
IsDistinctInContext = true; IsDistinctInContext = true;
auto *G = cast<GenericMDNode>(this); auto *T = cast<MDTuple>(this);
G->setHash(0); T->setHash(0);
getContext().pImpl->NonUniquedMDNodes.insert(G); getContext().pImpl->DistinctMDNodes.insert(T);
} }
void MDNode::replaceOperandWith(unsigned I, Metadata *New) { void MDNode::replaceOperandWith(unsigned I, Metadata *New) {
@ -630,7 +633,7 @@ void MDNode::replaceOperandWith(unsigned I, Metadata *New) {
return; return;
} }
cast<GenericMDNode>(this)->handleChangedOperand(mutable_begin() + I, New); cast<UniquableMDNode>(this)->handleChangedOperand(mutable_begin() + I, New);
} }
void MDNode::setOperand(unsigned I, Metadata *New) { void MDNode::setOperand(unsigned I, Metadata *New) {

View File

@ -18,8 +18,8 @@ using namespace llvm;
ReplaceableMetadataImpl *ReplaceableMetadataImpl::get(Metadata &MD) { ReplaceableMetadataImpl *ReplaceableMetadataImpl::get(Metadata &MD) {
if (auto *N = dyn_cast<MDNode>(&MD)) { if (auto *N = dyn_cast<MDNode>(&MD)) {
if (auto *G = dyn_cast<GenericMDNode>(N)) if (auto *U = dyn_cast<UniquableMDNode>(N))
return G->ReplaceableUses.get(); return U->ReplaceableUses.get();
return cast<MDNodeFwdDecl>(N); return cast<MDNodeFwdDecl>(N);
} }
return dyn_cast<ValueAsMetadata>(&MD); return dyn_cast<ValueAsMetadata>(&MD);

View File

@ -260,8 +260,8 @@ Metadata *llvm::MapMetadata(const Metadata *MD, ValueToValueMapTy &VM,
ValueMaterializer *Materializer) { ValueMaterializer *Materializer) {
Metadata *NewMD = MapMetadataImpl(MD, VM, Flags, TypeMapper, Materializer); Metadata *NewMD = MapMetadataImpl(MD, VM, Flags, TypeMapper, Materializer);
if (NewMD && NewMD != MD) if (NewMD && NewMD != MD)
if (auto *G = dyn_cast<GenericMDNode>(NewMD)) if (auto *N = dyn_cast<UniquableMDNode>(NewMD))
G->resolveCycles(); N->resolveCycles();
return NewMD; return NewMD;
} }