如何将 NaN 插入 xmm 寄存器?
How can you insert a NaN into a xmm register?
对于我正在编写的函数,如果输入没有意义,我想 return 一个 Nan。
如何以最简单的方式将 NaN 插入 xmm 寄存器?
全一是一个安静的(非信号,又名正常)NaN,这就是你想要的。生成一个的最简单方法是使用 SSE2 pcmpeqd xmm0,xmm0
将寄存器中的每一位设置为 1
,即 2 的补码整数 -1
。 ( / )
它实际上是一个 -NaN
- 设置了符号位。如果不需要,请考虑整数右移 (psrld xmm0,1
) 或除以零/零 (xorps xmm0,xmm0
/ divpd xmm0,xmm0
)。
想要 return NaN 的数学函数通常还想确保 MXCSR 中的 FP 无效粘性异常位被设置 (或者实际上引发异常,如果您的来电者揭露了该异常)。要做到 that,您可以将 NaN 与其自身相乘或相加。例如
...
.error_return_path:
pcmpeqd xmm0, xmm0
mulsd xmm0, xmm0 ; Cause an FP-invalid operation.
ret
或mulss
单精度float
。 mulpd
/ mulps
也合适。
NaN 与 NaN 相乘或相加的位模式肯定仍然是 NaN,并且应该仍然是相同的有效负载,所以仍然是全一。
将 return 值作为 mulsd
或 addsd
(或 divsd
)的结果还有一个优点,即如果调用者在循环,它不会有跨域旁路延迟。 (在 Sandybridge 系列上,这会持续到永远。例如,如果 xmm0 来自 pcmpeqd
,每个 addsd xmm1, xmm0
都会有一个额外的从 xmm1 输入到 xmm1 输出的延迟周期,即使那是很久以前的事,而且整数- SIMD uop 已经退役了。)
如果您使用 cmpsd
或 cmppd
,您甚至可以无分支地执行此操作:您可以 orps
将 0 / -1 掩码到结果中以使其成为 NaN 或不变。如果其他一些计算将(或已经)设置 FP-invalid 标志,或者如果您不关心它,那么您已经准备就绪。
注意不要用额外的 cmp / or 来延长关键路径;如果您希望它非常罕见,您可能宁愿比较和分支,例如在 cmppd 结果上使用 movmskpd
/ test eax,eax
/ jnz
查看是否设置了任一位 => 其中一个 SIMD 元素未通过某些检查。
对于我正在编写的函数,如果输入没有意义,我想 return 一个 Nan。
如何以最简单的方式将 NaN 插入 xmm 寄存器?
全一是一个安静的(非信号,又名正常)NaN,这就是你想要的。生成一个的最简单方法是使用 SSE2 pcmpeqd xmm0,xmm0
将寄存器中的每一位设置为 1
,即 2 的补码整数 -1
。 (
它实际上是一个 -NaN
- 设置了符号位。如果不需要,请考虑整数右移 (psrld xmm0,1
) 或除以零/零 (xorps xmm0,xmm0
/ divpd xmm0,xmm0
)。
想要 return NaN 的数学函数通常还想确保 MXCSR 中的 FP 无效粘性异常位被设置 (或者实际上引发异常,如果您的来电者揭露了该异常)。要做到 that,您可以将 NaN 与其自身相乘或相加。例如
...
.error_return_path:
pcmpeqd xmm0, xmm0
mulsd xmm0, xmm0 ; Cause an FP-invalid operation.
ret
或mulss
单精度float
。 mulpd
/ mulps
也合适。
NaN 与 NaN 相乘或相加的位模式肯定仍然是 NaN,并且应该仍然是相同的有效负载,所以仍然是全一。
将 return 值作为 mulsd
或 addsd
(或 divsd
)的结果还有一个优点,即如果调用者在循环,它不会有跨域旁路延迟。 (在 Sandybridge 系列上,这会持续到永远。例如,如果 xmm0 来自 pcmpeqd
,每个 addsd xmm1, xmm0
都会有一个额外的从 xmm1 输入到 xmm1 输出的延迟周期,即使那是很久以前的事,而且整数- SIMD uop 已经退役了。)
如果您使用 cmpsd
或 cmppd
,您甚至可以无分支地执行此操作:您可以 orps
将 0 / -1 掩码到结果中以使其成为 NaN 或不变。如果其他一些计算将(或已经)设置 FP-invalid 标志,或者如果您不关心它,那么您已经准备就绪。
注意不要用额外的 cmp / or 来延长关键路径;如果您希望它非常罕见,您可能宁愿比较和分支,例如在 cmppd 结果上使用 movmskpd
/ test eax,eax
/ jnz
查看是否设置了任一位 => 其中一个 SIMD 元素未通过某些检查。