超标量处理器设计——第四章_分支预测
参考《超标量处理器》姚永斌著
4.1 简述
- 分支预测主要与预测两个内容, 一个是分支方向, 还有一个是跳转的目标地址
- 首先需要识别出取出的指令是否是分支指令, 如果是需要送入方向和地址预测模块:

- 分支预测最好的时机就是当前周期取到指令地址的时候, 就进行预测, 这样就可以在下个周期根据预测结果取指
- 进行分支预测的PC实际是虚拟地址, 在一个进程内PC值对应唯一一条指令, 只不过在进程切换后需要将分支预测器的内容清空, 才能保证不同进程互不干扰.
4.2 分支指令的方向预测
4.2.1 基于两位饱和计数器的分支预测
-
最广泛使用的预测技术就是两位饱和计数器的分支预测器
-
有四个状态,如下图:
-
-
状态机在饱和时需要连续两次预测失败才会改变预测结果
-
相当于一个去抖电路
-
可以使用格雷码减少翻转降低功耗
-
每一个PC都会对应一个两位饱和计数器, 但是这样对于32位的PC长度来说, 全部分配一个显然是不现实的, 因此通常用PHT, 如下图:
-
-
PHT (Pattern History Table)是一个表, 存放PC值的一部分对应的两位饱和计数器的值.
-
PHT只用PC的k位来寻址, 以降低表项个数
-
PC值的k部分相同的两条指令会对应PHT的同一个表项, 这种情况称为别名(aliasing)
-
别名问题会导致分支预测的状态有可能错误跳转(因为会两条指令会相互干扰)
-
PHT越大, 别名问题就越不显著(因为k位相同的可能性降低了):
-
-
避免别名的方法: 哈希(Hash) , 对PC值进行处理后再寻址PHT:
-
-
哈希算法能够将32位PC压缩为固定长度的较小值, 这样保证了不同PC尽量不会寻址同一个PHT地址.
-
更新PHT的状态机有三个时机:
- 在取指令阶段, 进行分支预测时用预测结果更新PHT
- 在执行阶段, 当分支方向计算出来时根据结果更新PHT
- 在提交阶段, 分支指令要离开流水线时更新PHT
-
上面三种方法准确度依次提升. 方法1是最不可靠的, 因为预测结果可能是错的, 方法二也不能保证计算的分支结果是对的, 因为这条指令之前可能也有分支指令, 而该指令可能处于之前分支指令的预测错误路径上. 所以只有第三种方法才是万无一失的.
4.2.2 基于局部历史的分支预测
- 对于很有规律的分支指令, 两位饱和计数器的准确率可能很糟糕, 例如下图的情况, 初始在weakly not taken , 则对于TNTNTN…这样的序列, 预测将一次都不对:

解决办法:
-
BHR (Branch History Register) , 也称为自适应的两级分支预测(Adaptive Two-level Predictror)
-
将一条分支指令每次的结果都写入BHR寄存器, 就能记录该指令的历史状态
-
-
BHR位宽为n, PHT地址宽度与之对应. 用BHR来寻址PHT
-
PHT中实际不是每个表项都是一个饱和计数器, 实际只是存储了一个计数器的值. 每次更新表项需要先读出计数器值, 然后放到统一的饱和计数状态机里获得下一个状态的值再写回.
-
例子:
- 假设BHR位宽为2, 对应一个4个表项的PHT, 假设分支序列是T -> NT -> T -> NT -> T …
- BHR是一个移位寄存器, 所以相当于2位的寄存器在一个101010…的序列上滑动, 寄存器的值要么是10, 要么是01
- 当BHR是10时,下一次进来的一定是1,也就是一定是跳转,10寻址PHT的第三个表项,当分支结果计算出来之后会更新这个表项,则之后再遇到BHR是10的情况,去PHT中获取历史预测结果就可以得到预测为跳转的结果了。 同理BHR是01是处理过程也是类似的。