Nat*_*urz 5 x86 assembly cpu-registers mmx amd-processor
当我查看最近处理器的图表和概述时 [1],我从未看到提及 MMX 寄存器 MM0 - MM7。但从规格来看,它们似乎仍然存在。可以依赖它们存在于支持 SSE 的所有处理器中吗?除了更旧的 FPU 堆栈之外,它们是否与其他任何东西冲突?它们是否与一般 64 位的物理寄存器相同?
虽然 XMM 和 YMM 对于向量要好得多,但我偶尔想使用 MMX 寄存器来存储值,否则这些值会溢出到堆栈中。Speedwise 这看起来好一点,而且有时我想避免额外的商店和负载。
SSE1 意味着 MMX,所以支持 x86-64 保证 MMX(因为 SSE2 是 x86-64 的基线)。
它们别名 80 位 x87 寄存器,而不是通用整数寄存器!长模式不会改变 MMX 的工作方式。
所有现代 CPU 都支持 64 位,因此在所有模式下都可以使用 MMX。即使只有 32 位嵌入式AMD Geode CPU也有 MMX(但没有 SSE)。
当您拥有 16x XMM regs + 16x 64-bit GP regs 时,MMX 值得使用的情况非常罕见。 存储/重新加载并不可怕,特别是如果重新加载可以使用内存源操作数。
与存储/重新加载相比,将数据移入/移出 MMX regs 的额外 ALU uops 通常不值得。Reload 通常可以作为内存源操作数进行微融合,并且 ALU 执行端口压力很容易成为问题。
如果您在禁用缓存的情况下做了一些特殊的事情,那么当然可以,但是如果您可以将其远离关键路径,通常存储转发可以使存储/重新加载高效。(它确实有大约 5 个周期的延迟)。
但是,如果您确实想在 XMM 和 GP regs 之间移动数据,通常movd/movq或pinsrd/pextrd是一个不错的选择,而不是存储/重新加载。我是说在外循环中溢出/重新加载 GP 或 XMM reg 通常比 2x movq 或movq2dq xmm0, mm0.
事实上,在 Skylake 上,一个movq2dq成本为 2 uop。 对于movdq2q. (movq到/从 GP regs 仍然只有 1 uop,但具有与 XMM 和 GP regs 之间传输相同的端口 0 或端口 5 限制)。
另外,在函数中使用 MMX 会在emms它的末尾(或在任何函数调用之前,如果您想与 ABI 兼容)花费一条指令。MMX regs 在正常调用约定中都被调用破坏(实际上 FPU 必须处于 x87 状态而不是 MMX 状态)。
MMX 在现代 CPU 上绝对不如 XMM 高效。实际上将它用于存储以外的任何东西通常比 SSE2 更糟糕(movq如果你想在 64 位块中工作,加载/存储并忽略 XMM regs 的高字节)。
例如,在具有 mov-elimination for 的 Intel/AMD CPU 上movaps xmm,xmm,MMX 寄存器复制movq xmm1, xmm0仍然需要一个 ALU uop 并且仍然有 1 个延迟周期。(两者仍然为前端花费一个 uop;mov-elimination 只消除了除 ROB 条目之外的延迟和后端成本。)
此外,Skylake 对于某些指令的 XMM 版本具有比 MMX 版本更好的吞吐量。例如paddb/w/d/q mm,mm在 p05paddb/w/d/q xmm,xmm上运行,但在 p015 上运行。许多其他操作,如pavg*,pmadd*和 shifts 可以在 p01 上运行 XMM regs,但只能在端口 0 上运行 MMX regs。( https://agner.org/optimize/ )
因此,与 x87 FPU 一样,它仍然支持遗留代码,但支持它的执行单元较少。它还不是很糟糕,所以像 x264 和 FFmpeg 这样的软件仍然有大量的 MMX 代码,用于在 64 位块中自然工作的东西不会受到太严重的影响。
在许多情况下,128 位 AVX 版本的整数指令可能是避免寄存器复制mov指令的最佳选择。
| 归档时间: |
|
| 查看次数: |
1545 次 |
| 最近记录: |