diff options
author | Daniel Bertalan <dani@danielbertalan.dev> | 2022-07-18 13:37:40 +0200 |
---|---|---|
committer | Daniel Bertalan <dani@danielbertalan.dev> | 2022-07-18 19:32:58 +0200 |
commit | 1fb9466c6a4c5805f37cf2ab617d49a20b8a5225 (patch) | |
tree | e5a99d4a318c47efccc6f1a58fb76b4aa9bece90 /lld | |
parent | 477c2c6f4a5a99a7d7d21e5171611742320092f2 (diff) | |
download | llvm-1fb9466c6a4c5805f37cf2ab617d49a20b8a5225.zip llvm-1fb9466c6a4c5805f37cf2ab617d49a20b8a5225.tar.gz llvm-1fb9466c6a4c5805f37cf2ab617d49a20b8a5225.tar.bz2 |
[lld-macho] Devirtualize TargetInfo::getRelocAttrs
This method is called on each relocation when parsing input files, so
the overhead of using virtual functions ends up being quite large. We
now have a single non-virtual method, which reads from the appropriate
array of relocation attributes set in the TargetInfo constructor.
This change results in a modest 2.3% reduction in link time for
chromium_framework measured on an x86-64 VPS, and 0.7% on an arm64 Mac.
N Min Max Median Avg Stddev
x 10 11.869417 12.032609 11.935041 11.938268 0.045802324
+ 10 11.581526 11.785265 11.649885 11.659507 0.054634834
Difference at 95.0% confidence
-0.278761 +/- 0.0473673
-2.33502% +/- 0.396768%
(Student's t, pooled s = 0.0504124)
Differential Revision: https://reviews.llvm.org/D130000
Diffstat (limited to 'lld')
-rw-r--r-- | lld/MachO/Arch/ARM.cpp | 34 | ||||
-rw-r--r-- | lld/MachO/Arch/ARM64.cpp | 42 | ||||
-rw-r--r-- | lld/MachO/Arch/ARM64_32.cpp | 39 | ||||
-rw-r--r-- | lld/MachO/Arch/X86_64.cpp | 36 | ||||
-rw-r--r-- | lld/MachO/Target.h | 11 |
5 files changed, 73 insertions, 89 deletions
diff --git a/lld/MachO/Arch/ARM.cpp b/lld/MachO/Arch/ARM.cpp index fd215ed..424df41 100644 --- a/lld/MachO/Arch/ARM.cpp +++ b/lld/MachO/Arch/ARM.cpp @@ -38,35 +38,27 @@ struct ARM : TargetInfo { uint64_t entryAddr) const override; void relaxGotLoad(uint8_t *loc, uint8_t type) const override; - const RelocAttrs &getRelocAttrs(uint8_t type) const override; uint64_t getPageSize() const override { return 4 * 1024; } void handleDtraceReloc(const Symbol *sym, const Reloc &r, uint8_t *loc) const override; }; - } // namespace -const RelocAttrs &ARM::getRelocAttrs(uint8_t type) const { - static const std::array<RelocAttrs, 10> relocAttrsArray{{ +static constexpr std::array<RelocAttrs, 10> relocAttrsArray{{ #define B(x) RelocAttrBits::x - {"VANILLA", /* FIXME populate this */ B(_0)}, - {"PAIR", /* FIXME populate this */ B(_0)}, - {"SECTDIFF", /* FIXME populate this */ B(_0)}, - {"LOCAL_SECTDIFF", /* FIXME populate this */ B(_0)}, - {"PB_LA_PTR", /* FIXME populate this */ B(_0)}, - {"BR24", B(PCREL) | B(LOCAL) | B(EXTERN) | B(BRANCH) | B(BYTE4)}, - {"BR22", B(PCREL) | B(LOCAL) | B(EXTERN) | B(BRANCH) | B(BYTE4)}, - {"32BIT_BRANCH", /* FIXME populate this */ B(_0)}, - {"HALF", /* FIXME populate this */ B(_0)}, - {"HALF_SECTDIFF", /* FIXME populate this */ B(_0)}, + {"VANILLA", /* FIXME populate this */ B(_0)}, + {"PAIR", /* FIXME populate this */ B(_0)}, + {"SECTDIFF", /* FIXME populate this */ B(_0)}, + {"LOCAL_SECTDIFF", /* FIXME populate this */ B(_0)}, + {"PB_LA_PTR", /* FIXME populate this */ B(_0)}, + {"BR24", B(PCREL) | B(LOCAL) | B(EXTERN) | B(BRANCH) | B(BYTE4)}, + {"BR22", B(PCREL) | B(LOCAL) | B(EXTERN) | B(BRANCH) | B(BYTE4)}, + {"32BIT_BRANCH", /* FIXME populate this */ B(_0)}, + {"HALF", /* FIXME populate this */ B(_0)}, + {"HALF_SECTDIFF", /* FIXME populate this */ B(_0)}, #undef B - }}; - assert(type < relocAttrsArray.size() && "invalid relocation type"); - if (type >= relocAttrsArray.size()) - return invalidRelocAttrs; - return relocAttrsArray[type]; -} +}}; int64_t ARM::getEmbeddedAddend(MemoryBufferRef mb, uint64_t offset, relocation_info rel) const { @@ -167,6 +159,8 @@ ARM::ARM(uint32_t cpuSubtype) : TargetInfo(ILP32()) { stubSize = 0 /* FIXME */; stubHelperHeaderSize = 0 /* FIXME */; stubHelperEntrySize = 0 /* FIXME */; + + relocAttrs = {relocAttrsArray.data(), relocAttrsArray.size()}; } TargetInfo *macho::createARMTargetInfo(uint32_t cpuSubtype) { diff --git a/lld/MachO/Arch/ARM64.cpp b/lld/MachO/Arch/ARM64.cpp index 5901a9e..46e935a 100644 --- a/lld/MachO/Arch/ARM64.cpp +++ b/lld/MachO/Arch/ARM64.cpp @@ -34,7 +34,6 @@ struct ARM64 : ARM64Common { void writeStubHelperHeader(uint8_t *buf) const override; void writeStubHelperEntry(uint8_t *buf, const Symbol &, uint64_t entryAddr) const override; - const RelocAttrs &getRelocAttrs(uint8_t type) const override; void populateThunk(InputSection *thunk, Symbol *funcSym) override; void applyOptimizationHints(uint8_t *, const ConcatInputSection *, ArrayRef<uint64_t>) const override; @@ -48,31 +47,24 @@ struct ARM64 : ARM64Common { // absolute version of this relocation. The semantics of the absolute relocation // are weird -- it results in the value of the GOT slot being written, instead // of the address. Let's not support it unless we find a real-world use case. - -const RelocAttrs &ARM64::getRelocAttrs(uint8_t type) const { - static const std::array<RelocAttrs, 11> relocAttrsArray{{ +static constexpr std::array<RelocAttrs, 11> relocAttrsArray{{ #define B(x) RelocAttrBits::x - {"UNSIGNED", - B(UNSIGNED) | B(ABSOLUTE) | B(EXTERN) | B(LOCAL) | B(BYTE4) | B(BYTE8)}, - {"SUBTRACTOR", B(SUBTRAHEND) | B(EXTERN) | B(BYTE4) | B(BYTE8)}, - {"BRANCH26", B(PCREL) | B(EXTERN) | B(BRANCH) | B(BYTE4)}, - {"PAGE21", B(PCREL) | B(EXTERN) | B(BYTE4)}, - {"PAGEOFF12", B(ABSOLUTE) | B(EXTERN) | B(BYTE4)}, - {"GOT_LOAD_PAGE21", B(PCREL) | B(EXTERN) | B(GOT) | B(BYTE4)}, - {"GOT_LOAD_PAGEOFF12", - B(ABSOLUTE) | B(EXTERN) | B(GOT) | B(LOAD) | B(BYTE4)}, - {"POINTER_TO_GOT", B(PCREL) | B(EXTERN) | B(GOT) | B(POINTER) | B(BYTE4)}, - {"TLVP_LOAD_PAGE21", B(PCREL) | B(EXTERN) | B(TLV) | B(BYTE4)}, - {"TLVP_LOAD_PAGEOFF12", - B(ABSOLUTE) | B(EXTERN) | B(TLV) | B(LOAD) | B(BYTE4)}, - {"ADDEND", B(ADDEND)}, + {"UNSIGNED", + B(UNSIGNED) | B(ABSOLUTE) | B(EXTERN) | B(LOCAL) | B(BYTE4) | B(BYTE8)}, + {"SUBTRACTOR", B(SUBTRAHEND) | B(EXTERN) | B(BYTE4) | B(BYTE8)}, + {"BRANCH26", B(PCREL) | B(EXTERN) | B(BRANCH) | B(BYTE4)}, + {"PAGE21", B(PCREL) | B(EXTERN) | B(BYTE4)}, + {"PAGEOFF12", B(ABSOLUTE) | B(EXTERN) | B(BYTE4)}, + {"GOT_LOAD_PAGE21", B(PCREL) | B(EXTERN) | B(GOT) | B(BYTE4)}, + {"GOT_LOAD_PAGEOFF12", + B(ABSOLUTE) | B(EXTERN) | B(GOT) | B(LOAD) | B(BYTE4)}, + {"POINTER_TO_GOT", B(PCREL) | B(EXTERN) | B(GOT) | B(POINTER) | B(BYTE4)}, + {"TLVP_LOAD_PAGE21", B(PCREL) | B(EXTERN) | B(TLV) | B(BYTE4)}, + {"TLVP_LOAD_PAGEOFF12", + B(ABSOLUTE) | B(EXTERN) | B(TLV) | B(LOAD) | B(BYTE4)}, + {"ADDEND", B(ADDEND)}, #undef B - }}; - assert(type < relocAttrsArray.size() && "invalid relocation type"); - if (type >= relocAttrsArray.size()) - return invalidRelocAttrs; - return relocAttrsArray[type]; -} +}}; static constexpr uint32_t stubCode[] = { 0x90000010, // 00: adrp x16, __la_symbol_ptr@page @@ -150,6 +142,8 @@ ARM64::ARM64() : ARM64Common(LP64()) { stubHelperHeaderSize = sizeof(stubHelperHeaderCode); stubHelperEntrySize = sizeof(stubHelperEntryCode); + + relocAttrs = {relocAttrsArray.data(), relocAttrsArray.size()}; } namespace { diff --git a/lld/MachO/Arch/ARM64_32.cpp b/lld/MachO/Arch/ARM64_32.cpp index 5be411e..4830c26 100644 --- a/lld/MachO/Arch/ARM64_32.cpp +++ b/lld/MachO/Arch/ARM64_32.cpp @@ -33,36 +33,29 @@ struct ARM64_32 : ARM64Common { void writeStubHelperHeader(uint8_t *buf) const override; void writeStubHelperEntry(uint8_t *buf, const Symbol &, uint64_t entryAddr) const override; - const RelocAttrs &getRelocAttrs(uint8_t type) const override; }; } // namespace // These are very similar to ARM64's relocation attributes, except that we don't // have the BYTE8 flag set. -const RelocAttrs &ARM64_32::getRelocAttrs(uint8_t type) const { - static const std::array<RelocAttrs, 11> relocAttrsArray{{ +static constexpr std::array<RelocAttrs, 11> relocAttrsArray{{ #define B(x) RelocAttrBits::x - {"UNSIGNED", B(UNSIGNED) | B(ABSOLUTE) | B(EXTERN) | B(LOCAL) | B(BYTE4)}, - {"SUBTRACTOR", B(SUBTRAHEND) | B(EXTERN) | B(BYTE4)}, - {"BRANCH26", B(PCREL) | B(EXTERN) | B(BRANCH) | B(BYTE4)}, - {"PAGE21", B(PCREL) | B(EXTERN) | B(BYTE4)}, - {"PAGEOFF12", B(ABSOLUTE) | B(EXTERN) | B(BYTE4)}, - {"GOT_LOAD_PAGE21", B(PCREL) | B(EXTERN) | B(GOT) | B(BYTE4)}, - {"GOT_LOAD_PAGEOFF12", - B(ABSOLUTE) | B(EXTERN) | B(GOT) | B(LOAD) | B(BYTE4)}, - {"POINTER_TO_GOT", B(PCREL) | B(EXTERN) | B(GOT) | B(POINTER) | B(BYTE4)}, - {"TLVP_LOAD_PAGE21", B(PCREL) | B(EXTERN) | B(TLV) | B(BYTE4)}, - {"TLVP_LOAD_PAGEOFF12", - B(ABSOLUTE) | B(EXTERN) | B(TLV) | B(LOAD) | B(BYTE4)}, - {"ADDEND", B(ADDEND)}, + {"UNSIGNED", B(UNSIGNED) | B(ABSOLUTE) | B(EXTERN) | B(LOCAL) | B(BYTE4)}, + {"SUBTRACTOR", B(SUBTRAHEND) | B(EXTERN) | B(BYTE4)}, + {"BRANCH26", B(PCREL) | B(EXTERN) | B(BRANCH) | B(BYTE4)}, + {"PAGE21", B(PCREL) | B(EXTERN) | B(BYTE4)}, + {"PAGEOFF12", B(ABSOLUTE) | B(EXTERN) | B(BYTE4)}, + {"GOT_LOAD_PAGE21", B(PCREL) | B(EXTERN) | B(GOT) | B(BYTE4)}, + {"GOT_LOAD_PAGEOFF12", + B(ABSOLUTE) | B(EXTERN) | B(GOT) | B(LOAD) | B(BYTE4)}, + {"POINTER_TO_GOT", B(PCREL) | B(EXTERN) | B(GOT) | B(POINTER) | B(BYTE4)}, + {"TLVP_LOAD_PAGE21", B(PCREL) | B(EXTERN) | B(TLV) | B(BYTE4)}, + {"TLVP_LOAD_PAGEOFF12", + B(ABSOLUTE) | B(EXTERN) | B(TLV) | B(LOAD) | B(BYTE4)}, + {"ADDEND", B(ADDEND)}, #undef B - }}; - assert(type < relocAttrsArray.size() && "invalid relocation type"); - if (type >= relocAttrsArray.size()) - return invalidRelocAttrs; - return relocAttrsArray[type]; -} +}}; // The stub code is fairly similar to ARM64's, except that we load pointers into // 32-bit 'w' registers, instead of the 64-bit 'x' ones. @@ -112,6 +105,8 @@ ARM64_32::ARM64_32() : ARM64Common(ILP32()) { stubSize = sizeof(stubCode); stubHelperHeaderSize = sizeof(stubHelperHeaderCode); stubHelperEntrySize = sizeof(stubHelperEntryCode); + + relocAttrs = {relocAttrsArray.data(), relocAttrsArray.size()}; } TargetInfo *macho::createARM64_32TargetInfo() { diff --git a/lld/MachO/Arch/X86_64.cpp b/lld/MachO/Arch/X86_64.cpp index d2efa5b..b1c46cb 100644 --- a/lld/MachO/Arch/X86_64.cpp +++ b/lld/MachO/Arch/X86_64.cpp @@ -37,36 +37,28 @@ struct X86_64 : TargetInfo { uint64_t entryAddr) const override; void relaxGotLoad(uint8_t *loc, uint8_t type) const override; - const RelocAttrs &getRelocAttrs(uint8_t type) const override; uint64_t getPageSize() const override { return 4 * 1024; } void handleDtraceReloc(const Symbol *sym, const Reloc &r, uint8_t *loc) const override; }; - } // namespace -const RelocAttrs &X86_64::getRelocAttrs(uint8_t type) const { - static const std::array<RelocAttrs, 10> relocAttrsArray{{ +static constexpr std::array<RelocAttrs, 10> relocAttrsArray{{ #define B(x) RelocAttrBits::x - {"UNSIGNED", - B(UNSIGNED) | B(ABSOLUTE) | B(EXTERN) | B(LOCAL) | B(BYTE4) | B(BYTE8)}, - {"SIGNED", B(PCREL) | B(EXTERN) | B(LOCAL) | B(BYTE4)}, - {"BRANCH", B(PCREL) | B(EXTERN) | B(BRANCH) | B(BYTE4)}, - {"GOT_LOAD", B(PCREL) | B(EXTERN) | B(GOT) | B(LOAD) | B(BYTE4)}, - {"GOT", B(PCREL) | B(EXTERN) | B(GOT) | B(POINTER) | B(BYTE4)}, - {"SUBTRACTOR", B(SUBTRAHEND) | B(EXTERN) | B(BYTE4) | B(BYTE8)}, - {"SIGNED_1", B(PCREL) | B(EXTERN) | B(LOCAL) | B(BYTE4)}, - {"SIGNED_2", B(PCREL) | B(EXTERN) | B(LOCAL) | B(BYTE4)}, - {"SIGNED_4", B(PCREL) | B(EXTERN) | B(LOCAL) | B(BYTE4)}, - {"TLV", B(PCREL) | B(EXTERN) | B(TLV) | B(LOAD) | B(BYTE4)}, + {"UNSIGNED", + B(UNSIGNED) | B(ABSOLUTE) | B(EXTERN) | B(LOCAL) | B(BYTE4) | B(BYTE8)}, + {"SIGNED", B(PCREL) | B(EXTERN) | B(LOCAL) | B(BYTE4)}, + {"BRANCH", B(PCREL) | B(EXTERN) | B(BRANCH) | B(BYTE4)}, + {"GOT_LOAD", B(PCREL) | B(EXTERN) | B(GOT) | B(LOAD) | B(BYTE4)}, + {"GOT", B(PCREL) | B(EXTERN) | B(GOT) | B(POINTER) | B(BYTE4)}, + {"SUBTRACTOR", B(SUBTRAHEND) | B(EXTERN) | B(BYTE4) | B(BYTE8)}, + {"SIGNED_1", B(PCREL) | B(EXTERN) | B(LOCAL) | B(BYTE4)}, + {"SIGNED_2", B(PCREL) | B(EXTERN) | B(LOCAL) | B(BYTE4)}, + {"SIGNED_4", B(PCREL) | B(EXTERN) | B(LOCAL) | B(BYTE4)}, + {"TLV", B(PCREL) | B(EXTERN) | B(TLV) | B(LOAD) | B(BYTE4)}, #undef B - }}; - assert(type < relocAttrsArray.size() && "invalid relocation type"); - if (type >= relocAttrsArray.size()) - return invalidRelocAttrs; - return relocAttrsArray[type]; -} +}}; static int pcrelOffset(uint8_t type) { switch (type) { @@ -196,6 +188,8 @@ X86_64::X86_64() : TargetInfo(LP64()) { stubSize = sizeof(stub); stubHelperHeaderSize = sizeof(stubHelperHeader); stubHelperEntrySize = sizeof(stubHelperEntry); + + relocAttrs = {relocAttrsArray.data(), relocAttrsArray.size()}; } TargetInfo *macho::createX86_64TargetInfo() { diff --git a/lld/MachO/Target.h b/lld/MachO/Target.h index 5975022..ef54dbb 100644 --- a/lld/MachO/Target.h +++ b/lld/MachO/Target.h @@ -65,14 +65,19 @@ public: // on a level of address indirection. virtual void relaxGotLoad(uint8_t *loc, uint8_t type) const = 0; - virtual const RelocAttrs &getRelocAttrs(uint8_t type) const = 0; - virtual uint64_t getPageSize() const = 0; virtual void populateThunk(InputSection *thunk, Symbol *funcSym) { llvm_unreachable("target does not use thunks"); } + const RelocAttrs &getRelocAttrs(uint8_t type) const { + assert(type < relocAttrs.size() && "invalid relocation type"); + if (type >= relocAttrs.size()) + return invalidRelocAttrs; + return relocAttrs[type]; + } + bool hasAttr(uint8_t type, RelocAttrBits bit) const { return getRelocAttrs(type).hasAttr(bit); } @@ -111,6 +116,8 @@ public: uint8_t subtractorRelocType; uint8_t unsignedRelocType; + llvm::ArrayRef<RelocAttrs> relocAttrs; + // We contrive this value as sufficiently far from any valid address that it // will always be out-of-range for any architecture. UINT64_MAX is not a // good choice because it is (a) only 1 away from wrapping to 0, and (b) the |