[llvm] [BOLT] Compute local code section names lazily to reduce memory (PR #214890)

via llvm-commits llvm-commits at lists.llvm.org
Fri Aug 7 16:48:00 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-bolt

Author: Rafael Auler (rafaelauler)

<details>
<summary>Changes</summary>

Every BinaryFunction eagerly materialized two std::string members at construction: CodeSectionName (".local.text.<name>") and ColdCodeSectionName (".local.cold.text.<name>"), built by appending the full function name to a fixed prefix. On ELF the name is the (often large, mangled) symbol name, which is already owned by the function's MCSymbol. So every function stored two extra heap copies of its name -- for all functions, whether or not they were ever emitted into a per-function section. During discoverFileObjects on a large binary, this eager construction (buildSectionName -> Twine::str) accounted for 1-2% of RSS (1770MB).

Here we make both members std::optional<std::string>, left empty by default, and recompute the default name on demand in getCodeSectionName() from the function's name. Only functions with an explicitly assigned section name (via
setCodeSectionName/setColdCodeSectionName -- mostly short constants such as ".text"/".text.cold" set during reordering, plus the injected/patch cases) store a string. The common, unoptimized function stores nothing.

---
Full diff: https://github.com/llvm/llvm-project/pull/214890.diff


1 Files Affected:

- (modified) bolt/include/bolt/Core/BinaryFunction.h (+26-9) 


``````````diff
diff --git a/bolt/include/bolt/Core/BinaryFunction.h b/bolt/include/bolt/Core/BinaryFunction.h
index 2846b562a1c1a..14d7f9b5b5359 100644
--- a/bolt/include/bolt/Core/BinaryFunction.h
+++ b/bolt/include/bolt/Core/BinaryFunction.h
@@ -54,6 +54,7 @@
 #include <algorithm>
 #include <iterator>
 #include <limits>
+#include <optional>
 #include <unordered_map>
 #include <utility>
 #include <vector>
@@ -405,11 +406,15 @@ class BinaryFunction {
   /// to avoid redundant processing.
   bool NeedBranchValidation{true};
 
-  /// Name for the section this function code should reside in.
-  std::string CodeSectionName;
+  /// Name for the section this function code should reside in. When unset, the
+  /// default name is derived on demand from the function's name (see
+  /// getMainSectionName()). Deferring this avoids eagerly storing a copy of the
+  /// (potentially large, mangled) function name for every function, which is a
+  /// significant source of memory use on large binaries.
+  std::optional<std::string> CodeSectionName;
 
-  /// Name for the corresponding cold code section.
-  std::string ColdCodeSectionName;
+  /// Name for the corresponding cold code section. See CodeSectionName.
+  std::optional<std::string> ColdCodeSectionName;
 
   /// Parent function fragment for split function fragments.
   using FragmentsSetTy = SmallPtrSet<BinaryFunction *, 1>;
@@ -749,12 +754,24 @@ class BinaryFunction {
   static std::string buildColdCodeSectionName(StringRef Name,
                                               const BinaryContext &BC);
 
+  /// Return the name of the main code section, using the default derived from
+  /// the function's name when no name has been explicitly assigned.
+  std::string getMainSectionName() const {
+    return CodeSectionName ? *CodeSectionName
+                           : buildCodeSectionName(getOneName(), BC);
+  }
+
+  /// Return the name of the cold code section, using the default derived from
+  /// the function's name when no name has been explicitly assigned.
+  std::string getColdSectionName() const {
+    return ColdCodeSectionName ? *ColdCodeSectionName
+                               : buildColdCodeSectionName(getOneName(), BC);
+  }
+
   /// Creation should be handled by RewriteInstance or BinaryContext
   BinaryFunction(const std::string &Name, BinarySection &Section,
                  uint64_t Address, uint64_t Size, BinaryContext &BC)
       : OriginSection(&Section), Address(Address), Size(Size), BC(BC),
-        CodeSectionName(buildCodeSectionName(Name, BC)),
-        ColdCodeSectionName(buildColdCodeSectionName(Name, BC)),
         FunctionNumber(++Count) {
     Symbols.push_back(BC.Ctx->getOrCreateSymbol(Name));
   }
@@ -1400,12 +1417,12 @@ class BinaryFunction {
   SmallString<32>
   getCodeSectionName(const FragmentNum Fragment = FragmentNum::main()) const {
     if (Fragment == FragmentNum::main())
-      return SmallString<32>(CodeSectionName);
+      return SmallString<32>(getMainSectionName());
     if (Fragment == FragmentNum::cold())
-      return SmallString<32>(ColdCodeSectionName);
+      return SmallString<32>(getColdSectionName());
     if (BC.HasWarmSection && Fragment == FragmentNum::warm())
       return SmallString<32>(BC.getWarmCodeSectionName());
-    return formatv("{0}.{1}", ColdCodeSectionName, Fragment.get() - 1);
+    return formatv("{0}.{1}", getColdSectionName(), Fragment.get() - 1);
   }
 
   /// Assign a code section name to the function.

``````````

</details>


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


More information about the llvm-commits mailing list