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.