【问题标题】:Can two instructions execute in the same cycle if the same register is used as input and output respectively?如果将同一个寄存器分别用作输入和输出,两条指令能否在同一个周期内执行?
【发布时间】:2016-12-31 03:41:16
【问题描述】:

例如,这两条指令是否可以在同一个周期开始执行,或者它们是否会相互干扰?

MOV  %RAX, (ADDR)      # AT&T syntax: store rax
POP  %RAX

【问题讨论】:

  • 如果是movl 那么不应该是eax吗?
  • @LưuVĩnhPhúc:很好,这完全是伪造的代码。我假设它是 16 位 Intel 语法(dst first,WAW 危险),因为几乎没有人将 AT&T 语法用于 16 位代码。 POP AX (popw %ax) 在 64 位模式和 32 位模式下有效,但 POPL 不是(并且这被标记为 x86-64),但我仍然认为将代码转换为有效会更清楚64 位 AT&T 语法。
  • 这是 Go 汇编程序的语法,我认为它来自 Plan9。不是最好的例子,感谢您更改它。你的重写是正确的。

标签: assembly x86 x86-64 cpu-architecture micro-optimization


【解决方案1】:

是的,它们可以在现代乱序 CPU 上以相同的周期执行,因为它们使用Tomasulo's algorithm 进行寄存器重命名。它完全避免了所有write-after-read hazards like this, and also write-after-write,因此乱序执行仅受Read-after-Write true 依赖项的限制。

寄存器重命名后,pop 会将 RAX 架构寄存器的新值写入与保存 RAX 旧值(作为存储的输入)的物理寄存器不同的物理寄存器。

指令之间的交互为零,因为pop 为 RAX 的值启动了一个新的依赖链。 (它的输出是只写的。) pop(以及读/写 RAX 的后续指令)可以在存储之前执行多个周期,特别是如果要存储的值是由长依赖链产生的。

另请参阅 Agner Fog's microarch pdf 标签 wiki 中的其他链接。


更新:我以为您是在询问写入同一寄存器或读取同一寄存器的两条指令,因为您的原始示例代码省略了 % 标记,并使用了 AX,所以我假设它是 16 位英特尔-句法。无论如何都要留下这部分作为奖励。

读取同一个寄存器的两条指令(读后读)根本不构成危害。

Sandybridge 之前的 Intel CPU 对可以在同一周期内读取的非最近修改寄存器的数量有限制,但在附近指令中多次读取同一寄存器是没有问题的。 (在 Agner Fog 的 microarch pdf 中搜索寄存器读取端口停顿,和/或查看 this answer where it was relevant)。

【讨论】:

  • 迷人的现代无序 CPU 非常复杂 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-06-05
  • 1970-01-01
  • 2018-02-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多