是否有可能在GCC / Clang上强制进行尾调用优化?

时间:2011-01-24 17:32:27

标签: c clang tail-call-optimization

我正在尝试尽可能用C编写功能样式的程序。 我知道像GCC / Clang这样的优秀编译器可以默默地进行尾部调用优化,但是不能保证。是否有任何选项可以强制编译器进行尾调用优化? (当然只有在它自己结束时才被调用)

7 个答案:

答案 0 :(得分:6)

Clang根本没有做任何优化。有一个LLVM传递tailcallelim可以做你想要的(但不保证)。您可以使用opt单独运行。

答案 1 :(得分:3)

Clang 13“musttail”属性强制尾递归函数中的尾调用优化,即使优化被禁用。

https://clang.llvm.org/docs/AttributeReference.html#musttail

用法:

int f(int x) {
  ...
  __attribute__((musttail)) return f(x-1);
}

答案 2 :(得分:1)

一个元回答:

从函数式语言中接收C语言有一些教训是有用的:使用小函数,使用不会改变全局或输入参数的函数,不要害怕函数指针。但是,你可以合理地做到这一点是有限制的,并且依赖于尾部呼叫消除('尾部呼叫优化'并不是真正的权利术语)可能超出了有用的范围。你不能强迫编译器使用这个策略,即使你可以,生成的C也会非常单一,而且很难为其他人阅读,包括你未来的自我。

使用语言来发挥自己的优势。对于某些事情,C 是好的,所以要用它们做好C风格。如果您想要不同的优势,或者想要使用功能样式(出色的决定!),请使用函数式语言。

答案 3 :(得分:1)

我认为并不能真正实现,但是使用-foptimize-sibling-calls时可以使用gcc。如果您使用-O2-O3-Os,则会自动启用该功能。

答案 4 :(得分:1)

Alpha 和 i386 的 GCC 扩展在:

Proper Tail Recursion in C (Diploma Thesis) by Mark Probst,2001 年。

答案 5 :(得分:0)

实际上很多C编译器已经为你处理了这个问题。正如eq所提到的,你可以让编译器处理大部分这些事情,而不是试图创建在其他地方不起作用的优化。通常情况下,即使您设置了优化标记,也确实没有性能差异。

答案 6 :(得分:0)

如果它确实是一个尾调用,那么while循环或goto看起来与递归调用看起来不同。只需更新所有变量,而不是将它们作为参数传递。 AFAIK这是C中唯一能够在所有优化级别控制堆栈使用的跨平台方式。它实际上可以更具可读性,因为你有一个函数初始化后跟循环,这是非常惯用的。尾递归版需要两个函数,一个用于初始化,另一个用于递归部分。