¿Cómo se puede insertar un NaN en un registro xmm?


9

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?


1
¿Cómo se determina qué "entrada no tiene sentido"? Si este es el resultado de una comparación, puede simplemente bit a bit o su resultado "normal" con la máscara de resultados de la comparación.
chtz

Respuestas:


13

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,xmm0para 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 mulsspara precisión simple float. mulpd/ mulpstambié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 mulsdo 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, xmm0tendrí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 cmpsdo cmppd: puede orpsconvertir 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/ jnzen un resultado cmppd para ver si alguno de los bits se configuró => uno de los elementos SIMD falló alguna comprobación.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.