如何将NaN插入xmm寄存器?


9

对于我正在编写的函数,如果输入没有意义,我想返回Nan。

如何最简单地将NaN插入xmm寄存器


1
您如何确定哪个“输入没有意义”?如果这是比较的结果,则可以按位进行“或”“正常”结果,并带有比较的结果掩码。
chtz

Answers:


13

All-ones是一个安静的(非信令,又称正常)NaN,这就是您想要的。产生一个的最简单方法是使用SSE2 pcmpeqd xmm0,xmm0将寄存器中的每个位设置为12,即补码整数-1。(将CPU寄存器中的所有位有效设置为1 / 即时生成矢量常量的最佳指令序列是什么?

实际上是-NaN-符号位已设置。如果不希望使用整数右移(psrld xmm0,1)或除以零/零(xorps xmm0,xmm0/ divpd xmm0,xmm0)。


想要返回NaN的数学函数通常还希望确保在MXCSR中设置了FP无效的粘性异常位(或者,如果调用者未屏蔽该异常,则实际上引发异常)。要做到,你可以乘或与自身添加为NaN。例如

    ...
.error_return_path:
    pcmpeqd   xmm0, xmm0
    mulsd     xmm0, xmm0       ; Cause an FP-invalid operation.
    ret

mulss用于单精度floatmulpd/ mulps也将是适当的。

将NaN与NaN相乘或相加的位模式肯定仍然是NaN,并且仍然应该是相同的有效负载,因此仍然是全1。

将返回值作为mulsdaddsd(或divsd)的结果还具有以下优点:如果调用方在循环中重复使用该寄存器,则不会有跨域旁路等待时间。(在Sandybridge系列上,这种情况addsd xmm1, xmm0将永远持续下去。例如pcmpeqd,即使xmm0来自,即使从很早以前开始,并且整数SIMD uop已经退休,从xmm1输入到xmm1输出的每个延迟都会有一个额外的延迟周期。)


如果使用cmpsd或,您甚至可以无分支地进行此操作cmppd:您可以orps将0 / -1掩码转换为结果以使其为NaN或保持不变。如果其他一些计算将(或已经)设置了FP-invalid标志,或者如果您对此不关心,则全部设置完毕。

提防使用额外的cmp延长关键路径/或;如果您认为它非常稀有,则最好还是比较并分支,例如对cmppd结果使用movmskpd/ test eax,eax/ jnz来查看是否设置了任何一位=> SIMD元素之一未通过某些检查。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.