[PATCH] D65242: [ELF] More dynamic relocation packing

Vic Yang via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Tue Jul 30 11:31:01 PDT 2019


victoryang updated this revision to Diff 212394.

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D65242/new/

https://reviews.llvm.org/D65242

Files:
  lld/ELF/SyntheticSections.cpp


Index: lld/ELF/SyntheticSections.cpp
===================================================================
--- lld/ELF/SyntheticSections.cpp
+++ lld/ELF/SyntheticSections.cpp
@@ -1679,6 +1679,56 @@
       relativeGroups.emplace_back(std::move(group));
   }
 
+  // For non-relative relocations, we would like to:
+  //   1. Have relocations with the same symbol offset to be consecutive, so
+  //      that the runtime linker can speed-up symbol lookup by implementing an
+  //      1-entry cache.
+  //   2. Group relocations by r_info to reduce the size of the relocation
+  //      section.
+  // Since the symbol offset is the high bits in r_info, sorting by r_info
+  // allows us to do both.
+  //
+  // For Rela, we also want to sort by r_addend when r_info is the same.  This
+  // enables us to group by r_addend as well.
+  llvm::stable_sort(nonRelatives, [](const Elf_Rela &a, const Elf_Rela &b) {
+    if (a.r_info != b.r_info)
+      return a.r_info < b.r_info;
+    if (config->isRela)
+      return a.r_addend < b.r_addend;
+    return false;
+  });
+
+  // Group relocations with the same r_info.  Note that each group emits a group
+  // header and that may make the relocation section larger.  It is hard to
+  // estimate the size of a group header as the encoded size of that varies
+  // based on r_info.  However, we can approximate this trade-off by the number
+  // of values encoded.  Each group header contains 3 values, and each
+  // relocation in a group encodes one less value, as compared to when it is
+  // not grouped.  Therefore, we only group relocations if there are 3 or more
+  // of them with the same r_info.
+  //
+  // For Rela, the addend for most non-relative relocations is zero, and thus
+  // we can usually get a smaller relocation section if we group by addend
+  // as well.
+  std::vector<Elf_Rela> ungroupedNonRelatives;
+  std::vector<std::vector<Elf_Rela>> nonRelativeGroups;
+  for (auto i = nonRelatives.begin(), e = nonRelatives.end(); i != e;) {
+    auto j = i + 1;
+    while (j != e && i->r_info == j->r_info &&
+           (!config->isRela || i->r_addend == j->r_addend))
+      ++j;
+    if (j - i < 3)
+      ungroupedNonRelatives.insert(ungroupedNonRelatives.end(), i, j);
+    else
+      nonRelativeGroups.emplace_back(i, j);
+    i = j;
+  }
+
+  // Sort ungrouped relocations by offset to minimize the encoded length.
+  llvm::sort(ungroupedNonRelatives, [](const Elf_Rela &a, const Elf_Rela &b) {
+    return a.r_offset < b.r_offset;
+  });
+
   unsigned hasAddendIfRela =
       config->isRela ? RELOCATION_GROUP_HAS_ADDEND_FLAG : 0;
 
@@ -1733,14 +1783,30 @@
     }
   }
 
-  // Finally the non-relative relocations.
-  llvm::sort(nonRelatives, [](const Elf_Rela &a, const Elf_Rela &b) {
-    return a.r_offset < b.r_offset;
-  });
-  if (!nonRelatives.empty()) {
-    add(nonRelatives.size());
+  const unsigned groupedByAddendIfRela =
+    config->isRela ? RELOCATION_GROUPED_BY_ADDEND_FLAG : 0;
+
+  // Grouped non-relatives.
+  for (std::vector<Elf_Rela> &g : nonRelativeGroups) {
+    add(g.size());
+    add(RELOCATION_GROUPED_BY_INFO_FLAG | hasAddendIfRela |
+        groupedByAddendIfRela);
+    add(g[0].r_info);
+    if (config->isRela) {
+      add(g[0].r_addend - addend);
+      addend = g[0].r_addend;
+    }
+    for (Elf_Rela &r : g) {
+      add(r.r_offset - offset);
+      offset = r.r_offset;
+    }
+  }
+
+  // Finally the ungrouped non-relative relocations.
+  if (!ungroupedNonRelatives.empty()) {
+    add(ungroupedNonRelatives.size());
     add(hasAddendIfRela);
-    for (Elf_Rela &r : nonRelatives) {
+    for (Elf_Rela &r : ungroupedNonRelatives) {
       add(r.r_offset - offset);
       offset = r.r_offset;
       add(r.r_info);


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D65242.212394.patch
Type: text/x-patch
Size: 3732 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20190730/9fd37f33/attachment.bin>


More information about the llvm-commits mailing list