I tried to write some code to make a late initialization of an stack allocated array:
pub fn create_array_nocopy2() {
println!("fn create_array_nocopy2()");
let a = {
const NUMBER_OF_ARRAY_ELEMENTS: usize = 1000;
type ContentType = ContentI32;
let mut uninit = mem::MaybeUninit::<
[ContentType; NUMBER_OF_ARRAY_ELEMENTS],
>::uninit();
let unit_ptr = uninit.as_mut_ptr();
for index in 0 .. NUMBER_OF_ARRAY_ELEMENTS {
unsafe {
std::ptr::addr_of_mut!((*unit_ptr)[index])
.write(ContentType::new(content_from_index(index)));
};
}
// SAFETY: Everything is initialized.
// Performance impact: Unnecessary memcopy occurs here
// Performance impact: Unnecessary stack space allocated
unsafe { uninit.assume_init() }
};
print_array(&a);
}
For the discussion it is unnecessary to know, what type ContentI32
really is, (however the complete code is avalable at compiler explorer Example code.
If I look at the assemble output I made the following observations:
example::create_array_nocopy2:
push r14
push rbx
sub rsp, 2008 ; Allocation of 1000 unnecessary bytes
and later (comes from unsafe { uninit.assume_init() }
)
mov edx, 1000
mov rdi, rbx
call qword ptr [rip + memcpy@GOTPCREL] ; Unnecessary memcpy
What is reason about this? Shouldn't unnecessary moves be removed by the compiler?