当 skylake CPU 错误预测分支时究竟会发生什么?

What exactly happens when a skylake CPU mispredicts a branch?

我试图详细了解当错误预测分支时,skylake CPU 管道的各个阶段中的指令会发生什么情况,以及来自正确分支目的地的指令可以多快开始执行.

因此,让我们将此处的两条代码路径标记为红色(已预测但未实际采用)和绿色(已采用但未预测)。所以问题是: 1. 在红色指令开始被丢弃之前,分支必须经过流水线多远(以及它们在流水线的哪个或哪些阶段被丢弃)? 2. 绿色指令多久可以开始执行(就分支到达的流水线阶段而言)?

我查看了 Agner Fogg 的文档和多套讲义,但发现这些要点并不清楚。

分支执行单元(在端口 0 和 6 上)实际检查条件或间接分支的 FLAGS 或间接分支地址。我 认为 一旦执行单元发现它,恢复就开始了,而不是等待它退休。 (其中一些是我最好的猜测/理解,不一定由英特尔的优化手册支持。)

分支预测+推测执行将数据依赖与控制依赖解耦,但分支uop本身确实对EFLAGS或间接地址输入有数据依赖。

p0 上的分支单元只能运行 predicted-not-taken JCC uops(或宏融合的JCC uops),但这些很常见。 p6 上的分支单元是 "main" 处理分支的单元。


对于直接分支(jmp rel8/rel32 / call rel32),可以在解码时检查预测并重新引导获取阶段,可能会拖延前端,但我认为永远不需要触发任何后端的某种恢复。来自错误路径的 uops 永远不会为直接无条件分支发出。有用于管道重新引导的性能计数器。


分支错误预测可以通过分支顺序缓冲区快速恢复,这与异常情况下通常回滚到退休状态不同:When an interrupt occurs, what happens to instructions in the pipeline?. For more about how the pipeline treats everything as speculative until retirement, see .

根据David Kanter's Sandybridge microarch writeup

Nehalem enhanced the recovery from branch mispredictions, which has been carried over into Sandy Bridge. Once a branch misprediction is discovered, the core is able to restart decoding as soon as the correct path is known, at the same time that the out-of-order machine is clearing out uops from the wrongly speculated path. Previously, the decoding would not resume until the pipeline was fully flushed.

这是由分支顺序缓冲区启用的 "fast recovery",该缓冲区在条件和间接分支指令上快照注册重命名状态,预计即使在正常程序中也会出现错误预测。但是异常和内存排序机器清除的成本更高。它们确实会发生(尤其是页面错误),但它们更罕见且更难优化。

快速恢复的关键在于ROB+RS(scheduler)中已经存在的预测错误分支之前的uops可以继续执行之后uops 被丢弃 并且前端重新转向正确的地址。因此,如果 JCC uop 的输入准备得足够早,那么如果 CPU 可以在恢复时咀嚼很长的依赖链,则可以隐藏大部分分支未命中惩罚。例如从具有适当长度循环的循环退出的错误预测携带 dep 链,或除总 uop 吞吐量或端口 6 瓶颈之外的任何瓶颈。参见

如果没有快速恢复,我认为 ROB 中的 all 微指令将被丢弃(即所有未退休的微指令)。这里可能有一些中间立场,比如在 ROB 中但已经离开调度程序的分支之前保留已经执行的 uops。我不知道 Merom/Conroe 到底做了什么。


相关:Characterizing the Branch Misprediction Penalty 是一篇关于分支未命中和长缓存未命中如何与 ROB 交互的有趣论文。它基于简化的管道模型,但在我看来它的发现可能适用于 Skylake。