我发现所有主流的编译器在被调用的函数没有返回值(即标记为_Noreturn / [[noreturn]]或在调用后有__builtin_unreachable())时都不会进行尾调用优化。这是故意的行为,还是错失的优化机会?如果是故意的,请问原因是什么?
#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; }
boost::variant
切换访问代码膨胀的问题,看到了这个问题 https://godbolt.org/z/c__MxS。如果在某处有 noreturn 调用,Clang 会出现问题并在每个分支中都做堆栈调整。https://godbolt.org/z/PR6RMn 如果 GCC 看到abort
命令也会发生同样的情况。 - Nikita Kniazev