(一)分支预测的作用
从计算机发展来看,新的设计,新的架构,都是为了解决问题而产生,或功能问题,或性能问题。
以if(a>b) funcA; else funcB; 为例,这条语句可以简单分解为一条cmp比较指令(a>b)和一条jump指令决定跳到funcA还是funcB。如果没有分支预测,那么会出现如下图所示情况。
上图以五级流水线 为例,水平表示CPU的时间轴。如果没有分支预测,jmp指令取指后,根据指令PC是无法知道下一条指令到底是funcA还是funcB。这样,流水线可能需要停下来多个时钟周期,直到jump指令解析出下一个地址是funcA还是funcB。
因为不想要流水线在碰到分支时停顿,那么就引入了分支预测。即在jump指令取指后,就预测下一条指令。在常用软件中,约20%的指令为跳转指令,因此分支预测极其准确性是微架构的重要研究方向之一。
总之,分支预测的作用主要是通过提前预测后续指令,提高流水线的利用率,进一步提升指令并行度。随着流水线深度和发射宽度的增加,分支预测对CPU的性能影响也越大。
(二)分支预测相关的指令与分类
arm跳转指令分类
不同的指令集跳转指令实现有一些差异,这里主要介绍aarch64指令集的相关跳转指令,如下图p1,aarch64跳转指令从两个维度分类:
(1)有条件跳转/无条件跳转
(2)直接跳转/间接跳转
有条件表示要满足条件才跳转,比如if…else需要进行条件判断。直接跳转和间接跳转,可以理解为跳转的地址是一个立即数(固定的),还是需要存在寄存器中(不固定的)。
从以上维度组合2*2=4,有4种跳转指令,下图为指令的分类和应用场景。aarch64没有条件间接跳转指令。
条件直接跳转:if…else… /for… /switch…case…
无条件直接跳转:函数调用,代码块跳转
无条件间接跳转:函数指针,函数返回ret(ret跳转的地址隐含在LR寄存器中)
跳转指令与C语言
以下为C语言常见的跳转指令产生场景:
(三)分支预测的核心问题
从以上分支指令分类的两个维度可以看到,跳转指令关心跳转条件满足不满足(跳还是不跳),跳转地址存在指令编码的立即数,还是存在于寄存器。
因此再复杂的分支预测算法,核心问题永远是:
(1)跳不跳
Taken
Not Taken
(2)跳到哪里
PC+4(Not Taken)
PC+offset(Taken)
后续将继续介绍常用的分支预测算法