Para la función que estoy escribiendo, me gustaría devolver un Nan si la entrada no tiene sentido.
¿Cómo puedo insertar un NaN en un registro xmm de la manera más fácil?
Para la función que estoy escribiendo, me gustaría devolver un Nan si la entrada no tiene sentido.
¿Cómo puedo insertar un NaN en un registro xmm de la manera más fácil?
Respuestas:
All-ones es un NaN silencioso (sin señalización, también conocido como normal), que es lo que quieres. La forma más fácil de producir uno es con SSE2 pcmpeqd xmm0,xmm0
para establecer cada bit en el registro 1
, es decir, el número entero del complemento 2 -1
. ( Establezca todos los bits en el registro de la CPU en 1 de manera eficiente / ¿Cuáles son las mejores secuencias de instrucciones para generar constantes vectoriales sobre la marcha? )
En realidad es un -NaN
- el bit de signo está establecido. Considere el desplazamiento a la derecha de enteros ( psrld xmm0,1
) o divida por cero / cero ( xorps xmm0,xmm0
/ divpd xmm0,xmm0
) si eso no es deseable.
Las funciones matemáticas que desean devolver NaN a menudo también quieren asegurarse de que el bit de excepción permanente no válido FP se establezca en MXCSR (o en realidad generar una excepción si su interlocutor desenmascara esa excepción). Para hacer eso , puede multiplicar o agregar el NaN consigo mismo. p.ej
...
.error_return_path:
pcmpeqd xmm0, xmm0
mulsd xmm0, xmm0 ; Cause an FP-invalid operation.
ret
O mulss
para precisión simple float
. mulpd
/ mulps
también sería apropiado.
El patrón de bits para multiplicar o agregar NaN con NaN definitivamente sigue siendo un NaN, y aún debe ser la misma carga útil, por lo que sigue siendo todos.
Tener el valor de retorno como resultado de mulsd
o addsd
(o divsd
) también tiene la ventaja de que si la persona que llama usa ese registro repetidamente en un bucle, no tendrá latencia de derivación de cruce de dominio. (En la familia Sandybridge, esto dura para siempre. Por ejemplo, todos addsd xmm1, xmm0
tendrían un ciclo adicional de latencia desde la entrada xmm1 hasta la salida xmm1 si viniera xmm0 pcmpeqd
, incluso si eso fue hace mucho tiempo y el UOP entero-SIMD ya se ha retirado).
Incluso podría hacerlo sin ramificaciones si usa cmpsd
o cmppd
: puede orps
convertir esa máscara 0 / -1 en un resultado para que sea NaN o sin cambios. Si algún otro cálculo establecerá (o ya habrá) establecido el indicador FP-inválido, o si no le importa, ya está todo listo.
Tenga cuidado de alargar la ruta crítica con cmp adicional o; si espera que sea súper raro, podría comparar y ramificar, por ejemplo, con movmskpd
/ test eax,eax
/ jnz
en un resultado cmppd para ver si alguno de los bits se configuró => uno de los elementos SIMD falló alguna comprobación.