This c++ code is
#include<cmath>
double f1(double a){
return std::cos(a);
}
double f2(double a){
return std::cos(a) + std::sin(a);
}
is compiled into the following assembly (https://godbolt.org/z/Y578h1TKx)
f1(double):
jmp cos
f2(double):
sub rsp, 24
lea rdi, [rsp+8]
mov rsi, rsp
call sincos
movsd xmm0, QWORD PTR [rsp+8]
addsd xmm0, QWORD PTR [rsp]
add rsp, 24
ret
Does this mean that gcc knows the glibc's standard functions and have optimization technique for specific cases using them?
When compiling GCC itself, you specify a target triple that includes information about the platform and (maybe indirectly) the C standard library implementation used on the target that the compiled GCC will compile for.
For example x86_64-linux-gnu
or x86_64-unknown-linux-gnu
is a typical target triple for a target that runs Linux on a x86-64 processor with glibc as C standard library implementation.
Similarly x86_64-linux-musl
or x86_64-unknown-linux-musl
would be a similar target that uses the musl C standard library implementation instead.
Additionally there are -m
compiler switches (e.g. -mglibc
, -mmusl
, ...) to change the assumed target C standard library implementation.
In this way, GCC knows whether or not the target supports the non-standard sincos
function and if it does, then it can rewrite calls to std::cos
and std::sin
, which have semantics that are always known because they are specified by the C++ and C standards, to a call to sincos
in the way that you are seeing.
For example if you compile with -muclibc
for a Linux target using the uclibc C standard library implementation, then GCC assumes that sincos
is not present and won't rewrite to sincos
. (Although I think uclibc does actually support sincos.)
With the default configuration (i.e. without any -std=c*
or -ansi
flag) it is ok for the compiler to rewrite to the non-standard sincos
function, even though sincos
is not a name reserved by any standard and could therefore be used for a different purpose by the user, because the default options of GCC assume GNU extensions (i.e. -std=gnu++XX
instead of -std=c++XX
), not strict conformance to the standards.
Unfortunately GCC still performs this transformation even in strict standard conformance mode, where it shouldn't happen. See bug report here.