clang 1.1和1.0(llvm 2.7和2.6)生成的尾部调用
使用clang-O2(或使用)编译下一段代码后: 我认为clang 1.1和1.0(llvm 2.7和2.6)生成的尾部调用,llvm,clang,Llvm,Clang,使用clang-O2(或使用)编译下一段代码后: 我认为tail call意味着丢弃当前堆栈(即返回到上一帧,因此下一条指令应该是ret%5),但根据此代码,它将为其执行mul。在本机程序集中,有简单的调用,没有尾部优化(即使有适当的llc标志) sombody能解释为什么clang会生成这样的代码吗 此外,如果llvm可以简单地检查nextret是否将使用prevcall的结果,然后进行适当的优化或生成本机等效的尾部调用指令,我也无法理解为什么llvm会有tail call。它说: 可选的“t
tail call
意味着丢弃当前堆栈(即返回到上一帧,因此下一条指令应该是ret%5
),但根据此代码,它将为其执行mul
。在本机程序集中,有简单的调用
,没有尾部优化(即使有适当的llc标志)
sombody能解释为什么clang会生成这样的代码吗
此外,如果llvm可以简单地检查nextret
是否将使用prevcall的结果,然后进行适当的优化或生成本机等效的尾部调用指令,我也无法理解为什么llvm会有tail call
。它说:
可选的“tail”标记表示被调用者函数不访问调用者中的任何alloca或varargs。请注意,调用可能被标记为“tail”,即使它们不是在ret指令之前发生的
很可能有一个LLVM优化过程通过Clang分析被调用者是否访问调用者中的任何alloca或vararg。如果没有,pass会将调用标记为tail调用,并让LLVM的另一部分了解如何使用“tail”标记。也许这个函数现在不可能是真正的尾部调用,但经过进一步的转换之后,它可能是。我猜这样做是为了让过程的顺序变得不那么重要。是的,ret
不需要正好在tail call
之后,因为llvm可能会决定对指令重新排序。隐马尔可夫模型。。。对于Clang来说,在不检查依赖项的情况下放置tail
可能是明智的。让llvm检查它。
#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])));
}
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