Assembly 是mov-rax,0x12345678;jmp rax仍然终止分支预测?

Assembly 是mov-rax,0x12345678;jmp rax仍然终止分支预测?,assembly,x86-64,compiler-optimization,cpu-architecture,branch-prediction,Assembly,X86 64,Compiler Optimization,Cpu Architecture,Branch Prediction,我很难找到与上述两个案例相关的信息, 尽管听了你的专家意见 第一件事是:我知道间接jmp会损害分支预测,即使间接的结果是常量,它仍然需要预测维护缓冲区和其他东西,所有这些都与绝对jmp相比 我的问题是,如果有人知道: mov rax, 1234567812345678h; jmp rax; 仍然被处理器的分支预测器认为是间接的,或者它在这种情况下做了计算。。 我这样做是因为x64没有直接的“jmp absolute 64”指令,只有间接指令。:/(如果您不能将跳转放在离目标足够近的位置并使用j

我很难找到与上述两个案例相关的信息, 尽管听了你的专家意见

第一件事是:我知道间接jmp会损害分支预测,即使间接的结果是常量,它仍然需要预测维护缓冲区和其他东西,所有这些都与绝对jmp相比

我的问题是,如果有人知道:

mov rax, 1234567812345678h;
jmp rax;
仍然被处理器的分支预测器认为是间接的,或者它在这种情况下做了计算。。 我这样做是因为x64没有直接的“jmp absolute 64”指令,只有间接指令。:/(如果您不能将跳转放在离目标足够近的位置并使用
jmp rel32
,则建议使用此选项)


其次,在这个程度上,jmp 0x1234和调用0x1234(在处理器优化(指令缓存、预取器及其提示、分支预测)方面)有什么真正的区别吗?(vc2012“速度优化”产生呼叫,“最小尺寸选择”产生jmp,“混合优化”产生x64的jmp,产生x86的呼叫)

英特尔的分支目标(和分支)预测既非常复杂,又是一个保守的商业秘密。不一定只有一种算法,也就是说,您可以预期预测机制在不同的CPU之间是不同的;这取决于英特尔希望为给定处理器解决问题的晶体管数量。当然,除了英特尔,还有其他x86和x64处理器制造商

历史分支目标预测机制(historical branch target prediction mechanism)——它使用同一条指令的过去运行来预测后续执行的目标——几乎肯定会为该分支预测正确的目标,因为只有一个。因此,如果这个代码序列被重新执行(例如,在循环中),并且它在指令缓存中停留一段时间,它可能会得到很好的处理。(但是,在某些处理器上,如果其他地方发生另一个分支导致哈希冲突,则分支目标预测机制可能会被类似于缓存线冲突的效果抵消。)

一个更大的问题可能是,如果这样的序列在新加载到缓存中的代码中大量出现,那么它的处理情况会如何,这将导致处理器的非历史目标预测功能。这种(非历史的)分支目标预测可以很容易地确定给定此代码序列的分支位置,尽管它完全取决于制造商是否认为它值得任何给定处理器的芯片上的不动产。做出这种决定的因素包括功耗、权衡其他性能改进(即可能更好地使用同一芯片区域),以及此类和各种其他代码序列的预期频率。

“我知道间接JMP分支预测”

不,分支预测和间接跳转预测是不同的。此外,间接跳转用于基于表的switch语句和解释器中。这些是非常常见的用例,并在基准测试中显示出来。因此,英特尔和其他公司花费了大量的精力和大量的晶体管来提高其性能。一篇论文(在问题之后写得很好!)甚至说从桑迪桥开始,当涉及到间接跳跃预测时。英特尔+AMD有动机提高这一性能,他们也有

现在,如果您的jmp示例是冷代码,如果这是第一次执行,则无法预测,而且Skylake间接跳转预测器将预测跳转后的下一条指令,并从那里进行推测。您可以使用UD2(一种非法指令)关闭这种推测。在任何情况下,第二次执行jmp时(如果它仍然在BTB中),分支目标都是正确的


至于你的第二个问题,缓存效果并不重要。我想较小的版本可以英勇地保存缓存线溢出,但仅此而已。硬件预取器用于数据,而不是指令。

不要混淆分支预测和分支目标预测。分支预测是指分支是否将跳转。分支目标预测是分支将跳转的位置。在这种情况下,没有分支预测-这是一个无条件的跳转。我还要补充一点,在这种情况下,分支目标预测可能非常好(如果CPU记得上次的分支目标,那么..)。因此,如果我理解正确,就没有太大区别(在CPU硬件资源方面)由于RAX被硬编码预初始化为固定地址,并且RAX是易失性的,所以它将在这两种情况下使用cpu的目标预测资源?(后一种情况下唯一的额外成本是从另一个var间接读取RAX(例如)),或者说“它之前是硬编码预初始化的一行,所以我不需要占用分支目标历史缓冲区”会更明智吗)?我担心的是,管道中的预取器/早期阶段是否会认为,由于jmp是eax基,因此它不是“绝对”的,因此它无法预取目标指令,直到最后一分钟到达jmp(当它确定rax值时),而不是得出rax是硬编码的结论,所以jmp是绝对的..但是Agner记录了Intel CPU的一些特性;分支预测在第11-34页。我还没有听说过任何x86-64 CPU将mov r64、imm64/jmp reg融合到单个直接jmp uop中,甚至没有基于此进行预测。ARM CPU对thumb分支执行类似的操作,从技术上讲,thumb分支是两条指令,一条用于设置分支目标的一些位,另一条用于设置其余的位并跳转。但这只作为一对使用,没有副作用,而且很常见。这些都不适用于x86分支:更常见的是内存间接分支(都调用动态库)。您链接的论文()表明,在预测x86中的大型中央调度分支方面,真正做得很好的是Haswell,而不是SnB