Skip to content

Commit b670293

Browse files
author
Lukas Markeffsky
committed
outline large copies
1 parent 1e3849a commit b670293

File tree

1 file changed

+20
-7
lines changed
  • library/alloc/src/collections/vec_deque

1 file changed

+20
-7
lines changed

library/alloc/src/collections/vec_deque/drain.rs

+20-7
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,27 @@ impl<T, A: Allocator> Drop for Drain<'_, T, A> {
121121
let head_len = source_deque.len();
122122
let tail_len = new_len - head_len;
123123

124+
// When draining at the front (`.drain(..n)`) or at the back (`.drain(n..)`),
125+
// we don't need to copy any data.
126+
// Outlining this function helps LLVM to eliminate the copies in these cases.
124127
if head_len != 0 && tail_len != 0 {
128+
copy_data(source_deque, drain_len, head_len, tail_len);
129+
}
130+
131+
if new_len == 0 {
132+
source_deque.head = 0;
133+
} else if head_len < tail_len {
134+
source_deque.head = source_deque.to_physical_idx(drain_len);
135+
}
136+
source_deque.len = new_len;
137+
138+
#[cold]
139+
fn copy_data<T, A: Allocator>(
140+
source_deque: &mut VecDeque<T, A>,
141+
drain_len: usize,
142+
head_len: usize,
143+
tail_len: usize,
144+
) {
125145
let (src, dst, len);
126146
if head_len < tail_len {
127147
src = source_deque.head;
@@ -137,13 +157,6 @@ impl<T, A: Allocator> Drop for Drain<'_, T, A> {
137157
source_deque.wrap_copy(src, dst, len);
138158
}
139159
}
140-
141-
if new_len == 0 {
142-
source_deque.head = 0;
143-
} else if head_len < tail_len {
144-
source_deque.head = source_deque.to_physical_idx(drain_len);
145-
}
146-
source_deque.len = new_len;
147160
}
148161
}
149162

0 commit comments

Comments
 (0)