首页 > 解决方案 > GCC/Clang:禁用单个函数的尾递归优化

问题描述

我知道我可以使用选项禁用 GCC 中的尾递归优化-fno-optimize-sibling-calls。但是,它会禁用整个编译单元的优化。

有没有办法禁用单个功能的优化?

我的理解是我可以更改函数,因此它不是尾递归的有效候选者 - 例如,通过在表达式中使用返回值,因此返回不是函数中的最后一条指令(例如:)return f(n) + 1;

不过,上面的解决方案可能仍然是可优化的,并且编译器的未来(或当前,我不知道)版本可能足够聪明,可以使其成为尾调用 - 比如说,通过更改int f(i) { if(!i) return 0; return f(i - 1) + 1; }int f(i, r = 0) { if(!i) return r; return f(i - 1, r + 1); }

如果可能的话,我正在寻找一种不需要更改算法的更清洁且面向未来的解决方案。

查看文档,我找不到执行此操作的函数属性或内置函数,但我的搜索并不详尽。

标签: c++gccoptimizationclangtail-recursion

解决方案


您可以使用 GCC 特定的#pragma optimize()指令(结合适当的括号和 push/pop#pragma)来实现类似于指定函数属性的结果:

#pragma GCC push_options // Save current options
#pragma GCC optimize ("no-optimize-sibling-calls")
int test(int i)
{
    if (i == 1) return 0;
    return i + test(i - 1);
}
#pragma GCC pop_options  // Restore saved options

int main()
{
    int i = 5;
    int j = test(i);
    return j;
}

但请注意,clang 不支持这种形式的#pragma optimize. 另外,请注意手册中的此警告:

并非每个以属性指定的 -f 前缀开头的优化选项都一定会对函数产生影响。optimize 属性应仅用于调试目的。它不适合生产代码。


推荐阅读