Open
Description
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<T>(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)
}
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.