[lld] 3195297 - [MachO] Reduce size of Symbol and Defined

Shoaib Meenai via llvm-commits llvm-commits at lists.llvm.org
Tue Nov 16 16:31:06 PST 2021


Author: Shoaib Meenai
Date: 2021-11-16T16:30:33-08:00
New Revision: 31952978970dcc3a2b91a0ac240d9ab06c06c856

URL: https://github.com/llvm/llvm-project/commit/31952978970dcc3a2b91a0ac240d9ab06c06c856
DIFF: https://github.com/llvm/llvm-project/commit/31952978970dcc3a2b91a0ac240d9ab06c06c856.diff

LOG: [MachO] Reduce size of Symbol and Defined

We can lay out Symbol more optimally to reduce its size from 56 bytes to
48 bytes by eliminating unnecessary padding, and we can lay out Defined
such that its bitfield members are placed in the tail padding of Symbol
(on ABIs which support this), to reduce it from 96 bytes to 80 bytes (8
bytes from the Symbol reduction, and 8 bytes from the tail padding
reuse).

This is perf-neutral for an internal app (results from two different
machines):

```
           smol-syms       baseline        difference (95% CI)
sys_time   7.430 ± 0.202   7.440 ± 0.193   [  -2.6% ..   +2.9%]
user_time  21.443 ± 0.513  21.206 ± 0.396  [  -3.3% ..   +1.1%]
wall_time  20.453 ± 0.534  20.222 ± 0.488  [  -3.7% ..   +1.5%]
samples    9               8

           smol-syms       baseline        difference (95% CI)
sys_time   3.011 ± 0.050   3.040 ± 0.052   [  -0.4% ..   +2.3%]
user_time  10.416 ± 0.075  10.496 ± 0.091  [  +0.1% ..   +1.4%]
wall_time  12.229 ± 0.144  12.354 ± 0.192  [  -0.1% ..   +2.1%]
samples    14              13
```

However, on the first machine, it reduces maximum resident set size by
65.9 MB (0.8%, from 7.92 GB to 7.85 GB). On the second machine, it
reduces it by 92 MB (1.4%, from 6.40 GB to 6.31 GB).

Reviewed By: #lld-macho, int3

Differential Revision: https://reviews.llvm.org/D113813

Added: 
    

Modified: 
    lld/MachO/Symbols.cpp
    lld/MachO/Symbols.h

Removed: 
    


################################################################################
diff  --git a/lld/MachO/Symbols.cpp b/lld/MachO/Symbols.cpp
index ed9b4d6383ad..97fe33866e90 100644
--- a/lld/MachO/Symbols.cpp
+++ b/lld/MachO/Symbols.cpp
@@ -36,12 +36,11 @@ Defined::Defined(StringRefZ name, InputFile *file, InputSection *isec,
                  bool isPrivateExtern, bool isThumb,
                  bool isReferencedDynamically, bool noDeadStrip,
                  bool canOverrideWeakDef, bool isWeakDefCanBeHidden)
-    : Symbol(DefinedKind, name, file), isec(isec), value(value), size(size),
-      overridesWeakDef(canOverrideWeakDef), privateExtern(isPrivateExtern),
-      includeInSymtab(true), thumb(isThumb),
+    : Symbol(DefinedKind, name, file), overridesWeakDef(canOverrideWeakDef),
+      privateExtern(isPrivateExtern), includeInSymtab(true), thumb(isThumb),
       referencedDynamically(isReferencedDynamically), noDeadStrip(noDeadStrip),
       weakDefCanBeHidden(isWeakDefCanBeHidden), weakDef(isWeakDef),
-      external(isExternal) {
+      external(isExternal), isec(isec), value(value), size(size) {
   if (isec) {
     isec->symbols.push_back(this);
     // Maintain sorted order.

diff  --git a/lld/MachO/Symbols.h b/lld/MachO/Symbols.h
index 2d38eea88be0..0212a14e83d4 100644
--- a/lld/MachO/Symbols.h
+++ b/lld/MachO/Symbols.h
@@ -92,14 +92,14 @@ class Symbol {
 
 protected:
   Symbol(Kind k, StringRefZ name, InputFile *file)
-      : symbolKind(k), nameData(name.data), nameSize(name.size), file(file),
+      : symbolKind(k), nameData(name.data), file(file), nameSize(name.size),
         isUsedInRegularObj(!file || isa<ObjFile>(file)),
         used(!config->deadStrip) {}
 
   Kind symbolKind;
   const char *nameData;
-  mutable uint32_t nameSize;
   InputFile *file;
+  mutable uint32_t nameSize;
 
 public:
   // True if this symbol was referenced by a regular (non-bitcode) object.
@@ -109,6 +109,9 @@ class Symbol {
   bool used : 1;
 };
 
+static_assert(sizeof(void *) != 8 || sizeof(Symbol) == 48,
+              "Try to minimize Symbol's size; we create many instances");
+
 class Defined : public Symbol {
 public:
   Defined(StringRefZ name, InputFile *file, InputSection *isec, uint64_t value,
@@ -133,14 +136,8 @@ class Defined : public Symbol {
 
   static bool classof(const Symbol *s) { return s->kind() == DefinedKind; }
 
-  InputSection *isec;
-  // Contains the offset from the containing subsection. Note that this is
-  // 
diff erent from nlist::n_value, which is the absolute address of the symbol.
-  uint64_t value;
-  // size is only calculated for regular (non-bitcode) symbols.
-  uint64_t size;
-  ConcatInputSection *compactUnwind = nullptr;
-
+  // Place the bitfields first so that they can get placed in the tail padding
+  // of the parent class, on platforms which support it.
   bool overridesWeakDef : 1;
   // Whether this symbol should appear in the output binary's export trie.
   bool privateExtern : 1;
@@ -166,8 +163,24 @@ class Defined : public Symbol {
 private:
   const bool weakDef : 1;
   const bool external : 1;
+
+public:
+  InputSection *isec;
+  // Contains the offset from the containing subsection. Note that this is
+  // 
diff erent from nlist::n_value, which is the absolute address of the symbol.
+  uint64_t value;
+  // size is only calculated for regular (non-bitcode) symbols.
+  uint64_t size;
+  ConcatInputSection *compactUnwind = nullptr;
 };
 
+// The Microsoft ABI doesn't support using parent class tail padding for child
+// members, hence the _MSC_VER check.
+#if !defined(_MSC_VER)
+static_assert(sizeof(void *) != 8 || sizeof(Defined) == 80,
+              "Try to minimize Defined's size; we create many instances");
+#endif
+
 // This enum does double-duty: as a symbol property, it indicates whether & how
 // a dylib symbol is referenced. As a DylibFile property, it indicates the kind
 // of referenced symbols contained within the file. If there are both weak
@@ -294,6 +307,9 @@ union SymbolUnion {
   alignas(LazySymbol) char e[sizeof(LazySymbol)];
 };
 
+static_assert(sizeof(SymbolUnion) == sizeof(Defined),
+              "Defined should be the largest Symbol kind");
+
 template <typename T, typename... ArgT>
 T *replaceSymbol(Symbol *s, ArgT &&...arg) {
   static_assert(sizeof(T) <= sizeof(SymbolUnion), "SymbolUnion too small");


        


More information about the llvm-commits mailing list