Skip to content

Commit

Permalink
Auto merge of rust-lang#116568 - kornelski:hint-reserved, r=<try>
Browse files Browse the repository at this point in the history
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)`.
  • Loading branch information
bors committed Oct 10, 2023
2 parents fa6d1e7 + 9a55d7a commit 5137d8a
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 5 deletions.
22 changes: 18 additions & 4 deletions library/alloc/src/raw_vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,10 @@ impl<T, A: Allocator> RawVec<T, A> {

if self.needs_to_grow(len, additional) {
do_reserve_and_handle(self, len, additional);
unsafe {
// Inform the optimizer that the reservation has succeeded
core::intrinsics::assume(!self.needs_to_grow(len, additional));
}
}
}

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

/// Ensures that the buffer contains at least enough space to hold `len +
Expand Down Expand Up @@ -339,7 +346,14 @@ impl<T, A: Allocator> RawVec<T, A> {
len: usize,
additional: usize,
) -> Result<(), TryReserveError> {
if self.needs_to_grow(len, additional) { self.grow_exact(len, additional) } else { Ok(()) }
if self.needs_to_grow(len, additional) {
self.grow_exact(len, additional)?;
unsafe {
// Inform the optimizer that the reservation has succeeded
core::intrinsics::assume(!self.needs_to_grow(len, additional));
}
}
Ok(())
}

/// Shrinks the buffer down to the specified capacity. If the given amount
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/hygiene/panic-location.run.stderr
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
thread 'main' panicked at library/alloc/src/raw_vec.rs:534:5:
thread 'main' panicked at library/alloc/src/raw_vec.rs:548:5:
capacity overflow
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

0 comments on commit 5137d8a

Please sign in to comment.