From 54a1f9f9c1e2cf6f4541e998b20f5c7cfbe642d9 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Wed, 30 Dec 2009 21:42:11 +0000 Subject: [PATCH] do not bother reuniquing mdnodes whose operands drop to null. Doing so can be a huge performance issue when tearing down modules and mdnodes are not guaranteed to be unique anyway. This speeds up: $ time ~/llvm/Release/bin/clang gcc.c -w -S -g from 72 to 35s, where gcc.c is from: http://people.csail.mit.edu/smcc/projects/single-file-programs/ git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@92315 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Metadata.h | 18 +++++++++++++++--- lib/VMCore/Metadata.cpp | 36 +++++++++++++++++++++++++++--------- 2 files changed, 42 insertions(+), 12 deletions(-) diff --git a/include/llvm/Metadata.h b/include/llvm/Metadata.h index 86eba354e2c..b53fd49b6cc 100644 --- a/include/llvm/Metadata.h +++ b/include/llvm/Metadata.h @@ -85,8 +85,6 @@ class MDNodeElement; //===----------------------------------------------------------------------===// /// MDNode - a tuple of other values. -/// These contain a list of the values that represent the metadata. -/// MDNode is always unnamed. class MDNode : public MetadataBase, public FoldingSetNode { MDNode(const MDNode &); // DO NOT IMPLEMENT void operator=(const MDNode &); // DO NOT IMPLEMENT @@ -97,7 +95,14 @@ class MDNode : public MetadataBase, public FoldingSetNode { // Subclass data enums. enum { - FunctionLocalBit = 1 + /// FunctionLocalBit - This bit is set if this MDNode is function local. + /// This is true when it (potentially transitively) contains a reference to + /// something in a function, like an argument, basicblock, or instruction. + FunctionLocalBit = 1 << 0, + + /// NotUniquedBit - This is set on MDNodes that are not uniqued because they + /// have a null perand. + NotUniquedBit = 1 << 1 }; // Replace each instance of F from the element list of this node with T. @@ -138,6 +143,13 @@ public: return V->getValueID() == MDNodeVal; } private: + bool isNotUniqued() const { + return (getSubclassDataFromValue() & NotUniquedBit) != 0; + } + void setIsNotUniqued() { + setValueSubclassData(getSubclassDataFromValue() | NotUniquedBit); + } + // Shadow Value::setValueSubclassData with a private forwarding method so that // any future subclasses cannot accidentally use it. void setValueSubclassData(unsigned short D) { diff --git a/lib/VMCore/Metadata.cpp b/lib/VMCore/Metadata.cpp index d5c1dba2d7b..0bed865bbae 100644 --- a/lib/VMCore/Metadata.cpp +++ b/lib/VMCore/Metadata.cpp @@ -87,8 +87,10 @@ void MDNodeElement::allUsesReplacedWith(Value *NV) { /// ~MDNode - Destroy MDNode. MDNode::~MDNode() { - LLVMContextImpl *pImpl = getType()->getContext().pImpl; - pImpl->MDNodeSet.RemoveNode(this); + if (!isNotUniqued()) { + LLVMContextImpl *pImpl = getType()->getContext().pImpl; + pImpl->MDNodeSet.RemoveNode(this); + } delete [] Operands; Operands = NULL; } @@ -97,6 +99,7 @@ MDNode::MDNode(LLVMContext &C, Value *const *Vals, unsigned NumVals, bool isFunctionLocal) : MetadataBase(Type::getMetadataTy(C), Value::MDNodeVal) { NumOperands = NumVals; + // FIXME: Coallocate the operand list. These have fixed arity. Operands = new MDNodeElement[NumOperands]; for (unsigned i = 0; i != NumVals; ++i) @@ -146,25 +149,40 @@ void MDNode::replaceElement(MDNodeElement *Op, Value *To) { if (From == To) return; + // Update the operand. + Op->set(To, this); + + // If this node is already not being uniqued (because one of the operands + // already went to null), then there is nothing else to do here. + if (isNotUniqued()) return; + LLVMContextImpl *pImpl = getType()->getContext().pImpl; // Remove "this" from the context map. FoldingSet doesn't have to reprofile // this node to remove it, so we don't care what state the operands are in. pImpl->MDNodeSet.RemoveNode(this); - // Update the operand. - Op->set(To, this); - - // Insert updated "this" into the context's folding node set. - // If a node with same element list already exist then before inserting - // updated "this" into the folding node set, replace all uses of existing - // node with updated "this" node. + // If we are dropping an argument to null, we choose to not unique the MDNode + // anymore. This commonly occurs during destruction, and uniquing these + // brings little reuse. + if (To == 0) { + setIsNotUniqued(); + return; + } + + // Now that the node is out of the folding set, get ready to reinsert it. + // First, check to see if another node with the same operands already exists + // in the set. If it doesn't exist, this returns the position to insert it. FoldingSetNodeID ID; Profile(ID); void *InsertPoint; MDNode *N = pImpl->MDNodeSet.FindNodeOrInsertPos(ID, InsertPoint); if (N) { + // FIXME: + // If it already exists in the set, we don't reinsert it, we just claim it + // isn't uniqued. + N->replaceAllUsesWith(this); delete N; N = pImpl->MDNodeSet.FindNodeOrInsertPos(ID, InsertPoint);