Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ inline function & context specific optimization

I have read in Scott Meyers' Effective C++ book that:

When you inline a function you may enable the compiler to perform context specific optimizations on the body of function. Such optimization would be impossible for normal function calls.

Now the question is: what is context specific optimization and why it is necessary?

like image 202
Destructor Avatar asked Dec 25 '22 06:12

Destructor


2 Answers

I don't think "context specific optimization" is a defined term, but I think it basically means the compiler can analyse the call site and the code around it and use this information to optimise the function.

Here's an example. It's contrived, of course, but it should demonstrate the idea:

Function:

int foo(int i)
{
  if (i < 0) throw std::invalid_argument("");
  return -i;
}

Call site:

int bar()
{
  int i = 5;
  return foo(i);
}

If foo is compiled separately, it must contain a comparison and exception-throwing code. If it's inlined in bar, the compiler sees this code:

int bar()
{
  int i = 5;
  if (i < 0) throw std::invalid_argument("");
  return -i;
}

Any sane optimiser will evaluate this as

int bar()
{
  return -5;
}
like image 154
Angew is no longer proud of SO Avatar answered Jan 06 '23 08:01

Angew is no longer proud of SO


If the compile choose to inline a function, it will replace a function call to this function by the body of the function. It now has more code to optimize inside the caller function body. Therefore, it often leads to better code.

Imagine that:

bool callee(bool a){
   if(a) return false;
   else return true;
}

void caller(){
   if(callee(true)){
       //Do something
   }   
   //Do something
}

Once inlined, the code will be like this (approximatively):

void caller(){
   bool a = true;
   bool ret;
   if(a) ret = false;
   else ret = true;

   if(ret){
       //Do something
   }   
   //Do something
}

Which may be optimized further too:

void caller(){
   if(false){
       //Do something
   }   
   //Do something
}

And then to:

void caller(){
   //Do something
}

The function is now much smaller and you don't have the cost of the function call and especially (regarding the question) the cost of branching.

like image 30
Baptiste Wicht Avatar answered Jan 06 '23 08:01

Baptiste Wicht