IR: Separate out decrementUnresolvedOperandCount(), NFC
[oota-llvm.git] / lib / IR / Metadata.cpp
index 150a186424cbbaa6259d7175e69249bd853a55c4..f78e7d2534d9e3dabf68ea18b0c5d1af21557bc8 100644 (file)
@@ -22,7 +22,6 @@
 #include "llvm/IR/ConstantRange.h"
 #include "llvm/IR/Instruction.h"
 #include "llvm/IR/LLVMContext.h"
-#include "llvm/IR/LeakDetector.h"
 #include "llvm/IR/Module.h"
 #include "llvm/IR/ValueHandle.h"
 
@@ -121,9 +120,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 +140,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<Metadata **>(Ref) == &MD) &&
+  assert((OwnerAndIndex.first || *static_cast<Metadata **>(Ref) == &MD) &&
          "Reference without owner must be direct");
-  assert((Owner || *static_cast<Metadata **>(New) == &MD) &&
+  assert((OwnerAndIndex.first || *static_cast<Metadata **>(New) == &MD) &&
          "Reference without owner must be direct");
 }
 
@@ -155,29 +161,35 @@ void ReplaceableMetadataImpl::replaceAllUsesWith(Metadata *MD) {
     return;
 
   // Copy out uses since UseMap will get touched below.
-  SmallVector<std::pair<void *, OwnerTy>, 8> Uses(UseMap.begin(), UseMap.end());
+  typedef std::pair<void *, std::pair<OwnerTy, uint64_t>> UseTy;
+  SmallVector<UseTy, 8> 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<Metadata **>(Pair.first);
       Ref = MD;
-      MetadataTracking::track(Ref);
+      if (MD)
+        MetadataTracking::track(Ref);
       UseMap.erase(Pair.first);
       continue;
     }
 
     // Check for MetadataAsValue.
-    if (Pair.second.is<MetadataAsValue *>()) {
-      Pair.second.get<MetadataAsValue *>()->handleChangedMetadata(MD);
+    if (Owner.is<MetadataAsValue *>()) {
+      Owner.get<MetadataAsValue *>()->handleChangedMetadata(MD);
       continue;
     }
 
     // There's a Metadata owner -- dispatch.
-    Metadata *Owner = Pair.second.get<Metadata *>();
-    switch (Owner->getMetadataID()) {
+    Metadata *OwnerMD = Owner.get<Metadata *>();
+    switch (OwnerMD->getMetadataID()) {
 #define HANDLE_METADATA_LEAF(CLASS)                                            \
   case Metadata::CLASS##Kind:                                                  \
-    cast<CLASS>(Owner)->handleChangedOperand(Pair.first, MD);                  \
+    cast<CLASS>(OwnerMD)->handleChangedOperand(Pair.first, MD);                \
     continue;
 #include "llvm/IR/Metadata.def"
     default:
@@ -197,23 +209,26 @@ void ReplaceableMetadataImpl::resolveAllUses(bool ResolveUsers) {
   }
 
   // Copy out uses since UseMap could get touched below.
-  SmallVector<std::pair<void *, OwnerTy>, 8> Uses(UseMap.begin(), UseMap.end());
+  typedef std::pair<void *, std::pair<OwnerTy, uint64_t>> UseTy;
+  SmallVector<UseTy, 8> 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<MetadataAsValue *>())
+    if (Owner.is<MetadataAsValue *>())
       continue;
 
     // Resolve GenericMDNodes that point at this.
-    auto *Owner = dyn_cast<GenericMDNode>(Pair.second.get<Metadata *>());
-    if (!Owner)
+    auto *OwnerMD = dyn_cast<GenericMDNode>(Owner.get<Metadata *>());
+    if (!OwnerMD)
       continue;
-    if (Owner->isResolved())
+    if (OwnerMD->isResolved())
       continue;
-    Owner->decrementUnresolvedOperands();
-    if (!Owner->hasUnresolvedOperands())
-      Owner->resolve();
+    OwnerMD->decrementUnresolvedOperandCount();
   }
 }
 
@@ -238,9 +253,9 @@ ValueAsMetadata *ValueAsMetadata::get(Value *V) {
            "Expected this to be the only metadata use");
     V->NameAndIsUsedByMD.setInt(true);
     if (auto *C = dyn_cast<Constant>(V))
-      Entry = new ConstantAsMetadata(Context, C);
+      Entry = new ConstantAsMetadata(C);
     else
-      Entry = new LocalAsMetadata(Context, V);
+      Entry = new LocalAsMetadata(V);
   }
 
   return Entry;
