Thank you bearophile and Simen for your replies! Very helpful! 
I'll keep looking into it...

BR
/HF



bearophile Wrote:

> 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