IR: Invert logic to simplify control flow, NFC
[oota-llvm.git] / lib / IR / Metadata.cpp
index 0f748495261bfd0434b8934149289d1e679d1842..859512db001585cf77e417b6d37f9edf3ee1361c 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"
 
@@ -173,7 +172,8 @@ void ReplaceableMetadataImpl::replaceAllUsesWith(Metadata *MD) {
       // 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;
     }
@@ -228,9 +228,7 @@ void ReplaceableMetadataImpl::resolveAllUses(bool ResolveUsers) {
       continue;
     if (OwnerMD->isResolved())
       continue;
-    OwnerMD->decrementUnresolvedOperands();
-    if (!OwnerMD->hasUnresolvedOperands())
-      OwnerMD->resolve();
+    OwnerMD->decrementUnresolvedOperandCount();
   }
 }
 
@@ -255,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;
@@ -411,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() {
@@ -428,6 +433,7 @@ GenericMDNode::~GenericMDNode() {
     pImpl->NonUniquedMDNodes.erase(this);
   else
     pImpl->MDNodeSet.erase(this);
+  dropAllReferences();
 }
 
 void GenericMDNode::resolve() {
@@ -442,6 +448,22 @@ void GenericMDNode::resolve() {
   Uses->resolveAllUses();
 }
 
+void GenericMDNode::resolveAfterOperandChange(Metadata *Old, Metadata *New) {
+  assert(SubclassData32 != 0 && "Expected unresolved operands");
+
+  // Check if an operand was resolved.
+  if (!isOperandUnresolved(Old))
+    assert(isOperandUnresolved(New) && "Operand just became unresolved");
+  else if (!isOperandUnresolved(New))
+    decrementUnresolvedOperandCount();
+}
+
+void GenericMDNode::decrementUnresolvedOperandCount() {
+  if (!--SubclassData32)
+    // Last unresolved operand has just been resolved.
+    resolve();
+}
+
 void GenericMDNode::resolveCycles() {
   if (isResolved())
     return;
@@ -461,6 +483,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);
@@ -499,14 +533,6 @@ void GenericMDNode::handleChangedOperand(void *Ref, Metadata *New) {
     setOperand(Op, New);
     return;
   }
-  if (InRAUW) {
-    // We just hit a recursion due to RAUW.  Set the operand and move on, since
-    // we're about to be deleted.
-    //
-    // FIXME: Can this cycle really happen?
-    setOperand(Op, New);
-    return;
-  }
 
   auto &Store = getContext().pImpl->MDNodeSet;
   Store.erase(this);
@@ -514,47 +540,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;
   }
@@ -562,14 +564,17 @@ void GenericMDNode::handleChangedOperand(void *Ref, Metadata *New) {
   // Collision.
   if (!isResolved()) {
     // Still unresolved, so RAUW.
-    InRAUW = true;
+    //
+    // 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();
 }
 
@@ -585,22 +590,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);
 }
 
@@ -612,18 +621,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) {
@@ -837,13 +844,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);
 }
@@ -1049,4 +1059,3 @@ void Instruction::clearMetadataHashEntries() {
   getContext().pImpl->MetadataStore.erase(this);
   setHasMetadataHashEntry(false);
 }
-