编译后,使用clang-o2(或
online demo
):
#include <stdio.h>
#include <stdlib.h>
int flop(int x);
int flip(int x) {
if (x == 0) return 1;
return (x+1)*flop(x-1);
}
int flop(int x) {
if (x == 0) return 1;
return (x+0)*flip(x-1);
}
int main(int argc, char **argv) {
printf("%d\n", flip(atoi(argv[1])));
}
我要把LLVM程序集的下一个片段
flip
:
bb1.i: ; preds = %bb1
%4 = add nsw i32 %x, -2 ; <i32> [#uses=1]
%5 = tail call i32 @flip(i32 %4) nounwind ; <i32> [#uses=1]
%6 = mul nsw i32 %5, %2 ; <i32> [#uses=1]
br label %flop.exit
我想
tail call
表示丢弃当前堆栈(即返回到上一帧,因此下一条指令应为
ret %5
,但是根据这个代码
mul
为了它。在本机程序集中
call
不进行尾部优化(即使有适当的有限责任公司标志)
Sombody能解释为什么clang会生成这样的代码吗?
我也不明白为什么LLVM
尾部调用
如果它能简单地检查下一个
ret
将使用上一个的结果
呼叫
稍后,是否进行适当的优化或生成本地等价的尾调用指令?