@@ -341,7 +356,8 @@ MDString *MDString::get(LLVMContext &Context, StringRef Str) {
   if (I != Store.end())
     return &I->second;
 
-  auto *Entry = StringMapEntry<MDString>::Create(Str, Store.getAllocator());
+  auto *Entry =
+      StringMapEntry<MDString>::Create(Str, Store.getAllocator(), MDString());
   bool WasInserted = Store.insert(Entry);
   (void)WasInserted;
   assert(WasInserted && "Expected entry to be inserted");
@@ -360,14 +376,18 @@ StringRef MDString::getString() const {
 
 void *MDNode::operator new(size_t Size, unsigned NumOps) {
   void *Ptr = ::operator new(Size + NumOps * sizeof(MDOperand));
-  MDOperand *First = new (Ptr) MDOperand[NumOps];
-  return First + NumOps;
+  MDOperand *O = static_cast<MDOperand *>(Ptr);
+  for (MDOperand *E = O + NumOps; O != E; ++O)
+    (void)new (O) MDOperand;
+  return O;
 }
 
 void MDNode::operator delete(void *Mem) {
   MDNode *N = static_cast<MDNode *>(Mem);
-  MDOperand *Last = static_cast<MDOperand *>(Mem);
-  ::operator delete(Last - N->NumOperands);
+  MDOperand *O = static_cast<MDOperand *>(Mem);
+  for (MDOperand *E = O - N->NumOperands; O != E; --O)
+    (O - 1)->~MDOperand();
+  ::operator delete(O);
 }
 
 MDNode::MDNode(LLVMContext &Context, unsigned ID, ArrayRef<Metadata *> MDs)
@@ -389,15 +409,22 @@ static bool isOperandUnresolved(Metadata *Op) {
   return false;
 }
 
-GenericMDNode::GenericMDNode(LLVMContext &C, ArrayRef<Metadata *> Vals)
+GenericMDNode::GenericMDNode(LLVMContext &C, ArrayRef<Metadata *> Vals,
+                             bool AllowRAUW)
     : MDNode(C, GenericMDNodeKind, Vals) {
+  if (!AllowRAUW)
+    return;
+
   // Check whether any operands are unresolved, requiring re-uniquing.
+  unsigned NumUnresolved = 0;
   for (const auto &Op : operands())
-    if (isOperandUnresolved(Op))
-      incrementUnresolvedOperands();
+    NumUnresolved += unsigned(isOperandUnresolved(Op));
+
+  if (!NumUnresolved)
+    return;
 
-  if (hasUnresolvedOperands())
-    ReplaceableUses.reset(new ReplaceableMetadataImpl);
+  ReplaceableUses.reset(new ReplaceableMetadataImpl);
+  SubclassData32 = NumUnresolved;
 }
 
 GenericMDNode::~GenericMDNode() {
@@ -406,6 +433,7 @@ GenericMDNode::~GenericMDNode() {
     pImpl->NonUniquedMDNodes.erase(this);
   else
     pImpl->MDNodeSet.erase(this);
+  dropAllReferences();
 }
 
 void GenericMDNode::resolve() {
@@ -420,6 +448,25 @@ void GenericMDNode::resolve() {
   Uses->resolveAllUses();
 }
 
+void GenericMDNode::resolveAfterOperandChange(Metadata *Old, Metadata *New) {
+  assert(SubclassData32 != 0 && "Expected unresolved operands");
+
+  // Check if the last unresolved operand has just been resolved; if so,
+  // resolve this as well.
+  if (isOperandUnresolved(Old)) {
+    if (!isOperandUnresolved(New))
+      decrementUnresolvedOperandCount();
+  } else {
+    // Operands shouldn't become unresolved.
+    assert(isOperandUnresolved(New) && "Operand just became unresolved");
+  }
+}
+
+void GenericMDNode::decrementUnresolvedOperandCount() {
+  if (!--SubclassData32)
+    resolve();
+}
+
 void GenericMDNode::resolveCycles() {
   if (isResolved())
     return;
@@ -439,6 +486,18 @@ void GenericMDNode::resolveCycles() {
   }
 }
 
+void GenericMDNode::recalculateHash() {
+  setHash(hash_combine_range(op_begin(), op_end()));
+#ifndef NDEBUG
+  {
+    SmallVector<Metadata *, 8> MDs(op_begin(), op_end());
+    unsigned RawHash = hash_combine_range(MDs.begin(), MDs.end());
+    assert(getHash() == RawHash &&
+           "Expected hash of MDOperand to equal hash of Metadata*");
+  }
+#endif
+}
+
 void MDNode::dropAllReferences() {
   for (unsigned I = 0, E = NumOperands; I != E; ++I)
     setOperand(I, nullptr);
@@ -484,47 +543,23 @@ void GenericMDNode::handleChangedOperand(void *Ref, Metadata *New) {
   Metadata *Old = getOperand(Op);
   setOperand(Op, New);
 
-  // Drop uniquing for self-reference cycles or if an operand drops to null.
-  //
-  // FIXME: Stop dropping uniquing when an operand drops to null.  The original
-  // motivation was to prevent madness during teardown of LLVMContextImpl, but
-  // dropAllReferences() fixes that problem in a better way.  (It's just here
-  // now for better staging of semantic changes.)
-  if (New == this || !New) {
+  // Drop uniquing for self-reference cycles.
+  if (New == this) {
     storeDistinctInContext();
-    setHash(0);
     if (!isResolved())
       resolve();
     return;
   }
 
-  // Re-calculate the hash.
-  setHash(hash_combine_range(op_begin(), op_end()));
-#ifndef NDEBUG
-  {
-    SmallVector<Metadata *, 8> MDs(op_begin(), op_end());
-    unsigned RawHash = hash_combine_range(MDs.begin(), MDs.end());
-    assert(getHash() == RawHash &&
-           "Expected hash of MDOperand to equal hash of Metadata*");
-  }
-#endif
-
   // Re-unique the node.
+  recalculateHash();
   GenericMDNodeInfo::KeyTy Key(this);
   auto I = Store.find_as(Key);
   if (I == Store.end()) {
     Store.insert(this);
 
-    if (!isResolved()) {
-      // Check if the last unresolved operand has just been resolved; if so,
-      // resolve this as well.
-      if (isOperandUnresolved(Old))
-        decrementUnresolvedOperands();
-      if (isOperandUnresolved(New))
-        incrementUnresolvedOperands();
-      if (!hasUnresolvedOperands())
-        resolve();
-    }
+    if (!isResolved())
+      resolveAfterOperandChange(Old, New);
 
     return;
   }
@@ -532,13 +567,17 @@ void GenericMDNode::handleChangedOperand(void *Ref, Metadata *New) {
   // Collision.
   if (!isResolved()) {
     // Still unresolved, so RAUW.
+    //
+    // First, clear out all operands to prevent any recursion (similar to
+    // dropAllReferences(), but we still need the use-list).
+    for (unsigned O = 0, E = getNumOperands(); O != E; ++O)
+      setOperand(O, nullptr);
     ReplaceableUses->replaceAllUsesWith(*I);
     delete this;
     return;
   }
 
-  // Store in non-uniqued form if this node has already been resolved.
-  setHash(0);
+  // Store in non-uniqued form if RAUW isn't possible.
   storeDistinctInContext();
 }
 
@@ -554,22 +593,26 @@ MDNode *MDNode::getMDNode(LLVMContext &Context, ArrayRef<Metadata *> MDs,
     return nullptr;
 
   // Coallocate space for the node and Operands together, then placement new.
-  GenericMDNode *N = new (MDs.size()) GenericMDNode(Context, MDs);
+  auto *N = new (MDs.size()) GenericMDNode(Context, MDs, /* AllowRAUW */ true);
   N->setHash(Key.Hash);
   Store.insert(N);
   return N;
 }
 
+MDNode *MDNode::getDistinct(LLVMContext &Context, ArrayRef<Metadata *> MDs) {
+  auto *N = new (MDs.size()) GenericMDNode(Context, MDs, /* AllowRAUW */ false);
+  N->storeDistinctInContext();
+  return N;
+}
+
 MDNodeFwdDecl *MDNode::getTemporary(LLVMContext &Context,
                                     ArrayRef<Metadata *> MDs) {
   MDNodeFwdDecl *N = new (MDs.size()) MDNodeFwdDecl(Context, MDs);
-  LeakDetector::addGarbageObject(N);
   return N;
 }
 
 void MDNode::deleteTemporary(MDNode *N) {
   assert(isa<MDNodeFwdDecl>(N) && "Expected forward declaration");
-  LeakDetector::removeGarbageObject(N);
   delete cast<MDNodeFwdDecl>(N);
 }
 
@@ -581,18 +624,16 @@ void MDNode::storeDistinctInContext() {
   getContext().pImpl->NonUniquedMDNodes.insert(G);
 }
 
-// Replace value from this node's operand list.
 void MDNode::replaceOperandWith(unsigned I, Metadata *New) {
   if (getOperand(I) == New)
     return;
 
-  if (auto *N = dyn_cast<GenericMDNode>(this)) {
-    N->handleChangedOperand(mutable_begin() + I, New);
+  if (isDistinct()) {
+    setOperand(I, New);
     return;
   }
 
-  assert(isa<MDNodeFwdDecl>(this) && "Expected an MDNode");
-  setOperand(I, New);
+  cast<GenericMDNode>(this)->handleChangedOperand(mutable_begin() + I, New);
 }
 
 void MDNode::setOperand(unsigned I, Metadata *New) {
@@ -806,13 +847,16 @@ unsigned NamedMDNode::getNumOperands() const {
 MDNode *NamedMDNode::getOperand(unsigned i) const {
   assert(i < getNumOperands() && "Invalid Operand number!");
   auto *N = getNMDOps(Operands)[i].get();
-  if (N && i > 10000)
-    N->dump();
   return cast_or_null<MDNode>(N);
 }
 
 void NamedMDNode::addOperand(MDNode *M) { getNMDOps(Operands).emplace_back(M); }
 
+void NamedMDNode::setOperand(unsigned I, MDNode *New) {
+  assert(I < getNumOperands() && "Invalid operand number");
+  getNMDOps(Operands)[I].reset(New);
+}
+
 void NamedMDNode::eraseFromParent() {
   getParent()->eraseNamedMetadata(this);
 }
@@ -1018,4 +1062,3 @@ void Instruction::clearMetadataHashEntries() {
   getContext().pImpl->MetadataStore.erase(this);
   setHasMetadataHashEntry(false);
 }
-