[Mips] Handle R_MIPS_JALR relocation to omptimize jalr/jr instructions

llvm-svn: 242759
This commit is contained in:
Simon Atanasyan 2015-07-21 05:54:22 +00:00
parent 61459cef40
commit f9db71eaec
5 changed files with 255 additions and 10 deletions

View File

@ -21,7 +21,8 @@ namespace {
enum class CrossJumpMode {
None, // Not a jump or non-isa-cross jump
ToRegular, // cross isa jump to regular symbol
ToMicro // cross isa jump to microMips symbol
ToMicro, // cross isa jump to microMips symbol
ToMicroJalr// cross isa jump to microMips symbol referenced by R_MIPS_JALR
};
typedef std::function<std::error_code(int64_t, bool)> OverflowChecker;
@ -178,7 +179,7 @@ static MipsRelocationParams getRelocationParams(uint32_t rType) {
case R_MICROMIPS_GOT_OFST:
return {4, 0xffff, 0, true, signedCheck<16>};
case R_MIPS_JALR:
return {4, 0x0, 0, false, dummyCheck};
return {4, 0xffffffff, 0, false, dummyCheck};
case R_MICROMIPS_JALR:
return {4, 0x0, 0, true, dummyCheck};
case R_MIPS_JUMP_SLOT:
@ -200,6 +201,10 @@ static MipsRelocationParams getRelocationParams(uint32_t rType) {
}
}
template <class ELFT>
static uint64_t relocRead(const MipsRelocationParams &params,
const uint8_t *loc);
static int64_t getHi16(int64_t value) {
return ((value + 0x8000) >> 16) & 0xffff;
}
@ -299,6 +304,22 @@ static ErrorOr<int64_t> relocPc26(uint64_t P, uint64_t S, int64_t A) {
return S + A - P;
}
template <class ELFT>
static ErrorOr<int64_t> relocJalr(uint64_t P, uint64_t S, bool isCrossJump,
uint8_t *location) {
uint64_t ins = relocRead<ELFT>(getRelocationParams(R_MIPS_JALR), location);
if (isCrossJump)
return ins;
int64_t off = S - P - 4;
if (!llvm::isInt<18>(off))
return ins;
if (ins == 0x0320f809) // jalr t9
return 0x04110000 | ((off >> 2) & 0xffff);
if (ins == 0x03200008) // jr t9
return 0x10000000 | ((off >> 2) & 0xffff);
return ins;
}
static int64_t relocRel32(int64_t A) {
// If output relocation format is REL and the input one is RELA, the only
// method to transfer the relocation addend from the input relocation
@ -309,7 +330,7 @@ static int64_t relocRel32(int64_t A) {
static std::error_code adjustJumpOpCode(uint64_t &ins, uint64_t tgt,
CrossJumpMode mode) {
if (mode == CrossJumpMode::None)
if (mode == CrossJumpMode::None || mode == CrossJumpMode::ToMicroJalr)
return std::error_code();
bool toMicro = mode == CrossJumpMode::ToMicro;
@ -345,6 +366,8 @@ static CrossJumpMode getCrossJumpMode(const Reference &ref) {
return CrossJumpMode::None;
bool isTgtMicro = isMicroMipsAtom(ref.target());
switch (ref.kindValue()) {
case R_MIPS_JALR:
return isTgtMicro ? CrossJumpMode::ToMicroJalr : CrossJumpMode::None;
case R_MIPS_26:
case LLD_R_MIPS_GLOBAL_26:
return isTgtMicro ? CrossJumpMode::ToMicro : CrossJumpMode::None;
@ -356,11 +379,12 @@ static CrossJumpMode getCrossJumpMode(const Reference &ref) {
}
}
static ErrorOr<int64_t> calculateRelocation(Reference::KindValue kind,
Reference::Addend addend,
uint64_t tgtAddr, uint64_t relAddr,
uint64_t gpAddr, bool isGP,
bool isCrossJump, bool isDynamic) {
template <class ELFT>
static ErrorOr<int64_t>
calculateRelocation(Reference::KindValue kind, Reference::Addend addend,
uint64_t tgtAddr, uint64_t relAddr, uint64_t gpAddr,
bool isGP, bool isCrossJump, bool isDynamic,
uint8_t *location) {
switch (kind) {
case R_MIPS_NONE:
return 0;
@ -461,6 +485,7 @@ static ErrorOr<int64_t> calculateRelocation(Reference::KindValue kind,
case R_MICROMIPS_LITERAL:
return tgtAddr + addend - gpAddr;
case R_MIPS_JALR:
return relocJalr<ELFT>(relAddr, tgtAddr, isCrossJump, location);
case R_MICROMIPS_JALR:
// We do not do JALR optimization now.
return 0;
@ -591,8 +616,8 @@ std::error_code RelocationHandler<ELFT>::applyRelocation(
if (kind == R_MIPS_NONE)
break;
auto params = getRelocationParams(kind);
res = calculateRelocation(kind, *res, sym, relAddr, gpAddr, isGpDisp,
isCrossJump, _ctx.isDynamic());
res = calculateRelocation<ELFT>(kind, *res, sym, relAddr, gpAddr, isGpDisp,
isCrossJump, _ctx.isDynamic(), location);
if (auto ec = res.getError())
return ec;
// Check result for the last relocation only.

View File

@ -771,6 +771,10 @@ void RelocationPass<ELFT>::handleReference(const MipsELFDefinedAtom<ELFT> &atom,
ref.setTarget(getTLSGOTEntry(ref.target(), ref.addend()));
else if (kind == R_MIPS_GPREL32 || (isLocal(ref.target()) && isGpRelReloc(kind)))
ref.setAddend(ref.addend() + atom.file().getGP0());
else if (kind == R_MIPS_JALR) {
if (_ctx.getOutputELFType() != ET_EXEC || !isLocalCall(ref.target()))
ref.setKindValue(R_MIPS_NONE);
}
}
template <typename ELFT>

View File

@ -0,0 +1,47 @@
# Check that R_MIPS_JALR relocation does not affect code in case of cross jump.
# RUN: yaml2obj -format=elf %s > %t.o
# RUN: lld -flavor gnu -target mipsel -o %t.exe %t.o
# RUN: llvm-objdump -s %t.exe | FileCheck %s
# CHECK: Contents of section .text:
# CHECK-NEXT: {{[0-9a-f]+}} 08002003 00000000
FileHeader:
Class: ELFCLASS32
Data: ELFDATA2LSB
Type: ET_REL
Machine: EM_MIPS
Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32,
EF_MIPS_MICROMIPS, EF_MIPS_ARCH_32R2]
Sections:
- Name: .text
Type: SHT_PROGBITS
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
AddressAlign: 16
Content: "0800200300000000"
- Name: .rel.text
Type: SHT_REL
Link: .symtab
AddressAlign: 4
Info: .text
Relocations:
- Offset: 0
Symbol: M1
Type: R_MIPS_JALR
Symbols:
Global:
- Name: __start
Type: STT_FUNC
Section: .text
Value: 0
Size: 4
- Name: M1
Type: STT_FUNC
Section: .text
Value: 4
Size: 4
Other: [ STO_MIPS_MICROMIPS ]

View File

@ -0,0 +1,101 @@
# REQUIRES: mips
# Check handling of the R_MIPS_JALR relocation.
# RUN: yaml2obj -format=elf -docnum 1 %s > %t1.o
# RUN: lld -flavor gnu -target mipsel -shared -o %t.so %t1.o
# RUN: yaml2obj -format=elf -docnum 2 %s > %t2.o
# RUN: lld -flavor gnu -target mipsel -o %t.exe %t2.o %t.so
# RUN: llvm-objdump -d %t.exe | FileCheck %s
# CHECK: __start:
# CHECK-NEXT: {{[0-9a-f]+}}: 05 00 11 04 bal 24
# CHECK-NEXT: {{[0-9a-f]+}}: 00 00 00 00 nop
# CHECK-NEXT: {{[0-9a-f]+}}: 04 00 00 10 b 20
# CHECK-NEXT: {{[0-9a-f]+}}: 00 00 00 00 nop
# CHECK-NEXT: {{[0-9a-f]+}}: 09 f8 20 03 jalr $25
# CHECK-NEXT: {{[0-9a-f]+}}: 00 00 00 00 nop
# t1.o
---
FileHeader:
Class: ELFCLASS32
Data: ELFDATA2LSB
Type: ET_REL
Machine: EM_MIPS
Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
Sections:
- Name: .text
Type: SHT_PROGBITS
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
AddressAlign: 16
Size: 4
Symbols:
Global:
- Name: T3
Type: STT_FUNC
Section: .text
Value: 0
Size: 4
# t2.o
---
FileHeader:
Class: ELFCLASS32
Data: ELFDATA2LSB
Type: ET_REL
Machine: EM_MIPS
Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
Sections:
- Name: .text
Type: SHT_PROGBITS
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
AddressAlign: 16
Content: "09f8200300000000080020030000000009f82003000000000000000000000000"
# ^ jalr T1 ^ j T2 ^ jalr T3
- Name: .rel.text
Type: SHT_REL
Link: .symtab
AddressAlign: 4
Info: .text
Relocations:
- Offset: 0
Symbol: T1
Type: R_MIPS_JALR
- Offset: 8
Symbol: T2
Type: R_MIPS_JALR
- Offset: 16
Symbol: T3
Type: R_MIPS_JALR
- Name: .data
Type: SHT_PROGBITS
Flags: [ SHF_WRITE, SHF_ALLOC ]
AddressAlign: 16
Size: 0
Symbols:
Local:
- Name: T1
Type: STT_FUNC
Section: .text
Value: 24
Size: 4
Global:
- Name: __start
Type: STT_FUNC
Section: .text
Value: 0
Size: 24
- Name: T2
Type: STT_FUNC
Section: .text
Value: 28
Size: 4
- Name: T3
...

View File

@ -0,0 +1,68 @@
# REQUIRES: mips
# Check R_MIPS_JALR relocations do not affect the code
# in case of relocatable targets.
# RUN: yaml2obj -format=elf %s > %t.o
# RUN: lld -flavor gnu -target mipsel -shared -o %t.so %t.o
# RUN: llvm-objdump -d %t.so | FileCheck %s
# CHECK: __start:
# CHECK-NEXT: {{[0-9a-f]+}}: 09 f8 20 03 jalr $25
# CHECK-NEXT: {{[0-9a-f]+}}: 00 00 00 00 nop
# CHECK-NEXT: {{[0-9a-f]+}}: 08 00 20 03 jr $25
# CHECK-NEXT: {{[0-9a-f]+}}: 00 00 00 00 nop
---
FileHeader:
Class: ELFCLASS32
Data: ELFDATA2LSB
Type: ET_REL
Machine: EM_MIPS
Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
Sections:
- Name: .text
Type: SHT_PROGBITS
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
AddressAlign: 16
Content: "09f820030000000008002003000000000000000000000000"
# ^ jalr ^ jr ^ T1 ^ T2
- Name: .rel.text
Type: SHT_REL
Link: .symtab
AddressAlign: 4
Info: .text
Relocations:
- Offset: 0
Symbol: T1
Type: R_MIPS_JALR
- Offset: 8
Symbol: T2
Type: R_MIPS_JALR
- Name: .data
Type: SHT_PROGBITS
Flags: [ SHF_WRITE, SHF_ALLOC ]
AddressAlign: 16
Size: 0
Symbols:
Global:
- Name: __start
Type: STT_FUNC
Section: .text
Value: 0
Size: 16
- Name: T1
Type: STT_FUNC
Section: .text
Value: 16
Size: 4
- Name: T2
Type: STT_FUNC
Section: .text
Value: 20
Size: 4
...