10b57cec5SDimitry Andric //===- ICF.cpp ------------------------------------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // ICF is short for Identical Code Folding. That is a size optimization to 100b57cec5SDimitry Andric // identify and merge two or more read-only sections (typically functions) 110b57cec5SDimitry Andric // that happened to have the same contents. It usually reduces output size 120b57cec5SDimitry Andric // by a few percent. 130b57cec5SDimitry Andric // 140b57cec5SDimitry Andric // On Windows, ICF is enabled by default. 150b57cec5SDimitry Andric // 1685868e8aSDimitry Andric // See ELF/ICF.cpp for the details about the algorithm. 170b57cec5SDimitry Andric // 180b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 190b57cec5SDimitry Andric 200b57cec5SDimitry Andric #include "ICF.h" 21349cc55cSDimitry Andric #include "COFFLinkerContext.h" 220b57cec5SDimitry Andric #include "Chunks.h" 230b57cec5SDimitry Andric #include "Symbols.h" 240b57cec5SDimitry Andric #include "lld/Common/ErrorHandler.h" 250b57cec5SDimitry Andric #include "lld/Common/Timer.h" 260b57cec5SDimitry Andric #include "llvm/ADT/Hashing.h" 270b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 280b57cec5SDimitry Andric #include "llvm/Support/Parallel.h" 295f757f3fSDimitry Andric #include "llvm/Support/TimeProfiler.h" 300b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 310b57cec5SDimitry Andric #include "llvm/Support/xxhash.h" 320b57cec5SDimitry Andric #include <algorithm> 330b57cec5SDimitry Andric #include <atomic> 340b57cec5SDimitry Andric #include <vector> 350b57cec5SDimitry Andric 360b57cec5SDimitry Andric using namespace llvm; 370b57cec5SDimitry Andric 38bdd1243dSDimitry Andric namespace lld::coff { 390b57cec5SDimitry Andric 400b57cec5SDimitry Andric class ICF { 410b57cec5SDimitry Andric public: 42bdd1243dSDimitry Andric ICF(COFFLinkerContext &c) : ctx(c){}; 43349cc55cSDimitry Andric void run(); 440b57cec5SDimitry Andric 450b57cec5SDimitry Andric private: 460b57cec5SDimitry Andric void segregate(size_t begin, size_t end, bool constant); 470b57cec5SDimitry Andric 480b57cec5SDimitry Andric bool assocEquals(const SectionChunk *a, const SectionChunk *b); 490b57cec5SDimitry Andric 500b57cec5SDimitry Andric bool equalsConstant(const SectionChunk *a, const SectionChunk *b); 510b57cec5SDimitry Andric bool equalsVariable(const SectionChunk *a, const SectionChunk *b); 520b57cec5SDimitry Andric 530b57cec5SDimitry Andric bool isEligible(SectionChunk *c); 540b57cec5SDimitry Andric 550b57cec5SDimitry Andric size_t findBoundary(size_t begin, size_t end); 560b57cec5SDimitry Andric 570b57cec5SDimitry Andric void forEachClassRange(size_t begin, size_t end, 580b57cec5SDimitry Andric std::function<void(size_t, size_t)> fn); 590b57cec5SDimitry Andric 600b57cec5SDimitry Andric void forEachClass(std::function<void(size_t, size_t)> fn); 610b57cec5SDimitry Andric 620b57cec5SDimitry Andric std::vector<SectionChunk *> chunks; 630b57cec5SDimitry Andric int cnt = 0; 640b57cec5SDimitry Andric std::atomic<bool> repeat = {false}; 65349cc55cSDimitry Andric 66349cc55cSDimitry Andric COFFLinkerContext &ctx; 670b57cec5SDimitry Andric }; 680b57cec5SDimitry Andric 690b57cec5SDimitry Andric // Returns true if section S is subject of ICF. 700b57cec5SDimitry Andric // 710b57cec5SDimitry Andric // Microsoft's documentation 720b57cec5SDimitry Andric // (https://msdn.microsoft.com/en-us/library/bxwfs976.aspx; visited April 730b57cec5SDimitry Andric // 2017) says that /opt:icf folds both functions and read-only data. 740b57cec5SDimitry Andric // Despite that, the MSVC linker folds only functions. We found 750b57cec5SDimitry Andric // a few instances of programs that are not safe for data merging. 760b57cec5SDimitry Andric // Therefore, we merge only functions just like the MSVC tool. However, we also 770b57cec5SDimitry Andric // merge read-only sections in a couple of cases where the address of the 780b57cec5SDimitry Andric // section is insignificant to the user program and the behaviour matches that 790b57cec5SDimitry Andric // of the Visual C++ linker. 800b57cec5SDimitry Andric bool ICF::isEligible(SectionChunk *c) { 8185868e8aSDimitry Andric // Non-comdat chunks, dead chunks, and writable chunks are not eligible. 820b57cec5SDimitry Andric bool writable = c->getOutputCharacteristics() & llvm::COFF::IMAGE_SCN_MEM_WRITE; 830b57cec5SDimitry Andric if (!c->isCOMDAT() || !c->live || writable) 840b57cec5SDimitry Andric return false; 850b57cec5SDimitry Andric 86fe6060f1SDimitry Andric // Under regular (not safe) ICF, all code sections are eligible. 87bdd1243dSDimitry Andric if ((ctx.config.doICF == ICFLevel::All) && 88fe6060f1SDimitry Andric c->getOutputCharacteristics() & llvm::COFF::IMAGE_SCN_MEM_EXECUTE) 890b57cec5SDimitry Andric return true; 900b57cec5SDimitry Andric 910b57cec5SDimitry Andric // .pdata and .xdata unwind info sections are eligible. 920b57cec5SDimitry Andric StringRef outSecName = c->getSectionName().split('$').first; 930b57cec5SDimitry Andric if (outSecName == ".pdata" || outSecName == ".xdata") 940b57cec5SDimitry Andric return true; 950b57cec5SDimitry Andric 960b57cec5SDimitry Andric // So are vtables. 975f757f3fSDimitry Andric const char *itaniumVtablePrefix = 985f757f3fSDimitry Andric ctx.config.machine == I386 ? "__ZTV" : "_ZTV"; 995f757f3fSDimitry Andric if (c->sym && (c->sym->getName().starts_with("??_7") || 1005f757f3fSDimitry Andric c->sym->getName().starts_with(itaniumVtablePrefix))) 1010b57cec5SDimitry Andric return true; 1020b57cec5SDimitry Andric 1030b57cec5SDimitry Andric // Anything else not in an address-significance table is eligible. 1040b57cec5SDimitry Andric return !c->keepUnique; 1050b57cec5SDimitry Andric } 1060b57cec5SDimitry Andric 1070b57cec5SDimitry Andric // Split an equivalence class into smaller classes. 1080b57cec5SDimitry Andric void ICF::segregate(size_t begin, size_t end, bool constant) { 1090b57cec5SDimitry Andric while (begin < end) { 1100b57cec5SDimitry Andric // Divide [Begin, End) into two. Let Mid be the start index of the 1110b57cec5SDimitry Andric // second group. 1120b57cec5SDimitry Andric auto bound = std::stable_partition( 1130b57cec5SDimitry Andric chunks.begin() + begin + 1, chunks.begin() + end, [&](SectionChunk *s) { 1140b57cec5SDimitry Andric if (constant) 1150b57cec5SDimitry Andric return equalsConstant(chunks[begin], s); 1160b57cec5SDimitry Andric return equalsVariable(chunks[begin], s); 1170b57cec5SDimitry Andric }); 1180b57cec5SDimitry Andric size_t mid = bound - chunks.begin(); 1190b57cec5SDimitry Andric 1200b57cec5SDimitry Andric // Split [Begin, End) into [Begin, Mid) and [Mid, End). We use Mid as an 1210b57cec5SDimitry Andric // equivalence class ID because every group ends with a unique index. 1220b57cec5SDimitry Andric for (size_t i = begin; i < mid; ++i) 1230b57cec5SDimitry Andric chunks[i]->eqClass[(cnt + 1) % 2] = mid; 1240b57cec5SDimitry Andric 1250b57cec5SDimitry Andric // If we created a group, we need to iterate the main loop again. 1260b57cec5SDimitry Andric if (mid != end) 1270b57cec5SDimitry Andric repeat = true; 1280b57cec5SDimitry Andric 1290b57cec5SDimitry Andric begin = mid; 1300b57cec5SDimitry Andric } 1310b57cec5SDimitry Andric } 1320b57cec5SDimitry Andric 1330b57cec5SDimitry Andric // Returns true if two sections' associative children are equal. 1340b57cec5SDimitry Andric bool ICF::assocEquals(const SectionChunk *a, const SectionChunk *b) { 1355ffd83dbSDimitry Andric // Ignore associated metadata sections that don't participate in ICF, such as 1365ffd83dbSDimitry Andric // debug info and CFGuard metadata. 1375ffd83dbSDimitry Andric auto considerForICF = [](const SectionChunk &assoc) { 1385ffd83dbSDimitry Andric StringRef Name = assoc.getSectionName(); 13906c3fb27SDimitry Andric return !(Name.starts_with(".debug") || Name == ".gfids$y" || 140e8d8bef9SDimitry Andric Name == ".giats$y" || Name == ".gljmp$y"); 1410b57cec5SDimitry Andric }; 1425ffd83dbSDimitry Andric auto ra = make_filter_range(a->children(), considerForICF); 1435ffd83dbSDimitry Andric auto rb = make_filter_range(b->children(), considerForICF); 1445ffd83dbSDimitry Andric return std::equal(ra.begin(), ra.end(), rb.begin(), rb.end(), 1455ffd83dbSDimitry Andric [&](const SectionChunk &ia, const SectionChunk &ib) { 1465ffd83dbSDimitry Andric return ia.eqClass[cnt % 2] == ib.eqClass[cnt % 2]; 1475ffd83dbSDimitry Andric }); 1480b57cec5SDimitry Andric } 1490b57cec5SDimitry Andric 1500b57cec5SDimitry Andric // Compare "non-moving" part of two sections, namely everything 1510b57cec5SDimitry Andric // except relocation targets. 1520b57cec5SDimitry Andric bool ICF::equalsConstant(const SectionChunk *a, const SectionChunk *b) { 1530b57cec5SDimitry Andric if (a->relocsSize != b->relocsSize) 1540b57cec5SDimitry Andric return false; 1550b57cec5SDimitry Andric 1560b57cec5SDimitry Andric // Compare relocations. 1570b57cec5SDimitry Andric auto eq = [&](const coff_relocation &r1, const coff_relocation &r2) { 1580b57cec5SDimitry Andric if (r1.Type != r2.Type || 1590b57cec5SDimitry Andric r1.VirtualAddress != r2.VirtualAddress) { 1600b57cec5SDimitry Andric return false; 1610b57cec5SDimitry Andric } 1620b57cec5SDimitry Andric Symbol *b1 = a->file->getSymbol(r1.SymbolTableIndex); 1630b57cec5SDimitry Andric Symbol *b2 = b->file->getSymbol(r2.SymbolTableIndex); 1640b57cec5SDimitry Andric if (b1 == b2) 1650b57cec5SDimitry Andric return true; 1660b57cec5SDimitry Andric if (auto *d1 = dyn_cast<DefinedRegular>(b1)) 1670b57cec5SDimitry Andric if (auto *d2 = dyn_cast<DefinedRegular>(b2)) 1680b57cec5SDimitry Andric return d1->getValue() == d2->getValue() && 1690b57cec5SDimitry Andric d1->getChunk()->eqClass[cnt % 2] == d2->getChunk()->eqClass[cnt % 2]; 1700b57cec5SDimitry Andric return false; 1710b57cec5SDimitry Andric }; 1720b57cec5SDimitry Andric if (!std::equal(a->getRelocs().begin(), a->getRelocs().end(), 1730b57cec5SDimitry Andric b->getRelocs().begin(), eq)) 1740b57cec5SDimitry Andric return false; 1750b57cec5SDimitry Andric 1760b57cec5SDimitry Andric // Compare section attributes and contents. 1770b57cec5SDimitry Andric return a->getOutputCharacteristics() == b->getOutputCharacteristics() && 1780b57cec5SDimitry Andric a->getSectionName() == b->getSectionName() && 1790b57cec5SDimitry Andric a->header->SizeOfRawData == b->header->SizeOfRawData && 1800b57cec5SDimitry Andric a->checksum == b->checksum && a->getContents() == b->getContents() && 181*0fca6ea1SDimitry Andric a->getMachine() == b->getMachine() && assocEquals(a, b); 1820b57cec5SDimitry Andric } 1830b57cec5SDimitry Andric 1840b57cec5SDimitry Andric // Compare "moving" part of two sections, namely relocation targets. 1850b57cec5SDimitry Andric bool ICF::equalsVariable(const SectionChunk *a, const SectionChunk *b) { 1860b57cec5SDimitry Andric // Compare relocations. 187*0fca6ea1SDimitry Andric auto eqSym = [&](Symbol *b1, Symbol *b2) { 1880b57cec5SDimitry Andric if (b1 == b2) 1890b57cec5SDimitry Andric return true; 1900b57cec5SDimitry Andric if (auto *d1 = dyn_cast<DefinedRegular>(b1)) 1910b57cec5SDimitry Andric if (auto *d2 = dyn_cast<DefinedRegular>(b2)) 1920b57cec5SDimitry Andric return d1->getChunk()->eqClass[cnt % 2] == d2->getChunk()->eqClass[cnt % 2]; 1930b57cec5SDimitry Andric return false; 1940b57cec5SDimitry Andric }; 195*0fca6ea1SDimitry Andric auto eq = [&](const coff_relocation &r1, const coff_relocation &r2) { 196*0fca6ea1SDimitry Andric Symbol *b1 = a->file->getSymbol(r1.SymbolTableIndex); 197*0fca6ea1SDimitry Andric Symbol *b2 = b->file->getSymbol(r2.SymbolTableIndex); 198*0fca6ea1SDimitry Andric return eqSym(b1, b2); 199*0fca6ea1SDimitry Andric }; 200*0fca6ea1SDimitry Andric 201*0fca6ea1SDimitry Andric Symbol *e1 = a->getEntryThunk(); 202*0fca6ea1SDimitry Andric Symbol *e2 = b->getEntryThunk(); 203*0fca6ea1SDimitry Andric if ((e1 || e2) && (!e1 || !e2 || !eqSym(e1, e2))) 204*0fca6ea1SDimitry Andric return false; 205*0fca6ea1SDimitry Andric 2060b57cec5SDimitry Andric return std::equal(a->getRelocs().begin(), a->getRelocs().end(), 2070b57cec5SDimitry Andric b->getRelocs().begin(), eq) && 2080b57cec5SDimitry Andric assocEquals(a, b); 2090b57cec5SDimitry Andric } 2100b57cec5SDimitry Andric 2110b57cec5SDimitry Andric // Find the first Chunk after Begin that has a different class from Begin. 2120b57cec5SDimitry Andric size_t ICF::findBoundary(size_t begin, size_t end) { 2130b57cec5SDimitry Andric for (size_t i = begin + 1; i < end; ++i) 2140b57cec5SDimitry Andric if (chunks[begin]->eqClass[cnt % 2] != chunks[i]->eqClass[cnt % 2]) 2150b57cec5SDimitry Andric return i; 2160b57cec5SDimitry Andric return end; 2170b57cec5SDimitry Andric } 2180b57cec5SDimitry Andric 2190b57cec5SDimitry Andric void ICF::forEachClassRange(size_t begin, size_t end, 2200b57cec5SDimitry Andric std::function<void(size_t, size_t)> fn) { 2210b57cec5SDimitry Andric while (begin < end) { 2220b57cec5SDimitry Andric size_t mid = findBoundary(begin, end); 2230b57cec5SDimitry Andric fn(begin, mid); 2240b57cec5SDimitry Andric begin = mid; 2250b57cec5SDimitry Andric } 2260b57cec5SDimitry Andric } 2270b57cec5SDimitry Andric 2280b57cec5SDimitry Andric // Call Fn on each class group. 2290b57cec5SDimitry Andric void ICF::forEachClass(std::function<void(size_t, size_t)> fn) { 2300b57cec5SDimitry Andric // If the number of sections are too small to use threading, 2310b57cec5SDimitry Andric // call Fn sequentially. 2320b57cec5SDimitry Andric if (chunks.size() < 1024) { 2330b57cec5SDimitry Andric forEachClassRange(0, chunks.size(), fn); 2340b57cec5SDimitry Andric ++cnt; 2350b57cec5SDimitry Andric return; 2360b57cec5SDimitry Andric } 2370b57cec5SDimitry Andric 2380b57cec5SDimitry Andric // Shard into non-overlapping intervals, and call Fn in parallel. 2390b57cec5SDimitry Andric // The sharding must be completed before any calls to Fn are made 2400b57cec5SDimitry Andric // so that Fn can modify the Chunks in its shard without causing data 2410b57cec5SDimitry Andric // races. 2420b57cec5SDimitry Andric const size_t numShards = 256; 2430b57cec5SDimitry Andric size_t step = chunks.size() / numShards; 2440b57cec5SDimitry Andric size_t boundaries[numShards + 1]; 2450b57cec5SDimitry Andric boundaries[0] = 0; 2460b57cec5SDimitry Andric boundaries[numShards] = chunks.size(); 24781ad6265SDimitry Andric parallelFor(1, numShards, [&](size_t i) { 2480b57cec5SDimitry Andric boundaries[i] = findBoundary((i - 1) * step, chunks.size()); 2490b57cec5SDimitry Andric }); 25081ad6265SDimitry Andric parallelFor(1, numShards + 1, [&](size_t i) { 2510b57cec5SDimitry Andric if (boundaries[i - 1] < boundaries[i]) { 2520b57cec5SDimitry Andric forEachClassRange(boundaries[i - 1], boundaries[i], fn); 2530b57cec5SDimitry Andric } 2540b57cec5SDimitry Andric }); 2550b57cec5SDimitry Andric ++cnt; 2560b57cec5SDimitry Andric } 2570b57cec5SDimitry Andric 2580b57cec5SDimitry Andric // Merge identical COMDAT sections. 2590b57cec5SDimitry Andric // Two sections are considered the same if their section headers, 2600b57cec5SDimitry Andric // contents and relocations are all the same. 261349cc55cSDimitry Andric void ICF::run() { 2625f757f3fSDimitry Andric llvm::TimeTraceScope timeScope("ICF"); 263349cc55cSDimitry Andric ScopedTimer t(ctx.icfTimer); 2640b57cec5SDimitry Andric 2650b57cec5SDimitry Andric // Collect only mergeable sections and group by hash value. 2660b57cec5SDimitry Andric uint32_t nextId = 1; 267349cc55cSDimitry Andric for (Chunk *c : ctx.symtab.getChunks()) { 2680b57cec5SDimitry Andric if (auto *sc = dyn_cast<SectionChunk>(c)) { 2690b57cec5SDimitry Andric if (isEligible(sc)) 2700b57cec5SDimitry Andric chunks.push_back(sc); 2710b57cec5SDimitry Andric else 2720b57cec5SDimitry Andric sc->eqClass[0] = nextId++; 2730b57cec5SDimitry Andric } 2740b57cec5SDimitry Andric } 2750b57cec5SDimitry Andric 2760b57cec5SDimitry Andric // Make sure that ICF doesn't merge sections that are being handled by string 2770b57cec5SDimitry Andric // tail merging. 278349cc55cSDimitry Andric for (MergeChunk *mc : ctx.mergeChunkInstances) 2790b57cec5SDimitry Andric if (mc) 2800b57cec5SDimitry Andric for (SectionChunk *sc : mc->sections) 2810b57cec5SDimitry Andric sc->eqClass[0] = nextId++; 2820b57cec5SDimitry Andric 2830b57cec5SDimitry Andric // Initially, we use hash values to partition sections. 2840b57cec5SDimitry Andric parallelForEach(chunks, [&](SectionChunk *sc) { 28506c3fb27SDimitry Andric sc->eqClass[0] = xxh3_64bits(sc->getContents()); 2860b57cec5SDimitry Andric }); 2870b57cec5SDimitry Andric 2880b57cec5SDimitry Andric // Combine the hashes of the sections referenced by each section into its 2890b57cec5SDimitry Andric // hash. 2900b57cec5SDimitry Andric for (unsigned cnt = 0; cnt != 2; ++cnt) { 2910b57cec5SDimitry Andric parallelForEach(chunks, [&](SectionChunk *sc) { 2920b57cec5SDimitry Andric uint32_t hash = sc->eqClass[cnt % 2]; 2930b57cec5SDimitry Andric for (Symbol *b : sc->symbols()) 2940b57cec5SDimitry Andric if (auto *sym = dyn_cast_or_null<DefinedRegular>(b)) 2950b57cec5SDimitry Andric hash += sym->getChunk()->eqClass[cnt % 2]; 29685868e8aSDimitry Andric // Set MSB to 1 to avoid collisions with non-hash classes. 2970b57cec5SDimitry Andric sc->eqClass[(cnt + 1) % 2] = hash | (1U << 31); 2980b57cec5SDimitry Andric }); 2990b57cec5SDimitry Andric } 3000b57cec5SDimitry Andric 3010b57cec5SDimitry Andric // From now on, sections in Chunks are ordered so that sections in 3020b57cec5SDimitry Andric // the same group are consecutive in the vector. 3030b57cec5SDimitry Andric llvm::stable_sort(chunks, [](const SectionChunk *a, const SectionChunk *b) { 3040b57cec5SDimitry Andric return a->eqClass[0] < b->eqClass[0]; 3050b57cec5SDimitry Andric }); 3060b57cec5SDimitry Andric 3070b57cec5SDimitry Andric // Compare static contents and assign unique IDs for each static content. 3080b57cec5SDimitry Andric forEachClass([&](size_t begin, size_t end) { segregate(begin, end, true); }); 3090b57cec5SDimitry Andric 3100b57cec5SDimitry Andric // Split groups by comparing relocations until convergence is obtained. 3110b57cec5SDimitry Andric do { 3120b57cec5SDimitry Andric repeat = false; 3130b57cec5SDimitry Andric forEachClass( 3140b57cec5SDimitry Andric [&](size_t begin, size_t end) { segregate(begin, end, false); }); 3150b57cec5SDimitry Andric } while (repeat); 3160b57cec5SDimitry Andric 3170b57cec5SDimitry Andric log("ICF needed " + Twine(cnt) + " iterations"); 3180b57cec5SDimitry Andric 31985868e8aSDimitry Andric // Merge sections in the same classes. 3200b57cec5SDimitry Andric forEachClass([&](size_t begin, size_t end) { 3210b57cec5SDimitry Andric if (end - begin == 1) 3220b57cec5SDimitry Andric return; 3230b57cec5SDimitry Andric 3240b57cec5SDimitry Andric log("Selected " + chunks[begin]->getDebugName()); 3250b57cec5SDimitry Andric for (size_t i = begin + 1; i < end; ++i) { 3260b57cec5SDimitry Andric log(" Removed " + chunks[i]->getDebugName()); 3270b57cec5SDimitry Andric chunks[begin]->replace(chunks[i]); 3280b57cec5SDimitry Andric } 3290b57cec5SDimitry Andric }); 3300b57cec5SDimitry Andric } 3310b57cec5SDimitry Andric 3320b57cec5SDimitry Andric // Entry point to ICF. 333bdd1243dSDimitry Andric void doICF(COFFLinkerContext &ctx) { ICF(ctx).run(); } 3340b57cec5SDimitry Andric 335bdd1243dSDimitry Andric } // namespace lld::coff 336