Missed optimization when removing intermediate · Issue #116150 · rust-lang/rust (original) (raw)
Using Rust 1.72.0:
pub fn f(err: i32) -> Result<u16, i32> { if err < 0 { return Err(err); }
Ok(err as u16)
}
compiles to:
example::f: mov ecx, edi shl ecx, 16 xor eax, eax test edi, edi cmovns eax, ecx mov ecx, edi shr ecx, 31 shl rdi, 32 or rax, rdi or rax, rcx ret
But adding an intermediate before the conditional appears to help:
pub fn f(err: i32) -> Result<u16, i32> { let ok = err as u16;
if err < 0 {
return Err(err);
};
Ok(ok)
}
compiles to:
example::f: mov ecx, edi shr ecx, 31 mov rax, rdi shl rax, 32 shl edi, 16 or rax, rdi or rax, rcx ret
https://godbolt.org/z/bf6jW9d3c
This intermediate could be an argument in a call, which is in fact how I originally noticed it, i.e. this:
fn to_result_ok(err: i32, ok: T) -> Result<T, i32> { if err < 0 { return Err(err); }
Ok(ok)
}
pub fn f(ret: i32) -> Result<u16, i32> { to_result_ok(ret, ret as u16) }
compiles better than:
pub fn f(ret: i32) -> Result<u16, i32> { if ret < 0 { return Err(ret); }
Ok(ret as u16)
}