cassemblycompilationc99compound-literals

Why does return of a compound literal (C99) generate more assembly code?


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?


Solution

  • 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