-
Notifications
You must be signed in to change notification settings - Fork 13.7k
Description
This function should compile to the exact same assembly as FileType::is_file
itself, but doesn't: (godbolt.org link)
pub fn is_file(x: std::fs::FileType) -> bool {
x.is_file()
}
example::is_file:
push rax
mov dword ptr [rsp + 4], edi
lea rdi, [rsp + 4]
call qword ptr [rip + std::fs::FileType::is_file@GOTPCREL]
pop rcx
ret
FileType::is_file
is only 2-3 instructions and should surely meet the inlining threshold. Other functions such as std::fs::Metadata::ino
(provided by std::os::unix::fs::MetadataExt
) are also not inlined, despite ino()
being just a single load.
This also prevents simple optimizations; despite being a pure function, calling is_file()
twice results in two separate call instructions just to load, mask and compare the same unchanged var: (godbolt.org link)
When compiling a binary with LTO enabled, these functions get inlined as they should, as far as I can tell, but otherwise there seems to be some kind of boundary preventing the compiler from inlining them.
None of the functions in question are marked #[inline]
, but neither is Vec::is_empty
for example, yet that function gets inlined just fine.
This bug is present as early as rust 1.1.0 and is present in the current nightly:
rustc 1.47.0-nightly (05762e3d6 2020-08-01)
binary: rustc
commit-hash: 05762e3d6f5facafdd47efdf4203021fadf61bb1
commit-date: 2020-08-01
host: x86_64-unknown-linux-gnu
release: 1.47.0-nightly
LLVM version: 10.0