C++ 在LTO中进行的优化是否与在正常编译中相同?

C++ 在LTO中进行的优化是否与在正常编译中相同?,c++,optimization,compiler-construction,g++,llvm,C++,Optimization,Compiler Construction,G++,Llvm,在编译翻译单元的过程中,编译器进行了大量的优化——内联、常量折叠/传播、别名分析、循环展开、死代码消除以及许多我从未听说过的其他优化。 当在多个翻译单元之间使用LTO/LTCG/WPO时,所有这些都完成了吗?还是仅仅完成了其中的一个子集(或变体)(我听说过内联)? 如果不是所有的优化都完成了,我会认为Unity建立在LTO之上(或者当有超过1个统一源文件时,两者都可以使用)。 我的猜测是,这是不一样的(unity构建有完整的优化集),而且它在不同的编译器之间有很大的差异 关于每个编译器lto的文

在编译翻译单元的过程中,编译器进行了大量的优化——内联、常量折叠/传播、别名分析、循环展开、死代码消除以及许多我从未听说过的其他优化。 当在多个翻译单元之间使用LTO/LTCG/WPO时,所有这些都完成了吗?还是仅仅完成了其中的一个子集(或变体)(我听说过内联)? 如果不是所有的优化都完成了,我会认为Unity建立在LTO之上(或者当有超过1个统一源文件时,两者都可以使用)。 我的猜测是,这是不一样的(unity构建有完整的优化集),而且它在不同的编译器之间有很大的差异

关于每个编译器lto的文档并没有准确地回答这个问题(或者我无法理解它)

由于lto涉及到在目标文件中保存中间表示,理论上lto可以完成所有优化。。。对吧?

请注意,我不是在问构建速度——这是一个单独的问题

编辑
我最感兴趣的是gcc/llvm。

如果您查看了gcc文档,您会发现:

-flto[=n]

此选项运行标准链接时间优化器。当使用源代码调用时,它会生成GIMPLE(GCC的内部表示之一),并将其写入对象文件中的特殊ELF部分。当对象文件链接在一起时,所有函数体都从这些ELF部分读取并实例化,就像它们是同一翻译单元的一部分一样

要使用链接时优化器,应在编译时和最终链接期间指定-flto和优化选项。例如:

GCC的前两个调用将GIMPLE的字节码表示保存到foo.o和bar.o中的特殊ELF部分。最后一个调用从foo.o和bar.o读取GIMPLE字节码,将两个文件合并到一个内部映像中,并像往常一样编译结果。由于foo.o和bar.o都合并到一个映像中,这使得GCC中的所有过程间分析和优化都可以跨这两个文件工作,就像它们是单个文件一样。例如,这意味着内联器可以将bar.o中的函数内联到foo.o中的函数中,反之亦然。

正如文档所示,是的,全部!优化是在单个文件中编译程序时进行的。这也可以通过
-fwhole程序
实现,以获得“相同”的优化结果

如果编译这个非常简单的示例:

f1.cpp:

int f1() { return 10; }
f2.cpp:

int f2(int i) { return 2*i; }
main.cpp:

int main()
{   
    int res=f1();
    res=f2(res);
    res++;

    return res;
} 
我得到了汇编程序的输出:

00000000004005e0 <main>:
  4005e0:   b8 15 00 00 00          mov    $0x15,%eax
  4005e5:   c3                      retq   
  4005e6:   66 2e 0f 1f 84 00 00    nopw   %cs:0x0(%rax,%rax,1)
  4005ed:   00 00 00
0000000000 4005e0:
4005e0:b8 150 000 mov$0x15,%eax
4005e5:c3 retq
4005e6:66 2e 0f 1f 84 00 nopw%cs:0x0(%rax,%rax,1)
4005ed:00
所有代码都按预期内联

我的经验是,实际的gcc使用lto进行优化,就像在单个文件中编译一样。在非常罕见的情况下,我在使用lto时得到了冰。但在实际的5.2.0版本中,我没有再看到任何ICE


[ICE]->内部编译器错误

正如您自己所说,编译器之间可能存在很大差异。对GCC和LLVM进行回答可能是可行的,但除此之外,它的范围太广了。请缩小范围。@Bааћ链接时间优化(或链接时间代码生成或整个程序优化),这取决于编译器和目标。例如,DSP可以通过在第一块内存中放入一些代码来提高性能,而第一块内存通常具有更快的访问速度。
00000000004005e0 <main>:
  4005e0:   b8 15 00 00 00          mov    $0x15,%eax
  4005e5:   c3                      retq   
  4005e6:   66 2e 0f 1f 84 00 00    nopw   %cs:0x0(%rax,%rax,1)
  4005ed:   00 00 00