[llvm] r224146 - IR: Don't track nullptr on metadata RAUW

Duncan P. N. Exon Smith dexonsmith at apple.com
Fri Dec 12 11:24:33 PST 2014


Author: dexonsmith
Date: Fri Dec 12 13:24:33 2014
New Revision: 224146

URL: http://llvm.org/viewvc/llvm-project?rev=224146&view=rev
Log:
IR: Don't track nullptr on metadata RAUW

The RAUW support in `Metadata` supports going to `nullptr` specifically
to handle values being deleted, causing `ValueAsMetadata` to be deleted.

Fix the case where the reference is from a `TrackingMDRef` (as opposed
to an `MDOperand` or a `MetadataAsValue`).

This is surprisingly rare -- metadata tracked by `TrackingMDRef` going
to null -- but it came up in an openSUSE bootstrap during inlining.  The
tracking ref was held by the `ValueMap` because it was referencing a
local, the basic block containing the local became dead after it had
been merged in, and when the local was deleted, the tracking ref
asserted in an `isa`.

Modified:
    llvm/trunk/lib/IR/Metadata.cpp
    llvm/trunk/unittests/IR/MetadataTest.cpp

Modified: llvm/trunk/lib/IR/Metadata.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Metadata.cpp?rev=224146&r1=224145&r2=224146&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Metadata.cpp (original)
+++ llvm/trunk/lib/IR/Metadata.cpp Fri Dec 12 13:24:33 2014
@@ -173,7 +173,8 @@ void ReplaceableMetadataImpl::replaceAll
       // Update unowned tracking references directly.
       Metadata *&Ref = *static_cast<Metadata **>(Pair.first);
       Ref = MD;
-      MetadataTracking::track(Ref);
+      if (MD)
+        MetadataTracking::track(Ref);
       UseMap.erase(Pair.first);
       continue;
     }

Modified: llvm/trunk/unittests/IR/MetadataTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/IR/MetadataTest.cpp?rev=224146&r1=224145&r2=224146&view=diff
==============================================================================
--- llvm/trunk/unittests/IR/MetadataTest.cpp (original)
+++ llvm/trunk/unittests/IR/MetadataTest.cpp Fri Dec 12 13:24:33 2014
@@ -207,6 +207,53 @@ TEST_F(MetadataAsValueTest, MDNodeConsta
   EXPECT_EQ(V, V2);
 }
 
+typedef MetadataTest ValueAsMetadataTest;
+
+TEST_F(ValueAsMetadataTest, UpdatesOnRAUW) {
+  Type *Ty = Type::getInt1PtrTy(Context);
+  std::unique_ptr<GlobalVariable> GV0(
+      new GlobalVariable(Ty, false, GlobalValue::ExternalLinkage));
+  auto *MD = ValueAsMetadata::get(GV0.get());
+  EXPECT_TRUE(MD->getValue() == GV0.get());
+  ASSERT_TRUE(GV0->use_empty());
+
+  std::unique_ptr<GlobalVariable> GV1(
+      new GlobalVariable(Ty, false, GlobalValue::ExternalLinkage));
+  GV0->replaceAllUsesWith(GV1.get());
+  EXPECT_TRUE(MD->getValue() == GV1.get());
+}
+
+typedef MetadataTest TrackingMDRefTest;
+
+TEST_F(TrackingMDRefTest, UpdatesOnRAUW) {
+  Type *Ty = Type::getInt1PtrTy(Context);
+  std::unique_ptr<GlobalVariable> GV0(
+      new GlobalVariable(Ty, false, GlobalValue::ExternalLinkage));
+  TypedTrackingMDRef<ValueAsMetadata> MD(ValueAsMetadata::get(GV0.get()));
+  EXPECT_TRUE(MD->getValue() == GV0.get());
+  ASSERT_TRUE(GV0->use_empty());
+
+  std::unique_ptr<GlobalVariable> GV1(
+      new GlobalVariable(Ty, false, GlobalValue::ExternalLinkage));
+  GV0->replaceAllUsesWith(GV1.get());
+  EXPECT_TRUE(MD->getValue() == GV1.get());
+
+  // Reset it, so we don't inadvertently test deletion.
+  MD.reset();
+}
+
+TEST_F(TrackingMDRefTest, UpdatesOnDeletion) {
+  Type *Ty = Type::getInt1PtrTy(Context);
+  std::unique_ptr<GlobalVariable> GV(
+      new GlobalVariable(Ty, false, GlobalValue::ExternalLinkage));
+  TypedTrackingMDRef<ValueAsMetadata> MD(ValueAsMetadata::get(GV.get()));
+  EXPECT_TRUE(MD->getValue() == GV.get());
+  ASSERT_TRUE(GV->use_empty());
+
+  GV.reset();
+  EXPECT_TRUE(!MD);
+}
+
 TEST(NamedMDNodeTest, Search) {
   LLVMContext Context;
   ConstantAsMetadata *C =





More information about the llvm-commits mailing list