Почему 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 54

1 ответ:

ему не нужно звонить sqrt для вычисления результата; он уже был вычислен инструкцией SQRTSD. Он зовет sqrt чтобы создать требуемое поведение в соответствии со стандартом, когда отрицательное число передается в sqrt (например, set errno и/или поднять исключение с плавающей точкой). Инструкции PXOR, UCOMISD и JBE проверяют, является ли аргумент меньше 0, и пропускают вызов sqrt Если это не так.