Was the function really inlined?

Hi!
I have a question about inlining ...

How can i check was function really inlined by the compiler, or it fully ignored my request for some reasons (or particularly ignored). I know that I can read an assembly code generated by the compiler and check whether the call was inlined or not, but for big projects it may be very difficult. Are there any other opportunities?

Any ideas?

Last edited on
Nope. No way.
If you need to ensure inlining, some compilers have keywords that force inlining of certain functions, or special options to follow more aggressive inlining strategies.
Maybe there are methods that will work in runtime?

I mean something like this:

1
2
3
4
5
6
7
8
9
10
11
static inline result_t InlineFunction(param_t arg1, param_t arg2)
{
          void *address = getCS_IP();
          if (approximatelyEqual(currentAddress, (void *) &InlineFunction)) {
                  // Function was inlined 
          } else {
                  // Function was not inlined
          }

          // Function code
}


For now i just don't know how to implement this and really don't know will it work (compiler can just ignore inlining request for such a function).

How do you think, will it work and give me a hint on how to implement such approach?
Last edited on
It can also happen that you have an inlined and "regular" version of your function.
This can happen if you access an inlined function via a function pointer for instance.

Since the compiler is only allowed to inline a function if you can't tell the difference why do you want to know? The compiler is in most cases much better at guessing whether to inline a function or not. Inlining doesn't necessarily result in faster programs.

Maybe you want to have a look at:
http://www.parashift.com/c++-faq-lite/inline-functions.html
It can also happen that you have an inlined and "regular" version of your function.
This can happen if you access an inlined function via a function pointer for instance.


That's why i think that this approach will work (the difference between real function address and the value of CS:IP - (instruction pointer) will be big enough to determine if the function was inlined (no jump was performed)).

Since the compiler is only allowed to inline a function if you can't tell the difference why do you want to know? The compiler is in most cases much better at guessing whether to inline a function or not. Inlining doesn't necessarily result in faster programs.


I definitely know that in my situation, inline will improve performance and i can't use macros. But i am not sure that inlining took place in the result code.
the compiler is only allowed to inline a function if you can't tell the difference
Ah... Good ol' quantum behavior. The result changes by evaluating it.

I definitely know that in my situation, inline will improve performance
So force inlining through compiler extensions. What's the problem?
Sharing article on inline function, may this will help in giving you more vision

http://tajendrasengar.blogspot.com/2010/03/what-is-inline-function-in-cc.html

One more thing, sharing you trick for the same (Not tried but might work).
Just try declaring static int nTempVar = 0; inside your desired inlined funtcion. And increment nTempVar inside that function, if function does not got inlined then it will show exact function calling count. But if it got inlined then count will be diffrent as per its substitution into .cpp files.
So force inlining through compiler extensions. What's the problem?


Thanks. It seems the most appropriate solution.

One more thing, sharing you trick for the same (Not tried but might work).

...

Maybe understand some thing not right.
But here is the code on which i've tried to check inlining:

1
2
3
4
5
6
7
8
9
10
11
12
// tajendra.h
#include <cstdio>

static inline
void callToInlineFunctionFromFile(const char *filename) /* __attribute__((always_inline)) */;

static inline 
void callToInlineFunctionFromFile(const char *filename)
{
	static int counter = 0;
	printf("Call came from file %s and counter value is now %i\n", filename, ++counter);
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// tajendra.cpp
#include <cstdlib>
#include "tajendra.h"

extern void callToInlineFunctionFromOtherFile(void);

int main(void)
{
	callToInlineFunctionFromFile(__FILE__);
	callToInlineFunctionFromOtherFile();
	callToInlineFunctionFromFile(__FILE__);
	callToInlineFunctionFromOtherFile();
	return EXIT_SUCCESS;
}

1
2
3
4
5
6
7
// tajendra2.cpp
#include "tajendra.h"

void callToInlineFunctionFromOtherFile()
{
	callToInlineFunctionFromFile(__FILE__);
}


When i declared and defined a function as a static inline, i've got th next output:
Call came from file tajendra.cpp and counter value is now 1
Call came from file tajendra2.cpp and counter value is now 1
Call came from file tajendra.cpp and counter value is now 2
Call came from file tajendra2.cpp and counter value is now 2

But when i declared it as extern inline (and without extern) and defined as inline:
Call came from file tajendra.cpp and counter value is now 1
Call came from file tajendra2.cpp and counter value is now 2
Call came from file tajendra.cpp and counter value is now 3
Call came from file tajendra2.cpp and counter value is now 4

In both cases the function was inlined (i've checked the asm code). So maybe i understand something not right, but i don't understand how this can help in figuring out about was the function inlined.
Last edited on
But if it got inlined then count will be diffrent as per its substitution into .cpp files.


This is not true.
Just dump the symbols from your executable and search for the function in the symbol table.
Great! very pleasant see this note, i aslo learn a lot..
"gamlet2008 : So maybe i understand something not right, but i don't understand how this can help in figuring out about was the function inlined."


I think you got the answer now, if the function got inlined then static varibale will be initialized multiple times with 0, that is why you are getting different counter value in different .cpp files.

But on the other hand if function does not get inlined, then static varible will be initialized only once, and you will get exact count as your function get called.

So this will help in recognizing whether function got inlined or not at the runtime.

-Tajendra
But on the other hand if function does not get inlined, then static varible will be initialized only once, and you will get exact count as your function get called.
Except he clearly stated that both versions got inlined.
For now i just don't know how to implement this and really don't know will it work (compiler can just ignore inlining request for such a function).


I am using gcc. As i know it uses gas assemly. I don't know how to get current instruction address via asm (or if it's possible in c).

Maybe someone can help me?
Conclusion.

Was the function really inlined?

The only way to know this, is to read the asm-code. In general, if you really know that you need that the function was inlined, you can force it through compiler extensions.
Last edited on
Just to clarify, using a static variable to determine if a function call has been inlined or not will NOT work. Both the inlined and non-inlined function calls will access the SAME static variable.

In gamlet2008's tests, the callToInlineFunctionFromFile() function was declared as a static function. That means that when tajendra.cpp and tajendra2.cpp include tajendra.h, each compilation unit has its own static version of the callToInlineFunctionFromFile() function. And each function has its own counter variable. So the program really has two static counter variables, tajendra.cpp#callToInlineFunctionFromFile()#counter and tajendra2.cpp#callToInlineFunctionFromFile()#counter. Anytime callToInlineFunctionFromFile() is called from tajendra.cpp, the tajendra.cpp#callToInlineFunctionFromFile()#counter variable is incremented. It makes no difference if the call was inlined or not. Likewise, anytime callToInlineFunctionFromFile() is called from tajendra2.cpp, the tajendra2.cpp#callToInlineFunctionFromFile()#counter variable is incremented.

tajendra.cpp#callToInlineFunctionFromFile()#counter and tajendra2.cpp#callToInlineFunctionFromFile()#counter are distinct variables, but that is because of the scoping of the static function, not because of any inlining.
You can view the solution to this problem here http://www.cplusplus.com/forum/general/50009/, if you need.

P.S. Just to clarify
Just FYI, if you haven't done profiling, you shouldn't be concerned with inlining.
Topic archived. No new replies allowed.