如果定义在使用后出现,为什么XC16编译器会删除内联函数?

w1r*_*res 6 c embedded inline xc16

在XC16编译器的手册中,它说如下:

如果声明它们是静态的,并且函数定义在函数的所有使用之前,编译器将仅消除内联函数.

在foo.c的顶部,我声明了

 static inline void nop_10_times(void);
Run Code Online (Sandbox Code Playgroud)

然后在ISR的定义中定义为:

void _CNInterrupt(void)
{
    nop_10_times();

    // rest of function
}
Run Code Online (Sandbox Code Playgroud)

然后,作为测试,我将定义放在nop_10_times文件的底部.

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();
}
Run Code Online (Sandbox Code Playgroud)

当我编译我的项目并查看程序集时,似乎编译器实际上能够完全删除程序集中的函数,并且只将内联代码保留在ISR中调用的位置.

有谁知道它是如何做到这一点的?根据手册中的定义,它表示如果"函数定义先于函数的所有使用",它将消除内联函数.

eva*_*itl 1

这两种手动限制似乎都是合理的。对于早期版本的编译器来说,它们可能是正确的,或者至少在某个时刻的规范中是正确的。

  1. 如果函数未声明为静态,则可以从当前翻译单元(源文件)外部调用它。为此,需要放置一个非内联函数。

  2. 如果函数在定义之前的某个地方被调用,那么编译器在使用点没有足够的信息来内联该函数,只能生成函数调用。

听起来优化器人员领先于文档人员。当前的优化器可能正在处理完整翻译单元的解析树,并发现它可以删除调用/ret 序列。