Skip to content

feat: Support RISC-V call relaxation#1552

Merged
lapla-cogito merged 2 commits into
wild-linker:mainfrom
lapla-cogito:rv_call_relax
Feb 17, 2026
Merged

feat: Support RISC-V call relaxation#1552
lapla-cogito merged 2 commits into
wild-linker:mainfrom
lapla-cogito:rv_call_relax

Conversation

@lapla-cogito

@lapla-cogito lapla-cogito commented Feb 17, 2026

Copy link
Copy Markdown
Member

part of #874

This relaxation replaces auipc+jalr pairs (function calls via call) with a single jal instruction when the target is within ±1 MiB.

Below are the test results using the added wild/tests/sources/riscv-call-relaxation.s. First, the original code calls nearby_func using call, which has been replaced with jal.

(▰╹◡╹)❯  riscv64-linux-gnu-objdump -d wild/tests/build/riscv-call-relaxation.s/default-riscv64/riscv-call-relaxation.s.wild

wild/tests/build/riscv-call-relaxation.s/default-riscv64/riscv-call-relaxation.s.wild:     file format elf64-littleriscv


Disassembly of section .text:

00000000004013d0 <_start>:
  4013d0:       00c000ef                jal     4013dc <nearby_func>
  4013d4:       05d00893                li      a7,93
  4013d8:       00000073                ecall

00000000004013dc <nearby_func>:
  4013dc:       02a00513                li      a0,42
  4013e0:       8082                    ret

And the reduced _start symbol size resulting from this has also been updated in the symbol table.

(▰╹◡╹)❯  riscv64-linux-gnu-readelf -s wild/tests/build/riscv-call-relaxation.s/default-riscv64/riscv-call-relaxation.s.wild

Symbol table '.symtab' contains 5 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND
     1: 0000000000400000     0 NOTYPE  GLOBAL DEFAULT    1 __ehdr_start
     2: 0000000000400000     0 NOTYPE  GLOBAL DEFAULT    1 __executable_start
     3: 00000000004013d0    12 FUNC    GLOBAL DEFAULT    1 _start
     4: 00000000004013dc     6 FUNC    GLOBAL DEFAULT    1 nearby_func

@lapla-cogito

lapla-cogito commented Feb 17, 2026

Copy link
Copy Markdown
Member Author

This PR contains two commits. The first implements call relaxation based on the previously implemented byte reduction tracking infrastructure.

However, I found that this approach alone has limitations for applying relaxation generically. Without iterative relaxation, applying relaxation across object files proves difficult (as demonstrated by the riscv-cross-object-call-relaxation.s addition - this test fails in the first commit but succeeds in the second). Therefore, the second commit implements iterative relaxation. Initially, I believed that implementing iterative relaxation would require rerunning much of the layout processing. However, I determined that heavy operations like finalise_all_sizes() and compute_symbols_and_layouts() don't need to be reexecuted, with the most expensive component being the scan of relaxation scan paths. Nevertheless, this operation is inherently parallelizable, and since it currently only affects RISC-V builds with --relax, I decided to implement it together. That said, it may be feasible to merge only the first commit first.

@davidlattimore davidlattimore left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could be good to get @marxin's thoughts, but I think that should be post-submission, since I want to reduce the potential for merge conflicts with the changes I'm making, so getting this submitted sooner rather than later seems like a good idea.

Comment thread libwild/src/layout.rs
}
}

/// Compute the output address of every loaded input section across all object files.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow, that sounds expensive. But I think it's fine for now since it only affects riscv and it can be turned off with --no-relax. At some point, we should possibly think about ways to make this cheaper.

@lapla-cogito lapla-cogito merged commit ee3a866 into wild-linker:main Feb 17, 2026
20 checks passed
@lapla-cogito lapla-cogito deleted the rv_call_relax branch February 17, 2026 04:15
@marxin

marxin commented Feb 21, 2026

Copy link
Copy Markdown
Collaborator

My general view is that code relaxations aren’t worth the added linker complexity and longer link times (see: https://maskray.me/blog/2021-03-14-the-dark-side-of-riscv-linker-relaxation
).
I’d personally recommend using -mno-relax. That said, if @lapla-cogito has the energy and is willing to take this on, I’m happy to move forward 🙂

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants