Why elementary enum handling so bad?

#1

For such code:

#[derive(Debug, Clone, Copy)]
pub enum Foo {
    A,
    B,
    C,
    D
}

pub fn f123(foo: Foo) -> &'static str {
    match foo {
        Foo::A => "A",
        Foo::B => "B",
        Foo::C => "C",
        Foo::D => "/",
    }
}

I got (according to playground https://play.rust-lang.org/?version=nightly&mode=release&edition=2018&gist=0e5da532d1634f8e0e0aff1d66794a7a ) assembly like this one:

playground::f123: # @playground::f123
# %bb.0:
	cmpb	$1, %dil
	je	.LBB0_4
# %bb.1:
	cmpb	$2, %dil
	je	.LBB0_5
# %bb.2:
	cmpb	$3, %dil
	jne	.LBB0_3
# %bb.6:
	leaq	.Lanon.60a2f94f5920661f72bb42f61759974b.0(%rip), %rax
	movl	$1, %edx
	retq

.LBB0_4:
	leaq	.Lanon.60a2f94f5920661f72bb42f61759974b.2(%rip), %rax
	movl	$1, %edx
	retq

.LBB0_5:
	leaq	.Lanon.60a2f94f5920661f72bb42f61759974b.1(%rip), %rax
	movl	$1, %edx
	retq

.LBB0_3:
	leaq	.Lanon.60a2f94f5920661f72bb42f61759974b.3(%rip), %rax
	movl	$1, %edx
	retq

so it is basically:

if foo == Foo::A {
   "A"
} else if 
...

I expect something like this:

let foo_index: u8 = magic_to_get_descriminant_index(foo);
static ARR[&'static str; 4] = ["A", "B", "C", "/"];
ARR[foo_index]

why compiler do this kind of optimization?

0 Likes

#2

Extending to a few more variants does something closer to what you expect. So in this case LLVM believes that the comparison chain is likely to be better than some form of array indexing, whether that’s the right call I have no idea.

10 Likes

#3

Also see this thread:

5 Likes