From de18ce14fb9d00c612dfdfaeb005a138897b4d79 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Fri, 11 Oct 2024 14:41:02 -0700 Subject: [PATCH] Avoid superfluous UB checks in `IndexRange` `IndexRange::len` is justified as an overall invariant, and `take_prefix` and `take_suffix` are justified by local branch conditions. A few more UB-checked calls remain in cases that are only supported locally by `debug_assert!`, which won't do anything in distributed builds, so those UB checks may still be useful. We generally expect core's `#![rustc_preserve_ub_checks]` to optimize away in user's release builds, but the mere presence of that extra code can sometimes inhibit optimization, as seen in #131563. --- core/src/ops/index_range.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/core/src/ops/index_range.rs b/core/src/ops/index_range.rs index 64214eae377dd..dce3514a1595b 100644 --- a/core/src/ops/index_range.rs +++ b/core/src/ops/index_range.rs @@ -45,7 +45,8 @@ impl IndexRange { #[inline] pub const fn len(&self) -> usize { // SAFETY: By invariant, this cannot wrap - unsafe { self.end.unchecked_sub(self.start) } + // Using the intrinsic because a UB check here impedes LLVM optimization. (#131563) + unsafe { crate::intrinsics::unchecked_sub(self.end, self.start) } } /// # Safety @@ -82,7 +83,8 @@ impl IndexRange { let mid = if n <= self.len() { // SAFETY: We just checked that this will be between start and end, // and thus the addition cannot overflow. - unsafe { self.start.unchecked_add(n) } + // Using the intrinsic avoids a superfluous UB check. + unsafe { crate::intrinsics::unchecked_add(self.start, n) } } else { self.end }; @@ -100,8 +102,9 @@ impl IndexRange { pub fn take_suffix(&mut self, n: usize) -> Self { let mid = if n <= self.len() { // SAFETY: We just checked that this will be between start and end, - // and thus the addition cannot overflow. - unsafe { self.end.unchecked_sub(n) } + // and thus the subtraction cannot overflow. + // Using the intrinsic avoids a superfluous UB check. + unsafe { crate::intrinsics::unchecked_sub(self.end, n) } } else { self.start };