Codegen Optimization for Non-Consecutive Enum Match Arms
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 119k
- Forks
- 16.1k
- PR merge metrics
- PR metrics pending
Description
I tried this code:
enum Foo {
Field1 = 10,
Field2 = 11,
Field3 = 12,
Field4 = 20,
}
#[no_mangle]
fn f(value: u32) -> Foo {
match value {
10 => Foo::Field1,
11 => Foo::Field2,
12 => Foo::Field3,
20 => Foo::Field4,
_ => unreachable!(),
}
}
It was compiled as jump table.
f:
add edi, -10
cmp edi, 10
ja .LBB0_3
lea rax, [rip + .LJTI0_0]
movsxd rcx, dword ptr [rax + 4*rdi]
add rcx, rax
jmp rcx
.LBB0_2:
mov al, 10
ret
.LBB0_5:
mov al, 12
ret
.LBB0_6:
mov al, 20
ret
.LBB0_4:
mov al, 11
ret
For the case of smaller range, the compiler used another optimization.
#[no_mangle]
fn f(value: u32) -> Foo {
match value {
10 => Foo::Field1,
11 => Foo::Field2,
12 => Foo::Field3,
14 => Foo::Field4,
_ => unreachable!(),
}
}
f:
add edi, -10
cmp edi, 5
jae .LBB0_3
mov eax, 23
bt eax, edi
jae .LBB0_3
shl edi, 3
movabs rax, 86067907338
mov ecx, edi
shr rax, cl
ret
For the case taht matching arms are more than 4, the compiler used lookup table.
enum Foo {
Field1 = 10,
Field2 = 11,
Field3 = 12,
Field4 = 13,
Field5 = 20,
}
#[no_mangle]
fn f(value: u32) -> Foo {
match value {
10 => Foo::Field1,
11 => Foo::Field2,
12 => Foo::Field3,
13 => Foo::Field4,
20 => Foo::Field5,
_ => unreachable!(),
}
}
f:
add edi, -10
cmp edi, 11
jae .LBB0_3
mov eax, 1039
bt eax, edi
jae .LBB0_3
mov eax, edi
lea rcx, [rip + .Lswitch.table.f]
movzx eax, byte ptr [rax + rcx]
ret
I expected this, which can be attained only when the arm values are consecutive.
enum Foo {
Field1 = 10,
Field2 = 11,
Field3 = 12,
Field4 = 13,
Field5 = 14,
}
#[no_mangle]
fn f(value: u32) -> Foo {
match value {
10 => Foo::Field1,
11 => Foo::Field2,
12 => Foo::Field3,
13 => Foo::Field4,
14 => Foo::Field5,
_ => unreachable!(),
}
}
f:
add edi, -10
cmp edi, 5
jae .LBB0_2
add dil, 10
mov eax, edi
ret
Meta
rustc --version --verbose:
rustc 1.86.0 (05f9846f8 2025-03-31)
binary: rustc
commit-hash: 05f9846f893b09a1be1fc8560e33fc3c815cfecb
commit-date: 2025-03-31
host: x86_64-unknown-linux-gnu
release: 1.86.0
LLVM version: 19.1.7
Internal compiler ID: r1860
Compiler options:
-Copt-level=3
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 supplied Rust reproducer using rustc 1.86.0 and -Copt-level=3, comparing generated assembly for the three match layouts. Trace the compiler codegen optimization path that selects jump tables, bit tests, or lookup tables. Done means non-consecutive enum arms receive the expected compact handling without regressing the other examples.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100