让我们考虑一个定义如下的函数:
f(n, x) = F(n, x, f(n-1, x))
f(0, x) = g(x)
在我的程序中,n
的值在编译时始终是已知的。我想优化我的程序,避免在此函数中循环或递归调用。 f(n, x)
的整个表达式应该在编译时生成,以便允许编译器优化它。
直接解决方案是“手动”生成包含此表达式的字符串并使用mixin
语句。我不喜欢这样。
编译器是否能够/应该展开已知深度的递归?
即。将以我想要的方式优化以下功能:
double f(uint n)(double x)
{
static if(n == 0)
return g(x);
else
return F(n, x, f!(n-1)(x));
}
答案 0 :(得分:3)
据我所知,语言规范中的优化没有保证。虽然您的示例对于编译器进行优化看起来非常简单。
简单实验: 我编写了存根函数g()和F()来做一些简单的计算。编译 dmd -gc -O -inline“。用objdump检查:
0000000000426860 <_Dmain>:
426860: 55 push %rbp
426861: 48 8b ec mov %rsp,%rbp
426864: f2 48 0f 10 05 2b a7 rex.W movsd 0x2a72b(%rip),%xmm0 # 450f98 <_IO_stdin_used+0x38>
42686b: 02 00
42686d: be 0a 00 00 00 mov $0xa,%esi
426872: 48 bf 28 10 66 00 00 movabs $0x661028,%rdi
426879: 00 00 00
42687c: e8 6f 01 00 00 callq 4269f0 <_D3std5stdio4File14__T5writeTdTaZ5writeMFdaZv>
426881: 31 c0 xor %eax,%eax
426883: 5d pop %rbp
426884: c3 retq
正如您所看到的,一切都是在编译期间实际计算出来的,并替换为单个数值,该值立即作为writeln的参数打印出来。我还检查了修改,其中x在运行时读取,并且没有调用f()。 ASM列表相当长,所以我不会复制它。
此外,如果您的参数在编译时已知,则可能 CTFE (编译时功能评估)是更好的解决方案,因为它是有保证的。