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?
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?
Risposte:
All-one è un NaN silenzioso (non segnalatore, anche normale), che è quello che vuoi. Il modo più semplice per produrne uno è con SSE2 pcmpeqd xmm0,xmm0
su 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 mulss
per precisione singola float
. mulpd
/ mulps
sarebbe 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 mulsd
o 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, xmm0
avrebbe 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 cmpsd
o cmppd
: puoi orps
quella 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
/ jnz
su un risultato cmppd per vedere se uno dei bit è stato impostato => uno degli elementi SIMD ha fallito un controllo.