From Reddit

Frits van Bommel fvbommel at REMwOVExCAPSs.nl
Wed Jun 17 09:16:07 PDT 2009


Frits van Bommel wrote:
> bearophile wrote:
>>> Some are ignorant (the author concluded that dmd can't optimize tail 
>>> recursion by trying it with the non-tail-recursive factorial 
>>> function; and I took the time to explain him!).<
>>
>> If I compile this D2 program with DMD:
>>
>> import std.stdio: printf;
>> import std.conv: to;
>>
>> int sum(int[] a, int start=0) {
>>     if (start >= a.length)
>>         return 0;
>>     else {
>>         return a[start] + sum(a, start+1);
>>         //auto b = a[start];
>>         //return b + sum(a, start+1);
>>     }
>> }
>>
>> void main(char[][] args) {
>>     int n = args.length > 1 ? to!int(args[1]) : 1;
>>     auto a = new int[n];
>>     foreach(i, ref x; a)
>>         x = i;
>>     printf("%d\n", sum(a));
>> }
> 
> He's right though; the code isn't properly tail recursive (it performs 
> an add after the recursion). However, it can be *made* tail recursive by 
> introducing an accumulator, which is something LLVM does here[1].

Note that if the accumulator is introduced manually, the tail recursion indeed 
gets eliminated by DMD (and turned into a loop).

Code: (D1, Phobos or Tango)
-----
extern(C) int printf(char*, ...);
version(Tango)
     import tango.text.convert.Integer;
else
     import std.conv;

int sum(int[] a, int start=0, int acc = 0) {
     if (start >= a.length)
         return acc;
     else {
         return sum(a, start+1, acc + a[start]);
         //auto b = a[start];
         //return b + sum(a, start+1);
     }
}

void main(char[][] args) {
     int n = args.length > 1 ? toInt(args[1]) : 1;
     auto a = new int[n];
     foreach(i, ref x; a)
         x = i;
     printf("%d\n", sum(a));
}
-----

With dmd -O -release, I get the following objdump output (demangled):
-----
08049b54 <int test.sum(int[], int, int)>:
  8049b54:       55                      push   %ebp
  8049b55:       8b ec                   mov    %esp,%ebp
  8049b57:       83 ec 10                sub    $0x10,%esp
  8049b5a:       53                      push   %ebx
  8049b5b:       8b 5d 08                mov    0x8(%ebp),%ebx
  8049b5e:       89 c1                   mov    %eax,%ecx
  8049b60:       56                      push   %esi
  8049b61:       57                      push   %edi
  8049b62:       3b 5d 0c                cmp    0xc(%ebp),%ebx
  8049b65:       72 0b                   jb     8049b72 <int test.sum(int[], 
int, int)+0x1e>
  8049b67:       5f                      pop    %edi
  8049b68:       8b c1                   mov    %ecx,%eax
  8049b6a:       5e                      pop    %esi
  8049b6b:       5b                      pop    %ebx
  8049b6c:       8b e5                   mov    %ebp,%esp
  8049b6e:       5d                      pop    %ebp
  8049b6f:       c2 0c 00                ret    $0xc
  8049b72:       89 5d 08                mov    %ebx,0x8(%ebp)
  8049b75:       8b 55 10                mov    0x10(%ebp),%edx
  8049b78:       8b 5d 0c                mov    0xc(%ebp),%ebx
  8049b7b:       89 d7                   mov    %edx,%edi
  8049b7d:       8b 5d 08                mov    0x8(%ebp),%ebx
  8049b80:       8b 34 9f                mov    (%edi,%ebx,4),%esi
  8049b83:       03 f1                   add    %ecx,%esi
  8049b85:       8d 53 01                lea    0x1(%ebx),%edx
  8049b88:       3b 55 0c                cmp    0xc(%ebp),%edx
  8049b8b:       89 f1                   mov    %esi,%ecx
  8049b8d:       89 d3                   mov    %edx,%ebx
  8049b8f:       73 d6                   jae    8049b67 <int test.sum(int[], 
int, int)+0x13>
  8049b91:       eb ed                   jmp    8049b80 <int test.sum(int[], 
int, int)+0x2c>
  8049b93:       90                      nop
-----



More information about the Digitalmars-d mailing list