IT박스

GCC가 결과를 사용하지 않고 libc의 sqrt ()를 호출하는 이유는 무엇입니까?

itboxs 2020. 12. 31. 08:06
반응형

GCC가 결과를 사용하지 않고 libc의 sqrt ()를 호출하는 이유는 무엇입니까?


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    $24, %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    $7, %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    $24, %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 sqrt함수 를 호출합니다 . 그러나 그 xmm0이후와에 대한 두 번째 호출 전에는 절대 저장하지 않고 operator<<스택에서 값을 복원합니다 (를 xmm0처음 호출 할 때 손실 되었기 때문 operator<<).

더 간단한을 사용하면 std::cout << n;훨씬 더 분명합니다.

subq    $24, %rsp
movsd   %xmm1, 8(%rsp)
call    sqrt
movsd   8(%rsp), %xmm1
movl    std::cout, %edi
addq    $24, %rsp
movapd  %xmm1, %xmm0
jmp     std::basic_ostream<char, std::char_traits<char> >& std::basic_ostream<char, std::char_traits<char> >::_M_insert<double>(double)

GCC xmm0가 libc에서 계산 한 값을 사용하지 않는 이유는 무엇 sqrt입니까?


sqrt결과를 계산하기 위해 호출 필요가 없습니다 . 이미 SQRTSD 명령에 의해 계산되었습니다. sqrt음수가 전달 될 때 표준에 따라 필요한 동작을 생성하도록 호출 합니다 sqrt(예 errno: 부동 소수점 예외 설정 및 / 또는 발생). PXOR, UCOMISD 및 JBE 명령어는 인수가 0보다 작은 지 여부를 테스트하고 sqrt이것이 사실이 아닌 경우 호출을 건너 뜁니다 .

참조 URL : https://stackoverflow.com/questions/43303090/why-does-gcc-call-libcs-sqrt-without-using-its-result

반응형