mirror of
https://github.com/RPCS3/llvm.git
synced 2025-01-10 14:12:11 +00:00
IR: Add MDNode::getDistinct()
Allow distinct `MDNode`s to be explicitly created. There's no way (yet) of representing their distinctness in assembly/bitcode, however, so this still isn't first-class. Part of PR22111. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@225406 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
a3ee583339
commit
727176d00e
@ -621,6 +621,11 @@ public:
|
||||
return getMDNode(Context, MDs, false);
|
||||
}
|
||||
|
||||
/// \brief Return a distinct node.
|
||||
///
|
||||
/// Return a distinct node -- i.e., a node that is not uniqued.
|
||||
static MDNode *getDistinct(LLVMContext &Context, ArrayRef<Metadata *> MDs);
|
||||
|
||||
/// \brief Return a temporary MDNode
|
||||
///
|
||||
/// For use in constructing cyclic MDNode structures. A temporary MDNode is
|
||||
@ -700,7 +705,7 @@ public:
|
||||
/// RAUW. If an operand change (due to RAUW or otherwise) causes a uniquing
|
||||
/// collision, the uniquing bit is dropped.
|
||||
///
|
||||
/// TODO: Make uniquing opt-out (status: mandatory, sometimes dropped).
|
||||
/// TODO: Make 'distinct' survive across assembly/bitcode/ValueMap.
|
||||
class GenericMDNode : public MDNode {
|
||||
friend class Metadata;
|
||||
friend class MDNode;
|
||||
@ -717,7 +722,12 @@ class GenericMDNode : public MDNode {
|
||||
/// LLVMContext, and adding an LLVMContext reference to RMI.
|
||||
std::unique_ptr<ReplaceableMetadataImpl> ReplaceableUses;
|
||||
|
||||
GenericMDNode(LLVMContext &C, ArrayRef<Metadata *> Vals);
|
||||
/// \brief Create a new node.
|
||||
///
|
||||
/// If \c AllowRAUW, then if any operands are unresolved support RAUW. RAUW
|
||||
/// will be dropped once all operands have been resolved (or if \a
|
||||
/// resolveCycles() is called).
|
||||
GenericMDNode(LLVMContext &C, ArrayRef<Metadata *> Vals, bool AllowRAUW);
|
||||
~GenericMDNode();
|
||||
|
||||
void setHash(unsigned Hash) { MDNodeSubclassData = Hash; }
|
||||
|
@ -411,8 +411,12 @@ static bool isOperandUnresolved(Metadata *Op) {
|
||||
return false;
|
||||
}
|
||||
|
||||
GenericMDNode::GenericMDNode(LLVMContext &C, ArrayRef<Metadata *> Vals)
|
||||
GenericMDNode::GenericMDNode(LLVMContext &C, ArrayRef<Metadata *> Vals,
|
||||
bool AllowRAUW)
|
||||
: MDNode(C, GenericMDNodeKind, Vals) {
|
||||
if (!AllowRAUW)
|
||||
return;
|
||||
|
||||
// Check whether any operands are unresolved, requiring re-uniquing.
|
||||
for (const auto &Op : operands())
|
||||
if (isOperandUnresolved(Op))
|
||||
@ -581,12 +585,18 @@ MDNode *MDNode::getMDNode(LLVMContext &Context, ArrayRef<Metadata *> MDs,
|
||||
return nullptr;
|
||||
|
||||
// Coallocate space for the node and Operands together, then placement new.
|
||||
GenericMDNode *N = new (MDs.size()) GenericMDNode(Context, MDs);
|
||||
auto *N = new (MDs.size()) GenericMDNode(Context, MDs, /* AllowRAUW */ true);
|
||||
N->setHash(Key.Hash);
|
||||
Store.insert(N);
|
||||
return N;
|
||||
}
|
||||
|
||||
MDNode *MDNode::getDistinct(LLVMContext &Context, ArrayRef<Metadata *> MDs) {
|
||||
auto *N = new (MDs.size()) GenericMDNode(Context, MDs, /* AllowRAUW */ false);
|
||||
N->storeDistinctInContext();
|
||||
return N;
|
||||
}
|
||||
|
||||
MDNodeFwdDecl *MDNode::getTemporary(LLVMContext &Context,
|
||||
ArrayRef<Metadata *> MDs) {
|
||||
MDNodeFwdDecl *N = new (MDs.size()) MDNodeFwdDecl(Context, MDs);
|
||||
|
@ -249,6 +249,44 @@ TEST_F(MDNodeTest, DistinctOnUniquingCollision) {
|
||||
EXPECT_FALSE(Wrapped1->isDistinct());
|
||||
}
|
||||
|
||||
TEST_F(MDNodeTest, getDistinct) {
|
||||
// !{}
|
||||
MDNode *Empty = MDNode::get(Context, None);
|
||||
ASSERT_TRUE(Empty->isResolved());
|
||||
ASSERT_FALSE(Empty->isDistinct());
|
||||
ASSERT_EQ(Empty, MDNode::get(Context, None));
|
||||
|
||||
// distinct !{}
|
||||
MDNode *Distinct1 = MDNode::getDistinct(Context, None);
|
||||
MDNode *Distinct2 = MDNode::getDistinct(Context, None);
|
||||
EXPECT_TRUE(Distinct1->isResolved());
|
||||
EXPECT_TRUE(Distinct2->isDistinct());
|
||||
EXPECT_NE(Empty, Distinct1);
|
||||
EXPECT_NE(Empty, Distinct2);
|
||||
EXPECT_NE(Distinct1, Distinct2);
|
||||
|
||||
// !{}
|
||||
ASSERT_EQ(Empty, MDNode::get(Context, None));
|
||||
}
|
||||
|
||||
TEST_F(MDNodeTest, getDistinctWithUnresolvedOperands) {
|
||||
// temporary !{}
|
||||
MDNodeFwdDecl *Temp = MDNode::getTemporary(Context, None);
|
||||
ASSERT_FALSE(Temp->isResolved());
|
||||
|
||||
// distinct !{temporary !{}}
|
||||
Metadata *Ops[] = {Temp};
|
||||
MDNode *Distinct = MDNode::getDistinct(Context, Ops);
|
||||
EXPECT_TRUE(Distinct->isResolved());
|
||||
EXPECT_EQ(Temp, Distinct->getOperand(0));
|
||||
|
||||
// temporary !{} => !{}
|
||||
MDNode *Empty = MDNode::get(Context, None);
|
||||
Temp->replaceAllUsesWith(Empty);
|
||||
MDNode::deleteTemporary(Temp);
|
||||
EXPECT_EQ(Empty, Distinct->getOperand(0));
|
||||
}
|
||||
|
||||
typedef MetadataTest MetadataAsValueTest;
|
||||
|
||||
TEST_F(MetadataAsValueTest, MDNode) {
|
||||
|
Loading…
Reference in New Issue
Block a user