Colin Walls has over thirty years experience in the electronics industry, largely dedicated to embedded software. A frequent presenter at conferences and seminars and author of numerous technical articles and two books on embedded software, Colin is an embedded software technologist with Mentor … More »
Firmly in line
May 16th, 2016 by Colin Walls
A common compiler optimization is the inclusion of a function’s code at the location(s) from where the function is called, instead of just having calls to the code located elsewhere: inlining. This provides a speed advantage, as the call/return sequence is eliminated, but may increase the memory footprint, if the function is more than a few instructions and is called more than once. I have written about this topic before, here and here.
I have an enduring interest in code generation and compiler optimizations and my consideration of inlining was piqued by a recent comment on one of my earlier posts. I realized that there are two implementation related aspects of inlining which are particularly relevant to embedded software developers …
First off, I will consider the situation when a function is declared static. As a compiler knows that the function cannot be used outside of the module in hand, it can make some smart decisions. Specifically, if there is only a single call to the function, the code should be inlined automatically without further ado, as the result will always be faster and smaller – a win-win situation. It may be argued that doing this automatically is wrong, because the programmer explicitly specified a call. However, I would counter with the assertion that a compiler’s job is not to convert code in C to assembly language; it is required to translate an algorithm, expressed in C, to assembly language code with identical functionality.
The second situation is when a function is declared inline, but not static. In this case, the compiler can inline the function in the current module, but needs to generate an out of line copy too, in case it is called from another function. In this case, it would be down to the linker to sort out the problem. All that is necessary is for the linker to be able to detect “orphan” functions – i.e. functions that are not called from anywhere and there are tools that do just that.
These two situations are both important to embedded software developers because they relate to utilization of resources [primarily memory], which is always of interest. In both cases, there is no problem if the software development toolkit is strongly oriented towards the needs of such applications.