continue;
if (OwnerMD->isResolved())
continue;
- OwnerMD->decrementUnresolvedOperands();
- if (!OwnerMD->hasUnresolvedOperands())
- OwnerMD->resolve();
+ OwnerMD->decrementUnresolvedOperandCount();
}
}
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 (hasUnresolvedOperands())
- ReplaceableUses.reset(new ReplaceableMetadataImpl);
+ if (!NumUnresolved)
+ return;
+
+ ReplaceableUses.reset(new ReplaceableMetadataImpl);
+ SubclassData32 = NumUnresolved;
}
GenericMDNode::~GenericMDNode() {
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;
}
}
+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);
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);
// 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;
}
// 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();
}
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) {