Skip to content

Inefficient assembly for semantically equivalent way of matching on enum #85841

Closed
@e00E

Description

@e00E

https://godbolt.org/z/fYfohcsax

#[derive(Clone, Copy)]
pub enum E {
    E0,
    E1,
    E2,
    E3,
}

impl E {
    pub fn next0(self) -> Option<Self> {
        match self {
            E::E0 => Some(E::E1),
            E::E1 => Some(E::E2),
            E::E2 => Some(E::E3),
            E::E3 => None,
        }
    }

    pub fn next1(self) -> Option<Self> {
        Some(match self {
            E::E0 => E::E1,
            E::E1 => E::E2,
            E::E2 => E::E3,
            E::E3 => return None,
        })
    }
}

Optimized assembly on stable 1.52.0 and nightly:

example::E::next0:
        lea     eax, [rdi + 1]
        ret

example::E::next1:
        mov     al, 4
        mov     cl, 1
        movzx   edx, dil
        lea     rsi, [rip + .LJTI1_0]
        movsxd  rdx, dword ptr [rsi + 4*rdx]
        add     rdx, rsi
        jmp     rdx
.LBB1_1:
        mov     cl, 2
        jmp     .LBB1_3
.LBB1_2:
        mov     cl, 3
.LBB1_3:
        mov     eax, ecx
.LBB1_4:
        ret
.LJTI1_0:
        .long   .LBB1_3-.LJTI1_0
        .long   .LBB1_1-.LJTI1_0
        .long   .LBB1_2-.LJTI1_0
        .long   .LBB1_4-.LJTI1_0

I expected next1 to compile to the same assembly as next0.

Edit 2022-12-01: Not fixed on current stable 1.65 and nightly.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-LLVMArea: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.C-bugCategory: This is a bug.I-slowIssue: Problems and improvements with respect to performance of generated code.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions