我知道它们只有在提交重新排序缓冲区中的指令之前才能正确执行。我的疑问是,现代处理器是否会将它们保留到 ROB 中的最后一个,或者是否使用任何预测计数器/结构来预测标志值,例如零标志或进位标志,然后在预测错误时重做它们
最佳答案
I know they can only correctly execute after instructions before them in Re-Order Buffer are committed.
不,他们只需要准备好自己的输入:那些特定的先前指令已执行,而不是退休/提交。
条件移动指令(和 ARM 谓词执行)将标志输入视为数据依赖项,就像带进位的加法或整数输入寄存器一样。在所有 3 个输入都就绪1之前,条件指令无法发送到执行单元。 (或者在 ARM 上,标记 + 谓词指令通常具有的输入数量。)
与控制依赖项(分支)不同,它们不会预测或推测标志是什么,因此使用 cmovcc
而不是 jcc
可以创建循环携带的依赖链,最终比可预测的分支更糟糕。 gcc optimization flag -O3 makes code slower than -O2就是一个例子。
Linus Torvalds 更详细地解释了为什么 cmov 经常很糟糕:https://yarchive.net/comp/linux/cmov.html
(ARM 谓词执行的处理方式可能略有不同。即使对于加载或存储到无效地址,它也必须在逻辑上对指令进行 NOP。这可以通过条件加载的故障抑制来处理。我不知道是否具有错误谓词的指令仍然会在目标寄存器的依赖链中产生任何延迟。)
脚注 1:这就是为什么 cmovcc
和 adc
在 Broadwell 之前的 Intel 上是 2 个微指令:单个微指令不能有 3 个输入依赖项。 Haswell 引入了对 FMA 3 输入微指令的支持。
cmov
指令(即读取 CF 和 ZF 的 cmova
和 cmovbe
)实际上仍然是 2 Skylake 上的 uops。请参阅this Q&A详细信息:似乎这两个单独重命名的标志组都是单独的输入,避免了标志合并。另请参阅https://uops.info/用于微指令计数。
另请参阅http://agner.org/optimize/ ,和https://stackoverflow.com/tags/x86/info了解有关 x86 微体系结构详细信息和优化指南的更多信息。
关于assembly - 无序执行如何与条件指令一起工作,Ex : CMOVcc in Intel or ADDNE (Add not equal) in ARM,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50959808/