2017-09-27 20 views
6

ta jest mniej lub bardziej prośba o wyjaśnienie Casting a function pointer to another type z przykładowym kodemOptymalizacja z funkcji pomocniczych

struct my_struct; 
void my_callback_function(struct my_struct* arg); 
void do_stuff(void (*cb)(void*)); 

static void my_callback_helper(void* pv) 
{ 
    my_callback_function(pv); 
} 
int main() 
{ 
    do_stuff(&my_callback_helper); 
} 

Odpowiedź mówi „dobry” kompilator powinien być w stanie zoptymalizować się funkcję my_callback_helper() ale znalazłem nie kompilator na https://gcc.godbolt.org że robi to i funkcji pomocnika dostaje zawsze generowany nawet jeśli to just a jump to my_callback_function() (-O3):

my_callback_helper: 
     jmp  my_callback_function 
main: 
     subq $8, %rsp 
     movl $my_callback_helper, %edi 
     call do_stuff 
     xorl %eax, %eax 
     addq $8, %rsp 
     ret 

Moje pytanie brzmi: czy w standardzie jest coś, co uniemożliwia kompilatorom eliminowanie pomocnika?

+0

Z mojego doświadczenia wynika, że ​​kompilatory mają tendencję do wykonywania niewystarczającej pracy przy wywoływaniu wywołania funkcji, nawet jeśli wartość wskaźnika funkcji może być określona podczas kompilacji. Możesz spróbować wrzucić słowo kluczowe "inline". O ile mi wiadomo, nie ma nic w standardzie uniemożliwiającego optymalizację. – Lundin

Odpowiedz

3

Nie ma nic w standardzie, który bezpośrednio uniemożliwia tę optymalizację. Ale w praktyce kompilatory nie zawsze są dostępne, gdy nie mają "pełnego obrazu".

Podałeś adres my_callback_helper. Kompilator nie może z łatwością go zoptymalizować, ponieważ nie wie, co robi z nim. W oddzielnym module, w którym zdefiniowano do_stuff, kompilator nie wie, że może po prostu użyć/wywołać my_callback_function w miejsce swojego argumentu (my_callback_helper). Aby całkowicie zoptymalizować my_callback_helper, kompilator musi również wiedzieć, co robi do_stuff. Ale do_stuff jest zewnętrzną funkcją, której definicja nie jest dostępna dla kompilatora. Taka optymalizacja może się zdarzyć, jeśli podasz definicję dla do_stuff i wszystkich jej zastosowań.

+1

Powinno to również zostać usunięte poprzez zastosowanie optymalizacji czasu łącza (-flto z GCC) podczas kompilacji i kroków "link". – dbrank0

+0

Myślę, że być może jest to zabronione z powodu możliwości porównania wskaźnika. 'do_stuff()' może próbować porównać otrzymany wskaźnik z 'my_callback_function()'. Po przeprowadzeniu optymalizacji porównanie powie "moja_składka_funkcji == my_callback_helper" i może nie być legalne, aby dwa różne obiekty miały ten sam adres. Jeśli jest to nielegalne, to trochę niefortunne, skoku nie da się wyeliminować. Może lepiej byłoby, gdyby fn-casts były zdefiniowane w implementacji, a nie niezdefiniowane. – PSkocik

Powiązane problemy