Missed optimization: converting "equivalent" enum
s · Issue #116272 · rust-lang/rust (original) (raw)
With Rust 1.72.0:
#[repr(u32)] pub enum E1 { A = 0, B = 1, C = 255, }
pub enum E2 { A = 0, B = 1, C = 255, }
pub fn f(e: E1) -> E2 { match e { E1::A => E2::A, E1::B => E2::B, E1::C => E2::C, } }
pub fn g(e: E2) -> E1 { match e { E2::A => E1::A, E2::B => E1::B, E2::C => E1::C, } }
compiles to branches (f
) and a table-based approach (g
):
example::f: test edi, edi je .LBB0_1 cmp edi, 1 jne .LBB0_4 mov al, 1 ret .LBB0_1: xor eax, eax ret .LBB0_4: mov al, -1 ret
example::g: inc dil movsx rax, dil lea rcx, [rip + .Lswitch.table.example::g] mov eax, dword ptr [rcx + 4*rax] ret
.Lswitch.table.example::g: .long 255 .long 0 .long 1
However, they could simply be:
example::f: mov eax, edi ret
example::g: movzx eax, dil ret
https://godbolt.org/z/Ko5cKKojh
The compiler figures it out correctly if the values are contiguous (e.g. changing 255
above to 2
), or if the sizes / repr
is the same.
This sort of code may happen when one is safely wrapping an automatically generated Rust enum
from (e.g. from C code) into a better enum
(e.g. with a smaller layout, better docs or more idiomatic variant names).