Closed
Description
Found while tracking down the root cause of the slowdown in #51340. This is the minimized code which reproduces the performance issue (Playground link).
#![crate_type = "rlib"]
use std::num::NonZeroUsize;
unsafe fn repeat(c: bool) -> Option<NonZeroUsize> {
if c {
None
} else {
Some(NonZeroUsize::new_unchecked(8))
}
}
pub unsafe fn calculate_layout(c: bool) -> usize {
match repeat(c) {
Some(x) => 8 - x.get(),
None => std::hint::unreachable_unchecked(),
}
}
This code produces the following output:
// ASM
playground::calculate_layout:
mov eax, edi
shl rax, 3
ret
// LLVM
define i64 @_ZN10playground16calculate_layout17h33252013a8d7ec56E(i1 zeroext %c) unnamed_addr #0 {
start:
%0 = select i1 %c, i64 8, i64 0
ret i64 %0
}
Note that in practice, it is impossible for this function to return anything other than 0 (8 - 8
) due to the call to unreachable_unchecked
.
The version using usize
does not suffer from this (Playground link):
#![crate_type = "rlib"]
unsafe fn repeat(c: bool) -> Option<usize> {
if c {
None
} else {
Some(8)
}
}
pub unsafe fn calculate_layout(c: bool) -> usize {
match repeat(c) {
Some(x) => 8 - x,
None => std::hint::unreachable_unchecked(),
}
}
The new code produces the following output:
// ASM
playground::calculate_layout:
xor eax, eax
ret
// LLVM
define i64 @_ZN10playground16calculate_layout17h33252013a8d7ec56E(i1 zeroext %c) unnamed_addr #0 {
start:
ret i64 0
}