在编译时在D中生成代数表达式

时间:2012-09-13 13:13:54

标签: metaprogramming d

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

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

1 个答案:

答案 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 (编译时功能评估)是更好的解决方案,因为它是有保证的。