Компилятор MSVC может использовать (внутренние) функции
___libm_sse2_sincos_ (for x86)
__libm_sse2_sincos_ (for x64)
в оптимизированных сборках, если указаны соответствующие флаги компилятора (как минимум / O2 / arch: SSE2 / fp: fast). Названия этих функций, по-видимому, подразумевают, что они не вычисляют отдельные sin и cos, а оба «за один шаг».
Например:
void sincos(double const x, double & s, double & c)
{
s = std::sin(x);
c = std::cos(x);
}
Сборка (для x86) с / fp: fast:
movsd xmm0, QWORD PTR _x$[esp-4]
call ___libm_sse2_sincos_
mov eax, DWORD PTR _s$[esp-4]
movsd QWORD PTR [eax], xmm0
mov eax, DWORD PTR _c$[esp-4]
shufpd xmm0, xmm0, 1
movsd QWORD PTR [eax], xmm0
ret 0
Сборка (для x86) без / fp: быстрая, но с / fp: точная (вместо этого (по умолчанию)) вызывает отдельный sin и cos:
movsd xmm0, QWORD PTR _x$[esp-4]
call __libm_sse2_sin_precise
mov eax, DWORD PTR _s$[esp-4]
movsd QWORD PTR [eax], xmm0
movsd xmm0, QWORD PTR _x$[esp-4]
call __libm_sse2_cos_precise
mov eax, DWORD PTR _c$[esp-4]
movsd QWORD PTR [eax], xmm0
ret 0
Итак, / fp: fast обязателен для оптимизации sincos.
Но учтите, что
___libm_sse2_sincos_
возможно не так точно, как
__libm_sse2_sin_precise
__libm_sse2_cos_precise
из-за пропущенного «точного» в конце названия.