Skip to content

Unnecessary memcpy when returning a struct #57077

Closed
@MSxDOS

Description

@MSxDOS

Returning a newly created struct from a function causes an unnecessary memcpy even if the function is inlined:

use std::mem::uninitialized;

#[repr(C)]
pub struct SomeStruct(u64, u32, u16, u8, usize, u64, u64, u32, usize, u16, u32, usize, isize);

extern {
    pub fn SomeExternFun(val: *mut SomeStruct);
}

#[inline(always)]
unsafe fn ret_val() -> SomeStruct {
    let mut val: SomeStruct = uninitialized();
    SomeExternFun(&mut val);
    val
}

#[inline(always)]
unsafe fn by_ref(val: &mut SomeStruct) {
    SomeExternFun(val);
}

pub unsafe fn call_ret_val() {
     let val = ret_val();
     println!("{}", val.0);
}

pub unsafe fn call_by_ref() {
    let mut val: SomeStruct = uninitialized();
    by_ref(&mut val);
    println!("{}", val.0);
}
playground::call_ret_val: # @playground::call_ret_val
# %bb.0:
	sub	rsp, 184
	lea	rdi, [rsp + 16]
	call	qword ptr [rip + SomeExternFun@GOTPCREL]
	movups	xmm0, xmmword ptr [rsp + 80]
	movaps	xmmword ptr [rsp + 160], xmm0
	movups	xmm0, xmmword ptr [rsp + 16]
	movups	xmm1, xmmword ptr [rsp + 32]
	movups	xmm2, xmmword ptr [rsp + 48]
	movups	xmm3, xmmword ptr [rsp + 64]
	movaps	xmmword ptr [rsp + 144], xmm3
	movaps	xmmword ptr [rsp + 128], xmm2
	movaps	xmmword ptr [rsp + 112], xmm1
	movaps	xmmword ptr [rsp + 96], xmm0
	lea	rax, [rsp + 96]
	mov	qword ptr [rsp], rax
	mov	rax, qword ptr [rip + core::fmt::num::<impl core::fmt::Display for u64>::fmt@GOTPCREL]
	mov	qword ptr [rsp + 8], rax
	lea	rax, [rip + .Lanon.865785a9e3ffc8ff7f56f0b35003ddee.2]
	mov	qword ptr [rsp + 16], rax
	mov	qword ptr [rsp + 24], 2
	lea	rax, [rip + .Lanon.865785a9e3ffc8ff7f56f0b35003ddee.3]
	mov	qword ptr [rsp + 32], rax
	mov	qword ptr [rsp + 40], 1
	mov	rax, rsp
	mov	qword ptr [rsp + 48], rax
	mov	qword ptr [rsp + 56], 1
	lea	rdi, [rsp + 16]
	call	qword ptr [rip + std::io::stdio::_print@GOTPCREL]
	add	rsp, 184
	ret
                                        # -- End function

playground::call_by_ref: # @playground::call_by_ref
# %bb.0:
	push	rbx
	sub	rsp, 144
	lea	rbx, [rsp + 64]
	mov	rdi, rbx
	call	qword ptr [rip + SomeExternFun@GOTPCREL]
	mov	qword ptr [rsp], rbx
	mov	rax, qword ptr [rip + core::fmt::num::<impl core::fmt::Display for u64>::fmt@GOTPCREL]
	mov	qword ptr [rsp + 8], rax
	lea	rax, [rip + .Lanon.865785a9e3ffc8ff7f56f0b35003ddee.2]
	mov	qword ptr [rsp + 16], rax
	mov	qword ptr [rsp + 24], 2
	lea	rax, [rip + .Lanon.865785a9e3ffc8ff7f56f0b35003ddee.3]
	mov	qword ptr [rsp + 32], rax
	mov	qword ptr [rsp + 40], 1
	mov	rax, rsp
	mov	qword ptr [rsp + 48], rax
	mov	qword ptr [rsp + 56], 1
	lea	rdi, [rsp + 16]
	call	qword ptr [rip + std::io::stdio::_print@GOTPCREL]
	add	rsp, 144
	pop	rbx
	ret
                                        # -- End function

Playground

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-LLVMArea: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.A-mir-optArea: MIR optimizationsA-mir-opt-inliningArea: MIR inliningA-mir-opt-nrvoFixed by the Named Return Value Opt. (NRVO)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