强制函数在Clang / LLVM中内联
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了强制函数在Clang / LLVM中内联相关的知识,希望对你有一定的参考价值。
有没有办法在Clang / LLVM中强制使用内联函数?
AFAIK,以下只是对编译器的一个提示,但它可以忽略该请求。
__attribute__((always_inline))
我不介意如果它不能内联函数,编译将失败。
如果使用C99进行编译是一个很好的解决方案,这是Clang的默认设置。它只是使用内联属性。
inline void foo() {}
它在Clang's compatibility page写得很好:
默认情况下,Clang根据C99标准构建C代码,该标准为内联关键字提供与GCC默认行为不同的语义...
在C99中,内联意味着函数的定义仅提供给内联,并且程序中的其他位置还有另一个定义(没有内联)。这意味着该程序是不完整的,因为如果没有内联添加(例如,在没有优化的情况下进行编译),那么main将具有对该其他定义的未解析引用。因此,我们会得到(正确的)链接时错误...
GCC将其视为扩展,并将其视为优化器的提示。
所以为了保证函数内联:
- 不要使用静态内联。
- 不要为没有内联属性的函数添加其他实现。
- 您必须使用优化。但即使没有优化,编译也会失败,这是好的。
- 确保不要使用GNU89进行编译。
我将把你的问题视为在Clang / LLVM框架内要求任何工具。这是我的建议:将代码编译为LLVM bitcode,然后运行Always inline pass。
例如:
> clang <other CFLAGS> -emit-llvm -c -o foo.bc foo.c
> opt -always-inline foo.bc -o foo_inline.bc
> clang -c -o foo.o foo_inline.bc
我之前使用过这个序列,它内联了所有标记为“always_inline”的函数。在我的情况下,我已经在bitcode上做了其他的分析和转换,所以我只需要添加标志来选择。
您可以从以下实验开始:clang -mllvm -inline-threshold = n
参数n越大,内联就越激烈。默认值为225,因此将其设置为更大的值。期望大代码大小和长编译时间以及非常激进的内联。当您达到收益递减点时,您可以尝试分析代码并查找经常调用但未内联的函数,并尝试使用属性((always_inline))标记它们以进行更多内联。
如果您有标记为“内联”的函数,则还可以使用大于-inline-threshold的-inlinehint-threshold进行实验,并查看这是否会发生任何变化。
另外,您是否正在使用链接时优化进行编译?没有它们内联仅限于个别编译单元。
只是一些可能有用的评论。
对于OP的评论:
- 多个
static inline
定义是一个警告,因为它可以在更改其中一个时导致多个不同的函数,这些函数可能导致许多头部刮擦,特别是如果内联开始并且实际调用蒸发到不同的语句序列。 - 这可以产生与1类似的效果。
- 内联是一种优化,您可以查看编译器的手册以查看它何时启动(例如gcc doc page)。通常,它处于第一级。另见this答案。
有用的讨论和建议可以找到here。对C99的建议总结如下:
- 在头文件中定义以下内容并将其包含在任何需要的位置:
inline void foo() { /*...*/ }
- 在单个源文件中使用
extern
声明它以生成外部符号:extern inline foo();
至于提出的LLVM IR方法,它可以工作,但是你通过源语言域并受制于一组不同的规则(高度依赖于工具)。可以找到简短的指示性讨论here。
蛮力方法只是把它变成一个宏。
以上是关于强制函数在Clang / LLVM中内联的主要内容,如果未能解决你的问题,请参考以下文章