在previous question中,我正在查看一个简单的代码示例,查看尾部调用优化。
针对这个问题,我遇到了GCC应用太多优化的问题,以演示本示例代码要显示的原则,并消除了循环/递归。
如何在启用尾调用优化的情况下让GCC编译,但尽可能少进行其他优化?
我目前正在尝试使用以下选项进行编译:
Selector selectorObject;
thrust::transform(results.begin(), results.end(), count.begin(), selectorObject);
有问题的递归函数是:
gcc -O0 -foptimize-sibling-calls -ftree-tail-merge tail_recursive.c -o tail_recursive.c.exe
gcc -S -O0 -foptimize-sibling-calls -ftree-tail-merge tail_recursive.c
由此产生的汇编程序是:
long recursive_tco(long loop, long current) {
return (loop>0) ? recursive_tco(loop-1, current+1): current;
}
(注意它正在调用自己,而不是条件jmp,这是我期望的)
我没有哪些选项让gcc在不删除示例代码的情况下执行尾调用优化?
显然在实际代码中,我将只启用 .globl recursive_tco
.def recursive_tco; .scl 2; .type 32; .endef
.seh_proc recursive_tco
recursive_tco:
pushq %rbp
.seh_pushreg %rbp
movq %rsp, %rbp
.seh_setframe %rbp, 0
subq $32, %rsp
.seh_stackalloc 32
.seh_endprologue
movq %rcx, 16(%rbp)
movq %rdx, 24(%rbp)
cmpq $0, 16(%rbp)
jle .L2
movq 24(%rbp), %rax
leaq 1(%rax), %rdx
movq 16(%rbp), %rax
subq $1, %rax
movq %rax, %rcx
call recursive_tco
jmp .L3
,我更喜欢在C中编写循环而不是递归。
-O2
编辑:
将功能更改为:
gcc version 4.9.3 (GCC)
在-O2:
处产生以下结果__attribute__ ((noinline)) long recursive_tco(long loop, long current) {
return (loop>0) ? recursive_tco(loop-1, current+1): current;
}
如果我正在阅读汇编程序,那么在使用recursive_tco:
.seh_endprologue
movq %rdx, %rax
leaq (%rcx,%rdx), %rdx
testq %rcx, %rcx
cmovg %rdx, %rax
ret
进行编译时,它似乎可以完成尾递归函数的工作:
gcc -O1 -foptimize-sibling-calls -ftree-tail-merge
不幸的是,它也在以类似的方式优化非尾递归函数,这不是我所期望的:
recursive_tco:
.seh_endprologue
movq %rdx, %rax
testq %rcx, %rcx
jle .L2
movq %rcx, %r8
.L3:
subq $1, %r8
jne .L3
leaq (%rcx,%rax), %rax
.L2:
rep ret
我希望还有一些进一步的优化,我需要提供一些额外的标志来禁用它们。有什么建议吗?