diff --git a/include/llvm/IR/Metadata.h b/include/llvm/IR/Metadata.h index 3fa1661f74d..4d5b61b4cfb 100644 --- a/include/llvm/IR/Metadata.h +++ b/include/llvm/IR/Metadata.h @@ -722,6 +722,9 @@ public: static inline TempMDTuple getTemporary(LLVMContext &Context, ArrayRef MDs); + /// \brief Create a (temporary) clone of this. + TempMDNode clone() const; + /// \brief Deallocate a node created by getTemporary. /// /// The node must not have any users. @@ -898,6 +901,11 @@ class MDTuple : public MDNode { static MDTuple *getImpl(LLVMContext &Context, ArrayRef MDs, StorageType Storage, bool ShouldCreate = true); + TempMDTuple cloneImpl() const { + return getTemporary(getContext(), + SmallVector(op_begin(), op_end())); + } + public: /// \brief Get the hash, if any. unsigned getHash() const { return SubclassData32; } @@ -926,6 +934,9 @@ public: return TempMDTuple(getImpl(Context, MDs, Temporary)); } + /// \brief Return a (temporary) clone of this. + TempMDTuple clone() const { return cloneImpl(); } + static bool classof(const Metadata *MD) { return MD->getMetadataID() == MDTupleKind; } @@ -965,6 +976,11 @@ class MDLocation : public MDNode { Metadata *InlinedAt, StorageType Storage, bool ShouldCreate = true); + TempMDLocation cloneImpl() const { + return getTemporary(getContext(), getLine(), getColumn(), getScope(), + getInlinedAt()); + } + // Disallow replacing operands. void replaceOperandWith(unsigned I, Metadata *New) LLVM_DELETED_FUNCTION; @@ -991,6 +1007,9 @@ public: getImpl(Context, Line, Column, Scope, InlinedAt, Temporary)); } + /// \brief Return a (temporary) clone of this. + TempMDLocation clone() const { return cloneImpl(); } + unsigned getLine() const { return SubclassData32; } unsigned getColumn() const { return SubclassData16; } Metadata *getScope() const { return getOperand(0); } @@ -1054,6 +1073,12 @@ class GenericDwarfNode : public DwarfNode { StorageType Storage, bool ShouldCreate = true); + TempGenericDwarfNode cloneImpl() const { + return getTemporary( + getContext(), getTag(), getHeader(), + SmallVector(dwarf_op_begin(), dwarf_op_end())); + } + public: unsigned getHash() const { return SubclassData32; } @@ -1081,6 +1106,9 @@ public: getImpl(Context, Tag, Header, DwarfOps, Temporary)); } + /// \brief Return a (temporary) clone of this. + TempGenericDwarfNode clone() const { return cloneImpl(); } + unsigned getTag() const { return SubclassData16; } MDString *getHeader() const { return cast_or_null(getOperand(0)); } diff --git a/lib/IR/Metadata.cpp b/lib/IR/Metadata.cpp index fc1f3e7a3cf..6c8f71ffa99 100644 --- a/lib/IR/Metadata.cpp +++ b/lib/IR/Metadata.cpp @@ -418,6 +418,17 @@ MDNode::MDNode(LLVMContext &Context, unsigned ID, StorageType Storage, this->Context.makeReplaceable(make_unique(Context)); } +TempMDNode MDNode::clone() const { + switch (getMetadataID()) { + default: + llvm_unreachable("Invalid MDNode subclass"); +#define HANDLE_MDNODE_LEAF(CLASS) \ + case CLASS##Kind: \ + return cast(this)->cloneImpl(); +#include "llvm/IR/Metadata.def" + } +} + static bool isOperandUnresolved(Metadata *Op) { if (auto *N = dyn_cast_or_null(Op)) return !N->isResolved(); diff --git a/lib/Transforms/Utils/ValueMapper.cpp b/lib/Transforms/Utils/ValueMapper.cpp index cba4677a2b0..db8728e3fa9 100644 --- a/lib/Transforms/Utils/ValueMapper.cpp +++ b/lib/Transforms/Utils/ValueMapper.cpp @@ -180,37 +180,6 @@ static Metadata *mapMetadataOp(Metadata *Op, ValueToValueMapTy &VM, return nullptr; } -static TempMDTuple cloneMDTuple(const MDTuple *Node) { - SmallVector Elts; - Elts.append(Node->op_begin(), Node->op_end()); - return MDTuple::getTemporary(Node->getContext(), Elts); -} - -static TempMDLocation cloneMDLocation(const MDLocation *Node) { - return MDLocation::getTemporary(Node->getContext(), Node->getLine(), - Node->getColumn(), Node->getScope(), - Node->getInlinedAt()); -} - -static TempGenericDwarfNode -cloneGenericDwarfNode(const GenericDwarfNode *Node) { - SmallVector DwarfOps; - DwarfOps.append(Node->dwarf_op_begin(), Node->dwarf_op_end()); - return GenericDwarfNode::getTemporary(Node->getContext(), Node->getTag(), - Node->getHeader(), DwarfOps); -} - -static TempMDNode cloneMDNode(const MDNode *Node) { - switch (Node->getMetadataID()) { - default: - llvm_unreachable("Invalid MDNode subclass"); -#define HANDLE_MDNODE_LEAF(CLASS) \ - case Metadata::CLASS##Kind: \ - return clone##CLASS(cast(Node)); -#include "llvm/IR/Metadata.def" - } -} - /// \brief Remap nodes. /// /// Insert \c NewNode in the value map, and then remap \c OldNode's operands. @@ -253,7 +222,7 @@ static Metadata *mapDistinctNode(const MDNode *Node, ValueToValueMapTy &VM, ValueMaterializer *Materializer) { assert(Node->isDistinct() && "Expected distinct node"); - MDNode *NewMD = MDNode::replaceWithDistinct(cloneMDNode(Node)); + MDNode *NewMD = MDNode::replaceWithDistinct(Node->clone()); remap(Node, NewMD, VM, Flags, TypeMapper, Materializer); return NewMD; } @@ -268,8 +237,7 @@ static Metadata *mapUniquedNode(const MDNode *Node, ValueToValueMapTy &VM, assert(Node->isUniqued() && "Expected uniqued node"); // Create a temporary node upfront in case we have a metadata cycle. - auto ClonedMD = cloneMDNode(Node); - + auto ClonedMD = Node->clone(); if (!remap(Node, ClonedMD.get(), VM, Flags, TypeMapper, Materializer)) // No operands changed, so use the identity mapping. return mapToSelf(VM, Node);