[llvm] r225406 - IR: Add MDNode::getDistinct()
Duncan P. N. Exon Smith
dexonsmith at apple.com
Wed Jan 7 14:24:46 PST 2015
Author: dexonsmith
Date: Wed Jan 7 16:24:46 2015
New Revision: 225406
URL: http://llvm.org/viewvc/llvm-project?rev=225406&view=rev
Log:
IR: Add MDNode::getDistinct()
Allow distinct `MDNode`s to be explicitly created. There's no way (yet)
of representing their distinctness in assembly/bitcode, however, so this
still isn't first-class.
Part of PR22111.
Modified:
llvm/trunk/include/llvm/IR/Metadata.h
llvm/trunk/lib/IR/Metadata.cpp
llvm/trunk/unittests/IR/MetadataTest.cpp
Modified: llvm/trunk/include/llvm/IR/Metadata.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Metadata.h?rev=225406&r1=225405&r2=225406&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/Metadata.h (original)
+++ llvm/trunk/include/llvm/IR/Metadata.h Wed Jan 7 16:24:46 2015
@@ -621,6 +621,11 @@ public:
return getMDNode(Context, MDs, false);
}
+ /// \brief Return a distinct node.
+ ///
+ /// Return a distinct node -- i.e., a node that is not uniqued.
+ static MDNode *getDistinct(LLVMContext &Context, ArrayRef<Metadata *> MDs);
+
/// \brief Return a temporary MDNode
///
/// For use in constructing cyclic MDNode structures. A temporary MDNode is
@@ -700,7 +705,7 @@ public:
/// RAUW. If an operand change (due to RAUW or otherwise) causes a uniquing
/// collision, the uniquing bit is dropped.
///
-/// TODO: Make uniquing opt-out (status: mandatory, sometimes dropped).
+/// TODO: Make 'distinct' survive across assembly/bitcode/ValueMap.
class GenericMDNode : public MDNode {
friend class Metadata;
friend class MDNode;
@@ -717,7 +722,12 @@ class GenericMDNode : public MDNode {
/// LLVMContext, and adding an LLVMContext reference to RMI.
std::unique_ptr<ReplaceableMetadataImpl> ReplaceableUses;
- GenericMDNode(LLVMContext &C, ArrayRef<Metadata *> Vals);
+ /// \brief Create a new node.
+ ///
+ /// If \c AllowRAUW, then if any operands are unresolved support RAUW. RAUW
+ /// will be dropped once all operands have been resolved (or if \a
+ /// resolveCycles() is called).
+ GenericMDNode(LLVMContext &C, ArrayRef<Metadata *> Vals, bool AllowRAUW);
~GenericMDNode();
void setHash(unsigned Hash) { MDNodeSubclassData = Hash; }
Modified: llvm/trunk/lib/IR/Metadata.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Metadata.cpp?rev=225406&r1=225405&r2=225406&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Metadata.cpp (original)
+++ llvm/trunk/lib/IR/Metadata.cpp Wed Jan 7 16:24:46 2015
@@ -411,8 +411,12 @@ static bool isOperandUnresolved(Metadata
return false;
}
-GenericMDNode::GenericMDNode(LLVMContext &C, ArrayRef<Metadata *> Vals)
+GenericMDNode::GenericMDNode(LLVMContext &C, ArrayRef<Metadata *> Vals,
+ bool AllowRAUW)
: MDNode(C, GenericMDNodeKind, Vals) {
+ if (!AllowRAUW)
+ return;
+
// Check whether any operands are unresolved, requiring re-uniquing.
for (const auto &Op : operands())
if (isOperandUnresolved(Op))
@@ -581,12 +585,18 @@ MDNode *MDNode::getMDNode(LLVMContext &C
return nullptr;
// Coallocate space for the node and Operands together, then placement new.
- GenericMDNode *N = new (MDs.size()) GenericMDNode(Context, MDs);
+ auto *N = new (MDs.size()) GenericMDNode(Context, MDs, /* AllowRAUW */ true);
N->setHash(Key.Hash);
Store.insert(N);
return N;
}
+MDNode *MDNode::getDistinct(LLVMContext &Context, ArrayRef<Metadata *> MDs) {
+ auto *N = new (MDs.size()) GenericMDNode(Context, MDs, /* AllowRAUW */ false);
+ N->storeDistinctInContext();
+ return N;
+}
+
MDNodeFwdDecl *MDNode::getTemporary(LLVMContext &Context,
ArrayRef<Metadata *> MDs) {
MDNodeFwdDecl *N = new (MDs.size()) MDNodeFwdDecl(Context, MDs);
Modified: llvm/trunk/unittests/IR/MetadataTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/IR/MetadataTest.cpp?rev=225406&r1=225405&r2=225406&view=diff
==============================================================================
--- llvm/trunk/unittests/IR/MetadataTest.cpp (original)
+++ llvm/trunk/unittests/IR/MetadataTest.cpp Wed Jan 7 16:24:46 2015
@@ -249,6 +249,44 @@ TEST_F(MDNodeTest, DistinctOnUniquingCol
EXPECT_FALSE(Wrapped1->isDistinct());
}
+TEST_F(MDNodeTest, getDistinct) {
+ // !{}
+ MDNode *Empty = MDNode::get(Context, None);
+ ASSERT_TRUE(Empty->isResolved());
+ ASSERT_FALSE(Empty->isDistinct());
+ ASSERT_EQ(Empty, MDNode::get(Context, None));
+
+ // distinct !{}
+ MDNode *Distinct1 = MDNode::getDistinct(Context, None);
+ MDNode *Distinct2 = MDNode::getDistinct(Context, None);
+ EXPECT_TRUE(Distinct1->isResolved());
+ EXPECT_TRUE(Distinct2->isDistinct());
+ EXPECT_NE(Empty, Distinct1);
+ EXPECT_NE(Empty, Distinct2);
+ EXPECT_NE(Distinct1, Distinct2);
+
+ // !{}
+ ASSERT_EQ(Empty, MDNode::get(Context, None));
+}
+
+TEST_F(MDNodeTest, getDistinctWithUnresolvedOperands) {
+ // temporary !{}
+ MDNodeFwdDecl *Temp = MDNode::getTemporary(Context, None);
+ ASSERT_FALSE(Temp->isResolved());
+
+ // distinct !{temporary !{}}
+ Metadata *Ops[] = {Temp};
+ MDNode *Distinct = MDNode::getDistinct(Context, Ops);
+ EXPECT_TRUE(Distinct->isResolved());
+ EXPECT_EQ(Temp, Distinct->getOperand(0));
+
+ // temporary !{} => !{}
+ MDNode *Empty = MDNode::get(Context, None);
+ Temp->replaceAllUsesWith(Empty);
+ MDNode::deleteTemporary(Temp);
+ EXPECT_EQ(Empty, Distinct->getOperand(0));
+}
+
typedef MetadataTest MetadataAsValueTest;
TEST_F(MetadataAsValueTest, MDNode) {
More information about the llvm-commits
mailing list