LDC is a moving target because it's actively developed, and generally things 
improve with time.
This is a recent change by the quite active Frits van Bommel:
http://www.dsource.org/projects/ldc/changeset/1486%3A9ed0695cb93c

This is a cleaned up version discussed in this thread:

import tango.stdc.stdio: printf;
import Integer = tango.text.convert.Integer;

class AllocationItem {
    int value;
    this(int v) { this.value = v; }
}

int foo(int iters) {
    int sum = 0;
    for (int i = 0; i < iters; ++i) {
        auto item = new AllocationItem(i);
        sum += item.value;
    }
    return sum;
}

void main(char[][] args) {
    int iters = Integer.parse(args[1]);
    printf("%d\n", foo(iters));        
}


The asm generated by the last LDC (based on DMD v1.045 and llvm 2.6svn (Tue Jun 
 9 22:34:25 2009)) (this is just the important part of the asm):

foo:
        testl   %eax, %eax
        jle     .LBB2_4
        movl    %eax, %ecx
        xorl    %eax, %eax
        .align  16
.LBB2_2:
        incl    %eax
        cmpl    %ecx, %eax
        jne     .LBB2_2
        leal    -2(%ecx), %eax
        leal    -1(%ecx), %edx
        mull    %edx
        shldl   $31, %eax, %edx
        leal    -1(%edx,%ecx), %eax
        ret
.LBB2_4:
        xorl    %eax, %eax
        ret
*/


This is the same code with "scope" added:

import tango.stdc.stdio: printf;
import Integer = tango.text.convert.Integer;

class AllocationItem {
    int value;
    this(int v) { this.value = v; }
}

int foo(int iters) {
    int sum = 0;
    for (int i = 0; i < iters; ++i) {
        scope auto item = new AllocationItem(i);
        sum += item.value;
    }
    return sum;
}

void main(char[][] args) {
    int iters = Integer.parse(args[1]);
    printf("%d\n", foo(iters));        
}

Its asm:

/*
foo:
        pushl   %ebx
        pushl   %edi
        pushl   %esi
        subl    $24, %esp
        testl   %eax, %eax
        jle     .LBB2_4
        movl    %eax, %esi
        xorl    %edi, %edi
        leal    8(%esp), %ebx
        .align  16
.LBB2_2:
        movl    $_D11gc_test2b_d14AllocationItem6__vtblZ, 8(%esp)
        movl    $0, 12(%esp)
        movl    %edi, 16(%esp)
        movl    %ebx, (%esp)
        call    _d_callfinalizer
        incl    %edi
        cmpl    %esi, %edi
        jne     .LBB2_2
        leal    -2(%esi), %eax
        leal    -1(%esi), %ecx
        mull    %ecx
        shldl   $31, %eax, %edx
        leal    -1(%edx,%esi), %eax
        jmp     .LBB2_5
.LBB2_4:
        xorl    %eax, %eax
.LBB2_5:
        addl    $24, %esp
        popl    %esi
        popl    %edi
        popl    %ebx
        ret
*/


The running time:
...$ elaps ./gc_test1 250000000
-1782069568
real    0m0.170s
user    0m0.160s
sys     0m0.010s

The version with "scope":
...$ elaps ./gc_test2 250000000
-1782069568
real    0m6.430s
user    0m6.430s
sys     0m0.000s

(Later I may try again with a less simple and more realistic benchmark, because 
this is too much a toy to be interesting.)

Bye,
bearophile

Reply via email to