summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/include/llvm/IR/Metadata.def19
-rw-r--r--llvm/include/llvm/IR/Metadata.h8
-rw-r--r--llvm/lib/IR/LLVMContextImpl.cpp2
-rw-r--r--llvm/lib/IR/Metadata.cpp67
4 files changed, 81 insertions, 15 deletions
diff --git a/llvm/include/llvm/IR/Metadata.def b/llvm/include/llvm/IR/Metadata.def
index 33b9ca090c2..2d5d91eb12a 100644
--- a/llvm/include/llvm/IR/Metadata.def
+++ b/llvm/include/llvm/IR/Metadata.def
@@ -12,7 +12,8 @@
//===----------------------------------------------------------------------===//
#if !(defined HANDLE_METADATA || defined HANDLE_METADATA_LEAF || \
- defined HANDLE_METADATA_BRANCH)
+ defined HANDLE_METADATA_BRANCH || defined HANDLE_UNIQUABLE_LEAF || \
+ defined HANDLE_UNIQUABLE_BRANCH)
#error "Missing macro definition of HANDLE_METADATA*"
#endif
@@ -31,15 +32,27 @@
#define HANDLE_METADATA_BRANCH(CLASS) HANDLE_METADATA(CLASS)
#endif
+// Handler for leaf nodes under UniquableMDNode.
+#ifndef HANDLE_UNIQUABLE_LEAF
+#define HANDLE_UNIQUABLE_LEAF(CLASS) HANDLE_METADATA_LEAF(CLASS)
+#endif
+
+// Handler for non-leaf nodes under UniquableMDNode.
+#ifndef HANDLE_UNIQUABLE_BRANCH
+#define HANDLE_UNIQUABLE_BRANCH(CLASS) HANDLE_METADATA_BRANCH(CLASS)
+#endif
+
HANDLE_METADATA_LEAF(MDString)
HANDLE_METADATA_BRANCH(ValueAsMetadata)
HANDLE_METADATA_LEAF(ConstantAsMetadata)
HANDLE_METADATA_LEAF(LocalAsMetadata)
HANDLE_METADATA_BRANCH(MDNode)
HANDLE_METADATA_LEAF(MDNodeFwdDecl)
-HANDLE_METADATA_BRANCH(UniquableMDNode)
-HANDLE_METADATA_LEAF(MDTuple)
+HANDLE_UNIQUABLE_BRANCH(UniquableMDNode)
+HANDLE_UNIQUABLE_LEAF(MDTuple)
#undef HANDLE_METADATA
#undef HANDLE_METADATA_LEAF
#undef HANDLE_METADATA_BRANCH
+#undef HANDLE_UNIQUABLE_LEAF
+#undef HANDLE_UNIQUABLE_BRANCH
diff --git a/llvm/include/llvm/IR/Metadata.h b/llvm/include/llvm/IR/Metadata.h
index cc193df4323..e813ae9d6f1 100644
--- a/llvm/include/llvm/IR/Metadata.h
+++ b/llvm/include/llvm/IR/Metadata.h
@@ -755,6 +755,10 @@ private:
void resolve();
void resolveAfterOperandChange(Metadata *Old, Metadata *New);
void decrementUnresolvedOperandCount();
+
+ void deleteAsSubclass();
+ UniquableMDNode *uniquify();
+ void eraseFromStore();
};
/// \brief Tuple of metadata.
@@ -794,6 +798,10 @@ public:
static bool classof(const Metadata *MD) {
return MD->getMetadataID() == MDTupleKind;
}
+
+private:
+ MDTuple *uniquifyImpl();
+ void eraseFromStoreImpl();
};
MDNode *MDNode::get(LLVMContext &Context, ArrayRef<Metadata *> MDs) {
diff --git a/llvm/lib/IR/LLVMContextImpl.cpp b/llvm/lib/IR/LLVMContextImpl.cpp
index c78b76021da..d47a0d332fb 100644
--- a/llvm/lib/IR/LLVMContextImpl.cpp
+++ b/llvm/lib/IR/LLVMContextImpl.cpp
@@ -142,7 +142,7 @@ LLVMContextImpl::~LLVMContextImpl() {
I->dropAllReferences();
for (UniquableMDNode *I : DistinctMDNodes)
- delete cast<MDTuple>(I);
+ I->deleteAsSubclass();
for (MDTuple *I : MDTuples)
delete I;
diff --git a/llvm/lib/IR/Metadata.cpp b/llvm/lib/IR/Metadata.cpp
index fa1f302568f..13844313925 100644
--- a/llvm/lib/IR/Metadata.cpp
+++ b/llvm/lib/IR/Metadata.cpp
@@ -525,8 +525,8 @@ void UniquableMDNode::handleChangedOperand(void *Ref, Metadata *New) {
return;
}
- auto &Store = getContext().pImpl->MDTuples;
- Store.erase(cast<MDTuple>(this));
+ // This node is uniqued.
+ eraseFromStore();
Metadata *Old = getOperand(Op);
setOperand(Op, New);
@@ -540,15 +540,10 @@ void UniquableMDNode::handleChangedOperand(void *Ref, Metadata *New) {
}
// Re-unique the node.
- cast<MDTuple>(this)->recalculateHash();
- MDTupleInfo::KeyTy Key(cast<MDTuple>(this));
- auto I = Store.find_as(Key);
- if (I == Store.end()) {
- Store.insert(cast<MDTuple>(this));
-
+ auto *Uniqued = uniquify();
+ if (Uniqued == this) {
if (!isResolved())
resolveAfterOperandChange(Old, New);
-
return;
}
@@ -560,8 +555,8 @@ void UniquableMDNode::handleChangedOperand(void *Ref, Metadata *New) {
// dropAllReferences(), but we still need the use-list).
for (unsigned O = 0, E = getNumOperands(); O != E; ++O)
setOperand(O, nullptr);
- ReplaceableUses->replaceAllUsesWith(*I);
- delete cast<MDTuple>(this);
+ ReplaceableUses->replaceAllUsesWith(Uniqued);
+ deleteAsSubclass();
return;
}
@@ -569,6 +564,41 @@ void UniquableMDNode::handleChangedOperand(void *Ref, Metadata *New) {
storeDistinctInContext();
}
+void UniquableMDNode::deleteAsSubclass() {
+ switch (getMetadataID()) {
+ default:
+ llvm_unreachable("Invalid subclass of UniquableMDNode");
+#define HANDLE_UNIQUABLE_LEAF(CLASS) \
+ case CLASS##Kind: \
+ delete cast<CLASS>(this); \
+ break;
+#include "llvm/IR/Metadata.def"
+ }
+}
+
+UniquableMDNode *UniquableMDNode::uniquify() {
+ switch (getMetadataID()) {
+ default:
+ llvm_unreachable("Invalid subclass of UniquableMDNode");
+#define HANDLE_UNIQUABLE_LEAF(CLASS) \
+ case CLASS##Kind: \
+ return cast<CLASS>(this)->uniquifyImpl();
+#include "llvm/IR/Metadata.def"
+ }
+}
+
+void UniquableMDNode::eraseFromStore() {
+ switch (getMetadataID()) {
+ default:
+ llvm_unreachable("Invalid subclass of UniquableMDNode");
+#define HANDLE_UNIQUABLE_LEAF(CLASS) \
+ case CLASS##Kind: \
+ cast<CLASS>(this)->eraseFromStoreImpl(); \
+ break;
+#include "llvm/IR/Metadata.def"
+ }
+}
+
MDTuple *MDTuple::getImpl(LLVMContext &Context, ArrayRef<Metadata *> MDs,
bool ShouldCreate) {
MDTupleInfo::KeyTy Key(MDs);
@@ -593,6 +623,21 @@ MDTuple *MDTuple::getDistinct(LLVMContext &Context, ArrayRef<Metadata *> MDs) {
return N;
}
+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;
+}
+
+void MDTuple::eraseFromStoreImpl() { getContext().pImpl->MDTuples.erase(this); }
+
MDNodeFwdDecl *MDNode::getTemporary(LLVMContext &Context,
ArrayRef<Metadata *> MDs) {
return MDNodeFwdDecl::get(Context, MDs);
OpenPOWER on IntegriCloud