[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