Suboptimal codegen for ARM32 targets when performing offset load
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 119k
- Forks
- 16.1k
- PR merge metrics
- PR metrics pending
Description
rustc generates suboptimal code on 32-bit ARM targets when performing a load from a base + offset pointer. This seems to be a general issue, rearing its head in a number of programs I've written, including trivial examples.
Since this pattern - loading from a non-constant address that's been offset by an index - is very common in real code and in particular inner loops, I'd be surprised if this doesn't have a non-trivial impact on the performance of real code.
Note that LLVM doesn't seem to exhibit this poor behaviour on aarch64 (ARM 64) targets.
unsafe fn read(src: *const u16, n: usize) -> u16 {
src.byte_add(n).read()
}
produces
read:
add r0, r0, r1
ldrh r0, [r0]
bx lr
I'd expect it to produce
read:
ldrh r0, [r0, r1]
bx lr
as GCC does. I believe that on many targets (at the very least, armv4) the latter is always faster than the former.
Note that this is an issue with LLVM: Clang also exhibits this poor code generation.
Rust (rustc, bad): https://godbolt.org/z/7oPe8crM7
C (Clang, bad): https://godbolt.org/z/4M9E7Kh91
C (GCC, good): https://godbolt.org/z/639cxxKc8
I've not been able to test Rust's new GCC backend since I've not been able to work out how to tell it to generate code for ARM32 targets.
rustc --version --verbose:
rustc 1.79.0-nightly (8b2459c1f 2024-04-09)
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by compiling the provided unsafe Rust example for a 32-bit ARM target and comparing rustc's output with the expected indexed load and the linked GCC, Clang, and Rust Compiler Explorer examples. Investigate the LLVM code-generation path mentioned in the issue; done means ARM32 output uses the base-plus-index load form without regressing other targets.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- compilers, performance
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100