Skip to main content
GameDev.net gamedev.net
🔒 Locked

Inlined template functions.

Started by CodeStorm Sep 17, 2010 at 10:40 AM 7 replies 1.1k views
Original Post
CodeStorm
CodeStorm
I've been using '#pragma warning' to specifically raise the level of certain warnings in the event that the compiler doesn't inline any of the functions that I want it to. I totally understand the semantics which imply that the 'compiler (usually) knows best' when it comes to optimization etc, but sometimes having the compiler doing 'things behind your back' can leave you in the dark.

So, any time I wish to inline a function, I want to be warned of the compiler's decision. In that way, I can attempt to re-write the function in a way that would make the complier happy, which (hopefully) in turn would make me a better coder. So it's a win-win situation right?

Well... I'm in the middle of revamping my math (header-only) library which, as you can imagine, needs all the optimization it can get. Virtually all functions are implemented via a single line or two, making them ideal for inlining, and all of them are fully templated so that they can be used with any compatible types.

However, I appear to get no warning whatsoever from my MS Visual C++ 2010 Express complier, even when I resort to bloating up a function using all manner of madness (like exception handling) just to see if I can get my complier to at least cough at me.

I understand that complier warnings C4710 (level 4) and C4714 (also level 4) are raised in the event that ‘inline’ or ‘__forceinline’ get overruled by the compiler so, unless there are any other inline specific warnings out there (and yes I have checked and, just to be certain, enabled all warnings in my code to see if any crop up!) can I simply assume that compilers will ALWAYS inline template functions that are specified as inline?

This is not a serious issue of course, but sometimes it IS nice to know what your compiler is up to.
ApochPiQ
ApochPiQ
If you need to know for sure, just pop a breakpoint into the function, run in the debugger, and when the breakpoint hits, open up the Disassembly window and see if there's a function call or not [smile]
CodeStorm
CodeStorm
LOL! Yeah that's a good idea and I'll certainly give that a whirl. But I'm just curious about certain aspects of the complier I guess. I mean, are there any more inline warning codes out there?

There are sooo many of these damn codes out there that are supposed to make our jobs as coders easier. I simply wish to learn more about those specifically associated with inlining decisions.
no such user
no such user
Wait, you want a warning for each and every function call you make?
Antheus
Antheus
Quote:
Original post by CodeStorm

There are sooo many of these damn codes out there that are supposed to make our jobs as coders easier. I simply wish to learn more about those specifically associated with inlining decisions.


And all they do is distract from actually solving the problem.

If you have a single mathematical operation - computers are really fast these days, they will compute the result in a matter of nanoseconds.

And if there are many numbers - well, worry about the *many* problem.

Does your code inherently operate over arrays, rather than values?
Are all these arrays properly aligned?
Is data structures as SoA?
Do all iterations use simple forward iteration rather than random access to elements?

Quote:
needs all the optimization it can get
Not really. The calling code needs all optimizations it can get. sqrt is slow, no matter if inlined or not. So figure out a way to do 4 or 16 at a time, or perhaps even none at all.
CodeStorm
CodeStorm
Thanks for the advice guys!

But to be honest, I'm beginning to think that this is a bug.

I've logged on to Microsoft Connect and, after reading a report on a similar, possible bug (again to do with templates) I'm going to go ahead and submit this because it appears that MS Visual C++ 2010 Express does NOT give you ANY warning with regards to inlining template functions it seems.

Thanks for that heads up by the way ApochPiQ. I totally forgot I could use the disassembler to bypass the compiler's 'faultless' warning ability to check on things directly.

It took me a while to set up the debugger to run with Release code (I'm still adjusting to this new compiler), but thanks to your tip, and the results obtained, I'm pretty certain the compiler isn't raising the appropriate warning that it is supposed to.

Quote:

Wait, you want a warning for each and every function call you make?


No... I was just doing some tests to see when the compiler would and would not obey a directive to inline a templated function. I totally understand that the compiler should have this right (most of the time anyway!), but still, sometimes it IS nice to know what decisions the compiler makes on our behalf.
CodeStorm
CodeStorm
The issue is resolved!

In order to preserve the compiler's warning state, I surrounded inlined code between a pair of #pragma warnings. The first to set inline warning checks (which are off by default) and the second to reset them to their default (disabled) settings.

Template code, being complex as it is since it is executed during compile time AFTER the pre-processor has already set, and then subsequently reset the warning state via the #prama pair, becomes totally unaware of these changes and so no inlining warnings occur during instantiation.

Sigh... Templates...
taz0010
taz0010
VC++ doesn't ignore your __forceinline keyword. If it's possible to inline the function then it always will.

Quote:

Even with __forceinline, the compiler cannot inline code in all circumstances. The compiler cannot inline a function if:

The function or its caller is compiled with /Ob0 (the default option for debug builds).

The function and the caller use different types of exception handling (C++ exception handling in one, structured exception handling in the other).

The function has a variable argument list.

The function uses inline assembly, unless compiled with /Og, /Ox, /O1, or /O2.

The function is recursive and not accompanied by #pragma inline_recursion(on). With the pragma, recursive functions are inlined to a default depth of 16 calls. To reduce the inlining depth, use inline_depth pragma.

The function is virtual and is called virtually. Direct calls to virtual functions can be inlined.

The program takes the address of the function and the call is made via the pointer to the function. Direct calls to functions that have had their address taken can be inlined.

The function is also marked with the naked __declspec modifier.


You should profile your code before using __forceinline, or you risk losing performance instead of gaining it. Using __forceinline on 1-2 line functions is a waste of time really. The compiler knows that inlining short functions is a win/win and will do so automatically. Plus you're then dealing with internal linkage so you can't separate code from their headers and let Whole Project Optimisation do it's thing.
Zahlman
Zahlman
Quote:
Original post by CodeStorm
I totally understand the semantics which imply that the 'compiler (usually) knows best' when it comes to optimization etc, but sometimes having the compiler doing 'things behind your back' can leave you in the dark.


OK, so say you find out that the compiler is not inlining something that you think it should inline.

1) How are you going to prove that it really should be inlined?

2) If you prove it really should be inlined, what are you going to do about it?

Same question if it does inline something you think shouldn't be inlined.

How much work are you willing to do here? And why is it so important to you?

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.