[llvm] r223618 - IR: Drop uniquing for self-referencing MDNodes
Duncan P. N. Exon Smith
dexonsmith at apple.com
Sun Dec 7 11:52:07 PST 2014
Author: dexonsmith
Date: Sun Dec 7 13:52:06 2014
New Revision: 223618
URL: http://llvm.org/viewvc/llvm-project?rev=223618&view=rev
Log:
IR: Drop uniquing for self-referencing MDNodes
It doesn't make sense to unique self-referencing nodes. Drop uniquing
for them.
Note that `MDNode::intersect()` occasionally returns self-referencing
nodes. Previously these would be returned by `MDNode::get()`. I'm not
convinced this was intended behaviour -- to me it seems it should return
a node whose only operand is the self-reference -- but I don't know much
about alias scopes so I'm preserving it for now.
This is part of PR21532.
Modified:
llvm/trunk/lib/IR/Metadata.cpp
llvm/trunk/unittests/IR/MetadataTest.cpp
Modified: llvm/trunk/lib/IR/Metadata.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Metadata.cpp?rev=223618&r1=223617&r2=223618&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Metadata.cpp (original)
+++ llvm/trunk/lib/IR/Metadata.cpp Sun Dec 7 13:52:06 2014
@@ -353,7 +353,9 @@ void MDNode::replaceOperand(MDNodeOperan
// anymore. This commonly occurs during destruction, and uniquing these
// brings little reuse. Also, this means we don't need to include
// isFunctionLocal bits in the hash for MDNodes.
- if (!To) {
+ //
+ // Also drop uniquing if this has a reference to itself.
+ if (!To || To == this) {
setIsNotUniqued();
return;
}
@@ -406,6 +408,18 @@ MDNode *MDNode::intersect(MDNode *A, MDN
}
}
+ // Handle alias scope self-references specially.
+ //
+ // FIXME: This preserves long-standing behaviour, but is it really the right
+ // behaviour? Or was that an unintended side-effect of node uniquing?
+ if (!Vals.empty())
+ if (MDNode *N = dyn_cast_or_null<MDNode>(Vals[0]))
+ if (N->getNumOperands() == Vals.size() && N == N->getOperand(0)) {
+ for (unsigned I = 1, E = Vals.size(); I != E; ++I)
+ if (Vals[I] != N->getOperand(I))
+ return MDNode::get(A->getContext(), Vals);
+ return N;
+ }
return MDNode::get(A->getContext(), Vals);
}
Modified: llvm/trunk/unittests/IR/MetadataTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/IR/MetadataTest.cpp?rev=223618&r1=223617&r2=223618&view=diff
==============================================================================
--- llvm/trunk/unittests/IR/MetadataTest.cpp (original)
+++ llvm/trunk/unittests/IR/MetadataTest.cpp Sun Dec 7 13:52:06 2014
@@ -123,6 +123,46 @@ TEST_F(MDNodeTest, Delete) {
delete I;
}
+TEST_F(MDNodeTest, SelfReference) {
+ // !0 = metadata !{metadata !0}
+ // !1 = metadata !{metadata !0}
+ {
+ MDNode *Temp = MDNode::getTemporary(Context, None);
+ Value *Args[] = {Temp};
+ MDNode *Self = MDNode::get(Context, Args);
+ Self->replaceOperandWith(0, Self);
+ MDNode::deleteTemporary(Temp);
+ ASSERT_EQ(Self, Self->getOperand(0));
+
+ // Self-references should be distinct, so MDNode::get() should grab a
+ // uniqued node that references Self, not Self.
+ Args[0] = Self;
+ MDNode *Ref1 = MDNode::get(Context, Args);
+ MDNode *Ref2 = MDNode::get(Context, Args);
+ EXPECT_NE(Self, Ref1);
+ EXPECT_EQ(Ref1, Ref2);
+ }
+
+ // !0 = metadata !{metadata !0, metadata !{}}
+ // !1 = metadata !{metadata !0, metadata !{}}
+ {
+ MDNode *Temp = MDNode::getTemporary(Context, None);
+ Value *Args[] = {Temp, MDNode::get(Context, None)};
+ MDNode *Self = MDNode::get(Context, Args);
+ Self->replaceOperandWith(0, Self);
+ MDNode::deleteTemporary(Temp);
+ ASSERT_EQ(Self, Self->getOperand(0));
+
+ // Self-references should be distinct, so MDNode::get() should grab a
+ // uniqued node that references Self, not Self itself.
+ Args[0] = Self;
+ MDNode *Ref1 = MDNode::get(Context, Args);
+ MDNode *Ref2 = MDNode::get(Context, Args);
+ EXPECT_NE(Self, Ref1);
+ EXPECT_EQ(Ref1, Ref2);
+ }
+}
+
TEST(NamedMDNodeTest, Search) {
LLVMContext Context;
Constant *C = ConstantInt::get(Type::getInt32Ty(Context), 1);
More information about the llvm-commits
mailing list