summaryrefslogtreecommitdiffstats
path: root/llvm/unittests/Transforms/Utils/ValueMapperTest.cpp
diff options
context:
space:
mode:
authorDuncan P. N. Exon Smith <dexonsmith@apple.com>2016-04-13 22:54:01 +0000
committerDuncan P. N. Exon Smith <dexonsmith@apple.com>2016-04-13 22:54:01 +0000
commit11f60fd65a79350de1e9f295ea2c997bdc534ea9 (patch)
tree2a72eec0a206f64110c2c29bdeae9db1357a5356 /llvm/unittests/Transforms/Utils/ValueMapperTest.cpp
parent3ef4e4a98c9c8ea57ee803897895458087856dbb (diff)
downloadbcm5719-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.cpp42
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);
OpenPOWER on IntegriCloud