Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

temporary variables and performance in c++ [duplicate]

Tags:

c++

Let's say we have two functions:

int f();
int g();

I want to get the sum of f() and g().

First way:

int fRes = f();
int gRes = g();
int sum = fRes + gRes;

Second way:

int sum = f() + g();

Will be there any difference in performance in this two cases?

Same question for complex types instead of ints

EDIT

Do I understand right i should not worry about performance in such case (in each situation including frequently performed tasks) and use temporary variables to increase readability and to simplify the code ?

like image 754
Andrew Avatar asked Dec 01 '22 08:12

Andrew


1 Answers

You can answer questions like this for yourself by compiling to assembly language (with optimization on, of course) and inspecting the output. If I flesh your example out to a complete, compilable program...

extern int f();
extern int g();
int direct()
{ 
  return f() + g(); 
}
int indirect()
{
  int F = f();
  int G = g();
  return F + G;
}

and compile it (g++ -S -O2 -fomit-frame-pointer -fno-exceptions test.cc; the last two switches eliminate a bunch of distractions from the output), I get this (further distractions deleted):

__Z8indirectv:
        pushq   %rbx
        call    __Z1fv
        movl    %eax, %ebx
        call    __Z1gv
        addl    %ebx, %eax
        popq    %rbx
        ret

__Z6directv:
        pushq   %rbx
        call    __Z1fv
        movl    %eax, %ebx
        call    __Z1gv
        addl    %ebx, %eax
        popq    %rbx
        ret

As you can see, the code generated for both functions is identical, so the answer to your question is no, there will be no performance difference. Now let's look at complex numbers -- same code, but s/int/std::complex<double>/g throughout and #include <complex> at the top; same compilation switches --

__Z8indirectv:
        subq    $72, %rsp
        call    __Z1fv
        movsd   %xmm0, (%rsp)
        movsd   %xmm1, 8(%rsp)
        movq    (%rsp), %rax
        movq    %rax, 48(%rsp)
        movq    8(%rsp), %rax
        movq    %rax, 56(%rsp)
        call    __Z1gv
        movsd   %xmm0, (%rsp)
        movsd   %xmm1, 8(%rsp)
        movq    (%rsp), %rax
        movq    %rax, 32(%rsp)
        movq    8(%rsp), %rax
        movq    %rax, 40(%rsp)
        movsd   48(%rsp), %xmm0
        addsd   32(%rsp), %xmm0
        movsd   56(%rsp), %xmm1
        addsd   40(%rsp), %xmm1
        addq    $72, %rsp
        ret

__Z6directv:
        subq    $72, %rsp
        call    __Z1gv
        movsd   %xmm0, (%rsp)
        movsd   %xmm1, 8(%rsp)
        movq    (%rsp), %rax
        movq    %rax, 32(%rsp)
        movq    8(%rsp), %rax
        movq    %rax, 40(%rsp)
        call    __Z1fv
        movsd   %xmm0, (%rsp)
        movsd   %xmm1, 8(%rsp)
        movq    (%rsp), %rax
        movq    %rax, 48(%rsp)
        movq    8(%rsp), %rax
        movq    %rax, 56(%rsp)
        movsd   48(%rsp), %xmm0
        addsd   32(%rsp), %xmm0
        movsd   56(%rsp), %xmm1
        addsd   40(%rsp), %xmm1
        addq    $72, %rsp
        ret

That's a lot more instructions and the compiler isn't doing a perfect optimization job, it looks like, but nonetheless the code generated for both functions is identical.

like image 193
zwol Avatar answered Dec 18 '22 16:12

zwol