Jak wstawić NaN do rejestru xmm?

9

Dla funkcji, którą piszę, chciałbym zwrócić Nan, jeśli dane wejściowe nie mają sensu.

Jak w najprostszy sposób mogę wstawić NaN do rejestru xmm ?

Markus
źródło
1
Jak określić, które „wejście nie ma sensu”? Jeśli jest to wynik porównania, możesz po prostu bitowo lub swój „normalny” wynik za pomocą maski wyniku porównania.
chtz

Odpowiedzi:

13

Wszyscy to cichy (bez sygnalizacji, aka normalny) NaN, który jest tym, czego chcesz. Najłatwiejszym sposobem na wyprodukowanie takiego jest SSE2, pcmpeqd xmm0,xmm0aby ustawić każdy bit w rejestrze na 1, tj. Liczbę całkowitą dopełniającą 2 -1. ( Ustaw efektywnie wszystkie bity rejestru procesora na 1 / Jakie są najlepsze sekwencje instrukcji do generowania stałych wektorowych w locie? )

W rzeczywistości jest to -NaN- bit znaku jest ustawiony. Rozważ liczbę całkowitą w prawo shift ( psrld xmm0,1) lub podziel przez zero / zero ( xorps xmm0,xmm0/ divpd xmm0,xmm0), jeśli jest to niepożądane.


Funkcje matematyczne, które chcą zwrócić NaN, często chcą również upewnić się, że bit wyjątku lepkiego FP-nieprawidłowy zostanie ustawiony w MXCSR (lub faktycznie zgłosi wyjątek, jeśli osoba dzwoniąca zdemaskowała ten wyjątek). Aby to zrobić , że można mnożyć lub dodać NaN ze sobą. na przykład

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

Lub mulssdla pojedynczej precyzji float. mulpd/ mulpsbyłoby również odpowiednie.

Wzorzec bitowy dla zwielokrotnienia lub dodania NaN z NaN jest zdecydowanie nadal NaN i powinien nadal mieć ten sam ładunek, więc nadal wszystkie.

Posiadanie wartości zwracanej w wyniku mulsdlub addsd(lub divsd) ma również tę zaletę, że jeśli osoba wywołująca używa tego rejestru wielokrotnie w pętli, nie będzie mieć opóźnienia w obejściu domeny. (W przypadku rodziny Sandybridge trwa to wiecznie. Np. Każdy addsd xmm1, xmm0miałby dodatkowy cykl opóźnienia od wejścia xmm1 do wyjścia xmm1, gdyby xmm0 pochodziło pcmpeqd, nawet jeśli to było dawno temu, a uop liczby całkowitej-SIMD już wycofał się.)


Możesz nawet być w stanie zrobić to bez rozgałęzień, jeśli użyjesz cmpsdlub cmppd: możesz orpszamaskować maskę 0 / -1 w wyniku, aby ustawić NaN lub bez zmian. Jeśli jakieś inne obliczenia ustawią (lub już ustawią) flagę nieważności FP, lub jeśli nie przejmujesz się tym, wszystko jest ustawione.

Uważaj na wydłużenie ścieżki krytycznej o dodatkowe cmp / lub; jeśli spodziewasz się, że jest to bardzo rzadkie, możesz raczej porównać i rozgałęzić, np. z movmskpd/ test eax,eax/ jnzna wyniku cmppd, aby sprawdzić, czy któryś bit został ustawiony => jeden z elementów SIMD nie sprawdził się.

Peter Cordes
źródło