Unnecessary branch when using enums as an array index
Open
Nobody has claimed this yet.
A-codegen
A-LLVM
C-optimization
S-has-mcve
T-compiler
- Dominant language
- Rust
- Stars
- 119k
- Forks
- 16.1k
- PR merge metrics
- PR metrics pending
Description
The following should be codegen into a simple array access, but instead a jump table is emitted:
enum E { Q,W,E,R,T,Y }
fn foo(e: E, x: &[i32; 6]) -> &i32 {
match e {
E::Q => &x[0],
E::W => &x[1],
E::E => &x[2],
E::R => &x[3],
E::T => &x[4],
E::Y => &x[5],
}
}
The same issue (unsurprisingly) occurs when using a struct with the same layout:
enum E { Q,W,E,R,T,Y }
// Should also work without, but force the layout anyways
#[repr(C)]
struct S {
q: i32,
w: i32,
e: i32,
r: i32,
t: i32,
y: i32,
}
fn foo(e: E, x: &S) -> &i32 {
match e {
E::Q => &x.q,
E::W => &x.w,
E::E => &x.e,
E::R => &x.r,
E::T => &x.t,
E::Y => &x.y,
}
}
If the array access is moved outside the match then codegen works as expected:
enum E { Q,W,E,R,T,Y }
fn foo(e: E, x: &[i32; 6]) -> &i32 {
&x[match e {
E::Q => 0,
E::W => 1,
E::E => 2,
E::R => 3,
E::T => 4,
E::Y => 5,
}]
}
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 with the Godbolt reproduction linked in the issue and compare the generated code for the enum-indexed array and struct cases with the working array-outside-match variant. Trace the relevant Rust compiler code-generation path, then verify that the reported examples produce direct indexed accesses rather than jump tables.
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