6

In the manual for the XC16 compiler, it says the following:

The compiler will only eliminate inline functions if they are declared to be static and if the function definition precedes all uses of the function.

At the top of foo.c I declared

 static inline void nop_10_times(void);

Then in the definition for an ISR defined as:

void _CNInterrupt(void)
{
    nop_10_times();

    // rest of function
}

Then, as a test, I put the definition to nop_10_times at the bottom of the file.

static inline void nop_10_times(void)
{
    __builtin_nop();
    __builtin_nop();
    __builtin_nop();
    __builtin_nop();
    __builtin_nop();

    __builtin_nop();
    __builtin_nop();
    __builtin_nop();
    __builtin_nop();
    __builtin_nop();
}

When I compile my project and look at the assembly, it seems that the compiler was, in fact, able to completely remove the function in assembly and only leave the inline code where it was called in the ISR.

Does anyone know how it was able to do this? According to the definition in the manual, it said it would eliminate the inline function if "the function definition precedes all uses of the function."

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • 1
    The function definition (prototype) does precede your use of the function. It's the implementation that follows it. – Weather Vane Apr 30 '15 at 18:57
  • 4
    I thought the prototype was a "declaration" and the "definition" was where the implementation of the function is? –  Apr 30 '15 at 19:04
  • 4
    @WeatherVane: "Function definition" usually implies (including in the C89+ standards) that the body is included. Without the body, you have a function declaration. – Ulfalizer Apr 30 '15 at 19:04
  • 2
    @w1res Code first use of `nop_10_times()` occurs before definition. This is contrary to "...and if the function definition precedes all uses of the function." – chux - Reinstate Monica Apr 30 '15 at 19:05
  • 2
    @WeatherVane "A declaration introduces an identifier and describes its type" ...."A definition actually instantiates/implements this identifier." it's from [here](http://stackoverflow.com/questions/1410563/what-is-the-difference-between-a-definition-and-a-declaration) – Dabo Apr 30 '15 at 19:07
  • 1
    @chux: That's the point though. – Ulfalizer Apr 30 '15 at 19:08
  • 1
    @Dabo a good read, so I would suggest OP's manual is incorrect. As to *how* it works, a C compiler may make as many passes of the code as it wishes to, so long as the forward declaration exists. http://stackoverflow.com/questions/24299493/how-many-passes-does-a-c-compiler-do – Weather Vane Apr 30 '15 at 19:23
  • The compiler is based off of GCC, but everywhere I look seems to have some slight differences, being very specific about how definitions/declarations combinations will affect inlining of functions. Even although I can get it to work, I still worry that I might change some conditions and unknowingly it will stop working the way I expect. –  Apr 30 '15 at 19:57
  • 3
    See http://stackoverflow.com/questions/28365742/calls-that-precede-a-functions-definition-cannot-be-inlined – D Krueger Apr 30 '15 at 20:24
  • The real question is why do you care? If you don't want the function's body to be inlined, then don't declare/define it with the `inline` attribute! If the compiler decides it can inline your function then shouldn't care either (at least so long as the compiler still makes it possible for a symbolic debugger to correctly follow execution through the inlined code). – Greg A. Woods May 08 '15 at 16:28
  • You can't always believe the documentation. In this case it is clearly wrong. – Greg A. Woods May 08 '15 at 16:22
  • I think that the `inline` attribute is only a hint provided to the compiler. It may decide to inline the function with or without the `inline` being used. – Plouff Mar 09 '16 at 13:03
  • From C standard: "Making a function an inline function suggests that calls to the function be as fast as possible" nothing more! – Plouff Mar 09 '16 at 13:10
  • Did the compiler generate a non-inline version as well? Also, could it have been inlined at link time? – Dmitri Jul 03 '16 at 22:03

2 Answers2

1

Both of the manual restrictions seem reasonable. They were probably true for an earlier version of the compiler or at least were true in a specification at some point.

  1. If the function is not declared static, then it could be called from outside the current translation unit (source file). To do that, a non-inline function needs to be placed.

  2. If the function is called somewhere before it is defined, then the compiler doesn't have enough information at the use point to inline the function, only to generate a function call.

It sounds like the optimizer guys got ahead of the documentation guys. The current optimizer is probably working on the parse tree for the full translation unit and saw that it could remove a call/ret sequence.

evaitl
  • 1,365
  • 8
  • 16
0

First remember that directive inline is just an hint for compilers. Compilers are free to inline or not when they want.

Does anyone know how it was able to do this?

That is called a two-pass compiler. Wether the inlining is made at parse time, optimisation time, code emitting phase, etc, is not relevant here.

According to the definition in the manual, it said it would eliminate the inline function if "the function definition precedes all uses of the function."

It seems that the "if and only if" is now replaced by a simple "if", so that if the definition follows the call, it can sometimes inline... Or is it the effect of the optimizer, so the inlining can be considered as a border effect.

Jean-Baptiste Yunès
  • 34,548
  • 4
  • 48
  • 69