Path: blob/main/contrib/llvm-project/lld/ELF/BPSectionOrderer.cpp
213726 views
//===- BPSectionOrderer.cpp -----------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "BPSectionOrderer.h"9#include "InputFiles.h"10#include "InputSection.h"11#include "SymbolTable.h"12#include "Symbols.h"13#include "lld/Common/BPSectionOrdererBase.inc"14#include "llvm/Support/Endian.h"1516using namespace llvm;17using namespace lld::elf;1819namespace {20struct BPOrdererELF;21}22template <> struct lld::BPOrdererTraits<struct BPOrdererELF> {23using Section = elf::InputSectionBase;24using Defined = elf::Defined;25};26namespace {27struct BPOrdererELF : lld::BPOrderer<BPOrdererELF> {28DenseMap<const InputSectionBase *, Defined *> secToSym;2930static uint64_t getSize(const Section &sec) { return sec.getSize(); }31static bool isCodeSection(const Section &sec) {32return sec.flags & ELF::SHF_EXECINSTR;33}34ArrayRef<Defined *> getSymbols(const Section &sec) {35auto it = secToSym.find(&sec);36if (it == secToSym.end())37return {};38return ArrayRef(it->second);39}4041static void42getSectionHashes(const Section &sec, SmallVectorImpl<uint64_t> &hashes,43const DenseMap<const void *, uint64_t> §ionToIdx) {44constexpr unsigned windowSize = 4;4546// Calculate content hashes: k-mers and the last k-1 bytes.47ArrayRef<uint8_t> data = sec.content();48if (data.size() >= windowSize)49for (size_t i = 0; i <= data.size() - windowSize; ++i)50hashes.push_back(support::endian::read32le(data.data() + i));51for (uint8_t byte : data.take_back(windowSize - 1))52hashes.push_back(byte);5354llvm::sort(hashes);55hashes.erase(llvm::unique(hashes), hashes.end());56}5758static StringRef getSymName(const Defined &sym) { return sym.getName(); }59static uint64_t getSymValue(const Defined &sym) { return sym.value; }60static uint64_t getSymSize(const Defined &sym) { return sym.size; }61};62} // namespace6364DenseMap<const InputSectionBase *, int> elf::runBalancedPartitioning(65Ctx &ctx, StringRef profilePath, bool forFunctionCompression,66bool forDataCompression, bool compressionSortStartupFunctions,67bool verbose) {68// Collect candidate sections and associated symbols.69SmallVector<InputSectionBase *> sections;70DenseMap<CachedHashStringRef, std::set<unsigned>> rootSymbolToSectionIdxs;71BPOrdererELF orderer;7273auto addSection = [&](Symbol &sym) {74auto *d = dyn_cast<Defined>(&sym);75if (!d)76return;77auto *sec = dyn_cast_or_null<InputSection>(d->section);78// Skip empty, discarded, ICF folded sections. Skipping ICF folded sections79// reduces duplicate detection work in BPSectionOrderer.80if (!sec || sec->size == 0 || !sec->isLive() || sec->repl != sec ||81!orderer.secToSym.try_emplace(sec, d).second)82return;83rootSymbolToSectionIdxs[CachedHashStringRef(84lld::utils::getRootSymbol(sym.getName()))]85.insert(sections.size());86sections.emplace_back(sec);87};8889for (Symbol *sym : ctx.symtab->getSymbols())90addSection(*sym);91for (ELFFileBase *file : ctx.objectFiles)92for (Symbol *sym : file->getLocalSymbols())93addSection(*sym);94return orderer.computeOrder(profilePath, forFunctionCompression,95forDataCompression,96compressionSortStartupFunctions, verbose,97sections, rootSymbolToSectionIdxs);98}99100101