我在这里有一个测试问题。
哪些指令可能会减慢处理器的工作,然后管道无法预测(分支预测)进一步的执行方式吗?
可能的答案:JGE |添加| SUB |推| JMP | JNZ | MUL | JG |致电
如果我们在谈论分支预测,那么JGE,JMP,JNZ和JG是要走的路吗?
mul
之类的指令当然不会don't do anything special to EIP误判,但every的跳转/调用/分支在某种流水线设计中甚至在一个简单的call rel32
中都可能会误判。在诸如现代x86 CPU之类的大量流水线无序执行设计中,这种影响可能会很严重。
是,jcc
条件分支始终需要预测; FLAGS的值在解码时不可用,只有在执行时才可用。
甚至直接 [如果考虑一个简单的有序流水线,例如classic 5-stage RISC,则在各级之间没有缓冲区,则所有分支基本上都是等效的:获取级需要每个时钟获取1条指令以避免气泡。当前一条指令仍在解码时,它需要知道下一个提取地址。较长的管道会使此问题更严重。jmp rel8
/ jmp rel32
(和call rel32
)都需要预测] >>在前端甚至还没有解码之前,所以提取阶段知道接下来要提取哪个块] >在获取可能包含或不包含跳转的块之后(无条件或按预期采取的条件;它不需要知道,只是保持是否一直沿直线获取)。如果您的BTB太多,请参阅Slow jmp-instruction,以获取有关运行速度较慢的简单无条件直接分支的更多信息。
但更简单地说,jmp
和call
有间接形式,例如jmp eax
或jmp [edi]
,它们从寄存器或存储器中加载新的EIP
取决于数据的分支(取决于FLAGS,或者间接取决于寄存器或存储器)可以在发现错误预测之前一路进入后端(并无序执行)。要恢复,可能需要从错误的路径中丢弃executing后续指令的结果,以及获取/解码正确的路径。 What exactly happens when a skylake CPU mispredicts a branch?
但是处理直接jmp / call的错误预测更为简单:只需重新控制fetch / decode阶段,因为在解码指令后就知道了目标地址,而不必执行它。错误的预测不会使其进入后端,因此它只是前端中的一个气泡。
有趣的事实:ret
也可能会预测错误;它基本上是一个间接分支(pop eip
)。但是有一些特殊的预测变量可以利用调用和ret指令之间的常规配对,在内部保留最近调用的堆栈,以反映内存中可能如何使用该调用堆栈。 http://blog.stuffedcow.net/2018/04/ras-microbenchmarks/