mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-02-20 14:29:27 +00:00
IR: Enable uniquing callbacks during MDNode::replaceWithUniqued()
Uniqued nodes have more complete registration with `ReplaceableMetadataImpl` so that they can update themselves when operands change. Fix a bug where `MDNode::replaceWithUniqued()` wasn't enabling these callbacks. The two most obvious ways missing callbacks causes problems is that auto-resolution fails and re-uniquing (on changed operands) just doesn't happen. I've added tests for both -- in both cases, I confirmed that the final check was failing before the fix. rdar://problem/20365935 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@233751 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
d26a5d313c
commit
f067a68207
@ -761,6 +761,11 @@ protected:
|
||||
MDOperand *mutable_begin() { return mutable_end() - NumOperands; }
|
||||
MDOperand *mutable_end() { return reinterpret_cast<MDOperand *>(this); }
|
||||
|
||||
typedef iterator_range<MDOperand *> mutable_op_range;
|
||||
mutable_op_range mutable_operands() {
|
||||
return mutable_op_range(mutable_begin(), mutable_end());
|
||||
}
|
||||
|
||||
public:
|
||||
static inline MDTuple *get(LLVMContext &Context, ArrayRef<Metadata *> MDs);
|
||||
static inline MDTuple *getIfExists(LLVMContext &Context,
|
||||
|
@ -446,6 +446,10 @@ void MDNode::makeUniqued() {
|
||||
assert(isTemporary() && "Expected this to be temporary");
|
||||
assert(!isResolved() && "Expected this to be unresolved");
|
||||
|
||||
// Enable uniquing callbacks.
|
||||
for (auto &Op : mutable_operands())
|
||||
Op.reset(Op.get(), this);
|
||||
|
||||
// Make this 'uniqued'.
|
||||
Storage = Uniqued;
|
||||
if (!countUnresolvedOperands())
|
||||
|
@ -627,6 +627,48 @@ TEST_F(MDNodeTest, replaceWithUniqued) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(MDNodeTest, replaceWithUniquedUnresolved) {
|
||||
// temp !{}
|
||||
MDTuple *Op = MDTuple::getTemporary(Context, None).release();
|
||||
EXPECT_FALSE(Op->isResolved());
|
||||
|
||||
// temp !{temp !{}}
|
||||
Metadata *Ops[] = {Op};
|
||||
MDTuple *N = MDTuple::getTemporary(Context, Ops).release();
|
||||
EXPECT_FALSE(N->isResolved());
|
||||
|
||||
// temp !{temp !{}} => !{temp !{}}
|
||||
ASSERT_EQ(N, MDNode::replaceWithUniqued(TempMDTuple(N)));
|
||||
EXPECT_FALSE(N->isResolved());
|
||||
|
||||
// !{temp !{}} => !{!{}}
|
||||
ASSERT_EQ(Op, MDNode::replaceWithUniqued(TempMDTuple(Op)));
|
||||
EXPECT_TRUE(Op->isResolved());
|
||||
EXPECT_TRUE(N->isResolved());
|
||||
}
|
||||
|
||||
TEST_F(MDNodeTest, replaceWithUniquedUnresolvedChangedOperand) {
|
||||
// i1* @GV
|
||||
Type *Ty = Type::getInt1PtrTy(Context);
|
||||
std::unique_ptr<GlobalVariable> GV(
|
||||
new GlobalVariable(Ty, false, GlobalValue::ExternalLinkage));
|
||||
ConstantAsMetadata *Op = ConstantAsMetadata::get(GV.get());
|
||||
|
||||
// temp !{i1* @GV}
|
||||
Metadata *Ops[] = {Op};
|
||||
MDTuple *N = MDTuple::getTemporary(Context, Ops).release();
|
||||
|
||||
// temp !{i1* @GV} => !{i1* @GV}
|
||||
ASSERT_EQ(N, MDNode::replaceWithUniqued(TempMDTuple(N)));
|
||||
ASSERT_TRUE(N->isUniqued());
|
||||
|
||||
// !{i1* @GV} => !{null}
|
||||
GV.reset();
|
||||
ASSERT_TRUE(N->isUniqued());
|
||||
Metadata *NullOps[] = {nullptr};
|
||||
ASSERT_EQ(N, MDTuple::get(Context, NullOps));
|
||||
}
|
||||
|
||||
TEST_F(MDNodeTest, replaceWithDistinct) {
|
||||
{
|
||||
auto *Empty = MDTuple::get(Context, None);
|
||||
|
Loading…
x
Reference in New Issue
Block a user