笔者在查看PGO优化时看到了本站的这篇文章,其中代码和命令行部分贴上了序号,且命令行带上了$符号,不便于读者调试。
遂将代码重新整理到gitee,链接在此。
汇编代码分析
目前笔者使用的llvm版本为llvm-19,主要改动发生在生成的汇编文件上,可以看到,在使用PGO优化的版本里,已经没有了分支指令(不再存在两个不同的分支)。优化前的汇编代码:
main: # @main.cfi_startproc
# %bb.0:movl XX(%rip), %eaxmovl YY(%rip), %ecxcmpl $2, %edijl .LBB0_2
# %bb.1:addl $2, %eaximull %eax, %ecx
.LBB0_3:movl %eax, XX(%rip)movl %ecx, YY(%rip)xorl %eax, %eaxretq
.LBB0_2:decl %eaxsubl %eax, %ecxjmp .LBB0_3
可以看到,首先将XX分配给eax寄存器,然后将YY分配给ecx寄存器,分别有%bb.1和.LBB0_2两处不同的处理,对应着源代码中true分支和false分支的处理。
优化后的汇编代码:
main: # @main.cfi_startproc
# %bb.0:movl XX(%rip), %eaxmovl YY(%rip), %ecxleal 2(%rax), %edxmovl %ecx, %esiimull %edx, %esidecl %eaxsubl %eax, %ecxcmpl $2, %edicmovgel %edx, %eaxcmovgel %esi, %ecxmovl %eax, XX(%rip)movl %ecx, YY(%rip)xorl %eax, %eaxretq
关键在于true分支的值存放在edx和esi中,false分支的值放置在eax和ecx中,当程序进行到判断结构时,如果为true的情况,就将edx移动到eax,将esi移动到ecx中,使得最终的结果始终分别存放在eax和ecx两个寄存器当中。
涉及代码分析
lib/CodeGen/MachineBlockPlacement.cpp
此文件的部分主体逻辑基本未变化,把BranchProbability SuccProb = getAdjustedProbability(RealSuccProb, AdjustedSumProb);
看成计算出一个可用的概率的结果就可以了,其他部分基本无障碍。
/// The helper function returns the branch probability that is adjusted
/// or normalized over the new total \p AdjustedSumProb.
static BranchProbability
getAdjustedProbability(BranchProbability OrigProb,BranchProbability AdjustedSumProb) {BranchProbability SuccProb;uint32_t SuccProbN = OrigProb.getNumerator();uint32_t SuccProbD = AdjustedSumProb.getNumerator();if (SuccProbN >= SuccProbD)SuccProb = BranchProbability::getOne();elseSuccProb = BranchProbability(SuccProbN, SuccProbD);return SuccProb;
}
贴一个Chatgpt的解释:
这个函数的作用是根据给定的原始分支概率(OrigProb)和调整后的总和概率(AdjustedSumProb),返回一个调整后的分支概率(SuccProb)。
具体来说,函数的步骤如下:
- 获取原始分支概率的分子 SuccProbN,这是原始概率的分子部分。
- 获取调整后总和概率的分子 SuccProbD,这是调整后总和概率的分子部分。
- 检查原始概率的分子部分 SuccProbN 是否大于等于调整后总和概率的分子部分 SuccProbD。如果是,则将调整后的分支概率 SuccProb 设置为最大可能的分支概率,即 BranchProbability::getOne(),这表示概率为100%。
- 否则,根据 SuccProbN 和 SuccProbD 创建一个新的 BranchProbability 对象 SuccProb,这个对象将成为函数的返回值。
因此,这个函数的核心目的是根据原始分支概率和调整后的总和概率,计算并返回一个调整后的分支概率,确保它在有效的概率范围内(0到1之间),以反映新的条件或上下文下的分支可能性。