rust-lang / rust-lang/rust

Suboptimal codegen for ARM32 targets when performing offset load

Open
#125,386 1 comment 2 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

A-codegen A-LLVM C-bug O-Arm S-has-mcve T-compiler
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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.