llvm.org GIT mirror llvm / 4cd20e7
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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@266258 91177308-0d34-0410-b5e6-96231b3b80d8 Duncan P. N. Exon Smith 4 years ago
2 changed file(s) with 46 addition(s) and 2 deletion(s). Raw diff Collapse all Expand all
586586
587587 void MDNodeMapper::mapUniquedNodes() {
588588 // Construct uniqued nodes, building forward references as necessary.
589 SmallVector CyclicNodes;
589590 for (auto *N : POT) {
590591 if (N->isDistinct())
591592 continue;
600601
601602 TempMDNode ClonedN = D.Placeholder ? std::move(D.Placeholder) : N->clone();
602603 remapOperands(D, *ClonedN);
603 M.mapToMetadata(N, MDNode::replaceWithUniqued(std::move(ClonedN)));
604 CyclicNodes.push_back(MDNode::replaceWithUniqued(std::move(ClonedN)));
605 M.mapToMetadata(N, CyclicNodes.back());
604606 }
605607
606608 // Resolve cycles.
607 for (auto *N : POT)
609 for (auto *N : CyclicNodes)
608610 if (!N->isResolved())
609611 N->resolveCycles();
610612 }
88
99 #include "llvm/IR/Constants.h"
1010 #include "llvm/IR/Function.h"
11 #include "llvm/IR/GlobalVariable.h"
1112 #include "llvm/IR/LLVMContext.h"
1213 #include "llvm/IR/Metadata.h"
1314 #include "llvm/Transforms/Utils/ValueMapper.h"
6061 EXPECT_EQ(U1, MapMetadata(U1, VM, RF_None));
6162 EXPECT_EQ(U0, MapMetadata(U0, VM, RF_None));
6263 }
64 }
65
66 TEST(ValueMapperTest, MapMetadataDuplicatedCycle) {
67 LLVMContext Context;
68 auto *PtrTy = Type::getInt8Ty(Context)->getPointerTo();
69 std::unique_ptr G0 = llvm::make_unique(
70 PtrTy, false, GlobalValue::ExternalLinkage, nullptr, "G0");
71 std::unique_ptr G1 = llvm::make_unique(
72 PtrTy, false, GlobalValue::ExternalLinkage, nullptr, "G1");
73
74 // Create a cycle that references G0.
75 MDNode *N0; // !0 = !{!1}
76 MDNode *N1; // !1 = !{!0, i8* @G0}
77 {
78 auto T0 = MDTuple::getTemporary(Context, nullptr);
79 Metadata *Ops1[] = {T0.get(), ConstantAsMetadata::get(G0.get())};
80 N1 = MDTuple::get(Context, Ops1);
81 T0->replaceOperandWith(0, N1);
82 N0 = MDNode::replaceWithUniqued(std::move(T0));
83 }
84
85 // Resolve N0 and N1.
86 ASSERT_FALSE(N0->isResolved());
87 ASSERT_FALSE(N1->isResolved());
88 N0->resolveCycles();
89 ASSERT_TRUE(N0->isResolved());
90 ASSERT_TRUE(N1->isResolved());
91
92 // Seed the value map to map G0 to G1 and map the nodes. The output should
93 // have new nodes that reference G1 (instead of G0).
94 ValueToValueMapTy VM;
95 VM[G0.get()] = G1.get();
96 MDNode *MappedN0 = MapMetadata(N0, VM);
97 MDNode *MappedN1 = MapMetadata(N1, VM);
98 EXPECT_NE(N0, MappedN0);
99 EXPECT_NE(N1, MappedN1);
100 EXPECT_EQ(ConstantAsMetadata::get(G1.get()), MappedN1->getOperand(1));
101
102 // Check that the output nodes are resolved.
103 EXPECT_TRUE(MappedN0->isResolved());
104 EXPECT_TRUE(MappedN1->isResolved());
63105 }
64106
65107 TEST(ValueMapperTest, MapMetadataUnresolved) {