]> git.lizzy.rs Git - rust.git/commitdiff
Get rid of bounds check in slice::chunks_exact() and related functions during constru...
authorSebastian Dröge <sebastian@centricular.com>
Wed, 26 Aug 2020 06:59:04 +0000 (09:59 +0300)
committerSebastian Dröge <sebastian@centricular.com>
Sun, 30 Aug 2020 20:13:47 +0000 (23:13 +0300)
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

index d5f32ccc49bd636764a465df02308b8350686ae7..1f207198dedfd685351991b98e3f36ccde871e64 100644 (file)
@@ -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 }
     }