6

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

如果内联函数被声明为静态并且函数定义在函数的所有使用之前,编译器只会消除内联函数。

在 foo.c 的顶部我声明

 static inline void nop_10_times(void);

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

void _CNInterrupt(void)
{
    nop_10_times();

    // rest of function
}

然后,作为测试,我将定义放在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();
}

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

有谁知道它是如何做到这一点的?根据手册中的定义,它表示如果“函数定义在函数的所有使用之前”,它将消除内联函数。

4

2 回答 2

1

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

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

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

听起来优化人员领先于文档人员。当前的优化器可能正在为完整的翻译单元处理分析树,并看到它可以删除一个调用/返回序列。

于 2016-07-09T01:38:07.150 回答
0

首先请记住,该指令inline只是对编译器的提示。编译器可以在需要时自由内联或不内联。

有谁知道它是如何做到这一点的?

这称为两遍编译器。内联是在解析时、优化时、代码发射阶段等进行的,这里不相关。

根据手册中的定义,它表示如果“函数定义在函数的所有使用之前”,它将消除内联函数。

现在好像把“当且仅当”换成了简单的“如果”,这样如果定义跟在调用后面,有时可以内联……或者是优化器的作用,所以内联可以视为边界效应。

于 2016-07-09T03:01:31.053 回答