在结构冒险和数据冒险中,所有的流水线停顿操作都要从指令执行阶段开始。而控制冒险(Control Hazard)则是发生在取指令和指令译码阶段。
在 jmp 指令发生的时候,CPU 可能会跳转去执行其他指令。jmp 后的那一条指令是否应该顺序加载执行,在流水线里面进行取指令的时候,我们没法知道。要等 jmp 指令执行完成,去更新了 PC 寄存器之后,我们才能知道,是否执行下一条指令,还是跳转到另外一个内存地址,去取别的指令。
1. 缩短分支延迟
将条件判断、地址跳转都提前到指令译码阶段进行,而不需要放在指令执行阶段。在 CPU 里面设计对应的旁路,在指令译码阶段,就提供对应的比较电路。
但是,跳转指令的比较结果,仍然需要在指令执行完的时候才能知道。在流水线里,第一条指令进行指令译码的时钟周期里,其实就要去取下一条指令了。这个时候,其实还没有开始指令执行阶段,自然也就不知道比较的结果。
2. 分支预测
最简单的分支预测(Branch Prediction)技术叫做假装分支不发生。即仍然按照顺序,把指令继续往下执行。这样的预测也叫作静态预测技术。
3. 动态分支预测
常见的预测方法,一级分支预测(One Level Branch Prediction)(也称 1 比特饱和计数(1 bit saturating counter)),用一个比特,去记录当前分支的比较情况,直接用当前分支的比较情况,来预测下一次分支时候的比较情况。还有 2 比特饱和计数(也称双模态预测器(Bimodal Predictor))。其实也只是通过一个状态机,多看了一步过去的跳转比较结果。
两者都是利用 状态机 来进行预测。