Skip to content

Commit

Permalink
Auto merge of rust-lang#121300 - c410-f3r:perf-try, r=<try>
Browse files Browse the repository at this point in the history
[Experiment] Eliminate possible `Vec::push` branches

Related to rust-lang#105156. Requesting a perf run.

```rust
pub fn push(v: &mut Vec<u8>) {
    let _ = v.reserve(4);
    v.push(1);
    v.push(2);
    v.push(3);
    v.push(4);
}
```

AFAICT, the codegen backend should infer the infallibility of these `push`s but unfortunately with LLVM 18 we still have unnecessary `reserve_for_push` branches.

For the sake of curiosity, `assert_unchecked` was included in `push` to see any potential impact of such change. Take a look at the generated assembly at https://godbolt.org/z/b5jjPhsf8.

AFAICT (again), the assumption of more available capacity for each `push` is not valid for all situations.
  • Loading branch information
bors committed Feb 19, 2024
2 parents 43d3470 + e64d4ba commit ba16851
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 0 deletions.
5 changes: 5 additions & 0 deletions library/alloc/src/vec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -905,10 +905,14 @@ impl<T, A: Allocator> Vec<T, A> {
/// vec.reserve(10);
/// assert!(vec.capacity() >= 11);
/// ```
#[inline(always)]
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn reserve(&mut self, additional: usize) {
self.buf.reserve(self.len, additional);
unsafe {
core::hint::assert_unchecked(self.len().unchecked_add(additional) <= self.capacity());
}
}

/// Reserves the minimum capacity for at least `additional` more elements to
Expand Down Expand Up @@ -1925,6 +1929,7 @@ impl<T, A: Allocator> Vec<T, A> {
let end = self.as_mut_ptr().add(self.len);
ptr::write(end, value);
self.len += 1;
core::hint::assert_unchecked(self.len() <= self.capacity());
}
}

Expand Down
16 changes: 16 additions & 0 deletions tests/codegen/reserve_local_push.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// compile-flags: -O

#![crate_type = "lib"]

#[no_mangle]
pub fn push(v: &mut Vec<u8>) {
let _ = v.reserve(4);
// CHECK-NOT: call {{.*}}reserve_for_push
v.push(1);
// CHECK-NOT: call {{.*}}reserve_for_push
v.push(2);
// CHECK-NOT: call {{.*}}reserve_for_push
v.push(3);
// CHECK-NOT: call {{.*}}reserve_for_push
v.push(4);
}

0 comments on commit ba16851

Please sign in to comment.