[lld] [lld-macho] Include ICF safe thunks in balanced partitioning (PR #212096)

Ellis Hoag via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 31 09:36:05 PDT 2026


================
@@ -119,36 +119,76 @@ DenseMap<const InputSection *, int> lld::macho::runBalancedPartitioning(
     bool compressionSortStartupFunctions, bool verbose) {
   // Collect candidate sections and associated symbols.
   SmallVector<InputSection *> sections;
+  DenseMap<const InputSection *, unsigned> sectionToIdx;
   DenseMap<CachedHashStringRef, std::set<unsigned>> rootSymbolToSectionIdxs;
+  auto addSectionForName = [&](StringRef name, unsigned idx) {
+    auto rootName = lld::utils::getRootSymbol(name);
+    rootSymbolToSectionIdxs[CachedHashStringRef(rootName)].insert(idx);
+    if (auto linkageName = BPOrdererMachO::getResolvedLinkageName(rootName))
+      rootSymbolToSectionIdxs[CachedHashStringRef(*linkageName)].insert(idx);
+  };
+  auto addSection = [&](InputSection *isec) {
+    if (!isec || isec->data.empty() || !isec->data.data())
+      return;
+    // CString section order is handled by
+    // {Deduplicated}CStringSection::finalizeContents()
+    if (isa<CStringInputSection>(isec) || isec->isFinal)
+      return;
+    // ConcatInputSections are entirely live or dead, so the offset is
+    // irrelevant.
+    if (isa<ConcatInputSection>(isec) && !isec->isLive(0))
+      return;
+    unsigned idx = sections.size();
+    sections.emplace_back(isec);
+    sectionToIdx.try_emplace(isec, idx);
+    for (auto *sym : isec->symbols)
+      addSectionForName(sym->getName(), idx);
+  };
   for (const auto *file : inputFiles) {
     for (auto *sec : file->sections) {
       if (sec->name == section_names::ehFrame &&
           sec->segname == segment_names::text)
         continue;
-      for (auto &subsec : sec->subsections) {
-        auto *isec = subsec.isec;
-        if (!isec || isec->data.empty() || !isec->data.data())
-          continue;
-        // CString section order is handled by
-        // {Deduplicated}CStringSection::finalizeContents()
-        if (isa<CStringInputSection>(isec) || isec->isFinal)
-          continue;
-        // ConcatInputSections are entirely live or dead, so the offset is
-        // irrelevant.
-        if (isa<ConcatInputSection>(isec) && !isec->isLive(0))
-          continue;
-        size_t idx = sections.size();
-        sections.emplace_back(isec);
-        for (auto *sym : BPOrdererMachO::getSymbols(*isec)) {
-          auto rootName = lld::utils::getRootSymbol(sym->getName());
-          rootSymbolToSectionIdxs[CachedHashStringRef(rootName)].insert(idx);
-          if (auto linkageName =
-                  BPOrdererMachO::getResolvedLinkageName(rootName))
-            rootSymbolToSectionIdxs[CachedHashStringRef(*linkageName)].insert(
-                idx);
+      for (auto &subsec : sec->subsections)
+        addSection(subsec.isec);
+    }
+  }
+  // ICF safe thunks are linker-created after the input-file section graph is
+  // built, so they do not appear in file->sections. Include them through the
+  // same path as input-file sections so only live BP candidates are added.
+  for (auto *isec : inputSections) {
+    for (auto *sym : isec->symbols) {
+      if (sym->identicalCodeFoldingKind == Symbol::ICFFoldKind::Thunk) {
+        addSection(isec);
+        break;
+      }
+    }
+  }
+
+  // A temporal profile naming an ICF thunk describes execution of both the
+  // thunk and the shared body it branches to. Add the body to each name that
+  // resolves to a thunk, following the thunk relocation to find it.
+  for (auto &entry : rootSymbolToSectionIdxs) {
----------------
ellishg wrote:

Does this compile? I remember we sometimes need to use `const auto`, but that might not be possible since we are appending to `sectionIdxs`.
```suggestion
  for (auto &[symbol, sectionIdxs] : rootSymbolToSectionIdxs) {
```

https://github.com/llvm/llvm-project/pull/212096


More information about the llvm-commits mailing list