diff --git a/llvm/include/llvm/IR/GlobalObject.h b/llvm/include/llvm/IR/GlobalObject.h --- a/llvm/include/llvm/IR/GlobalObject.h +++ b/llvm/include/llvm/IR/GlobalObject.h @@ -40,7 +40,6 @@ Comdat *ObjComdat; enum { LastAlignmentBit = 4, - HasMetadataHashEntryBit, HasSectionHashEntryBit, GlobalObjectBits, @@ -106,59 +105,6 @@ Comdat *getComdat() { return ObjComdat; } void setComdat(Comdat *C) { ObjComdat = C; } - /// 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 - /// of the given kind, and return \c nullptr if such an attachment is missing. - /// @{ - MDNode *getMetadata(unsigned KindID) const; - MDNode *getMetadata(StringRef Kind) const; - /// @} - - /// Appends all attachments with the given ID to \c MDs in insertion order. - /// If the global has no attachments with the given ID, or if ID is invalid, - /// leaves MDs unchanged. - /// @{ - void getMetadata(unsigned KindID, SmallVectorImpl &MDs) const; - void getMetadata(StringRef Kind, SmallVectorImpl &MDs) const; - /// @} - - /// Set a particular kind of metadata attachment. - /// - /// Sets the given attachment to \c MD, erasing it if \c MD is \c nullptr or - /// replacing it if it already exists. - /// @{ - void setMetadata(unsigned KindID, MDNode *MD); - void setMetadata(StringRef Kind, MDNode *MD); - /// @} - - /// Add a metadata attachment. - /// @{ - void addMetadata(unsigned KindID, MDNode &MD); - void addMetadata(StringRef Kind, MDNode &MD); - /// @} - - /// Appends all attachments for the global to \c MDs, sorting by attachment - /// ID. Attachments with the same ID appear in insertion order. - void - getAllMetadata(SmallVectorImpl> &MDs) const; - - /// Erase all metadata attachments with the given kind. - /// - /// \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); @@ -174,8 +120,6 @@ V->getValueID() == Value::GlobalVariableVal; } - void clearMetadata(); - private: void setGlobalObjectFlag(unsigned Bit, bool Val) { unsigned Mask = 1 << Bit; @@ -183,13 +127,6 @@ (Val ? Mask : 0u)); } - bool hasMetadataHashEntry() const { - return getGlobalValueSubClassData() & (1 << HasMetadataHashEntryBit); - } - void setHasMetadataHashEntry(bool HasEntry) { - setGlobalObjectFlag(HasMetadataHashEntryBit, HasEntry); - } - StringRef getSectionImpl() const; }; diff --git a/llvm/include/llvm/IR/Instruction.h b/llvm/include/llvm/IR/Instruction.h --- a/llvm/include/llvm/IR/Instruction.h +++ b/llvm/include/llvm/IR/Instruction.h @@ -45,12 +45,6 @@ BasicBlock *Parent; DebugLoc DbgLoc; // 'dbg' Metadata cache. - enum { - /// This is a bit stored in the SubClassData field which indicates whether - /// this instruction has metadata attached to it or not. - HasMetadataBit = 1 << 15 - }; - protected: ~Instruction(); // Use deleteValue() to delete a generic Instruction. @@ -221,12 +215,12 @@ //===--------------------------------------------------------------------===// /// Return true if this instruction has any metadata attached to it. - bool hasMetadata() const { return DbgLoc || hasMetadataHashEntry(); } + bool hasMetadata() const { return DbgLoc || Value::hasMetadata(); } /// Return true if this instruction has metadata attached to it other than a /// debug location. bool hasMetadataOtherThanDebugLoc() const { - return hasMetadataHashEntry(); + return Value::hasMetadata(); } /// Return true if this instruction has the given type of metadata attached. @@ -266,8 +260,7 @@ /// debug location. void getAllMetadataOtherThanDebugLoc( SmallVectorImpl> &MDs) const { - if (hasMetadataOtherThanDebugLoc()) - getAllMetadataOtherThanDebugLocImpl(MDs); + Value::getAllMetadata(MDs); } /// Fills the AAMDNodes structure with AA metadata from this instruction. @@ -456,20 +449,11 @@ void applyMergedLocation(const DILocation *LocA, const DILocation *LocB); private: - /// Return true if we have an entry in the on-the-side metadata hash. - bool hasMetadataHashEntry() const { - return (getSubclassDataFromValue() & HasMetadataBit) != 0; - } - // These are all implemented in Metadata.cpp. MDNode *getMetadataImpl(unsigned KindID) const; MDNode *getMetadataImpl(StringRef Kind) const; void getAllMetadataImpl(SmallVectorImpl> &) const; - void getAllMetadataOtherThanDebugLocImpl( - SmallVectorImpl> &) const; - /// Clear all hashtable-based metadata from this instruction. - void clearMetadataHashEntries(); public: //===--------------------------------------------------------------------===// @@ -749,25 +733,15 @@ return Value::getSubclassDataFromValue(); } - void setHasMetadataHashEntry(bool V) { - setValueSubclassData((getSubclassDataFromValue() & ~HasMetadataBit) | - (V ? HasMetadataBit : 0)); - } - void setParent(BasicBlock *P); protected: - // Instruction subclasses can stick up to 15 bits of stuff into the - // SubclassData field of instruction with these members. - - // Verify that only the low 15 bits are used. void setInstructionSubclassData(unsigned short D) { - assert((D & HasMetadataBit) == 0 && "Out of range value put into field"); - setValueSubclassData((getSubclassDataFromValue() & HasMetadataBit) | D); + setValueSubclassData(D); } unsigned getSubclassDataFromInstruction() const { - return getSubclassDataFromValue() & ~HasMetadataBit; + return getSubclassDataFromValue(); } Instruction(Type *Ty, unsigned iType, Use *Ops, unsigned NumOps, diff --git a/llvm/include/llvm/IR/Value.h b/llvm/include/llvm/IR/Value.h --- a/llvm/include/llvm/IR/Value.h +++ b/llvm/include/llvm/IR/Value.h @@ -15,6 +15,7 @@ #include "llvm-c/Types.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringRef.h" #include "llvm/ADT/iterator_range.h" #include "llvm/IR/Use.h" #include "llvm/Support/CBindingWrapping.h" @@ -42,11 +43,11 @@ class InlineAsm; class Instruction; class LLVMContext; +class MDNode; class Module; class ModuleSlotTracker; class raw_ostream; template class StringMapEntry; -class StringRef; class Twine; class Type; class User; @@ -111,12 +112,13 @@ /// /// Note, this should *NOT* be used directly by any class other than User. /// User uses this value to find the Use list. - enum : unsigned { NumUserOperandsBits = 28 }; + enum : unsigned { NumUserOperandsBits = 27 }; unsigned NumUserOperands : NumUserOperandsBits; // Use the same type as the bitfield above so that MSVC will pack them. unsigned IsUsedByMD : 1; unsigned HasName : 1; + unsigned HasMetadata : 1; // Has metadata attached to this? unsigned HasHungOffUses : 1; unsigned HasDescriptor : 1; @@ -507,6 +509,66 @@ /// Return true if there is metadata referencing this value. bool isUsedByMetadata() const { return IsUsedByMD; } + /// Get the current metadata attachments for the given kind, if any. + /// + /// These functions require that the value have at most a single attachment + /// of the given kind, and return \c nullptr if such an attachment is missing. + /// @{ + MDNode *getMetadata(unsigned KindID) const; + MDNode *getMetadata(StringRef Kind) const; + /// @} + + /// Appends all attachments with the given ID to \c MDs in insertion order. + /// If the Value has no attachments with the given ID, or if ID is invalid, + /// leaves MDs unchanged. + /// @{ + void getMetadata(unsigned KindID, SmallVectorImpl &MDs) const; + void getMetadata(StringRef Kind, SmallVectorImpl &MDs) const; + /// @} + + /// Appends all metadata attached to this value to \c MDs, sorting by + /// KindID. The first element of each pair returned is the KindID, the second + /// element is the metadata value. Attachments with the same ID appear in + /// insertion order. + void + getAllMetadata(SmallVectorImpl> &MDs) const; + + /// Return true if this value has any metadata attached to it. + bool hasMetadata() const { return (bool)HasMetadata; } + + /// Return true if this value has the given type of metadata attached. + /// @{ + bool hasMetadata(unsigned KindID) const { + return getMetadata(KindID) != nullptr; + } + bool hasMetadata(StringRef Kind) const { + return getMetadata(Kind) != nullptr; + } + /// @} + + /// Set a particular kind of metadata attachment. + /// + /// Sets the given attachment to \c MD, erasing it if \c MD is \c nullptr or + /// replacing it if it already exists. + /// @{ + void setMetadata(unsigned KindID, MDNode *Node); + void setMetadata(StringRef Kind, MDNode *Node); + /// @} + + /// Add a metadata attachment. + /// @{ + void addMetadata(unsigned KindID, MDNode &MD); + void addMetadata(StringRef Kind, MDNode &MD); + /// @} + + /// Erase all metadata attachments with the given kind. + /// + /// \returns true if any metadata was removed. + bool eraseMetadata(unsigned KindID); + + /// Erase all metadata attached to this Value. + void clearMetadata(); + /// Return true if this value is a swifterror value. /// /// swifterror values can be either a function argument or an alloca with a diff --git a/llvm/lib/IR/Core.cpp b/llvm/lib/IR/Core.cpp --- a/llvm/lib/IR/Core.cpp +++ b/llvm/lib/IR/Core.cpp @@ -916,6 +916,7 @@ LLVMInstructionGetAllMetadataOtherThanDebugLoc(LLVMValueRef Value, size_t *NumEntries) { return llvm_getMetadata(NumEntries, [&Value](MetadataEntries &Entries) { + Entries.clear(); unwrap(Value)->getAllMetadata(Entries); }); } @@ -2023,6 +2024,7 @@ LLVMValueMetadataEntry *LLVMGlobalCopyAllMetadata(LLVMValueRef Value, size_t *NumEntries) { return llvm_getMetadata(NumEntries, [&Value](MetadataEntries &Entries) { + Entries.clear(); if (Instruction *Instr = dyn_cast(unwrap(Value))) { Instr->getAllMetadata(Entries); } else { diff --git a/llvm/lib/IR/Instruction.cpp b/llvm/lib/IR/Instruction.cpp --- a/llvm/lib/IR/Instruction.cpp +++ b/llvm/lib/IR/Instruction.cpp @@ -43,8 +43,6 @@ Instruction::~Instruction() { assert(!Parent && "Instruction still linked in the program!"); - if (hasMetadataHashEntry()) - clearMetadataHashEntries(); } diff --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h --- a/llvm/lib/IR/LLVMContextImpl.h +++ b/llvm/lib/IR/LLVMContextImpl.h @@ -1171,74 +1171,59 @@ #define HANDLE_MDNODE_LEAF(CLASS) using CLASS##Info = MDNodeInfo; #include "llvm/IR/Metadata.def" -/// Map-like storage for metadata attachments. -class MDAttachmentMap { - SmallVector, 2> Attachments; +/// Multimap-like storage for metadata attachments. +class MDAttachments { +public: + struct Attachment { + unsigned MDKind; + TrackingMDNodeRef Node; + }; + +private: + SmallVector Attachments; public: bool empty() const { return Attachments.empty(); } size_t size() const { return Attachments.size(); } - /// Get a particular attachment (if any). + /// Returns the first attachment with the given ID or nullptr if no such + /// attachment exists. MDNode *lookup(unsigned ID) const; + /// 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 &Result) const; + + /// Appends all attachments for the global to \c Result, sorting by attachment + /// ID. Attachments with the same ID appear in insertion order. This function + /// does \em not clear \c Result. + void getAll(SmallVectorImpl> &Result) const; + /// Set an attachment to a particular node. /// - /// Set the \c ID attachment to \c MD, replacing the current attachment at \c + /// Set the \c ID attachment to \c MD, replacing the current attachments at \c /// ID (if anyway). - void set(unsigned ID, MDNode &MD); + void set(unsigned ID, MDNode *MD); - /// Remove an attachment. - /// - /// Remove the attachment at \c ID, if any. - bool erase(unsigned ID); + /// Adds an attachment to a particular node. + void insert(unsigned ID, MDNode &MD); - /// Copy out all the attachments. + /// Remove attachments with the given ID. /// - /// Copies all the current attachments into \c Result, sorting by attachment - /// ID. This function does \em not clear \c Result. - void getAll(SmallVectorImpl> &Result) const; + /// Remove the attachments at \c ID, if any. + bool erase(unsigned ID); /// Erase matching attachments. /// /// Erases all attachments matching the \c shouldRemove predicate. - template void remove_if(PredTy shouldRemove) { + template + void remove_if(PredTy shouldRemove) { Attachments.erase(llvm::remove_if(Attachments, shouldRemove), Attachments.end()); } }; -/// Multimap-like storage for metadata attachments for globals. This differs -/// from MDAttachmentMap in that it allows multiple attachments per metadata -/// kind. -class MDGlobalAttachmentMap { - struct Attachment { - unsigned MDKind; - TrackingMDNodeRef Node; - }; - SmallVector Attachments; - -public: - bool empty() const { return Attachments.empty(); } - - /// 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 &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); - 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 - /// does \em not clear \c Result. - void getAll(SmallVectorImpl> &Result) const; -}; - class LLVMContextImpl { public: /// OwnedModules - The set of modules instantiated in this context, and which @@ -1347,11 +1332,8 @@ /// CustomMDKindNames - Map to hold the metadata string to ID mapping. StringMap CustomMDKindNames; - /// Collection of per-instruction metadata used in this context. - DenseMap InstructionMetadata; - - /// Collection of per-GlobalObject metadata used in this context. - DenseMap GlobalObjectMetadata; + /// Collection of metadata used in this context. + DenseMap ValueMetadata; /// Collection of per-GlobalObject sections used in this context. DenseMap GlobalObjectSections; diff --git a/llvm/lib/IR/LLVMContextImpl.cpp b/llvm/lib/IR/LLVMContextImpl.cpp --- a/llvm/lib/IR/LLVMContextImpl.cpp +++ b/llvm/lib/IR/LLVMContextImpl.cpp @@ -48,11 +48,11 @@ delete *OwnedModules.begin(); #ifndef NDEBUG - // Check for metadata references from leaked Instructions. - for (auto &Pair : InstructionMetadata) + // Check for metadata references from leaked Values. + for (auto &Pair : ValueMetadata) Pair.first->dump(); - assert(InstructionMetadata.empty() && - "Instructions with metadata have been leaked"); + assert(ValueMetadata.empty() && + "Values with metadata have been leaked"); #endif // Drop references for MDNodes. Do this before Values get deleted to avoid diff --git a/llvm/lib/IR/Metadata.cpp b/llvm/lib/IR/Metadata.cpp --- a/llvm/lib/IR/Metadata.cpp +++ b/llvm/lib/IR/Metadata.cpp @@ -1099,89 +1099,164 @@ //===----------------------------------------------------------------------===// // Instruction Metadata method implementations. // -void MDAttachmentMap::set(unsigned ID, MDNode &MD) { - for (auto &I : Attachments) - if (I.first == ID) { - I.second.reset(&MD); - return; - } - Attachments.emplace_back(std::piecewise_construct, std::make_tuple(ID), - std::make_tuple(&MD)); + +MDNode *MDAttachments::lookup(unsigned ID) const { + for (const auto &A : Attachments) + if (A.MDKind == ID) + return A.Node; + return nullptr; +} + +void MDAttachments::get(unsigned ID, SmallVectorImpl &Result) const { + for (const auto &A : Attachments) + if (A.MDKind == ID) + Result.push_back(A.Node); } -bool MDAttachmentMap::erase(unsigned ID) { +void MDAttachments::getAll( + SmallVectorImpl> &Result) const { + 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 + // need to preserve the original insertion order though. + if (Result.size() > 1) + llvm::stable_sort(Result, less_first()); +} + +void MDAttachments::set(unsigned ID, MDNode *MD) { + erase(ID); + if (MD) + insert(ID, *MD); +} + +void MDAttachments::insert(unsigned ID, MDNode &MD) { + Attachments.push_back({ID, TrackingMDNodeRef(&MD)}); +} + +bool MDAttachments::erase(unsigned ID) { if (empty()) return false; - // Common case is one/last value. - if (Attachments.back().first == ID) { + // Common case is one value. + if (Attachments.size() == 1 && Attachments.back().MDKind == ID) { Attachments.pop_back(); return true; } - for (auto I = Attachments.begin(), E = std::prev(Attachments.end()); I != E; - ++I) - if (I->first == ID) { - *I = std::move(Attachments.back()); - Attachments.pop_back(); - return true; - } + 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; +} - return false; + +MDNode *Value::getMetadata(unsigned KindID) const { + if (!hasMetadata()) + return nullptr; + const auto &Info = getContext().pImpl->ValueMetadata[this]; + assert(!Info.empty() && "bit out of sync with hash table"); + return Info.lookup(KindID); } -MDNode *MDAttachmentMap::lookup(unsigned ID) const { - for (const auto &I : Attachments) - if (I.first == ID) - return I.second; - return nullptr; +MDNode *Value::getMetadata(StringRef Kind) const { + if (!hasMetadata()) + return nullptr; + const auto &Info = getContext().pImpl->ValueMetadata[this]; + assert(!Info.empty() && "bit out of sync with hash table"); + return Info.lookup(getContext().getMDKindID(Kind)); } -void MDAttachmentMap::getAll( - SmallVectorImpl> &Result) const { - Result.append(Attachments.begin(), Attachments.end()); +void Value::getMetadata(unsigned KindID, SmallVectorImpl &MDs) const { + if (hasMetadata()) + getContext().pImpl->ValueMetadata[this].get(KindID, MDs); +} - // Sort the resulting array so it is stable. - if (Result.size() > 1) - array_pod_sort(Result.begin(), Result.end()); +void Value::getMetadata(StringRef Kind, SmallVectorImpl &MDs) const { + if (hasMetadata()) + getMetadata(getContext().getMDKindID(Kind), MDs); } -void MDGlobalAttachmentMap::insert(unsigned ID, MDNode &MD) { - Attachments.push_back({ID, TrackingMDNodeRef(&MD)}); +void Value::getAllMetadata( + SmallVectorImpl> &MDs) const { + if (hasMetadata()) { + assert(getContext().pImpl->ValueMetadata.count(this) && + "bit out of sync with hash table"); + const auto &Info = getContext().pImpl->ValueMetadata.find(this)->second; + assert(!Info.empty() && "Shouldn't have called this"); + Info.getAll(MDs); + } } -MDNode *MDGlobalAttachmentMap::lookup(unsigned ID) const { - for (const auto &A : Attachments) - if (A.MDKind == ID) - return A.Node; - return nullptr; +void Value::setMetadata(unsigned KindID, MDNode *Node) { + assert(isa(this) || isa(this)); + + // Handle the case when we're adding/updating metadata on a value. + if (Node) { + auto &Info = getContext().pImpl->ValueMetadata[this]; + assert(!Info.empty() == HasMetadata && "bit out of sync with hash table"); + if (Info.empty()) + HasMetadata = true; + Info.set(KindID, Node); + return; + } + + // Otherwise, we're removing metadata from an instruction. + assert((HasMetadata == + (getContext().pImpl->ValueMetadata.count(this) > 0)) && + "bit out of sync with hash table"); + if (!HasMetadata) + return; // Nothing to remove! + auto &Info = getContext().pImpl->ValueMetadata[this]; + + // Handle removal of an existing value. + Info.erase(KindID); + if (!Info.empty()) + return; + getContext().pImpl->ValueMetadata.erase(this); + HasMetadata = false; } -void MDGlobalAttachmentMap::get(unsigned ID, - SmallVectorImpl &Result) const { - for (const auto &A : Attachments) - if (A.MDKind == ID) - Result.push_back(A.Node); +void Value::setMetadata(StringRef Kind, MDNode *Node) { + if (!Node && !HasMetadata) + return; + setMetadata(getContext().getMDKindID(Kind), Node); } -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 Value::addMetadata(unsigned KindID, MDNode &MD) { + assert(isa(this) || isa(this)); + if (!HasMetadata) + HasMetadata = true; + getContext().pImpl->ValueMetadata[this].insert(KindID, MD); } -void MDGlobalAttachmentMap::getAll( - SmallVectorImpl> &Result) const { - for (const auto &A : Attachments) - Result.emplace_back(A.MDKind, A.Node); +void Value::addMetadata(StringRef Kind, MDNode &MD) { + addMetadata(getContext().getMDKindID(Kind), MD); +} - // Sort the resulting array so it is stable with respect to metadata IDs. We - // need to preserve the original insertion order though. - llvm::stable_sort(Result, less_first()); +bool Value::eraseMetadata(unsigned KindID) { + // Nothing to unset. + if (!HasMetadata) + return false; + + auto &Store = getContext().pImpl->ValueMetadata[this]; + bool Changed = Store.erase(KindID); + if (Store.empty()) + clearMetadata(); + return Changed; +} + +void Value::clearMetadata() { + if (!HasMetadata) + return; + assert(getContext().pImpl->ValueMetadata.count(this) && + "bit out of sync with hash table"); + getContext().pImpl->ValueMetadata.erase(this); + HasMetadata = false; } + void Instruction::setMetadata(StringRef Kind, MDNode *Node) { if (!Node && !hasMetadata()) return; @@ -1193,29 +1268,28 @@ } void Instruction::dropUnknownNonDebugMetadata(ArrayRef KnownIDs) { - if (!hasMetadataHashEntry()) + if (!Value::hasMetadata()) return; // Nothing to remove! - auto &InstructionMetadata = getContext().pImpl->InstructionMetadata; - - SmallSet KnownSet; - KnownSet.insert(KnownIDs.begin(), KnownIDs.end()); - if (KnownSet.empty()) { + if (KnownIDs.empty()) { // Just drop our entry at the store. - InstructionMetadata.erase(this); - setHasMetadataHashEntry(false); + clearMetadata(); return; } - auto &Info = InstructionMetadata[this]; - Info.remove_if([&KnownSet](const std::pair &I) { - return !KnownSet.count(I.first); + SmallSet KnownSet; + KnownSet.insert(KnownIDs.begin(), KnownIDs.end()); + + auto &MetadataStore = getContext().pImpl->ValueMetadata; + auto &Info = MetadataStore[this]; + assert(!Info.empty() && "bit out of sync with hash table"); + Info.remove_if([&KnownSet](const MDAttachments::Attachment &I) { + return !KnownSet.count(I.MDKind); }); if (Info.empty()) { // Drop our entry at the store. - InstructionMetadata.erase(this); - setHasMetadataHashEntry(false); + clearMetadata(); } } @@ -1229,33 +1303,7 @@ return; } - // Handle the case when we're adding/updating metadata on an instruction. - if (Node) { - auto &Info = getContext().pImpl->InstructionMetadata[this]; - assert(!Info.empty() == hasMetadataHashEntry() && - "HasMetadata bit is wonked"); - if (Info.empty()) - setHasMetadataHashEntry(true); - Info.set(KindID, *Node); - return; - } - - // Otherwise, we're removing metadata from an instruction. - assert((hasMetadataHashEntry() == - (getContext().pImpl->InstructionMetadata.count(this) > 0)) && - "HasMetadata bit out of date!"); - if (!hasMetadataHashEntry()) - return; // Nothing to remove! - auto &Info = getContext().pImpl->InstructionMetadata[this]; - - // Handle removal of an existing value. - Info.erase(KindID); - - if (!Info.empty()) - return; - - getContext().pImpl->InstructionMetadata.erase(this); - setHasMetadataHashEntry(false); + Value::setMetadata(KindID, Node); } void Instruction::setAAMetadata(const AAMDNodes &N) { @@ -1268,13 +1316,7 @@ // Handle 'dbg' as a special case since it is not stored in the hash table. if (KindID == LLVMContext::MD_dbg) return DbgLoc.getAsMDNode(); - - if (!hasMetadataHashEntry()) - return nullptr; - auto &Info = getContext().pImpl->InstructionMetadata[this]; - assert(!Info.empty() && "bit out of sync with hash table"); - - return Info.lookup(KindID); + return Value::getMetadata(KindID); } void Instruction::getAllMetadataImpl( @@ -1285,27 +1327,8 @@ if (DbgLoc) { Result.push_back( std::make_pair((unsigned)LLVMContext::MD_dbg, DbgLoc.getAsMDNode())); - if (!hasMetadataHashEntry()) - return; } - - assert(hasMetadataHashEntry() && - getContext().pImpl->InstructionMetadata.count(this) && - "Shouldn't have called this"); - const auto &Info = getContext().pImpl->InstructionMetadata.find(this)->second; - assert(!Info.empty() && "Shouldn't have called this"); - Info.getAll(Result); -} - -void Instruction::getAllMetadataOtherThanDebugLocImpl( - SmallVectorImpl> &Result) const { - Result.clear(); - assert(hasMetadataHashEntry() && - getContext().pImpl->InstructionMetadata.count(this) && - "Shouldn't have called this"); - const auto &Info = getContext().pImpl->InstructionMetadata.find(this)->second; - assert(!Info.empty() && "Shouldn't have called this"); - Info.getAll(Result); + Value::getAllMetadata(Result); } bool Instruction::extractProfMetadata(uint64_t &TrueVal, @@ -1369,84 +1392,6 @@ return false; } -void Instruction::clearMetadataHashEntries() { - assert(hasMetadataHashEntry() && "Caller should check"); - getContext().pImpl->InstructionMetadata.erase(this); - setHasMetadataHashEntry(false); -} - -void GlobalObject::getMetadata(unsigned KindID, - SmallVectorImpl &MDs) const { - if (hasMetadata()) - getContext().pImpl->GlobalObjectMetadata[this].get(KindID, MDs); -} - -void GlobalObject::getMetadata(StringRef Kind, - SmallVectorImpl &MDs) const { - if (hasMetadata()) - getMetadata(getContext().getMDKindID(Kind), MDs); -} - -void GlobalObject::addMetadata(unsigned KindID, MDNode &MD) { - if (!hasMetadata()) - setHasMetadataHashEntry(true); - - getContext().pImpl->GlobalObjectMetadata[this].insert(KindID, MD); -} - -void GlobalObject::addMetadata(StringRef Kind, MDNode &MD) { - addMetadata(getContext().getMDKindID(Kind), MD); -} - -bool GlobalObject::eraseMetadata(unsigned KindID) { - // Nothing to unset. - if (!hasMetadata()) - return false; - - auto &Store = getContext().pImpl->GlobalObjectMetadata[this]; - bool Changed = Store.erase(KindID); - if (Store.empty()) - clearMetadata(); - return Changed; -} - -void GlobalObject::getAllMetadata( - SmallVectorImpl> &MDs) const { - MDs.clear(); - - if (!hasMetadata()) - return; - - getContext().pImpl->GlobalObjectMetadata[this].getAll(MDs); -} - -void GlobalObject::clearMetadata() { - if (!hasMetadata()) - return; - getContext().pImpl->GlobalObjectMetadata.erase(this); - setHasMetadataHashEntry(false); -} - -void GlobalObject::setMetadata(unsigned KindID, MDNode *N) { - eraseMetadata(KindID); - if (N) - addMetadata(KindID, *N); -} - -void GlobalObject::setMetadata(StringRef Kind, MDNode *N) { - setMetadata(getContext().getMDKindID(Kind), N); -} - -MDNode *GlobalObject::getMetadata(unsigned KindID) const { - if (hasMetadata()) - return getContext().pImpl->GlobalObjectMetadata[this].lookup(KindID); - return nullptr; -} - -MDNode *GlobalObject::getMetadata(StringRef Kind) const { - return getMetadata(getContext().getMDKindID(Kind)); -} - void GlobalObject::copyMetadata(const GlobalObject *Other, unsigned Offset) { SmallVector, 8> MDs; Other->getAllMetadata(MDs); diff --git a/llvm/lib/IR/Value.cpp b/llvm/lib/IR/Value.cpp --- a/llvm/lib/IR/Value.cpp +++ b/llvm/lib/IR/Value.cpp @@ -52,7 +52,8 @@ Value::Value(Type *ty, unsigned scid) : VTy(checkType(ty)), UseList(nullptr), SubclassID(scid), HasValueHandle(0), SubclassOptionalData(0), SubclassData(0), - NumUserOperands(0), IsUsedByMD(false), HasName(false) { + NumUserOperands(0), IsUsedByMD(false), HasName(false), + HasMetadata(false) { static_assert(ConstantFirstVal == 0, "!(SubclassID < ConstantFirstVal)"); // FIXME: Why isn't this in the subclass gunk?? // Note, we cannot call isa before the CallInst has been @@ -76,6 +77,10 @@ if (isUsedByMetadata()) ValueAsMetadata::handleDeletion(this); + // Remove associated metadata from context. + if (HasMetadata) + clearMetadata(); + #ifndef NDEBUG // Only in -g mode... // Check to make sure that there are no uses of this value that are still // around when the value is destroyed. If there are, then we have a dangling