xref: /freebsd/contrib/llvm-project/lld/COFF/ICF.cpp (revision e6bfd18d21b225af6a0ed67ceeaf1293b7b9eba5)
1 //===- ICF.cpp ------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // ICF is short for Identical Code Folding. That is a size optimization to
10 // identify and merge two or more read-only sections (typically functions)
11 // that happened to have the same contents. It usually reduces output size
12 // by a few percent.
13 //
14 // On Windows, ICF is enabled by default.
15 //
16 // See ELF/ICF.cpp for the details about the algorithm.
17 //
18 //===----------------------------------------------------------------------===//
19 
20 #include "ICF.h"
21 #include "COFFLinkerContext.h"
22 #include "Chunks.h"
23 #include "Symbols.h"
24 #include "lld/Common/ErrorHandler.h"
25 #include "lld/Common/Timer.h"
26 #include "llvm/ADT/Hashing.h"
27 #include "llvm/Support/Debug.h"
28 #include "llvm/Support/Parallel.h"
29 #include "llvm/Support/raw_ostream.h"
30 #include "llvm/Support/xxhash.h"
31 #include <algorithm>
32 #include <atomic>
33 #include <vector>
34 
35 using namespace llvm;
36 
37 namespace lld {
38 namespace coff {
39 
40 class ICF {
41 public:
42   ICF(COFFLinkerContext &c, ICFLevel icfLevel) : icfLevel(icfLevel), ctx(c){};
43   void run();
44 
45 private:
46   void segregate(size_t begin, size_t end, bool constant);
47 
48   bool assocEquals(const SectionChunk *a, const SectionChunk *b);
49 
50   bool equalsConstant(const SectionChunk *a, const SectionChunk *b);
51   bool equalsVariable(const SectionChunk *a, const SectionChunk *b);
52 
53   bool isEligible(SectionChunk *c);
54 
55   size_t findBoundary(size_t begin, size_t end);
56 
57   void forEachClassRange(size_t begin, size_t end,
58                          std::function<void(size_t, size_t)> fn);
59 
60   void forEachClass(std::function<void(size_t, size_t)> fn);
61 
62   std::vector<SectionChunk *> chunks;
63   int cnt = 0;
64   std::atomic<bool> repeat = {false};
65   ICFLevel icfLevel = ICFLevel::All;
66 
67   COFFLinkerContext &ctx;
68 };
69 
70 // Returns true if section S is subject of ICF.
71 //
72 // Microsoft's documentation
73 // (https://msdn.microsoft.com/en-us/library/bxwfs976.aspx; visited April
74 // 2017) says that /opt:icf folds both functions and read-only data.
75 // Despite that, the MSVC linker folds only functions. We found
76 // a few instances of programs that are not safe for data merging.
77 // Therefore, we merge only functions just like the MSVC tool. However, we also
78 // merge read-only sections in a couple of cases where the address of the
79 // section is insignificant to the user program and the behaviour matches that
80 // of the Visual C++ linker.
81 bool ICF::isEligible(SectionChunk *c) {
82   // Non-comdat chunks, dead chunks, and writable chunks are not eligible.
83   bool writable = c->getOutputCharacteristics() & llvm::COFF::IMAGE_SCN_MEM_WRITE;
84   if (!c->isCOMDAT() || !c->live || writable)
85     return false;
86 
87   // Under regular (not safe) ICF, all code sections are eligible.
88   if ((icfLevel == ICFLevel::All) &&
89       c->getOutputCharacteristics() & llvm::COFF::IMAGE_SCN_MEM_EXECUTE)
90     return true;
91 
92   // .pdata and .xdata unwind info sections are eligible.
93   StringRef outSecName = c->getSectionName().split('$').first;
94   if (outSecName == ".pdata" || outSecName == ".xdata")
95     return true;
96 
97   // So are vtables.
98   if (c->sym && c->sym->getName().startswith("??_7"))
99     return true;
100 
101   // Anything else not in an address-significance table is eligible.
102   return !c->keepUnique;
103 }
104 
105 // Split an equivalence class into smaller classes.
106 void ICF::segregate(size_t begin, size_t end, bool constant) {
107   while (begin < end) {
108     // Divide [Begin, End) into two. Let Mid be the start index of the
109     // second group.
110     auto bound = std::stable_partition(
111         chunks.begin() + begin + 1, chunks.begin() + end, [&](SectionChunk *s) {
112           if (constant)
113             return equalsConstant(chunks[begin], s);
114           return equalsVariable(chunks[begin], s);
115         });
116     size_t mid = bound - chunks.begin();
117 
118     // Split [Begin, End) into [Begin, Mid) and [Mid, End). We use Mid as an
119     // equivalence class ID because every group ends with a unique index.
120     for (size_t i = begin; i < mid; ++i)
121       chunks[i]->eqClass[(cnt + 1) % 2] = mid;
122 
123     // If we created a group, we need to iterate the main loop again.
124     if (mid != end)
125       repeat = true;
126 
127     begin = mid;
128   }
129 }
130 
131 // Returns true if two sections' associative children are equal.
132 bool ICF::assocEquals(const SectionChunk *a, const SectionChunk *b) {
133   // Ignore associated metadata sections that don't participate in ICF, such as
134   // debug info and CFGuard metadata.
135   auto considerForICF = [](const SectionChunk &assoc) {
136     StringRef Name = assoc.getSectionName();
137     return !(Name.startswith(".debug") || Name == ".gfids$y" ||
138              Name == ".giats$y" || Name == ".gljmp$y");
139   };
140   auto ra = make_filter_range(a->children(), considerForICF);
141   auto rb = make_filter_range(b->children(), considerForICF);
142   return std::equal(ra.begin(), ra.end(), rb.begin(), rb.end(),
143                     [&](const SectionChunk &ia, const SectionChunk &ib) {
144                       return ia.eqClass[cnt % 2] == ib.eqClass[cnt % 2];
145                     });
146 }
147 
148 // Compare "non-moving" part of two sections, namely everything
149 // except relocation targets.
150 bool ICF::equalsConstant(const SectionChunk *a, const SectionChunk *b) {
151   if (a->relocsSize != b->relocsSize)
152     return false;
153 
154   // Compare relocations.
155   auto eq = [&](const coff_relocation &r1, const coff_relocation &r2) {
156     if (r1.Type != r2.Type ||
157         r1.VirtualAddress != r2.VirtualAddress) {
158       return false;
159     }
160     Symbol *b1 = a->file->getSymbol(r1.SymbolTableIndex);
161     Symbol *b2 = b->file->getSymbol(r2.SymbolTableIndex);
162     if (b1 == b2)
163       return true;
164     if (auto *d1 = dyn_cast<DefinedRegular>(b1))
165       if (auto *d2 = dyn_cast<DefinedRegular>(b2))
166         return d1->getValue() == d2->getValue() &&
167                d1->getChunk()->eqClass[cnt % 2] == d2->getChunk()->eqClass[cnt % 2];
168     return false;
169   };
170   if (!std::equal(a->getRelocs().begin(), a->getRelocs().end(),
171                   b->getRelocs().begin(), eq))
172     return false;
173 
174   // Compare section attributes and contents.
175   return a->getOutputCharacteristics() == b->getOutputCharacteristics() &&
176          a->getSectionName() == b->getSectionName() &&
177          a->header->SizeOfRawData == b->header->SizeOfRawData &&
178          a->checksum == b->checksum && a->getContents() == b->getContents() &&
179          assocEquals(a, b);
180 }
181 
182 // Compare "moving" part of two sections, namely relocation targets.
183 bool ICF::equalsVariable(const SectionChunk *a, const SectionChunk *b) {
184   // Compare relocations.
185   auto eq = [&](const coff_relocation &r1, const coff_relocation &r2) {
186     Symbol *b1 = a->file->getSymbol(r1.SymbolTableIndex);
187     Symbol *b2 = b->file->getSymbol(r2.SymbolTableIndex);
188     if (b1 == b2)
189       return true;
190     if (auto *d1 = dyn_cast<DefinedRegular>(b1))
191       if (auto *d2 = dyn_cast<DefinedRegular>(b2))
192         return d1->getChunk()->eqClass[cnt % 2] == d2->getChunk()->eqClass[cnt % 2];
193     return false;
194   };
195   return std::equal(a->getRelocs().begin(), a->getRelocs().end(),
196                     b->getRelocs().begin(), eq) &&
197          assocEquals(a, b);
198 }
199 
200 // Find the first Chunk after Begin that has a different class from Begin.
201 size_t ICF::findBoundary(size_t begin, size_t end) {
202   for (size_t i = begin + 1; i < end; ++i)
203     if (chunks[begin]->eqClass[cnt % 2] != chunks[i]->eqClass[cnt % 2])
204       return i;
205   return end;
206 }
207 
208 void ICF::forEachClassRange(size_t begin, size_t end,
209                             std::function<void(size_t, size_t)> fn) {
210   while (begin < end) {
211     size_t mid = findBoundary(begin, end);
212     fn(begin, mid);
213     begin = mid;
214   }
215 }
216 
217 // Call Fn on each class group.
218 void ICF::forEachClass(std::function<void(size_t, size_t)> fn) {
219   // If the number of sections are too small to use threading,
220   // call Fn sequentially.
221   if (chunks.size() < 1024) {
222     forEachClassRange(0, chunks.size(), fn);
223     ++cnt;
224     return;
225   }
226 
227   // Shard into non-overlapping intervals, and call Fn in parallel.
228   // The sharding must be completed before any calls to Fn are made
229   // so that Fn can modify the Chunks in its shard without causing data
230   // races.
231   const size_t numShards = 256;
232   size_t step = chunks.size() / numShards;
233   size_t boundaries[numShards + 1];
234   boundaries[0] = 0;
235   boundaries[numShards] = chunks.size();
236   parallelFor(1, numShards, [&](size_t i) {
237     boundaries[i] = findBoundary((i - 1) * step, chunks.size());
238   });
239   parallelFor(1, numShards + 1, [&](size_t i) {
240     if (boundaries[i - 1] < boundaries[i]) {
241       forEachClassRange(boundaries[i - 1], boundaries[i], fn);
242     }
243   });
244   ++cnt;
245 }
246 
247 // Merge identical COMDAT sections.
248 // Two sections are considered the same if their section headers,
249 // contents and relocations are all the same.
250 void ICF::run() {
251   ScopedTimer t(ctx.icfTimer);
252 
253   // Collect only mergeable sections and group by hash value.
254   uint32_t nextId = 1;
255   for (Chunk *c : ctx.symtab.getChunks()) {
256     if (auto *sc = dyn_cast<SectionChunk>(c)) {
257       if (isEligible(sc))
258         chunks.push_back(sc);
259       else
260         sc->eqClass[0] = nextId++;
261     }
262   }
263 
264   // Make sure that ICF doesn't merge sections that are being handled by string
265   // tail merging.
266   for (MergeChunk *mc : ctx.mergeChunkInstances)
267     if (mc)
268       for (SectionChunk *sc : mc->sections)
269         sc->eqClass[0] = nextId++;
270 
271   // Initially, we use hash values to partition sections.
272   parallelForEach(chunks, [&](SectionChunk *sc) {
273     sc->eqClass[0] = xxHash64(sc->getContents());
274   });
275 
276   // Combine the hashes of the sections referenced by each section into its
277   // hash.
278   for (unsigned cnt = 0; cnt != 2; ++cnt) {
279     parallelForEach(chunks, [&](SectionChunk *sc) {
280       uint32_t hash = sc->eqClass[cnt % 2];
281       for (Symbol *b : sc->symbols())
282         if (auto *sym = dyn_cast_or_null<DefinedRegular>(b))
283           hash += sym->getChunk()->eqClass[cnt % 2];
284       // Set MSB to 1 to avoid collisions with non-hash classes.
285       sc->eqClass[(cnt + 1) % 2] = hash | (1U << 31);
286     });
287   }
288 
289   // From now on, sections in Chunks are ordered so that sections in
290   // the same group are consecutive in the vector.
291   llvm::stable_sort(chunks, [](const SectionChunk *a, const SectionChunk *b) {
292     return a->eqClass[0] < b->eqClass[0];
293   });
294 
295   // Compare static contents and assign unique IDs for each static content.
296   forEachClass([&](size_t begin, size_t end) { segregate(begin, end, true); });
297 
298   // Split groups by comparing relocations until convergence is obtained.
299   do {
300     repeat = false;
301     forEachClass(
302         [&](size_t begin, size_t end) { segregate(begin, end, false); });
303   } while (repeat);
304 
305   log("ICF needed " + Twine(cnt) + " iterations");
306 
307   // Merge sections in the same classes.
308   forEachClass([&](size_t begin, size_t end) {
309     if (end - begin == 1)
310       return;
311 
312     log("Selected " + chunks[begin]->getDebugName());
313     for (size_t i = begin + 1; i < end; ++i) {
314       log("  Removed " + chunks[i]->getDebugName());
315       chunks[begin]->replace(chunks[i]);
316     }
317   });
318 }
319 
320 // Entry point to ICF.
321 void doICF(COFFLinkerContext &ctx, ICFLevel icfLevel) {
322   ICF(ctx, icfLevel).run();
323 }
324 
325 } // namespace coff
326 } // namespace lld
327