Metadata *MD) {
MD = canonicalizeMetadataForValue(Context, MD);
auto &Store = Context.pImpl->MetadataAsValues;
- auto I = Store.find(MD);
- return I == Store.end() ? nullptr : I->second;
+ return Store.lookup(MD);
}
void MetadataAsValue::handleChangedMetadata(Metadata *MD) {
unsigned MDNode::countUnresolvedOperands() {
assert(NumUnresolved == 0 && "Expected unresolved ops to be uncounted");
- for (const auto &Op : operands())
- NumUnresolved += unsigned(isOperandUnresolved(Op));
+ NumUnresolved = std::count_if(op_begin(), op_end(), isOperandUnresolved);
return NumUnresolved;
}
}
}
+static bool hasSelfReference(MDNode *N) {
+ for (Metadata *MD : N->operands())
+ if (MD == N)
+ return true;
+ return false;
+}
+
+MDNode *MDNode::replaceWithPermanentImpl() {
+ if (hasSelfReference(this))
+ return replaceWithDistinctImpl();
+ return replaceWithUniquedImpl();
+}
+
MDNode *MDNode::replaceWithUniquedImpl() {
// Try to uniquify in place.
MDNode *UniquedNode = uniquify();
+
if (UniquedNode == this) {
makeUniqued();
return this;
};
MDNode *MDNode::uniquify() {
+ assert(!hasSelfReference(this) && "Cannot uniquify a self-referencing node");
+
// Try to insert into uniquing store.
switch (getMetadataID()) {
default:
if (!B)
return A;
- SmallVector<Metadata *, 4> MDs(A->getNumOperands() + B->getNumOperands());
-
- unsigned j = 0;
- for (unsigned i = 0, ie = A->getNumOperands(); i != ie; ++i)
- MDs[j++] = A->getOperand(i);
- for (unsigned i = 0, ie = B->getNumOperands(); i != ie; ++i)
- MDs[j++] = B->getOperand(i);
+ SmallVector<Metadata *, 4> MDs;
+ MDs.reserve(A->getNumOperands() + B->getNumOperands());
+ MDs.append(A->op_begin(), A->op_end());
+ MDs.append(B->op_begin(), B->op_end());
// FIXME: This preserves long-standing behaviour, but is it really the right
// behaviour? Or was that an unintended side-effect of node uniquing?
return nullptr;
SmallVector<Metadata *, 4> MDs;
- for (unsigned i = 0, ie = A->getNumOperands(); i != ie; ++i) {
- Metadata *MD = A->getOperand(i);
- for (unsigned j = 0, je = B->getNumOperands(); j != je; ++j)
- if (MD == B->getOperand(j)) {
- MDs.push_back(MD);
- break;
- }
- }
+ for (Metadata *MD : A->operands())
+ if (std::find(B->op_begin(), B->op_end(), MD) != B->op_end())
+ MDs.push_back(MD);
+
+ // FIXME: This preserves long-standing behaviour, but is it really the right
+ // behaviour? Or was that an unintended side-effect of node uniquing?
+ return getOrSelfReference(A->getContext(), MDs);
+}
+
+MDNode *MDNode::getMostGenericAliasScope(MDNode *A, MDNode *B) {
+ if (!A || !B)
+ return nullptr;
+
+ SmallVector<Metadata *, 4> MDs(B->op_begin(), B->op_end());
+ for (Metadata *MD : A->operands())
+ if (std::find(B->op_begin(), B->op_end(), MD) == B->op_end())
+ MDs.push_back(MD);
// FIXME: This preserves long-standing behaviour, but is it really the right
// behaviour? Or was that an unintended side-effect of node uniquing?