diff --git a/include/llvm/IR/Metadata.h b/include/llvm/IR/Metadata.h index 81107e69806..ffdd7002cea 100644 --- a/include/llvm/IR/Metadata.h +++ b/include/llvm/IR/Metadata.h @@ -141,9 +141,11 @@ public: typedef MetadataTracking::OwnerTy OwnerTy; private: - SmallDenseMap UseMap; + uint64_t NextIndex; + SmallDenseMap, 4> UseMap; public: + ReplaceableMetadataImpl() : NextIndex(0) {} ~ReplaceableMetadataImpl() { assert(UseMap.empty() && "Cannot destroy in-use replaceable metadata"); } diff --git a/lib/IR/Metadata.cpp b/lib/IR/Metadata.cpp index cd5edd216c3..805b7377bce 100644 --- a/lib/IR/Metadata.cpp +++ b/lib/IR/Metadata.cpp @@ -121,9 +121,14 @@ void MetadataAsValue::untrack() { } void ReplaceableMetadataImpl::addRef(void *Ref, OwnerTy Owner) { - bool WasInserted = UseMap.insert(std::make_pair(Ref, Owner)).second; + bool WasInserted = + UseMap.insert(std::make_pair(Ref, std::make_pair(Owner, NextIndex))) + .second; (void)WasInserted; assert(WasInserted && "Expected to add a reference"); + + ++NextIndex; + assert(NextIndex != 0 && "Unexpected overflow"); } void ReplaceableMetadataImpl::dropRef(void *Ref) { @@ -136,15 +141,17 @@ void ReplaceableMetadataImpl::moveRef(void *Ref, void *New, const Metadata &MD) { auto I = UseMap.find(Ref); assert(I != UseMap.end() && "Expected to move a reference"); - OwnerTy Owner = I->second; + auto OwnerAndIndex = I->second; UseMap.erase(I); - addRef(New, Owner); + bool WasInserted = UseMap.insert(std::make_pair(New, OwnerAndIndex)).second; + (void)WasInserted; + assert(WasInserted && "Expected to add a reference"); // Check that the references are direct if there's no owner. (void)MD; - assert((Owner || *static_cast(Ref) == &MD) && + assert((OwnerAndIndex.first || *static_cast(Ref) == &MD) && "Reference without owner must be direct"); - assert((Owner || *static_cast(New) == &MD) && + assert((OwnerAndIndex.first || *static_cast(New) == &MD) && "Reference without owner must be direct"); } @@ -155,9 +162,14 @@ void ReplaceableMetadataImpl::replaceAllUsesWith(Metadata *MD) { return; // Copy out uses since UseMap will get touched below. - SmallVector, 8> Uses(UseMap.begin(), UseMap.end()); + typedef std::pair> UseTy; + SmallVector Uses(UseMap.begin(), UseMap.end()); + std::sort(Uses.begin(), Uses.end(), [](const UseTy &L, const UseTy &R) { + return L.second.second < R.second.second; + }); for (const auto &Pair : Uses) { - if (!Pair.second) { + OwnerTy Owner = Pair.second.first; + if (!Owner) { // Update unowned tracking references directly. Metadata *&Ref = *static_cast(Pair.first); Ref = MD; @@ -167,17 +179,17 @@ void ReplaceableMetadataImpl::replaceAllUsesWith(Metadata *MD) { } // Check for MetadataAsValue. - if (Pair.second.is()) { - Pair.second.get()->handleChangedMetadata(MD); + if (Owner.is()) { + Owner.get()->handleChangedMetadata(MD); continue; } // There's a Metadata owner -- dispatch. - Metadata *Owner = Pair.second.get(); - switch (Owner->getMetadataID()) { + Metadata *OwnerMD = Owner.get(); + switch (OwnerMD->getMetadataID()) { #define HANDLE_METADATA_LEAF(CLASS) \ case Metadata::CLASS##Kind: \ - cast(Owner)->handleChangedOperand(Pair.first, MD); \ + cast(OwnerMD)->handleChangedOperand(Pair.first, MD); \ continue; #include "llvm/IR/Metadata.def" default: @@ -197,23 +209,28 @@ void ReplaceableMetadataImpl::resolveAllUses(bool ResolveUsers) { } // Copy out uses since UseMap could get touched below. - SmallVector, 8> Uses(UseMap.begin(), UseMap.end()); + typedef std::pair> UseTy; + SmallVector Uses(UseMap.begin(), UseMap.end()); + std::sort(Uses.begin(), Uses.end(), [](const UseTy &L, const UseTy &R) { + return L.second.second < R.second.second; + }); UseMap.clear(); for (const auto &Pair : Uses) { - if (!Pair.second) + auto Owner = Pair.second.first; + if (!Owner) continue; - if (Pair.second.is()) + if (Owner.is()) continue; // Resolve GenericMDNodes that point at this. - auto *Owner = dyn_cast(Pair.second.get()); - if (!Owner) + auto *OwnerMD = dyn_cast(Owner.get()); + if (!OwnerMD) continue; - if (Owner->isResolved()) + if (OwnerMD->isResolved()) continue; - Owner->decrementUnresolvedOperands(); - if (!Owner->hasUnresolvedOperands()) - Owner->resolve(); + OwnerMD->decrementUnresolvedOperands(); + if (!OwnerMD->hasUnresolvedOperands()) + OwnerMD->resolve(); } }