Skip to content

Field ordering causes extra memcpy #56356

Closed
@jrmuizel

Description

@jrmuizel

In the following test case reduced from SmallVec:

use std::mem;

struct SV {
    capacity: usize,
    disc: usize,
    data: [usize; 40],
}

impl SV {
    fn new() -> SV {
        SV { data: unsafe { mem::uninitialized() },
            disc: 0,
            capacity: 0 }
    }
}

pub struct L {
    a: SV,
}

pub struct Allocation<T> {
    f: *mut T,
}

impl<T> Allocation<T> {
    pub fn init(self, value: T) {
        use std::ptr;
        unsafe {
        ptr::write(self.f, value);
        }
    }
}

#[inline(never)]
pub fn foo(a: Allocation<L>) {
    a.init(L {
        a: SV::new(),
    });
}

produces

example::foo:
  sub rsp, 344
  xorps xmm0, xmm0
  movaps xmmword ptr [rsp], xmm0
  mov rsi, rsp
  mov edx, 336
  call memcpy@PLT
  add rsp, 344
  ret

moving capacity to the end of the struct gives:

example::foo:
  mov qword ptr [rdi], 0
  mov qword ptr [rdi + 328], 0
  ret

This is surprising to me.

Metadata

Metadata

Assignees

Labels

A-LLVMArea: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.I-slowIssue: Problems and improvements with respect to performance of generated code.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions