Quantcast
Channel: Active questions tagged gcc - Stack Overflow
Viewing all articles
Browse latest Browse all 22102

Does the RVO is enable by default for C?

$
0
0

I want ot know if RVO is enable by default for C. I know that the "-fno-elide-constructors" flag is not enable for gcc but maybe I have a miss on this feature.

Basically, I try to compile this two code :

// 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;
}

And this one :

// 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;
}

I compile both code with the same way :

gcc main.c -S -o c_main.s

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

I have this 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"

And for the 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"

For the cpp assembly, you can remove the overhead 20 first line and you have the same number line for c asm and c++ asm.

I'm not very fluent with assembly code but with this result, I think I can say that the RVO is enable for C.

To be sure, if I compile C++ code with -fgcc no-elide-constructors I have so much more assembly line. This is why I think my struct instanciate in the 'f' function is not "copied" in C and 'construct' just one time. At the g assembly function, we clearly can see that there are no manipulation with the 'C' field structure.

Am I wrong ?

Edit : compile with -O0 give the same assembly for main.c.


Viewing all articles
Browse latest Browse all 22102

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>