用于 gcc 或 clang 的 LTO 是否可以跨 C 和 C++ 方法进行优化
Can LTO for gcc or clang optimize across C and C++ methods
如果 link 时间优化 (LTO) 与 gcc or clang 一起使用,是否可以跨 C 和 C++ 语言边界优化代码?
例如,能否将 C 函数内联到 C++ 调用程序中?
是的!
Link-time 优化通常适用于 "fat" 目标文件中存在的中间表示 (IR),它可以包含传统 linking 的机器码和 LTO 的 IR linking.
在这个阶段,没有更多的高级语言结构,所以 link-time-optimization 与语言无关。
海湾合作委员会
GCC 的 link-time optimization (LTO) 在 GIMPLE 上工作,GIMPLE 是 GCC 的中间表示之一。 IR 始终与语言无关,因此任何 link 时间优化都适用于从任何语言生成的代码。
来自 GCC Optimization Options 文档:
Another feature of LTO is that it is possible to apply interprocedural optimizations on files written in different languages:
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
Notice that the final link is done with g++ to get the C++ runtime libraries and -lgfortran
is added to get the Fortran runtime libraries. In general, when mixing languages in LTO mode, you should use the same link command options as when mixing languages in a regular (non-LTO) compilation.
这里有一个例子可以向您展示这项技术的强大之处。我们将定义一个 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
使用相同的语法,Clang 能够使用 LLVM IR 生成 "fat" 目标文件,这可以在 link 时间内进行优化。参见 LLVM Link Time Optimization。
使用与上面相同的测试代码,clang 产生完全相同的结果:
00000000004004b0 <main>:
4004b0: b8 0a 00 00 00 mov eax,0xa
4004b5: c3 ret
如果 link 时间优化 (LTO) 与 gcc or clang 一起使用,是否可以跨 C 和 C++ 语言边界优化代码?
例如,能否将 C 函数内联到 C++ 调用程序中?
是的!
Link-time 优化通常适用于 "fat" 目标文件中存在的中间表示 (IR),它可以包含传统 linking 的机器码和 LTO 的 IR linking.
在这个阶段,没有更多的高级语言结构,所以 link-time-optimization 与语言无关。
海湾合作委员会
GCC 的 link-time optimization (LTO) 在 GIMPLE 上工作,GIMPLE 是 GCC 的中间表示之一。 IR 始终与语言无关,因此任何 link 时间优化都适用于从任何语言生成的代码。
来自 GCC Optimization Options 文档:
Another feature of LTO is that it is possible to apply interprocedural optimizations on files written in different languages:
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
Notice that the final link is done with g++ to get the C++ runtime libraries and
-lgfortran
is added to get the Fortran runtime libraries. In general, when mixing languages in LTO mode, you should use the same link command options as when mixing languages in a regular (non-LTO) compilation.
这里有一个例子可以向您展示这项技术的强大之处。我们将定义一个 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
使用相同的语法,Clang 能够使用 LLVM IR 生成 "fat" 目标文件,这可以在 link 时间内进行优化。参见 LLVM Link Time Optimization。
使用与上面相同的测试代码,clang 产生完全相同的结果:
00000000004004b0 <main>:
4004b0: b8 0a 00 00 00 mov eax,0xa
4004b5: c3 ret