From e822937428e80bb9609a40b298d1c8b4e157c6ef Mon Sep 17 00:00:00 2001 From: Philippe-Cholet <44676486+Philippe-Cholet@users.noreply.github.com> Date: Tue, 26 Mar 2024 11:19:27 +0100 Subject: [PATCH] Add invariant to VecDeque::pop_* that len < cap if pop successful Similar to #114370 for VecDeque instead of Vec. --- .../alloc/src/collections/vec_deque/mod.rs | 6 ++ tests/codegen/vecdeque_pop_push.rs | 75 +++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100644 tests/codegen/vecdeque_pop_push.rs diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index 41adc2e79dc74..07b1b73c4f6a5 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -1614,6 +1614,9 @@ impl VecDeque { let old_head = self.head; self.head = self.to_physical_idx(1); self.len -= 1; + unsafe { + core::intrinsics::assume(self.len < self.capacity()); + } Some(unsafe { self.buffer_read(old_head) }) } } @@ -1638,6 +1641,9 @@ impl VecDeque { None } else { self.len -= 1; + unsafe { + core::intrinsics::assume(self.len < self.capacity()); + } Some(unsafe { self.buffer_read(self.to_physical_idx(self.len)) }) } } diff --git a/tests/codegen/vecdeque_pop_push.rs b/tests/codegen/vecdeque_pop_push.rs new file mode 100644 index 0000000000000..c0c28a1193367 --- /dev/null +++ b/tests/codegen/vecdeque_pop_push.rs @@ -0,0 +1,75 @@ +//@ compile-flags: -O + +#![crate_type = "lib"] + +use std::collections::VecDeque; + +#[no_mangle] +// CHECK-LABEL: @noop_back( +pub fn noop_back(v: &mut VecDeque) { + // CHECK-NOT: reserve_for_push + // CHECK-NOT: call + // CHECK: tail call void @llvm.assume + // CHECK-NOT: reserve_for_push + // CHECK-NOT: call + // CHECK: ret + if let Some(x) = v.pop_back() { + v.push_back(x); + } +} + +#[no_mangle] +// CHECK-LABEL: @noop_front( +pub fn noop_front(v: &mut VecDeque) { + // CHECK-NOT: reserve_for_push + // CHECK-NOT: call + // CHECK: tail call void @llvm.assume + // CHECK-NOT: reserve_for_push + // CHECK-NOT: call + // CHECK: ret + if let Some(x) = v.pop_front() { + v.push_front(x); + } +} + +#[no_mangle] +// CHECK-LABEL: @move_byte_front_to_back( +pub fn move_byte_front_to_back(v: &mut VecDeque) { + // CHECK-NOT: reserve_for_push + // CHECK-NOT: call + // CHECK: tail call void @llvm.assume + // CHECK-NOT: reserve_for_push + // CHECK-NOT: call + // CHECK: ret + if let Some(x) = v.pop_front() { + v.push_back(x); + } +} + +#[no_mangle] +// CHECK-LABEL: @move_byte_back_to_front( +pub fn move_byte_back_to_front(v: &mut VecDeque) { + // CHECK-NOT: reserve_for_push + // CHECK-NOT: call + // CHECK: tail call void @llvm.assume + // CHECK-NOT: reserve_for_push + // CHECK-NOT: call + // CHECK: ret + if let Some(x) = v.pop_back() { + v.push_front(x); + } +} + +#[no_mangle] +// CHECK-LABEL: @push_back_byte( +pub fn push_back_byte(v: &mut VecDeque) { + // CHECK: call {{.*}}reserve_for_push + v.push_back(3); +} + +#[no_mangle] +// CHECK-LABEL: @push_front_byte( +pub fn push_front_byte(v: &mut VecDeque) { + // CHECK: call {{.*}}reserve_for_push + v.push_front(3); +}