[lld] [lld][ELF] Extend profile guided function ordering to ELF binaries (PR #117514)

via llvm-commits llvm-commits at lists.llvm.org
Wed Dec 11 22:39:05 PST 2024


================
@@ -14,13 +14,138 @@
 #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/StringRef.h"
+#include "llvm/ADT/TinyPtrVector.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;
+  uint64_t sectionIdx;
+
+public:
+  explicit BPSectionMacho(const InputSection *sec, uint64_t sectionIdx)
+      : isec(sec), sectionIdx(sectionIdx) {}
+
+  const InputSection *getSection() const { return isec; }
+
+  uint64_t getSize() const override { return isec->getSize(); }
+
+  uint64_t getSectionIdx() const { return sectionIdx; }
+
+  bool isCodeSection() const override { return macho::isCodeSection(isec); }
+
+  bool hasValidData() const override {
+    return isec && !isec->data.empty() && isec->data.data();
+  }
+
+  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 override {
+    constexpr unsigned windowSize = 4;
+
+    // Calculate content hashes
+    size_t dataSize = isec->data.size();
+    for (size_t i = 0; i < dataSize; i++) {
+      auto window = isec->data.drop_front(i).take_front(windowSize);
+      hashes.push_back(xxHash64(window));
+    }
+
+    // Calculate relocation hashes
+    for (const auto &r : isec->relocs) {
+      if (r.length == 0 || r.referent.isNull() || r.offset >= isec->data.size())
+        continue;
+
+      uint64_t relocHash = getRelocHash(r, this);
+      uint32_t start = (r.offset < windowSize) ? 0 : r.offset - windowSize + 1;
+      for (uint32_t i = start; i < r.offset + r.length; i++) {
+        auto window = isec->data.drop_front(i).take_front(windowSize);
+        hashes.push_back(xxHash64(window) + relocHash);
+      }
+    }
+
+    llvm::sort(hashes);
+    hashes.erase(std::unique(hashes.begin(), hashes.end()), hashes.end());
+  }
+
+  const InputSection *getInputSection() const { return isec; }
+
+  static bool classof(const BPSectionBase *s) { return true; }
+
+private:
+  static uint64_t getRelocHash(const Reloc &reloc,
+                               const BPSectionMacho *section) {
+    auto *isec = reloc.getReferentInputSection();
+    std::optional<uint64_t> sectionIdx;
+    if (isec && isec == section->getSection())
+      sectionIdx = section->getSectionIdx();
----------------
Colibrow wrote:

Yes. Added the sectiontToIdx map.

https://github.com/llvm/llvm-project/pull/117514


More information about the llvm-commits mailing list