整数 DIV 指令的微指令

uops for integer DIV instruction

我正在查看 Agner Fog 的说明表 here,具体来说,我正在查看沙桥外壳,有一件事引起了我的注意。如果您查看 DIV 指令,您会发现,例如,r64 DIV 指令最多可以解码 56 微指令!我的问题是:这是真的还是我误解了?

这是我什至没有想到的事情。我一直认为 2 个寄存器的整数 division 仅在 1 uop 中解码。并认为那个 uop 被发送到端口 0(例如在 Sandy Bridge)。

我认为这里发生的事情是:uop 被分派到 Port0 并在一些周期后完成。但是,由于流水线,1 div uop(或另一个需要 port0 的 uop)可以在每个周期发送到该端口。但这完全打破了我的计划:56 个不同的 uops 需要在 56 个不同的周期中调度并占用 56 个 ROB 条目以仅执行 1 个整数 division?

并非端口 0 上的实际 divider 单元上的所有这些微指令 运行。似乎只有签名 idiv 是 Skylake 上的许多微指令, div r64 是“仅”33 微指令。也许带符号的 idiv r64 正在采用绝对值来使用较窄的 HW divider 单元进行扩展精度 division,就像您对软件扩展精度所做的那样? (Why is __int128_t faster than long long on x86-64 GCC?)

idiv/div r32 是“仅”10 微指令,可能只有 1 或 2 个需要端口 0 上的实际 divide 单元,其他人在其他端口上做 IDK。请注意 上 Skylake 配置文件结果中显示的 arith.divider_active 的计数 - div r64 的小输入勉强保持实际端口 0 divider 的活动时间超过div r32,但其他开销使其变慢。

FP division 实际上是单 uop,因为 FP div 性能在一些现实世界的算法中很重要。 (特别是一个 divpd 对周围代码的前端吞吐量的影响)。参见 Floating point division vs floating point multiplication

另见 - Ice Lake 改进了 divider 硬件。


另请参阅评论中消除其他误解的讨论。

相关:

  • Why is division more expensive than multiplication? division 从根本上说很难流水线化。

我想我读过现代 divider 单元通常由一个迭代的非完全流水线部分构建,然后是 2 个流水线化的 Newton Raphson 步骤。这就是 division 可以在现代 CPU 上部分流水化的方式:只要当前一个可以进入执行单元的 Newton-Raphson 流水线部分,下一个就可以开始。