}
void ReplaceableMetadataImpl::replaceAllUsesWith(Metadata *MD) {
- assert(!(MD && isa<MDNodeFwdDecl>(MD)) && "Expected non-temp node");
+ assert(!(MD && isa<MDNode>(MD) && cast<MDNode>(MD)->isTemporary()) &&
+ "Expected non-temp node");
if (UseMap.empty())
return;
MDNodeSubclassData(0) {
for (unsigned I = 0, E = MDs.size(); I != E; ++I)
setOperand(I, MDs[I]);
-}
-bool MDNode::isResolved() const {
- if (isa<MDNodeFwdDecl>(this))
- return false;
- return cast<UniquableMDNode>(this)->isResolved();
+ if (isTemporary())
+ this->Context.makeReplaceable(
+ make_unique<ReplaceableMetadataImpl>(Context));
}
static bool isOperandUnresolved(Metadata *Op) {
UniquableMDNode::UniquableMDNode(LLVMContext &C, unsigned ID,
StorageType Storage, ArrayRef<Metadata *> Vals)
: MDNode(C, ID, Storage, Vals) {
- if (Storage != Uniqued)
+ if (!isUniqued())
return;
// Check whether any operands are unresolved, requiring re-uniquing.
if (!NumUnresolved)
return;
- ReplaceableUses.reset(new ReplaceableMetadataImpl);
+ this->Context.makeReplaceable(make_unique<ReplaceableMetadataImpl>(C));
SubclassData32 = NumUnresolved;
}
void UniquableMDNode::resolve() {
+ assert(isUniqued() && "Expected this to be uniqued");
assert(!isResolved() && "Expected this to be unresolved");
// Move the map, so that this immediately looks resolved.
- auto Uses = std::move(ReplaceableUses);
+ auto Uses = Context.takeReplaceableUses();
SubclassData32 = 0;
assert(isResolved() && "Expected this to be resolved");
// Resolve all operands.
for (const auto &Op : operands()) {
- if (!Op)
+ auto *N = dyn_cast_or_null<UniquableMDNode>(Op);
+ if (!N)
continue;
- assert(!isa<MDNodeFwdDecl>(Op) &&
+
+ assert(!N->isTemporary() &&
"Expected all forward declarations to be resolved");
- if (auto *N = dyn_cast<UniquableMDNode>(Op))
- if (!N->isResolved())
- N->resolveCycles();
+ if (!N->isResolved())
+ N->resolveCycles();
}
}
setOperand(I, nullptr);
if (auto *N = dyn_cast<UniquableMDNode>(this))
if (!N->isResolved()) {
- N->ReplaceableUses->resolveAllUses(/* ResolveUsers */ false);
- N->ReplaceableUses.reset();
+ N->Context.getReplaceableUses()->resolveAllUses(/* ResolveUsers */ false);
+ (void)N->Context.takeReplaceableUses();
}
}
unsigned Op = static_cast<MDOperand *>(Ref) - op_begin();
assert(Op < getNumOperands() && "Expected valid operand");
- if (isStoredDistinctInContext()) {
- assert(isResolved() && "Expected distinct node to be resolved");
-
+ if (!isUniqued()) {
// This node is not uniqued. Just set the operand and be done with it.
setOperand(Op, New);
return;
// Drop uniquing for self-reference cycles.
if (New == this) {
- storeDistinctInContext();
if (!isResolved())
resolve();
+ storeDistinctInContext();
return;
}
// dropAllReferences(), but we still need the use-list).
for (unsigned O = 0, E = getNumOperands(); O != E; ++O)
setOperand(O, nullptr);
- ReplaceableUses->replaceAllUsesWith(Uniqued);
+ Context.getReplaceableUses()->replaceAllUsesWith(Uniqued);
deleteAsSubclass();
return;
}
}
}
-MDTuple *MDTuple::getImpl(LLVMContext &Context, ArrayRef<Metadata *> MDs,
- bool ShouldCreate) {
- MDTupleInfo::KeyTy Key(MDs);
-
- auto &Store = Context.pImpl->MDTuples;
+template <class T, class InfoT>
+static T *getUniqued(DenseSet<T *, InfoT> &Store,
+ const typename InfoT::KeyTy &Key) {
auto I = Store.find_as(Key);
- if (I != Store.end())
- return *I;
- if (!ShouldCreate)
- return nullptr;
+ return I == Store.end() ? nullptr : *I;
+}
- // Coallocate space for the node and Operands together, then placement new.
- auto *N = new (MDs.size()) MDTuple(Context, Uniqued, MDs);
- N->setHash(Key.Hash);
- Store.insert(N);
+template <class T, class StoreT>
+T *UniquableMDNode::storeImpl(T *N, StorageType Storage, StoreT &Store) {
+ switch (Storage) {
+ case Uniqued:
+ Store.insert(N);
+ break;
+ case Distinct:
+ N->storeDistinctInContext();
+ break;
+ case Temporary:
+ break;
+ }
return N;
}
-MDTuple *MDTuple::getDistinct(LLVMContext &Context, ArrayRef<Metadata *> MDs) {
- auto *N = new (MDs.size()) MDTuple(Context, Distinct, MDs);
- N->storeDistinctInContext();
- return N;
+MDTuple *MDTuple::getImpl(LLVMContext &Context, ArrayRef<Metadata *> MDs,
+ StorageType Storage, bool ShouldCreate) {
+ unsigned Hash = 0;
+ if (Storage == Uniqued) {
+ MDTupleInfo::KeyTy Key(MDs);
+ if (auto *N = getUniqued(Context.pImpl->MDTuples, Key))
+ return N;
+ if (!ShouldCreate)
+ return nullptr;
+ Hash = Key.Hash;
+ } else {
+ assert(ShouldCreate && "Expected non-uniqued nodes to always be created");
+ }
+
+ return storeImpl(new (MDs.size()) MDTuple(Context, Storage, Hash, MDs),
+ Storage, Context.pImpl->MDTuples);
}
MDTuple *MDTuple::uniquifyImpl() {
recalculateHash();
- MDTupleInfo::KeyTy Key(this);
-
auto &Store = getContext().pImpl->MDTuples;
- auto I = Store.find_as(Key);
- if (I == Store.end()) {
- Store.insert(this);
- return this;
- }
- return *I;
+ if (MDTuple *N = getUniqued(Store, this))
+ return N;
+
+ Store.insert(this);
+ return this;
}
void MDTuple::eraseFromStoreImpl() { getContext().pImpl->MDTuples.erase(this); }
SubclassData16 = Column;
}
-MDLocation *MDLocation::constructHelper(LLVMContext &Context,
- StorageType Storage, unsigned Line,
- unsigned Column, Metadata *Scope,
- Metadata *InlinedAt) {
- SmallVector<Metadata *, 2> Ops;
- Ops.push_back(Scope);
- if (InlinedAt)
- Ops.push_back(InlinedAt);
- return new (Ops.size()) MDLocation(Context, Storage, Line, Column, Ops);
-}
-
static void adjustLine(unsigned &Line) {
// Set to unknown on overflow. Still use 24 bits for now.
if (Line >= (1u << 24))
MDLocation *MDLocation::getImpl(LLVMContext &Context, unsigned Line,
unsigned Column, Metadata *Scope,
- Metadata *InlinedAt, bool ShouldCreate) {
+ Metadata *InlinedAt, StorageType Storage,
+ bool ShouldCreate) {
// Fixup line/column.
adjustLine(Line);
adjustColumn(Column);
- MDLocationInfo::KeyTy Key(Line, Column, Scope, InlinedAt);
-
- auto &Store = Context.pImpl->MDLocations;
- auto I = Store.find_as(Key);
- if (I != Store.end())
- return *I;
- if (!ShouldCreate)
- return nullptr;
-
- auto *N = constructHelper(Context, Uniqued, Line, Column, Scope, InlinedAt);
- Store.insert(N);
- return N;
-}
-
-MDLocation *MDLocation::getDistinct(LLVMContext &Context, unsigned Line,
- unsigned Column, Metadata *Scope,
- Metadata *InlinedAt) {
- // Fixup line/column.
- adjustLine(Line);
- adjustColumn(Column);
+ if (Storage == Uniqued) {
+ if (auto *N = getUniqued(
+ Context.pImpl->MDLocations,
+ MDLocationInfo::KeyTy(Line, Column, Scope, InlinedAt)))
+ return N;
+ if (!ShouldCreate)
+ return nullptr;
+ } else {
+ assert(ShouldCreate && "Expected non-uniqued nodes to always be created");
+ }
- auto *N = constructHelper(Context, Distinct, Line, Column, Scope, InlinedAt);
- N->storeDistinctInContext();
- return N;
+ SmallVector<Metadata *, 2> Ops;
+ Ops.push_back(Scope);
+ if (InlinedAt)
+ Ops.push_back(InlinedAt);
+ return storeImpl(new (Ops.size())
+ MDLocation(Context, Storage, Line, Column, Ops),
+ Storage, Context.pImpl->MDLocations);
}
MDLocation *MDLocation::uniquifyImpl() {
- MDLocationInfo::KeyTy Key(this);
-
auto &Store = getContext().pImpl->MDLocations;
- auto I = Store.find_as(Key);
- if (I == Store.end()) {
- Store.insert(this);
- return this;
- }
- return *I;
+ if (MDLocation *N = getUniqued(Store, this))
+ return N;
+
+ Store.insert(this);
+ return this;
}
void MDLocation::eraseFromStoreImpl() {
getContext().pImpl->MDLocations.erase(this);
}
-MDNodeFwdDecl *MDNode::getTemporary(LLVMContext &Context,
- ArrayRef<Metadata *> MDs) {
- return MDNodeFwdDecl::get(Context, MDs);
+void MDNode::deleteTemporary(MDNode *N) {
+ assert(N->isTemporary() && "Expected temporary node");
+ cast<UniquableMDNode>(N)->deleteAsSubclass();
}
-void MDNode::deleteTemporary(MDNode *N) { delete cast<MDNodeFwdDecl>(N); }
-
void UniquableMDNode::storeDistinctInContext() {
+ assert(isResolved() && "Expected resolved nodes");
Storage = Distinct;
if (auto *T = dyn_cast<MDTuple>(this))
T->setHash(0);
void MDNode::setOperand(unsigned I, Metadata *New) {
assert(I < NumOperands);
- if (isStoredDistinctInContext() || isa<MDNodeFwdDecl>(this))
- // No need for a callback, this isn't uniqued.
- mutable_begin()[I].reset(New, nullptr);
- else
- mutable_begin()[I].reset(New, this);
+ mutable_begin()[I].reset(New, isUniqued() ? this : nullptr);
}
/// \brief Get a node, or a self-reference that looks like it.