Skip to content

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

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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-optimizationCategory: An issue highlighting optimization opportunities or PRs implementing such

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions