【问题标题】:Optimizing out helper functions优化辅助函数
【发布时间】:2017-09-27 11:53:47
【问题描述】:

这或多或少是要求澄清 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

所以我的问题是:标准中是否有任何内容阻止编译器消除助手?

【问题讨论】:

  • 根据我的经验,编译器在内联函数指针调用方面往往做得很差,即使函数指针的值可以在编译时确定。您可以尝试输入inline 关键字。据我所知,标准中没有任何内容阻止优化。

标签: c callback language-lawyer function-pointers


【解决方案1】:

标准中没有任何内容可以直接阻止这种优化。但在实践中,当编译器没有“全貌”时,它们并不总是可能的。

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

【讨论】:

  • 这也应该通过在编译和“链接”步骤中使用链接时间优化(-flto with GCC)来解决。
  • 我在想可能是因为指针比较的可能性而被禁止。 do_stuff() 可能正在尝试将接收到的指针与 my_callback_function() 进行比较。启用优化后,比较结果会显示为my_callback_function == my_callback_helper,两个不同的对象具有相同的地址可能是不合法的。如果是非法的,那么跳跃无法消除就有点可惜了。也许 fn-cast 最好是实现定义而不是未定义。
猜你喜欢
  • 1970-01-01
  • 2014-01-23
  • 2021-05-24
  • 1970-01-01
  • 1970-01-01
  • 2012-10-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多