From d08996ac543b4d330bef790ff9f727e99c7a539c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Wed, 26 Aug 2020 09:59:04 +0300 Subject: [PATCH] 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. --- library/core/src/slice/mod.rs | 16 ++++++++++------ 1 file 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 @@ pub fn chunks_mut(&mut self, chunk_size: usize) -> ChunksMut<'_, 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 @@ pub fn chunks_exact(&self, chunk_size: usize) -> ChunksExact<'_, 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 @@ pub fn rchunks_mut(&mut self, chunk_size: usize) -> RChunksMut<'_, 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 @@ pub fn rchunks_exact(&self, chunk_size: usize) -> RChunksExact<'_, 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 } }