From 03d03c666c337acdaeb8911deaade55366bf8959 Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Fri, 16 Feb 2024 19:43:50 +0100 Subject: [PATCH] Always inline check in `assert_unsafe_precondition` with cfg(debug_assertions) The current complexities in `assert_unsafe_precondition` are delicately balancing several concerns, among them compile times for the cases where there are no debug assertions. This comes at a large runtime cost when the assertions are enabled, making the debug assertion compiler a lot slower, which is very annoying. To avoid this, we always inline the check when building with debug assertions. Numbers (compiling stage1 library after touching core): - master: 80s - just adding `#[inline(always)]` to the `cfg(bootstrap)` `debug_assertions`: 67s - this: 54s So this seems like a good solution. I think we can still get the same run-time perf improvements for other users too by massaging this code further (see my other PR about adding `#[rustc_no_mir_inline]`) but this is a simpler step that solves the imminent problem of "holy shit my rustc is sooo slow". Funny consequence: This now means compiling the standard library with dbeug assertions makes it faster (than without, when using debug assertions downstream)! --- library/core/src/intrinsics.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index ce1876d5a2f2f..d1ffc39ecbfc2 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -2575,6 +2575,7 @@ pub const fn is_val_statically_known(_arg: T) -> bool { /// assertions disabled. This intrinsic is primarily used by [`assert_unsafe_precondition`]. #[rustc_const_unstable(feature = "delayed_debug_assertions", issue = "none")] #[unstable(feature = "core_intrinsics", issue = "none")] +#[inline(always)] #[cfg_attr(not(bootstrap), rustc_intrinsic)] pub(crate) const fn debug_assertions() -> bool { cfg!(debug_assertions) @@ -2659,7 +2660,13 @@ pub const unsafe fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize) macro_rules! assert_unsafe_precondition { ($message:expr, ($($name:ident:$ty:ty = $arg:expr),*$(,)?) => $e:expr $(,)?) => { { - #[inline(never)] + // When the standard library is compiled with debug assertions, we want the check to inline for better performance. + // This is important when working on the compiler, which is compiled with debug assertions locally. + // When not compiled with debug assertions (so the precompiled std) we outline the check to minimize the compile + // time impact when debug assertions are disabled. + // It is not clear whether that is the best solution, see #120848. + #[cfg_attr(debug_assertions, inline(always))] + #[cfg_attr(not(debug_assertions), inline(never))] #[rustc_nounwind] fn precondition_check($($name:$ty),*) { if !$e {