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,
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())
}
}
+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);