我正在嘗試使用以下簡單的C代碼來描述計算sqrt所花費的時間,其中readTSC()是讀取CPU循環計數器的函數。爲什麼編譯器會在編譯的彙編代碼中生成額外的sqrts
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);
然而,正如我打印出一個Intel機器上使用
gcc -S timing.c -o timing.s
彙編代碼,結果(如下所示)是令人驚訝的?
爲什麼在彙編代碼中有兩個sqrts,一個使用sqrtsd
指令,另一個使用函數調用?它是否與循環展開並試圖在一次迭代中執行兩個sqrt相關?
以及如何理解行
ucomisd %xmm0, %xmm0
爲什麼它比較%xmm0
本身?
//----------------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
這必須是未優化的代碼。 [真正的代碼](http://goo.gl/CewylI)正確地設置了分支(在非NaN情況下沒有采用分支),並且遺漏了'je',因爲它在ucomisd後總是成立'。 –