どのようにしてNaNをxmmレジスタに挿入できますか?


9

私が書いている関数では、入力が意味をなさない場合はNanを返したいと思います。

NaNをxmmレジスターに最も簡単な方法で挿入するにはどうすればよいですか?


1
どの「入力が意味をなさない」かをどのように判断しますか?これが比較の結果である場合は、ビット単位で、または比較の結果マスクを使用して「通常の」結果を得ることができます。
1

回答:


13

すべて1は、静かな(非シグナリング、別名通常)NaNです。1を生成する最も簡単な方法は、SSE2 pcmpeqd xmm0,xmm0を使用して、レジスタのすべてのビットを1、つまり2の補数の整数に設定すること-1です。(CPUレジスタのすべてのビットを1に効率的に設定します / オンザフライでベクトル定数を生成するのに最適な命令シーケンスは何ですか?

実際には-NaN-符号ビットが設定されています。整数の右シフト(psrld xmm0,1)を検討するか、それが望ましくない場合はゼロ/ゼロ(xorps xmm0,xmm0/ divpd xmm0,xmm0)で除算してください。


NaNを返したい数学関数は、FPCSRで無効なスティッキー例外ビットが MXCSR に設定さていることを確認することも必要です(または、呼び出し元が例外をマスクしない場合は、実際に例外を発生させます)。これを行うに、NaNを乗算または追加します。例えば

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

またはmulss単精度の場合floatmulpd/ mulpsも適切でしょう。

NaNとNaNの乗算または追加のビットパターンは、間違いなくNaNであり、同じペイロードである必要があるため、すべて1です。

mulsdor addsd(またはdivsd)の結果が戻り値になることには、呼び出し元がそのレジスタをループで繰り返し使用する場合に、ドメイン横断バイパスレイテンシがないという利点もあります。(Sandybridgeファミリでは、これは永遠に続きます。たとえばaddsd xmm1, xmm0、xmm0がから来たpcmpeqd場合、それがずっと前で、整数SIMD uopがすでに廃止されていたとしても、xmm1入力からxmm1出力までのレイテンシの追加サイクルがあります。)


cmpsdor を使用すると、ブランチなしでそれを実行できる場合もあります。結果を0 / -1でマスクして、NaNまたは未変更にすることcmppdができますorps。他の計算でFP-invalidフラグが設定される場合(または既に設定されている場合)、またはそれを気にしない場合は、すべて設定されています。

追加のcmp /またはでクリティカルパスを長くすることに注意してください。それが非常にまれであると予想する場合は、どちらか一方のビットが設定されているかどうかを確認するために、たとえばcmppd結果でmovmskpd/ test eax,eax/を使用jnzして比較して分岐する可能性があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.