Skip to content

Commit f1ae531

Browse files
Avoid reloading Vec::len across grow_one in push
This saves an extra load from memory.
1 parent c3ceb00 commit f1ae531

File tree

2 files changed

+21
-3
lines changed

2 files changed

+21
-3
lines changed

Diff for: library/alloc/src/vec/mod.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -1991,15 +1991,17 @@ impl<T, A: Allocator> Vec<T, A> {
19911991
#[stable(feature = "rust1", since = "1.0.0")]
19921992
#[rustc_confusables("push_back", "put", "append")]
19931993
pub fn push(&mut self, value: T) {
1994+
// Inform codegen that the length does not change across grow_one().
1995+
let len = self.len;
19941996
// This will panic or abort if we would allocate > isize::MAX bytes
19951997
// or if the length increment would overflow for zero-sized types.
1996-
if self.len == self.buf.capacity() {
1998+
if len == self.buf.capacity() {
19971999
self.buf.grow_one();
19982000
}
19992001
unsafe {
2000-
let end = self.as_mut_ptr().add(self.len);
2002+
let end = self.as_mut_ptr().add(len);
20012003
ptr::write(end, value);
2002-
self.len += 1;
2004+
self.len = len + 1;
20032005
}
20042006
}
20052007

Diff for: tests/codegen/vec-len-invariant.rs

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//@ compile-flags: -O
2+
//@ only-64bit
3+
//
4+
// This test confirms that we do not reload the length of a Vec after growing it in push.
5+
6+
#![crate_type = "lib"]
7+
8+
// CHECK-LABEL: @should_load_once
9+
#[no_mangle]
10+
pub fn should_load_once(v: &mut Vec<u8>) {
11+
// CHECK: load i64
12+
// CHECK: call {{.*}}grow_one
13+
// CHECK-NOT: load i64
14+
// CHECK: add {{.*}}, 1
15+
v.push(1);
16+
}

0 commit comments

Comments
 (0)