¿Por qué el comstackdor genera sqrts adicionales en el código de ensamblaje comstackdo?

Estoy tratando de perfilar el tiempo que toma computar un sqrt usando el siguiente código C simple, donde readTSC () es una función para leer el contador de ciclos de la CPU.

double sum = 0.0; int i; tm = readTSC(); for ( i = 0; i < n; i++ ) sum += sqrt((double) i); tm = readTSC() - tm; printf("%lld clocks in total\n",tm); printf("%15.6e\n",sum); 

Sin embargo, como imprimí el código de ensamblaje usando

 gcc -S timing.c -o timing.s 

en una máquina Intel, el resultado (que se muestra a continuación) fue sorprendente?

¿Por qué hay dos sqrts en el código de ensamblaje, uno usando la instrucción sqrtsd y el otro usando una llamada de función? ¿Está relacionado con el desenrollado de bucle y el bash de ejecutar dos sqrts en una iteración?

Y como entender la linea.

 ucomisd %xmm0, %xmm0 

¿Por qué compara %xmm0 mismo?

 //----------------start of for loop---------------- call readTSC movq %rax, -32(%rbp) movl $0, -4(%rbp) jmp .L4 .L6: cvtsi2sd -4(%rbp), %xmm1 // 1. use sqrtsd instruction sqrtsd %xmm1, %xmm0 ucomisd %xmm0, %xmm0 jp .L8 je .L5 .L8: movapd %xmm1, %xmm0 // 2. use C funciton call call sqrt .L5: movsd -16(%rbp), %xmm1 addsd %xmm1, %xmm0 movsd %xmm0, -16(%rbp) addl $1, -4(%rbp) .L4: movl -4(%rbp), %eax cmpl -36(%rbp), %eax jl .L6 //----------------end of for loop---------------- call readTSC 

Está usando la función sqrt la biblioteca para el manejo de errores. Consulte la documentación de glibc: 20.5.4 Informe de errores por funciones matemáticas: las funciones matemáticas configuran errno para la compatibilidad con sistemas que no tienen marcas de excepción IEEE754. Relacionados: glibc’s math_error(7) man page.

Como optimización, primero intenta realizar la raíz cuadrada mediante la instrucción sqrtsd línea, luego verifica el resultado contra sí mismo usando la instrucción ucomisd que establece los indicadores de la siguiente manera:

 CASE (RESULT) OF UNORDERED: ZF,PF,CF 111; GREATER_THAN: ZF,PF,CF 000; LESS_THAN: ZF,PF,CF 001; EQUAL: ZF,PF,CF 100; ESAC; 

En particular, la comparación de un QNaN se devolverá a UNORDERED , que es lo que obtendrá si intenta obtener la raíz cuadrada de un número negativo. Esto está cubierto por la twig jp . El chequeo es solo paranoia, verificando la igualdad exacta.


También tenga en cuenta que gcc tiene una -fno-math-errno que sacrificará este manejo de errores por velocidad. Esta opción forma parte de -ffast-math , pero se puede usar por sí sola sin habilitar optimizaciones que cambien los resultados.

sqrtsd solo genera correctamente NaN para entradas negativas y NaN, y establece el indicador IEEE754 Invalid. El cheque y la twig es solo para preservar la semántica de configuración errno la que la mayoría de los códigos no se basan.

-fno-math-errno es el valor predeterminado en Darwin (OS X), donde la biblioteca matemática nunca establece errno , por lo que las funciones pueden integrarse sin esta comprobación.