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.