为什么 noreturn/__builtin_unreachable 会阻止尾部调用优化
Why noreturn/__builtin_unreachable prevents tail call optimization
事实上,如果被调用的函数没有返回(即标记为_Noreturn
/[[noreturn]]
或调用后有__builtin_unreachable()
(,所有主要的编译器都不会进行尾部调用优化(。这是预期的行为,而不是错过的优化吗?如果是,为什么?
示例 1:
#ifndef __cplusplus
#define NORETURN _Noreturn
#else
#define NORETURN [[noreturn]]
#endif
void canret(void);
NORETURN void noret(void);
void foo(void) { canret(); }
void bar(void) { noret(); }
C: https://godbolt.org/z/pJfEe-C++:https://godbolt.org/z/-4c78K
示例 2:
#ifdef _MSC_VER
#define UNREACHABLE __assume(0)
#else
#define UNREACHABLE __builtin_unreachable()
#endif
void f(void);
void foo(void) { f(); }
void bar(void) { f(); UNREACHABLE; }
https://godbolt.org/z/PFhWKR
这是故意的,尽管可能会引起争议,因为它会严重损害堆栈使用属性; 出于这个原因,我甚至欺骗编译器认为无法返回的函数可以。原因是许多noreturn函数abort
类似(甚至调用abort
(,并且很可能是运行调试器的人希望能够看到调用发生的位置 - 这些信息将被尾部调用丢失。
引文:
- https://gcc.gnu.org/bugzilla/show_bug.cgi?id=10837
- https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56165
- https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67327
- 等。
相关文章:
- 什么时候调用组成单元对象的析构函数
- 对RValue对象调用的LValue ref限定成员函数
- 为什么使用 "this" 指针调用派生成员函数?
- 函数调用中参数的顺序重要吗
- OpenGL - 在抛出"__gnu_cxx::recursive_init_error"实例后终止调用?
- 基于另一个成员参数将函数调用从类传递给它的一个成员
- 为什么我的C#代码在调用回C++COM直到Task时会暂停.等待/线程.加入
- 在c++类上调用void函数
- 为什么 std::unique 不调用 std::sort?
- 调用专用模板时出错"no matching function for call to [...]"
- 选择要调用的构造函数
- 将尾部调用void(i32,..)位转换为llvm::函数以获取FnAttribute
- 如何应用尾部调用优化
- 尾部调用优化是否适用于此功能?
- 如何防止递归功能调用(尾部回复)堆积在堆栈中
- 为什么 noreturn/__builtin_unreachable 会阻止尾部调用优化
- 尾部调用优化似乎略微降低了性能
- 这可以优化尾部调用吗?如果是这样,它没有发生的特殊原因是什么?
- 局部变量和尾部调用优化
- 引用传递阻碍了gcc消除尾部调用