[llvm] [IR] Move the LLVMContext out of ReplaceableMetadataImpl. NFC (PR #222085)
Fangrui Song via llvm-commits
llvm-commits at lists.llvm.org
Tue Sep 8 10:53:02 PDT 2026
https://github.com/MaskRay created https://github.com/llvm/llvm-project/pull/222085
No ReplaceableMetadataImpl method reads its LLVMContext reference, and
ValueAsMetadata reaches the context through the wrapped Value. Keep the
reference in a derived ReplaceableMetadataImplWithContext, used by the
two owners with no other route to it: MDNode's on-demand RAUW support
and DIArgList.
sizeof(ValueAsMetadata) 152 -> 144.
>From ca197e43d8cbfc49608956bbd13e646b1a87746d Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Tue, 8 Sep 2026 10:41:54 -0700
Subject: [PATCH] [IR] Move the LLVMContext out of ReplaceableMetadataImpl. NFC
No ReplaceableMetadataImpl method reads its LLVMContext reference, and
ValueAsMetadata reaches the context through the wrapped Value. Keep the
reference in a derived ReplaceableMetadataImplWithContext, used by the
two owners with no other route to it: MDNode's on-demand RAUW support
and DIArgList.
sizeof(ValueAsMetadata) 152 -> 144.
---
llvm/include/llvm/IR/DebugInfoMetadata.h | 6 +--
llvm/include/llvm/IR/Metadata.h | 47 ++++++++++++++----------
llvm/unittests/IR/MetadataTest.cpp | 9 +++--
3 files changed, 36 insertions(+), 26 deletions(-)
diff --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h
index e75dc8eb60b80..86c72213a5938 100644
--- a/llvm/include/llvm/IR/DebugInfoMetadata.h
+++ b/llvm/include/llvm/IR/DebugInfoMetadata.h
@@ -4977,7 +4977,7 @@ class DIMacroFile : public DIMacroNode {
/// List of ValueAsMetadata, to be used as an argument to a dbg.value
/// intrinsic.
-class DIArgList : public Metadata, ReplaceableMetadataImpl {
+class DIArgList : public Metadata, ReplaceableMetadataImplWithContext {
friend class ReplaceableMetadataImpl;
friend class LLVMContextImpl;
using iterator = SmallVectorImpl<ValueAsMetadata *>::iterator;
@@ -4985,8 +4985,8 @@ class DIArgList : public Metadata, ReplaceableMetadataImpl {
SmallVector<ValueAsMetadata *, 4> Args;
DIArgList(LLVMContext &Context, ArrayRef<ValueAsMetadata *> Args)
- : Metadata(DIArgListKind, Uniqued), ReplaceableMetadataImpl(Context),
- Args(Args) {
+ : Metadata(DIArgListKind, Uniqued),
+ ReplaceableMetadataImplWithContext(Context), Args(Args) {
track();
}
~DIArgList() { untrack(); }
diff --git a/llvm/include/llvm/IR/Metadata.h b/llvm/include/llvm/IR/Metadata.h
index a53cb63ed59cf..7c4cc00396cfe 100644
--- a/llvm/include/llvm/IR/Metadata.h
+++ b/llvm/include/llvm/IR/Metadata.h
@@ -395,19 +395,15 @@ class ReplaceableMetadataImpl {
using OwnerTy = MetadataTracking::OwnerTy;
private:
- LLVMContext &Context;
uint64_t NextIndex = 0;
SmallDenseMap<void *, std::pair<OwnerTy, uint64_t>, 4> UseMap;
-public:
- ReplaceableMetadataImpl(LLVMContext &Context) : Context(Context) {}
-
+protected:
~ReplaceableMetadataImpl() {
assert(UseMap.empty() && "Cannot destroy in-use replaceable metadata");
}
- LLVMContext &getContext() const { return Context; }
-
+public:
/// Replace all uses of this with MD.
///
/// Replace all uses of this with \c MD, which is allowed to be null.
@@ -448,6 +444,17 @@ class ReplaceableMetadataImpl {
static bool isReplaceable(const Metadata &MD);
};
+/// Replaceable metadata that remembers its \a LLVMContext, for owners with no
+/// other route to it. \a ValueAsMetadata goes through the wrapped \a Value.
+class ReplaceableMetadataImplWithContext : public ReplaceableMetadataImpl {
+ LLVMContext &Context;
+
+public:
+ ReplaceableMetadataImplWithContext(LLVMContext &Context) : Context(Context) {}
+
+ LLVMContext &getContext() const { return Context; }
+};
+
/// Value wrapper in the Metadata hierarchy.
///
/// This is a custom value handle that allows other metadata to refer to
@@ -468,8 +475,7 @@ class ValueAsMetadata : public Metadata, ReplaceableMetadataImpl {
}
protected:
- ValueAsMetadata(unsigned ID, Value *V)
- : Metadata(ID, Uniqued), ReplaceableMetadataImpl(V->getContext()), V(V) {
+ ValueAsMetadata(unsigned ID, Value *V) : Metadata(ID, Uniqued), V(V) {
assert(V && "Expected valid value");
}
@@ -964,14 +970,14 @@ template <> struct simplify_type<const MDOperand> {
/// Pointer to the context, with optional RAUW support.
///
/// Either a raw (non-null) pointer to the \a LLVMContext, or an owned pointer
-/// to \a ReplaceableMetadataImpl (which has a reference to \a LLVMContext).
+/// to \a ReplaceableMetadataImplWithContext.
class ContextAndReplaceableUses {
- PointerUnion<LLVMContext *, ReplaceableMetadataImpl *> Ptr;
+ PointerUnion<LLVMContext *, ReplaceableMetadataImplWithContext *> Ptr;
public:
ContextAndReplaceableUses(LLVMContext &Context) : Ptr(&Context) {}
ContextAndReplaceableUses(
- std::unique_ptr<ReplaceableMetadataImpl> ReplaceableUses)
+ std::unique_ptr<ReplaceableMetadataImplWithContext> ReplaceableUses)
: Ptr(ReplaceableUses.release()) {
assert(getReplaceableUses() && "Expected non-null replaceable uses");
}
@@ -987,7 +993,7 @@ class ContextAndReplaceableUses {
/// Whether this contains RAUW support.
bool hasReplaceableUses() const {
- return isa<ReplaceableMetadataImpl *>(Ptr);
+ return isa<ReplaceableMetadataImplWithContext *>(Ptr);
}
LLVMContext &getContext() const {
@@ -996,16 +1002,17 @@ class ContextAndReplaceableUses {
return *cast<LLVMContext *>(Ptr);
}
- ReplaceableMetadataImpl *getReplaceableUses() const {
+ ReplaceableMetadataImplWithContext *getReplaceableUses() const {
if (hasReplaceableUses())
- return cast<ReplaceableMetadataImpl *>(Ptr);
+ return cast<ReplaceableMetadataImplWithContext *>(Ptr);
return nullptr;
}
/// Ensure that this has RAUW support, and then return it.
- ReplaceableMetadataImpl *getOrCreateReplaceableUses() {
+ ReplaceableMetadataImplWithContext *getOrCreateReplaceableUses() {
if (!hasReplaceableUses())
- makeReplaceable(std::make_unique<ReplaceableMetadataImpl>(getContext()));
+ makeReplaceable(
+ std::make_unique<ReplaceableMetadataImplWithContext>(getContext()));
return getReplaceableUses();
}
@@ -1013,8 +1020,8 @@ class ContextAndReplaceableUses {
///
/// Make this replaceable, taking ownership of \c ReplaceableUses (which must
/// not be null).
- void
- makeReplaceable(std::unique_ptr<ReplaceableMetadataImpl> ReplaceableUses) {
+ void makeReplaceable(
+ std::unique_ptr<ReplaceableMetadataImplWithContext> ReplaceableUses) {
assert(ReplaceableUses && "Expected non-null replaceable uses");
assert(&ReplaceableUses->getContext() == &getContext() &&
"Expected same context");
@@ -1025,9 +1032,9 @@ class ContextAndReplaceableUses {
/// Drop RAUW support.
///
/// Cede ownership of RAUW support, returning it.
- std::unique_ptr<ReplaceableMetadataImpl> takeReplaceableUses() {
+ std::unique_ptr<ReplaceableMetadataImplWithContext> takeReplaceableUses() {
assert(hasReplaceableUses() && "Expected to own replaceable uses");
- std::unique_ptr<ReplaceableMetadataImpl> ReplaceableUses(
+ std::unique_ptr<ReplaceableMetadataImplWithContext> ReplaceableUses(
getReplaceableUses());
Ptr = &ReplaceableUses->getContext();
return ReplaceableUses;
diff --git a/llvm/unittests/IR/MetadataTest.cpp b/llvm/unittests/IR/MetadataTest.cpp
index 5f6feb5bd87bb..5faf354e76187 100644
--- a/llvm/unittests/IR/MetadataTest.cpp
+++ b/llvm/unittests/IR/MetadataTest.cpp
@@ -44,7 +44,8 @@ TEST(ContextAndReplaceableUsesTest, FromContext) {
TEST(ContextAndReplaceableUsesTest, FromReplaceableUses) {
LLVMContext Context;
- ContextAndReplaceableUses CRU(std::make_unique<ReplaceableMetadataImpl>(Context));
+ ContextAndReplaceableUses CRU(
+ std::make_unique<ReplaceableMetadataImplWithContext>(Context));
EXPECT_EQ(&Context, &CRU.getContext());
EXPECT_TRUE(CRU.hasReplaceableUses());
EXPECT_TRUE(CRU.getReplaceableUses());
@@ -53,7 +54,8 @@ TEST(ContextAndReplaceableUsesTest, FromReplaceableUses) {
TEST(ContextAndReplaceableUsesTest, makeReplaceable) {
LLVMContext Context;
ContextAndReplaceableUses CRU(Context);
- CRU.makeReplaceable(std::make_unique<ReplaceableMetadataImpl>(Context));
+ CRU.makeReplaceable(
+ std::make_unique<ReplaceableMetadataImplWithContext>(Context));
EXPECT_EQ(&Context, &CRU.getContext());
EXPECT_TRUE(CRU.hasReplaceableUses());
EXPECT_TRUE(CRU.getReplaceableUses());
@@ -61,7 +63,8 @@ TEST(ContextAndReplaceableUsesTest, makeReplaceable) {
TEST(ContextAndReplaceableUsesTest, takeReplaceableUses) {
LLVMContext Context;
- auto ReplaceableUses = std::make_unique<ReplaceableMetadataImpl>(Context);
+ auto ReplaceableUses =
+ std::make_unique<ReplaceableMetadataImplWithContext>(Context);
auto *Ptr = ReplaceableUses.get();
ContextAndReplaceableUses CRU(std::move(ReplaceableUses));
ReplaceableUses = CRU.takeReplaceableUses();
More information about the llvm-commits
mailing list