哪些指令会在 x86 CPU 上产生分支预测错误?

Rim*_*eps 3 cpu x86 assembly pipeline branch-prediction

我这里有一个测试题。

哪些指令可能会减慢处理器的工作速度,然后流水线不会预测(分支预测)进一步的执行方式?

可能的答案: JGE | 添加 | 订阅 | 推 | JMP | JNZ | 多| JG | 称呼

如果我们谈论分支预测,JGE、JMP、JNZ 和 JG 是要走的路吗?

Pet*_*des 5

mul这样的指令对 EIP 没有任何特殊作用,当然不能预测错误,但是在流水线设计中,每种跳转/调用/分支都可能在一定程度上预测错误,即使是简单的call rel32. 在像现代 x86 CPU 这样的大量流水线乱序执行设计中,这种影响可能很严重。

是的,jcc条件分支总是需要预测;FLAGS 的值在解码时不可用,只有在稍后执行时才可用。

即使直接jmp rel8/ jmp rel32(和call rel32)也需要在前端早期进行预测,甚至在它们被解码之前,因此获取阶段知道在获取可能包含或不包含跳转(无条件或预测采取的有条件的;它不需要知道,只需要知道是否保持直线获取)。如果 BTB 数量过多,请参阅Slow jmp-instruction以获取有关运行速度较慢的简单无条件直接分支的更多信息。

如果你考虑一个简单的有序流水线,比如经典的 5 级 RISC,在阶段之间没有缓冲区,那么所有分支基本上是等效的:获取阶段需要每个时钟获取 1 条指令以避免气泡。它需要在前一条指令仍在解码时知道下一个取指地址。更长的管道使这个问题更加严重。


但更简单的是,有间接形式的jmpand calllike jmp eaxorjmp [edi]从寄存器或内存加载新的 EIP。那些显然需要预测;你有无限的可能性来决定它的去向,而不仅仅是被接受或不被接受。

依赖于数据的分支(以 FLAGS 为条件,或间接依赖于寄存器或内存)可以在发现错误预测之前一直进入后端(并乱序执行)。恢复可能需要丢弃 从错误路径执行后续指令的结果,以及获取/解码正确路径。 当 Skylake CPU 错误预测分支时究竟会发生什么?

但是处理直接 jmp/call 的错误预测更简单:只需重新引导提取/解码阶段,因为在解码指令后目标地址是已知的,而不必执行它。错误预测不会进入后端,所以它“只是”前端的一个泡沫。


有趣的事实:ret也可能会错误预测;它基本上是一个间接分支 ( pop eip)。但是有一些特殊的预测器利用了 call 和 ret 指令之间通常的配对,保留了最近调用的内部堆栈,反映了内存中调用堆栈的可能使用方式。 http://blog.stuffedcow.net/2018/04/ras-microbenchmarks/