diff options
author | Duncan P. N. Exon Smith <dexonsmith@apple.com> | 2016-04-13 22:54:01 +0000 |
---|---|---|
committer | Duncan P. N. Exon Smith <dexonsmith@apple.com> | 2016-04-13 22:54:01 +0000 |
commit | 11f60fd65a79350de1e9f295ea2c997bdc534ea9 (patch) | |
tree | 2a72eec0a206f64110c2c29bdeae9db1357a5356 /llvm/unittests/Transforms/Utils/ValueMapperTest.cpp | |
parent | 3ef4e4a98c9c8ea57ee803897895458087856dbb (diff) | |
download | bcm5719-llvm-11f60fd65a79350de1e9f295ea2c997bdc534ea9.tar.gz bcm5719-llvm-11f60fd65a79350de1e9f295ea2c997bdc534ea9.zip |
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.
llvm-svn: 266258
Diffstat (limited to 'llvm/unittests/Transforms/Utils/ValueMapperTest.cpp')
-rw-r--r-- | llvm/unittests/Transforms/Utils/ValueMapperTest.cpp | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/llvm/unittests/Transforms/Utils/ValueMapperTest.cpp b/llvm/unittests/Transforms/Utils/ValueMapperTest.cpp index 5221ab705a3..d66bd808e7b 100644 --- a/llvm/unittests/Transforms/Utils/ValueMapperTest.cpp +++ b/llvm/unittests/Transforms/Utils/ValueMapperTest.cpp @@ -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); |