[llvm] r266258 - ValueMapper: Resolve cycles on the new nodes

Duncan P. N. Exon Smith via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 13 15:54:01 PDT 2016


Author: dexonsmith
Date: Wed Apr 13 17:54:01 2016
New Revision: 266258

URL: http://llvm.org/viewvc/llvm-project?rev=266258&view=rev
Log:
ValueMapper: Resolve cycles on the new nodes

Fix a major bug from r265456.  Although it's now much rarer, ValueMapper
sometimes has to duplicate cycles.  The
might-transitively-reference-a-temporary counts don't decrement on their
own when there are cycles, and you need to call MDNode::resolveCycles to
fix it.

r265456 was checking the input nodes to see if they were unresolved.
This is useless; they should never be unresolved.  Instead we should
check the output nodes and resolve cycles on them.

Modified:
    llvm/trunk/lib/Transforms/Utils/ValueMapper.cpp
    llvm/trunk/unittests/Transforms/Utils/ValueMapperTest.cpp

Modified: llvm/trunk/lib/Transforms/Utils/ValueMapper.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/ValueMapper.cpp?rev=266258&r1=266257&r2=266258&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Utils/ValueMapper.cpp (original)
+++ llvm/trunk/lib/Transforms/Utils/ValueMapper.cpp Wed Apr 13 17:54:01 2016
@@ -587,6 +587,7 @@ void MDNodeMapper::mapDistinctNodes() {
 
 void MDNodeMapper::mapUniquedNodes() {
   // Construct uniqued nodes, building forward references as necessary.
+  SmallVector<MDNode *, 16> CyclicNodes;
   for (auto *N : POT) {
     if (N->isDistinct())
       continue;
@@ -601,11 +602,12 @@ void MDNodeMapper::mapUniquedNodes() {
 
     TempMDNode ClonedN = D.Placeholder ? std::move(D.Placeholder) : N->clone();
     remapOperands(D, *ClonedN);
-    M.mapToMetadata(N, MDNode::replaceWithUniqued(std::move(ClonedN)));
+    CyclicNodes.push_back(MDNode::replaceWithUniqued(std::move(ClonedN)));
+    M.mapToMetadata(N, CyclicNodes.back());
   }
 
   // Resolve cycles.
-  for (auto *N : POT)
+  for (auto *N : CyclicNodes)
     if (!N->isResolved())
       N->resolveCycles();
 }

Modified: llvm/trunk/unittests/Transforms/Utils/ValueMapperTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Transforms/Utils/ValueMapperTest.cpp?rev=266258&r1=266257&r2=266258&view=diff
==============================================================================
--- llvm/trunk/unittests/Transforms/Utils/ValueMapperTest.cpp (original)
+++ llvm/trunk/unittests/Transforms/Utils/ValueMapperTest.cpp Wed Apr 13 17:54:01 2016
@@ -9,6 +9,7 @@
 
 #include "llvm/IR/Constants.h"
 #include "llvm/IR/Function.h"
+#include "llvm/IR/GlobalVariable.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/Metadata.h"
 #include "llvm/Transforms/Utils/ValueMapper.h"
@@ -63,6 +64,47 @@ TEST(ValueMapperTest, MapMetadataCycle)
   }
 }
 
+TEST(ValueMapperTest, MapMetadataDuplicatedCycle) {
+  LLVMContext Context;
+  auto *PtrTy = Type::getInt8Ty(Context)->getPointerTo();
+  std::unique_ptr<GlobalVariable> G0 = llvm::make_unique<GlobalVariable>(
+      PtrTy, false, GlobalValue::ExternalLinkage, nullptr, "G0");
+  std::unique_ptr<GlobalVariable> G1 = llvm::make_unique<GlobalVariable>(
+      PtrTy, false, GlobalValue::ExternalLinkage, nullptr, "G1");
+
+  // Create a cycle that references G0.
+  MDNode *N0; // !0 = !{!1}
+  MDNode *N1; // !1 = !{!0, i8* @G0}
+  {
+    auto T0 = MDTuple::getTemporary(Context, nullptr);
+    Metadata *Ops1[] = {T0.get(), ConstantAsMetadata::get(G0.get())};
+    N1 = MDTuple::get(Context, Ops1);
+    T0->replaceOperandWith(0, N1);
+    N0 = MDNode::replaceWithUniqued(std::move(T0));
+  }
+
+  // Resolve N0 and N1.
+  ASSERT_FALSE(N0->isResolved());
+  ASSERT_FALSE(N1->isResolved());
+  N0->resolveCycles();
+  ASSERT_TRUE(N0->isResolved());
+  ASSERT_TRUE(N1->isResolved());
+
+  // Seed the value map to map G0 to G1 and map the nodes.  The output should
+  // have new nodes that reference G1 (instead of G0).
+  ValueToValueMapTy VM;
+  VM[G0.get()] = G1.get();
+  MDNode *MappedN0 = MapMetadata(N0, VM);
+  MDNode *MappedN1 = MapMetadata(N1, VM);
+  EXPECT_NE(N0, MappedN0);
+  EXPECT_NE(N1, MappedN1);
+  EXPECT_EQ(ConstantAsMetadata::get(G1.get()), MappedN1->getOperand(1));
+
+  // Check that the output nodes are resolved.
+  EXPECT_TRUE(MappedN0->isResolved());
+  EXPECT_TRUE(MappedN1->isResolved());
+}
+
 TEST(ValueMapperTest, MapMetadataUnresolved) {
   LLVMContext Context;
   TempMDTuple T = MDTuple::getTemporary(Context, None);




More information about the llvm-commits mailing list