Extend the GlobalObject metadata interface

- Make eraseMetadata return whether it changed something
- Wire getMetadata for a single MDNode efficiently into the attachment
map
- Add hasMetadata, which is less weird than checking getMetadata ==
nullptr on a multimap.

Use it to simplify code.

llvm-svn: 333649
This commit is contained in:
Benjamin Kramer 2018-05-31 13:29:58 +00:00
parent e37a5ce148
commit 0deb9a9a1f
6 changed files with 64 additions and 59 deletions

View File

@ -105,6 +105,14 @@ public:
/// Check if this has any metadata.
bool hasMetadata() const { return hasMetadataHashEntry(); }
/// Check if this has any metadata of the given kind.
bool hasMetadata(unsigned KindID) const {
return getMetadata(KindID) != nullptr;
}
bool hasMetadata(StringRef Kind) const {
return getMetadata(Kind) != nullptr;
}
/// Get the current metadata attachments for the given kind, if any.
///
/// These functions require that the function have at most a single attachment
@ -143,7 +151,9 @@ public:
getAllMetadata(SmallVectorImpl<std::pair<unsigned, MDNode *>> &MDs) const;
/// Erase all metadata attachments with the given kind.
void eraseMetadata(unsigned KindID);
///
/// \returns true if any metadata was removed.
bool eraseMetadata(unsigned KindID);
/// Copy metadata from Src, adjusting offsets by Offset.
void copyMetadata(const GlobalObject *Src, unsigned Offset);

View File

