Change:
I want to initialize a large with . Compiling with Rust 1.66 generates instructions. However, after initializing with the code gets vectorized as expected: The generated assembly contains instructions. Now, the weird thing is that if I have both functions in the same file, both get vectorized. See this . As long as is commented out, is not vectorized. As soon as you remove the comment, both functions are vectorized.
Easiest fix for specifically would be to update , I think. We don't guarantee a layout for it, but internally for optimizations I think we'd be safe doing this. (We can put some tests like in non-public stuff to help double-check it.)
When is , couldn't the part of the memory layout be anything since it shouldn't be accessed? Couldn't we use that for optimization? So for example, if sets the discriminator bit to 0, couldn't we always zero out the entire memory no matter what is? Or if the discriminator is represented with a non-zero value, couldn't the whole data structure be filled up with that value (or just left unitialized depending on which is faster)?
Unfortunately not, because there can be other niches than 0. For instance, has the value 0xffff_ffff on Unix platforms.
Can we at least assume that two -s will always have the same bytes in memory for any fixed ? If so, couldn't we vectorize filling up the with those bytes?
I think similar to . iirc the main issue is that LLVM's InstCombine removes the instructions before reaching the passes that could use this information to optimize - at this point, it generally becomes a series of stores with gaps between which LLVM no longer knows can be written to freely.
No, because something like is half , where "the same" isn't a meaningful question. That's exactly what I mention for -- you can use that to check that it's a value where it would be legal to zero out the whole thing, and if that function returns then uses a zeroing allocator instead of the needing initialize the memory.

Discussion:
#![feature(const_size_of_val)] #![feature(const_align_of_val)] #![feature(const_ptr_read)] <ins> #![feature(const_maybe_uninit_zeroed)] </ins> #![feature(const_maybe_uninit_write)] #![feature(const_maybe_uninit_as_mut_ptr)] #![feature(const_refs_to_cell)]

#[rustc_specialization_trait] pub(super) unsafe trait IsZero { <del> /// Whether this value's representation is all zeros </del> <ins> /// Whether this value's representation is all zeros, /// or can be represented with all zeroes. </ins> fn is_zero(&self) -> bool; }

NonZeroIsize, ); <ins> macro_rules! impl_is_zero_option_of_num { ($($t:ty,)+) => {$( unsafe impl IsZero for Option<$t> { #[inline] fn is_zero(&self) -> bool { const { let none: Self = unsafe { core::mem::MaybeUninit::zeroed().assume_init() }; assert!(none.is_none()); } self.is_none() } } )+}; } impl_is_zero_option_of_num!(u8, u16, u32, u64, u128, i8, i16, i32, i64, i128, usize, isize,); </ins> unsafe impl<T: IsZero> IsZero for Wrapping<T> { #[inline] fn is_zero(&self) -> bool {

vec![Some(false); n] } <ins> // CHECK-LABEL: @vec_option_i32 #[no_mangle] pub fn vec_option_i32(n: usize) -> Vec<Option<i32>> { // CHECK-NOT: call {{.*}}alloc::vec::from_elem // CHECK-NOT: call {{.*}}reserve // CHECK-NOT: call {{.*}}__rust_alloc( // CHECK: call {{.*}}__rust_alloc_zeroed( // CHECK-NOT: call {{.*}}alloc::vec::from_elem // CHECK-NOT: call {{.*}}reserve // CHECK-NOT: call {{.*}}__rust_alloc( // CHECK: ret void vec![None; n] } </ins> // Ensure that __rust_alloc_zeroed gets the right attributes for LLVM to optimize it away. // CHECK: declare noalias ptr @__rust_alloc_zeroed(i64, i64 allocalign) unnamed_addr [[RUST_ALLOC_ZEROED_ATTRS:#[0-9]+]]