RVO включен по умолчанию для C? - PullRequest
0 голосов
/ 02 февраля 2020

Я не хочу знать, включен ли RVO по умолчанию для C. Я знаю, что флаг "-fno-elide-constructors" не разрешен для g cc, но, возможно, у меня отсутствует эта функция.

По сути, я пытаюсь скомпилировать эти два кода:

// main.c :


typedef struct C {
  int a;
  int b;
  int c;
} C;

C f() {
  C a;
  a.a = 333;
  a.b = 444;
  a.c = 555;
  return a;
}

C g() { return f(); }

int main() {
  C obj = g();
  obj.a = 666;
  obj.b = 777;
  obj.c = 888;
}

И этот:

// main.cpp :

struct C {
  C() {}
  C(const C&) {}
  int a;
  int b;
  int c;
};

C f() {
  C a;
  a.a = 333;
  a.b = 444;
  a.c = 555;
  return a;
}

C g() { return f(); }

int main() {
  C obj = g();
  obj.a = 666;
  obj.b = 777;
  obj.c = 888;
}

Я компилирую оба кода одинаково:

g cc main. c -S -o c_main.s

g ++ main. cpp -S -o cpp_main.s

У меня есть такой asm:

    .file   "main.c"
    .text
    .globl  f
    .def    f;  .scl    2;  .type   32; .endef
    .seh_proc   f
f:
    pushq   %rbp
    .seh_pushreg    %rbp
    movq    %rsp, %rbp
    .seh_setframe   %rbp, 0
    subq    $16, %rsp
    .seh_stackalloc 16
    .seh_endprologue
    movq    %rcx, 16(%rbp)
    movl    $333, -12(%rbp)
    movl    $444, -8(%rbp)
    movl    $555, -4(%rbp)
    movq    16(%rbp), %rax
    movq    -12(%rbp), %rdx
    movq    %rdx, (%rax)
    movl    -4(%rbp), %edx
    movl    %edx, 8(%rax)
    movq    16(%rbp), %rax
    addq    $16, %rsp
    popq    %rbp
    ret
    .seh_endproc
    .globl  g
    .def    g;  .scl    2;  .type   32; .endef
    .seh_proc   g
g:
    pushq   %rbp
    .seh_pushreg    %rbp
    movq    %rsp, %rbp
    .seh_setframe   %rbp, 0
    subq    $32, %rsp
    .seh_stackalloc 32
    .seh_endprologue
    movq    %rcx, 16(%rbp)
    movq    16(%rbp), %rax
    movq    %rax, %rcx
    call    f
    movq    16(%rbp), %rax
    addq    $32, %rsp
    popq    %rbp
    ret
    .seh_endproc
    .def    __main; .scl    2;  .type   32; .endef
    .globl  main
    .def    main;   .scl    2;  .type   32; .endef
    .seh_proc   main
main:
    pushq   %rbp
    .seh_pushreg    %rbp
    movq    %rsp, %rbp
    .seh_setframe   %rbp, 0
    subq    $48, %rsp
    .seh_stackalloc 48
    .seh_endprologue
    call    __main
    leaq    -12(%rbp), %rax
    movq    %rax, %rcx
    call    g
    movl    $666, -12(%rbp)
    movl    $777, -8(%rbp)
    movl    $888, -4(%rbp)
    movl    $0, %eax
    addq    $48, %rsp
    popq    %rbp
    ret
    .seh_endproc
    .ident  "GCC: (x86_64-posix-seh-rev0, Built by MinGW-W64 project) 8.1.0"

А для cpp:

    .file   "main.cpp"
    .text
    .section    .text$_ZN1CC1Ev,"x"
    .linkonce discard
    .align 2
    .globl  _ZN1CC1Ev
    .def    _ZN1CC1Ev;  .scl    2;  .type   32; .endef
    .seh_proc   _ZN1CC1Ev
_ZN1CC1Ev:
.LFB2:
    pushq   %rbp
    .seh_pushreg    %rbp
    movq    %rsp, %rbp
    .seh_setframe   %rbp, 0
    .seh_endprologue
    movq    %rcx, 16(%rbp)
    nop
    popq    %rbp
    ret
    .seh_endproc
    .text
    .globl  _Z1fv
    .def    _Z1fv;  .scl    2;  .type   32; .endef
    .seh_proc   _Z1fv
_Z1fv:
.LFB6:
    pushq   %rbp
    .seh_pushreg    %rbp
    movq    %rsp, %rbp
    .seh_setframe   %rbp, 0
    subq    $32, %rsp
    .seh_stackalloc 32
    .seh_endprologue
    movq    %rcx, 16(%rbp)
    movq    16(%rbp), %rcx
    call    _ZN1CC1Ev
    movq    16(%rbp), %rax
    movl    $333, (%rax)
    movq    16(%rbp), %rax
    movl    $444, 4(%rax)
    movq    16(%rbp), %rax
    movl    $555, 8(%rax)
    nop
    movq    16(%rbp), %rax
    addq    $32, %rsp
    popq    %rbp
    ret
    .seh_endproc
    .globl  _Z1gv
    .def    _Z1gv;  .scl    2;  .type   32; .endef
    .seh_proc   _Z1gv
_Z1gv:
.LFB7:
    pushq   %rbp
    .seh_pushreg    %rbp
    movq    %rsp, %rbp
    .seh_setframe   %rbp, 0
    subq    $32, %rsp
    .seh_stackalloc 32
    .seh_endprologue
    movq    %rcx, 16(%rbp)
    movq    16(%rbp), %rax
    movq    %rax, %rcx
    call    _Z1fv
    movq    16(%rbp), %rax
    addq    $32, %rsp
    popq    %rbp
    ret
    .seh_endproc
    .def    __main; .scl    2;  .type   32; .endef
    .globl  main
    .def    main;   .scl    2;  .type   32; .endef
    .seh_proc   main
main:
.LFB8:
    pushq   %rbp
    .seh_pushreg    %rbp
    movq    %rsp, %rbp
    .seh_setframe   %rbp, 0
    subq    $48, %rsp
    .seh_stackalloc 48
    .seh_endprologue
    call    __main
    leaq    -12(%rbp), %rax
    movq    %rax, %rcx
    call    _Z1gv
    movl    $666, -12(%rbp)
    movl    $777, -8(%rbp)
    movl    $888, -4(%rbp)
    movl    $0, %eax
    addq    $48, %rsp
    popq    %rbp
    ret
    .seh_endproc
    .ident  "GCC: (x86_64-posix-seh-rev0, Built by MinGW-W64 project) 8.1.0"

Для сборки cpp вы можете удалить служебную 20 первую строку, и у вас есть одинаковые номера строк для c asm и c ++ asm.

Я не очень хорошо разбираюсь в сборке код, но с этим результатом, я думаю, я могу сказать, что RVO включен для C.

Конечно, если я скомпилирую код C ++ с -fg cc no-elide-constructors, у меня так гораздо больше сборочной линии. Вот почему я думаю, что мой экземпляр структуры в функции 'f' не "копируется" в C и "конструируется" только один раз. В данной функции сборки мы ясно видим, что нет никаких манипуляций со структурой поля 'C'.

Я ошибаюсь?

Редактировать: компилировать с -O0 дают то же самое сборка для магистрали. c.

...