1

让我们考虑一个定义如下的函数:

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));
}
4

1 回答 1

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(编译时函数评估)可能是一个更好的解决方案,因为它得到了保证。

于 2012-09-13T17:22:01.527 回答