https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87205

--- Comment #4 from Peter Dimov <pdimov at gmail dot com> ---
If the code is not the same the jump table is not optimized out and there's no
extra check. But it also happens with code that is not the same on the C++
side, for example:

```
struct X
{
    int v;
};

template<int I> struct Y: X
{
};

void f( X* x );

void h( unsigned ix, void* p )
{
    switch( ix )
    {
        case 0: f( (Y<0>*)p ); break;
        case 1: f( (Y<1>*)p ); break;
        case 2: f( (Y<2>*)p ); break;
        case 3: f( (Y<3>*)p ); break;
        case 4: f( (Y<4>*)p ); break;
        case 5: f( (Y<5>*)p ); break;
        default: __builtin_unreachable();
    }
}
```

```
h(unsigned int, void*):
  cmp edi, 5
  jbe .L5
.L5:
  mov rdi, rsi
  jmp f(X*)
```

https://godbolt.org/z/2Lh_GZ

A variation on the same theme, which demonstrates another kind of missed
optimization:

```
struct X
{
    int v;
};

template<int I> struct Y: X
{
};

int h( unsigned ix, void* p )
{
    switch( ix )
    {
        case 0: return ((Y<0>*)p)->v;
        case 1: return ((Y<1>*)p)->v;
        case 2: return ((Y<2>*)p)->v;
        case 3: return ((Y<3>*)p)->v;
        case 4: return ((Y<4>*)p)->v;
        case 5: return ((Y<5>*)p)->v;
        default: __builtin_unreachable();
    }
}
```

```
h(unsigned int, void*):
  mov edi, edi
  mov eax, DWORD PTR [rsi]
  jmp [QWORD PTR .L4[0+rdi*8]]
.L4:
  .quad .L9
  .quad .L8
  .quad .L7
  .quad .L6
  .quad .L5
  .quad .L3
.L5:
  ret
.L3:
  ret
.L9:
  ret
.L8:
  ret
.L7:
  ret
.L6:
  ret
```

https://godbolt.org/z/lCzlR2

There's a table, so there's no redundant check.

Reply via email to