diff options
| author | Sebastian Dröge <sebastian@centricular.com> | 2020-08-26 09:59:04 +0300 |
|---|---|---|
| committer | Sebastian Dröge <sebastian@centricular.com> | 2020-08-30 23:13:47 +0300 |
| commit | d08996ac543b4d330bef790ff9f727e99c7a539c (patch) | |
| tree | 554b264fd6cb49b27723ea87533224ed82b38df4 | |
| parent | 30dc32b10eb53e4a92c61a42062983db58838217 (diff) | |
| download | rust-d08996ac543b4d330bef790ff9f727e99c7a539c.tar.gz rust-d08996ac543b4d330bef790ff9f727e99c7a539c.zip | |
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.
| -rw-r--r-- | library/core/src/slice/mod.rs | 16 |
1 files changed, 10 insertions, 6 deletions
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index d5f32ccc49b..1f207198ded 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -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 } } @@ -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 } } @@ -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 } } @@ -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 } } |
