分支预测如何与指令指针交互

How does branch prediction interact with the instruction pointer

我的理解是,在处理器流水线的开始,指令指针(指向下一条要执行的指令的地址)在取指后被分支预测器更新,这样这个新地址就可以被在下一个周期获取。

但是,如果指令指针在流水线的早期被修改,这不会影响当前处于可能依赖于旧指令指针值的执行阶段的指令吗?比如在做call的时候需要把当前的EIP压入栈,但是分支预测的时候更新指令指针不会有影响吗?

您似乎假设整个 CPU 核心只使用一个物理 EIP 寄存器。

这行不通,因为每条可能发生异常的指令都需要知道自己的地址。或者当外部中断到达时,CPU 可以决定在任何指令之后为中断服务,使该指令成为架构 EIP。在长模式 (x86-64) 中,还有相对于 RIP 的寻址模式,因此 call 不是唯一需要当前程序计数器作为数据的指令。

一个简单的流水线 CPU 可能每个流水线阶段都有一个 EIP。

现代超标量乱序 x86 将 EIP(或 RIP)与每个运行中的指令(或者可能是每个 uop;但是多 uop 指令具有所有它们的 uops 相互关联,因此指令不能部分退出。)

与架构状态的其他部分(例如 EFLAGS、EAX 等)不同,该值在解码后是静态已知的。实际上甚至早于立即值;在预解码阶段(或在 L1i 缓存中标记)检测指令边界,以便可以将多条指令并行馈送到多个解码器。

早期的 fetch/decode 阶段可能只跟踪 16 字节或 32 字节的提取块的地址,但解码后我假设内部 uop 表示中有一个地址字段。对于非分支指令,它可能只是与之前(保存 space)的一个小偏移量,因此如果需要它可以计算,但我们在这里深入研究实现细节。乱序执行在程序顺序中维护指令 运行 的 错觉 ,并且它们确实按顺序发出和退出(enter/leave 乱序-命令执行部分的核心)。

相关: 基于观察玩具 CPU 做出了类似的错误假设。也没有 "current instruction" 寄存器保存机器代码字节。查看我的答案中的更多链接,了解更多关于 OoO / 流水线 CPUs.


分支预测必须在块被解码之前工作。即假设我们刚刚在地址 abc 获取了一个块,我们需要预测下一个要获取的块。即预测必须预测将并行解码的 16 字节指令块中是否存在跳转。

相关:Why did Intel change the static branch prediction mechanism over these years?