From: Duncan P. N. Exon Smith Date: Mon, 12 Jan 2015 20:09:34 +0000 (+0000) Subject: IR: Split GenericMDNode into MDTuple and UniquableMDNode X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=ae9e15f9145ea6da81c297ac01dd42d1330c52ad;p=oota-llvm.git 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 --- diff --git a/include/llvm/IR/Metadata.def b/include/llvm/IR/Metadata.def index 75e0e3ef482..33b9ca090c2 100644 --- a/include/llvm/IR/Metadata.def +++ b/include/llvm/IR/Metadata.def @@ -37,7 +37,8 @@ HANDLE_METADATA_LEAF(ConstantAsMetadata) HANDLE_METADATA_LEAF(LocalAsMetadata) HANDLE_METADATA_BRANCH(MDNode) HANDLE_METADATA_LEAF(MDNodeFwdDecl) -HANDLE_METADATA_LEAF(GenericMDNode) +HANDLE_METADATA_BRANCH(UniquableMDNode) +HANDLE_METADATA_LEAF(MDTuple) #undef HANDLE_METADATA #undef HANDLE_METADATA_LEAF diff --git a/include/llvm/IR/Metadata.h b/include/llvm/IR/Metadata.h index 263f7f21023..dbf16408fc0 100644 --- a/include/llvm/IR/Metadata.h +++ b/include/llvm/IR/Metadata.h @@ -56,7 +56,7 @@ protected: public: enum MetadataKind { - GenericMDNodeKind, + MDTupleKind, MDNodeFwdDeclKind, ConstantAsMetadataKind, LocalAsMetadataKind, @@ -158,7 +158,7 @@ public: /// \brief Resolve all uses of this. /// /// 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. void resolveAllUses(bool ResolveUsers = true); @@ -682,7 +682,7 @@ public: /// \brief Methods for support type inquiry through isa, cast, and dyn_cast: static bool classof(const Metadata *MD) { - return MD->getMetadataID() == GenericMDNodeKind || + return MD->getMetadataID() == MDTupleKind || MD->getMetadataID() == MDNodeFwdDeclKind; } @@ -698,46 +698,46 @@ public: 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 -/// RAUW. If an operand change (due to RAUW or otherwise) causes a uniquing -/// collision, the uniquing bit is dropped. -class GenericMDNode : public MDNode { - friend class Metadata; +/// There is limited support for RAUW at construction time. At +/// construction time, if any operands are an instance of \a +/// MDNodeFwdDecl (or another unresolved \a UniquableMDNode, which +/// indicates an \a MDNodeFwdDecl in its path), the node itself will be +/// 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 LLVMContextImpl; - friend class ReplaceableMetadataImpl; /// \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 /// LLVMContext, and adding an LLVMContext reference to RMI. std::unique_ptr ReplaceableUses; +protected: /// \brief Create a new node. /// /// If \c AllowRAUW, then if any operands are unresolved support RAUW. RAUW /// will be dropped once all operands have been resolved (or if \a /// resolveCycles() is called). - GenericMDNode(LLVMContext &C, ArrayRef Vals, bool AllowRAUW); - ~GenericMDNode(); - - void setHash(unsigned Hash) { MDNodeSubclassData = Hash; } - void recalculateHash(); + UniquableMDNode(LLVMContext &C, unsigned ID, ArrayRef Vals, + bool AllowRAUW); + ~UniquableMDNode(); public: - /// \brief Get the hash, if any. - unsigned getHash() const { return MDNodeSubclassData; } - static bool classof(const Metadata *MD) { - return MD->getMetadataID() == GenericMDNodeKind; + return MD->getMetadataID() == MDTupleKind; } /// \brief Check whether any operands are forward declarations. @@ -766,11 +766,36 @@ private: 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 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. /// -/// Forward declaration of metadata, in the form of a metadata node. Unlike \a -/// GenericMDNode, this class has support for RAUW and is suitable for forward -/// references. +/// Forward declaration of metadata, in the form of a basic tuple. Unlike \a +/// MDTuple, this class has full support for RAUW, is not owned, is not +/// uniqued, and is suitable for forward references. class MDNodeFwdDecl : public MDNode, ReplaceableMetadataImpl { friend class Metadata; friend class MDNode; diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp index bcb314dfbd7..b33d6ad35c9 100644 --- a/lib/AsmParser/LLParser.cpp +++ b/lib/AsmParser/LLParser.cpp @@ -169,8 +169,8 @@ bool LLParser::ValidateEndOfModule() { // Resolve metadata cycles. for (auto &N : NumberedMetadata) - if (auto *G = cast_or_null(N)) - G->resolveCycles(); + if (auto *U = cast_or_null(N)) + U->resolveCycles(); // Look for intrinsic functions and CallInst that need to be upgraded for (Module::iterator FI = M->begin(), FE = M->end(); FI != FE; ) diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp index 75d311c0386..6f58f2241a6 100644 --- a/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/lib/Bitcode/Reader/BitcodeReader.cpp @@ -558,8 +558,8 @@ void BitcodeReaderMDValueList::tryToResolveCycles() { // Resolve any cycles. for (auto &MD : MDValuePtrs) { assert(!(MD && isa(MD)) && "Unexpected forward reference"); - if (auto *G = dyn_cast_or_null(MD)) - G->resolveCycles(); + if (auto *N = dyn_cast_or_null(MD)) + N->resolveCycles(); } } diff --git a/lib/IR/DIBuilder.cpp b/lib/IR/DIBuilder.cpp index 6485ca5a003..856bb3c3375 100644 --- a/lib/IR/DIBuilder.cpp +++ b/lib/IR/DIBuilder.cpp @@ -55,7 +55,8 @@ DIBuilder::DIBuilder(Module &m, bool AllowUnresolvedNodes) AllowUnresolvedNodes(AllowUnresolvedNodes) {} static bool isUnresolved(MDNode *N) { - return N && (isa(N) || !cast(N)->isResolved()); + return N && + (isa(N) || !cast(N)->isResolved()); } void DIBuilder::trackIfUnresolved(MDNode *N) { @@ -110,7 +111,7 @@ void DIBuilder::finalize() { // cycles. for (const auto &N : UnresolvedNodes) if (N) - cast(N)->resolveCycles(); + cast(N)->resolveCycles(); UnresolvedNodes.clear(); // Can't handle unresolved nodes anymore. diff --git a/lib/IR/LLVMContextImpl.cpp b/lib/IR/LLVMContextImpl.cpp index 7c34f0949a4..a9268b46488 100644 --- a/lib/IR/LLVMContextImpl.cpp +++ b/lib/IR/LLVMContextImpl.cpp @@ -135,17 +135,17 @@ LLVMContextImpl::~LLVMContextImpl() { for (auto &Pair : ValuesAsMetadata) delete Pair.second; - // Destroy MDNodes. ~MDNode can move and remove nodes between the MDNodeSet - // and the NonUniquedMDNodes sets, so copy the values out first. - SmallVector MDNodes; - MDNodes.reserve(MDNodeSet.size() + NonUniquedMDNodes.size()); - MDNodes.append(MDNodeSet.begin(), MDNodeSet.end()); - MDNodes.append(NonUniquedMDNodes.begin(), NonUniquedMDNodes.end()); - for (GenericMDNode *I : MDNodes) + // Destroy MDNodes. ~MDNode can move and remove nodes between the MDTuples + // and the DistinctMDNodes sets, so copy the values out first. + SmallVector Uniquables; + Uniquables.reserve(MDTuples.size() + DistinctMDNodes.size()); + Uniquables.append(MDTuples.begin(), MDTuples.end()); + Uniquables.append(DistinctMDNodes.begin(), DistinctMDNodes.end()); + for (UniquableMDNode *I : Uniquables) I->dropAllReferences(); - for (GenericMDNode *I : MDNodes) - delete I; - assert(MDNodeSet.empty() && NonUniquedMDNodes.empty() && + for (UniquableMDNode *I : Uniquables) + delete cast(I); + assert(MDTuples.empty() && DistinctMDNodes.empty() && "Destroying all MDNodes didn't empty the Context's sets."); // Destroy MDStrings. diff --git a/lib/IR/LLVMContextImpl.h b/lib/IR/LLVMContextImpl.h index a9de5c78822..11b8d38f9af 100644 --- a/lib/IR/LLVMContextImpl.h +++ b/lib/IR/LLVMContextImpl.h @@ -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 /// the operands. -struct GenericMDNodeInfo { +struct MDTupleInfo { struct KeyTy { ArrayRef RawOps; ArrayRef Ops; @@ -179,10 +179,10 @@ struct GenericMDNodeInfo { KeyTy(ArrayRef Ops) : 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()) {} - bool operator==(const GenericMDNode *RHS) const { + bool operator==(const MDTuple *RHS) const { if (RHS == getEmptyKey() || RHS == getTombstoneKey()) return false; if (Hash != RHS->getHash()) @@ -191,26 +191,26 @@ struct GenericMDNodeInfo { return RawOps.empty() ? compareOps(Ops, RHS) : compareOps(RawOps, RHS); } template - static bool compareOps(ArrayRef Ops, const GenericMDNode *RHS) { + static bool compareOps(ArrayRef Ops, const MDTuple *RHS) { if (Ops.size() != RHS->getNumOperands()) return false; return std::equal(Ops.begin(), Ops.end(), RHS->op_begin()); } }; - static inline GenericMDNode *getEmptyKey() { - return DenseMapInfo::getEmptyKey(); + static inline MDTuple *getEmptyKey() { + return DenseMapInfo::getEmptyKey(); } - static inline GenericMDNode *getTombstoneKey() { - return DenseMapInfo::getTombstoneKey(); + static inline MDTuple *getTombstoneKey() { + return DenseMapInfo::getTombstoneKey(); } static unsigned getHashValue(const KeyTy &Key) { return Key.Hash; } - static unsigned getHashValue(const GenericMDNode *U) { + static unsigned getHashValue(const MDTuple *U) { return U->getHash(); } - static bool isEqual(const KeyTy &LHS, const GenericMDNode *RHS) { + static bool isEqual(const KeyTy &LHS, const MDTuple *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; } }; @@ -245,13 +245,13 @@ public: DenseMap ValuesAsMetadata; DenseMap MetadataAsValues; - DenseSet MDNodeSet; + DenseSet MDTuples; // 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 // one object can destroy them. This set allows us to at least destroy them // on Context destruction. - SmallPtrSet NonUniquedMDNodes; + SmallPtrSet DistinctMDNodes; DenseMap CAZConstants; diff --git a/lib/IR/Metadata.cpp b/lib/IR/Metadata.cpp index 859512db001..282ea49aa41 100644 --- a/lib/IR/Metadata.cpp +++ b/lib/IR/Metadata.cpp @@ -222,8 +222,8 @@ void ReplaceableMetadataImpl::resolveAllUses(bool ResolveUsers) { if (Owner.is()) continue; - // Resolve GenericMDNodes that point at this. - auto *OwnerMD = dyn_cast(Owner.get()); + // Resolve UniquableMDNodes that point at this. + auto *OwnerMD = dyn_cast(Owner.get()); if (!OwnerMD) continue; if (OwnerMD->isResolved()) @@ -400,7 +400,7 @@ MDNode::MDNode(LLVMContext &Context, unsigned ID, ArrayRef MDs) bool MDNode::isResolved() const { if (isa(this)) return false; - return cast(this)->isResolved(); + return cast(this)->isResolved(); } static bool isOperandUnresolved(Metadata *Op) { @@ -409,9 +409,9 @@ static bool isOperandUnresolved(Metadata *Op) { return false; } -GenericMDNode::GenericMDNode(LLVMContext &C, ArrayRef Vals, - bool AllowRAUW) - : MDNode(C, GenericMDNodeKind, Vals) { +UniquableMDNode::UniquableMDNode(LLVMContext &C, unsigned ID, + ArrayRef Vals, bool AllowRAUW) + : MDNode(C, ID, Vals) { if (!AllowRAUW) return; @@ -427,16 +427,14 @@ GenericMDNode::GenericMDNode(LLVMContext &C, ArrayRef Vals, SubclassData32 = NumUnresolved; } -GenericMDNode::~GenericMDNode() { - LLVMContextImpl *pImpl = getContext().pImpl; +UniquableMDNode::~UniquableMDNode() { if (isStoredDistinctInContext()) - pImpl->NonUniquedMDNodes.erase(this); - else - pImpl->MDNodeSet.erase(this); + getContext().pImpl->DistinctMDNodes.erase(this); + dropAllReferences(); } -void GenericMDNode::resolve() { +void UniquableMDNode::resolve() { assert(!isResolved() && "Expected this to be unresolved"); // Move the map, so that this immediately looks resolved. @@ -448,7 +446,7 @@ void GenericMDNode::resolve() { Uses->resolveAllUses(); } -void GenericMDNode::resolveAfterOperandChange(Metadata *Old, Metadata *New) { +void UniquableMDNode::resolveAfterOperandChange(Metadata *Old, Metadata *New) { assert(SubclassData32 != 0 && "Expected unresolved operands"); // Check if an operand was resolved. @@ -458,13 +456,13 @@ void GenericMDNode::resolveAfterOperandChange(Metadata *Old, Metadata *New) { decrementUnresolvedOperandCount(); } -void GenericMDNode::decrementUnresolvedOperandCount() { +void UniquableMDNode::decrementUnresolvedOperandCount() { if (!--SubclassData32) // Last unresolved operand has just been resolved. resolve(); } -void GenericMDNode::resolveCycles() { +void UniquableMDNode::resolveCycles() { if (isResolved()) return; @@ -477,13 +475,18 @@ void GenericMDNode::resolveCycles() { continue; assert(!isa(Op) && "Expected all forward declarations to be resolved"); - if (auto *N = dyn_cast(Op)) + if (auto *N = dyn_cast(Op)) if (!N->isResolved()) 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())); #ifndef NDEBUG { @@ -498,10 +501,10 @@ void GenericMDNode::recalculateHash() { void MDNode::dropAllReferences() { for (unsigned I = 0, E = NumOperands; I != E; ++I) setOperand(I, nullptr); - if (auto *G = dyn_cast(this)) - if (!G->isResolved()) { - G->ReplaceableUses->resolveAllUses(/* ResolveUsers */ false); - G->ReplaceableUses.reset(); + if (auto *N = dyn_cast(this)) + if (!N->isResolved()) { + N->ReplaceableUses->resolveAllUses(/* ResolveUsers */ false); + N->ReplaceableUses.reset(); } } @@ -522,7 +525,7 @@ namespace llvm { 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(Ref) - op_begin(); assert(Op < getNumOperands() && "Expected valid operand"); @@ -534,8 +537,8 @@ void GenericMDNode::handleChangedOperand(void *Ref, Metadata *New) { return; } - auto &Store = getContext().pImpl->MDNodeSet; - Store.erase(this); + auto &Store = getContext().pImpl->MDTuples; + Store.erase(cast(this)); Metadata *Old = getOperand(Op); setOperand(Op, New); @@ -549,11 +552,11 @@ void GenericMDNode::handleChangedOperand(void *Ref, Metadata *New) { } // Re-unique the node. - recalculateHash(); - GenericMDNodeInfo::KeyTy Key(this); + cast(this)->recalculateHash(); + MDTupleInfo::KeyTy Key(cast(this)); auto I = Store.find_as(Key); if (I == Store.end()) { - Store.insert(this); + Store.insert(cast(this)); if (!isResolved()) resolveAfterOperandChange(Old, New); @@ -570,7 +573,7 @@ void GenericMDNode::handleChangedOperand(void *Ref, Metadata *New) { for (unsigned O = 0, E = getNumOperands(); O != E; ++O) setOperand(O, nullptr); ReplaceableUses->replaceAllUsesWith(*I); - delete this; + delete cast(this); return; } @@ -580,9 +583,9 @@ void GenericMDNode::handleChangedOperand(void *Ref, Metadata *New) { MDNode *MDNode::getMDNode(LLVMContext &Context, ArrayRef MDs, 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); if (I != Store.end()) return *I; @@ -590,14 +593,14 @@ MDNode *MDNode::getMDNode(LLVMContext &Context, ArrayRef MDs, return nullptr; // 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); Store.insert(N); return N; } MDNode *MDNode::getDistinct(LLVMContext &Context, ArrayRef MDs) { - auto *N = new (MDs.size()) GenericMDNode(Context, MDs, /* AllowRAUW */ false); + auto *N = new (MDs.size()) MDTuple(Context, MDs, /* AllowRAUW */ false); N->storeDistinctInContext(); return N; } @@ -616,9 +619,9 @@ void MDNode::deleteTemporary(MDNode *N) { void MDNode::storeDistinctInContext() { assert(!IsDistinctInContext && "Expected newly distinct metadata"); IsDistinctInContext = true; - auto *G = cast(this); - G->setHash(0); - getContext().pImpl->NonUniquedMDNodes.insert(G); + auto *T = cast(this); + T->setHash(0); + getContext().pImpl->DistinctMDNodes.insert(T); } void MDNode::replaceOperandWith(unsigned I, Metadata *New) { @@ -630,7 +633,7 @@ void MDNode::replaceOperandWith(unsigned I, Metadata *New) { return; } - cast(this)->handleChangedOperand(mutable_begin() + I, New); + cast(this)->handleChangedOperand(mutable_begin() + I, New); } void MDNode::setOperand(unsigned I, Metadata *New) { diff --git a/lib/IR/MetadataTracking.cpp b/lib/IR/MetadataTracking.cpp index 5b4b55586a9..ba97ca033a4 100644 --- a/lib/IR/MetadataTracking.cpp +++ b/lib/IR/MetadataTracking.cpp @@ -18,8 +18,8 @@ using namespace llvm; ReplaceableMetadataImpl *ReplaceableMetadataImpl::get(Metadata &MD) { if (auto *N = dyn_cast(&MD)) { - if (auto *G = dyn_cast(N)) - return G->ReplaceableUses.get(); + if (auto *U = dyn_cast(N)) + return U->ReplaceableUses.get(); return cast(N); } return dyn_cast(&MD); diff --git a/lib/Transforms/Utils/ValueMapper.cpp b/lib/Transforms/Utils/ValueMapper.cpp index 064cc575548..5d1c409371e 100644 --- a/lib/Transforms/Utils/ValueMapper.cpp +++ b/lib/Transforms/Utils/ValueMapper.cpp @@ -260,8 +260,8 @@ Metadata *llvm::MapMetadata(const Metadata *MD, ValueToValueMapTy &VM, ValueMaterializer *Materializer) { Metadata *NewMD = MapMetadataImpl(MD, VM, Flags, TypeMapper, Materializer); if (NewMD && NewMD != MD) - if (auto *G = dyn_cast(NewMD)) - G->resolveCycles(); + if (auto *N = dyn_cast(NewMD)) + N->resolveCycles(); return NewMD; }