【问题标题】:GCC/Clang: disable tail recursion optimization for single functionGCC/Clang:禁用单个函数的尾递归优化
【发布时间】:2021-11-18 12:18:37
【问题描述】:

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

有没有办法禁用单个函数的优化?

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

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

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

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

【问题讨论】:

  • "... 它禁用整个编译单元的优化.." 将函数移动到它自己的文件中。
  • 如果函数不是内联函数或模板,这将起作用。
  • 你为什么想要那个?
  • 好奇心。为什么?禁用它有什么好处?
  • 假设我有充分的理由。我不想让谈话偏离想要它的理由是否合法。如果您要寻找的只是解决方案的约束,假设我需要为每个函数调用提供独立的堆栈框架。

标签: c++ gcc optimization clang tail-recursion


【解决方案1】:

__attribute__((__optimize__("no-optimize-sibling-calls"))) 似乎适用于 GCC。

Clang 给出warning: unknown attribute '__optimize__' ignored

【讨论】:

    【解决方案2】:

    您也许可以使用 GCC 特定的 #pragma optimize() 指令 (combined with suitable bracketing with push/pop #pragma lines) 来实现类似于指定函数属性的结果:

    #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。另外,请注意此警告from the manual

    并非每个以指定 -f 前缀开头的优化选项 由属性必然对功能产生影响。这 optimize 属性应仅用于调试目的。它是 不适合生产代码。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-03-31
      • 2018-03-08
      • 2010-10-20
      • 1970-01-01
      • 1970-01-01
      • 2014-06-23
      • 2017-05-23
      相关资源
      最近更新 更多