Skip to content

Unnecessary copying of struct field when the same field is later overwritten #163899

@Kmeakin

Description

@Kmeakin

These functions should all produce the same assembly

https://godbolt.org/z/4c674fKxE

typedef unsigned long u64;

typedef struct {
    u64 x;
    u64 y;
    u64 z;
} Big;

// Not optimized

Big assign(Big b) {
    b.x = 0;
    return b;
}

Big copy_then_assign(Big b) {
    Big c = b;
    c.x = 0;
    return c;
}

Big memcpy_then_assign(Big b) {
    Big c;
    __builtin_memcpy(&c, &b, sizeof(b));
    c.x = 0;
    return c;
}

// Optimized

Big c99_initializer(Big b) { return (Big){0, b.y, b.z}; }

Big c99_initializer2(Big b) {
    Big c = {b.x, b.y, b.z};
    c.x = 0;
    return c;
}

Big copy_individually(Big b) {
    Big c;
    c.x = 0;
    c.y = b.y;
    c.z = b.z;
    return c;
}

Big copy_individually_then_assign(Big b) {
    Big c;
    c.x = b.x;
    c.y = b.y;
    c.z = b.z;
    c.x = 0;
    return c;
}

Unoptimized assembly:

assign:
        str     xzr, [x0]
        ldr     x9, [x0, #16]
        ldr     q0, [x0]
        str     x9, [x8, #16]
        str     q0, [x8]
        ret

Optimized assembly:

c99_initializer:
        ldur    q0, [x0, #8]
        str     xzr, [x8]
        stur    q0, [x8, #8]
        ret

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions