1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-18 18:42:46 +02:00

[IR] Merge metadata manipulation code into Value

Now there are two main classes in Value hierarchy, which support metadata,
these are Instruction and GlobalObject. They implement different APIs for
metadata manipulation, which however overlap. This change moves metadata
manipulation code into Value, so descendant classes can use this code for
their operations on metadata.

No functional changes intended.

Differential Revision: https://reviews.llvm.org/D67626
This commit is contained in:
Serge Pavlov 2019-09-14 00:21:24 +07:00
parent f4f0edfc5e
commit e062f1d0ad
9 changed files with 267 additions and 347 deletions

View File

@ -54,7 +54,6 @@ protected:
Comdat *ObjComdat;
enum {
LastAlignmentBit = 4,
HasMetadataHashEntryBit,
HasSectionHashEntryBit,
GlobalObjectBits,
@ -127,58 +126,13 @@ public:
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<MDNode *> &MDs) const;
void getMetadata(StringRef Kind, SmallVectorImpl<MDNode *> &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<std::pair<unsigned, MDNode *>> &MDs) const;
/// Erase all metadata attachments with the given kind.
///
/// \returns true if any metadata was removed.
bool eraseMetadata(unsigned KindID);
using Value::addMetadata;
using Value::clearMetadata;
using Value::eraseMetadata;
using Value::getAllMetadata;
using Value::getMetadata;
using Value::hasMetadata;
using Value::setMetadata;
/// Copy metadata from Src, adjusting offsets by Offset.
void copyMetadata(const GlobalObject *Src, unsigned Offset);
@ -204,8 +158,6 @@ public:
V->getValueID() == Value::GlobalVariableVal;
}
void clearMetadata();
private:
void setGlobalObjectFlag(unsigned Bit, bool Val) {
unsigned Mask = 1 << Bit;
@ -213,13 +165,6 @@ private:
(Val ? Mask : 0u));
}
bool hasMetadataHashEntry() const {
return getGlobalValueSubClassData() & (1 << HasMetadataHashEntryBit);
}
void setHasMetadataHashEntry(bool HasEntry) {
setGlobalObjectFlag(HasMetadataHashEntryBit, HasEntry);
}
StringRef getSectionImpl() const;
};

View File

@ -256,13 +256,11 @@ public:
//===--------------------------------------------------------------------===//
/// 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();
}
bool hasMetadataOtherThanDebugLoc() const { return Value::hasMetadata(); }
/// Return true if this instruction has the given type of metadata attached.
bool hasMetadata(unsigned KindID) const {
@ -301,8 +299,7 @@ public:
/// debug location.
void getAllMetadataOtherThanDebugLoc(
SmallVectorImpl<std::pair<unsigned, MDNode *>> &MDs) const {
if (hasMetadataOtherThanDebugLoc())
getAllMetadataOtherThanDebugLocImpl(MDs);
Value::getAllMetadata(MDs);
}
/// Fills the AAMDNodes structure with AA metadata from this instruction.
@ -507,20 +504,11 @@ public:
void dropLocation();
private:
/// Return true if we have an entry in the on-the-side metadata hash.
bool hasMetadataHashEntry() const {
return Bitfield::test<HasMetadataField>(getSubclassDataFromValue());
}
// These are all implemented in Metadata.cpp.
MDNode *getMetadataImpl(unsigned KindID) const;
MDNode *getMetadataImpl(StringRef Kind) const;
void
getAllMetadataImpl(SmallVectorImpl<std::pair<unsigned, MDNode *>> &) const;
void getAllMetadataOtherThanDebugLocImpl(
SmallVectorImpl<std::pair<unsigned, MDNode *>> &) const;
/// Clear all hashtable-based metadata from this instruction.
void clearMetadataHashEntries();
public:
//===--------------------------------------------------------------------===//
@ -801,8 +789,6 @@ private:
return Value::getSubclassDataFromValue();
}
void setHasMetadataHashEntry(bool V) { setSubclassData<HasMetadataField>(V); }
void setParent(BasicBlock *P);
protected:

View File

