[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