为什么 noreturn/__builtin_unreachable 会阻止尾部调用优化

Why noreturn/__builtin_unreachable prevents tail call optimization

本文关键字:尾部 调用 优化 unreachable noreturn builtin 为什么      更新时间:2023-10-16

事实上,如果被调用的函数没有返回(即标记为_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
  • 等。