Open
Description
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
Labels
Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.Category: An issue highlighting optimization opportunities or PRs implementing suchIssue: Problems and improvements with respect to performance of generated code.Relevant to the compiler team, which will review and decide on the PR/issue.