[llvm] [IR] Remove Value::HasMetadata (PR #189917)

Alexis Engelke via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 1 03:46:41 PDT 2026


https://github.com/aengelke updated https://github.com/llvm/llvm-project/pull/189917

>From 1926270fae630e00ed9fc775b2be1fedffe54389 Mon Sep 17 00:00:00 2001
From: Alexis Engelke <engelke at in.tum.de>
Date: Wed, 1 Apr 2026 08:44:47 +0000
Subject: [PATCH 1/3] [spr] initial version

Created using spr 1.3.8-wip
---
 llvm/include/llvm/IR/GlobalObject.h | 37 +++++++++++++++++++++++++++--
 llvm/include/llvm/IR/Instruction.h  |  7 +++---
 llvm/include/llvm/IR/Value.h        | 35 +++------------------------
 llvm/lib/IR/Globals.cpp             |  8 ++++++-
 llvm/lib/IR/Instruction.cpp         | 11 ++++++---
 llvm/lib/IR/Metadata.cpp            | 29 ++++++++--------------
 llvm/lib/IR/Value.cpp               |  9 +++----
 7 files changed, 70 insertions(+), 66 deletions(-)

diff --git a/llvm/include/llvm/IR/GlobalObject.h b/llvm/include/llvm/IR/GlobalObject.h
index d6b04001fdc09..1e03e22f0403b 100644
--- a/llvm/include/llvm/IR/GlobalObject.h
+++ b/llvm/include/llvm/IR/GlobalObject.h
@@ -144,10 +144,43 @@ class GlobalObject : public GlobalValue {
   using Value::eraseMetadata;
   using Value::eraseMetadataIf;
   using Value::getAllMetadata;
-  using Value::getMetadata;
-  using Value::hasMetadata;
   using Value::setMetadata;
 
+  /// Return true if this GlobalObject has any metadata attached to it.
+  bool hasMetadata() const { return MetadataIndex != 0; }
+
+  /// Return true if this instruction has the given type of metadata attached.
+  bool hasMetadata(unsigned KindID) const {
+    return getMetadata(KindID) != nullptr;
+  }
+
+  /// Return true if this instruction has the given type of metadata attached.
+  bool hasMetadata(StringRef Kind) const {
+    return getMetadata(Kind) != nullptr;
+  }
+
+  /// Get the metadata of given kind attached to this GlobalObject.
+  /// If the metadata is not found then return null.
+  MDNode *getMetadata(unsigned KindID) const {
+    return hasMetadata() ? getMetadataImpl(KindID) : nullptr;
+  }
+
+  /// Get the metadata of given kind attached to this GlobalObject.
+  /// If the metadata is not found then return null.
+  MDNode *getMetadata(StringRef Kind) const {
+    return hasMetadata() ? Value::getMetadata(Kind) : nullptr;
+  }
+
+  /// Appends all attachments with the given ID to \c MDs in insertion order.
+  /// If the Value has no attachments with the given ID, or if ID is invalid,
+  /// leaves MDs unchanged.
+  /// @{
+  LLVM_ABI void getMetadata(unsigned KindID,
+                            SmallVectorImpl<MDNode *> &MDs) const;
+  LLVM_ABI void getMetadata(StringRef Kind,
+                            SmallVectorImpl<MDNode *> &MDs) const;
+  /// @}
+
   LLVM_ABI bool hasMetadataOtherThanDebugLoc() const;
 
   /// Copy metadata from Src, adjusting offsets by Offset.
diff --git a/llvm/include/llvm/IR/Instruction.h b/llvm/include/llvm/IR/Instruction.h
index 396d8a5f25ba3..be35f645009f5 100644
--- a/llvm/include/llvm/IR/Instruction.h
+++ b/llvm/include/llvm/IR/Instruction.h
@@ -439,7 +439,7 @@ class Instruction : public User,
   //===--------------------------------------------------------------------===//
 
   /// Return true if this instruction has any metadata attached to it.
-  bool hasMetadata() const { return DbgLoc || Value::hasMetadata(); }
+  bool hasMetadata() const { return DbgLoc || MetadataIndex != 0; }
 
   // Return true if this instruction contains loop metadata other than
   // a debug location
@@ -447,7 +447,7 @@ class Instruction : public User,
 
   /// Return true if this instruction has metadata attached to it other than a
   /// debug location.
-  bool hasMetadataOtherThanDebugLoc() const { return Value::hasMetadata(); }
+  bool hasMetadataOtherThanDebugLoc() const { return MetadataIndex != 0; }
 
   /// Return true if this instruction has the given type of metadata attached.
   bool hasMetadata(unsigned KindID) const {
@@ -465,7 +465,8 @@ class Instruction : public User,
     // Handle 'dbg' as a special case since it is not stored in the hash table.
     if (KindID == LLVMContext::MD_dbg)
       return DbgLoc.getAsMDNode();
-    return Value::getMetadata(KindID);
+    return hasMetadataOtherThanDebugLoc() ? Value::getMetadataImpl(KindID)
+                                          : nullptr;
   }
 
   /// Get the metadata of given kind attached to this Instruction.
diff --git a/llvm/include/llvm/IR/Value.h b/llvm/include/llvm/IR/Value.h
index b149fe55375b1..9b424a6703394 100644
--- a/llvm/include/llvm/IR/Value.h
+++ b/llvm/include/llvm/IR/Value.h
@@ -105,13 +105,12 @@ class Value {
   ///
   /// Note, this should *NOT* be used directly by any class other than User.
   /// User uses this value to find the Use list.
-  enum : unsigned { NumUserOperandsBits = 27 };
+  enum : unsigned { NumUserOperandsBits = 28 };
   unsigned NumUserOperands : NumUserOperandsBits;
 
   // Use the same type as the bitfield above so that MSVC will pack them.
   unsigned IsUsedByMD : 1;
   unsigned HasName : 1;
-  unsigned HasMetadata : 1; // Has metadata attached to this?
   unsigned HasHungOffUses : 1;
   unsigned HasDescriptor : 1;
 
@@ -574,12 +573,7 @@ class Value {
   /// These functions require that the value have at most a single attachment
   /// of the given kind, and return \c nullptr if such an attachment is missing.
   /// @{
-  MDNode *getMetadata(unsigned KindID) const {
-    if (!HasMetadata)
-      return nullptr;
-    return getMetadataImpl(KindID);
-  }
-  LLVM_ABI MDNode *getMetadata(StringRef Kind) const;
+  LLVM_ABI MDNode *getMetadata(StringRef Kind) const LLVM_READONLY;
   /// @}
 
 private:
@@ -587,16 +581,6 @@ class Value {
   LLVM_ABI unsigned &getMetadataIndex();
 
 protected:
-  /// Appends all attachments with the given ID to \c MDs in insertion order.
-  /// If the Value has no attachments with the given ID, or if ID is invalid,
-  /// leaves MDs unchanged.
-  /// @{
-  LLVM_ABI void getMetadata(unsigned KindID,
-                            SmallVectorImpl<MDNode *> &MDs) const;
-  LLVM_ABI void getMetadata(StringRef Kind,
-                            SmallVectorImpl<MDNode *> &MDs) const;
-  /// @}
-
   /// Appends all metadata attached to this value to \c MDs, sorting by
   /// KindID. The first element of each pair returned is the KindID, the second
   /// element is the metadata value. Attachments with the same ID appear in
@@ -604,19 +588,6 @@ class Value {
   LLVM_ABI void
   getAllMetadata(SmallVectorImpl<std::pair<unsigned, MDNode *>> &MDs) const;
 
-  /// Return true if this value has any metadata attached to it.
-  bool hasMetadata() const { return (bool)HasMetadata; }
-
-  /// Return true if this value has the given type of metadata attached.
-  /// @{
-  bool hasMetadata(unsigned KindID) const {
-    return getMetadata(KindID) != nullptr;
-  }
-  bool hasMetadata(StringRef Kind) const {
-    return getMetadata(Kind) != nullptr;
-  }
-  /// @}
-
   /// Set a particular kind of metadata attachment.
   ///
   /// Sets the given attachment to \c MD, erasing it if \c MD is \c nullptr or
@@ -646,7 +617,7 @@ class Value {
   /// Get metadata for the given kind, if any.
   /// This is an internal function that must only be called after
   /// checking that `hasMetadata()` returns true.
-  LLVM_ABI MDNode *getMetadataImpl(unsigned KindID) const;
+  LLVM_ABI MDNode *getMetadataImpl(unsigned KindID) const LLVM_READONLY;
 
 public:
   /// Return true if this value is a swifterror value.
diff --git a/llvm/lib/IR/Globals.cpp b/llvm/lib/IR/Globals.cpp
index 81976f389ff9d..1bd7e9605ffc7 100644
--- a/llvm/lib/IR/Globals.cpp
+++ b/llvm/lib/IR/Globals.cpp
@@ -105,7 +105,13 @@ void GlobalValue::eraseFromParent() {
   llvm_unreachable("not a global");
 }
 
-GlobalObject::~GlobalObject() { setComdat(nullptr); }
+GlobalObject::~GlobalObject() {
+  // Remove associated metadata from context.
+  if (hasMetadata())
+    clearMetadata();
+
+  setComdat(nullptr);
+}
 
 bool GlobalValue::isInterposable() const {
   if (isInterposableLinkage(getLinkage()))
diff --git a/llvm/lib/IR/Instruction.cpp b/llvm/lib/IR/Instruction.cpp
index 5205d36a228c1..d3b3e6eea53ff 100644
--- a/llvm/lib/IR/Instruction.cpp
+++ b/llvm/lib/IR/Instruction.cpp
@@ -74,9 +74,14 @@ Instruction::~Instruction() {
   if (isUsedByMetadata())
     ValueAsMetadata::handleRAUW(this, PoisonValue::get(getType()));
 
-  // Explicitly remove DIAssignID metadata to clear up ID -> Instruction(s)
-  // mapping in LLVMContext.
-  setMetadata(LLVMContext::MD_DIAssignID, nullptr);
+  // Remove associated metadata from context.
+  if (hasMetadata()) {
+    // Explicitly remove DIAssignID metadata to clear up ID -> Instruction(s)
+    // mapping in LLVMContext.
+    // TODO: still needed?
+    setMetadata(LLVMContext::MD_DIAssignID, nullptr);
+    clearMetadata();
+  }
 }
 
 const Module *Instruction::getModule() const {
diff --git a/llvm/lib/IR/Metadata.cpp b/llvm/lib/IR/Metadata.cpp
index e3c837885de8b..4f4662df774a1 100644
--- a/llvm/lib/IR/Metadata.cpp
+++ b/llvm/lib/IR/Metadata.cpp
@@ -1558,8 +1558,6 @@ unsigned Value::getMetadataIndex() const {
 }
 
 MDNode *Value::getMetadata(StringRef Kind) const {
-  if (!hasMetadata())
-    return nullptr;
   unsigned KindID = getContext().getMDKindID(Kind);
   return getMetadataImpl(KindID);
 }
@@ -1576,9 +1574,10 @@ MDNode *Value::getMetadataImpl(unsigned KindID) const {
   return nullptr;
 }
 
-void Value::getMetadata(unsigned KindID, SmallVectorImpl<MDNode *> &MDs) const {
+void GlobalObject::getMetadata(unsigned KindID,
+                               SmallVectorImpl<MDNode *> &MDs) const {
   const LLVMContext &Ctx = getContext();
-  unsigned Idx = getMetadataIndex();
+  unsigned Idx = MetadataIndex;
   while (Idx) {
     const MDAttachment &A = Ctx.pImpl->Metadatas[Idx];
     if (A.MDKind == KindID)
@@ -1589,7 +1588,8 @@ void Value::getMetadata(unsigned KindID, SmallVectorImpl<MDNode *> &MDs) const {
   std::reverse(MDs.begin(), MDs.end());
 }
 
-void Value::getMetadata(StringRef Kind, SmallVectorImpl<MDNode *> &MDs) const {
+void GlobalObject::getMetadata(StringRef Kind,
+                               SmallVectorImpl<MDNode *> &MDs) const {
   getMetadata(getContext().getMDKindID(Kind), MDs);
 }
 
@@ -1613,20 +1613,17 @@ void Value::getAllMetadata(
 void Value::setMetadata(unsigned KindID, MDNode *Node) {
   assert(isa<Instruction>(this) || isa<GlobalObject>(this));
 
-  eraseMetadata(KindID);
+  if (getMetadataIndex() != 0)
+    eraseMetadata(KindID);
   if (Node)
     addMetadata(KindID, *Node);
 }
 
 void Value::setMetadata(StringRef Kind, MDNode *Node) {
-  if (!Node && !HasMetadata)
-    return;
   setMetadata(getContext().getMDKindID(Kind), Node);
 }
 
 void Value::addMetadata(unsigned KindID, MDNode &MD) {
-  if (!HasMetadata)
-    HasMetadata = true;
   const LLVMContext &Ctx = getContext();
   unsigned &Idx = getMetadataIndex();
   unsigned NewIdx = Ctx.pImpl->MetadataRecycleHead;
@@ -1677,8 +1674,6 @@ void Value::eraseMetadataIf(function_ref<bool(unsigned, MDNode *)> Pred) {
       Idx = &A.Next;
     }
   }
-  if (getMetadataIndex() == 0)
-    HasMetadata = false;
 }
 
 void Value::clearMetadata() {
@@ -1686,8 +1681,6 @@ void Value::clearMetadata() {
 }
 
 void Instruction::setMetadata(StringRef Kind, MDNode *Node) {
-  if (!Node && !hasMetadata())
-    return;
   setMetadata(getContext().getMDKindID(Kind), Node);
 }
 
@@ -1696,7 +1689,7 @@ MDNode *Instruction::getMetadataImpl(StringRef Kind) const {
   unsigned KindID = Ctx.getMDKindID(Kind);
   if (KindID == LLVMContext::MD_dbg)
     return DbgLoc.getAsMDNode();
-  return Value::getMetadata(KindID);
+  return Value::getMetadataImpl(KindID);
 }
 
 void Instruction::eraseMetadataIf(function_ref<bool(unsigned, MDNode *)> Pred) {
@@ -1707,7 +1700,7 @@ void Instruction::eraseMetadataIf(function_ref<bool(unsigned, MDNode *)> Pred) {
 }
 
 void Instruction::dropUnknownNonDebugMetadata(ArrayRef<unsigned> KnownIDs) {
-  if (!Value::hasMetadata())
+  if (!hasMetadataOtherThanDebugLoc())
     return; // Nothing to remove!
 
   SmallSet<unsigned, 32> KnownSet(llvm::from_range, KnownIDs);
@@ -1824,9 +1817,7 @@ void Instruction::addAnnotationMetadata(StringRef Name) {
 
 AAMDNodes Instruction::getAAMetadata() const {
   AAMDNodes Result;
-  // Not using Instruction::hasMetadata() because we're not interested in
-  // DebugInfoMetadata.
-  if (Value::hasMetadata()) {
+  if (hasMetadataOtherThanDebugLoc()) {
     unsigned Idx = MetadataIndex;
     const auto &Metadatas = getContext().pImpl->Metadatas;
     while (Idx) {
diff --git a/llvm/lib/IR/Value.cpp b/llvm/lib/IR/Value.cpp
index 0bb493438b13b..360bf0f8fc47f 100644
--- a/llvm/lib/IR/Value.cpp
+++ b/llvm/lib/IR/Value.cpp
@@ -53,7 +53,7 @@ static inline Type *checkType(Type *Ty) {
 Value::Value(Type *ty, unsigned scid)
     : SubclassID(scid), HasValueHandle(0), SubclassOptionalData(0),
       SubclassData(0), NumUserOperands(0), IsUsedByMD(false), HasName(false),
-      HasMetadata(false), VTy(checkType(ty)) {
+      VTy(checkType(ty)) {
   static_assert(ConstantFirstVal == 0, "!(SubclassID < ConstantFirstVal)");
   // FIXME: Why isn't this in the subclass gunk??
   // Note, we cannot call isa<CallInst> before the CallInst has been
@@ -80,10 +80,6 @@ Value::~Value() {
   if (isUsedByMetadata())
     ValueAsMetadata::handleDeletion(this);
 
-  // Remove associated metadata from context.
-  if (HasMetadata)
-    clearMetadata();
-
 #ifndef NDEBUG      // Only in -g mode...
   // Check to make sure that there are no uses of this value that are still
   // around when the value is destroyed.  If there are, then we have a dangling
@@ -848,7 +844,8 @@ bool Value::canBeFreed() const {
       return false;
   }
 
-  if (isa<IntToPtrInst>(this) && getMetadata(LLVMContext::MD_nofree))
+  if (auto *ITP = dyn_cast<IntToPtrInst>(this);
+      ITP && ITP->hasMetadata(LLVMContext::MD_nofree))
     return false;
 
   const Function *F = nullptr;

>From eed5592b0cdc33a2bdb5d339981bb5b76c5a5392 Mon Sep 17 00:00:00 2001
From: Alexis Engelke <engelke at in.tum.de>
Date: Wed, 1 Apr 2026 10:06:29 +0000
Subject: [PATCH 2/3] fix perf regression

Created using spr 1.3.8-wip
---
 llvm/lib/IR/Instruction.cpp | 3 +--
 llvm/lib/IR/Metadata.cpp    | 2 ++
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/IR/Instruction.cpp b/llvm/lib/IR/Instruction.cpp
index d3b3e6eea53ff..8aa19a436a157 100644
--- a/llvm/lib/IR/Instruction.cpp
+++ b/llvm/lib/IR/Instruction.cpp
@@ -78,8 +78,7 @@ Instruction::~Instruction() {
   if (hasMetadata()) {
     // Explicitly remove DIAssignID metadata to clear up ID -> Instruction(s)
     // mapping in LLVMContext.
-    // TODO: still needed?
-    setMetadata(LLVMContext::MD_DIAssignID, nullptr);
+    updateDIAssignIDMapping(nullptr);
     clearMetadata();
   }
 }
diff --git a/llvm/lib/IR/Metadata.cpp b/llvm/lib/IR/Metadata.cpp
index 4f4662df774a1..80db7824b754c 100644
--- a/llvm/lib/IR/Metadata.cpp
+++ b/llvm/lib/IR/Metadata.cpp
@@ -1620,6 +1620,8 @@ void Value::setMetadata(unsigned KindID, MDNode *Node) {
 }
 
 void Value::setMetadata(StringRef Kind, MDNode *Node) {
+  if (!Node && getMetadataIndex() == 0)
+    return;
   setMetadata(getContext().getMDKindID(Kind), Node);
 }
 

>From 853cbc2ed1b8bd49b2e3e8e276300531732e160d Mon Sep 17 00:00:00 2001
From: Alexis Engelke <engelke at in.tum.de>
Date: Wed, 1 Apr 2026 10:46:01 +0000
Subject: [PATCH 3/3] second attempt of perf regression fix...

Created using spr 1.3.8-wip
---
 llvm/lib/IR/Metadata.cpp | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/llvm/lib/IR/Metadata.cpp b/llvm/lib/IR/Metadata.cpp
index 80db7824b754c..82f224438eec5 100644
--- a/llvm/lib/IR/Metadata.cpp
+++ b/llvm/lib/IR/Metadata.cpp
@@ -1683,6 +1683,8 @@ void Value::clearMetadata() {
 }
 
 void Instruction::setMetadata(StringRef Kind, MDNode *Node) {
+  if (!Node && MetadataIndex == 0)
+    return;
   setMetadata(getContext().getMDKindID(Kind), Node);
 }
 



More information about the llvm-commits mailing list