diff --git a/lld/Common/CMakeLists.txt b/lld/Common/CMakeLists.txt index 43e91b85821d..4f503d04f784 100644 --- a/lld/Common/CMakeLists.txt +++ b/lld/Common/CMakeLists.txt @@ -24,7 +24,6 @@ set_source_files_properties("${version_inc}" add_lld_library(lldCommon Args.cpp - BPSectionOrdererBase.cpp CommonLinkerContext.cpp DriverDispatcher.cpp DWARF.cpp @@ -48,7 +47,6 @@ add_lld_library(lldCommon Demangle MC Option - ProfileData Support Target TargetParser diff --git a/lld/MachO/BPSectionOrderer.cpp b/lld/MachO/BPSectionOrderer.cpp index c2d03c968534..e2f7a387deeb 100644 --- a/lld/MachO/BPSectionOrderer.cpp +++ b/lld/MachO/BPSectionOrderer.cpp @@ -8,39 +8,141 @@ #include "BPSectionOrderer.h" #include "InputSection.h" +#include "Relocations.h" +#include "Symbols.h" +#include "lld/Common/BPSectionOrdererBase.inc" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/StableHashing.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/xxhash.h" #define DEBUG_TYPE "bp-section-orderer" using namespace llvm; using namespace lld::macho; +namespace { +struct BPOrdererMachO; +} +template <> struct lld::BPOrdererTraits<struct BPOrdererMachO> { + using Section = macho::InputSection; + using Symbol = macho::Symbol; +}; +namespace { +struct BPOrdererMachO : lld::BPOrderer<BPOrdererMachO> { + static uint64_t getSize(const Section &sec) { return sec.getSize(); } + static bool isCodeSection(const Section &sec) { + return macho::isCodeSection(&sec); + } + static SmallVector<Symbol *, 0> getSymbols(const Section &sec) { + SmallVector<Symbol *, 0> symbols; + for (auto *sym : sec.symbols) + if (auto *d = llvm::dyn_cast_or_null<Defined>(sym)) + symbols.emplace_back(d); + return symbols; + } + + // Linkage names can be prefixed with "_" or "l_" on Mach-O. See + // Mangler::getNameWithPrefix() for details. + std::optional<StringRef> static getResolvedLinkageName(llvm::StringRef name) { + if (name.consume_front("_") || name.consume_front("l_")) + return name; + return {}; + } + + static void + getSectionHashes(const Section &sec, llvm::SmallVectorImpl<uint64_t> &hashes, + const llvm::DenseMap<const void *, uint64_t> §ionToIdx) { + constexpr unsigned windowSize = 4; + + // Calculate content hashes: k-mers and the last k-1 bytes. + ArrayRef<uint8_t> data = sec.data; + if (data.size() >= windowSize) + for (size_t i = 0; i <= data.size() - windowSize; ++i) + hashes.push_back(llvm::support::endian::read32le(data.data() + i)); + for (uint8_t byte : data.take_back(windowSize - 1)) + hashes.push_back(byte); + + // Calculate relocation hashes + for (const auto &r : sec.relocs) { + if (r.length == 0 || r.referent.isNull() || r.offset >= data.size()) + continue; + + uint64_t relocHash = getRelocHash(r, sectionToIdx); + uint32_t start = (r.offset < windowSize) ? 0 : r.offset - windowSize + 1; + for (uint32_t i = start; i < r.offset + r.length; i++) { + auto window = data.drop_front(i).take_front(windowSize); + hashes.push_back(xxh3_64bits(window) ^ relocHash); + } + } + + llvm::sort(hashes); + hashes.erase(std::unique(hashes.begin(), hashes.end()), hashes.end()); + } + + static llvm::StringRef getSymName(const Symbol &sym) { return sym.getName(); } + static uint64_t getSymValue(const Symbol &sym) { + if (auto *d = dyn_cast<Defined>(&sym)) + return d->value; + return 0; + } + static uint64_t getSymSize(const Symbol &sym) { + if (auto *d = dyn_cast<Defined>(&sym)) + return d->size; + return 0; + } + +private: + static uint64_t + getRelocHash(const Reloc &reloc, + const llvm::DenseMap<const void *, uint64_t> §ionToIdx) { + auto *isec = reloc.getReferentInputSection(); + std::optional<uint64_t> sectionIdx; + if (auto it = sectionToIdx.find(isec); it != sectionToIdx.end()) + sectionIdx = it->second; + uint64_t kind = -1, value = 0; + if (isec) + kind = uint64_t(isec->kind()); + + if (auto *sym = reloc.referent.dyn_cast<Symbol *>()) { + kind = (kind << 8) | uint8_t(sym->kind()); + if (auto *d = llvm::dyn_cast<Defined>(sym)) + value = d->value; + } + return llvm::stable_hash_combine(kind, sectionIdx.value_or(0), value, + reloc.addend); + } +}; +} // namespace + DenseMap<const InputSection *, int> lld::macho::runBalancedPartitioning( StringRef profilePath, bool forFunctionCompression, bool forDataCompression, bool compressionSortStartupFunctions, bool verbose) { - - SmallVector<std::unique_ptr<BPSectionBase>> sections; + // Collect candidate sections and associated symbols. + SmallVector<InputSection *> sections; + DenseMap<CachedHashStringRef, DenseSet<unsigned>> rootSymbolToSectionIdxs; for (const auto *file : inputFiles) { for (auto *sec : file->sections) { for (auto &subsec : sec->subsections) { auto *isec = subsec.isec; - if (!isec || isec->data.empty() || !isec->data.data()) + if (!isec || isec->data.empty()) continue; - sections.emplace_back(std::make_unique<BPSectionMacho>(isec)); + size_t idx = sections.size(); + sections.emplace_back(isec); + for (auto *sym : BPOrdererMachO::getSymbols(*isec)) { + auto rootName = getRootSymbol(sym->getName()); + rootSymbolToSectionIdxs[CachedHashStringRef(rootName)].insert(idx); + if (auto linkageName = + BPOrdererMachO::getResolvedLinkageName(rootName)) + rootSymbolToSectionIdxs[CachedHashStringRef(*linkageName)].insert( + idx); + } } } } - auto reorderedSections = BPSectionBase::reorderSectionsByBalancedPartitioning( - profilePath, forFunctionCompression, forDataCompression, - compressionSortStartupFunctions, verbose, sections); - - DenseMap<const InputSection *, int> result; - for (const auto &[sec, priority] : reorderedSections) { - result.try_emplace( - static_cast<const InputSection *>( - static_cast<const BPSectionMacho *>(sec)->getSection()), - priority); - } - return result; + return BPOrdererMachO::computeOrder(profilePath, forFunctionCompression, + forDataCompression, + compressionSortStartupFunctions, verbose, + sections, rootSymbolToSectionIdxs); } diff --git a/lld/MachO/BPSectionOrderer.h b/lld/MachO/BPSectionOrderer.h index e3e6b12092e2..a27f605cb118 100644 --- a/lld/MachO/BPSectionOrderer.h +++ b/lld/MachO/BPSectionOrderer.h @@ -14,134 +14,18 @@ #ifndef LLD_MACHO_BPSECTION_ORDERER_H #define LLD_MACHO_BPSECTION_ORDERER_H -#include "InputSection.h" -#include "Relocations.h" -#include "Symbols.h" -#include "lld/Common/BPSectionOrdererBase.h" #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/StableHashing.h" #include "llvm/ADT/StringRef.h" -#include "llvm/Support/Endian.h" -#include "llvm/Support/xxhash.h" namespace lld::macho { - class InputSection; -class BPSymbolMacho : public BPSymbol { - const Symbol *sym; - -public: - explicit BPSymbolMacho(const Symbol *s) : sym(s) {} - - llvm::StringRef getName() const override { return sym->getName(); } - - const Defined *asDefined() const { - return llvm::dyn_cast_or_null<Defined>(sym); - } - - std::optional<uint64_t> getValue() const override { - if (auto *d = asDefined()) - return d->value; - return {}; - } - - std::optional<uint64_t> getSize() const override { - if (auto *d = asDefined()) - return d->size; - return {}; - } - - const Symbol *getSymbol() const { return sym; } -}; - -class BPSectionMacho : public BPSectionBase { - const InputSection *isec; - -public: - explicit BPSectionMacho(const InputSection *sec) : isec(sec) {} - - const void *getSection() const override { return isec; } - - uint64_t getSize() const override { return isec->getSize(); } - - bool isCodeSection() const override { return macho::isCodeSection(isec); } - - SmallVector<std::unique_ptr<BPSymbol>> getSymbols() const override { - SmallVector<std::unique_ptr<BPSymbol>> symbols; - for (auto *sym : isec->symbols) - if (auto *d = llvm::dyn_cast_or_null<Defined>(sym)) - symbols.emplace_back(std::make_unique<BPSymbolMacho>(d)); - return symbols; - } - - // Linkage names can be prefixed with "_" or "l_" on Mach-O. See - // Mangler::getNameWithPrefix() for details. - std::optional<StringRef> - getResolvedLinkageName(llvm::StringRef name) const override { - if (name.consume_front("_") || name.consume_front("l_")) - return name; - return {}; - } - - void getSectionHashes(llvm::SmallVectorImpl<uint64_t> &hashes, - const llvm::DenseMap<const void *, uint64_t> - §ionToIdx) const override { - constexpr unsigned windowSize = 4; - - // Calculate content hashes: k-mers and the last k-1 bytes. - ArrayRef<uint8_t> data = isec->data; - if (data.size() >= windowSize) - for (size_t i = 0; i <= data.size() - windowSize; ++i) - hashes.push_back(llvm::support::endian::read32le(data.data() + i)); - for (uint8_t byte : data.take_back(windowSize - 1)) - hashes.push_back(byte); - - // Calculate relocation hashes - for (const auto &r : isec->relocs) { - if (r.length == 0 || r.referent.isNull() || r.offset >= data.size()) - continue; - - uint64_t relocHash = getRelocHash(r, sectionToIdx); - uint32_t start = (r.offset < windowSize) ? 0 : r.offset - windowSize + 1; - for (uint32_t i = start; i < r.offset + r.length; i++) { - auto window = data.drop_front(i).take_front(windowSize); - hashes.push_back(xxh3_64bits(window) ^ relocHash); - } - } - - llvm::sort(hashes); - hashes.erase(std::unique(hashes.begin(), hashes.end()), hashes.end()); - } - -private: - static uint64_t - getRelocHash(const Reloc &reloc, - const llvm::DenseMap<const void *, uint64_t> §ionToIdx) { - auto *isec = reloc.getReferentInputSection(); - std::optional<uint64_t> sectionIdx; - if (auto it = sectionToIdx.find(isec); it != sectionToIdx.end()) - sectionIdx = it->second; - uint64_t kind = -1, value = 0; - if (isec) - kind = uint64_t(isec->kind()); - - if (auto *sym = reloc.referent.dyn_cast<Symbol *>()) { - kind = (kind << 8) | uint8_t(sym->kind()); - if (auto *d = llvm::dyn_cast<Defined>(sym)) - value = d->value; - } - return llvm::stable_hash_combine(kind, sectionIdx.value_or(0), value, - reloc.addend); - } -}; - /// Run Balanced Partitioning to find the optimal function and data order to /// improve startup time and compressed size. /// /// It is important that .subsections_via_symbols is used to ensure functions /// and data are in their own sections and thus can be reordered. -llvm::DenseMap<const lld::macho::InputSection *, int> +llvm::DenseMap<const InputSection *, int> runBalancedPartitioning(llvm::StringRef profilePath, bool forFunctionCompression, bool forDataCompression, bool compressionSortStartupFunctions, bool verbose); diff --git a/lld/MachO/CMakeLists.txt b/lld/MachO/CMakeLists.txt index c778fcf7b6ff..ecf6ce609e59 100644 --- a/lld/MachO/CMakeLists.txt +++ b/lld/MachO/CMakeLists.txt @@ -50,6 +50,7 @@ add_lld_library(lldMachO Object Option Passes + ProfileData Support TargetParser TextAPI diff --git a/lld/include/lld/Common/BPSectionOrdererBase.h b/lld/include/lld/Common/BPSectionOrdererBase.h deleted file mode 100644 index bbd05edc5e55..000000000000 --- a/lld/include/lld/Common/BPSectionOrdererBase.h +++ /dev/null @@ -1,70 +0,0 @@ -//===- BPSectionOrdererBase.h ---------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines the common interfaces which may be used by -// BPSectionOrderer. -// -//===----------------------------------------------------------------------===// - -#ifndef LLD_COMMON_BP_SECTION_ORDERER_BASE_H -#define LLD_COMMON_BP_SECTION_ORDERER_BASE_H - -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/Twine.h" -#include <memory> -#include <optional> - -namespace lld { - -class BPSymbol { - -public: - virtual ~BPSymbol() = default; - virtual llvm::StringRef getName() const = 0; - virtual std::optional<uint64_t> getValue() const = 0; - virtual std::optional<uint64_t> getSize() const = 0; -}; - -class BPSectionBase { -public: - virtual ~BPSectionBase() = default; - virtual uint64_t getSize() const = 0; - virtual bool isCodeSection() const = 0; - virtual llvm::SmallVector<std::unique_ptr<BPSymbol>> getSymbols() const = 0; - virtual const void *getSection() const = 0; - virtual void getSectionHashes( - llvm::SmallVectorImpl<uint64_t> &hashes, - const llvm::DenseMap<const void *, uint64_t> §ionToIdx) const = 0; - virtual std::optional<llvm::StringRef> - getResolvedLinkageName(llvm::StringRef name) const = 0; - - /// Symbols can be appended with "(.__uniq.xxxx)?.llvm.yyyy" where "xxxx" and - /// "yyyy" are numbers that could change between builds. We need to use the - /// root symbol name before this suffix so these symbols can be matched with - /// profiles which may have different suffixes. - static llvm::StringRef getRootSymbol(llvm::StringRef Name) { - auto [P0, S0] = Name.rsplit(".llvm."); - auto [P1, S1] = P0.rsplit(".__uniq."); - return P1; - } - - /// Reorders sections using balanced partitioning algorithm based on profile - /// data. - static llvm::DenseMap<const BPSectionBase *, int> - reorderSectionsByBalancedPartitioning( - llvm::StringRef profilePath, bool forFunctionCompression, - bool forDataCompression, bool compressionSortStartupFunctions, - bool verbose, - llvm::SmallVector<std::unique_ptr<BPSectionBase>> &inputSections); -}; - -} // namespace lld - -#endif diff --git a/lld/Common/BPSectionOrdererBase.cpp b/lld/include/lld/Common/BPSectionOrdererBase.inc similarity index 74% rename from lld/Common/BPSectionOrdererBase.cpp rename to lld/include/lld/Common/BPSectionOrdererBase.inc index 7d26a5fb8448..9a2ee4d50738 100644 --- a/lld/Common/BPSectionOrdererBase.cpp +++ b/lld/include/lld/Common/BPSectionOrdererBase.inc @@ -1,31 +1,76 @@ -//===- BPSectionOrdererBase.cpp -------------------------------------------===// +//===- BPSectionOrdererBase.inc ---------------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// +// +// This file defines the common BPSectionOrderer interface using the Curiously +// Recurring Template Pattern and dispatches to the BalancedPartitioning +// algorithm implemented in LLVMSupport. The optimized section layout attempts +// to group similar sections together (resulting in a smaller compressed app +// size) and utilize a temporal profile file to reduce page faults during +// program startup. +// +// Clients should derive from BPOrderer, providing concrete implementations for +// section and symbol representations. Include this file in a .cpp file to +// specialize the template for the derived class. +// +//===----------------------------------------------------------------------===// -#include "lld/Common/BPSectionOrdererBase.h" #include "lld/Common/ErrorHandler.h" +#include "llvm/ADT/CachedHashString.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/SetVector.h" #include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Twine.h" #include "llvm/ProfileData/InstrProfReader.h" #include "llvm/Support/BalancedPartitioning.h" #include "llvm/Support/TimeProfiler.h" #include "llvm/Support/VirtualFileSystem.h" +#include <memory> +#include <optional> #define DEBUG_TYPE "bp-section-orderer" using namespace llvm; using namespace lld; +namespace lld { +template <class D> struct BPOrdererTraits; + +template <class D> struct BPOrderer { + using Section = typename BPOrdererTraits<D>::Section; + using Symbol = typename BPOrdererTraits<D>::Symbol; + + // Compute a section order using the Balanced Partitioning algorithm. + // + // * for*Compresion: Improve Lempel-Ziv compression by grouping + // similar sections together. + // * profilePath: Utilize a temporal profile file to reduce page faults during + // program startup. + // * compressionSortStartupFunctions: if profilePath is specified, allocate + // extra utility vertices to prioritize nearby function similarity. + static auto + computeOrder(llvm::StringRef profilePath, bool forFunctionCompression, + bool forDataCompression, bool compressionSortStartupFunctions, + bool verbose, llvm::ArrayRef<Section *> sections, + const DenseMap<CachedHashStringRef, DenseSet<unsigned>> + &rootSymbolToSectionIdxs) + -> llvm::DenseMap<const Section *, int>; +}; +} // namespace lld + using UtilityNodes = SmallVector<BPFunctionNode::UtilityNodeT>; +template <class D> static SmallVector<std::pair<unsigned, UtilityNodes>> getUnsForCompression( - ArrayRef<const BPSectionBase *> sections, + ArrayRef<const typename D::Section *> sections, const DenseMap<const void *, uint64_t> §ionToIdx, ArrayRef<unsigned> sectionIdxs, DenseMap<unsigned, SmallVector<unsigned>> *duplicateSectionIdxs, @@ -38,7 +83,7 @@ static SmallVector<std::pair<unsigned, UtilityNodes>> getUnsForCompression( for (unsigned sectionIdx : sectionIdxs) { const auto *isec = sections[sectionIdx]; - isec->getSectionHashes(hashes, sectionToIdx); + D::getSectionHashes(*isec, hashes, sectionToIdx); sectionHashes.emplace_back(sectionIdx, std::move(hashes)); hashes.clear(); } @@ -96,36 +141,27 @@ static SmallVector<std::pair<unsigned, UtilityNodes>> getUnsForCompression( return sectionUns; } -llvm::DenseMap<const BPSectionBase *, int> -BPSectionBase::reorderSectionsByBalancedPartitioning( - llvm::StringRef profilePath, bool forFunctionCompression, - bool forDataCompression, bool compressionSortStartupFunctions, bool verbose, - SmallVector<std::unique_ptr<BPSectionBase>> &inputSections) { - TimeTraceScope timeScope("Setup Balanced Partitioning"); - SmallVector<const BPSectionBase *> sections; - DenseMap<const void *, uint64_t> sectionToIdx; - StringMap<DenseSet<unsigned>> symbolToSectionIdxs; +/// Symbols can be appended with "(.__uniq.xxxx)?.llvm.yyyy" where "xxxx" and +/// "yyyy" are numbers that could change between builds. We need to use the +/// root symbol name before this suffix so these symbols can be matched with +/// profiles which may have different suffixes. +inline StringRef getRootSymbol(StringRef name) { + auto [P0, S0] = name.rsplit(".llvm."); + auto [P1, S1] = P0.rsplit(".__uniq."); + return P1; +} - // Process input sections - for (const auto &isec : inputSections) { - unsigned sectionIdx = sections.size(); - sectionToIdx.try_emplace(isec->getSection(), sectionIdx); - sections.emplace_back(isec.get()); - for (auto &sym : isec->getSymbols()) - symbolToSectionIdxs[sym->getName()].insert(sectionIdx); - } - StringMap<DenseSet<unsigned>> rootSymbolToSectionIdxs; - for (auto &entry : symbolToSectionIdxs) { - StringRef name = entry.getKey(); - auto §ionIdxs = entry.getValue(); - name = BPSectionBase::getRootSymbol(name); - rootSymbolToSectionIdxs[name].insert(sectionIdxs.begin(), - sectionIdxs.end()); - if (auto resolvedLinkageName = - sections[*sectionIdxs.begin()]->getResolvedLinkageName(name)) - rootSymbolToSectionIdxs[resolvedLinkageName.value()].insert( - sectionIdxs.begin(), sectionIdxs.end()); - } +template <class D> +auto BPOrderer<D>::computeOrder( + StringRef profilePath, bool forFunctionCompression, bool forDataCompression, + bool compressionSortStartupFunctions, bool verbose, + ArrayRef<Section *> sections, + const DenseMap<CachedHashStringRef, DenseSet<unsigned>> + &rootSymbolToSectionIdxs) -> DenseMap<const Section *, int> { + TimeTraceScope timeScope("Setup Balanced Partitioning"); + DenseMap<const void *, uint64_t> sectionToIdx; + for (auto [i, isec] : llvm::enumerate(sections)) + sectionToIdx.try_emplace(isec, i); BPFunctionNode::UtilityNodeT maxUN = 0; DenseMap<unsigned, UtilityNodes> startupSectionIdxUNs; @@ -150,17 +186,18 @@ BPSectionBase::reorderSectionsByBalancedPartitioning( size_t cutoffTimestamp = 1; auto &trace = traces[traceIdx].FunctionNameRefs; for (size_t timestamp = 0; timestamp < trace.size(); timestamp++) { - auto [Filename, ParsedFuncName] = getParsedIRPGOName( + auto [_, parsedFuncName] = getParsedIRPGOName( reader->getSymtab().getFuncOrVarName(trace[timestamp])); - ParsedFuncName = BPSectionBase::getRootSymbol(ParsedFuncName); + parsedFuncName = getRootSymbol(parsedFuncName); - auto sectionIdxsIt = rootSymbolToSectionIdxs.find(ParsedFuncName); + auto sectionIdxsIt = + rootSymbolToSectionIdxs.find(CachedHashStringRef(parsedFuncName)); if (sectionIdxsIt == rootSymbolToSectionIdxs.end()) continue; - auto §ionIdxs = sectionIdxsIt->getValue(); + auto §ionIdxs = sectionIdxsIt->second; // If the same symbol is found in multiple sections, they might be // identical, so we arbitrarily use the size from the first section. - currentSize += sections[*sectionIdxs.begin()]->getSize(); + currentSize += D::getSize(*sections[*sectionIdxs.begin()]); // Since BalancedPartitioning is sensitive to the initial order, we need // to explicitly define it to be ordered by earliest timestamp. @@ -193,7 +230,7 @@ BPSectionBase::reorderSectionsByBalancedPartitioning( if (startupSectionIdxUNs.count(sectionIdx)) continue; const auto *isec = sections[sectionIdx]; - if (isec->isCodeSection()) { + if (D::isCodeSection(*isec)) { if (forFunctionCompression) sectionIdxsForFunctionCompression.push_back(sectionIdx); } else { @@ -207,8 +244,8 @@ BPSectionBase::reorderSectionsByBalancedPartitioning( for (auto &[sectionIdx, uns] : startupSectionIdxUNs) startupIdxs.push_back(sectionIdx); auto unsForStartupFunctionCompression = - getUnsForCompression(sections, sectionToIdx, startupIdxs, - /*duplicateSectionIdxs=*/nullptr, maxUN); + getUnsForCompression<D>(sections, sectionToIdx, startupIdxs, + /*duplicateSectionIdxs=*/nullptr, maxUN); for (auto &[sectionIdx, compressionUns] : unsForStartupFunctionCompression) { auto &uns = startupSectionIdxUNs[sectionIdx]; @@ -221,10 +258,10 @@ BPSectionBase::reorderSectionsByBalancedPartitioning( // Map a section index (order directly) to a list of duplicate section indices // (not ordered directly). DenseMap<unsigned, SmallVector<unsigned>> duplicateSectionIdxs; - auto unsForFunctionCompression = getUnsForCompression( + auto unsForFunctionCompression = getUnsForCompression<D>( sections, sectionToIdx, sectionIdxsForFunctionCompression, &duplicateSectionIdxs, maxUN); - auto unsForDataCompression = getUnsForCompression( + auto unsForDataCompression = getUnsForCompression<D>( sections, sectionToIdx, sectionIdxsForDataCompression, &duplicateSectionIdxs, maxUN); @@ -263,7 +300,7 @@ BPSectionBase::reorderSectionsByBalancedPartitioning( unsigned numDuplicateCodeSections = 0; unsigned numDataCompressionSections = 0; unsigned numDuplicateDataSections = 0; - SetVector<const BPSectionBase *> orderedSections; + SetVector<const Section *> orderedSections; // Order startup functions, for (auto &node : nodesForStartup) { const auto *isec = sections[node.Id]; @@ -320,23 +357,22 @@ BPSectionBase::reorderSectionsByBalancedPartitioning( const uint64_t pageSize = (1 << 14); uint64_t currentAddress = 0; for (const auto *isec : orderedSections) { - for (auto &sym : isec->getSymbols()) { - uint64_t startAddress = currentAddress + sym->getValue().value_or(0); - uint64_t endAddress = startAddress + sym->getSize().value_or(0); + for (auto *sym : D::getSymbols(*isec)) { + uint64_t startAddress = currentAddress + D::getSymValue(*sym); + uint64_t endAddress = startAddress + D::getSymSize(*sym); uint64_t firstPage = startAddress / pageSize; // I think the kernel might pull in a few pages when one it touched, // so it might be more accurate to force lastPage to be aligned by // 4? uint64_t lastPage = endAddress / pageSize; - StringRef rootSymbol = sym->getName(); - rootSymbol = BPSectionBase::getRootSymbol(rootSymbol); + StringRef rootSymbol = D::getSymName(*sym); + rootSymbol = getRootSymbol(rootSymbol); symbolToPageNumbers.try_emplace(rootSymbol, firstPage, lastPage); - if (auto resolvedLinkageName = - isec->getResolvedLinkageName(rootSymbol)) + if (auto resolvedLinkageName = D::getResolvedLinkageName(rootSymbol)) symbolToPageNumbers.try_emplace(resolvedLinkageName.value(), firstPage, lastPage); } - currentAddress += isec->getSize(); + currentAddress += D::getSize(*isec); } // The area under the curve F where F(t) is the total number of page @@ -348,7 +384,7 @@ BPSectionBase::reorderSectionsByBalancedPartitioning( auto traceId = trace.FunctionNameRefs[step]; auto [Filename, ParsedFuncName] = getParsedIRPGOName(reader->getSymtab().getFuncOrVarName(traceId)); - ParsedFuncName = BPSectionBase::getRootSymbol(ParsedFuncName); + ParsedFuncName = getRootSymbol(ParsedFuncName); auto it = symbolToPageNumbers.find(ParsedFuncName); if (it != symbolToPageNumbers.end()) { auto &[firstPage, lastPage] = it->getValue(); @@ -363,7 +399,7 @@ BPSectionBase::reorderSectionsByBalancedPartitioning( } } - DenseMap<const BPSectionBase *, int> sectionPriorities; + DenseMap<const Section *, int> sectionPriorities; int prio = -orderedSections.size(); for (const auto *isec : orderedSections) sectionPriorities[isec] = prio++;