我有一个需要尽可能快的函数,它只使用整数运算。它运行在AMD64架构上,我需要做一些推/弹,以便有足够的寄存器来使用。现在我想知道,x64 ABI声明前四个浮点寄存器(XMM0,XMM1,XMM2和XMM3)是易失性的,不需要在函数调用中保留。
所以我想我可以通过movq(MMX或SSE指令集)存储我需要保存在这些寄存器的低64位(即MM0,MM1,...)中的64位寄存器,而不是使用堆栈,节省一些内存加载/存储。此外,我不需要使用EMMS来存储FPU状态 - 这会破坏目的 - 因为我实际上并没有操纵浮点寄存器而只是使用它们作为存储(而且无论如何,x87单元根本不使用x64,因为它基本上被SSE取代)
我已完成修改并且它有效(没有崩溃,并且可观察到性能提高了4%),但我想知道,这个“黑客”真的有用吗?还是会引入我可能错过的任何特殊副作用(像FPU状态腐败,即使我不使用它,那种事情)。加载/存储到FPU寄存器总是比任何当前架构上的内存加载/存储更快?
而且,是的,这种优化需要 。公平地说,这不会严重降低代码维护成本,单行评论就足以解释这个伎俩。因此,如果我可以免费获得每个字节少的时钟而不会产生意想不到的后果,我很乐意接受它们:)
感谢。
答案 0 :(得分:3)
只有在MMX操作后清除状态才需要EMMS指令。 SSE指令不要求它。所以这肯定不会发生冲突。
当然,您应该记住,不同的编译器和操作系统使用不同的调用约定,有些可能会以不同的方式处理这四个寄存器。
但是,只要记住这一点,我就不会发现这种方法存在问题。您根据ABI按照他们应该使用的方式使用所有寄存器。
假设这是用汇编语言编写的,那么就没有必要考虑这是否会妨碍编译器优化(一个潜入ASM并开始讨论特定寄存器的C / C ++函数会使编译器更加困难)优化代码)