Skip to content

Commit 5137d8a

Browse files
committed
Auto merge of rust-lang#116568 - kornelski:hint-reserved, r=<try>
Hint optimizer about reserved capacity The fact that `Vec` had capacity increased is not known to the optimizer, because functions like `do_reserve_and_handle` are not inlined. Because of that, code such as: ```rust vec.try_reserve(123)?; vec.extend_from_slice(&s[..123]); ``` Tries to reserve the capacity **twice**. This is unnecessary code bloat. https://rust.godbolt.org/z/YWY16Ezej Adding a hint after reserve optimizes out the next check of `self.needs_to_grow(len, additional)`.
2 parents fa6d1e7 + 9a55d7a commit 5137d8a

File tree

2 files changed

+19
-5
lines changed

2 files changed

+19
-5
lines changed

library/alloc/src/raw_vec.rs

+18-4
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,10 @@ impl<T, A: Allocator> RawVec<T, A> {
291291

292292
if self.needs_to_grow(len, additional) {
293293
do_reserve_and_handle(self, len, additional);
294+
unsafe {
295+
// Inform the optimizer that the reservation has succeeded
296+
core::intrinsics::assume(!self.needs_to_grow(len, additional));
297+
}
294298
}
295299
}
296300

@@ -305,10 +309,13 @@ impl<T, A: Allocator> RawVec<T, A> {
305309
/// The same as `reserve`, but returns on errors instead of panicking or aborting.
306310
pub fn try_reserve(&mut self, len: usize, additional: usize) -> Result<(), TryReserveError> {
307311
if self.needs_to_grow(len, additional) {
308-
self.grow_amortized(len, additional)
309-
} else {
310-
Ok(())
312+
self.grow_amortized(len, additional)?;
313+
unsafe {
314+
// Inform the optimizer that the reservation has succeeded
315+
core::intrinsics::assume(!self.needs_to_grow(len, additional));
316+
}
311317
}
318+
Ok(())
312319
}
313320

314321
/// Ensures that the buffer contains at least enough space to hold `len +
@@ -339,7 +346,14 @@ impl<T, A: Allocator> RawVec<T, A> {
339346
len: usize,
340347
additional: usize,
341348
) -> Result<(), TryReserveError> {
342-
if self.needs_to_grow(len, additional) { self.grow_exact(len, additional) } else { Ok(()) }
349+
if self.needs_to_grow(len, additional) {
350+
self.grow_exact(len, additional)?;
351+
unsafe {
352+
// Inform the optimizer that the reservation has succeeded
353+
core::intrinsics::assume(!self.needs_to_grow(len, additional));
354+
}
355+
}
356+
Ok(())
343357
}
344358

345359
/// Shrinks the buffer down to the specified capacity. If the given amount
+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
thread 'main' panicked at library/alloc/src/raw_vec.rs:534:5:
1+
thread 'main' panicked at library/alloc/src/raw_vec.rs:548:5:
22
capacity overflow
33
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

0 commit comments

Comments
 (0)