[llvm] IRLinker: avoid quardatic behavior (PR #157045)

Vitaly Buka via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 5 01:21:08 PDT 2025


https://github.com/vitalybuka created https://github.com/llvm/llvm-project/pull/157045

is_contained does linear search trough
all previously inserted operands.

On large binaries it can take up to 30%
for ThinLTO linking with CFI, which has
large `cfi.function` metadata.


>From 008d698ea272f501713d2a51ecda4fbcfd493f19 Mon Sep 17 00:00:00 2001
From: Vitaly Buka <vitalybuka at google.com>
Date: Fri, 5 Sep 2025 01:20:48 -0700
Subject: [PATCH] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20initia?=
 =?UTF-8?q?l=20version?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Created using spr 1.3.6
---
 llvm/lib/Linker/IRMover.cpp | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/Linker/IRMover.cpp b/llvm/lib/Linker/IRMover.cpp
index d6c15de4c4cdc..8903f6e9775d8 100644
--- a/llvm/lib/Linker/IRMover.cpp
+++ b/llvm/lib/Linker/IRMover.cpp
@@ -8,6 +8,7 @@
 
 #include "llvm/Linker/IRMover.h"
 #include "LinkDiagnosticInfo.h"
+#include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/IR/AutoUpgrade.h"
@@ -290,6 +291,9 @@ class IRLinker {
   Module &DstM;
   std::unique_ptr<Module> SrcM;
 
+  // Lookup table to optimize IRMover::linkNamedMDNodes().
+  DenseMap<StringRef, DenseSet<MDNode *>> NamedMDNodes;
+
   /// See IRMover::move().
   IRMover::LazyCallback AddLazyFor;
 
@@ -1132,12 +1136,20 @@ void IRLinker::linkNamedMDNodes() {
       continue;
 
     NamedMDNode *DestNMD = DstM.getOrInsertNamedMetadata(NMD.getName());
+
+    auto &Inserted = NamedMDNodes[DestNMD->getName()];
+    if (Inserted.size() < DestNMD->getNumOperands()) {
+      // Must be the first module, copy everything from DestNMD.
+      Inserted.insert(DestNMD->operands().begin(), DestNMD->operands().end());
+    }
+
     // Add Src elements into Dest node.
     for (const MDNode *Op : NMD.operands()) {
       MDNode *MD = Mapper.mapMDNode(*Op);
-      if (!is_contained(DestNMD->operands(), MD))
+      if (Inserted.insert(MD).second)
         DestNMD->addOperand(MD);
     }
+    assert(Inserted.size() == DestNMD->getNumOperands());
   }
 }
 



More information about the llvm-commits mailing list