Pertimbangkan loop sederhana ini:
float f(float x[]) {
float p = 1.0;
for (int i = 0; i < 959; i++)
p += 1;
return p;
}
Jika Anda mengompilasi dengan gcc 7 (snapshot) atau dentang (trunk) dengan -march=core-avx2 -Ofast
Anda mendapatkan sesuatu yang sangat mirip.
.LCPI0_0:
.long 1148190720 # float 960
f: # @f
vmovss xmm0, dword ptr [rip + .LCPI0_0] # xmm0 = mem[0],zero,zero,zero
ret
Dengan kata lain itu hanya mengatur jawaban ke 960 tanpa perulangan.
Namun, jika Anda mengubah kode menjadi:
float f(float x[]) {
float p = 1.0;
for (int i = 0; i < 960; i++)
p += 1;
return p;
}
Perakitan yang dihasilkan benar-benar melakukan jumlah loop? Misalnya dentang memberi:
.LCPI0_0:
.long 1065353216 # float 1
.LCPI0_1:
.long 1086324736 # float 6
f: # @f
vmovss xmm0, dword ptr [rip + .LCPI0_0] # xmm0 = mem[0],zero,zero,zero
vxorps ymm1, ymm1, ymm1
mov eax, 960
vbroadcastss ymm2, dword ptr [rip + .LCPI0_1]
vxorps ymm3, ymm3, ymm3
vxorps ymm4, ymm4, ymm4
.LBB0_1: # =>This Inner Loop Header: Depth=1
vaddps ymm0, ymm0, ymm2
vaddps ymm1, ymm1, ymm2
vaddps ymm3, ymm3, ymm2
vaddps ymm4, ymm4, ymm2
add eax, -192
jne .LBB0_1
vaddps ymm0, ymm1, ymm0
vaddps ymm0, ymm3, ymm0
vaddps ymm0, ymm4, ymm0
vextractf128 xmm1, ymm0, 1
vaddps ymm0, ymm0, ymm1
vpermilpd xmm1, xmm0, 1 # xmm1 = xmm0[1,0]
vaddps ymm0, ymm0, ymm1
vhaddps ymm0, ymm0, ymm0
vzeroupper
ret
Mengapa ini dan mengapa persis sama untuk dentang dan gcc?
Batas untuk loop yang sama jika Anda ganti float
dengan double
adalah 479. Ini sama untuk gcc dan berdering lagi.
Perbarui 1
Ternyata gcc 7 (snapshot) dan dentang (trunk) berperilaku sangat berbeda. dentang mengoptimalkan loop untuk semua batas kurang dari 960 sejauh yang saya tahu. gcc di sisi lain sensitif terhadap nilai yang tepat dan tidak memiliki batas atas. Misalnya ia tidak mengoptimalkan loop ketika batasnya adalah 200 (dan juga banyak nilai lainnya) tetapi ia melakukannya ketika batasnya adalah 202 dan 20002 (serta banyak nilai lainnya).