特别是如果我有以下代码:
func sum(n: Int,acc: Int) -> Int {
if n == 0 { return acc }
else { return sum(n - 1,acc + n) }
}
将Swift编译器优化到一个循环?在下面更有趣的情况下是这样吗?
func isOdd(n: Int) -> Bool {
if n == 0 { return false; }
else { return isEven(n - 1) }
}
func isEven(n: Int) -> Bool {
if n == 0 { return true }
else { return isOdd(n - 1) }
}
最好的检查方法是检查编译器生成的汇编语言代码。我把上面的代码和编译它:
swift -O3 -S tco.swift >tco.asm
输出的相关部分
.globl __TF3tco3sumFTSiSi_Si
.align 4,0x90
__TF3tco3sumFTSiSi_Si:
pushq %rbp
movq %rsp,%rbp
testq %rdi,%rdi
je LBB0_4
.align 4,0x90
LBB0_1:
movq %rdi,%rax
decq %rax
jo LBB0_5
addq %rdi,%rsi
jo LBB0_5
testq %rax,%rax
movq %rax,%rdi
jne LBB0_1
LBB0_4:
movq %rsi,%rax
popq %rbp
retq
LBB0_5:
ud2
.globl __TF3tco5isOddFSiSb
.align 4,0x90
__TF3tco5isOddFSiSb:
pushq %rbp
movq %rsp,%rdi
je LBB1_1
decq %rdi
jo LBB1_9
movb $1,%al
LBB1_5:
testq %rdi,%rdi
je LBB1_2
decq %rdi
jo LBB1_9
testq %rdi,%rdi
je LBB1_1
decq %rdi
jno LBB1_5
LBB1_9:
ud2
LBB1_1:
xorl %eax,%eax
LBB1_2:
popq %rbp
retq
.globl __TF3tco6isEvenFSiSb
.align 4,0x90
__TF3tco6isEvenFSiSb:
pushq %rbp
movq %rsp,%rbp
movb $1,%al
LBB2_1:
testq %rdi,%rdi
je LBB2_5
decq %rdi
jo LBB2_7
testq %rdi,%rdi
je LBB2_4
decq %rdi
jno LBB2_1
LBB2_7:
ud2
LBB2_4:
xorl %eax,%eax
LBB2_5:
popq %rbp
retq
这清楚地表明,swift在这两种情况下都做尾调用优化。
此外,isOdd / isEven函数的有趣之处在于,编译器不仅似乎执行TCO,而且还在每种情况下内联其他函数。