@ -313,7 +313,7 @@ static MDNode *stripDebugLocFromLoopID(MDNode *N) {
bool llvm::stripDebugInfo(Function &F) {
bool Changed = false;
if (F.getMetadata(LLVMContext::MD_dbg)) {
if (F.hasMetadata(LLVMContext::MD_dbg)) {
Changed = true;
F.setSubprogram(nullptr);
}
@ -369,12 +369,7 @@ bool llvm::StripDebugInfo(Module &M) {
Changed |= stripDebugInfo(F);
for (auto &GV : M.globals()) {
SmallVector<MDNode *, 1> MDs;
GV.getMetadata(LLVMContext::MD_dbg, MDs);
if (!MDs.empty()) {
GV.eraseMetadata(LLVMContext::MD_dbg);
Changed = true;
}
Changed |= GV.eraseMetadata(LLVMContext::MD_dbg);
}
if (GVMaterializer *Materializer = M.getMaterializer())

View File

@ -1164,7 +1164,7 @@ public:
/// Remove an attachment.
///
/// Remove the attachment at \c ID, if any.
void erase(unsigned ID);
bool erase(unsigned ID);
/// Copy out all the attachments.
///
@ -1197,10 +1197,14 @@ public:
/// Appends all attachments with the given ID to \c Result in insertion order.
/// If the global has no attachments with the given ID, or if ID is invalid,
/// leaves Result unchanged.
void get(unsigned ID, SmallVectorImpl<MDNode *> &Result);
void get(unsigned ID, SmallVectorImpl<MDNode *> &Result) const;
/// Returns the first attachment with the given ID or nullptr if no such
/// attachment exists.
MDNode *lookup(unsigned ID) const;
void insert(unsigned ID, MDNode &MD);
void erase(unsigned ID);
bool erase(unsigned ID);
/// Appends all attachments for the global to \c Result, sorting by attachment
/// ID. Attachments with the same ID appear in insertion order. This function

View File

@ -1110,14 +1110,14 @@ void MDAttachmentMap::set(unsigned ID, MDNode &MD) {
std::make_tuple(&MD));
}
void MDAttachmentMap::erase(unsigned ID) {
bool MDAttachmentMap::erase(unsigned ID) {
if (empty())
return;
return false;
// Common case is one/last value.
if (Attachments.back().first == ID) {
Attachments.pop_back();
return;
return true;
}
for (auto I = Attachments.begin(), E = std::prev(Attachments.end()); I != E;
@ -1125,8 +1125,10 @@ void MDAttachmentMap::erase(unsigned ID) {
if (I->first == ID) {
*I = std::move(Attachments.back());
Attachments.pop_back();
return;
return true;
}
return false;
}
MDNode *MDAttachmentMap::lookup(unsigned ID) const {
@ -1149,29 +1151,31 @@ void MDGlobalAttachmentMap::insert(unsigned ID, MDNode &MD) {
Attachments.push_back({ID, TrackingMDNodeRef(&MD)});
}
MDNode *MDGlobalAttachmentMap::lookup(unsigned ID) const {
for (const auto &A : Attachments)
if (A.MDKind == ID)
return A.Node;
return nullptr;
}
void MDGlobalAttachmentMap::get(unsigned ID,
SmallVectorImpl<MDNode *> &Result) {
for (auto A : Attachments)
SmallVectorImpl<MDNode *> &Result) const {
for (const auto &A : Attachments)
if (A.MDKind == ID)
Result.push_back(A.Node);
}
void MDGlobalAttachmentMap::erase(unsigned ID) {
auto Follower = Attachments.begin();
for (auto Leader = Attachments.begin(), E = Attachments.end(); Leader != E;
++Leader) {
if (Leader->MDKind != ID) {
if (Follower != Leader)
*Follower = std::move(*Leader);
++Follower;
}
}
Attachments.resize(Follower - Attachments.begin());
bool MDGlobalAttachmentMap::erase(unsigned ID) {
auto I = std::remove_if(Attachments.begin(), Attachments.end(),
[ID](const Attachment &A) { return A.MDKind == ID; });
bool Changed = I != Attachments.end();
Attachments.erase(I, Attachments.end());
return Changed;
}
void MDGlobalAttachmentMap::getAll(
SmallVectorImpl<std::pair<unsigned, MDNode *>> &Result) const {
for (auto &A : Attachments)
for (const auto &A : Attachments)
Result.emplace_back(A.MDKind, A.Node);
// Sort the resulting array so it is stable with respect to metadata IDs. We
@ -1398,15 +1402,16 @@ void GlobalObject::addMetadata(StringRef Kind, MDNode &MD) {
addMetadata(getContext().getMDKindID(Kind), MD);
}
void GlobalObject::eraseMetadata(unsigned KindID) {
bool GlobalObject::eraseMetadata(unsigned KindID) {
// Nothing to unset.
if (!hasMetadata())
return;
return false;
auto &Store = getContext().pImpl->GlobalObjectMetadata[this];
Store.erase(KindID);
bool Changed = Store.erase(KindID);
if (Store.empty())
clearMetadata();
return Changed;
}
void GlobalObject::getAllMetadata(
@ -1437,11 +1442,9 @@ void GlobalObject::setMetadata(StringRef Kind, MDNode *N) {
}
MDNode *GlobalObject::getMetadata(unsigned KindID) const {
SmallVector<MDNode *, 1> MDs;
getMetadata(KindID, MDs);
if (MDs.empty())
return nullptr;
return MDs[0];
if (hasMetadata())
return getContext().pImpl->GlobalObjectMetadata[this].lookup(KindID);
return nullptr;
}
MDNode *GlobalObject::getMetadata(StringRef Kind) const {

View File

@ -130,8 +130,7 @@ void promoteTypeIds(Module &M, StringRef ModuleId) {
}
GO.addMetadata(
LLVMContext::MD_type,
*MDNode::get(M.getContext(),
ArrayRef<Metadata *>{MD->getOperand(0), I->second}));
*MDNode::get(M.getContext(), {MD->getOperand(0), I->second}));
}
}
}
@ -216,10 +215,8 @@ void splitAndWriteThinLTOBitcode(
// Returns whether a global has attached type metadata. Such globals may
// participate in CFI or whole-program devirtualization, so they need to
// appear in the merged module instead of the thin LTO module.
auto HasTypeMetadata = [&](const GlobalObject *GO) {
SmallVector<MDNode *, 1> MDs;
GO->getMetadata(LLVMContext::MD_type, MDs);
return !MDs.empty();
auto HasTypeMetadata = [](const GlobalObject *GO) {
return GO->hasMetadata(LLVMContext::MD_type);
};
// Collect the set of virtual functions that are eligible for virtual constant
@ -337,14 +334,15 @@ void splitAndWriteThinLTOBitcode(
continue;
auto *F = cast<Function>(A.getAliasee());
SmallVector<Metadata *, 4> Elts;
Elts.push_back(MDString::get(Ctx, A.getName()));
Elts.push_back(MDString::get(Ctx, F->getName()));
Elts.push_back(ConstantAsMetadata::get(
llvm::ConstantInt::get(Type::getInt8Ty(Ctx), A.getVisibility())));
Elts.push_back(ConstantAsMetadata::get(
llvm::ConstantInt::get(Type::getInt8Ty(Ctx), A.isWeakForLinker())));
Metadata *Elts[] = {
MDString::get(Ctx, A.getName()),
MDString::get(Ctx, F->getName()),
ConstantAsMetadata::get(
ConstantInt::get(Type::getInt8Ty(Ctx), A.getVisibility())),
ConstantAsMetadata::get(
ConstantInt::get(Type::getInt8Ty(Ctx), A.isWeakForLinker())),
};
FunctionAliases.push_back(MDTuple::get(Ctx, Elts));
}
@ -361,11 +359,8 @@ void splitAndWriteThinLTOBitcode(
if (!F || F->use_empty())
return;
SmallVector<Metadata *, 2> Elts;
Elts.push_back(MDString::get(Ctx, Name));
Elts.push_back(MDString::get(Ctx, Alias));
Symvers.push_back(MDTuple::get(Ctx, Elts));
Symvers.push_back(MDTuple::get(
Ctx, {MDString::get(Ctx, Name), MDString::get(Ctx, Alias)}));
});
if (!Symvers.empty()) {
@ -418,10 +413,8 @@ void splitAndWriteThinLTOBitcode(
// Returns whether this module needs to be split because it uses type metadata.
bool requiresSplit(Module &M) {
SmallVector<MDNode *, 1> MDs;
for (auto &GO : M.global_objects()) {
GO.getMetadata(LLVMContext::MD_type, MDs);
if (!MDs.empty())
if (GO.hasMetadata(LLVMContext::MD_type))
return true;
}

View File

@ -1066,7 +1066,7 @@ Constant *DevirtModule::importConstant(VTableSlot Slot, ArrayRef<uint64_t> Args,
// We only need to set metadata if the global is newly created, in which
// case it would not have hidden visibility.
if (GV->getMetadata(LLVMContext::MD_absolute_symbol))
if (GV->hasMetadata(LLVMContext::MD_absolute_symbol))
return C;
auto SetAbsRange = [&](uint64_t Min, uint64_t Max) {