PGO 如何应用于源代码?它如何影响 CFG?

How are PGOs applied to the source code? How does it affects the CFG?

最近一直在找PGO的相关话题,开始琢磨它们是怎么应用到源码上的,应用效果一个接一个地应用了。

我的意思是,如果您在 GCC 或 CLang 中启用 PGO 优化,例如,它将应用所有优化(内联、虚拟调用推测、死代码分离等),对吧!?

即使它们都没有应用到源代码,我们假设其中一些是。然后,我猜它们是按顺序应用的,对吧?

那么,他们能否将 CFG(控制流图)修改到丢失一些基本块频率的程度?

例如,如果在名为"A"的PGO之后应用了名为"B"的PGO,并且"A"修改了源代码,从而丢失了一些Basic Blocks频率,如何"B" 是否应用(假设两者都是依赖于 BB 频率的 PGO)?

(抱歉我的英语不好)

PGO 和大多数其他优化不应用于源代码,它们应用于中间代码。源代码本身保持不变。但是,生成的二进制代码将(希望)得到优化。

PGO 的目的是提高传统优化的有效性,包括内联、虚拟调用推测和很少执行的代码分离。所以它们都仍然适用。您猜对了,它们是按顺序应用的。

其中一些优化更改了代码的 CFG。但是,编译器会跟踪已分析的原始基本块,即使它们在中间代码中的位置已更改。在 PGO 中,编译器从不删除任何基本块。然而,编译器可能会保持基本块不变、更改其位置、将基本块扩展为多个基本块或插入新的基本块。无论它做什么,它都会跟踪原始配置文件的基本块及其执行统计信息,以便进一步优化知道如何使用配置文件。如果插入了新的基本块,将正常优化而不使用配置文件。