xref: /llvm-project-15.0.7/lld/COFF/ICF.cpp (revision 8692a4d1)
1 //===- ICF.cpp ------------------------------------------------------------===//
2 //
3 //                             The LLVM Linker
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // Implements ICF (Identical COMDAT Folding)
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "Chunks.h"
15 #include <tuple>
16 #include <unordered_set>
17 #include <vector>
18 
19 namespace lld {
20 namespace coff {
21 namespace {
22 
23 struct Hasher {
24   size_t operator()(const SectionChunk *C) const { return C->getHash(); }
25 };
26 
27 struct Equals {
28   bool operator()(const SectionChunk *A, const SectionChunk *B) const {
29     return A->equals(B);
30   }
31 };
32 
33 } // anonymous namespace
34 
35 // Merge identical COMDAT sections.
36 // Two sections are considered as identical when their section headers,
37 // contents and relocations are all the same.
38 void doICF(const std::vector<Chunk *> &Chunks) {
39   std::unordered_set<SectionChunk *, Hasher, Equals> Set;
40   bool Redo;
41   do {
42     Set.clear();
43     Redo = false;
44     for (Chunk *C : Chunks) {
45       auto *SC = dyn_cast<SectionChunk>(C);
46       if (!SC || !SC->isCOMDAT() || !SC->isLive())
47         continue;
48       auto P = Set.insert(SC);
49       bool Inserted = P.second;
50       if (Inserted)
51         continue;
52       SectionChunk *Existing = *P.first;
53       SC->replaceWith(Existing);
54       // By merging sections, two relocations that originally pointed to
55       // different locations can now point to the same location.
56       // So, repeat the process until a convegence is obtained.
57       Redo = true;
58     }
59   } while (Redo);
60 }
61 
62 } // namespace coff
63 } // namespace lld
64