Can C ++ compilers optimize function callbacks?

Do compilers (as a rule, or in particular) optimize repeated function calls?

For example, consider this case.

struct foo {
  member_type m;
  return_type f() const; // returns by value
};

Function definition is in one translation unit

return_type foo::f() const {
  /* do some computation using the value of m */
  /* return by value */
}

Repeated function calls are in another block

foo bar;

some_other_function_a(bar.f());
some_other_function_b(bar.f());

Will the code be converted to the second translation unit?

foo bar;

const return_type _tmp_bar_f = bar.f();

some_other_function_a(_tmp_bar_f);
some_other_function_b(_tmp_bar_f);

Potentially, computation fcan be expensive, but the return type can be something very small (think of a math function returning double). Do compilers make up? Are there any cases when they do it or not? You can consider a generalized version of this question, and not just for member functions or functions without arguments.

Clarification at the suggestion of @BaummitAugen:

, , , . GCC x86_64 Linux.

+4
3

GCC , , . : https://gcc.gnu.org/wiki/LinkTimeOptimization , , .

, , . , const :

struct foo {
  member_type m;
  return_type f() const __attribute__((const)); // returns by value
};

GCC, , : https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html

. , . , , , , GCC , , . , ( ) .

EDIT:

GCC . -O3 -fno-inline:

++:

#include <iostream>

int function(int c){
  for(int i = 0; i != c; ++i){
    c += i;
  }
  return c;
}

int main(){
  char c;
  ::std::cin >> c;
  return function(c) + function(c) + function(c) + function(c) + function(c);
}

:

4006a0: 48 83 ec 18             sub    rsp,0x18
4006a4: bf 80 0c 60 00          mov    edi,0x600c80
4006a9: 48 8d 74 24 0f          lea    rsi,[rsp+0xf]
4006ae: e8 ad ff ff ff          call   400660 <_ZStrsIcSt11char_traitsIcEERSt13basic_istreamIT_T0_ES6_RS3_@plt>
4006b3: 0f b6 7c 24 0f          movzx  edi,BYTE PTR [rsp+0xf]
4006b8: e8 13 01 00 00          call   4007d0 <_Z8functioni>
4006bd: 48 83 c4 18             add    rsp,0x18
4006c1: 8d 04 80                lea    eax,[rax+rax*4]
4006c4: c3                      ret    
4006c5: 66 66 2e 0f 1f 84 00    data32 nop WORD PTR cs:[rax+rax*1+0x0]
4006cc: 00 00 00 00 

, , -flto . , :

call   4007d0 <_Z8functioni>

5 ( ):

lea    eax,[rax+rax*4]
+3

, , , .

+1

(.. - ), . :

int test();
void some(int a);
void more(int b);

int main()
{
    some(test());
    more(test());
}

test, , , (LTO , : " " ). , , , test some , caling test more(test()) , test some(test()). ( GCC Clang) test:

int test() __attribute__ ((pure));
void some(int a) __attribute__ ((pure));
void more(int b);

int main()
{
    some(test());
    more(test());
}

( , more .)

Unfortunately, while there is no standard way to declare a function as pure, above is a non-standard GCC extension. There is a proposal sentence N3744 to add [[pure]]to the C ++ ISO (with even more reliable guarantees of cleanliness, someit would not be necessary to clean it), but I don’t know if this will lead to C ++ 17 or not.

0
source

Source: https://habr.com/ru/post/1669213/


All Articles