diff options
| author | Duncan P. N. Exon Smith <dexonsmith@apple.com> | 2016-04-03 21:23:52 +0000 |
|---|---|---|
| committer | Duncan P. N. Exon Smith <dexonsmith@apple.com> | 2016-04-03 21:23:52 +0000 |
| commit | fef609f15e09b4c42334a8ff8c2de29af502ff56 (patch) | |
| tree | e2828f1845b49898b1aabb25d42b8bbdde52ac8c /llvm/lib | |
| parent | bd088744be436e74af45ba76cc28fbe6dbe4402d (diff) | |
| download | bcm5719-llvm-fef609f15e09b4c42334a8ff8c2de29af502ff56.tar.gz bcm5719-llvm-fef609f15e09b4c42334a8ff8c2de29af502ff56.zip | |
IR: Lazily create ReplaceableMetadataImpl on MDNode
RAUW support on MDNode usually requires an extra allocation for
ReplaceableMetadataImpl. This is only strictly necessary if there are
tracking references to the MDNode. Make the construction of
ReplaceableMetadataImpl lazy, so that we don't get allocations if we
don't need them.
Since MDNode::isResolved now checks MDNode::isTemporary and
MDNode::NumUnresolved instead of whether a ReplaceableMetadataImpl is
allocated, the internal changes are intrusive (at various internal
checkpoints, isResolved now has a different answer).
However, there should be no real functionality change here; just
slightly lazier allocation behaviour. The external semantics should be
identical.
llvm-svn: 265279
Diffstat (limited to 'llvm/lib')
| -rw-r--r-- | llvm/lib/IR/Metadata.cpp | 91 |
1 files changed, 60 insertions, 31 deletions
diff --git a/llvm/lib/IR/Metadata.cpp b/llvm/lib/IR/Metadata.cpp index b874308afa3..fc134e4b5d9 100644 --- a/llvm/lib/IR/Metadata.cpp +++ b/llvm/lib/IR/Metadata.cpp @@ -124,7 +124,7 @@ bool MetadataTracking::track(void *Ref, Metadata &MD, OwnerTy Owner) { assert(Ref && "Expected live reference"); assert((Owner || *static_cast<Metadata **>(Ref) == &MD) && "Reference without owner must be direct"); - if (auto *R = ReplaceableMetadataImpl::get(MD)) { + if (auto *R = ReplaceableMetadataImpl::getOrCreate(MD)) { R->addRef(Ref, Owner); return true; } @@ -133,7 +133,7 @@ bool MetadataTracking::track(void *Ref, Metadata &MD, OwnerTy Owner) { void MetadataTracking::untrack(void *Ref, Metadata &MD) { assert(Ref && "Expected live reference"); - if (auto *R = ReplaceableMetadataImpl::get(MD)) + if (auto *R = ReplaceableMetadataImpl::getIfExists(MD)) R->dropRef(Ref); } @@ -141,15 +141,17 @@ bool MetadataTracking::retrack(void *Ref, Metadata &MD, void *New) { assert(Ref && "Expected live reference"); assert(New && "Expected live reference"); assert(Ref != New && "Expected change"); - if (auto *R = ReplaceableMetadataImpl::get(MD)) { + if (auto *R = ReplaceableMetadataImpl::getIfExists(MD)) { R->moveRef(Ref, New, MD); return true; } + assert(!isReplaceable(MD) && + "Expected un-replaceable metadata, since we didn't move a reference"); return false; } bool MetadataTracking::isReplaceable(const Metadata &MD) { - return ReplaceableMetadataImpl::get(const_cast<Metadata &>(MD)); + return ReplaceableMetadataImpl::isReplaceable(MD); } void ReplaceableMetadataImpl::addRef(void *Ref, OwnerTy Owner) { @@ -268,9 +270,21 @@ void ReplaceableMetadataImpl::resolveAllUses(bool ResolveUsers) { } } -ReplaceableMetadataImpl *ReplaceableMetadataImpl::get(Metadata &MD) { +ReplaceableMetadataImpl *ReplaceableMetadataImpl::getOrCreate(Metadata &MD) { if (auto *N = dyn_cast<MDNode>(&MD)) - return N->Context.getReplaceableUses(); + return N->isResolved() ? nullptr : N->Context.getOrCreateReplaceableUses(); + return dyn_cast<ValueAsMetadata>(&MD); +} + +ReplaceableMetadataImpl *ReplaceableMetadataImpl::getIfExists(Metadata &MD) { + if (auto *N = dyn_cast<MDNode>(&MD)) + return N->isResolved() ? nullptr : N->Context.getReplaceableUses(); + return dyn_cast<ValueAsMetadata>(&MD); +} + +bool ReplaceableMetadataImpl::isReplaceable(const Metadata &MD) { + if (auto *N = dyn_cast<MDNode>(&MD)) + return !N->isResolved(); return dyn_cast<ValueAsMetadata>(&MD); } @@ -452,16 +466,12 @@ MDNode::MDNode(LLVMContext &Context, unsigned ID, StorageType Storage, for (Metadata *MD : Ops2) setOperand(Op++, MD); - if (isDistinct()) + if (!isUniqued()) return; - if (isUniqued()) - // Check whether any operands are unresolved, requiring re-uniquing. If - // not, don't support RAUW. - if (!countUnresolvedOperands()) - return; - - this->Context.makeReplaceable(make_unique<ReplaceableMetadataImpl>(Context)); + // Count the unresolved operands. If there are any, RAUW support will be + // added lazily on first reference. + countUnresolvedOperands(); } TempMDNode MDNode::clone() const { @@ -481,10 +491,10 @@ static bool isOperandUnresolved(Metadata *Op) { return false; } -unsigned MDNode::countUnresolvedOperands() { +void MDNode::countUnresolvedOperands() { assert(NumUnresolved == 0 && "Expected unresolved ops to be uncounted"); + assert(isUniqued() && "Expected this to be uniqued"); NumUnresolved = std::count_if(op_begin(), op_end(), isOperandUnresolved); - return NumUnresolved; } void MDNode::makeUniqued() { @@ -497,8 +507,11 @@ void MDNode::makeUniqued() { // Make this 'uniqued'. Storage = Uniqued; - if (!countUnresolvedOperands()) - resolve(); + countUnresolvedOperands(); + if (!NumUnresolved) { + dropReplaceableUses(); + assert(isResolved() && "Expected this to be resolved"); + } assert(isUniqued() && "Expected this to be uniqued"); } @@ -507,9 +520,8 @@ void MDNode::makeDistinct() { assert(isTemporary() && "Expected this to be temporary"); assert(!isResolved() && "Expected this to be unresolved"); - // Pretend to be uniqued, resolve the node, and then store in distinct table. - Storage = Uniqued; - resolve(); + // Drop RAUW support and store as a distinct node. + dropReplaceableUses(); storeDistinctInContext(); assert(isDistinct() && "Expected this to be distinct"); @@ -520,16 +532,22 @@ void MDNode::resolve() { assert(isUniqued() && "Expected this to be uniqued"); assert(!isResolved() && "Expected this to be unresolved"); - // Move the map, so that this immediately looks resolved. - auto Uses = Context.takeReplaceableUses(); NumUnresolved = 0; + dropReplaceableUses(); + assert(isResolved() && "Expected this to be resolved"); +} + +void MDNode::dropReplaceableUses() { + assert(!NumUnresolved && "Unexpected unresolved operand"); - // Drop RAUW support. - Uses->resolveAllUses(); + // Drop any RAUW support. + if (Context.hasReplaceableUses()) + Context.takeReplaceableUses()->resolveAllUses(); } void MDNode::resolveAfterOperandChange(Metadata *Old, Metadata *New) { + assert(isUniqued() && "Expected this to be uniqued"); assert(NumUnresolved != 0 && "Expected unresolved operands"); // Check if an operand was resolved. @@ -542,9 +560,17 @@ void MDNode::resolveAfterOperandChange(Metadata *Old, Metadata *New) { } void MDNode::decrementUnresolvedOperandCount() { - if (!--NumUnresolved) - // Last unresolved operand has just been resolved. - resolve(); + assert(!isResolved() && "Expected this to be unresolved"); + if (isTemporary()) + return; + + assert(isUniqued() && "Expected this to be uniqued"); + if (--NumUnresolved) + return; + + // Last unresolved operand has just been resolved. + dropReplaceableUses(); + assert(isResolved() && "Expected this to become resolved"); } void MDNode::resolveCycles() { @@ -619,7 +645,7 @@ void MDTuple::recalculateHash() { void MDNode::dropAllReferences() { for (unsigned I = 0, E = NumOperands; I != E; ++I) setOperand(I, nullptr); - if (!isResolved()) { + if (Context.hasReplaceableUses()) { Context.getReplaceableUses()->resolveAllUses(/* ResolveUsers */ false); (void)Context.takeReplaceableUses(); } @@ -665,7 +691,8 @@ void MDNode::handleChangedOperand(void *Ref, Metadata *New) { // dropAllReferences(), but we still need the use-list). for (unsigned O = 0, E = getNumOperands(); O != E; ++O) setOperand(O, nullptr); - Context.getReplaceableUses()->replaceAllUsesWith(Uniqued); + if (Context.hasReplaceableUses()) + Context.getReplaceableUses()->replaceAllUsesWith(Uniqued); deleteAsSubclass(); return; } @@ -763,8 +790,10 @@ void MDNode::deleteTemporary(MDNode *N) { } void MDNode::storeDistinctInContext() { - assert(isResolved() && "Expected resolved nodes"); + assert(!Context.hasReplaceableUses() && "Unexpected replaceable uses"); + assert(!NumUnresolved && "Unexpected unresolved nodes"); Storage = Distinct; + assert(isResolved() && "Expected this to be resolved"); // Reset the hash. switch (getMetadataID()) { |

