Skip to content

Missed optimization: converting "equivalent" enums #116272

Open
@ojeda

Description

@ojeda

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).

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-LLVMArea: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.C-optimizationCategory: An issue highlighting optimization opportunities or PRs implementing suchI-slowIssue: Problems and improvements with respect to performance of generated code.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions