mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-13 20:32:21 +00:00
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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@223618 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
6bb158dd34
commit
7280d8ccce
@ -353,7 +353,9 @@ void MDNode::replaceOperand(MDNodeOperand *Op, Value *To) {
|
||||
// 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, MDNode *B) {
|
||||
}
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user