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

Vic Yang via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon Jul 29 10:36:05 PDT 2019


victoryang updated this revision to Diff 212195.
victoryang added a comment.

Updated comments in code to better explain what's going on, as per requested by ruiu.


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,46 @@
       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.
+  llvm::sort(nonRelatives, [](const Elf_Rela &a, const Elf_Rela &b) {
+    return a.r_info < b.r_info;
+  });
+
+  // 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.
+  std::vector<Elf_Rela> ungroupedNonRelatives;
+  std::vector<std::vector<Elf_Rela>> nonRelativeGroups;
+  for (auto i = nonRelatives.begin(), e = nonRelatives.end(); i != e;) {
+    std::vector<Elf_Rela> group;
+    do {
+      group.push_back(*i++);
+    } while (i != e && (i - 1)->r_info == i->r_info);
+
+    if (group.size() < 3)
+      ungroupedNonRelatives.insert(ungroupedNonRelatives.end(), group.begin(),
+                                   group.end());
+    else
+      nonRelativeGroups.emplace_back(std::move(group));
+  }
+
+  // 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 +1773,26 @@
     }
   }
 
-  // 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());
+  // Grouped non-relatives.
+  for (std::vector<Elf_Rela> &g : nonRelativeGroups) {
+    add(g.size());
+    add(RELOCATION_GROUPED_BY_INFO_FLAG | hasAddendIfRela);
+    add(g[0].r_info);
+    for (Elf_Rela &r : g) {
+      add(r.r_offset - offset);
+      offset = r.r_offset;
+      if (config->isRela) {
+        add(r.r_addend - addend);
+        addend = r.r_addend;
+      }
+    }
+  }
+
+  // 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.212195.patch
Type: text/x-patch
Size: 3218 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20190729/7cad521b/attachment.bin>


More information about the llvm-commits mailing list