2017-09-27 142 views
6

这或多或少澄清 Casting a function pointer to another type与示例代码的请求优化了辅助功能

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); 
} 

回答说,“好”的编译器应该能够优化出 的my_callback_helper()功能,但我发现没有编译器在https://gcc.godbolt.org ,做它和辅助功能被一直产生,即使它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 

所以我的问题是:标准中有什么能够防止编译器消除帮助者?

+0

以我的经验,编译器倾向于在即使在编译时确定的函数指针的值内联函数指针调用做的不好。你可以试着折腾'inline'关键字。据我所知,标准中没有任何内容阻止优化。 – Lundin

回答

3

标准中没有任何东西可以直接阻止这种优化。但在实践中,编译器并不总是可能的,因为他们没有“全貌”。

您已经采取的my_callback_helper地址。所以编译器不能轻易优化它,因为它不知道do_stuff如何处理它。在定义了do_stuff的单独模块中,编译器不知道它可以简单地使用/调用my_callback_function来代替它的参数(my_callback_helper)。为了完全优化出my_callback_helper,编译器必须知道do_stuff的功能。但是do_stuff是一个外部函数,其定义不适用于编译器。因此,如果您提供do_stuff及其所有用途的定义,则可能会发生此类优化。

+1

这也应该在编译和“链接”步骤中使用链接时间优化(-flto和GCC)来重新使用。 – dbrank0

+0

我想也许这是禁止的,因为可能性指针比较。 'do_stuff()'可能试图将接收到的指针与'my_callback_function()'进行比较。通过优化,比较将会说'my_callback_function == my_callback_helper',并且两个不同的对象具有相同的地址可能是不合法的。如果它是非法的,那么它有点不幸跳跃不能被消除。也许这对于fn-casts来说更好是实现定义的而不是未定义的。 – PSkocik