如果链接时优化 (LTO) 与gcc或clang一起使用,是否可以跨 C 和 C++ 语言边界优化代码?
例如,可以将 C 函数内联到 C++ 调用程序中吗?
是的!
链接时优化通常适用于“胖”目标文件中存在的中间表示(IR),它可以包含用于传统链接的机器代码和用于 LTO 链接的 IR。
在这个阶段,没有更多的高级语言结构,因此链接时间优化与语言无关。
GCC 的链接时间优化(LTO) 适用于 GIMPLE,它是 GCC 的中间表示之一。IR 始终与语言无关,因此任何链接时优化都适用于从任何语言生成的代码。
从GCC 优化选项文档:
LTO 的另一个特点是可以对用不同语言编写的文件应用程序间优化:
gcc -c -flto foo.c g++ -c -flto bar.cc gfortran -c -flto baz.f90 g++ -o myprog -flto -O3 foo.o bar.o baz.o -lgfortran
请注意,最后一个链接是使用 g++ 完成的,以获取 C++ 运行时库,并
-lgfortran
添加以获取 Fortran 运行时库。通常,在 LTO 模式下混合语言时,您应该使用与在常规(非 LTO)编译中混合语言时相同的链接命令选项。
这是一个示例,可以向您展示这项技术的强大功能。我们将定义一个 C 函数并从 C++ 程序中调用它:
func.h
#ifndef FUNC_DOT_H
#define FUNC_DOT_H
#ifdef __cplusplus
extern "C" {
#endif
int func(int a, int b, int c);
#ifdef __cplusplus
}
#endif
#endif /* FUNC_DOT_H */
func.c
#include "func.h"
int func(int a, int b, int c)
{
return 3*a + 2*b + c;
}
main.cpp
#include "func.h"
int main()
{
int a = 1;
int b = 2;
int c = 3;
return func(a, b, c);
}
编译
gcc -o func.o -c -Wall -Werror -flto -O2 func.c
g++ -o main.o -c -Wall -Werror -flto -O2 main.cpp
g++ -o testlto -flto -O2 main.o func.o
拆机( objdump -Mintel -d -R -C testlto
)
Disassembly of section .text:
00000000004003d0 <main>:
4003d0: b8 0a 00 00 00 mov eax,0xa ; 1*3 + 2*2 + 3 = 10
4003d5: c3 ret
你可以看到它不仅将我的 C 内联func()
到我的 C++main()
中,而且把整个事情变成了一个常量表达式!
使用相同的语法,Clang 能够使用 LLVM IR 发出“胖”目标文件,可以在链接时进行优化。请参阅LLVM 链接时间优化。
使用与上面相同的测试代码,clang 产生完全相同的结果:
00000000004004b0 <main>:
4004b0: b8 0a 00 00 00 mov eax,0xa
4004b5: c3 ret