lea 与 mov 在寄存器中存储地址常量

问题描述 投票:0回答:1

我有一个常量(64 位)地址,我想将其加载到寄存器中。该地址位于代码段中,因此可以相对于RIP 进行寻址。有什么区别

movabs rax, 0x1234567

lea rax, [rip+0xFF] // relative offset for 0x1234567

就执行速度而言,哪一个更可取(在理论上可以使用两种替代方案的情况下;例如在 JIT 中或当地址可以在链接时固定时)?通过查看反汇编结果,lea 的代码更少,但会因此更快吗?或者由于相对编码偏移可能会变慢?

assembly x86-64
1个回答
0
投票

在热循环中,前者 (

movabs
) 通常更快,因为它在大多数现代处理器上具有更高的倒数吞吐量。


事实上,在 Intel Haswell/Broadwell/Skylake/CoffeeLake/CannonLake/IceLake/TigerLake/RocketLake(这些湖太多)上,

movabs
的吞吐量倒数为 0.25,而
lea
的倒数吞吐量为 1(由于
rip
相对寻址)。

在最近的Intel AlderLake混合架构上,事情要复杂得多。 AlderLake 的 P 核 (GoldenCove) 的

movabs
的吞吐量倒数为 0.2,
lea
的倒数吞吐量为 1(主要是由于
rip
再次相对寻址)。 AlderLake 的 E-core (Gracemont) 非常不同:
movabs
的倒数吞吐量为 0.33,而
lea
的倒数吞吐量为 0.25。这意味着最好使用的指令取决于线程的调度位置!这太疯狂了。更有趣的是:看起来 Goldmont/Tremont 在 SunnyCove/WillowCove 时已经有了带有 rip 相对寻址的快速
lea
。这是因为 P 核和 E 核的架构是为不同的目的而设计的(据我所知,类 Mon 的架构是为低功耗处理器设计的,而类 Cove 的架构是为桌面处理器设计的)。更不用说英特尔最初肯定没有计划在同一芯片中混合两种架构。

AMD Zen1/Zen2 上,

movabs
为 0.25,
lea
为 0.5,因此前者也更好。在 AMD Zen3/Zen4 上,两者的吞吐量倒数均为 0.25,因此它们在此架构上的速度相同。

话虽这么说,前者需要更多的空间,并且“解码”速度可能比后者慢,因此后者可能会更好地超越热循环。事实上,指令被解码为微指令一次,然后放入缓存中进行相对较短的循环,但解码通常是执行一次大型代码的瓶颈(没有热循环或非常大的循环,并且可能需要从RAM 或 L3)。

© www.soinside.com 2019 - 2024. All rights reserved.