Jump Table Switch Case question

前端 未结 6 614
孤街浪徒
孤街浪徒 2020-12-08 00:55

I am trying to understand some things about jump tables and its relationship between a switch case statement.

I was told that a jump table is a O(1) structure that t

6条回答
  •  悲&欢浪女
    2020-12-08 01:42

    To further elaborate on Jerry's answer and others

    Given:

    int x=1;
    switch (i) {
       case 1: x=6; break;
       case 2: x++;
       // Fall through
       case 3: x+=7; break;
    }
    

    you could have something like the following:

    int f1() {return 6;}
    int f2() {return 1+f3();}
    int f3() {return 8;}
    

    The the compiler could use a jump table to index {f1, f2, f3}

    The compiler can do inlining when creating the table having f1, f2, f3 setting x directly to 6,9,8

    But if you wrote the functions, and rolled your own jump table, f1,f2,f3 could be anywhere, but the compiler will know to put them close to the switch creating much better code locality than you could.

    Note that in many cases the compiler will generate a guard to check if i is in range (or to handle the default) and if you are sure that it always is one of the cases, you could skip that

    The interesting thing is that for under a small number of cases, and under different compiler flags (compiler dependent) the switch would not use a table, but would just do ifs, similar to:

    if (i==1) x=f1();
    else if (i==2) x=f2();
    else if (i==3) x=f3();
    

    or it might optimize this (where simple tests are one instruction) to:

    x=(i==1) ? f1()
    : (i==2) ? f2()
    : (i==3) ? f3()
    : x;
    

    The best advice is to look at the assembly generated to see what the compiler did to your code on your architecture, g++ on Linux/intel will generate something like the following, if there is a jump table

    (note I had to go to 5 case statements to force the jump table, it used ifs below that number of case statements)

    Note that small holes will be in the jump table to do the default

    int foo(int i)
    {
       int x=1;
       switch (i) {
           case 1: x=6; break;
           case 2: x++;
            // Fall through
           case 3: x+=7; break;
           case 4: x+=2; break;
           case 5: x+=9; break;
        }
      return x;
    }
    

    would generate the following assembly code (// comments are mine):

            cmp     edi, 5                     //make sure it is not over 5
            ja      .L2                        //jump to default case
            mov     edi, edi
            jmp     [QWORD PTR .L4[0+rdi*8]]   // use the jump table at label L4:
    .L4:
            .quad   .L2                        // if i=0, set x=1 (default)
            .quad   .L9                        // f1() see below
            .quad   .L10                       // f2() see below
            .quad   .L6                        // f3() see below
            .quad   .L7                        // f4() see below
            .quad   .L8                        // f5() see below
    .L10:
            mov     eax, 9                     // x=9
            ret
    .L9:
            mov     eax, 6                     // x=6
            ret
    .L8:
            mov     eax, 10                    // x=10
            ret
    .L6:
            mov     eax, 8                     // x=8
            ret
    .L7:
            mov     eax, 3                     // x=3
            ret
    .L2:
            mov     eax, 1                     // default, x was 1, noop is: x=1
            ret
    

提交回复
热议问题