Rollup merge of #124699 - scottmcm:split_at_unchecked_should_use_unchecked, r=Nilstrieb

Use `unchecked_sub` in `split_at`

LLVM currently isn't figuring it out on its own, even in the checked version where it hypothetically could.

Before: <https://rust.godbolt.org/z/PEY38YrKs>
```llvm
bb1:                                              ; preds = %start
  %4 = getelementptr inbounds float, ptr %x.0, i64 %n
  %5 = sub i64 %x.1, %n
```

After:
```llvm
bb1:                                              ; preds = %start
  %4 = getelementptr inbounds float, ptr %x.0, i64 %n
  %5 = sub nuw i64 %x.1, %n
```

This is not using the wrapper because there's already a ubcheck covering it, so I don't want this to get a second one once #121571 lands.

---

This is basically the same as #108763, since `split_at` is essentially doing two `get_unchecked`s.
This commit is contained in:
Matthias Krüger 2024-05-04 18:36:38 +02:00 committed by GitHub
commit a5cc1f663f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -9,7 +9,7 @@
use crate::cmp::Ordering::{self, Equal, Greater, Less}; use crate::cmp::Ordering::{self, Equal, Greater, Less};
use crate::fmt; use crate::fmt;
use crate::hint; use crate::hint;
use crate::intrinsics::exact_div; use crate::intrinsics::{exact_div, unchecked_sub};
use crate::mem::{self, SizedTypeProperties}; use crate::mem::{self, SizedTypeProperties};
use crate::num::NonZero; use crate::num::NonZero;
use crate::ops::{Bound, OneSidedRange, Range, RangeBounds}; use crate::ops::{Bound, OneSidedRange, Range, RangeBounds};
@ -1983,7 +1983,7 @@ pub const fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) {
); );
// SAFETY: Caller has to check that `0 <= mid <= self.len()` // SAFETY: Caller has to check that `0 <= mid <= self.len()`
unsafe { (from_raw_parts(ptr, mid), from_raw_parts(ptr.add(mid), len - mid)) } unsafe { (from_raw_parts(ptr, mid), from_raw_parts(ptr.add(mid), unchecked_sub(len, mid))) }
} }
/// Divides one mutable slice into two at an index, without doing bounds checking. /// Divides one mutable slice into two at an index, without doing bounds checking.
@ -2035,7 +2035,12 @@ pub const fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) {
// //
// `[ptr; mid]` and `[mid; len]` are not overlapping, so returning a mutable reference // `[ptr; mid]` and `[mid; len]` are not overlapping, so returning a mutable reference
// is fine. // is fine.
unsafe { (from_raw_parts_mut(ptr, mid), from_raw_parts_mut(ptr.add(mid), len - mid)) } unsafe {
(
from_raw_parts_mut(ptr, mid),
from_raw_parts_mut(ptr.add(mid), unchecked_sub(len, mid)),
)
}
} }
/// Divides one slice into two at an index, returning `None` if the slice is /// Divides one slice into two at an index, returning `None` if the slice is