about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2024-04-08 14:31:11 +0200
committerGitHub <noreply@github.com>2024-04-08 14:31:11 +0200
commit17c94b5f121ce05547ba5e47bfb1bfd6da317ee2 (patch)
treed846b5b650afe287ef0b18ee59d28e2a36f8f293
parent98fbf86af9aa425a273d7e28f94a52cef61231da (diff)
parent7a2678de7d3c0caa169542bd56a4fbf41b73a5b5 (diff)
downloadrust-17c94b5f121ce05547ba5e47bfb1bfd6da317ee2.tar.gz
rust-17c94b5f121ce05547ba5e47bfb1bfd6da317ee2.zip
Rollup merge of #123089 - Philippe-Cholet:vecdeque_pop_assume_cap, r=Nilstrieb
Add invariant to VecDeque::pop_* that len < cap if pop successful

Similar to #114370 for VecDeque instead of Vec.

I initially come from https://github.com/rust-itertools/itertools/pull/899 where we noticed that `pop_front;push_back;` was slower than expected so `@scottmcm` suggested I file an issue which lead to https://internals.rust-lang.org/t/vecdeque-pop-front-push-back/20483 where **kornel** mentionned #114334 (fixed by #114370).

This is my first time with codegen tests, I based the test on what was done for Vec.
-rw-r--r--library/alloc/src/collections/vec_deque/mod.rs10
-rw-r--r--tests/codegen/vecdeque_pop_push.rs67
2 files changed, 75 insertions, 2 deletions
diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs
index e2fc320f280..693ecb0b6b4 100644
--- a/library/alloc/src/collections/vec_deque/mod.rs
+++ b/library/alloc/src/collections/vec_deque/mod.rs
@@ -1614,7 +1614,10 @@ impl<T, A: Allocator> VecDeque<T, A> {
             let old_head = self.head;
             self.head = self.to_physical_idx(1);
             self.len -= 1;
-            Some(unsafe { self.buffer_read(old_head) })
+            unsafe {
+                core::hint::assert_unchecked(self.len < self.capacity());
+                Some(self.buffer_read(old_head))
+            }
         }
     }
 
@@ -1638,7 +1641,10 @@ impl<T, A: Allocator> VecDeque<T, A> {
             None
         } else {
             self.len -= 1;
-            Some(unsafe { self.buffer_read(self.to_physical_idx(self.len)) })
+            unsafe {
+                core::hint::assert_unchecked(self.len < self.capacity());
+                Some(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 00000000000..040d5a279dc
--- /dev/null
+++ b/tests/codegen/vecdeque_pop_push.rs
@@ -0,0 +1,67 @@
+//@ compile-flags: -O
+
+#![crate_type = "lib"]
+
+use std::collections::VecDeque;
+
+#[no_mangle]
+// CHECK-LABEL: @noop_back(
+pub fn noop_back(v: &mut VecDeque<u8>) {
+    // CHECK-NOT: grow
+    // CHECK: tail call void @llvm.assume
+    // CHECK-NOT: grow
+    // 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<u8>) {
+    // CHECK-NOT: grow
+    // CHECK: tail call void @llvm.assume
+    // CHECK-NOT: grow
+    // 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<u8>) {
+    // CHECK-NOT: grow
+    // CHECK: tail call void @llvm.assume
+    // CHECK-NOT: grow
+    // 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<u8>) {
+    // CHECK-NOT: grow
+    // CHECK: tail call void @llvm.assume
+    // CHECK-NOT: grow
+    // 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<u8>) {
+    // CHECK: call {{.*}}grow
+    v.push_back(3);
+}
+
+#[no_mangle]
+// CHECK-LABEL: @push_front_byte(
+pub fn push_front_byte(v: &mut VecDeque<u8>) {
+    // CHECK: call {{.*}}grow
+    v.push_front(3);
+}