Skip to content

missed optimization when writing a value with inner padding. #157373

@Morgane55440

Description

@Morgane55440

Code

I tried this code:

use std::mem::MaybeUninit;
#[repr(C)]
pub struct X {
    a : u16,
    b : u8,
    c : u32
}

#[unsafe(no_mangle)]
pub fn bad(a: &mut [MaybeUninit<u32>;2])  {
    let x = X { a : 0, b : 0, c : 0};
    unsafe {
        std::ptr::write((&raw mut *a).cast::<X>(), x)
    }
}


#[unsafe(no_mangle)]
pub fn bad_too(a: &mut MaybeUninit<X>)  {
    let x = X { a : 0, b : 0, c : 0};
    unsafe {
        std::ptr::write(a.as_mut_ptr(), x)
    }
}


#[unsafe(no_mangle)]
pub fn not_bad(a: &mut MaybeUninit<X>)  {
    let x = X { a : 0, b : 0, c : 0};
    a.write(x);
}

I expected to see this happen: each function would result in either 2 4-byte stores of 0 or one 8-byte store of 0 dependinding on how the compiler deals with the alignement.

what happened :

bad:
        mov     word ptr [rdi], 0
        mov     byte ptr [rdi + 2], 0
        mov     dword ptr [rdi + 4], 0
        ret

not_bad:
        mov     qword ptr [rdi], 0
        ret

bad_too = bad

both bad and bad_too avoided writing the padding byte, even though there is no reason for them to do so.

this has been the case since 1.81 when MaybeUninit::write was stabilized

godbolt link ; https://godbolt.org/z/Yj6GWhebq

this might be an llvm issue, but i gigured it might be best to ask here first

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-optimizationCategory: An issue highlighting optimization opportunities or PRs implementing suchneeds-triageThis issue may need triage. Remove it if it has been sufficiently triaged.

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions