Oto mój kod:Dlaczego GCC implementuje isnan() bardziej wydajnie dla C++ <cmath> niż C <math.h>?
int f(double x)
{
return isnan(x);
}
Gdybym #include <cmath>
otrzymuję ten montaż:
xorl %eax, %eax
ucomisd %xmm0, %xmm0
setp %al
to rozsądnie mądry: ucomisd ustawia flagę parzystości jeśli porównanie xz sobie jest nieuporządkowane, Znaczenie X to NAN. Następnie setp kopiuje flagę parzystości do wyniku (tylko jeden bajt, stąd początkowe usunięcie z %eax
).
ale gdybym #include <math.h>
otrzymuję ten montaż:
jmp __isnan
Teraz kod nie jest inline, a funkcja __isnan
pewnością nie szybciej INSTRUKCJA ucomisd
, więc ponieśli skok do żadnych korzyści. Mam to samo, gdybym skompilować kod jako C.
Teraz jeśli zmienię wywołanie isnan()
do __builtin_isnan()
, mam prostą instrukcję ucomisd
instrukcji niezależnie od nagłówka I to, i to działa w C też. Podobnie jak ja po prostu return x != x
.
Moje pytanie brzmi: dlaczego nagłówek C <math.h>
zapewnia mniej wydajną implementację isnan()
niż nagłówek C++ <cmath>
? Czy ludzie naprawdę powinni używać __builtin_isnan()
, a jeśli tak, dlaczego? Przetestowałem GCC 4.7.2 i 4.9.0 na x86-64 z -O2
i -O3
.
Oto moja spekulacja: pre c99, nie ma funkcji inline w c. brak funkcji inline oznacza, że funkcje muszą być wywoływane przez jmp/call (lub jakiś rodzaj rozgałęzień). __builtin_isnan nie jest częścią c. to prawdopodobnie specyficzna platforma wewnętrzna. – thang
Ale z pewnością nagłówek systemowy, taki jak ' ', może korzystać z wbudowanych funkcji platformy. –
Jestem prawie pewny, że 'isnan' użyje' __builtin_isnan' jeśli to możliwe. Nie widzę powodu, dla którego musiałbyś zadzwonić ręcznie. – Rapptz