Skip to content

Commit

Permalink
Relax GOT indirection into PC-relative addressing
Browse files Browse the repository at this point in the history
Some psABIs define the linker optimizations to relax a GOT load into a
PC-relative address materialization. AArch64 [1] allows the linker to
rewrite ADRP+ADD into ADR. x86-64 does the same thing with the
`R_X86_64_GOTPCRELX` and `R_X86_64_REX_GOTPCRELX` relocations.

In our case, we have lots of AUIPC+LD instruction pairs to load an
address from the GOT in our RISC-V programs because `la` assembly pseudo
instruction is expanded to that instruction pair. If the PC-relative
address loaded by the instruction pair is a link-time constant, we can
rewrite the instructions with AUIPC+ADDI to directly materialize the
value into a register, which eliminates one memory load.

We can't rewrite existing AUIPC+ADDI instruction pairs unconditionally
because technically there may exist code that jumps to the middle of the
instruction pair. That should be extremely rare, but we can't deny the
possibility. Therefore, `R_RISCV_GOT_HI20` is required to be annotated
with `R_RISCV_RELAX` in this proposal. Currently, neither gas nor LLVM
assembler emit `R_RISCV_RELAX` for `R_RISCV_GOT_HI20`. I have a WIP
patch to emit `R_RISCV_RELAX` only for the `la` pseudo instruction.

[1] https://github.com/ARM-software/abi-aa/blob/844a79fd4c77252a11342709e3b27b2c9f590cf1/aaelf64/aaelf64.rst#relocation-optimization
  • Loading branch information
rui314 committed Sep 18, 2023
1 parent 3e4edc7 commit ee68f8e
Showing 1 changed file with 49 additions and 0 deletions.
49 changes: 49 additions & 0 deletions riscv-elf.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -1567,6 +1567,55 @@ optimize code size and performance of the symbol accessing.

NOTE: Tag_RISCV_x3_reg_usage is treated as 0 if it is not present.

==== GOT load relaxation

Target Relocation:: R_RISCV_GOT_HI20, R_RISCV_PCREL_LO12_I

Description:: This relaxation can relax a GOT indirection into PC-relative
addressing. This relaxation is intended to optimize the `la` assembly
pseudo-instruction, which loads a symbol's address from a GOT entry.

Condition::
- Both `R_RISCV_GOT_HI20` and `R_RISCV_PCREL_LO12_I` are annotated with
`R_RISCV_RELAX`.

- `R_RISCV_GOT_HI20` refers to the location 4 bytes before where
`R_RISCV_PCREL_LO12_I` points.

- The symbol pointed to by `R_RISCV_PCREL_LO12_I` is at the location to
which `R_RISCV_GOT_HI20` refers.

- The symbol's PC-relative address is a link-time constant.

- The offset between the location to which `R_RISCV_GOT_HI20` refers and
the target symbol is within +-2GiB.

Relaxation::
- Instruction sequence associated with `R_RISCV_GOT_HI20` and
`R_RISCV_PCREL_LO12_I` can be rewritten to a `auipc` and `addi` to
materialize the symbol's address in the PC-relative manner, eliminating
a load from the GOT.

- If this relaxation eliminates all references to the symbol's GOT slot,
the linker may opt not to create a GOT slot for that symbol.

Example::
+
--
[,asm]
----
label:
auipc t0, 0 # R_RISCV_GOT_HI20 (symbol), R_RISCV_RELAX
ld t0, 0(t0) # R_RISCV_PCREL_LO12_I (label), R_RISCV_RELAX
----
Relaxation result:
[,asm]
----
auipc t0, <hi>
addi t0, <lo>
----
--

==== Zero-page Relaxation

Target Relocation:: R_RISCV_HI20, R_RISCV_LO12_I, R_RISCV_LO12_S
Expand Down

0 comments on commit ee68f8e

Please sign in to comment.