Come puoi inserire un NaN in un registro xmm?


9

Per la funzione che sto scrivendo vorrei restituire un Nan se l'input non ha senso.

Come posso inserire un NaN in un registro xmm nel modo più semplice?


1
Come si determina quale "input non ha senso"? Se questo è il risultato di un confronto, puoi semplicemente bit a bit o il tuo risultato "normale" con la maschera del risultato del confronto.
CHTZ

Risposte:


13

All-one è un NaN silenzioso (non segnalatore, anche normale), che è quello che vuoi. Il modo più semplice per produrne uno è con SSE2 pcmpeqd xmm0,xmm0su cui impostare ogni bit nel registro 1, ovvero il numero intero del complemento di 2 -1. ( Impostare tutti i bit nel registro CPU su 1 in modo efficiente / Quali sono le migliori sequenze di istruzioni per generare al volo costanti vettoriali? )

In realtà è un -NaN- il bit di segno è impostato. Considera lo spostamento a destra intero ( psrld xmm0,1) o dividi per zero / zero ( xorps xmm0,xmm0/ divpd xmm0,xmm0) se ciò è indesiderabile.


Le funzioni matematiche che vogliono restituire NaN spesso vogliono anche assicurarsi che il bit di eccezione appiccicoso non valido FP sia impostato in MXCSR (o effettivamente sollevare un'eccezione se il chiamante ha smascherato tale eccezione). Per fare ciò , puoi moltiplicare o aggiungere la NaN con se stessa. per esempio

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

O mulssper precisione singola float. mulpd/ mulpssarebbe anche appropriato.

Il bit-pattern per moltiplicare o aggiungere NaN con NaN è sicuramente ancora un NaN e dovrebbe essere sempre lo stesso payload, quindi ancora tutti.

Avere il valore restituito come risultato di mulsdo addsd(o divsd) ha anche il vantaggio che se il chiamante utilizza quel registro ripetutamente in un ciclo, non avrà latenza di bypass di attraversamento del dominio. (Sulla famiglia Sandybridge, questo dura per sempre. Ad esempio, ognuno addsd xmm1, xmm0avrebbe un ulteriore ciclo di latenza dall'input xmm1 all'output xmm1 se xmm0 provenisse pcmpeqd, anche se quello era tanto tempo fa e il numero intero SIMD uop si è già ritirato.)


Potresti anche essere in grado di farlo senza rami se usi cmpsdo cmppd: puoi orpsquella maschera 0 / -1 in un risultato per renderlo NaN o invariato. Se qualche altro calcolo (o avrà già) impostato il flag FP non valido, o se non ti interessa, sei pronto.

Attenzione ad allungare il percorso critico con cmp / / extra; se ti aspetti che sia super raro, potresti preferire comunque confrontare e ramificare, ad esempio con movmskpd/ test eax,eax/ jnzsu un risultato cmppd per vedere se uno dei bit è stato impostato => uno degli elementi SIMD ha fallito un controllo.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.