diff options
author | Duncan P. N. Exon Smith <dexonsmith@apple.com> | 2015-02-10 19:13:46 +0000 |
---|---|---|
committer | Duncan P. N. Exon Smith <dexonsmith@apple.com> | 2015-02-10 19:13:46 +0000 |
commit | 4ee4a98eaae16bbf9041acd3bc0f605b03d196e2 (patch) | |
tree | d96a528b2f7d05c661b4ebd3084552754202c905 /llvm/unittests/IR/MetadataTest.cpp | |
parent | 82f1c775a074feaa724948cbc1795336deaa2b4f (diff) | |
download | bcm5719-llvm-4ee4a98eaae16bbf9041acd3bc0f605b03d196e2.tar.gz bcm5719-llvm-4ee4a98eaae16bbf9041acd3bc0f605b03d196e2.zip |
IR: Add MDNode::replaceWithPermanent()
Add new API for converting temporaries that may self-reference.
Self-referencing nodes are not allowed to be uniqued, so sending them
into `replaceWithUniqued()` is dangerous (and this commit adds
assertions that prevent it).
`replaceWithPermanent()` has similar semantics to `get()` followed by
calls to `replaceOperandWith()`. In particular, if there's a
self-reference, it returns a distinct node; otherwise, it returns a
uniqued one. Like `replaceWithUniqued()` and `replaceWithDistinct()`
(well, it calls out to them) it mutates the temporary node in place if
possible, only calling `replaceAllUsesWith()` on a uniquing collision.
llvm-svn: 228726
Diffstat (limited to 'llvm/unittests/IR/MetadataTest.cpp')
-rw-r--r-- | llvm/unittests/IR/MetadataTest.cpp | 38 |
1 files changed, 38 insertions, 0 deletions
diff --git a/llvm/unittests/IR/MetadataTest.cpp b/llvm/unittests/IR/MetadataTest.cpp index 9bc8164dd48..e8e6d68c5fa 100644 --- a/llvm/unittests/IR/MetadataTest.cpp +++ b/llvm/unittests/IR/MetadataTest.cpp @@ -518,6 +518,44 @@ TEST_F(MDNodeTest, replaceWithDistinct) { } } +TEST_F(MDNodeTest, replaceWithPermanent) { + Metadata *Ops[] = {nullptr}; + auto Temp = MDTuple::getTemporary(Context, Ops); + auto *T = Temp.get(); + + // U is a normal, uniqued node that references T. + auto *U = MDTuple::get(Context, T); + EXPECT_TRUE(U->isUniqued()); + + // Make Temp self-referencing. + Temp->replaceOperandWith(0, T); + + // Try to uniquify Temp. This should, despite the name in the API, give a + // 'distinct' node, since self-references aren't allowed to be uniqued. + // + // Since it's distinct, N should have the same address as when it was a + // temporary (i.e., be equal to T not U). + auto *N = MDNode::replaceWithPermanent(std::move(Temp)); + EXPECT_EQ(N, T); + EXPECT_TRUE(N->isDistinct()); + + // U should be the canonical unique node with N as the argument. + EXPECT_EQ(U, MDTuple::get(Context, N)); + EXPECT_TRUE(U->isUniqued()); + + // This temporary should collide with U when replaced, but it should still be + // uniqued. + EXPECT_EQ(U, MDNode::replaceWithPermanent(MDTuple::getTemporary(Context, N))); + EXPECT_TRUE(U->isUniqued()); + + // This temporary should become a new uniqued node. + auto Temp2 = MDTuple::getTemporary(Context, U); + auto *V = Temp2.get(); + EXPECT_EQ(V, MDNode::replaceWithPermanent(std::move(Temp2))); + EXPECT_TRUE(V->isUniqued()); + EXPECT_EQ(U, V->getOperand(0)); +} + TEST_F(MDNodeTest, deleteTemporaryWithTrackingRef) { TrackingMDRef Ref; EXPECT_EQ(nullptr, Ref.get()); |