about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLukas Markeffsky <@>2023-11-23 23:31:19 +0100
committerLukas Markeffsky <@>2024-02-16 13:10:52 +0100
commitb6702939f72c6c55a74fc5f343d34c01e3d8521b (patch)
treefdf2fca266bc817c156956d2e9e0027d8eb7e99e
parent1e3849aed010c3ff2a4c7b7b644ca67d087ab4c1 (diff)
downloadrust-b6702939f72c6c55a74fc5f343d34c01e3d8521b.tar.gz
rust-b6702939f72c6c55a74fc5f343d34c01e3d8521b.zip
outline large copies
-rw-r--r--library/alloc/src/collections/vec_deque/drain.rs27
1 files changed, 20 insertions, 7 deletions
diff --git a/library/alloc/src/collections/vec_deque/drain.rs b/library/alloc/src/collections/vec_deque/drain.rs
index 7a413ddf971..bf8c9b2d47a 100644
--- a/library/alloc/src/collections/vec_deque/drain.rs
+++ b/library/alloc/src/collections/vec_deque/drain.rs
@@ -121,7 +121,27 @@ impl<T, A: Allocator> Drop for Drain<'_, T, A> {
                 let head_len = source_deque.len();
                 let tail_len = new_len - head_len;
 
+                // When draining at the front (`.drain(..n)`) or at the back (`.drain(n..)`),
+                // we don't need to copy any data.
+                // Outlining this function helps LLVM to eliminate the copies in these cases.
                 if head_len != 0 && tail_len != 0 {
+                    copy_data(source_deque, drain_len, head_len, tail_len);
+                }
+
+                if new_len == 0 {
+                    source_deque.head = 0;
+                } else if head_len < tail_len {
+                    source_deque.head = source_deque.to_physical_idx(drain_len);
+                }
+                source_deque.len = new_len;
+
+                #[cold]
+                fn copy_data<T, A: Allocator>(
+                    source_deque: &mut VecDeque<T, A>,
+                    drain_len: usize,
+                    head_len: usize,
+                    tail_len: usize,
+                ) {
                     let (src, dst, len);
                     if head_len < tail_len {
                         src = source_deque.head;
@@ -137,13 +157,6 @@ impl<T, A: Allocator> Drop for Drain<'_, T, A> {
                         source_deque.wrap_copy(src, dst, len);
                     }
                 }
-
-                if new_len == 0 {
-                    source_deque.head = 0;
-                } else if head_len < tail_len {
-                    source_deque.head = source_deque.to_physical_idx(drain_len);
-                }
-                source_deque.len = new_len;
             }
         }