Вот простой код C:
#include <math.h>
float f( float x ) { return sqrtf( x ); }
GCC 7.3 и 8.2 (amd64, ubuntu 18.04) генерирует очень странный код:
f:
pxor xmm2,xmm2
sqrtss xmm1,xmm0
ucomiss xmm2,xmm0
ja .L8 ; 0 < x? then, jump to .L8.
movaps xmm0,xmm1
ret
.L8:
sub rsp,24
movss [rsp+12],xmm1 ; save sqrtss result.
call sqrtf
movss xmm1,[rsp+12] ; restore sqrtss result.
add rsp,24
movaps xmm0,xmm1
ret
Такое поведение я вижу на GCC 7.3 8.2 из репозиториев ubuntu-18.04 и также на MinGW-w64. Я не смог найти эту ошибку в GCC Bugzilla (и не могу сообщить о ней).
Есть мысли?
GCC генерирует строго совместимые вычисления математических операций с плавающей точкой с кодом, который Вы скомпилировали (я подозреваю с-O2 или-O3). Я предполагаю, что Вы ожидали, что это скомпилирует его вниз во что-то как следующее (в газовом ассемблере формата):
f:
.LFB9:
.cfi_startproc
sqrtss %xmm0, %xmm0
ret
.cfi_endproc
.LFE9:
Необходимо отключить строгие математические правила соответствия при помощи -ffast-math
сгенерировать быстрее "оптимизированный" код. Обратите внимание, что эта опция включает
-fno-math-errno
-funsafe-math-optimizations
-ffinite-math-only
-fno-rounding-math
-fno-signaling-nans
-fcx-limited-range
-fexcess-precision=fast
Опции GCC, поэтому остерегайтесь потери точности и потери математических ошибок.