Skip to content

Commit 7115a0b

Browse files
authored
IRLinker: avoid quadratic behavior (#157045)
After #146020 `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.functions` metadata.
1 parent 74ec38f commit 7115a0b

File tree

1 file changed

+14
-1
lines changed

1 file changed

+14
-1
lines changed

llvm/lib/Linker/IRMover.cpp

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
#include "llvm/Linker/IRMover.h"
1010
#include "LinkDiagnosticInfo.h"
11+
#include "llvm/ADT/DenseMap.h"
12+
#include "llvm/ADT/DenseSet.h"
1113
#include "llvm/ADT/SetVector.h"
1214
#include "llvm/ADT/SmallString.h"
1315
#include "llvm/IR/AutoUpgrade.h"
@@ -290,6 +292,9 @@ class IRLinker {
290292
Module &DstM;
291293
std::unique_ptr<Module> SrcM;
292294

295+
// Lookup table to optimize IRMover::linkNamedMDNodes().
296+
DenseMap<StringRef, DenseSet<MDNode *>> NamedMDNodes;
297+
293298
/// See IRMover::move().
294299
IRMover::LazyCallback AddLazyFor;
295300

@@ -1132,12 +1137,20 @@ void IRLinker::linkNamedMDNodes() {
11321137
continue;
11331138

11341139
NamedMDNode *DestNMD = DstM.getOrInsertNamedMetadata(NMD.getName());
1140+
1141+
auto &Inserted = NamedMDNodes[DestNMD->getName()];
1142+
if (Inserted.empty()) {
1143+
// Must be the first module, copy everything from DestNMD.
1144+
Inserted.insert(DestNMD->operands().begin(), DestNMD->operands().end());
1145+
}
1146+
11351147
// Add Src elements into Dest node.
11361148
for (const MDNode *Op : NMD.operands()) {
11371149
MDNode *MD = Mapper.mapMDNode(*Op);
1138-
if (!is_contained(DestNMD->operands(), MD))
1150+
if (Inserted.insert(MD).second)
11391151
DestNMD->addOperand(MD);
11401152
}
1153+
assert(Inserted.size() == DestNMD->getNumOperands());
11411154
}
11421155
}
11431156

0 commit comments

Comments
 (0)