Was the function really inlined?

Sep 4, 2011 at 9:35pm
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 Sep 5, 2011 at 7:22am
Sep 4, 2011 at 9:39pm
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.
Sep 5, 2011 at 7:00am
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 Sep 5, 2011 at 7:00am
Sep 5, 2011 at 7:23am
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
Sep 5, 2011 at 8:23am
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.
Sep 5, 2011 at 8:48am
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?
Sep 5, 2011 at 9:56am
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.
Sep 5, 2011 at 6:40pm
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 Sep 5, 2011 at 6:59pm
Sep 5, 2011 at 9:25pm
But if it got inlined then count will be diffrent as per its substitution into .cpp files.


This is not true.
Sep 5, 2011 at 11:24pm
Just dump the symbols from your executable and search for the function in the symbol table.
Sep 6, 2011 at 5:15am
Great! very pleasant see this note, i aslo learn a lot..
Sep 6, 2011 at 7:51am
"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
Sep 6, 2011 at 8:19am
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.
Sep 7, 2011 at 12:29pm
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?
Sep 7, 2011 at 6:24pm
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 Sep 7, 2011 at 6:28pm
Sep 22, 2011 at 8:33pm
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.
Sep 23, 2011 at 2:01pm
You can view the solution to this problem here http://www.cplusplus.com/forum/general/50009/, if you need.

P.S. Just to clarify
Sep 23, 2011 at 2:05pm
Just FYI, if you haven't done profiling, you shouldn't be concerned with inlining.
Topic archived. No new replies allowed.