【问题标题】:Why does gcc/clang not inline even on highest optimization level为什么 gcc/clang 即使在最高优化级别也不内联
【发布时间】:2019-07-05 17:39:14
【问题描述】:

我想知道为什么函数 foobar() 没有被 gcc/clang 内联。即使使用-O3 也不会执行内联。我本来希望 gcc 足够聪明地这样做。 如果我将inline 关键字添加到函数中,则会执行内联。但是,我认为手动指定 inline 关键字有点过时了。

我还尝试在本地机器上使用 gcc-8 编译此示例,但结果相同。

#include <cstdio>

int foobar()
{   
   return 0;
}

int main()
{
    printf("%d", foobar());
}

Compiler Explorer.

【问题讨论】:

  • 调用被内联在你提供的链接中,main 中没有调用 foobar。
  • 请注意该函数存在(内联调用旁边),因为它可能从另一个翻译单元链接(即使在这种情况下没有其他翻译单元)。
  • 我认为您将函数调用与函数定义混淆了。
  • inline的原义同时被移动。由于编译器可以最好地确定内联的价值,因此不再需要提示。 inline 现在用于标记重复的外部定义(否则会导致链接错误),例如标头中的变量或函数定义(必须是inlined)。 (inline)
  • @Scheff:非常感谢。事实上,我忽略了这个事实。我刚刚看到该函数仍然存在,但实际上它从未被调用过。

标签: c++ optimization inline


【解决方案1】:

即使没有inline 关键字,它们也是内联的。你的例子太简单了,不需要 inling,因为在编译过程中返回值是已知的

https://godbolt.org/z/tNcSrf

volatile int x;

int foobar(int x)
{   
   return x * x;
}

int main()
{
    printf("%d\n", foobar(x));
}

foobar:
        mul     r0, r0, r0
        bx      lr
main:
        push    {r3, lr}
        ldr     r3, .L5
        ldr     r0, .L5+4      //inlined here
        ldr     r1, [r3]
        mul     r1, r1, r1
        bl      printf
        movs    r0, #0
        pop     {r3, pc}
.L5:
        .word   x
        .word   .LC0
.LC0:
        .ascii  "%d\012\000"

它会保留函数的副本,因为它可能会从另一个翻译单元调用。如果函数在同一个单元中被多次调用,编译器可以完全不内联它(取决于编译选项)。

要确保函数始终是内联的,您需要使用属性

inline __attribute__((always_inline)) int foobar(int x);

static inline __attribute__((always_inline)) int foobar(int x);

【讨论】:

  • 我看到了你的全球volatile int x;。我强烈假设,您这样做是为了防止编译时计算。另一个简单的选择是使这些变量成为控制台输入的对象。 IE。 int x; scanf("%d", &amp;x); 应该达到同样的效果。 (用户输入在运行时给出的变量值不能在编译时是已知/考虑的。);-)
  • @Scheff 它必须被使用或容易产生副作用。方法无所谓。
猜你喜欢
  • 2013-06-16
  • 2021-11-22
  • 1970-01-01
  • 2013-03-10
  • 1970-01-01
  • 2019-06-14
  • 2013-09-19
  • 2018-11-01
相关资源
最近更新 更多