multiply to shift optimization not used?

85 points chokomancarr 40 comments

I heard that compilers can turn multiplications into shifts to make them faster, so I decided to test it out.

I wrote the simplest code on the Playground:

#[unsafe(no_mangle)]
fn a(x: u32) -> u32 {
    x * 8
}

compiled it in release mode, and it emits the following assembly:

a:
    lea x, [8*rdi]
    ret

It keeps the multiply instruction, even when the right operand is a constant and trivial to convert to a shift.

In fact, the multiply -> shift only starts to kick in for the following:

enum E {
    A, B, C
}

#[unsafe(no_mangle)]
fn a(x: u32, e: E) -> u32 {
    match e {
        E::A => x * 8,
        E::B => 12,
        _ => 42,
    }
}

where the expected shl eax, 3 is generated.

(in fact, if you comment out the E::B match case, it falls back to multiply!)

I know this is a tiny optimization that probably wont matter in the grand scale of things, but is there a reason this simple optimization is ignored for certain programs?