Skip to content

Commit

Permalink
Get rid of bounds check in slice::chunks_exact() and related function…
Browse files Browse the repository at this point in the history
…s 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.
  • Loading branch information
sdroege committed Aug 30, 2020
1 parent 30dc32b commit d08996a
Showing 1 changed file with 10 additions and 6 deletions.
16 changes: 10 additions & 6 deletions library/core/src/slice/mod.rs
Expand Up @@ -865,8 +865,9 @@ impl<T> [T] {
pub fn chunks_exact(&self, chunk_size: usize) -> ChunksExact<'_, T> {
assert_ne!(chunk_size, 0);
let rem = self.len() % chunk_size;
let len = self.len() - rem;
let (fst, snd) = self.split_at(len);
let fst_len = self.len() - rem;
// SAFETY: 0 <= fst_len <= self.len() by construction above
let (fst, snd) = unsafe { self.split_at_unchecked(fst_len) };
ChunksExact { v: fst, rem: snd, chunk_size }
}

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

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

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

Expand Down

0 comments on commit d08996a

Please sign in to comment.