Skip to content

Commit d08996a

Browse files
committed
Get rid of bounds check in slice::chunks_exact() and related functions during construction
LLVM can't figure out in let rem = self.len() % chunk_size; let len = self.len() - rem; let (fst, snd) = self.split_at(len); and let rem = self.len() % chunk_size; let (fst, snd) = self.split_at(rem); that the index passed to split_at() is smaller than the slice length and adds a bounds check plus panic for it. Apart from removing the overhead of the bounds check this also allows LLVM to optimize code around the ChunksExact iterator better.
1 parent 30dc32b commit d08996a

File tree

1 file changed

+10
-6
lines changed

1 file changed

+10
-6
lines changed

library/core/src/slice/mod.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -865,8 +865,9 @@ impl<T> [T] {
865865
pub fn chunks_exact(&self, chunk_size: usize) -> ChunksExact<'_, T> {
866866
assert_ne!(chunk_size, 0);
867867
let rem = self.len() % chunk_size;
868-
let len = self.len() - rem;
869-
let (fst, snd) = self.split_at(len);
868+
let fst_len = self.len() - rem;
869+
// SAFETY: 0 <= fst_len <= self.len() by construction above
870+
let (fst, snd) = unsafe { self.split_at_unchecked(fst_len) };
870871
ChunksExact { v: fst, rem: snd, chunk_size }
871872
}
872873

@@ -910,8 +911,9 @@ impl<T> [T] {
910911
pub fn chunks_exact_mut(&mut self, chunk_size: usize) -> ChunksExactMut<'_, T> {
911912
assert_ne!(chunk_size, 0);
912913
let rem = self.len() % chunk_size;
913-
let len = self.len() - rem;
914-
let (fst, snd) = self.split_at_mut(len);
914+
let fst_len = self.len() - rem;
915+
// SAFETY: 0 <= fst_len <= self.len() by construction above
916+
let (fst, snd) = unsafe { self.split_at_mut_unchecked(fst_len) };
915917
ChunksExactMut { v: fst, rem: snd, chunk_size }
916918
}
917919

@@ -1063,7 +1065,8 @@ impl<T> [T] {
10631065
pub fn rchunks_exact(&self, chunk_size: usize) -> RChunksExact<'_, T> {
10641066
assert!(chunk_size != 0);
10651067
let rem = self.len() % chunk_size;
1066-
let (fst, snd) = self.split_at(rem);
1068+
// SAFETY: 0 <= rem <= self.len() by construction above
1069+
let (fst, snd) = unsafe { self.split_at_unchecked(rem) };
10671070
RChunksExact { v: snd, rem: fst, chunk_size }
10681071
}
10691072

@@ -1108,7 +1111,8 @@ impl<T> [T] {
11081111
pub fn rchunks_exact_mut(&mut self, chunk_size: usize) -> RChunksExactMut<'_, T> {
11091112
assert!(chunk_size != 0);
11101113
let rem = self.len() % chunk_size;
1111-
let (fst, snd) = self.split_at_mut(rem);
1114+
// SAFETY: 0 <= rem <= self.len() by construction above
1115+
let (fst, snd) = unsafe { self.split_at_mut_unchecked(rem) };
11121116
RChunksExactMut { v: snd, rem: fst, chunk_size }
11131117
}
11141118

0 commit comments

Comments
 (0)