RISC-V: Improve link time complexity.
authorPatrick O'Neill <patrick@rivosinc.com>
Mon, 17 Oct 2022 01:37:35 +0000 (09:37 +0800)
committerNelson Chu <nelson@rivosinc.com>
Tue, 25 Oct 2022 01:20:23 +0000 (09:20 +0800)
commit43025f01a0c99c939e20e90a6e695741c14a925a
treed1df267389c4a7255941b22de909541d1770b83f
parent4ed07377e47addf4dd0594ac5b16d7e4cdb19436
RISC-V: Improve link time complexity.

The riscv port does deletion and symbol table update for each relocation
while relaxing, so we are moving section bytes and scanning symbol table once
for each relocation.  Compared to microblaze port, they record the relaxation
changes into a table, then do the deletion and symbol table update once per
section, rather than per relocation.  Therefore, they should have better link
time complexity than us.

To improve the link time complexity, this patch try to make the deletion in
linear time.  Compared to record the relaxation changes into a table, we
replace the unused relocation with R_RISCV_DELETE for the deleted bytes, and
then resolve them at the end of the section.  Assuming the number of
R_RISCV_DELETE is m, and the number of symbols is n, the total link complexity
should be O(m) for moving section bytes, and O(m*n^2) for symbol table update.
If we record the relaxation changes into the table, and then sort the symbol
table by values, then probably can reduce the time complexity to O(m*n*log(n))
for updating symbol table, but it doesn't seem worth it for now.

bfd/
    * elfnn-riscv.c (_riscv_relax_delete_bytes): Renamed from
    riscv_relax_delete_bytes, updated to reduce the tiem complexity to O(m)
    for memmove.
    (typedef relax_delete_t): Function pointer declaration of delete functions.
    (riscv_relax_delete_bytes): Can choose to use _riscv_relax_delete_piecewise
    or _riscv_relax_delete_immediate for deletion.
    (_riscv_relax_delete_piecewise): Just mark the deleted bytes as R_RISCV_DELETE.
    (_riscv_relax_delete_immediate): Delete some bytes from a section while
    relaxing.
    (riscv_relax_resolve_delete_relocs): Delete the bytes for R_RISCV_DELETE
    relocations from a section, at the end of _bfd_riscv_relax_section.
    (_bfd_riscv_relax_call): Mark deleted bytes as R_RISCV_DELETE by reusing
    R_RISCV_RELAX.
    (_bfd_riscv_relax_lui): Likewise, but reuse R_RISCV_HI20 for lui, and reuse
    R_RISCV_RELAX for c.lui.
    (_bfd_riscv_relax_tls_le): Likewise, but resue R_RISCV_TPREL_HI20 and
    R_RISCV_TPREL_ADD.
    (_bfd_riscv_relax_pc): Likewise, but resue R_RISCV_PCREL_HI20 for auipc.
    (_bfd_riscv_relax_align): Updated, don't need to resue relocation since
    calling _riscv_relax_delete_immediate.
    (_bfd_riscv_relax_delete): Removed.
    (_bfd_riscv_relax_section): Set riscv_relax_delete_bytes for each relax_func,
    to delete bytes immediately or later.  Call riscv_relax_resolve_delete_relocs
    to delete bytes for DELETE relocations from a section.
bfd/elfnn-riscv.c