Simen kjaeraas:

> Essentially, mark the switch as final, and cover every option.
> Likely, the optimizer does that for you if you cover every option but
> don't mark the switch as final.

This is true in theory, and I remember Walter liking this optimization. But in 
practice I don't know if DMD performs this optimization already, so you need to 
take a look at the produced asm to be sure.

--------------------------------

This is a little test, D2 code:

enum E { e1, e2, e3 }

int foo1(E e) {
    switch (e) {
        case E.e1: return 1;
        case E.e2: return 2;
        case E.e3: return 3;
        default: assert(0);
    }
}

int foo2(E e) {
    switch (e) {
        case E.e1: return 1;
        case E.e2: return 2;
        default: return 3;
    }
}

int foo3(E e) {
    final switch (e) {
        case E.e1: return 1;
        case E.e2: return 2;
        case E.e3: return 3;
    }
}
void main() {}


_D5test4foo1FE5test31EZi
        push EAX
        test EAX,EAX
        je  L11
        cmp EAX,1
        je  L18
        cmp EAX,2
        je  L1F
        jmp short L26
L11:    pop ECX
        mov EAX,1
        ret
L18:    pop ECX
        mov EAX,2
        ret
L1F:    pop ECX
        mov EAX,3
        ret
L26:    hlt

_D5test4foo2FE5test31EZi
        push EAX
        test EAX,EAX
        je  LC
        cmp EAX,1
        je  L13
        jmp short L1A
LC:     pop ECX
        mov EAX,1
        ret
L13:    pop ECX
        mov EAX,2
        ret
L1A:    pop ECX
        mov EAX,3
        ret

_D5test4foo3FE5test31EZi
        push EAX
        test EAX,EAX
        je  L11
        cmp EAX,1
        je  L18
        cmp EAX,2
        je  L1F
        jmp short L26
L11:    pop ECX
        mov EAX,1
        ret
L18:    pop ECX
        mov EAX,2
        ret
L1F:    pop ECX
        mov EAX,3
        ret
L26:    pop EAX
        ret

--------------------------------

Some C code compiled with GCC 4.5.1:

typedef enum { e1, e2, e3 } E;

int foo2(E e) {
    switch (e) {
        case e1: return 1;
        case e2: return 2;
        default: return 3;
    }
}

int foo3(E e) {
    switch (e) {
        case e1: return 1;
        case e2: return 2;
        case e3: return 3;
    }
}

int foo4(E e) {
    static void *array[] = { &&E1, &&E2, &&E3 };

    goto *array[e];

    E1: return 1;
    E2: return 2;
    E3: return 3;
}

int main() {
    return 0;
}


_foo2:
    movl    4(%esp), %edx
    movl    $3, %eax
    cmpl    $1, %edx
    jbe L5
    rep
    ret
    .p2align 4,,7
L5:
    movl    _CSWTCH.1(,%edx,4), %eax
    ret
    .p2align 4,,15

_foo3:
    movl    4(%esp), %edx
    cmpl    $1, %edx
    je  L11
    movl    $1, %eax
    jb  L6
    cmpl    $2, %edx
    je  L13
    .p2align 4,,3
    rep
    ret
    .p2align 4,,7
L11:
    movl    $2, %eax
L6:
    .p2align 4,,3
    rep
    ret
    .p2align 4,,7
L13:
    movb    $3, %al
    ret

_foo4:
        movl    4(%esp), %eax
        jmp     *_array.1639(,%eax,4)
        .p2align 4,,7
L15:
        movl    $1, %eax
        ret
        .p2align 4,,7
L17:
        movl    $2, %eax
        ret
        .p2align 4,,7
L18:
        movl    $3, %eax
        ret

--------------------------------

> My forays into the inline asm idea proved fruitless, but there may yet be 
> ways.

In D+DMD inline asm kills inlining, so you may use inline asm only if you need 
to do lot of computations.
In LDC there are pragma(allow_inline) and asm expressions that some most of 
this problem.

Going back to the OP problem: in D there are no computed gotos, that are useful 
if you want to write very fast interpreters and other things. But keep in mind 
that DMD supports normal gotos from and in inlined asm (LLVM-LDC doesn't 
supports this well), plus naked asm, this gives you some possibilities.
An option on Linux is to write the interpreter core using GNU C (that has 
computed gotos) and then link the core to the D code compiled with DMD/GDC.

It's strange how something as basic, old and necessary as a switch, to create a 
basic but fast interpreter, is so hard to compile well for compilers :-)

Bye,
bearophile

Reply via email to