Почему GCC вызывает sqrt () libc без использования его результата?
используя GCC 6.3, следующий код C++:
#include <cmath>
#include <iostream>
void norm(double r, double i)
{
double n = std::sqrt(r * r + i * i);
std::cout << "norm = " << n;
}
создает следующую сборку x86-64:
norm(double, double):
mulsd %xmm1, %xmm1
subq , %rsp
mulsd %xmm0, %xmm0
addsd %xmm1, %xmm0
pxor %xmm1, %xmm1
ucomisd %xmm0, %xmm1
sqrtsd %xmm0, %xmm2
movsd %xmm2, 8(%rsp)
jbe .L2
call sqrt
.L2:
movl std::cout, %edi
movl , %edx
movl $.LC1, %esi
call std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)
movsd 8(%rsp), %xmm0
movl std::cout, %edi
addq , %rsp
jmp std::basic_ostream<char, std::char_traits<char> >& std::basic_ostream<char, std::char_traits<char> >::_M_insert<double>(double)
для вызова std::sqrt
, GCC сначала делает это с помощью sqrtsd
и сохраняет результат в стек. Если он переполняется, он затем вызывает libc
1 ответ:
ему не нужно звонить
sqrt
для вычисления результата; он уже был вычислен инструкцией SQRTSD. Он зоветsqrt
чтобы создать требуемое поведение в соответствии со стандартом, когда отрицательное число передается вsqrt
(например, seterrno
и/или поднять исключение с плавающей точкой). Инструкции PXOR, UCOMISD и JBE проверяют, является ли аргумент меньше 0, и пропускают вызовsqrt
Если это не так.