Skip to content

Possibly missed return value optimization #144009

@mxple

Description

@mxple

Given a function like:

let result = func();

fn func() -> T {
    let mut ret = T;  // size of T is known at compile-time
    // ...
    return ret;
}

I would expect result to be constructed in-place.

However, with code like

pub fn generate_moves(game: &BoardState) -> MoveList {
    let mut movelist = MoveList::new();
    match game.whites_turn() {
        true => MoveGen::<true>::new(game).generate_all_moves(&mut movelist),
        false => MoveGen::<false>::new(game).generate_all_moves(&mut movelist),
    }
    movelist
}

#[bitfield]
#[derive(Copy, Clone, Debug)]
#[repr(u16)]
pub struct Move {
    pub start: B6,  // 0-63
    pub variant: Variant, // normal, castle, promo, enpassant
    pub target: B6, // 0-63
    pub promo: Promo,  // knight, bishop, rook, queen
}

pub struct MoveList {
    size: u32,
    list: [Move; 224],
}

movelist is constructed on the stack, then copied/moved into the memory ___location reserved for the return spot. In MIR, movelist is not given the _0 binding and it's not apparent why rustc made that choice.

Hopefully, someone with more experience and chime in and give insight on whether this is a missed optimization or something purposefully overlooked.

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-discussionCategory: Discussion or questions that doesn't represent real issues.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions