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.

[1] https://github.com/ARM-software/abi-aa/blob/844a79fd4c77252a11342709e3b27b2c9f590cf1/aaelf64/aaelf64.rst#relocation-optimization
  • Loading branch information
rui314 committed Sep 19, 2023
1 parent 3e4edc7 commit 49ae4e2
Showing 1 changed file with 52 additions and 0 deletions.
52 changes: 52 additions & 0 deletions riscv-elf.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -1567,6 +1567,58 @@ 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 with
an `auipc` + `ld` instruction pair.

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

- `R_RISCV_PCREL_LO12_I` is annotated with `R_RISCV_RELAX`.

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

- The rd operands of the instructions referred to by `R_RISCV_GOT_HI20`
and `R_RISCV_PCREL_LO12_I` are the same.

- 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 an `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)
ld t0, 0(t0) # R_RISCV_PCREL_LO12_I (label), R_RISCV_RELAX
----
Relaxation result:
[,asm]
----
auipc t0, <hi>
addi t0, t0, <lo>
----
--

==== Zero-page Relaxation

Target Relocation:: R_RISCV_HI20, R_RISCV_LO12_I, R_RISCV_LO12_S
Expand Down

0 comments on commit 49ae4e2

Please sign in to comment.