6

我有一个需要尽可能快的函数,它只使用整数运算。它在 AMD64 架构上运行,我需要做一些推送/弹出操作才能有足够的寄存器来使用。现在我想知道,x64 ABI 声明前四个浮点寄存器(XMM0、XMM1、XMM2 和 XMM3)是易失性的,不需要在函数调用中保留。

所以我想我可以通过 movq(MMX 或 SSE 指令集)而不是使用堆栈来存储我需要保存在这些寄存器的低 64 位(即 MM0、MM1、...)中的 64 位寄存器,从而节省了自己一些内存加载/存储。此外,我不需要使用 EMMS 存储 FPU 状态——这会破坏目的——因为我实际上并没有操作浮点寄存器,而只是将它们用作存储(而且无论如何,x87 单元在x64,因为它基本上被 SSE 取代)

我已经完成了修改并且它可以工作(没有崩溃,并且性能显着提高了 4%),但我想知道,这个“hack”是否真的有效,或者它会引入我可能错过的任何特定副作用(比如 FPU 状态腐败,即使我不使用它,那种东西)。在任何当前架构上,加载/存储到 FPU 寄存器总是比内存加载/存储快吗?

而且,是的,确实需要这种优化。公平地说,这不会严重降低代码维护成本,一行注释就足以解释这个技巧。因此,如果我可以免费获得每个字节少几个时钟而不会产生意外后果,我会很乐意接受它们 :)

谢谢。

4

1 回答 1

3

EMMS 指令只需要在 MMX 操作后清除状态。SSE 指令不需要它。所以肯定不会冲突。

当然,您应该记住,不同的编译器和操作系统使用不同的调用约定,有些可能会以不同的方式处理这四个寄存器。

但是,只要牢记这一点,我认为这种方法没有问题。您正在按照 ABI 应该使用的方式使用所有寄存器。

并且假设这是用汇编编写的,则无需考虑这是否会妨碍编译器优化(深入到 ASM 并开始讨论特定寄存器的 C/C++ 函数使编译器更难优化代码)

于 2012-07-14T16:00:50.023 回答