<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40"><head><meta http-equiv=Content-Type content="text/html; charset=utf-8"><meta name=Generator content="Microsoft Word 15 (filtered medium)"><style><!--
/* Font Definitions */
@font-face
        {font-family:"Cambria Math";
        panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0in;
        margin-bottom:.0001pt;
        font-size:11.0pt;
        font-family:"Calibri",sans-serif;}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:blue;
        text-decoration:underline;}
.MsoChpDefault
        {mso-style-type:export-only;}
@page WordSection1
        {size:8.5in 11.0in;
        margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
        {page:WordSection1;}
--></style></head><body lang=EN-US link=blue vlink="#954F72"><div class=WordSection1><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>In an interesting coincidence, the place where I recall seeing the use of goto I described was also in a bytecode interpreter, for the “Pawn Scripting language” (which is really cool by the way, I’ve got it to run on 8 bit AVR, arm cortex-M and also transpiled to JavaScript using emscripten, and run inside a browser. It is extremely fast for a bytecode interpreter)</p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>Check out line 208:</p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal> <a href="https://github.com/compuphase/pawn/blob/master/amx/amxexec_gcc.c">https://github.com/compuphase/pawn/blob/master/amx/amxexec_gcc.c</a></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>That ‘NEXT’ macro is using a goto behind the scenes. Each block of code in between that labels (ie the semantic ‘case statement’ equivalents) ends with a NEXT macro, so it may actually be faster than even a compiler optimized switch-case because there is no ‘loop’ logic needed, to cycle back around to the ‘switch’. Its really just a devilish jumping around inside that function. </p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>One could argue that ‘break’ and ‘continue’ statements used inside loops are really just dressed up ‘gotos’ with specific jump destinations. I’ve been writing code almost daily for close to 30 years, and much of that time doing C or C++, and I’d estimate the time in between occasions where I used the goto keyword to be 2-5 years, so in other words, pretty rare. One of those uses can be for “breaking’ out of a nested loop. Java has a “break <label>” statement that you can use to break out of an outer loop from within an inner loop. Standard C/C++ doesn’t have anything like that so you have to either use a flag, restructure your loops, or use a goto statement. I think it’s a matter of option,  on a case by case basis which technique will lead to cleaner, easier to follow code in any particular situation. </p><p class=MsoNormal><o:p> </o:p></p><div style='mso-element:para-border-div;border:none;border-top:solid #E1E1E1 1.0pt;padding:3.0pt 0in 0in 0in'><p class=MsoNormal style='border:none;padding:0in'><b>From: </b><a href="mailto:triembed@triembed.org">Pete Soper via TriEmbed</a><br><b>Sent: </b>Wednesday, July 1, 2020 6:39 PM<br><b>To: </b><a href="mailto:triembed@triembed.org">triembed@triembed.org</a><br><b>Subject: </b>[TriEmbed] optimized switch statements Re: Hacking a fake vintage radio (with Arduino + Pi 0)</p></div><p class=MsoNormal><o:p> </o:p></p></div></body></html><html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; ">
  </head>
  <body>
    <p>Gcc already does use jump tables without the user having to force
      anything. Below is a simple C program followed by the X64 assembly
      language. Notice the table of addresses and the jump through rax.
      But what the programmer has to do is craft their case values to
      make a "dense" range that is mostly consecutive. How smart this
      is, I don't recall (e.g. if case values 4, 8, 12, 16 would be
      recognized as easy to compute an index with, how many "gaps" in
      the case value range would be tolerated, etc). But also the
      compiler won't use the jump table until there are more than a
      handful of cases (the example below, with only three cases
      compiled into sequences of tests and conditional branches because
      the compiler writer judged the tradeoff of speed and space wasn't
      worth it). <br>
    </p>
    <p>The reason I'm familiar with this is that the gcc compiler's
      smarts gave the Linux version of the Java virtual machine an edge
      with dispatching op codes but the Sun Solaris C++ compiler didn't
      have the optimization (and was in a 'caretaker state' with no hope
      of getting the optimization by then, in the early 2000s). But the
      speed of dispatch was about interpretation and that was an
      absolute nit for code that executed frequently, as it was
      automagically compiled into native code by the late 90s and the
      quality of that native code got better and better over the years.
      <br>
    </p>
    <p>-Pete</p>
    <p><tt>// Just for fun try putting "static" in front of the two int
        declarations</tt></p>
    <p><tt>// (first mystery _import and then also for
        disgusting_global_side effect) and see what comes out with gcc
        -S -O4</tt><tt><br>
      </tt></p>
    <p><tt>int mystery_import;</tt><tt><br>
      </tt><tt>int disgusting_global_side_effect;</tt></p>
    <p><tt>int main(int argc, char **argv) {</tt><tt><br>
      </tt><tt> switch (mystery_import) {</tt><tt><br>
      </tt><tt>   case 0: </tt><tt><br>
      </tt><tt>     disgusting_global_side_effect = 123;</tt><tt><br>
      </tt><tt>     break;</tt><tt><br>
      </tt><tt>   case 1: </tt><tt><br>
      </tt><tt>     disgusting_global_side_effect = 124;</tt><tt><br>
      </tt><tt>     break;</tt><tt><br>
      </tt><tt>   case 2: </tt><tt><br>
      </tt><tt>     disgusting_global_side_effect = 125;</tt><tt><br>
      </tt><tt>     break;</tt><tt><br>
      </tt><tt>   case 3: </tt><tt><br>
      </tt><tt>     disgusting_global_side_effect = 126;</tt><tt><br>
      </tt><tt>     break;</tt><tt><br>
      </tt><tt>   case 4: </tt><tt><br>
      </tt><tt>     disgusting_global_side_effect = 127;</tt><tt><br>
      </tt><tt>     break;</tt><tt><br>
      </tt><tt>   case 5: </tt><tt><br>
      </tt><tt>     disgusting_global_side_effect = 128;</tt><tt><br>
      </tt><tt>     break;</tt><tt><br>
      </tt><tt>  }</tt><tt><br>
      </tt><tt>  return 0;</tt><tt><br>
      </tt><tt>}</tt><tt><br>
      </tt><tt><br>
      </tt><tt>        .file   "dense-switch.c"</tt><tt><br>
      </tt><tt>        .text</tt><tt><br>
      </tt><tt>        .section        .text.startup,"ax",@progbits</tt><tt><br>
      </tt><tt>        .p2align 4</tt><tt><br>
      </tt><tt>        .globl  main</tt><tt><br>
      </tt><tt>        .type   main, @function</tt><tt><br>
      </tt><tt>main:</tt><tt><br>
      </tt><tt>.LFB0:</tt><tt><br>
      </tt><tt>        .cfi_startproc</tt><tt><br>
      </tt><tt>        endbr64</tt><tt><br>
      </tt><tt>        cmpl    $5, mystery_import(%rip)</tt><tt><br>
      </tt><tt>        ja      .L2</tt><tt><br>
      </tt><tt>        movl    mystery_import(%rip), %eax</tt><tt><br>
      </tt><tt>        leaq    .L4(%rip), %rdx</tt><tt><br>
      </tt><tt>        movslq  (%rdx,%rax,4), %rax</tt><tt><br>
      </tt><tt>        addq    %rdx, %rax</tt><tt><br>
      </tt><tt>        notrack jmp     *%rax</tt><tt><br>
      </tt><tt>        .section        .rodata</tt><tt><br>
      </tt><tt>        .align 4</tt><tt><br>
      </tt><tt>        .align 4</tt><tt><br>
      </tt><tt>.L4:</tt><tt><br>
      </tt><tt>        .long   .L9-.L4</tt><tt><br>
      </tt><tt>        .long   .L8-.L4</tt><tt><br>
      </tt><tt>        .long   .L7-.L4</tt><tt><br>
      </tt><tt>        .long   .L6-.L4</tt><tt><br>
      </tt><tt>        .long   .L5-.L4</tt><tt><br>
      </tt><tt>        .long   .L3-.L4</tt><tt><br>
      </tt><tt>        .section        .text.startup</tt><tt><br>
      </tt><tt>.L3:</tt><tt><br>
      </tt><tt>        movl    $128, disgusting_global_side_effect(%rip)</tt><tt><br>
      </tt><tt>.L2:</tt><tt><br>
      </tt><tt>        xorl    %eax, %eax</tt><tt><br>
      </tt><tt>        ret</tt><tt><br>
      </tt><tt>.L5:</tt><tt><br>
      </tt><tt>        movl    $127, disgusting_global_side_effect(%rip)</tt><tt><br>
      </tt><tt>        jmp     .L2</tt><tt><br>
      </tt><tt>        movl    $123, disgusting_global_side_effect(%rip)</tt><tt><br>
      </tt><tt>        jmp     .L2</tt><tt><br>
      </tt><tt>.L8:</tt><tt><br>
      </tt><tt>        movl    $124, disgusting_global_side_effect(%rip)</tt><tt><br>
      </tt><tt>        jmp     .L2</tt><tt><br>
      </tt><tt>.L7:</tt><tt><br>
      </tt><tt>        movl    $125, disgusting_global_side_effect(%rip)</tt><tt><br>
      </tt><tt>        jmp     .L2</tt><tt><br>
      </tt><tt>.L6:</tt><tt><br>
      </tt><tt>        movl    $126, disgusting_global_side_effect(%rip)</tt><tt><br>
      </tt><tt>        jmp     .L2</tt><tt><br>
      </tt><tt>        .cfi_endproc</tt><tt><br>
      </tt><tt>.LFE0:</tt><tt><br>
      </tt><tt>        .size   main, .-main</tt><tt><br>
      </tt><tt>        .comm   disgusting_global_side_effect,4,4</tt><tt><br>
      </tt><tt>        .comm   mystery_import,4,4</tt><tt><br>
      </tt><tt>        .ident  "GCC: (Ubuntu 9.3.0-10ubuntu2) 9.3.0"</tt><tt><br>
      </tt><tt>        .section        .note.GNU-stack,"",@progbits</tt><tt><br>
      </tt><tt>        .section        .note.gnu.property,"a"</tt><tt><br>
      </tt><tt>        .align 8</tt><tt><br>
      </tt><tt>        .long    1f - 0f</tt><tt><br>
      </tt><tt>        .long    4f - 1f</tt><tt><br>
      </tt><tt>        .long    5</tt><tt><br>
      </tt><tt>0:</tt><tt><br>
      </tt><tt>        .string  "GNU"</tt><tt><br>
      </tt><tt>1:</tt><tt><br>
      </tt><tt>        .align 8</tt><tt><br>
      </tt><tt>        .long    0xc0000002</tt><tt><br>
      </tt><tt>        .long    3f - 2f</tt><tt><br>
      </tt><tt>2:</tt><tt><br>
      </tt><tt>        .long    0x3</tt><tt><br>
      </tt><tt>3:</tt><tt><br>
      </tt><tt>        .align 8</tt><tt><br>
      </tt><tt>4:</tt><br>
      <br>
    </p>
    <p><br>
    </p>
    <div class="moz-cite-prefix">On 7/1/20 2:12 PM, Jon Wolfe via
      TriEmbed wrote:<br>
    </div>
    <blockquote type="cite" cite="mid:md5:QV09Nx1XOt%2FMpYir+IKsYw==">
      <meta http-equiv="Content-Type" content="text/html; ">
      <meta name="Generator" content="Microsoft Word 15 (filtered
        medium)">
      <style><!--
