I have two functions that return a struct, one returns it via compund litearal and the other initializes a variable to then return it:
typedef struct {
int storage[256];
} data_t;
data_t data_init_compound_literal() {
return (data_t){
.storage = {1}
};
}
data_t data_init_var() {
data_t self;
self.storage[0] = 1;
return self;
}
int main(void) {
data_t em = data_init_compound_literal();
return em.storage[0];
}
When inspecting the generated assembly code in godbolt (with -O2
), it seems that the compound liteal approach genereates more lines of code:
data_init_compound_literal:
movq $0, (%rdi)
movq %rdi, %rdx
leaq 8(%rdi), %rdi
xorl %eax, %eax
movq $0, 1008(%rdi)
movq %rdx, %rcx
andq $-8, %rdi
subq %rdi, %rcx
addl $1024, %ecx
shrl $3, %ecx
rep stosq
movl $1, (%rdx)
movq %rdx, %rax
ret
data_init_var:
movl $1, (%rdi)
movq %rdi, %rax
ret
main:
movl $1, %eax
ret
Is there a reason for this?
As GSerg and Peter Cordes mentioned, the data_t self
variable is not initialized so the compiler generates less assembly code.
If changed to data_t self = {};
the resulting assembly code would be similar.
typedef struct {
int storage[256];
} data_t;
data_t data_init_compound_literal() {
return (data_t){
.storage = {1}
};
}
data_t data_init_var() {
data_t self = {.storage = {1}};
return self;
}
int main(void) {
data_t em = data_init_compound_literal();
return em.storage[0];
}
Results on:
data_init_compound_literal:
movq $0, (%rdi)
movq %rdi, %rdx
leaq 8(%rdi), %rdi
xorl %eax, %eax
movq $0, 1008(%rdi)
movq %rdx, %rcx
andq $-8, %rdi
subq %rdi, %rcx
addl $1024, %ecx
shrl $3, %ecx
rep stosq
movl $1, (%rdx)
movq %rdx, %rax
ret
data_init_var:
subq $912, %rsp
movq %rdi, %rdx
xorl %eax, %eax
movl $128, %ecx
leaq -120(%rsp), %rdi
leaq -120(%rsp), %rsi
rep stosq
movl $1, -120(%rsp)
leaq 8(%rdx), %rdi
movq %rdx, %rcx
andq $-8, %rdi
movq -120(%rsp), %rax
subq %rdi, %rcx
subq %rcx, %rsi
addl $1024, %ecx
movq %rax, (%rdx)
movq 896(%rsp), %rax
shrl $3, %ecx
movq %rax, 1016(%rdx)
movq %rdx, %rax
rep movsq
addq $912, %rsp
ret
main:
movl $1, %eax
ret