可以通过C和C++方法优化LTO for gcc或clang

Bee*_*ope 9 c c++ gcc clang link-time-optimization

如果链接时优化(LTO)与gccclang一起使用,是否可以跨C和C++语言边界优化代码?

例如,C函数可以内联到C++调用者中吗?

Jon*_*art 10

是!

链接时优化通常适用于"胖"目标文件中存在的中间表示(IR),其可以包含用于传统链接的机器代码和用于LTO链接的IR.

在这个阶段,没有更多的高级语言结构,因此链接时优化与语言无关.


GCC

GCC的链路时间优化(LTO)适用于GCC的中间代表之一GIMPLE.IR始终与语言无关,因此任何链接时优化都可以在任何语言生成的代码中使用.

GCC Optimization Options文档中:

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
Run Code Online (Sandbox Code Playgroud)

请注意,最终链接是使用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 */
Run Code Online (Sandbox Code Playgroud)

func.c

#include "func.h"

int func(int a, int b, int c)
{
    return 3*a + 2*b + c;
}
Run Code Online (Sandbox Code Playgroud)

main.cpp

#include "func.h"

int main()
{
    int a = 1;
    int b = 2;
    int c = 3;

    return func(a, b, c);
}
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

拆解(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
Run Code Online (Sandbox Code Playgroud)

你可以看到它不仅将我的C内联func()到我的C++中main(),而且它将整个事物变成了一个常量表达式!


Clang/LLVM

使用相同的语法,Clang能够使用LLVM IR发出"胖"对象文件,可以在链接时进行优化.请参阅LLVM链路时间优化.

使用与上面相同的测试代码,clang产生完全相同的结果:

00000000004004b0 <main>:
  4004b0:   b8 0a 00 00 00          mov    eax,0xa
  4004b5:   c3                      ret
Run Code Online (Sandbox Code Playgroud)

  • 对 - 我的答案是假设一个正确,正常工作的编译器/链接器安装. (2认同)
  • Clang似乎没有产生“胖”目标文件的方法(至少根据gcc的术语)。`func.o`只是LLVM IR位码,所以它不能用clang以外的任何东西进行编译(虽然我现在很挣扎,但是应该可以用clang进行反编译):https://stackoverflow.com/questions / 51259340 / clang-gcc-and-lto之间的互操作性 (2认同)