[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