Skip to content

Update LLVM from 18 to 22#4951

Draft
stertl wants to merge 2 commits into
bytecodealliance:mainfrom
siemens:dev/update_to_llvm_22
Draft

Update LLVM from 18 to 22#4951
stertl wants to merge 2 commits into
bytecodealliance:mainfrom
siemens:dev/update_to_llvm_22

Conversation

@stertl

@stertl stertl commented May 22, 2026

Copy link
Copy Markdown
Contributor

Changes

Bumps the LLVM version from LLVM 18 (llvmorg-18.1.8) to LLVM 22 (llvmorg-22.1.6). The ARC architecture target branch is updated accordingly from release/18.x to release/22.x.

Motivation

LLVM 22 delivers a significant AoT compilation speedup compared to LLVM 18. Compiling an example program (example.c.zip — a large C file with many global variables) to AOT shows:

wamrc version Wall time
wamrc 2.4.4 (LLVM 18) 66.79 s
wamrc with LLVM 22 12.59 s

~5× speedup — the updated compiler takes roughly one fifth of the time of the previous version for this workload.

Testing

# Compile C to Wasm
$ time clang-21 -target wasm32 -O3 -nostdlib example.c -Wl,--no-entry,--export=function -o example.wasm

# Compile Wasm to AoT with wamrc-2.4.4 with LLVM 18
$ time wamrc-2.4.4 -o example.aot example.wasm                                                                    
Create AoT compiler with:
  target:        x86_64
  target cpu:    skylake
  target triple: x86_64-unknown-linux-gnu
  cpu features:  
  opt level:     3
  size level:    3
  output format: AoT file
Compile success, file example.aot was generated.
wamrc -o example.aot example.wasm  66.79s user 0.04s system 99% cpu 1:06.83 total

# Compile Wasm to AoT with wamrc with LLVM22
$ time ./wamr-compiler/build/wamrc -o example.aot example.wasm
Create AoT compiler with:
  target:        x86_64
  target cpu:    skylake
  target triple: x86_64-unknown-linux-gnu
  cpu features:  
  opt level:     3
  size level:    3
  output format: AoT file
Compile success, file example.aot was generated.
/home/stefan/git/siemens-wasm-micro-runtime/wamr-compiler/build/wamrc -o    12.59s user 0.13s system 99% cpu 12.719 total

@stertl stertl marked this pull request as draft May 26, 2026 07:16
@lum1n0us

Copy link
Copy Markdown
Contributor

@TianlongLiang Please feel free to jump in

  • I re-ran all the failed CI jobs. There are still some compilation errors and AOT generation failures. Please look into these issues.
  • During the CI build, the LLVM library is generating extra cache data. This might lead to storage pressure. I’ll fix this as soon as possible.
  • Upgrading LLVM is a foundational change. In addition to making sure CI passes, please run local tests, including unit tests, regression tests, spec tests, and sample tests. Also, please do a manual check of the PGO feature.

@stertl stertl force-pushed the dev/update_to_llvm_22 branch 2 times, most recently from 656bb20 to 29b9b03 Compare June 8, 2026 15:16
Ertl, Stefan (DI FA SEA R&D-AT S7P) and others added 2 commits June 10, 2026 12:50
The RISC-V AOT relocation loader assumed that the R_RISCV_PCREL_LO12_I/S
instruction always immediately follows its R_RISCV_PCREL_HI20 (AUIPC) at
AUIPC+4. The HI20 handler patched both the AUIPC high 20 bits and the
instruction at AUIPC+4, while the LO12 handler did nothing unless it sat
exactly 4 bytes after the AUIPC (otherwise it took the unimplemented
goto fail_addr_out_of_range path).

This assumption holds for older toolchains but breaks with LLVM 22, whose
instruction scheduler may place unrelated instructions between the AUIPC
and its %pcrel_lo instruction (and may emit several %pcrel_lo accesses
sharing a single AUIPC). The result was corrupted code: the HI20 handler
clobbered the unrelated instruction at AUIPC+4, and the LO12 patch was
skipped, leading to illegal-instruction faults or hangs at runtime
(e.g. i32.ctz de Bruijn tables, switch/br_table jump tables, and any
PC-relative rodata access).

Pair the two relocations by address, the way a linker does:

- Split R_RISCV_CALL/CALL_PLT (whose AUIPC+JALR pair really is adjacent)
  into its own case, leaving its AUIPC+4 patching unchanged.
- R_RISCV_PCREL_HI20 now patches only the AUIPC high 20 bits and records
  the resolved PC-relative value keyed by the AUIPC address in a small
  thread-local most-recently-used cache.
- R_RISCV_PCREL_LO12_I/S reconstructs the AUIPC address from symbol+addend,
  looks up the cached value, and patches its own instruction with the
  correct I-type (load/ADDI) or S-type (store) immediate.

This works regardless of instruction placement and when multiple LO12
accesses share one AUIPC. The cache is thread-local so concurrent module
loads do not interfere.

Fixes the RISC-V64 AOT spec-test suite under QEMU/NuttX.
@stertl stertl force-pushed the dev/update_to_llvm_22 branch from 29b9b03 to 8793961 Compare June 10, 2026 10:51
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.

2 participants