[lld-macho] Emit REBASE_OPCODE_ADD_ADDR_IMM_SCALED if possible

An ADD_ADDR rebase opcode's argument can be encoded as an immediate if
the offset is less than 15 * word size. This change reduces the size of
chromium_framework by 100+ KiB.

Differential Revision: https://reviews.llvm.org/D128798
This commit is contained in:
Daniel Bertalan 2022-06-29 11:33:41 +02:00
parent 017c068f78
commit 8d29f0fdb9
2 changed files with 57 additions and 2 deletions

View File

@ -202,8 +202,18 @@ static void encodeRebase(const OutputSection *osec, uint64_t outSecOff,
lastRebase.offset = offset;
} else {
assert(lastRebase.offset != offset);
os << static_cast<uint8_t>(REBASE_OPCODE_ADD_ADDR_ULEB);
encodeULEB128(offset - lastRebase.offset, os);
uint64_t delta = offset - lastRebase.offset;
// For unknown reasons, ld64 checks if the scaled offset is strictly less
// than REBASE_IMMEDIATE_MASK instead of allowing equality. We match this
// behavior as a precaution.
if ((delta % target->wordSize == 0) &&
(delta / target->wordSize < REBASE_IMMEDIATE_MASK)) {
os << static_cast<uint8_t>(REBASE_OPCODE_ADD_ADDR_IMM_SCALED |
(delta / target->wordSize));
} else {
os << static_cast<uint8_t>(REBASE_OPCODE_ADD_ADDR_ULEB);
encodeULEB128(delta, os);
}
lastRebase.offset = offset;
}
}

View File

@ -0,0 +1,45 @@
# REQUIRES: x86
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %s -o %t.o
# RUN: %lld -dylib %t.o -o %t.dylib
# RUN: obj2yaml %t.dylib | FileCheck %s
## Test that:
## 1/ Consecutive rebases are encoded as REBASE_OPCODE_DO_REBASE_IMM_TIMES.
## 2/ Gaps smaller than 15 words are encoded as REBASE_OPCODE_ADD_ADDR_IMM_SCALED.
## 3/ Gaps larger than that become REBASE_OPCODE_ADD_ADDR_ULEB.
## FIXME: The last rebase could be transformed into a REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB.
# CHECK: RebaseOpcodes:
# CHECK-NEXT: Opcode: REBASE_OPCODE_SET_TYPE_IMM
# CHECK-NEXT: Imm: 1
# CHECK-NEXT: Opcode: REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
# CHECK-NEXT: Imm: 1
# CHECK-NEXT: ExtraData: [ 0x0 ]
# CHECK-NEXT: Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES
# CHECK-NEXT: Imm: 1
# CHECK-NEXT: Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED
# CHECK-NEXT: Imm: 14
# CHECK-NEXT: Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES
# CHECK-NEXT: Imm: 3
# CHECK-NEXT: Opcode: REBASE_OPCODE_ADD_ADDR_ULEB
# CHECK-NEXT: Imm: 0
# CHECK-NEXT: ExtraData: [ 0x78 ]
# CHECK-NEXT: Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES
# CHECK-NEXT: Imm: 1
# CHECK-NEXT: Opcode: REBASE_OPCODE_DONE
# CHECK-NEXT: Imm: 0
.text
.globl _foo
_foo:
.data
.quad _foo
.space 112
.quad _foo
.quad _foo
.quad _foo
.space 120
.quad _foo