/* Font Definitions */
@font-face
        {font-family:"Cambria Math";
        panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0in;
        margin-bottom:.0001pt;
        font-size:11.0pt;
        font-family:"Calibri",sans-serif;}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:blue;
        text-decoration:underline;}
.MsoChpDefault
        {mso-style-type:export-only;}
@page WordSection1
        {size:8.5in 11.0in;
        margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
        {page:WordSection1;}
--></style>
      <div class="WordSection1">
        <p class="MsoNormal">This is one of those rare circumstances,
          imho, where goto can reasonably be used, Dijkstra be damned <span
            style="font-family:"Segoe UI Emoji",sans-serif">😊</span>.
        </p>
        <p class="MsoNormal"><o:p> </o:p></p>
        <p class="MsoNormal">Where I have seen it used like this , it’s
          an optimization, and doesn’t change the semantics of code flow
          from a traditional switch-case, and it was wrapped in a macro
          I think so it could be used, if supported, by the compiler.
          It’s like putting inline assembly in the code: only do it if
          the benefit is worth the sacrifice in code portability and
          maintainability. </p>
        <p class="MsoNormal"><o:p> </o:p></p>
        <p class="MsoNormal">I’m not a compiler optimization expert, but
          the code generation optimization of using a jump table would
          be at the discretion of the optimizer, using a goto construct
          would be a way to force that. It may also be the case that the
          way it is implemented at the machine code level is faster
          using gotos.  </p>
        <p class="MsoNormal"><o:p> </o:p></p>
      </div>
    </blockquote>
  </body>
</html>