Skip to content

Commit

Permalink
Auto merge of rust-lang#123930 - Mark-Simulacrum:vec-length-invariant…
Browse files Browse the repository at this point in the history
…, r=jhpratt

Tell LLVM Vec::len is invariant across growth

This allows LLVM to avoid re-loading it from memory.
  • Loading branch information
bors committed Apr 21, 2024
2 parents 426a698 + f1ae531 commit 13eb8c7
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 3 deletions.
8 changes: 5 additions & 3 deletions library/alloc/src/vec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1991,15 +1991,17 @@ impl<T, A: Allocator> Vec<T, A> {
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_confusables("push_back", "put", "append")]
pub fn push(&mut self, value: T) {
// Inform codegen that the length does not change across grow_one().
let len = self.len;
// This will panic or abort if we would allocate > isize::MAX bytes
// or if the length increment would overflow for zero-sized types.
if self.len == self.buf.capacity() {
if len == self.buf.capacity() {
self.buf.grow_one();
}
unsafe {
let end = self.as_mut_ptr().add(self.len);
let end = self.as_mut_ptr().add(len);
ptr::write(end, value);
self.len += 1;
self.len = len + 1;
}
}

Expand Down
16 changes: 16 additions & 0 deletions tests/codegen/vec-len-invariant.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//@ compile-flags: -O
//@ only-64bit
//
// This test confirms that we do not reload the length of a Vec after growing it in push.

#![crate_type = "lib"]

// CHECK-LABEL: @should_load_once
#[no_mangle]
pub fn should_load_once(v: &mut Vec<u8>) {
// CHECK: load i64
// CHECK: call {{.*}}grow_one
// CHECK-NOT: load i64
// CHECK: add {{.*}}, 1
v.push(1);
}

0 comments on commit 13eb8c7

Please sign in to comment.