-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Vec::resize
for bytes should be a single memset
#120050
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
use core::iter::repeat_n; | ||
|
||
use super::Vec; | ||
use crate::alloc::Allocator; | ||
|
||
// Specialization trait used for Vec::extend_elem | ||
pub(super) trait SpecExtendElem<T> { | ||
fn spec_extend_elem(&mut self, n: usize, value: T); | ||
} | ||
|
||
impl<T, A: Allocator> SpecExtendElem<T> for Vec<T, A> | ||
where | ||
T: Clone, | ||
{ | ||
default fn spec_extend_elem(&mut self, n: usize, value: T) { | ||
self.extend_trusted(repeat_n(value, n)) | ||
} | ||
} | ||
|
||
impl<T, A: Allocator> SpecExtendElem<T> for Vec<T, A> | ||
where | ||
T: Copy, | ||
{ | ||
fn spec_extend_elem(&mut self, n: usize, value: T) { | ||
self.extend_elem_copy(n, value) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am not sure if this specialization is correct for all cases of At the moment:
Which means that at the moment for This is the reason why I've only implemented the specialization for As mentioned in #118094 (comment), this kind of change is still allowed, although I expect that there must be an explicit proof that this is a valid optimization and an update to An alternative may be to add a perma-unstable fn to |
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
//@ compile-flags: -O | ||
//@ only-64bit | ||
|
||
#![crate_type = "lib"] | ||
|
||
// CHECK-LABEL: @resize_bytes_is_one_memset | ||
#[no_mangle] | ||
pub fn resize_bytes_is_one_memset(x: &mut Vec<u8>) { | ||
// CHECK: call void @llvm.memset.p0.i64({{.+}}, i8 123, i64 456789, i1 false) | ||
let new_len = x.len() + 456789; | ||
x.resize(new_len, 123); | ||
} | ||
|
||
#[derive(Copy, Clone)] | ||
struct ByteNewtype(i8); | ||
|
||
// CHECK-LABEL: @from_elem_is_one_memset | ||
#[no_mangle] | ||
pub fn from_elem_is_one_memset() -> Vec<ByteNewtype> { | ||
// CHECK: %[[P:.+]] = tail call{{.+}}@__rust_alloc(i64 noundef 123456, i64 noundef 1) | ||
// CHECK: call void @llvm.memset.p0.i64({{.+}} %[[P]], i8 42, i64 123456, i1 false) | ||
vec![ByteNewtype(42); 123456] | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cc @JarvisCraft in case you have thoughts on this approach, since I removed your specialization from #118094 in this PR
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for tagging me! I've commented below on what I am unsure about, though the optimization really looks promising.