@ -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/Alignment.h"
@ -43,11 +44,11 @@ class GlobalVariable;
class InlineAsm;
class Instruction;
class LLVMContext;
class MDNode;
class Module;
class ModuleSlotTracker;
class raw_ostream;
template<typename ValueTy> class StringMapEntry;
class StringRef;
class Twine;
class Type;
class User;
@ -110,12 +111,13 @@ protected:
///
/// 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;
@ -550,6 +552,68 @@ public:
/// Return true if there is metadata referencing this value.
bool isUsedByMetadata() const { return IsUsedByMD; }
protected:
/// 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<MDNode *> &MDs) const;
void getMetadata(StringRef Kind, SmallVectorImpl<MDNode *> &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<std::pair<unsigned, MDNode *>> &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();
public:
/// Return true if this value is a swifterror value.
///
/// swifterror values can be either a function argument or an alloca with a

View File

@ -930,6 +930,7 @@ LLVMValueMetadataEntry *
LLVMInstructionGetAllMetadataOtherThanDebugLoc(LLVMValueRef Value,
size_t *NumEntries) {
return llvm_getMetadata(NumEntries, [&Value](MetadataEntries &Entries) {
Entries.clear();
unwrap<Instruction>(Value)->getAllMetadata(Entries);
});
}
@ -2039,6 +2040,7 @@ void LLVMSetAlignment(LLVMValueRef V, unsigned Bytes) {
LLVMValueMetadataEntry *LLVMGlobalCopyAllMetadata(LLVMValueRef Value,
size_t *NumEntries) {
return llvm_getMetadata(NumEntries, [&Value](MetadataEntries &Entries) {
Entries.clear();
if (Instruction *Instr = dyn_cast<Instruction>(unwrap(Value))) {
Instr->getAllMetadata(Entries);
} else {

View File

@ -55,9 +55,6 @@ Instruction::~Instruction() {
// instructions in a BasicBlock are deleted).
if (isUsedByMetadata())
ValueAsMetadata::handleRAUW(this, UndefValue::get(getType()));
if (hasMetadataHashEntry())
clearMetadataHashEntries();
}

View File

@ -50,11 +50,10 @@ LLVMContextImpl::~LLVMContextImpl() {
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

View File

@ -1224,34 +1224,49 @@ template <class NodeTy> struct MDNodeInfo {
#define HANDLE_MDNODE_LEAF(CLASS) using CLASS##Info = MDNodeInfo<CLASS>;
#include "llvm/IR/Metadata.def"
/// Map-like storage for metadata attachments.
class MDAttachmentMap {
SmallVector<std::pair<unsigned, TrackingMDNodeRef>, 2> Attachments;
/// Multimap-like storage for metadata attachments.
class MDAttachments {
public:
struct Attachment {
unsigned MDKind;
TrackingMDNodeRef Node;
};
private:
SmallVector<Attachment, 1> 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<MDNode *> &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<std::pair<unsigned, MDNode *>> &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.
/// Adds an attachment to a particular node.
void insert(unsigned ID, MDNode &MD);
/// Remove attachments with the given ID.
///
/// Remove the attachment at \c ID, if any.
/// Remove the attachments at \c ID, if any.
bool erase(unsigned ID);
/// Copy out all the attachments.
///
/// Copies all the current attachments into \c Result, sorting by attachment
/// ID. This function does \em not clear \c Result.
void getAll(SmallVectorImpl<std::pair<unsigned, MDNode *>> &Result) const;
/// Erase matching attachments.
///
/// Erases all attachments matching the \c shouldRemove predicate.
@ -1261,37 +1276,6 @@ public:
}
};
/// 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<Attachment, 1> 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<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);
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<std::pair<unsigned, MDNode *>> &Result) const;
};
class LLVMContextImpl {
public:
/// OwnedModules - The set of modules instantiated in this context, and which
@ -1407,11 +1391,8 @@ public:
/// CustomMDKindNames - Map to hold the metadata string to ID mapping.
StringMap<unsigned> CustomMDKindNames;
/// Collection of per-instruction metadata used in this context.
DenseMap<const Instruction *, MDAttachmentMap> InstructionMetadata;
/// Collection of per-GlobalObject metadata used in this context.
DenseMap<const GlobalObject *, MDGlobalAttachmentMap> GlobalObjectMetadata;
/// Collection of metadata used in this context.
DenseMap<const Value *, MDAttachments> ValueMetadata;
/// Collection of per-GlobalObject sections used in this context.
DenseMap<const GlobalObject *, StringRef> GlobalObjectSections;

View File

@ -1101,72 +1101,51 @@ StringRef NamedMDNode::getName() const { return StringRef(Name); }
//===----------------------------------------------------------------------===//
// 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));
}
bool MDAttachmentMap::erase(unsigned ID) {
if (empty())
return false;
// Common case is one/last value.
if (Attachments.back().first == 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;
}
return false;
}
MDNode *MDAttachmentMap::lookup(unsigned ID) const {
for (const auto &I : Attachments)
if (I.first == ID)
return I.second;
return nullptr;
}
void MDAttachmentMap::getAll(
SmallVectorImpl<std::pair<unsigned, MDNode *>> &Result) const {
Result.append(Attachments.begin(), Attachments.end());
// Sort the resulting array so it is stable.
if (Result.size() > 1)
array_pod_sort(Result.begin(), Result.end());
}
void MDGlobalAttachmentMap::insert(unsigned ID, MDNode &MD) {
Attachments.push_back({ID, TrackingMDNodeRef(&MD)});
}
MDNode *MDGlobalAttachmentMap::lookup(unsigned ID) const {
MDNode *MDAttachments::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) const {
void MDAttachments::get(unsigned ID, SmallVectorImpl<MDNode *> &Result) const {
for (const auto &A : Attachments)
if (A.MDKind == ID)
Result.push_back(A.Node);
}
bool MDGlobalAttachmentMap::erase(unsigned ID) {
void MDAttachments::getAll(
SmallVectorImpl<std::pair<unsigned, MDNode *>> &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 value.
if (Attachments.size() == 1 && Attachments.back().MDKind == ID) {
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();
@ -1174,14 +1153,107 @@ bool MDGlobalAttachmentMap::erase(unsigned ID) {
return Changed;
}
void MDGlobalAttachmentMap::getAll(
SmallVectorImpl<std::pair<unsigned, MDNode *>> &Result) const {
for (const auto &A : Attachments)
Result.emplace_back(A.MDKind, A.Node);
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);
}
// 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());
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 Value::getMetadata(unsigned KindID, SmallVectorImpl<MDNode *> &MDs) const {
if (hasMetadata())
getContext().pImpl->ValueMetadata[this].get(KindID, MDs);
}
void Value::getMetadata(StringRef Kind, SmallVectorImpl<MDNode *> &MDs) const {
if (hasMetadata())
getMetadata(getContext().getMDKindID(Kind), MDs);
}
void Value::getAllMetadata(
SmallVectorImpl<std::pair<unsigned, MDNode *>> &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);
}
}
void Value::setMetadata(unsigned KindID, MDNode *Node) {
assert(isa<Instruction>(this) || isa<GlobalObject>(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 Value::setMetadata(StringRef Kind, MDNode *Node) {
if (!Node && !HasMetadata)
return;
setMetadata(getContext().getMDKindID(Kind), Node);
}
void Value::addMetadata(unsigned KindID, MDNode &MD) {
assert(isa<Instruction>(this) || isa<GlobalObject>(this));
if (!HasMetadata)
HasMetadata = true;
getContext().pImpl->ValueMetadata[this].insert(KindID, MD);
}
void Value::addMetadata(StringRef Kind, MDNode &MD) {
addMetadata(getContext().getMDKindID(Kind), MD);
}
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) {
@ -1195,29 +1267,28 @@ MDNode *Instruction::getMetadataImpl(StringRef Kind) const {
}
void Instruction::dropUnknownNonDebugMetadata(ArrayRef<unsigned> KnownIDs) {
if (!hasMetadataHashEntry())
if (!Value::hasMetadata())
return; // Nothing to remove!
auto &InstructionMetadata = getContext().pImpl->InstructionMetadata;
SmallSet<unsigned, 4> 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<unsigned, TrackingMDNodeRef> &I) {
return !KnownSet.count(I.first);
SmallSet<unsigned, 4> 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();
}
}
@ -1231,33 +1302,7 @@ void Instruction::setMetadata(unsigned KindID, MDNode *Node) {
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) {
@ -1271,13 +1316,7 @@ MDNode *Instruction::getMetadataImpl(unsigned KindID) const {
// 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(
@ -1288,27 +1327,8 @@ void Instruction::getAllMetadataImpl(
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<std::pair<unsigned, MDNode *>> &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,
@ -1372,84 +1392,6 @@ bool Instruction::extractProfTotalWeight(uint64_t &TotalVal) const {
return false;
}
void Instruction::clearMetadataHashEntries() {
assert(hasMetadataHashEntry() && "Caller should check");
getContext().pImpl->InstructionMetadata.erase(this);
setHasMetadataHashEntry(false);
}
void GlobalObject::getMetadata(unsigned KindID,
SmallVectorImpl<MDNode *> &MDs) const {
if (hasMetadata())
getContext().pImpl->GlobalObjectMetadata[this].get(KindID, MDs);
}
void GlobalObject::getMetadata(StringRef Kind,
SmallVectorImpl<MDNode *> &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<std::pair<unsigned, MDNode *>> &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<std::pair<unsigned, MDNode *>, 8> MDs;
Other->getAllMetadata(MDs);

View File

@ -51,9 +51,9 @@ static inline Type *checkType(Type *Ty) {
}
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) {
: VTy(checkType(ty)), UseList(nullptr), SubclassID(scid), HasValueHandle(0),
SubclassOptionalData(0), SubclassData(0), 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<CallInst> before the CallInst has been
@ -77,6 +77,10 @@ Value::~Value() {
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